diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 19f47b17..effce9b0 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,6 +1,6 @@ # These are supported funding model platforms -github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] +github: CalcProgrammer1 patreon: CalcProgrammer1 open_collective: # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username diff --git a/.github/workflows/issue_opened.yml b/.github/workflows/issue_opened.yml new file mode 100644 index 00000000..36975f09 --- /dev/null +++ b/.github/workflows/issue_opened.yml @@ -0,0 +1,21 @@ +name: Issue Opened + +on: + issues: + types: [opened,reopened] + +jobs: + issue_greeting: + runs-on: ubuntu-latest + permissions: + issues: write + steps: + - name: Greeting + run: gh issue comment "$NUMBER" --body "$BODY" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + NUMBER: ${{ github.event.issue.number }} + BODY: > + This Github repo is a mirror of the main repository on Gitlab. + For any new issue please refer to https://gitlab.com/CalcProgrammer1/OpenRGB/-/issues diff --git a/.github/workflows/pr_opened.yml b/.github/workflows/pr_opened.yml new file mode 100644 index 00000000..adbcc965 --- /dev/null +++ b/.github/workflows/pr_opened.yml @@ -0,0 +1,21 @@ +name: PR Opened + +on: + pull_request: + types: [opened,reopened] + +jobs: + pr_greeting: + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - name: Greeting + run: gh pr comment "$NUMBER" --body "$BODY" + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + NUMBER: ${{ github.event.pull_request.number }} + BODY: > + This Github repo is a mirror of the main repository on Gitlab. + Please fork https://gitlab.com/CalcProgrammer1/OpenRGB/ and raise the appropriate merge request on Gitlab. diff --git a/.gitignore b/.gitignore index ae8884ad..ef469b19 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,7 @@ Build/ .qmake.stash .vscode .vs +.idea # Generic Files .DS_Store diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 22e2e51c..90c3681e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,6 +7,22 @@ #-----------------------------------------------------------------------# # OpenRGB GitLab CI Configuration # #-----------------------------------------------------------------------# +.fork_local_runner_rules: + rules: + - if: $CI_PROJECT_PATH == "CalcProgrammer1/OpenRGB" || $CI_PIPELINE_SOURCE == "push" + when: on_success + +.fork_gitlab_runner_rules: + rules: + - if: $CI_PROJECT_PATH != "CalcProgrammer1/OpenRGB" && $CI_PIPELINE_SOURCE == "push" + when: manual + allow_failure: true + +.upstream_rules: + rules: + - if: '$CI_PROJECT_PATH == "CalcProgrammer1/OpenRGB"' + when: on_success + - !reference [.fork_gitlab_runner_rules, rules] .shared_windows_runners: tags: @@ -17,22 +33,22 @@ stages: - build - test + - deploy + +variables: + GIT_DEPTH: 0 before_script: - echo "started by ${GITLAB_USER_NAME}" -#reusable templates -.ccache_init: &ccache_init - before_script: - - export QT_SELECT=qt5 - - export APPIMAGE_EXTRACT_AND_RUN=1 - #-----------------------------------------------------------------------# # Supported Devices Build Target # #-----------------------------------------------------------------------# "Supported Devices": - <<: *ccache_init - image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:bullseye-64 + image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:bookworm-amd64 + tags: + - linux + - amd64 stage: build script: - qmake @@ -42,217 +58,142 @@ before_script: artifacts: name: "${CI_PROJECT_NAME}_Supported_Devices_${CI_COMMIT_SHORT_SHA}" paths: - - ./*.md - Supported Devices.csv - exclude: - - README.md - - CONTRIBUTING.md expire_in: 30 days rules: - - if: '$CI_PROJECT_PATH == "CalcProgrammer1/OpenRGB"' - when: on_success - - if: $CI_PIPELINE_SOURCE == "push" - when: manual - allow_failure: true + - !reference [.upstream_rules, rules] #-----------------------------------------------------------------------# -# Linux (AppImage) 32-bit Build Target # +# OpenRGB Common Appimage Build Steps # #-----------------------------------------------------------------------# -"Linux 32 AppImage": - <<: *ccache_init - image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:bullseye-32 +.hidden_appimage_script: &appimage_script_steps + image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:bookworm-${TGT_ARCH} + tags: + - linux + - ${TGT_ARCH} stage: build script: - export $(dpkg-architecture) - - ./scripts/build-appimage.sh + - ./scripts/build-appimage.sh ${TGT_QT} artifacts: - name: "${CI_PROJECT_NAME}_Linux_32_${CI_COMMIT_SHORT_SHA}" + name: "${CI_PROJECT_NAME}_Linux_${TGT_NAME}_${CI_COMMIT_SHORT_SHA}" paths: - - OpenRGB-i386.AppImage + - OpenRGB-${TGT_PATH}.AppImage - 60-openrgb.rules - README.md expire_in: 30 days rules: - - if: '$CI_PROJECT_PATH == "CalcProgrammer1/OpenRGB"' - when: on_success - - if: $CI_PIPELINE_SOURCE == "push" - when: manual - allow_failure: true + - !reference [.upstream_rules, rules] #-----------------------------------------------------------------------# -# Linux (AppImage) 64-bit Build Target # +# Linux (AppImage) i386 Build Target # #-----------------------------------------------------------------------# -"Linux 64 AppImage": - <<: *ccache_init - image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:bullseye-64 - stage: build - script: - - export $(dpkg-architecture) - - ./scripts/build-appimage.sh - - artifacts: - name: "${CI_PROJECT_NAME}_Linux_64_${CI_COMMIT_SHORT_SHA}" - paths: - - OpenRGB-x86_64.AppImage - - 60-openrgb.rules - - README.md - expire_in: 30 days +"Linux i386 AppImage": + variables: + TGT_ARCH: "i386" + TGT_QT: "" + TGT_NAME: "${TGT_ARCH}" + TGT_PATH: "${TGT_ARCH}" + <<: *appimage_script_steps #-----------------------------------------------------------------------# -# Linux (.deb) Debian Buster (Legacy) 32-bit Build Target # +# Linux (AppImage) Qt6 i386 Build Target # #-----------------------------------------------------------------------# -"Linux 32 .deb (Debian Buster)": - <<: *ccache_init - image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:buster-32 - stage: build - script: - - ./scripts/build-package-files.sh debian/changelog - - 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 i386 AppImage Qt6": + variables: + TGT_ARCH: "i386" + TGT_QT: "qt6" + TGT_NAME: "${TGT_ARCH}_${TGT_QT^}" + TGT_PATH: "${TGT_ARCH}" + <<: *appimage_script_steps +#-----------------------------------------------------------------------# +# Linux (AppImage) amd64 Build Target # +#-----------------------------------------------------------------------# +"Linux amd64 AppImage": + variables: + TGT_ARCH: "amd64" + TGT_QT: "" + TGT_NAME: "${TGT_ARCH}" + TGT_PATH: "x86_64" + <<: *appimage_script_steps rules: - - if: '$CI_PROJECT_PATH == "CalcProgrammer1/OpenRGB"' - when: on_success - - if: $CI_PIPELINE_SOURCE == "push" - when: manual - allow_failure: true - -#-----------------------------------------------------------------------# -# Linux (.deb) Debian Buster (Legacy) 64-bit Build Target # -#-----------------------------------------------------------------------# -"Linux 64 .deb (Debian Buster)": - <<: *ccache_init - image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:buster-64 - stage: build - script: - - ./scripts/build-package-files.sh debian/changelog - - 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 + - !reference [.fork_local_runner_rules, rules] +"Linux amd64 AppImage (gitlab.com runner)": + extends: "Linux amd64 AppImage" rules: - - if: '$CI_PROJECT_PATH == "CalcProgrammer1/OpenRGB"' - when: on_success - - if: $CI_PIPELINE_SOURCE == "push" - when: manual - allow_failure: true + - !reference [.fork_gitlab_runner_rules, rules] + tags: + - "saas-linux-small-amd64" #-----------------------------------------------------------------------# -# Linux (.deb) Debian Bullseye 32-bit Build Target # +# Linux (AppImage) Qt6 amd64 Build Target # #-----------------------------------------------------------------------# -"Linux 32 .deb (Debian Bullseye)": - <<: *ccache_init - image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:bullseye-32 - stage: build - script: - - ./scripts/build-package-files.sh debian/changelog - - 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 - - rules: - - if: '$CI_PROJECT_PATH == "CalcProgrammer1/OpenRGB"' - when: on_success - - if: $CI_PIPELINE_SOURCE == "push" - when: manual - allow_failure: true - -#-----------------------------------------------------------------------# -# Linux (.deb) Debian Bullseye 64-bit Build Target # -#-----------------------------------------------------------------------# -"Linux 64 .deb (Debian Bullseye)": - <<: *ccache_init - image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:bullseye-64 - stage: build - script: - - ./scripts/build-package-files.sh debian/changelog - - 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 - - rules: - - if: '$CI_PROJECT_PATH == "CalcProgrammer1/OpenRGB"' - when: on_success - - if: $CI_PIPELINE_SOURCE == "push" - when: manual - allow_failure: true - -#-----------------------------------------------------------------------# -# Linux (.deb) Debian Bookworm 32-bit Build Target # -#-----------------------------------------------------------------------# -"Linux 32 .deb (Debian Bookworm)": - <<: *ccache_init - image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:bookworm-32 - stage: build - script: - - ./scripts/build-package-files.sh debian/changelog - - 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 - - rules: - - if: '$CI_PROJECT_PATH == "CalcProgrammer1/OpenRGB"' - when: on_success - - if: $CI_PIPELINE_SOURCE == "push" - when: manual - allow_failure: true - -#-----------------------------------------------------------------------# -# Linux (.deb) Debian Bookworm 64-bit Build Target # -#-----------------------------------------------------------------------# -"Linux 64 .deb (Debian Bookworm)": - <<: *ccache_init - image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:bookworm-64 +"Linux amd64 AppImage Qt6": + variables: + TGT_ARCH: "amd64" + TGT_QT: "qt6" + TGT_NAME: "${TGT_ARCH}_${TGT_QT^}" + TGT_PATH: "x86_64" + <<: *appimage_script_steps + +#-----------------------------------------------------------------------# +# Linux (AppImage) armhf Build Target # +#-----------------------------------------------------------------------# +"Linux armhf AppImage": + variables: + TGT_ARCH: "armhf" + TGT_QT: "" + TGT_NAME: "${TGT_ARCH}" + TGT_PATH: "${TGT_ARCH}" + <<: *appimage_script_steps + +#-----------------------------------------------------------------------# +# Linux (AppImage) Qt6 armhf Build Target # +#-----------------------------------------------------------------------# +"Linux armhf AppImage Qt6": + variables: + TGT_ARCH: "armhf" + TGT_QT: "qt6" + TGT_NAME: "${TGT_ARCH}_${TGT_QT^}" + TGT_PATH: "${TGT_ARCH}" + <<: *appimage_script_steps + +#-----------------------------------------------------------------------# +# Linux (AppImage) arm64 Build Target # +#-----------------------------------------------------------------------# +"Linux arm64 AppImage": + variables: + TGT_ARCH: "arm64" + TGT_QT: "" + TGT_NAME: "${TGT_ARCH}" + TGT_PATH: "${TGT_ARCH}" + <<: *appimage_script_steps + +#-----------------------------------------------------------------------# +# Linux (AppImage) Qt6 arm64 Build Target # +#-----------------------------------------------------------------------# +"Linux arm64 AppImage Qt6": + variables: + TGT_ARCH: "arm64" + TGT_QT: "qt6" + TGT_NAME: "${TGT_ARCH}_${TGT_QT^}" + TGT_PATH: "${TGT_ARCH}" + <<: *appimage_script_steps + +#-----------------------------------------------------------------------# +# OpenRGB Common Debian Build Steps # +#-----------------------------------------------------------------------# +.hidden_deb_script: &debian_script_steps stage: build + image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:$TGT_DEB-$TGT_ARCH + tags: + - linux + - $TGT_ARCH script: - ./scripts/build-package-files.sh debian/changelog - dpkg-architecture -l @@ -261,36 +202,100 @@ before_script: - mv -v ../openrgb*.deb ./ artifacts: - name: "${CI_PROJECT_NAME}_Linux_64_deb_${CI_COMMIT_SHORT_SHA}" + name: "${CI_PROJECT_NAME}_Linux_${TGT_ARCH}_deb_${CI_COMMIT_SHORT_SHA}" paths: - openrgb*.deb exclude: - openrgb-dbgsym*.deb expire_in: 30 days - rules: - - if: '$CI_PROJECT_PATH == "CalcProgrammer1/OpenRGB"' - when: on_success - - if: $CI_PIPELINE_SOURCE == "push" - when: manual - allow_failure: true + - !reference [.upstream_rules, rules] #-----------------------------------------------------------------------# -# Linux (.rpm, f35) 64-bit Build Target # +# Linux (.deb) Debian Bookworm i386 Build Target # #-----------------------------------------------------------------------# -"Linux 64 f35 rpm": - image: fedora:35 +"Linux i386 .deb (Debian Bookworm)": + variables: + TGT_ARCH: "i386" + TGT_DEB: "bookworm" + <<: *debian_script_steps + +#-----------------------------------------------------------------------# +# Linux (.deb) Debian Trixie i386 Build Target # +#-----------------------------------------------------------------------# +"Linux i386 .deb (Debian Trixie)": + variables: + TGT_ARCH: "i386" + TGT_DEB: "trixie" + <<: *debian_script_steps + +#-----------------------------------------------------------------------# +# Linux (.deb) Debian Bookworm amd64 Build Target # +#-----------------------------------------------------------------------# +"Linux amd64 .deb (Debian Bookworm)": + variables: + TGT_ARCH: "amd64" + TGT_DEB: "bookworm" + <<: *debian_script_steps + +#-----------------------------------------------------------------------# +# Linux (.deb) Debian Trixie amd64 Build Target # +#-----------------------------------------------------------------------# +"Linux amd64 .deb (Debian Trixie)": + variables: + TGT_ARCH: "amd64" + TGT_DEB: "trixie" + <<: *debian_script_steps + +#-----------------------------------------------------------------------# +# Linux (.deb) Debian Bookworm armhf Build Target # +#-----------------------------------------------------------------------# +"Linux armhf .deb (Debian Bookworm)": + variables: + TGT_ARCH: "armhf" + TGT_DEB: "bookworm" + <<: *debian_script_steps + +#-----------------------------------------------------------------------# +# Linux (.deb) Debian Trixie armhf Build Target # +#-----------------------------------------------------------------------# +"Linux armhf .deb (Debian Trixie)": + variables: + TGT_ARCH: "armhf" + TGT_DEB: "trixie" + <<: *debian_script_steps + +#-----------------------------------------------------------------------# +# Linux (.deb) Debian Bookworm arm64 Build Target # +#-----------------------------------------------------------------------# +"Linux arm64 .deb (Debian Bookworm)": + variables: + TGT_ARCH: "arm64" + TGT_DEB: "bookworm" + <<: *debian_script_steps + +#-----------------------------------------------------------------------# +# Linux (.deb) Debian Trixie arm64 Build Target # +#-----------------------------------------------------------------------# +"Linux arm64 .deb (Debian Trixie)": + variables: + TGT_ARCH: "arm64" + TGT_DEB: "trixie" + <<: *debian_script_steps + +#-----------------------------------------------------------------------# +# Linux (.rpm, F40) 64-bit Build Target # +#-----------------------------------------------------------------------# +"Linux 64 F40 rpm": + image: fedora:40 stage: build script: - - dnf install rpmdevtools dnf-plugins-core -y + - dnf install rpmdevtools dnf-plugins-core libcurl-devel qt5-qtbase-devel git -y - rpmdev-setuptree - ./scripts/build-package-files.sh fedora/OpenRGB.spec - - ls /root/ - cp fedora/OpenRGB.spec /root/rpmbuild/SPECS - - cp ../OpenRGB /root/rpmbuild/SOURCES/ -r - - cd /root/rpmbuild/SOURCES - - tar -cf OpenRGB.tar.gz OpenRGB/ - - cd .. + - cp -rp . /root/rpmbuild/SOURCES/OpenRGB + - cd /root/rpmbuild - dnf builddep SPECS/OpenRGB.spec -y - rpmbuild -ba SPECS/OpenRGB.spec - cd RPMS/x86_64/ @@ -304,115 +309,12 @@ before_script: expire_in: 30 days rules: - - if: '$CI_PROJECT_PATH == "CalcProgrammer1/OpenRGB"' - when: on_success - - if: $CI_PIPELINE_SOURCE == "push" - when: manual - allow_failure: true + - !reference [.upstream_rules, rules] #-----------------------------------------------------------------------# -# Linux (.rpm, f36) 64-bit Build Target # +# Debian i386 Bookworm test # #-----------------------------------------------------------------------# -"Linux 64 f36 rpm": - image: fedora:36 - stage: build - script: - - dnf install rpmdevtools dnf-plugins-core libcurl-devel qt5-qtbase-devel -y - - rpmdev-setuptree - - ./scripts/build-package-files.sh fedora/OpenRGB.spec - - ls /root/ - - cp fedora/OpenRGB.spec /root/rpmbuild/SPECS - - cp ../OpenRGB /root/rpmbuild/SOURCES/ -r - - cd /root/rpmbuild/SOURCES - - tar -cf OpenRGB.tar.gz OpenRGB/ - - cd .. - - dnf builddep SPECS/OpenRGB.spec -y - - rpmbuild -ba SPECS/OpenRGB.spec - - cd RPMS/x86_64/ - - mv openrgb*.rpm ${CI_PROJECT_DIR}/ - - cd ${CI_PROJECT_DIR} - - artifacts: - name: "${CI_PROJECT_NAME}_Linux_64_rpm_${CI_COMMIT_SHORT_SHA}" - paths: - - openrgb*.rpm - expire_in: 30 days - - rules: - - if: '$CI_PROJECT_PATH == "CalcProgrammer1/OpenRGB"' - when: on_success - - if: $CI_PIPELINE_SOURCE == "push" - when: manual - allow_failure: true - -#-----------------------------------------------------------------------# -# 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 - - apt remove -y openrgb - dependencies: - - "Linux 32 .deb (Debian Buster)" - needs: - - "Linux 32 .deb (Debian Buster)" - -#-----------------------------------------------------------------------# -# Debian 64 Buster test # -#-----------------------------------------------------------------------# -"Debian 64 Buster": - image: amd64/debian:buster - stage: test - script: - - apt update - - DEBIAN_FRONTEND=noninteractive apt install -yq --no-install-recommends ./openrgb*amd64.deb - - openrgb --version - - apt remove -y openrgb - dependencies: - - "Linux 64 .deb (Debian Buster)" - needs: - - "Linux 64 .deb (Debian Buster)" - -#-----------------------------------------------------------------------# -# 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 - - apt remove -y openrgb - dependencies: - - "Linux 32 .deb (Debian Bullseye)" - needs: - - "Linux 32 .deb (Debian Bullseye)" - -#-----------------------------------------------------------------------# -# Debian 64 Bullseye test # -#-----------------------------------------------------------------------# -"Debian 64 Bullseye": - image: amd64/debian:bullseye - stage: test - script: - - apt update - - DEBIAN_FRONTEND=noninteractive apt install -yq --no-install-recommends ./openrgb*amd64.deb - - openrgb --version - - apt remove -y openrgb - dependencies: - - "Linux 64 .deb (Debian Bullseye)" - needs: - - "Linux 64 .deb (Debian Bullseye)" - -#-----------------------------------------------------------------------# -# Debian 32 Bookworm test # -#-----------------------------------------------------------------------# -"Debian 32 Bookworm": +"Debian i386 Bookworm": image: i386/debian:bookworm stage: test script: @@ -421,14 +323,14 @@ before_script: - openrgb --version - apt remove -y openrgb dependencies: - - "Linux 32 .deb (Debian Bookworm)" + - "Linux i386 .deb (Debian Bookworm)" needs: - - "Linux 32 .deb (Debian Bookworm)" + - "Linux i386 .deb (Debian Bookworm)" #-----------------------------------------------------------------------# -# Debian 64 Bookworm test # +# Debian amd64 Bookworm test # #-----------------------------------------------------------------------# -"Debian 64 Bookworm": +"Debian amd64 Bookworm": image: amd64/debian:bookworm stage: test script: @@ -437,30 +339,14 @@ before_script: - openrgb --version - apt remove -y openrgb dependencies: - - "Linux 64 .deb (Debian Bookworm)" + - "Linux amd64 .deb (Debian Bookworm)" needs: - - "Linux 64 .deb (Debian Bookworm)" + - "Linux amd64 .deb (Debian Bookworm)" #-----------------------------------------------------------------------# -# Ubuntu 64 20.04LTS test # +# Ubuntu amd64 22.04 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 - - apt remove -y openrgb - dependencies: - - "Linux 64 .deb (Debian Buster)" - needs: - - "Linux 64 .deb (Debian Buster)" - -#-----------------------------------------------------------------------# -# Ubuntu 64 22.04 test # -#-----------------------------------------------------------------------# -"Ubuntu 64 22.04LTS": +"Ubuntu amd64 22.04LTS": image: ubuntu:jammy stage: test script: @@ -469,39 +355,40 @@ before_script: - openrgb --version - apt remove -y openrgb dependencies: - - "Linux 64 .deb (Debian Bookworm)" + - "Linux amd64 .deb (Debian Bookworm)" needs: - - "Linux 64 .deb (Debian Bookworm)" + - "Linux amd64 .deb (Debian Bookworm)" #-----------------------------------------------------------------------# -# Fedora 64 v35 test # +# Ubuntu amd64 24.04 test # #-----------------------------------------------------------------------# -"Fedora 64 v35": - image: fedora:35 +"Ubuntu amd64 24.04LTS": + image: ubuntu:noble + stage: test + script: + - apt update + - DEBIAN_FRONTEND=noninteractive apt install -yq --no-install-recommends ./openrgb*amd64.deb + - openrgb --version + - apt remove -y openrgb + dependencies: + - "Linux amd64 .deb (Debian Bookworm)" + needs: + - "Linux amd64 .deb (Debian Bookworm)" + +#-----------------------------------------------------------------------# +# Fedora 64 v40 test # +#-----------------------------------------------------------------------# +"Fedora 64 v40": + image: fedora:40 stage: test script: - yum -y localinstall ./openrgb*64.rpm - openrgb --version - yum -y remove openrgb dependencies: - - "Linux 64 f35 rpm" + - "Linux 64 F40 rpm" needs: - - "Linux 64 f35 rpm" - -#-----------------------------------------------------------------------# -# Fedora 64 v36 test # -#-----------------------------------------------------------------------# -"Fedora 64 v36": - image: fedora:36 - stage: test - script: - - yum -y localinstall ./openrgb*64.rpm - - openrgb --version - - yum -y remove openrgb - dependencies: - - "Linux 64 f36 rpm" - needs: - - "Linux 64 f36 rpm" + - "Linux 64 F40 rpm" #-----------------------------------------------------------------------# # Windows (32-bit) Build Target # @@ -511,61 +398,7 @@ before_script: - .shared_windows_runners stage: build script: - - $esc = "$([char]27)" - - $count = 0 - - function _unix_tmsec_ { [int64](([datetime]::UtcNow)-(get-date "1/1/1970")).TotalSeconds } - - function _fold_start_ { param( [string]$TEXT_TAG ) $t=_unix_tmsec_; $global:count += 1; Write-Host -NoNewLine "`r`n`r`nsection_start:${t}:sect_${count}`r${esc}[0K${esc}[33m${TEXT_TAG}${esc}[39m`r`n"; } - - function _fold_final_ { $t=_unix_tmsec_; Write-Host -NoNewLine "`r`n`r`nsection_end:${t}:sect_${count}`r${esc}[0K`r`n" ; } - - - - _fold_start_ 'configuring the msvc environment variables' - - Push-Location "C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Auxiliary/Build" - - '& cmd.exe /C "vcvarsall.bat x86 & set" | Foreach-Object { if ($_ -match "(.*?)=(.*)") { Set-Item -force -path "Env:\$($matches[1])" -value "$($matches[2])" } }' - - Pop-Location - - _fold_final_ - - - _fold_start_ 'downloading precompiled versions of qtbase, qttools (for windeployqt) and jom (for a more parallel nmake)' - - mkdir _qt - - mkdir _qt_download - - Push-Location _qt_download - - curl.exe -LJ -o qt-base.7z 'https://gitlab.com/OpenRGBDevelopers/openrgb-linux-ci-deb-builder/-/package_files/55610076/download' - - curl.exe -LJ -o qt-tools.7z 'https://gitlab.com/OpenRGBDevelopers/openrgb-linux-ci-deb-builder/-/package_files/55610097/download' - - curl.exe -LJ -o qt-jom.zip 'https://gitlab.com/OpenRGBDevelopers/openrgb-linux-ci-deb-builder/-/package_files/55610138/download' - - _fold_final_ - - - _fold_start_ 'extracting the downloaded qt binaries' - - 7z x qt-base.7z '-o../_qt' -y - - 7z x qt-tools.7z '-o../_qt' -y - - 7z x qt-jom.zip '-o../_qt' -y - - _fold_final_ - - - _fold_start_ 'turn the qt install from enterprise to foss; remove the licensing checks' - - ${qconfig-pri-folder} = '..\_qt\5.15.0\msvc2019\mkspecs\qconfig.pri' - - (Get-Content ${qconfig-pri-folder}).replace('QT_EDITION = Enterprise', 'QT_EDITION = OpenSource') | Set-Content ${qconfig-pri-folder} - - (Get-Content ${qconfig-pri-folder}).replace('QT_LICHECK = licheck.exe', '') | Set-Content ${qconfig-pri-folder} - - Pop-Location - - _fold_final_ - - - _fold_start_ 'run qmake and generate the msvc nmake makefile' - - mkdir _build; cd _build - - ..\_qt\5.15.0\msvc2019\bin\qmake ..\OpenRGB.pro - - _fold_final_ - - - _fold_start_ 'start the actual build with jom instead of nmake; for speed' - - ..\_qt\jom - - _fold_final_ - - - _fold_start_ 'run windeployqt to automatically copy the needed dll files' - - ..\_qt\5.15.0\msvc2019\bin\windeployqt --no-angle --no-translations --no-opengl-sw --no-system-d3d-compiler --no-compiler-runtime --no-webkit2 .\release\ - - _fold_final_ - - - _fold_start_ 'Moving results for upload' - - mv release ../'OpenRGB Windows 32-bit' - - _fold_final_ -# cache: -# key: same-key -# paths: -# - C:\vcpkg\installed\ + - scripts\build-windows.bat 5.15.0 2019 32 artifacts: name: "${CI_PROJECT_NAME}_Windows_32_${CI_COMMIT_SHORT_SHA}" paths: @@ -575,75 +408,37 @@ before_script: expire_in: 30 days rules: - - if: '$CI_PROJECT_PATH == "CalcProgrammer1/OpenRGB"' - when: on_success - - if: $CI_PIPELINE_SOURCE == "push" - when: manual - allow_failure: true + - !reference [.upstream_rules, rules] #-----------------------------------------------------------------------# -# Windows (64-bit) Build Target # +# Windows (32-bit) Qt6 Build Target # #-----------------------------------------------------------------------# -"Windows 64": +"Windows 32 Qt6": extends: - .shared_windows_runners stage: build script: - - $esc = "$([char]27)" - - $count = 0 - - function _unix_tmsec_ { [int64](([datetime]::UtcNow)-(get-date "1/1/1970")).TotalSeconds } - - function _fold_start_ { param( [string]$TEXT_TAG ) $t=_unix_tmsec_; $global:count += 1; Write-Host -NoNewLine "`r`n`r`nsection_start:${t}:sect_${count}`r${esc}[0K${esc}[33m${TEXT_TAG}${esc}[39m`r`n"; } - - function _fold_final_ { $t=_unix_tmsec_; Write-Host -NoNewLine "`r`n`r`nsection_end:${t}:sect_${count}`r${esc}[0K`r`n" ; } + - scripts\build-windows.bat 6.8.3 2022 32 + artifacts: + name: "${CI_PROJECT_NAME}_Windows_32_Qt6_${CI_COMMIT_SHORT_SHA}" + paths: + - 'OpenRGB Windows 32-bit' + exclude: + - 'OpenRGB Windows 32-bit\*.qm' + expire_in: 30 days + rules: + - !reference [.upstream_rules, rules] - - _fold_start_ 'configuring the msvc environment variables' - - Push-Location "C:/Program Files (x86)/Microsoft Visual Studio/2019/BuildTools/VC/Auxiliary/Build" - - '& cmd.exe /C "vcvarsall.bat x64 & set" | Foreach-Object { if ($_ -match "(.*?)=(.*)") { Set-Item -force -path "Env:\$($matches[1])" -value "$($matches[2])" } }' - - Pop-Location - - _fold_final_ - - - _fold_start_ 'downloading precompiled versions of qtbase, qttools (for windeployqt) and jom (for a more parallel nmake)' - - mkdir _qt - - mkdir _qt_download - - Push-Location _qt_download - - curl.exe -LJ -o qt-base.7z 'https://gitlab.com/OpenRGBDevelopers/openrgb-linux-ci-deb-builder/-/package_files/55610116/download' - - curl.exe -LJ -o qt-tools.7z 'https://gitlab.com/OpenRGBDevelopers/openrgb-linux-ci-deb-builder/-/package_files/55610131/download' - - curl.exe -LJ -o qt-jom.zip 'https://gitlab.com/OpenRGBDevelopers/openrgb-linux-ci-deb-builder/-/package_files/55610138/download' - - _fold_final_ - - - _fold_start_ 'extracting the downloaded qt binaries' - - 7z x qt-base.7z '-o../_qt' -y - - 7z x qt-tools.7z '-o../_qt' -y - - 7z x qt-jom.zip '-o../_qt' -y - - _fold_final_ - - - _fold_start_ 'turn the qt install from enterprise to foss; remove the licensing checks' - - ${qconfig-pri-folder} = '..\_qt\5.15.0\msvc2019_64\mkspecs\qconfig.pri' - - (Get-Content ${qconfig-pri-folder}).replace('QT_EDITION = Enterprise', 'QT_EDITION = OpenSource') | Set-Content ${qconfig-pri-folder} - - (Get-Content ${qconfig-pri-folder}).replace('QT_LICHECK = licheck.exe', '') | Set-Content ${qconfig-pri-folder} - - Pop-Location - - _fold_final_ - - - _fold_start_ 'run qmake and generate the msvc nmake makefile' - - mkdir _build; cd _build - - ..\_qt\5.15.0\msvc2019_64\bin\qmake ..\OpenRGB.pro - - _fold_final_ - - - _fold_start_ 'start the actual build with jom instead of nmake; for speed' - - ..\_qt\jom - - _fold_final_ - - - _fold_start_ 'run windeployqt to automatically copy the needed dll files' - - ..\_qt\5.15.0\msvc2019_64\bin\windeployqt --no-angle --no-translations --no-opengl-sw --no-system-d3d-compiler --no-compiler-runtime --no-webkit2 .\release\ - - _fold_final_ - - - _fold_start_ 'Moving results for upload' - - mv release ../'OpenRGB Windows 64-bit' - - _fold_final_ -# cache: -# key: same-key -# paths: -# - C:\vcpkg\installed\ +#-----------------------------------------------------------------------# +# Windows (64-bit) Build Target # +#-----------------------------------------------------------------------# +"Windows 64 Base": + extends: + - .shared_windows_runners + stage: build + script: + - scripts\build-windows.bat 5.15.0 2019 64 artifacts: name: "${CI_PROJECT_NAME}_Windows_64_${CI_COMMIT_SHORT_SHA}" paths: @@ -652,6 +447,67 @@ before_script: - 'OpenRGB Windows 64-bit\*.qm' expire_in: 30 days + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_PIPELINE_SOURCE == "push" + when: never + + +"Windows 64": + extends: "Windows 64 Base" + rules: + - !reference [.fork_local_runner_rules, rules] + +"Windows 64 (gitlab.com runner)": + extends: "Windows 64 Base" + before_script: + - git clone https://gitlab.com/OpenRGBDevelopers/OpenRGB-Qt-Packages + - cd OpenRGB-Qt-Packages + - .\install-chocolatey.bat + - cd .. + rules: + - !reference [.fork_gitlab_runner_rules, rules] + tags: + - "saas-windows-medium-amd64" + +#-----------------------------------------------------------------------# +# Windows (64-bit) Qt6 Build Target # +#-----------------------------------------------------------------------# +"Windows 64 Qt6 Base": + extends: + - .shared_windows_runners + stage: build + script: + - scripts\build-windows.bat 6.8.3 2022 64 + artifacts: + name: "${CI_PROJECT_NAME}_Windows_64_Qt6_${CI_COMMIT_SHORT_SHA}" + paths: + - 'OpenRGB Windows 64-bit' + exclude: + - 'OpenRGB Windows 64-bit\*.qm' + expire_in: 30 days + + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" || $CI_PIPELINE_SOURCE == "push" + when: never + + +"Windows 64 Qt6": + extends: "Windows 64 Qt6 Base" + rules: + - !reference [.fork_local_runner_rules, rules] + +"Windows 64 Qt6 (gitlab.com runner)": + extends: "Windows 64 Qt6 Base" + before_script: + - git clone https://gitlab.com/OpenRGBDevelopers/OpenRGB-Qt-Packages + - cd OpenRGB-Qt-Packages + - .\install-chocolatey.bat + - cd .. + rules: + - !reference [.fork_gitlab_runner_rules, rules] + tags: + - "saas-windows-medium-amd64" + #-----------------------------------------------------------------------# # MacOS Build Target # #-----------------------------------------------------------------------# @@ -704,3 +560,30 @@ before_script: - if: $CI_PIPELINE_SOURCE == "push" when: manual allow_failure: true + +#-----------------------------------------------------------------------# +# Windows (64-bit) MSI Target # +#-----------------------------------------------------------------------# +"Windows 64 MSI": + image: registry.gitlab.com/openrgbdevelopers/openrgb-linux-ci-deb-builder:bookworm-i386 + stage: deploy + tags: + - linux + - i386 + script: + - ls -la + - ls -la "OpenRGB Windows 64-bit/" + - ./scripts/build-msi.sh + dependencies: + - "Windows 64" + needs: + - "Windows 64" + + artifacts: + name: "${CI_PROJECT_NAME}_Windows_64_msi_${CI_COMMIT_SHORT_SHA}" + paths: + - OpenRGB_Windows_64.msi + expire_in: 30 days + + rules: + - !reference [.upstream_rules, rules] diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index f17c3308..80cf0f32 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -43,6 +43,7 @@ CODEOWNERS @Calcprogrammer1 /Controllers/EVGAGP102GPUController/ /Controllers/EVGAPascalGPUController/ /Controllers/EVGATuringGPUController/ @TheRogueZeta +/Controllers/EVGASMBusController/ @balika011 /Controllers/EVGAUSBController/ @Dr_No /Controllers/EVisionKeyboardController/ /Controllers/EspurnaController/ @@ -74,7 +75,6 @@ CODEOWNERS @Calcprogrammer1 /Controllers/NZXTHue2Controller/ /Controllers/NZXTHuePlusController/ /Controllers/NZXTKrakenController/ -/Controllers/OpenRazerController/ /Controllers/PNYGPUController/ /Controllers/PatriotViperController/ /Controllers/PhilipsHueController/ diff --git a/.gitlab/issue_templates/New Device.md b/.gitlab/issue_templates/New Device.md index a8d78925..d2056027 100644 --- a/.gitlab/issue_templates/New Device.md +++ b/.gitlab/issue_templates/New Device.md @@ -23,9 +23,9 @@ Please add a link to the manufacturer's product page beneath this line ~"DeviceType::IDK" ~"DeviceType::USB" ~"DeviceType::GPU::AMD" -~"DeviceType::GPU::NVidia" +~"DeviceType::GPU::NVidia" ~"DeviceType::SMBus" -~"DeviceType::WMI" +~"DeviceType::WMI" diff --git a/.gitlab/merge_request_templates/New Device.md b/.gitlab/merge_request_templates/New Device.md index 9740c96c..ba552ea5 100644 --- a/.gitlab/merge_request_templates/New Device.md +++ b/.gitlab/merge_request_templates/New Device.md @@ -10,6 +10,7 @@ Please put "Initial commit for" name of the product, including manufacturer abov # Checklist for Accepting a Merge Request for a New Device +- [ ] The source branch of the merge request is not protected (`master` is protected by default when creating a fork, so it is recommended to not use it as your source). - [ ] The `New Device` issue raised for this device is linked to this MR with a keyword `Closes / Resolves / Implements` - [ ] There is a device protocol page in the [Developer Wiki](https://gitlab.com/OpenRGBDevelopers/OpenRGB-Wiki) or there is enough information / captures in the `New Device` issue to provide ongoing support. - [ ] The code to be merged follows the style guide and change requirements as [documented in the contributing guide](https://gitlab.com/CalcProgrammer1/OpenRGB/-/blob/master/CONTRIBUTING.md). diff --git a/AutoStart/AutoStart-FreeBSD.cpp b/AutoStart/AutoStart-FreeBSD.cpp index f335136e..46994683 100644 --- a/AutoStart/AutoStart-FreeBSD.cpp +++ b/AutoStart/AutoStart-FreeBSD.cpp @@ -1,17 +1,20 @@ -#include "AutoStart-FreeBSD.h" -#include "LogManager.h" -#include "filesystem.h" +/*---------------------------------------------------------*\ +| AutoStart-FreeBSD.cpp | +| | +| Autostart implementation for FreeBSD | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include #include #include #include #include - -/*-----------------------------------------------------*\ -| FreeBSD AutoStart Implementation | -| Public Methods | -\*-----------------------------------------------------*/ +#include "AutoStart-FreeBSD.h" +#include "LogManager.h" +#include "filesystem.h" AutoStart::AutoStart(std::string name) { @@ -23,21 +26,21 @@ bool AutoStart::DisableAutoStart() std::error_code autostart_file_remove_errcode; bool success = false; - /*-------------------------------------------------*\ - | Check if the filename is valid | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check if the filename is valid | + \*-----------------------------------------------------*/ if(autostart_file != "") { - /*---------------------------------------------*\ - | If file doesn't exist, disable is successful | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | If file doesn't exist, disable is successful | + \*-------------------------------------------------*/ if(!filesystem::exists(autostart_file)) { success = true; } - /*---------------------------------------------*\ - | Otherwise, delete the file | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | Otherwise, delete the file | + \*-------------------------------------------------*/ else { success = filesystem::remove(autostart_file, autostart_file_remove_errcode); @@ -50,7 +53,7 @@ bool AutoStart::DisableAutoStart() } else { - LOG_ERROR("Could not establish correct autostart file path."); + LOG_ERROR("[AutoStart] Could not establish correct autostart file path."); } return(success); @@ -60,39 +63,38 @@ bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info) { bool success = false; - /*-------------------------------------------------*\ - | Check if the filename is valid | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check if the filename is valid | + \*-----------------------------------------------------*/ if(autostart_file != "") { std::ofstream autostart_file_stream(autostart_file, std::ios::out | std::ios::trunc); - /*---------------------------------------------*\ - | Error out if the file could not be opened | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | Error out if the file could not be opened | + \*-------------------------------------------------*/ if(!autostart_file_stream) { - LOG_ERROR("Could not open %s for writing.", autostart_file.c_str()); + LOG_ERROR("[AutoStart] Could not open %s for writing.", autostart_file.c_str()); success = false; } - /*---------------------------------------------*\ - | Otherwise, write the file | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | Otherwise, write the file | + \*-------------------------------------------------*/ else { - //autostart_file_stream << desktop_file; autostart_file_stream.close(); success = !autostart_file_stream.fail(); if (!success) { - LOG_ERROR("An error occurred writing the auto start file."); + LOG_ERROR("[AutoStart] An error occurred writing the auto start file."); } } } else { - LOG_ERROR("Could not establish correct autostart file path."); + LOG_ERROR("[AutoStart] Could not establish correct autostart file path."); } return(success); @@ -100,9 +102,9 @@ bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info) bool AutoStart::IsAutoStartEnabled() { - /*-------------------------------------------------*\ - | Check if the filename is valid | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check if the filename is valid | + \*-----------------------------------------------------*/ if(autostart_file != "") { return(filesystem::exists(autostart_file)); @@ -115,9 +117,9 @@ bool AutoStart::IsAutoStartEnabled() std::string AutoStart::GetExePath() { - /*-------------------------------------------------*\ - | Create the OpenRGB executable path | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Create the OpenRGB executable path | + \*-----------------------------------------------------*/ char exepath[ PATH_MAX ]; ssize_t count = readlink("/proc/self/exe", exepath, PATH_MAX); @@ -131,16 +133,16 @@ void AutoStart::InitAutoStart(std::string name) autostart_name = name; - /*-------------------------------------------------*\ - | Get home and config paths | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Get home and config paths | + \*-----------------------------------------------------*/ const char *xdg_config_home = getenv("XDG_CONFIG_HOME"); const char *home = getenv("HOME"); - /*-------------------------------------------------*\ - | Determine where the autostart .desktop files are | - | kept | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Determine where the autostart .desktop files are | + | kept | + \*-----------------------------------------------------*/ if(xdg_config_home != NULL) { autostart_dir = xdg_config_home; @@ -152,9 +154,9 @@ void AutoStart::InitAutoStart(std::string name) autostart_dir = autostart_dir + "/.config/autostart/"; } - /*-------------------------------------------------*\ - | Check if the filename is valid | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check if the filename is valid | + \*-----------------------------------------------------*/ if(autostart_dir != "") { std::error_code ec; diff --git a/AutoStart/AutoStart-FreeBSD.h b/AutoStart/AutoStart-FreeBSD.h index 1a90ec31..96d1d0b2 100644 --- a/AutoStart/AutoStart-FreeBSD.h +++ b/AutoStart/AutoStart-FreeBSD.h @@ -1,3 +1,12 @@ +/*---------------------------------------------------------*\ +| AutoStart-FreeBSD.h | +| | +| Autostart implementation for FreeBSD | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include diff --git a/AutoStart/AutoStart-Linux.cpp b/AutoStart/AutoStart-Linux.cpp index f09f97e5..b9f8451e 100644 --- a/AutoStart/AutoStart-Linux.cpp +++ b/AutoStart/AutoStart-Linux.cpp @@ -1,16 +1,20 @@ -#include "AutoStart-Linux.h" -#include "LogManager.h" -#include "filesystem.h" +/*---------------------------------------------------------*\ +| AutoStart-Linux.cpp | +| | +| Autostart implementation for Linux | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include #include +#include #include #include - -/*-----------------------------------------------------*\ -| Linux AutoStart Implementation | -| Public Methods | -\*-----------------------------------------------------*/ +#include "AutoStart-Linux.h" +#include "LogManager.h" +#include "filesystem.h" AutoStart::AutoStart(std::string name) { @@ -22,21 +26,21 @@ bool AutoStart::DisableAutoStart() std::error_code autostart_file_remove_errcode; bool success = false; - /*-------------------------------------------------*\ - | Check if the filename is valid | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check if the filename is valid | + \*-----------------------------------------------------*/ if(autostart_file != "") { - /*---------------------------------------------*\ - | If file doesn't exist, disable is successful | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | If file doesn't exist, disable is successful | + \*-------------------------------------------------*/ if(!filesystem::exists(autostart_file)) { success = true; } - /*---------------------------------------------*\ - | Otherwise, delete the file | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | Otherwise, delete the file | + \*-------------------------------------------------*/ else { success = filesystem::remove(autostart_file, autostart_file_remove_errcode); @@ -49,7 +53,7 @@ bool AutoStart::DisableAutoStart() } else { - LOG_ERROR("Could not establish correct autostart file path."); + LOG_ERROR("[AutoStart] Could not establish correct autostart file path."); } return(success); @@ -59,25 +63,25 @@ bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info) { bool success = false; - /*-------------------------------------------------*\ - | Check if the filename is valid | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check if the filename is valid | + \*-----------------------------------------------------*/ if(autostart_file != "") { std::string desktop_file = GenerateDesktopFile(autostart_info); std::ofstream autostart_file_stream(autostart_file, std::ios::out | std::ios::trunc); - /*---------------------------------------------*\ - | Error out if the file could not be opened | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | Error out if the file could not be opened | + \*-------------------------------------------------*/ if(!autostart_file_stream) { - LOG_ERROR("Could not open %s for writing.", autostart_file.c_str()); + LOG_ERROR("[AutoStart] Could not open %s for writing.", autostart_file.c_str()); success = false; } - /*---------------------------------------------*\ - | Otherwise, write the file | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | Otherwise, write the file | + \*-------------------------------------------------*/ else { autostart_file_stream << desktop_file; @@ -86,13 +90,13 @@ bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info) if (!success) { - LOG_ERROR("An error occurred writing the auto start file."); + LOG_ERROR("[AutoStart] An error occurred writing the auto start file."); } } } else { - LOG_ERROR("Could not establish correct autostart file path."); + LOG_ERROR("[AutoStart] Could not establish correct autostart file path."); } return(success); @@ -100,9 +104,9 @@ bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info) bool AutoStart::IsAutoStartEnabled() { - /*-------------------------------------------------*\ - | Check if the filename is valid | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check if the filename is valid | + \*-----------------------------------------------------*/ if(autostart_file != "") { return(filesystem::exists(autostart_file)); @@ -115,27 +119,27 @@ bool AutoStart::IsAutoStartEnabled() std::string AutoStart::GetExePath() { - /*-------------------------------------------------*\ - | Create the OpenRGB executable path | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Create the OpenRGB executable path | + \*-----------------------------------------------------*/ char exepath[ PATH_MAX ]; ssize_t count = readlink("/proc/self/exe", exepath, PATH_MAX); - + return(std::string(exepath, (count > 0) ? count : 0)); } -/*-----------------------------------------------------*\ -| Linux AutoStart Implementation | -| Private Methods | -\*-----------------------------------------------------*/ +/*---------------------------------------------------------*\ +| Linux AutoStart Implementation | +| Private Methods | +\*---------------------------------------------------------*/ std::string AutoStart::GenerateDesktopFile(AutoStartInfo autostart_info) { - /*-------------------------------------------------*\ - | Generate a .desktop file from the AutoStart | - | parameters | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Generate a .desktop file from the AutoStart | + | parameters | + \*-----------------------------------------------------*/ std::stringstream fileContents; fileContents << "[Desktop Entry]" << std::endl; @@ -147,9 +151,9 @@ std::string AutoStart::GenerateDesktopFile(AutoStartInfo autostart_info) fileContents << "Terminal=false" << std::endl; fileContents << "Type=Application" << std::endl; - /*-------------------------------------------------*\ - | Add the executable path and arguments | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Add the executable path and arguments | + \*-----------------------------------------------------*/ fileContents << "Exec=" << autostart_info.path; if (autostart_info.args != "") @@ -158,7 +162,7 @@ std::string AutoStart::GenerateDesktopFile(AutoStartInfo autostart_info) } fileContents << std::endl; - + return(fileContents.str()); } @@ -168,16 +172,16 @@ void AutoStart::InitAutoStart(std::string name) autostart_name = name; - /*-------------------------------------------------*\ - | Get home and config paths | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Get home and config paths | + \*-----------------------------------------------------*/ const char *xdg_config_home = getenv("XDG_CONFIG_HOME"); const char *home = getenv("HOME"); - /*-------------------------------------------------*\ - | Determine where the autostart .desktop files are | - | kept | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Determine where the autostart .desktop files are | + | kept | + \*-----------------------------------------------------*/ if(xdg_config_home != NULL) { autostart_dir = xdg_config_home; @@ -189,15 +193,15 @@ void AutoStart::InitAutoStart(std::string name) autostart_dir = autostart_dir + "/.config/autostart/"; } - /*-------------------------------------------------*\ - | Check if the filename is valid | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check if the filename is valid | + \*-----------------------------------------------------*/ if(autostart_dir != "") { std::error_code ec; bool success = true; - + if(!filesystem::exists(autostart_dir)) { success = filesystem::create_directories(autostart_dir, ec); diff --git a/AutoStart/AutoStart-Linux.h b/AutoStart/AutoStart-Linux.h index 3ea43ec8..b7f059c0 100644 --- a/AutoStart/AutoStart-Linux.h +++ b/AutoStart/AutoStart-Linux.h @@ -1,3 +1,12 @@ +/*---------------------------------------------------------*\ +| AutoStart-Linux.h | +| | +| Autostart implementation for Linux | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include diff --git a/AutoStart/AutoStart-MacOS.cpp b/AutoStart/AutoStart-MacOS.cpp index 9060b597..4beef379 100644 --- a/AutoStart/AutoStart-MacOS.cpp +++ b/AutoStart/AutoStart-MacOS.cpp @@ -1,18 +1,20 @@ -#include "AutoStart-MacOS.h" -#include "LogManager.h" -#include "filesystem.h" +/*---------------------------------------------------------*\ +| AutoStart-MacOS.cpp | +| | +| Autostart implementation for MacOS | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include #include #include #include - #include - -/*-----------------------------------------------------*\ -| MacOS AutoStart Implementation | -| Public Methods | -\*-----------------------------------------------------*/ +#include "AutoStart-MacOS.h" +#include "LogManager.h" +#include "filesystem.h" AutoStart::AutoStart(std::string name) { @@ -24,21 +26,21 @@ bool AutoStart::DisableAutoStart() std::error_code autostart_file_remove_errcode; bool success = false; - /*-------------------------------------------------*\ - | Check if the filename is valid | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check if the filename is valid | + \*-----------------------------------------------------*/ if(autostart_file != "") { - /*---------------------------------------------*\ - | If file doesn't exist, disable is successful | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | If file doesn't exist, disable is successful | + \*-------------------------------------------------*/ if(!filesystem::exists(autostart_file)) { success = true; } - /*---------------------------------------------*\ - | Otherwise, delete the file | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | Otherwise, delete the file | + \*-------------------------------------------------*/ else { success = filesystem::remove(autostart_file, autostart_file_remove_errcode); @@ -51,7 +53,7 @@ bool AutoStart::DisableAutoStart() } else { - LOG_ERROR("Could not establish correct autostart file path."); + LOG_ERROR("[AutoStart] Could not establish correct autostart file path."); } return(success); @@ -61,25 +63,25 @@ bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info) { bool success = false; - /*-------------------------------------------------*\ - | Check if the filename is valid | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check if the filename is valid | + \*-----------------------------------------------------*/ if(autostart_file != "") { std::string desktop_file = GenerateLaunchAgentFile(autostart_info); std::ofstream autostart_file_stream(autostart_file, std::ios::out | std::ios::trunc); - /*---------------------------------------------*\ - | Error out if the file could not be opened | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | Error out if the file could not be opened | + \*-------------------------------------------------*/ if(!autostart_file_stream) { - LOG_ERROR("Could not open %s for writing.", autostart_file.c_str()); + LOG_ERROR("[AutoStart] Could not open %s for writing.", autostart_file.c_str()); success = false; } - /*---------------------------------------------*\ - | Otherwise, write the file | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | Otherwise, write the file | + \*-------------------------------------------------*/ else { autostart_file_stream << desktop_file; @@ -88,13 +90,13 @@ bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info) if (!success) { - LOG_ERROR("An error occurred writing the auto start file."); + LOG_ERROR("[AutoStart] An error occurred writing the auto start file."); } } } else { - LOG_ERROR("Could not establish correct autostart file path."); + LOG_ERROR("[AutoStart] Could not establish correct autostart file path."); } return(success); @@ -102,9 +104,9 @@ bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info) bool AutoStart::IsAutoStartEnabled() { - /*-------------------------------------------------*\ - | Check if the filename is valid | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check if the filename is valid | + \*-----------------------------------------------------*/ if(autostart_file != "") { return(filesystem::exists(autostart_file)); @@ -117,9 +119,9 @@ bool AutoStart::IsAutoStartEnabled() std::string AutoStart::GetExePath() { - /*-------------------------------------------------*\ - | Create the OpenRGB executable path | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Create the OpenRGB executable path | + \*-----------------------------------------------------*/ char exepath[ PATH_MAX ]; uint32_t exesize = PATH_MAX; @@ -130,17 +132,17 @@ std::string AutoStart::GetExePath() return(""); } -/*-----------------------------------------------------*\ -| MacOS AutoStart Implementation | -| Private Methods | -\*-----------------------------------------------------*/ +/*---------------------------------------------------------*\ +| MacOS AutoStart Implementation | +| Private Methods | +\*---------------------------------------------------------*/ std::string AutoStart::GenerateLaunchAgentFile(AutoStartInfo autostart_info) { - /*-------------------------------------------------*\ - | Generate a .plist file from the AutoStart | - | parameters | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Generate a .plist file from the AutoStart | + | parameters | + \*-----------------------------------------------------*/ std::stringstream fileContents; fileContents << "" << std::endl; @@ -152,7 +154,7 @@ std::string AutoStart::GenerateLaunchAgentFile(AutoStartInfo autostart_info) fileContents << " ProgramArguments" << std::endl; fileContents << " " << std::endl; fileContents << " " << autostart_info.path << "" << std::endl; - + if(autostart_info.args != "") { std::istringstream arg_parser(autostart_info.args); @@ -163,12 +165,12 @@ std::string AutoStart::GenerateLaunchAgentFile(AutoStartInfo autostart_info) fileContents << " " << arg << "" << std::endl; } } - + fileContents << " " << std::endl; fileContents << " RunAtLoad" << std::endl; fileContents << "" << std::endl; fileContents << "" << std::endl; - + return(fileContents.str()); } @@ -178,22 +180,22 @@ void AutoStart::InitAutoStart(std::string name) autostart_name = name; - /*-------------------------------------------------*\ - | Determine where the autostart .desktop files are | - | kept | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Determine where the autostart .desktop files are | + | kept | + \*-----------------------------------------------------*/ autostart_dir = getenv("HOME"); autostart_dir = autostart_dir + "/Library/LaunchAgents/"; - /*-------------------------------------------------*\ - | Check if the filename is valid | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check if the filename is valid | + \*-----------------------------------------------------*/ if(autostart_dir != "") { std::error_code ec; bool success = true; - + if(!filesystem::exists(autostart_dir)) { success = filesystem::create_directories(autostart_dir, ec); diff --git a/AutoStart/AutoStart-MacOS.h b/AutoStart/AutoStart-MacOS.h index 1a90ec31..4d26ecae 100644 --- a/AutoStart/AutoStart-MacOS.h +++ b/AutoStart/AutoStart-MacOS.h @@ -1,3 +1,12 @@ +/*---------------------------------------------------------*\ +| AutoStart-MacOS.h | +| | +| Autostart implementation for MacOS | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include diff --git a/AutoStart/AutoStart-Windows.cpp b/AutoStart/AutoStart-Windows.cpp index 8ca7cd8b..2e992d89 100644 --- a/AutoStart/AutoStart-Windows.cpp +++ b/AutoStart/AutoStart-Windows.cpp @@ -1,17 +1,19 @@ -#include "AutoStart-Windows.h" -#include "LogManager.h" -#include "filesystem.h" +/*---------------------------------------------------------*\ +| AutoStart-Windows.cpp | +| | +| Autostart implementation for Windows | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include #include - -#include "windows.h" #include - -/*-----------------------------------------------------*\ -| Windows AutoStart Implementation | -| Public Methods | -\*-----------------------------------------------------*/ +#include "AutoStart-Windows.h" +#include "LogManager.h" +#include "filesystem.h" +#include "windows.h" AutoStart::AutoStart(std::string name) { @@ -23,34 +25,34 @@ bool AutoStart::DisableAutoStart() std::error_code autostart_file_remove_errcode; bool success = false; - /*-------------------------------------------------*\ - | Check if the filename is valid | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check if the filename is valid | + \*-----------------------------------------------------*/ if(autostart_file != "") { - /*---------------------------------------------*\ - | If file doesn't exist, disable is successful | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | If file doesn't exist, disable is successful | + \*-------------------------------------------------*/ if(!filesystem::exists(autostart_file)) { success = true; } - /*---------------------------------------------*\ - | Otherwise, delete the file | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | Otherwise, delete the file | + \*-------------------------------------------------*/ else { success = filesystem::remove(autostart_file, autostart_file_remove_errcode); - + if(!success) { - LOG_ERROR("An error occurred removing the auto start file."); + LOG_ERROR("[AutoStart] An error occurred removing the auto start file."); } } } else { - LOG_ERROR("Could not establish correct autostart file path."); + LOG_ERROR("[AutoStart] Could not establish correct autostart file path."); } return(success); @@ -60,9 +62,9 @@ bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info) { bool success = false; - /*-------------------------------------------------*\ - | Check if the filename is valid | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check if the filename is valid | + \*-----------------------------------------------------*/ if(autostart_file != "") { bool weInitialised = false; @@ -77,9 +79,9 @@ bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info) result = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLinkW, (void**)&shellLink); - /*---------------------------------------------*\ - | If not initialized, initialize | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | If not initialized, initialize | + \*-------------------------------------------------*/ if(result == CO_E_NOTINITIALIZED) { weInitialised = true; @@ -87,21 +89,21 @@ bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info) result = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_ALL, IID_IShellLinkW, (void**)&shellLink); } - /*---------------------------------------------*\ - | If successfully initialized, save a shortcut | - | from the AutoStart parameters | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | If successfully initialized, save a shortcut | + | from the AutoStart parameters | + \*-------------------------------------------------*/ if(SUCCEEDED(result)) { shellLink->SetPath(exepathw.c_str()); shellLink->SetArguments(argumentsw.c_str()); shellLink->SetDescription(descriptionw.c_str()); shellLink->SetIconLocation(iconw.c_str(), 0); - + IPersistFile* persistFile; - + result = shellLink->QueryInterface(IID_IPersistFile, (void**)&persistFile); - + if(SUCCEEDED(result)) { result = persistFile->Save(startupfilepathw.c_str(), TRUE); @@ -112,9 +114,9 @@ bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info) shellLink->Release(); } - /*---------------------------------------------*\ - | Uninitialize when done | - \*---------------------------------------------*/ + /*-------------------------------------------------*\ + | Uninitialize when done | + \*-------------------------------------------------*/ if(weInitialised) { CoUninitialize(); @@ -122,7 +124,7 @@ bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info) } else { - LOG_ERROR("Could not establish correct autostart file path."); + LOG_ERROR("[AutoStart] Could not establish correct autostart file path."); } return success; @@ -130,9 +132,9 @@ bool AutoStart::EnableAutoStart(AutoStartInfo autostart_info) bool AutoStart::IsAutoStartEnabled() { - /*-------------------------------------------------*\ - | Check if the filename is valid | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check if the filename is valid | + \*-----------------------------------------------------*/ if(autostart_file != "") { return(filesystem::exists(autostart_file)); @@ -145,20 +147,20 @@ bool AutoStart::IsAutoStartEnabled() std::string AutoStart::GetExePath() { - /*-------------------------------------------------*\ - | Create the OpenRGB executable path | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Create the OpenRGB executable path | + \*-----------------------------------------------------*/ char exepath[MAX_PATH] = ""; DWORD count = GetModuleFileNameA(NULL, exepath, MAX_PATH); - + return(std::string(exepath, (count > 0) ? count : 0)); } -/*-----------------------------------------------------*\ -| Windows AutoStart Implementation | -| Private Methods | -\*-----------------------------------------------------*/ +/*---------------------------------------------------------*\ +| Windows AutoStart Implementation | +| Private Methods | +\*---------------------------------------------------------*/ void AutoStart::InitAutoStart(std::string name) { @@ -166,9 +168,9 @@ void AutoStart::InitAutoStart(std::string name) autostart_name = name; - /*-------------------------------------------------*\ - | Get startup applications path | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Get startup applications path | + \*-----------------------------------------------------*/ HRESULT result = SHGetFolderPathA(NULL, CSIDL_PROGRAMS, NULL, 0, startMenuPath); if(SUCCEEDED(result)) @@ -183,10 +185,10 @@ void AutoStart::InitAutoStart(std::string name) } } -/*-----------------------------------------------------*\ -| Convert an UTF8 string to a wide Unicode String | -| (from wmi.cpp) | -\*-----------------------------------------------------*/ +/*---------------------------------------------------------*\ +| Convert an UTF8 string to a wide Unicode String | +| (from wmi.cpp) | +\*---------------------------------------------------------*/ std::wstring AutoStart::utf8_decode(const std::string& str) { if(str.empty()) @@ -197,8 +199,8 @@ std::wstring AutoStart::utf8_decode(const std::string& str) int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int) str.size(), nullptr, 0); std::wstring wstrTo(size_needed, 0); - + MultiByteToWideChar(CP_UTF8, 0, &str[0], (int) str.size(), &wstrTo[0], size_needed); - + return(wstrTo); } diff --git a/AutoStart/AutoStart-Windows.h b/AutoStart/AutoStart-Windows.h index 017ec59a..96dced9f 100644 --- a/AutoStart/AutoStart-Windows.h +++ b/AutoStart/AutoStart-Windows.h @@ -1,3 +1,12 @@ +/*---------------------------------------------------------*\ +| AutoStart-Windows.h | +| | +| Autostart implementation for Windows | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include diff --git a/AutoStart/AutoStart.cpp b/AutoStart/AutoStart.cpp index a483e29d..0b07cc56 100644 --- a/AutoStart/AutoStart.cpp +++ b/AutoStart/AutoStart.cpp @@ -1,9 +1,13 @@ -#include "AutoStart.h" +/*---------------------------------------------------------*\ +| AutoStart.cpp | +| | +| Autostart common implementation | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -/*-----------------------------------------------------*\ -| Common AutoStart Implementation | -| Public Methods | -\*-----------------------------------------------------*/ +#include "AutoStart.h" std::string AutoStartInterface::GetAutoStartFile() { diff --git a/AutoStart/AutoStart.h b/AutoStart/AutoStart.h index 7b37e7c3..04eb432e 100644 --- a/AutoStart/AutoStart.h +++ b/AutoStart/AutoStart.h @@ -1,3 +1,12 @@ +/*---------------------------------------------------------*\ +| AutoStart.h | +| | +| Autostart common implementation | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 15dd819b..678764a6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,6 +11,7 @@ To create a merge request, log into GitLab and fork the OpenRGB project. Push y * Mark your merge request as a draft (start title with "Draft:") until it has been tested and verified working. * Follow the Style Guidelines below when making your code changes. * Avoid using `git merge` when updating your fork. The OpenRGB project uses a linear git history, meaning all changes are rebased onto the tip of master. By using `git rebase` to update your fork, you will make it easier to accept merge requests. +* Do not submit a merge request using your fork's `master` branch as the source. The `master` branch is protected by default when creating a fork and I cannot manually rebase a protected branch before merging. If you submit a merge request with a protected `master` branch as the source, it may not get merged until you unprotect it. ### Pipelines, Shared Runners and Quotas @@ -66,3 +67,8 @@ OpenRGB is written in C++, uses the Qt framework for UI, and uses the QMake buil | This is a comment | \*_-------------------------------*/ ``` + +## Translating + +Translation files are located in [`OpenRGB/qt/i18n/`](https://gitlab.com/CalcProgrammer1/OpenRGB/-/tree/master/qt/i18n), where languages are formatted using ISO 639-1 format: `OpenRGB_xx_XX.ts` — `xx_XX` representing the language code. +In order to translate a file, you need to [fork](https://gitlab.com/CalcProgrammer1/OpenRGB/-/forks/new) the project, create a new file for your language with `lupdate` (or edit an exisiting one), edit the file with `qtlinguist`, commit, push, and create a merge request. diff --git a/Colors.h b/Colors.h index 345df3ad..7c890991 100644 --- a/Colors.h +++ b/Colors.h @@ -1,3 +1,12 @@ +/*---------------------------------------------------------*\ +| Colors.h | +| | +| List of named color constants | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #ifndef COLORS_H #define COLORS_H diff --git a/Controllers/A4TechController/A4Tech_Detector.cpp b/Controllers/A4TechController/A4Tech_Detector.cpp index 4e2dcea9..c728e048 100644 --- a/Controllers/A4TechController/A4Tech_Detector.cpp +++ b/Controllers/A4TechController/A4Tech_Detector.cpp @@ -1,15 +1,26 @@ +/*---------------------------------------------------------*\ +| A4TechDetector.cpp | +| | +| Detector for A4Tech Devices | +| | +| Chris M (Dr_No) 30 Jun 2022 | +| Mohammed Julfikar Ali Mahbub (o-julfikar) 01 Apr 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + /*-----------------------------------------------------*\ | OpenRGB includes | \*-----------------------------------------------------*/ -#include +#include #include "Detector.h" -#include "LogManager.h" -#include "RGBController.h" /*-----------------------------------------------------*\ | A4 Tech specific includes | \*-----------------------------------------------------*/ #include "RGBController_BloodyMouse.h" +#include "RGBController_BloodyB820R.h" /*-----------------------------------------------------*\ | A4 Tech USB vendor ID | @@ -22,13 +33,29 @@ void DetectA4TechMouseControllers(hid_device_info* info, const std::string& name if(dev) { - BloodyMouseController* controller = new BloodyMouseController(dev, info->path, info->product_id); + BloodyMouseController* controller = new BloodyMouseController(dev, info->path, info->product_id, name); RGBController_BloodyMouse* rgb_controller = new RGBController_BloodyMouse(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } -REGISTER_HID_DETECTOR_IPU("Bloody W60 Pro", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_W60_PRO_PID, 2, 0xFF33, 0x0529); -REGISTER_HID_DETECTOR_IPU("Bloody MP 50RS", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_MP_50RS_PID, 2, 0xFFF2, 0x6009); +void DetectBloodyB820R(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + BloodyB820RController* controller = new BloodyB820RController(dev, info->path, name); + RGBController_BloodyB820R* rgb_controller = new RGBController_BloodyB820R(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR_IPU("Bloody W60 Pro", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_W60_PRO_PID, 2, 0xFF33, 0x0529); +REGISTER_HID_DETECTOR_IPU("Bloody W70 Max", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_W70_MAX_PID, 2, 0xFF33, 0x0518); +REGISTER_HID_DETECTOR_IPU("Bloody W90 Max", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_W90_MAX_PID, 2, 0xFF33, 0x053D); +REGISTER_HID_DETECTOR_IPU("Bloody W90 Pro", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_W90_PRO_PID, 2, 0xFF33, 0x054D); +REGISTER_HID_DETECTOR_IPU("Bloody MP 50RS", DetectA4TechMouseControllers, A4_TECH_VID, BLOODY_MP_50RS_PID, 2, 0xFFF2, 0x6009); +REGISTER_HID_DETECTOR_IPU("Bloody B820R", DetectBloodyB820R, A4_TECH_VID, BLOODY_B820R_PID, 2, 0xFF52, 0x0210); diff --git a/Controllers/A4TechController/BloodyB820RController/BloodyB820RController.cpp b/Controllers/A4TechController/BloodyB820RController/BloodyB820RController.cpp new file mode 100644 index 00000000..d702058a --- /dev/null +++ b/Controllers/A4TechController/BloodyB820RController/BloodyB820RController.cpp @@ -0,0 +1,110 @@ +/*---------------------------------------------------------*\ +| BloodyB820RController.cpp | +| | +| Driver for A4Tech Bloody B820R Keyboard | +| | +| Mohammed Julfikar Ali Mahbub (o-julfikar) 01 Apr 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "BloodyB820RController.h" +#include "StringUtils.h" + +/*-------------------------------------------------------------------------------------*\ +| The controller for this device should pass a packet of 64 bytes where the subsequent | +| two packets are for RED, GREEN, and BLUE respectively. The first 6 bytes are control | +| or information bytes and colors bytes starts from index 6. Moreover, the first pack- | +| et of each RGB contains color for 58 keys and the rest (104 - 58 == 46) are send on | +| the second packet. | +\*-------------------------------------------------------------------------------------*/ + +BloodyB820RController::BloodyB820RController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + + SendControlPacket(BLOODY_B820R_GAIN_CONTROL); +} + +BloodyB820RController::~BloodyB820RController() +{ + SendControlPacket(BLOODY_B820R_RELEASE_CONTROL); + hid_close(dev); +} + +std::string BloodyB820RController::GetSerial() +{ + wchar_t serial_string[HID_MAX_STR]; + int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string BloodyB820RController::GetLocation() +{ + return("HID: " + location); +} + +std::string BloodyB820RController::GetName() +{ + return(name); +} + +void BloodyB820RController::SendControlPacket(uint8_t data) +{ + uint8_t buffer[BLOODY_B820R_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00 }; + + hid_send_feature_report(dev, buffer, BLOODY_B820R_PACKET_SIZE); + + buffer[BLOODY_B820R_MODE_BYTE] = 0; + buffer[BLOODY_B820R_DATA_BYTE] = data; + + hid_send_feature_report(dev, buffer, BLOODY_B820R_PACKET_SIZE); +} + +void BloodyB820RController::SetLEDDirect(std::vector colors) +{ + + uint8_t r1_buffer[BLOODY_B820R_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x07, 0x00, 0x00 }; + uint8_t r2_buffer[BLOODY_B820R_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x08, 0x00, 0x00 }; + uint8_t g1_buffer[BLOODY_B820R_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x09, 0x00, 0x00 }; + uint8_t g2_buffer[BLOODY_B820R_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x0A, 0x00, 0x00 }; + uint8_t b1_buffer[BLOODY_B820R_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x0B, 0x00, 0x00 }; + uint8_t b2_buffer[BLOODY_B820R_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x0C, 0x00, 0x00 }; + + /*-----------------------------------------------------------------*\ + | Set up Direct packet | + | packet_map is the index of the Key from full_matrix_map and | + | the value is the position in the direct packet buffer | + \*-----------------------------------------------------------------*/ + for(size_t i = 0; i < colors.size(); i++) + { + RGBColor color = colors[i]; + uint8_t offset = BLOODY_B820R_RGB_OFFSET; + uint8_t buffer_idx = offset + i % BLOODY_B820R_RGB_BUFFER_SIZE; + uint8_t* buffers[2][3] = + { + {r1_buffer, g1_buffer, b1_buffer}, + {r2_buffer, g2_buffer, b2_buffer} + }; + + buffers[i >= BLOODY_B820R_RGB_BUFFER_SIZE][0][buffer_idx] = RGBGetRValue(color); + buffers[i >= BLOODY_B820R_RGB_BUFFER_SIZE][1][buffer_idx] = RGBGetGValue(color); + buffers[i >= BLOODY_B820R_RGB_BUFFER_SIZE][2][buffer_idx] = RGBGetBValue(color); + } + + hid_send_feature_report(dev, r1_buffer, BLOODY_B820R_PACKET_SIZE); + hid_send_feature_report(dev, r2_buffer, BLOODY_B820R_PACKET_SIZE); + hid_send_feature_report(dev, g1_buffer, BLOODY_B820R_PACKET_SIZE); + hid_send_feature_report(dev, g2_buffer, BLOODY_B820R_PACKET_SIZE); + hid_send_feature_report(dev, b1_buffer, BLOODY_B820R_PACKET_SIZE); + hid_send_feature_report(dev, b2_buffer, BLOODY_B820R_PACKET_SIZE); +} diff --git a/Controllers/A4TechController/BloodyB820RController/BloodyB820RController.h b/Controllers/A4TechController/BloodyB820RController/BloodyB820RController.h new file mode 100644 index 00000000..1a32448b --- /dev/null +++ b/Controllers/A4TechController/BloodyB820RController/BloodyB820RController.h @@ -0,0 +1,55 @@ +/*---------------------------------------------------------*\ +| BloodyB820RController.h | +| | +| Driver for A4Tech Bloody B820R Keyboard | +| | +| Mohammed Julfikar Ali Mahbub (o-julfikar) 01 Apr 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define HID_MAX_STR 255 + +#define BLOODY_B820R_RGB_BUFFER_SIZE 58 +#define BLOODY_B820R_RGB_OFFSET 6 +#define BLOODY_B820R_PACKET_SIZE 64 +#define BLOODY_B820R_KEYCOUNT 104 +#define BLOODY_B820R_MODE_BYTE 3 +#define BLOODY_B820R_DATA_BYTE 8 +#define BLOODY_B820R_GAIN_CONTROL 0x01 +#define BLOODY_B820R_RELEASE_CONTROL 0x00 + +/*---------------------------------------------------------*\ +| Bloody B820R product ID | +\*---------------------------------------------------------*/ +#define BLOODY_B820R_PID 0xFA10 + +enum +{ + BLOODY_B820R_MODE_DIRECT = 0x01, // Direct LED control - Independently set LEDs in zone +}; + +class BloodyB820RController +{ +public: + BloodyB820RController(hid_device* dev_handle, const char* path, std::string dev_name); + ~BloodyB820RController(); + + std::string GetSerial(); + std::string GetLocation(); + std::string GetName(); + + void SetLEDDirect(std::vector colors); + void SendControlPacket(uint8_t data); +private: + std::string location; + std::string name; + hid_device* dev; +}; diff --git a/Controllers/A4TechController/BloodyB820RController/RGBController_BloodyB820R.cpp b/Controllers/A4TechController/BloodyB820RController/RGBController_BloodyB820R.cpp new file mode 100644 index 00000000..f3ad57b5 --- /dev/null +++ b/Controllers/A4TechController/BloodyB820RController/RGBController_BloodyB820R.cpp @@ -0,0 +1,253 @@ +/*---------------------------------------------------------*\ +| RGBController_BloodyB820R.cpp | +| | +| RGBController for A4Tech Bloody B820R Keyboard | +| | +| Mohammed Julfikar Ali Mahbub (o-julfikar) 01 Apr 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBControllerKeyNames.h" +#include "RGBController_BloodyB820R.h" + +//0xFFFFFFFF indicates an unused entry in matrix +#define NA 0xFFFFFFFF + +static unsigned int matrix_map[6][21] = + { + {0, NA, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, NA, NA, NA, NA, 13, 14, 15}, + {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36}, + {37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57}, + {58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, NA, NA, NA, NA, 71, 72, 73, NA}, + {74, NA, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, NA, NA, 86, NA, 87, 88, 89, 90}, + {91, 92, 93, 94, NA, NA, NA, NA, NA, NA, 95, 96, 97, 98, 99, 100, 101, 102, NA, 103, NA}, + }; + +static const char *led_names[] = + { + KEY_EN_ESCAPE, //00 + KEY_EN_F1, + KEY_EN_F2, + KEY_EN_F3, + KEY_EN_F4, + KEY_EN_F5, + KEY_EN_F6, + KEY_EN_F7, + KEY_EN_F8, + KEY_EN_F9, + KEY_EN_F10, + KEY_EN_F11, + KEY_EN_F12, + KEY_EN_PRINT_SCREEN, + KEY_EN_SCROLL_LOCK, + KEY_EN_PAUSE_BREAK, + + KEY_EN_BACK_TICK, //10 + KEY_EN_1, + KEY_EN_2, + KEY_EN_3, + KEY_EN_4, + KEY_EN_5, + KEY_EN_6, + KEY_EN_7, + KEY_EN_8, + KEY_EN_9, + KEY_EN_0, + KEY_EN_MINUS, + KEY_EN_EQUALS, + KEY_EN_BACKSPACE, + KEY_EN_INSERT, + KEY_EN_HOME, + KEY_EN_PAGE_UP, + KEY_EN_NUMPAD_LOCK, + KEY_EN_NUMPAD_DIVIDE, + KEY_EN_NUMPAD_TIMES, + KEY_EN_NUMPAD_MINUS, + + KEY_EN_TAB, //20 + KEY_EN_Q, + KEY_EN_W, + KEY_EN_E, + KEY_EN_R, + KEY_EN_T, + KEY_EN_Y, + KEY_EN_U, + KEY_EN_I, + KEY_EN_O, + KEY_EN_P, + KEY_EN_LEFT_BRACKET, + KEY_EN_RIGHT_BRACKET, + KEY_EN_ANSI_BACK_SLASH, + KEY_EN_DELETE, + KEY_EN_END, + KEY_EN_PAGE_DOWN, + KEY_EN_NUMPAD_7, + KEY_EN_NUMPAD_8, + KEY_EN_NUMPAD_9, + KEY_EN_NUMPAD_PLUS, + + KEY_EN_CAPS_LOCK, //30 + KEY_EN_A, + KEY_EN_S, + KEY_EN_D, + KEY_EN_F, + KEY_EN_G, + KEY_EN_H, + KEY_EN_J, + KEY_EN_K, + KEY_EN_L, + KEY_EN_SEMICOLON, + KEY_EN_QUOTE, + KEY_EN_ANSI_ENTER, + KEY_EN_NUMPAD_4, + KEY_EN_NUMPAD_5, + KEY_EN_NUMPAD_6, + + KEY_EN_LEFT_SHIFT, //40 + KEY_EN_Z, + KEY_EN_X, + KEY_EN_C, + KEY_EN_V, + KEY_EN_B, + KEY_EN_N, + KEY_EN_M, + KEY_EN_COMMA, + KEY_EN_PERIOD, + KEY_EN_FORWARD_SLASH, + KEY_EN_RIGHT_SHIFT, + KEY_EN_UP_ARROW, + KEY_EN_NUMPAD_1, + KEY_EN_NUMPAD_2, + KEY_EN_NUMPAD_3, + KEY_EN_NUMPAD_ENTER, + + KEY_EN_LEFT_CONTROL, //50 + KEY_EN_LEFT_WINDOWS, + KEY_EN_LEFT_ALT, + KEY_EN_SPACE, + KEY_EN_RIGHT_ALT, + KEY_EN_RIGHT_FUNCTION, + KEY_EN_MENU, + KEY_EN_RIGHT_CONTROL, + KEY_EN_LEFT_ARROW, + KEY_EN_DOWN_ARROW, + KEY_EN_RIGHT_ARROW, + KEY_EN_NUMPAD_0, + KEY_EN_NUMPAD_PERIOD + }; + +/**------------------------------------------------------------------*\ + @name A4Tech Bloody B820R + @category Keyboard + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectBloodyB820R + @comment The A4Tech Bloody B820R keyboard controller currently + supports the full size (ANSI layout). +\*-------------------------------------------------------------------*/ + +RGBController_BloodyB820R::RGBController_BloodyB820R(BloodyB820RController *controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = "A4Tech"; + type = DEVICE_TYPE_KEYBOARD; + description = "A4Tech Bloody Keyboard"; + serial = controller->GetSerial(); + location = controller->GetLocation(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = BLOODY_B820R_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + SetupZones(); +} + +RGBController_BloodyB820R::~RGBController_BloodyB820R() +{ + delete controller; +} + +void RGBController_BloodyB820R::SetupZones() +{ + /*-------------------------------------------------*\ + | Create the Keyboard zone and add the matrix map | + \*-------------------------------------------------*/ + zone KB_zone; + KB_zone.name = ZONE_EN_KEYBOARD; + KB_zone.type = ZONE_TYPE_MATRIX; + KB_zone.leds_min = BLOODY_B820R_KEYCOUNT; + KB_zone.leds_max = BLOODY_B820R_KEYCOUNT; + KB_zone.leds_count = BLOODY_B820R_KEYCOUNT; + + KB_zone.matrix_map = new matrix_map_type; + KB_zone.matrix_map->height = 6; + KB_zone.matrix_map->width = 21; + KB_zone.matrix_map->map = (unsigned int *)&matrix_map; + zones.push_back(KB_zone); + + /*-------------------------------------------------*\ + | Clear any existing color/LED configuration | + \*-------------------------------------------------*/ + leds.clear(); + colors.clear(); + + /*---------------------------------------------------------*\ + | Set up zones | + \*---------------------------------------------------------*/ + for(unsigned int led_index = 0; led_index < BLOODY_B820R_KEYCOUNT; led_index++) + { + led new_led; + new_led.name = led_names[led_index]; + new_led.value = led_index; + leds.push_back(new_led); + } + + SetupColors(); +} + +void RGBController_BloodyB820R::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + + +void RGBController_BloodyB820R::DeviceUpdateLEDs() +{ + controller->SetLEDDirect(colors); +} + +void RGBController_BloodyB820R::UpdateZoneLEDs(int zone) +{ + std::vector colour; + + for(size_t i = 0; i < zones[zone].leds_count; i++) + { + colour.push_back(zones[zone].colors[i]); + } + + controller->SetLEDDirect(colour); +} + +void RGBController_BloodyB820R::UpdateSingleLED(int led) +{ + std::vector colour; + colour.push_back(colors[led]); + + controller->SetLEDDirect(colour); +} + +void RGBController_BloodyB820R::DeviceUpdateMode() +{ + /* This device does not support modes yet */ +} diff --git a/Controllers/A4TechController/BloodyB820RController/RGBController_BloodyB820R.h b/Controllers/A4TechController/BloodyB820RController/RGBController_BloodyB820R.h new file mode 100644 index 00000000..a9659e60 --- /dev/null +++ b/Controllers/A4TechController/BloodyB820RController/RGBController_BloodyB820R.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_BloodyB820R.h | +| | +| RGBController for A4Tech Bloody B820R Keyboard | +| | +| Mohammed Julfikar Ali Mahbub (o-julfikar) 01 Apr 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "BloodyB820RController.h" + +class RGBController_BloodyB820R : public RGBController +{ +public: + RGBController_BloodyB820R(BloodyB820RController* controller_ptr); + ~RGBController_BloodyB820R(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + BloodyB820RController* controller; +}; diff --git a/Controllers/A4TechController/BloodyMouseController.cpp b/Controllers/A4TechController/BloodyMouseController.cpp deleted file mode 100644 index 1f33c9ab..00000000 --- a/Controllers/A4TechController/BloodyMouseController.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/*---------------------------------------------------------------------*\ -| BloodyMouseController.cpp | -| | -| Driver for BloodyMouse USB Controller | -| | -| Chris M (Dr_No) 30 Jun 2022 | -| | -\*---------------------------------------------------------------------*/ - -#include "BloodyMouseController.h" - -BloodyMouseController::BloodyMouseController(hid_device* dev_handle, const char* path, uint16_t product_id) -{ - dev = dev_handle; - location = path; - pid = product_id; - - InitDevice(); -} - -BloodyMouseController::~BloodyMouseController() -{ - hid_close(dev); -} - -uint16_t BloodyMouseController::GetPid() -{ - return pid; -} - -std::string BloodyMouseController::GetSerial() -{ - const uint8_t sz = HID_MAX_STR; - wchar_t tmp[sz]; - - int ret = hid_get_serial_number_string(dev, tmp, sz); - - if (ret != 0) - { - LOG_DEBUG("[BloodyMouse] Get HID Serial string failed"); - return(""); - } - - std::wstring w_tmp = std::wstring(tmp); - std::string serial = std::string(w_tmp.begin(), w_tmp.end()); - - return serial; -} - -std::string BloodyMouseController::GetLocation() -{ - return("HID: " + location); -} - -void BloodyMouseController::InitDevice() -{ - uint8_t buffer[BLOODYMOUSE_WRITE_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00 }; - - hid_send_feature_report(dev, buffer, BLOODYMOUSE_WRITE_PACKET_SIZE); - - buffer[BLOODYMOUSE_MODE_BYTE] = 0; - buffer[BLOODYMOUSE_DATA_BYTE] = 1; - - hid_send_feature_report(dev, buffer, BLOODYMOUSE_WRITE_PACKET_SIZE); -} - -void BloodyMouseController::SetLedsDirect(std::vector colors) -{ - uint8_t buffer[BLOODYMOUSE_WRITE_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00 }; - - for(uint8_t i = 0; i < colors.size(); i++) - { - uint8_t offset = 3 * (colors[i] >> 24) + BLOODYMOUSE_DATA_BYTE; - - buffer[offset] = RGBGetRValue(colors[i]); - buffer[offset + 1] = RGBGetGValue(colors[i]); - buffer[offset + 2] = RGBGetBValue(colors[i]); - } - - hid_send_feature_report(dev, buffer, BLOODYMOUSE_WRITE_PACKET_SIZE); -} diff --git a/Controllers/A4TechController/BloodyMouseController.h b/Controllers/A4TechController/BloodyMouseController.h deleted file mode 100644 index e8841351..00000000 --- a/Controllers/A4TechController/BloodyMouseController.h +++ /dev/null @@ -1,63 +0,0 @@ -/*---------------------------------------------------------------------*\ -| BloodyMouseController.h | -| | -| Driver for BloodyMouse USB Controller | -| | -| Chris M (Dr_No) 30 Jun 2022 | -| | -\*---------------------------------------------------------------------*/ - -#include -#include -#include "LogManager.h" -#include "RGBController.h" - -#pragma once - -/*-----------------------------------------------------*\ -| Mouse product IDs | -\*-----------------------------------------------------*/ -#define BLOODY_W60_PRO_PID 0x37EA - -/*-----------------------------------------------------*\ -| Mousemat product IDs | -\*-----------------------------------------------------*/ -#define BLOODY_MP_50RS_PID 0xFA60 - -#define HID_MAX_STR 255 -#define BLOODYMOUSE_WRITE_PACKET_SIZE 64 - -#define BLOODYMOUSE_BRIGHTNESS_MIN 0 -#define BLOODYMOUSE_BRIGHTNESS_MAX 255 - -enum -{ - BLOODYMOUSE_MODE_DIRECT = 0x01, //Direct Led Control - Independently set LEDs in zone -}; - -enum -{ - BLOODYMOUSE_REPORT_BYTE = 1, - BLOODYMOUSE_COMMAND_BYTE = 2, - BLOODYMOUSE_MODE_BYTE = 3, - BLOODYMOUSE_DATA_BYTE = 8, -}; - -class BloodyMouseController -{ -public: - BloodyMouseController(hid_device* dev_handle, const char* path, uint16_t product_id); - ~BloodyMouseController(); - - uint16_t GetPid(); - std::string GetSerial(); - std::string GetLocation(); - - void SetLedsDirect(std::vector colors); -private: - uint16_t pid; - std::string location; - hid_device* dev; - - void InitDevice(); -}; diff --git a/Controllers/A4TechController/BloodyMouseController/BloodyMouseController.cpp b/Controllers/A4TechController/BloodyMouseController/BloodyMouseController.cpp new file mode 100644 index 00000000..9091b37c --- /dev/null +++ b/Controllers/A4TechController/BloodyMouseController/BloodyMouseController.cpp @@ -0,0 +1,84 @@ +/*---------------------------------------------------------*\ +| BloodyMouseController.cpp | +| | +| Driver for A4Tech Bloody Mouse | +| | +| Chris M (Dr_No) 30 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "BloodyMouseController.h" +#include "StringUtils.h" + +BloodyMouseController::BloodyMouseController(hid_device* dev_handle, const char* path, uint16_t product_id, std::string dev_name) +{ + dev = dev_handle; + location = path; + pid = product_id; + name = dev_name; + + InitDevice(); +} + +BloodyMouseController::~BloodyMouseController() +{ + hid_close(dev); +} + +uint16_t BloodyMouseController::GetPid() +{ + return(pid); +} + +std::string BloodyMouseController::GetSerial() +{ + wchar_t serial_string[HID_MAX_STR]; + int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string BloodyMouseController::GetLocation() +{ + return("HID: " + location); +} + +std::string BloodyMouseController::GetName() +{ + return(name); +} + +void BloodyMouseController::InitDevice() +{ + uint8_t buffer[BLOODYMOUSE_WRITE_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00 }; + + hid_send_feature_report(dev, buffer, BLOODYMOUSE_WRITE_PACKET_SIZE); + + buffer[BLOODYMOUSE_MODE_BYTE] = 0; + buffer[BLOODYMOUSE_DATA_BYTE] = 1; + + hid_send_feature_report(dev, buffer, BLOODYMOUSE_WRITE_PACKET_SIZE); +} + +void BloodyMouseController::SetLedsDirect(std::vector colors) +{ + uint8_t buffer[BLOODYMOUSE_WRITE_PACKET_SIZE] = { 0x07, 0x03, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00 }; + + for(uint8_t i = 0; i < colors.size(); i++) + { + uint8_t offset = 3 * (colors[i] >> 24) + BLOODYMOUSE_DATA_BYTE; + + buffer[offset] = RGBGetRValue(colors[i]); + buffer[offset + 1] = RGBGetGValue(colors[i]); + buffer[offset + 2] = RGBGetBValue(colors[i]); + } + + hid_send_feature_report(dev, buffer, BLOODYMOUSE_WRITE_PACKET_SIZE); +} diff --git a/Controllers/A4TechController/BloodyMouseController/BloodyMouseController.h b/Controllers/A4TechController/BloodyMouseController/BloodyMouseController.h new file mode 100644 index 00000000..de162415 --- /dev/null +++ b/Controllers/A4TechController/BloodyMouseController/BloodyMouseController.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------*\ +| BloodyMouseController.h | +| | +| Driver for A4Tech Bloody Mouse | +| | +| Chris M (Dr_No) 30 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +/*-----------------------------------------------------*\ +| Mouse product IDs | +\*-----------------------------------------------------*/ +#define BLOODY_W60_PRO_PID 0x37EA +#define BLOODY_W70_MAX_PID 0x79EF +#define BLOODY_W90_MAX_PID 0x3666 +#define BLOODY_W90_PRO_PID 0x39B6 + +/*-----------------------------------------------------*\ +| Mousemat product IDs | +\*-----------------------------------------------------*/ +#define BLOODY_MP_50RS_PID 0xFA60 + +#define HID_MAX_STR 255 +#define BLOODYMOUSE_WRITE_PACKET_SIZE 64 + +#define BLOODYMOUSE_BRIGHTNESS_MIN 0 +#define BLOODYMOUSE_BRIGHTNESS_MAX 255 + +enum +{ + BLOODYMOUSE_MODE_DIRECT = 0x01, //Direct Led Control - Independently set LEDs in zone +}; + +enum +{ + BLOODYMOUSE_REPORT_BYTE = 1, + BLOODYMOUSE_COMMAND_BYTE = 2, + BLOODYMOUSE_MODE_BYTE = 3, + BLOODYMOUSE_DATA_BYTE = 8, +}; + +class BloodyMouseController +{ +public: + BloodyMouseController(hid_device* dev_handle, const char* path, uint16_t product_id, std::string dev_name); + ~BloodyMouseController(); + + uint16_t GetPid(); + std::string GetSerial(); + std::string GetLocation(); + std::string GetName(); + + void SetLedsDirect(std::vector colors); + +private: + uint16_t pid; + std::string location; + std::string name; + hid_device* dev; + + void InitDevice(); +}; diff --git a/Controllers/A4TechController/RGBController_BloodyMouse.cpp b/Controllers/A4TechController/BloodyMouseController/RGBController_BloodyMouse.cpp similarity index 80% rename from Controllers/A4TechController/RGBController_BloodyMouse.cpp rename to Controllers/A4TechController/BloodyMouseController/RGBController_BloodyMouse.cpp index 230c629c..d25a7dd4 100644 --- a/Controllers/A4TechController/RGBController_BloodyMouse.cpp +++ b/Controllers/A4TechController/BloodyMouseController/RGBController_BloodyMouse.cpp @@ -1,11 +1,13 @@ -/*---------------------------------------------------------------------*\ -| RGBController_BloodyMouse.cpp | -| | -| Driver for BloodyMouse USB Controller | -| | -| Chris M (Dr_No) 30 Jun 2022 | -| | -\*---------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_BloodyMouse.cpp | +| | +| RGBController for A4Tech Bloody Mouse | +| | +| Chris M (Dr_No) 30 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_BloodyMouse.h" @@ -25,6 +27,19 @@ static const mouse_layout w60_pro } }; +static const mouse_layout w90_max +{ + { + "Scroll Wheel", { 14 } + }, + { + "Logo", { 7 } + }, + { + "Rear", { 13, 12, 11, 10, 9, 8, 6, 5, 4, 3, 2, 1, 0 } + } +}; + static const mouse_layout mp_50rs { { @@ -56,7 +71,7 @@ RGBController_BloodyMouse::RGBController_BloodyMouse(BloodyMouseController *cont type = DEVICE_TYPE_MOUSE; } - name = "BloodyMouse"; + name = controller->GetName(); vendor = "Bloody"; description = "Controller compatible with the Bloody W60 Pro and MP 50RS"; serial = controller->GetSerial(); @@ -89,11 +104,17 @@ void RGBController_BloodyMouse::SetupZones() | Select layout from PID | \*-------------------------------------------------*/ mouse_layout layout; + switch(controller->GetPid()) { case BLOODY_W60_PRO_PID: layout = w60_pro; break; + case BLOODY_W70_MAX_PID: + case BLOODY_W90_MAX_PID: + case BLOODY_W90_PRO_PID: + layout = w90_max; + break; case BLOODY_MP_50RS_PID: layout = mp_50rs; break; @@ -109,7 +130,7 @@ void RGBController_BloodyMouse::SetupZones() zone new_zone; new_zone.name = mz.name; - new_zone.leds_min = mz.zone_leds.size(); + new_zone.leds_min = (unsigned int)mz.zone_leds.size(); new_zone.leds_max = new_zone.leds_min; new_zone.leds_count = new_zone.leds_min; new_zone.type = bool_single ? ZONE_TYPE_SINGLE : ZONE_TYPE_LINEAR; diff --git a/Controllers/A4TechController/BloodyMouseController/RGBController_BloodyMouse.h b/Controllers/A4TechController/BloodyMouseController/RGBController_BloodyMouse.h new file mode 100644 index 00000000..ec7dfa96 --- /dev/null +++ b/Controllers/A4TechController/BloodyMouseController/RGBController_BloodyMouse.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------*\ +| RGBController_BloodyMouse.h | +| | +| RGBController for A4Tech Bloody Mouse | +| | +| Chris M (Dr_No) 30 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "BloodyMouseController.h" + +struct mouse_zone +{ + std::string name; + std::vector zone_leds; +}; + +typedef std::vector mouse_layout; + +class RGBController_BloodyMouse : public RGBController +{ +public: + RGBController_BloodyMouse(BloodyMouseController* controller_ptr); + ~RGBController_BloodyMouse(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + BloodyMouseController* controller; +}; diff --git a/Controllers/A4TechController/RGBController_BloodyMouse.h b/Controllers/A4TechController/RGBController_BloodyMouse.h deleted file mode 100644 index c2ba6005..00000000 --- a/Controllers/A4TechController/RGBController_BloodyMouse.h +++ /dev/null @@ -1,41 +0,0 @@ -/*---------------------------------------------------------------------*\ -| RGBController_BloodyMouse.h | -| | -| Driver for BloodyMouse USB Controller | -| | -| Chris M (Dr_No) 30 Jun 2022 | -| | -\*---------------------------------------------------------------------*/ - -#pragma once -#include -#include "LogManager.h" -#include "RGBController.h" -#include "BloodyMouseController.h" - -struct mouse_zone -{ - std::string name; - std::vector zone_leds; -}; - -typedef std::vector mouse_layout; - -class RGBController_BloodyMouse : public RGBController -{ -public: - RGBController_BloodyMouse(BloodyMouseController* controller_ptr); - ~RGBController_BloodyMouse(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - BloodyMouseController* controller; -}; diff --git a/Controllers/AMBXController/AMBXController.cpp b/Controllers/AMBXController/AMBXController.cpp new file mode 100644 index 00000000..cee18d59 --- /dev/null +++ b/Controllers/AMBXController/AMBXController.cpp @@ -0,0 +1,195 @@ +/*---------------------------------------------------------*\ +| AMBXController.cpp | +| | +| Driver for Philips amBX Gaming lights | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "AMBXController.h" +#include "LogManager.h" +#include "StringUtils.h" +#include +#include +#include + +AMBXController::AMBXController(const char* path) +{ + initialized = false; + usb_context = nullptr; + dev_handle = nullptr; + + location = "USB: "; + location += path; + + // Initialize libusb in this instance + if(libusb_init(&usb_context) < 0) + { + return; + } + + // Get the device list + libusb_device** device_list; + ssize_t device_count = libusb_get_device_list(usb_context, &device_list); + + if(device_count < 0) + { + return; + } + + for(ssize_t i = 0; i < device_count; i++) + { + libusb_device* device = device_list[i]; + struct libusb_device_descriptor desc; + + if(libusb_get_device_descriptor(device, &desc) != LIBUSB_SUCCESS) + { + continue; + } + + if(desc.idVendor == AMBX_VID && desc.idProduct == AMBX_PID) + { + uint8_t bus = libusb_get_bus_number(device); + uint8_t address = libusb_get_device_address(device); + + char current_path[32]; + snprintf(current_path, sizeof(current_path), "%d-%d", bus, address); + + if(strcmp(path, current_path) == 0) + { + // Try to open this device + if(libusb_open(device, &dev_handle) != LIBUSB_SUCCESS) + { + continue; + } + + // Try to detach the kernel driver if attached + if(libusb_kernel_driver_active(dev_handle, 0)) + { + libusb_detach_kernel_driver(dev_handle, 0); + } + + // Set auto-detach for Windows compatibility + libusb_set_auto_detach_kernel_driver(dev_handle, 1); + + // Claim the interface + if(libusb_claim_interface(dev_handle, 0) != LIBUSB_SUCCESS) + { + libusb_close(dev_handle); + dev_handle = nullptr; + continue; + } + + // Get string descriptor for serial number if available + if(desc.iSerialNumber != 0) + { + unsigned char serial_str[256]; + int serial_result = libusb_get_string_descriptor_ascii(dev_handle, desc.iSerialNumber, + serial_str, sizeof(serial_str)); + if(serial_result > 0) + { + serial = std::string(reinterpret_cast(serial_str), serial_result); + } + } + + // Successfully opened and claimed the device + initialized = true; + break; + } + } + } + + libusb_free_device_list(device_list, 1); +} + +AMBXController::~AMBXController() +{ + if(initialized) + { + // Turn off all lights before closing + unsigned int led_ids[5] = + { + AMBX_LIGHT_LEFT, + AMBX_LIGHT_RIGHT, + AMBX_LIGHT_WALL_LEFT, + AMBX_LIGHT_WALL_CENTER, + AMBX_LIGHT_WALL_RIGHT + }; + + RGBColor colors[5] = { 0, 0, 0, 0, 0 }; + SetLEDColors(led_ids, colors, 5); + } + + if(dev_handle != nullptr) + { + // Release the interface + libusb_release_interface(dev_handle, 0); + + // Close the device + libusb_close(dev_handle); + dev_handle = nullptr; + } + + if(usb_context != nullptr) + { + libusb_exit(usb_context); + usb_context = nullptr; + } +} + +std::string AMBXController::GetDeviceLocation() +{ + return location; +} + +std::string AMBXController::GetSerialString() +{ + return serial; +} + +bool AMBXController::IsInitialized() +{ + return initialized; +} + +void AMBXController::SendPacket(unsigned char* packet, unsigned int size) +{ + if(!initialized || dev_handle == nullptr) + { + return; + } + + int actual_length = 0; + libusb_interrupt_transfer(dev_handle, AMBX_ENDPOINT_OUT, packet, size, &actual_length, 100); +} + +void AMBXController::SetLEDColor(unsigned int led, RGBColor color) +{ + if(!initialized) + { + return; + } + + unsigned char color_buf[6] = + { + AMBX_PACKET_HEADER, + static_cast(led), + AMBX_SET_COLOR, + (unsigned char)RGBGetRValue(color), + (unsigned char)RGBGetGValue(color), + (unsigned char)RGBGetBValue(color) + }; + + SendPacket(color_buf, 6); + + std::this_thread::sleep_for(std::chrono::milliseconds(2)); +} + +void AMBXController::SetLEDColors(unsigned int* leds, RGBColor* colors, unsigned int count) +{ + for(unsigned int i = 0; i < count; i++) + { + SetLEDColor(leds[i], colors[i]); + } +} diff --git a/Controllers/AMBXController/AMBXController.h b/Controllers/AMBXController/AMBXController.h new file mode 100644 index 00000000..a5ea914d --- /dev/null +++ b/Controllers/AMBXController/AMBXController.h @@ -0,0 +1,57 @@ +/*---------------------------------------------------------*\ +| AMBXController.h | +| | +| Driver for Philips amBX Gaming lights | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include + +#ifdef _WIN32 +#include "dependencies/libusb-1.0.27/include/libusb.h" +#else +#include +#endif + +#define AMBX_VID 0x0471 +#define AMBX_PID 0x083F +#define AMBX_ENDPOINT_OUT 0x02 +#define AMBX_PACKET_HEADER 0xA1 +#define AMBX_SET_COLOR 0x03 + +enum +{ + AMBX_LIGHT_LEFT = 0x0B, + AMBX_LIGHT_RIGHT = 0x1B, + AMBX_LIGHT_WALL_LEFT = 0x2B, + AMBX_LIGHT_WALL_CENTER = 0x3B, + AMBX_LIGHT_WALL_RIGHT = 0x4B +}; + +class AMBXController +{ +public: + AMBXController(const char* path); + ~AMBXController(); + + std::string GetDeviceLocation(); + std::string GetSerialString(); + + bool IsInitialized(); + void SetLEDColor(unsigned int led, RGBColor color); + void SetLEDColors(unsigned int* leds, RGBColor* colors, unsigned int count); + +private: + libusb_context* usb_context; + libusb_device_handle* dev_handle; + std::string location; + std::string serial; + bool initialized; + + void SendPacket(unsigned char* packet, unsigned int size); +}; diff --git a/Controllers/AMBXController/AMBXControllerDetect.cpp b/Controllers/AMBXController/AMBXControllerDetect.cpp new file mode 100644 index 00000000..cae0f4c3 --- /dev/null +++ b/Controllers/AMBXController/AMBXControllerDetect.cpp @@ -0,0 +1,83 @@ +/*---------------------------------------------------------*\ +| AMBXControllerDetect.cpp | +| | +| Detector for Philips amBX Gaming lights | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "AMBXController.h" +#include "RGBController.h" +#include "RGBController_AMBX.h" + +#ifdef _WIN32 +#include "dependencies/libusb-1.0.27/include/libusb.h" +#else +#include +#endif + +/******************************************************************************************\ +* * +* DetectAMBXControllers * +* * +* Detect Philips amBX Gaming devices * +* * +\******************************************************************************************/ + +void DetectAMBXControllers() +{ + libusb_context* ctx = NULL; + + if(libusb_init(&ctx) < 0) + { + return; + } + + libusb_device** devs; + ssize_t num_devs = libusb_get_device_list(ctx, &devs); + + if(num_devs <= 0) + { + libusb_exit(ctx); + return; + } + + for(ssize_t i = 0; i < num_devs; i++) + { + libusb_device* dev = devs[i]; + libusb_device_descriptor desc; + + if(libusb_get_device_descriptor(dev, &desc) != 0) + { + continue; + } + + if(desc.idVendor == AMBX_VID && desc.idProduct == AMBX_PID) + { + uint8_t bus = libusb_get_bus_number(dev); + uint8_t address = libusb_get_device_address(dev); + char device_path[32]; + snprintf(device_path, sizeof(device_path), "%d-%d", bus, address); + + // Use the AMBXController to handle opening and initializing + AMBXController* controller = new AMBXController(device_path); + + if(controller->IsInitialized()) + { + RGBController_AMBX* rgb_controller = new RGBController_AMBX(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + else + { + delete controller; + } + } + } + + libusb_free_device_list(devs, 1); + libusb_exit(ctx); +} + +REGISTER_DETECTOR("Philips amBX", DetectAMBXControllers); diff --git a/Controllers/AMBXController/RGBController_AMBX.cpp b/Controllers/AMBXController/RGBController_AMBX.cpp new file mode 100644 index 00000000..48edae0c --- /dev/null +++ b/Controllers/AMBXController/RGBController_AMBX.cpp @@ -0,0 +1,179 @@ +/*---------------------------------------------------------*\ +| RGBController_AMBX.cpp | +| | +| RGB Controller for Philips amBX Gaming lights | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_AMBX.h" + +/**------------------------------------------------------------------*\ + @name Philips amBX + @category Accessory + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectAMBXControllers + @comment The Philips amBX Gaming lights system includes left and right + lights and a wall-washer bar with three zones. +\*-------------------------------------------------------------------*/ + +RGBController_AMBX::RGBController_AMBX(AMBXController* controller_ptr) +{ + controller = controller_ptr; + + name = "Philips amBX"; + vendor = "Philips"; + type = DEVICE_TYPE_ACCESSORY; + description = "Philips amBX Gaming Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + 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(); +} + +RGBController_AMBX::~RGBController_AMBX() +{ + delete controller; +} + +void RGBController_AMBX::SetupZones() +{ + // Set up zones + zone side_lights_zone; + side_lights_zone.name = "Side Lights"; + side_lights_zone.type = ZONE_TYPE_LINEAR; + side_lights_zone.leds_min = 2; + side_lights_zone.leds_max = 2; + side_lights_zone.leds_count = 2; + side_lights_zone.matrix_map = NULL; + zones.push_back(side_lights_zone); + + zone wallwasher_zone; + wallwasher_zone.name = "Wallwasher"; + wallwasher_zone.type = ZONE_TYPE_LINEAR; + wallwasher_zone.leds_min = 3; + wallwasher_zone.leds_max = 3; + wallwasher_zone.leds_count = 3; + wallwasher_zone.matrix_map = NULL; + zones.push_back(wallwasher_zone); + + // Set up LEDs + led left_light; + left_light.name = "Left"; + left_light.value = AMBX_LIGHT_LEFT; + leds.push_back(left_light); + + led right_light; + right_light.name = "Right"; + right_light.value = AMBX_LIGHT_RIGHT; + leds.push_back(right_light); + + led wall_left; + wall_left.name = "Wall Left"; + wall_left.value = AMBX_LIGHT_WALL_LEFT; + leds.push_back(wall_left); + + led wall_center; + wall_center.name = "Wall Center"; + wall_center.value = AMBX_LIGHT_WALL_CENTER; + leds.push_back(wall_center); + + led wall_right; + wall_right.name = "Wall Right"; + wall_right.value = AMBX_LIGHT_WALL_RIGHT; + leds.push_back(wall_right); + + SetupColors(); +} + +void RGBController_AMBX::ResizeZone(int /*zone*/, int /*new_size*/) +{ + // This device does not support resizing zones +} + +void RGBController_AMBX::DeviceUpdateLEDs() +{ + if(!controller->IsInitialized()) + { + return; + } + + unsigned int led_values[5]; + RGBColor led_colors[5]; + + for(unsigned int led_idx = 0; led_idx < leds.size(); led_idx++) + { + led_values[led_idx] = leds[led_idx].value; + led_colors[led_idx] = colors[led_idx]; + } + + controller->SetLEDColors(led_values, led_colors, static_cast(leds.size())); +} + +void RGBController_AMBX::UpdateZoneLEDs(int zone) +{ + if(!controller->IsInitialized()) + { + return; + } + + unsigned int start_idx = 0; + unsigned int zone_size = 0; + + // Calculate start index and size + for(unsigned int z_idx = 0; z_idx < zones.size(); z_idx++) + { + if(z_idx == (unsigned int)zone) + { + zone_size = zones[z_idx].leds_count; + break; + } + + start_idx += zones[z_idx].leds_count; + } + + unsigned int led_values[5]; + RGBColor led_colors[5]; + + for(unsigned int led_idx = 0; led_idx < zone_size; led_idx++) + { + unsigned int current_idx = start_idx + led_idx; + led_values[led_idx] = leds[current_idx].value; + led_colors[led_idx] = colors[current_idx]; + } + + controller->SetLEDColors(led_values, led_colors, zone_size); +} + +void RGBController_AMBX::UpdateSingleLED(int led) +{ + if(!controller->IsInitialized()) + { + return; + } + + unsigned int led_value = leds[led].value; + RGBColor color = colors[led]; + controller->SetLEDColor(led_value, color); +} + +void RGBController_AMBX::DeviceUpdateMode() +{ + if(!controller->IsInitialized()) + { + return; + } + + DeviceUpdateLEDs(); +} diff --git a/Controllers/AMBXController/RGBController_AMBX.h b/Controllers/AMBXController/RGBController_AMBX.h new file mode 100644 index 00000000..143f10c9 --- /dev/null +++ b/Controllers/AMBXController/RGBController_AMBX.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------*\ +| RGBController_AMBX.h | +| | +| RGB Controller for Philips amBX Gaming lights | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AMBXController.h" + +class RGBController_AMBX : public RGBController +{ +public: + RGBController_AMBX(AMBXController* controller_ptr); + ~RGBController_AMBX(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + AMBXController* controller; +}; diff --git a/Controllers/AMDWraithPrismController/AMDWraithPrismController.cpp b/Controllers/AMDWraithPrismController/AMDWraithPrismController.cpp index 03c620c4..6108fff1 100644 --- a/Controllers/AMDWraithPrismController/AMDWraithPrismController.cpp +++ b/Controllers/AMDWraithPrismController/AMDWraithPrismController.cpp @@ -1,21 +1,24 @@ -/*-----------------------------------------*\ -| AMDWraithPrismController.h | -| | -| Driver for AMD Wraith Prism RGB lighting | -| controller | -| | -| Adam Honse (CalcProgrammer1) 12/6/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| AMDWraithPrismController.cpp | +| | +| Driver for AMD Wraith Prism | +| | +| Adam Honse (CalcProgrammer1) 06 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "AMDWraithPrismController.h" #include #include #include +#include "AMDWraithPrismController.h" +#include "StringUtils.h" AMDWraithPrismController::AMDWraithPrismController(hid_device* dev_handle, const char* path) { - dev = dev_handle; - location = path; + dev = dev_handle; + location = path; current_fan_mode = AMD_WRAITH_PRISM_FAN_LOGO_MODE_STATIC; current_fan_speed = 0xFF; @@ -53,10 +56,7 @@ std::string AMDWraithPrismController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } std::string AMDWraithPrismController::GetFirmwareVersionString() diff --git a/Controllers/AMDWraithPrismController/AMDWraithPrismController.h b/Controllers/AMDWraithPrismController/AMDWraithPrismController.h index 02008de3..3473bc64 100644 --- a/Controllers/AMDWraithPrismController/AMDWraithPrismController.h +++ b/Controllers/AMDWraithPrismController/AMDWraithPrismController.h @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| AMDWraithPrismController.h | -| | -| Definitions and types for AMD Wraith | -| Prism lighting controller | -| | -| Adam Honse (CalcProgrammer1) 12/6/2019 | -\*-----------------------------------------*/ - -#include -#include - -#include "RGBController.h" +/*---------------------------------------------------------*\ +| AMDWraithPrismController.h | +| | +| Driver for AMD Wraith Prism | +| | +| Adam Honse (CalcProgrammer1) 06 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + #define AMD_WRAITH_PRISM_FAN_BRIGHTNESS_DEFAULT_MAX 0xFF #define AMD_WRAITH_PRISM_FAN_BRIGHTNESS_CYCLE_MAX 0x7F diff --git a/Controllers/AMDWraithPrismController/AMDWraithPrismControllerDetect.cpp b/Controllers/AMDWraithPrismController/AMDWraithPrismControllerDetect.cpp index 3b6d49df..d567e656 100644 --- a/Controllers/AMDWraithPrismController/AMDWraithPrismControllerDetect.cpp +++ b/Controllers/AMDWraithPrismController/AMDWraithPrismControllerDetect.cpp @@ -1,11 +1,28 @@ +/*---------------------------------------------------------*\ +| AMDWraithPrismControllerDetect.cpp | +| | +| Detector for AMD Wraith Prism | +| | +| Adam Honse (CalcProgrammer1) 06 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "AMDWraithPrismController.h" -#include "RGBController.h" #include "RGBController_AMDWraithPrism.h" -#include -#define AMD_WRAITH_PRISM_VID 0x2516 -#define AMD_WRAITH_PRISM_PID 0x0051 +/*---------------------------------------------------------*\ +| AMD Wraith Prism vendor ID | +\*---------------------------------------------------------*/ +#define AMD_WRAITH_PRISM_VID 0x2516 + +/*---------------------------------------------------------*\ +| AMD Wraith Prism product ID | +\*---------------------------------------------------------*/ +#define AMD_WRAITH_PRISM_PID 0x0051 /******************************************************************************************\ * * @@ -18,11 +35,12 @@ void DetectAMDWraithPrismControllers(hid_device_info* info, const std::string&) { hid_device* dev = hid_open_path(info->path); - if( dev ) + + if(dev) { AMDWraithPrismController* controller = new AMDWraithPrismController(dev, info->path); RGBController_AMDWraithPrism* rgb_controller = new RGBController_AMDWraithPrism(controller); - // Constructor sets the name + ResourceManager::get()->RegisterRGBController(rgb_controller); } } diff --git a/Controllers/AMDWraithPrismController/RGBController_AMDWraithPrism.cpp b/Controllers/AMDWraithPrismController/RGBController_AMDWraithPrism.cpp index 1b13f1f7..4830ab20 100644 --- a/Controllers/AMDWraithPrismController/RGBController_AMDWraithPrism.cpp +++ b/Controllers/AMDWraithPrismController/RGBController_AMDWraithPrism.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_AMDWraithPrism.cpp | -| | -| Generic RGB Interface for AMD Wraith | -| Prism | -| | -| Adam Honse (CalcProgrammer1) 12/25/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AMDWraithPrism.cpp | +| | +| RGBController for AMD Wraith Prism | +| | +| Adam Honse (CalcProgrammer1) 25 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_AMDWraithPrism.h" @@ -25,14 +27,14 @@ RGBController_AMDWraithPrism::RGBController_AMDWraithPrism(AMDWraithPrismController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "AMD Wraith Prism"; - vendor = "Cooler Master"; - type = DEVICE_TYPE_COOLER; - description = "AMD Wraith Prism Device"; - version = controller->GetFirmwareVersionString(); - location = controller->GetLocationString(); + name = "AMD Wraith Prism"; + vendor = "Cooler Master"; + type = DEVICE_TYPE_COOLER; + description = "AMD Wraith Prism Device"; + version = controller->GetFirmwareVersionString(); + location = controller->GetLocationString(); mode Direct; Direct.name = "Direct"; @@ -138,8 +140,8 @@ void RGBController_AMDWraithPrism::SetupZones() /*---------------------------------------------------------*\ | LED maps | \*---------------------------------------------------------*/ - const unsigned int logo_leds[1] = { 0x00 }; - const unsigned int fan_leds[1] = { 0x01 }; + const unsigned int logo_leds[1] = { 0x00 }; + const unsigned int fan_leds[1] = { 0x01 }; const unsigned int ring_leds[14] = { 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x10, 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09 }; @@ -179,24 +181,24 @@ void RGBController_AMDWraithPrism::SetupZones() for(unsigned int led_idx = 0; led_idx < 1; led_idx++) { led logo_led; - logo_led.name = "Logo LED"; - logo_led.value = logo_leds[led_idx]; + logo_led.name = "Logo LED"; + logo_led.value = logo_leds[led_idx]; leds.push_back(logo_led); } for(unsigned int led_idx = 0; led_idx < 1; led_idx++) { led fan_led; - fan_led.name = "Fan LED"; - fan_led.value = fan_leds[led_idx]; + fan_led.name = "Fan LED"; + fan_led.value = fan_leds[led_idx]; leds.push_back(fan_led); } for(unsigned int led_idx = 0; led_idx < 14; led_idx++) { led ring_led; - ring_led.name = "Ring LED"; - ring_led.value = ring_leds[led_idx]; + ring_led.name = "Ring LED"; + ring_led.value = ring_leds[led_idx]; leds.push_back(ring_led); } diff --git a/Controllers/AMDWraithPrismController/RGBController_AMDWraithPrism.h b/Controllers/AMDWraithPrismController/RGBController_AMDWraithPrism.h index 3d8d3181..a0d6eb33 100644 --- a/Controllers/AMDWraithPrismController/RGBController_AMDWraithPrism.h +++ b/Controllers/AMDWraithPrismController/RGBController_AMDWraithPrism.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_AMDWraithPrism.h | -| | -| Generic RGB Interface for AMD Wraith | -| Prism | -| | -| Adam Honse (CalcProgrammer1) 12/25/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AMDWraithPrism.h | +| | +| RGBController for AMD Wraith Prism | +| | +| Adam Honse (CalcProgrammer1) 25 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "AMDWraithPrismController.h" diff --git a/Controllers/AOCKeyboardController/AOCKeyboardController.cpp b/Controllers/AOCKeyboardController/AOCKeyboardController.cpp index d81b283d..fa06d204 100644 --- a/Controllers/AOCKeyboardController/AOCKeyboardController.cpp +++ b/Controllers/AOCKeyboardController/AOCKeyboardController.cpp @@ -1,24 +1,27 @@ -/*-----------------------------------------*\ -| AOCKeyboardController.cpp | -| | -| Driver for AOC Keyboard lighting | -| controller | -| | -| Adam Honse (CalcProgrammer1) 5/10/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| AOCKeyboardController.cpp | +| | +| Driver for AOC keyboard | +| | +| Adam Honse (CalcProgrammer1) 10 May 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "AOCKeyboardController.h" - -#include #include +#include #include +#include "AOCKeyboardController.h" +#include "StringUtils.h" using namespace std::chrono_literals; -AOCKeyboardController::AOCKeyboardController(hid_device* dev_handle, const char* path) +AOCKeyboardController::AOCKeyboardController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } AOCKeyboardController::~AOCKeyboardController() @@ -31,6 +34,11 @@ std::string AOCKeyboardController::GetDeviceLocation() return("HID " + location); } +std::string AOCKeyboardController::GetDeviceName() +{ + return(name); +} + std::string AOCKeyboardController::GetSerialString() { wchar_t serial_string[128]; @@ -41,10 +49,7 @@ std::string AOCKeyboardController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void AOCKeyboardController::SetLightingConfig diff --git a/Controllers/AOCKeyboardController/AOCKeyboardController.h b/Controllers/AOCKeyboardController/AOCKeyboardController.h index bc5c349a..6c15b381 100644 --- a/Controllers/AOCKeyboardController/AOCKeyboardController.h +++ b/Controllers/AOCKeyboardController/AOCKeyboardController.h @@ -1,18 +1,20 @@ -/*-----------------------------------------*\ -| AOCKeyboardController.h | -| | -| Definitions and types for AOC keyboard | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 5/10/2023 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include +/*---------------------------------------------------------*\ +| AOCKeyboardController.h | +| | +| Driver for AOC keyboard | +| | +| Adam Honse (CalcProgrammer1) 10 May 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + /*-----------------------------------------*\ | AOC Keyboard Modes | \*-----------------------------------------*/ @@ -62,10 +64,11 @@ enum class AOCKeyboardController { public: - AOCKeyboardController(hid_device* dev_handle, const char* path); + AOCKeyboardController(hid_device* dev_handle, const char* path, std::string dev_name); ~AOCKeyboardController(); std::string GetDeviceLocation(); + std::string GetDeviceName(); std::string GetSerialString(); void SetLightingConfig @@ -86,6 +89,7 @@ public: private: hid_device* dev; std::string location; + std::string name; void SendStartPacket(); void SendEndPacket(); diff --git a/Controllers/AOCKeyboardController/AOCKeyboardControllerDetect.cpp b/Controllers/AOCKeyboardController/AOCKeyboardControllerDetect.cpp index 1b58b760..b7c528f2 100644 --- a/Controllers/AOCKeyboardController/AOCKeyboardControllerDetect.cpp +++ b/Controllers/AOCKeyboardController/AOCKeyboardControllerDetect.cpp @@ -1,13 +1,24 @@ +/*---------------------------------------------------------*\ +| AOCKeyboardControllerDetect.cpp | +| | +| Detector for AOC keyboard | +| | +| Adam Honse (CalcProgrammer1) 10 May 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "AOCKeyboardController.h" -#include "RGBController.h" #include "RGBController_AOCKeyboard.h" /*-----------------------------------------------------*\ -| AOC Mousemat IDs | +| AOC Keyboard IDs | \*-----------------------------------------------------*/ #define AOC_VID 0x3938 #define AOC_GK500_PID 0x1178 +#define AOC_GK500_PID_2 0x1229 /******************************************************************************************\ * * @@ -23,12 +34,12 @@ void DetectAOCKeyboardControllers(hid_device_info* info, const std::string& name if(dev) { - AOCKeyboardController* controller = new AOCKeyboardController(dev, info->path); + AOCKeyboardController* controller = new AOCKeyboardController(dev, info->path, name); RGBController_AOCKeyboard* rgb_controller = new RGBController_AOCKeyboard(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } REGISTER_HID_DETECTOR_PU("AOC GK500", DetectAOCKeyboardControllers, AOC_VID, AOC_GK500_PID, 0xFF19, 0xFF19); +REGISTER_HID_DETECTOR_PU("AOC GK500", DetectAOCKeyboardControllers, AOC_VID, AOC_GK500_PID_2, 0xFF19, 0xFF19); diff --git a/Controllers/AOCKeyboardController/RGBController_AOCKeyboard.cpp b/Controllers/AOCKeyboardController/RGBController_AOCKeyboard.cpp index 88209130..4c5fb201 100644 --- a/Controllers/AOCKeyboardController/RGBController_AOCKeyboard.cpp +++ b/Controllers/AOCKeyboardController/RGBController_AOCKeyboard.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_AOCKeyboard.cpp | -| | -| Generic RGB Interface for AOC keyboard | -| | -| Adam Honse (CalcProgrammer1) 5/10/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AOCKeyboard.cpp | +| | +| RGBController for AOC keyboard | +| | +| Adam Honse (CalcProgrammer1) 10 May 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_AOCKeyboard.h" #include "KeyboardLayoutManager.h" @@ -32,10 +35,10 @@ layout_values aoc_keyboard_offset_values = 75, 76, 91, 62, 48, 64, 50, 65, 66, 67, 97, 68, 84, 70, 59, 74, 89, 58, 73, 88, 103, /* TAB Q W E R T Y U I O P [ ] \ DEL END PGDN NP7 NP8 NP9 NP+ */ 60, 61, 47, 78, 33, 49, 35, 80, 51, 52, 53, 69, 99, 25, 44, 29, 14, 43, 28, 13, 102, - /* CPLK A S D F G H J K L ; " ENTR NP4 NP5 NP6 */ - 45, 46, 32, 93, 18, 34, 20, 95, 36, 37, 38, 54, 10, 57, 72, 87, - /* LSFT Z X C V B N M , . / RSFT ARWU NP1 NP2 NP3 NPEN */ - 30, 31, 17, 2, 3, 19, 5, 6, 21, 22, 23, 39, 11, 42, 27, 12, 101, + /* CPLK A S D F G H J K L ; " # ENTR NP4 NP5 NP6 */ + 45, 46, 32, 93, 18, 34, 20, 95, 36, 37, 38, 54, 0, 10, 57, 72, 87, + /* LSFT \ Z X C V B N M , . / RSFT ARWU NP1 NP2 NP3 NPEN */ + 30, 0, 31, 17, 2, 3, 19, 5, 6, 21, 22, 23, 39, 11, 42, 27, 12, 101, /* LCTL LWIN LALT SPC RALT RFNC RMNU RCTL ARWL ARWD ARWR NP0 NP. */ 15, 0, 1, 4, 7, 8, 24, 9, 26, 41, 56, 71, 86 }, @@ -47,14 +50,14 @@ layout_values aoc_keyboard_offset_values = RGBController_AOCKeyboard::RGBController_AOCKeyboard(AOCKeyboardController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "AOC Keyboard Device"; - vendor = "AOC"; - type = DEVICE_TYPE_KEYBOARD; - description = "AOC Keyboard Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetDeviceName(); + vendor = "AOC"; + type = DEVICE_TYPE_KEYBOARD; + description = "AOC Keyboard Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Static; Static.name = "Static"; @@ -288,7 +291,7 @@ void RGBController_AOCKeyboard::SetupZones() | Create LEDs for the Matrix zone | | Place keys in the layout to populate the matrix | \*---------------------------------------------------------*/ - for(size_t led_idx = 0; led_idx < new_zone.leds_count; led_idx++) + for(unsigned int led_idx = 0; led_idx < new_zone.leds_count; led_idx++) { led new_led; @@ -299,8 +302,6 @@ void RGBController_AOCKeyboard::SetupZones() zones.push_back(new_zone); - - SetupColors(); } diff --git a/Controllers/AOCKeyboardController/RGBController_AOCKeyboard.h b/Controllers/AOCKeyboardController/RGBController_AOCKeyboard.h index 61a08f2d..61ae9653 100644 --- a/Controllers/AOCKeyboardController/RGBController_AOCKeyboard.h +++ b/Controllers/AOCKeyboardController/RGBController_AOCKeyboard.h @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_AOCKeyboard.h | -| | -| Generic RGB Interface for AOC keyboard | -| | -| Adam Honse (CalcProgrammer1) 5/10/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AOCKeyboard.h | +| | +| RGBController for AOC keyboard | +| | +| Adam Honse (CalcProgrammer1) 10 May 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/AOCMouseController/AOCMouseController.cpp b/Controllers/AOCMouseController/AOCMouseController.cpp index 4d5f5c11..f6c6175c 100644 --- a/Controllers/AOCMouseController/AOCMouseController.cpp +++ b/Controllers/AOCMouseController/AOCMouseController.cpp @@ -1,19 +1,23 @@ -/*-----------------------------------------*\ -| AOCMouseController.cpp | -| | -| Driver for AOC Mouse lighting controller | -| | -| Adam Honse (CalcProgrammer1) 4/20/2023 | -\*-----------------------------------------*/ - -#include "AOCMouseController.h" +/*---------------------------------------------------------*\ +| AOCMouseController.cpp | +| | +| Driver for AOC mouse | +| | +| Adam Honse (CalcProgrammer1) 20 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "AOCMouseController.h" +#include "StringUtils.h" -AOCMouseController::AOCMouseController(hid_device* dev_handle, const char* path) +AOCMouseController::AOCMouseController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } AOCMouseController::~AOCMouseController() @@ -26,6 +30,11 @@ std::string AOCMouseController::GetDeviceLocation() return("HID " + location); } +std::string AOCMouseController::GetDeviceName() +{ + return(name); +} + std::string AOCMouseController::GetSerialString() { wchar_t serial_string[128]; @@ -36,10 +45,7 @@ std::string AOCMouseController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } /*-------------------------------------------------------------------------------------------------*\ diff --git a/Controllers/AOCMouseController/AOCMouseController.h b/Controllers/AOCMouseController/AOCMouseController.h index 2683ea07..81454c12 100644 --- a/Controllers/AOCMouseController/AOCMouseController.h +++ b/Controllers/AOCMouseController/AOCMouseController.h @@ -1,18 +1,20 @@ -/*-----------------------------------------*\ -| AOCMouseController.h | -| | -| Definitions and types for AOC mouse | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 4/20/2023 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include +/*---------------------------------------------------------*\ +| AOCMouseController.h | +| | +| Driver for AOC mouse | +| | +| Adam Honse (CalcProgrammer1) 20 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + /*-----------------------------------------*\ | AOC Mousemat Modes | | Note: The 0x80 bit is the random flag | @@ -54,10 +56,11 @@ enum class AOCMouseController { public: - AOCMouseController(hid_device* dev_handle, const char* path); + AOCMouseController(hid_device* dev_handle, const char* path, std::string dev_name); ~AOCMouseController(); std::string GetDeviceLocation(); + std::string GetDeviceName(); std::string GetSerialString(); void SendDirect @@ -77,4 +80,5 @@ public: private: hid_device* dev; std::string location; + std::string name; }; diff --git a/Controllers/AOCMouseController/AOCMouseControllerDetect.cpp b/Controllers/AOCMouseController/AOCMouseControllerDetect.cpp index d07c15f2..974209f9 100644 --- a/Controllers/AOCMouseController/AOCMouseControllerDetect.cpp +++ b/Controllers/AOCMouseController/AOCMouseControllerDetect.cpp @@ -1,10 +1,20 @@ +/*---------------------------------------------------------*\ +| AOCMouseControllerDetect.cpp | +| | +| Detector for AOC mouse | +| | +| Adam Honse (CalcProgrammer1) 20 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "AOCMouseController.h" -#include "RGBController.h" #include "RGBController_AOCMouse.h" /*-----------------------------------------------------*\ -| AOC Mousemat IDs | +| AOC Mouse IDs | \*-----------------------------------------------------*/ #define AOC_VID 0x3938 #define AOC_GM500_PID 0x1179 @@ -23,9 +33,8 @@ void DetectAOCMouseControllers(hid_device_info* info, const std::string& name) if(dev) { - AOCMouseController* controller = new AOCMouseController(dev, info->path); + AOCMouseController* controller = new AOCMouseController(dev, info->path, name); RGBController_AOCMouse* rgb_controller = new RGBController_AOCMouse(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } diff --git a/Controllers/AOCMouseController/RGBController_AOCMouse.cpp b/Controllers/AOCMouseController/RGBController_AOCMouse.cpp index d15cddb0..d7caa317 100644 --- a/Controllers/AOCMouseController/RGBController_AOCMouse.cpp +++ b/Controllers/AOCMouseController/RGBController_AOCMouse.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_AOCMouse.cpp | -| | -| Generic RGB Interface for AOC mouse | -| | -| Adam Honse (CalcProgrammer1) 4/20/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AOCMouse.cpp | +| | +| RGBController for AOC mouse | +| | +| Adam Honse (CalcProgrammer1) 20 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_AOCMouse.h" @@ -21,14 +24,14 @@ RGBController_AOCMouse::RGBController_AOCMouse(AOCMouseController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "AOC Mouse Device"; - vendor = "AOC"; - type = DEVICE_TYPE_MOUSE; - description = "AOC Mouse Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetDeviceName(); + vendor = "AOC"; + type = DEVICE_TYPE_MOUSE; + description = "AOC Mouse Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; Direct.name = "Direct"; diff --git a/Controllers/AOCMouseController/RGBController_AOCMouse.h b/Controllers/AOCMouseController/RGBController_AOCMouse.h index 3193d31d..b4c0c76e 100644 --- a/Controllers/AOCMouseController/RGBController_AOCMouse.h +++ b/Controllers/AOCMouseController/RGBController_AOCMouse.h @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_AOCMouse.h | -| | -| Generic RGB Interface for AOC mouse | -| | -| Adam Honse (CalcProgrammer1) 4/20/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AOCMouse.h | +| | +| RGBController for AOC mouse | +| | +| Adam Honse (CalcProgrammer1) 20 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/AOCMousematController/AOCMousematController.cpp b/Controllers/AOCMousematController/AOCMousematController.cpp index df085604..897af8f8 100644 --- a/Controllers/AOCMousematController/AOCMousematController.cpp +++ b/Controllers/AOCMousematController/AOCMousematController.cpp @@ -1,20 +1,23 @@ -/*-----------------------------------------*\ -| AOCMousematController.cpp | -| | -| Driver for AOC Mousemat lighting | -| controller | -| | -| Adam Honse (CalcProgrammer1) 4/15/2023 | -\*-----------------------------------------*/ - -#include "AOCMousematController.h" +/*---------------------------------------------------------*\ +| AOCMousematController.cpp | +| | +| Driver for AOC mousemat | +| | +| Adam Honse (CalcProgrammer1) 15 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "AOCMousematController.h" +#include "StringUtils.h" -AOCMousematController::AOCMousematController(hid_device* dev_handle, const char* path) +AOCMousematController::AOCMousematController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } AOCMousematController::~AOCMousematController() @@ -27,6 +30,11 @@ std::string AOCMousematController::GetDeviceLocation() return("HID " + location); } +std::string AOCMousematController::GetDeviceName() +{ + return(name); +} + std::string AOCMousematController::GetSerialString() { wchar_t serial_string[128]; @@ -37,10 +45,7 @@ std::string AOCMousematController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } /*-------------------------------------------------------------------------------------------------*\ diff --git a/Controllers/AOCMousematController/AOCMousematController.h b/Controllers/AOCMousematController/AOCMousematController.h index 77371a54..413a9569 100644 --- a/Controllers/AOCMousematController/AOCMousematController.h +++ b/Controllers/AOCMousematController/AOCMousematController.h @@ -1,18 +1,20 @@ -/*-----------------------------------------*\ -| AOCMousematController.h | -| | -| Definitions and types for AOC mousemat | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 4/15/2023 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include +/*---------------------------------------------------------*\ +| AOCMousematController.h | +| | +| Driver for AOC mousemat | +| | +| Adam Honse (CalcProgrammer1) 15 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + /*-----------------------------------------*\ | AOC Mousemat Modes | | Note: The 0x80 bit is the random flag | @@ -53,10 +55,11 @@ enum class AOCMousematController { public: - AOCMousematController(hid_device* dev_handle, const char* path); + AOCMousematController(hid_device* dev_handle, const char* path, std::string dev_name); ~AOCMousematController(); std::string GetDeviceLocation(); + std::string GetDeviceName(); std::string GetSerialString(); void SendDirect @@ -76,4 +79,5 @@ public: private: hid_device* dev; std::string location; + std::string name; }; diff --git a/Controllers/AOCMousematController/AOCMousematControllerDetect.cpp b/Controllers/AOCMousematController/AOCMousematControllerDetect.cpp index 8fbfaf04..1d0cc0d0 100644 --- a/Controllers/AOCMousematController/AOCMousematControllerDetect.cpp +++ b/Controllers/AOCMousematController/AOCMousematControllerDetect.cpp @@ -1,6 +1,16 @@ +/*---------------------------------------------------------*\ +| AOCMousematControllerDetect.cpp | +| | +| Detector for AOC mousemat | +| | +| Adam Honse (CalcProgrammer1) 15 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "AOCMousematController.h" -#include "RGBController.h" #include "RGBController_AOCMousemat.h" /*-----------------------------------------------------*\ @@ -23,12 +33,11 @@ void DetectAOCMousematControllers(hid_device_info* info, const std::string& name if(dev) { - AOCMousematController* controller = new AOCMousematController(dev, info->path); + AOCMousematController* controller = new AOCMousematController(dev, info->path, name); RGBController_AOCMousemat* rgb_controller = new RGBController_AOCMousemat(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } -REGISTER_HID_DETECTOR_IPU("AOC AGON AMM700", DetectAOCMousematControllers, AOC_VID, AOC_AMM700_PID, 1, 0xFF19, 0xFF19); \ No newline at end of file +REGISTER_HID_DETECTOR_IPU("AOC AGON AMM700", DetectAOCMousematControllers, AOC_VID, AOC_AMM700_PID, 1, 0xFF19, 0xFF19); diff --git a/Controllers/AOCMousematController/RGBController_AOCMousemat.cpp b/Controllers/AOCMousematController/RGBController_AOCMousemat.cpp index 92395c7e..b70ec0ae 100644 --- a/Controllers/AOCMousematController/RGBController_AOCMousemat.cpp +++ b/Controllers/AOCMousematController/RGBController_AOCMousemat.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_AOCMousemat.cpp | -| | -| Generic RGB Interface for AOC mousemat | -| | -| Adam Honse (CalcProgrammer1) 4/15/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AOCMousemat.cpp | +| | +| RGBController for AOC mousemat | +| | +| Adam Honse (CalcProgrammer1) 15 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_AOCMousemat.h" @@ -21,14 +24,14 @@ RGBController_AOCMousemat::RGBController_AOCMousemat(AOCMousematController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "AOC Mousemat Device"; - vendor = "AOC"; - type = DEVICE_TYPE_MOUSEMAT; - description = "AOC Mousemat Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetDeviceName(); + vendor = "AOC"; + type = DEVICE_TYPE_MOUSEMAT; + description = "AOC Mousemat Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; Direct.name = "Direct"; diff --git a/Controllers/AOCMousematController/RGBController_AOCMousemat.h b/Controllers/AOCMousematController/RGBController_AOCMousemat.h index 768f433f..05d2c5c6 100644 --- a/Controllers/AOCMousematController/RGBController_AOCMousemat.h +++ b/Controllers/AOCMousematController/RGBController_AOCMousemat.h @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_AOCMousemat.h | -| | -| Generic RGB Interface for AOC mousemat | -| | -| Adam Honse (CalcProgrammer1) 4/15/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AOCMousemat.h | +| | +| RGBController for AOC mousemat | +| | +| Adam Honse (CalcProgrammer1) 15 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/ASRockPolychromeUSBController/ASRockPolychromeUSBController.cpp b/Controllers/ASRockPolychromeUSBController/ASRockPolychromeUSBController.cpp index 77505772..2294b307 100755 --- a/Controllers/ASRockPolychromeUSBController/ASRockPolychromeUSBController.cpp +++ b/Controllers/ASRockPolychromeUSBController/ASRockPolychromeUSBController.cpp @@ -1,19 +1,22 @@ -/*-----------------------------------------*\ -| ASRockPolychromeUSBController.cpp | -| | -| Driver for ASRock Polychrome USB | -| lighting controller | -| | -| Ed Kambulow (dredvard) 12/20/2020 | -| Shady Nawara (ShadyNawara) 01/16/2023 | -\*-----------------------------------------*/ -#include -#include +/*---------------------------------------------------------*\ +| ASRockPolychromeUSBController.cpp | +| | +| Driver for ASRock Polychrome USB motherboards | +| | +| Ed Kambulow (dredvard) 20 Dec 2020 | +| Shady Nawara (ShadyNawara) 16 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include "RGBController.h" #include "ResourceManager.h" +#include "SettingsManager.h" +#include "StringUtils.h" #include "ASRockPolychromeUSBController.h" -#include "dependencies/dmiinfo.h" +#include "dmiinfo.h" #define POLYCHROME_USB_READ_ZONE_CONFIG 0x11 #define POLYCHROME_USB_READ_HEADER 0x14 @@ -54,7 +57,7 @@ PolychromeUSBController::~PolychromeUSBController() unsigned int PolychromeUSBController::GetChannelCount() { - return(device_info.size()); + return((unsigned int)device_info.size()); } std::string PolychromeUSBController::GetDeviceLocation() @@ -77,10 +80,7 @@ std::string PolychromeUSBController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void PolychromeUSBController::SetDeviceInfo() @@ -380,7 +380,7 @@ void PolychromeUSBController::WriteRGSwap bool chnl8 ) { - unsigned char rgconfig[1] = {static_cast(((chnl8 << 7) | (pcb << 6) | (io << 5) | (pch << 4) | (ahdr1 << 3) | (ahdr0 << 2) | (hdr1 << 1) | hdr0))}; + unsigned char rgconfig[1] = {static_cast((((unsigned char)chnl8 << 7) | ((unsigned char)pcb << 6) | ((unsigned char)io << 5) | ((unsigned char)pch << 4) | ((unsigned char)ahdr1 << 3) | ((unsigned char)ahdr0 << 2) | ((unsigned char)hdr1 << 1) | (unsigned char)hdr0))}; WriteHeader(POLYCHROME_USB_RGSWAP_CFG, rgconfig, 1); } diff --git a/Controllers/ASRockPolychromeUSBController/ASRockPolychromeUSBController.h b/Controllers/ASRockPolychromeUSBController/ASRockPolychromeUSBController.h index 4c801de7..7c62547c 100755 --- a/Controllers/ASRockPolychromeUSBController/ASRockPolychromeUSBController.h +++ b/Controllers/ASRockPolychromeUSBController/ASRockPolychromeUSBController.h @@ -1,19 +1,21 @@ -/*-----------------------------------------*\ -| ASRockPolychromeUSBController.h | -| | -| Driver for ASRock Polychrome USB | -| lighting controller | -| | -| Ed Kambulow (dredvard) 12/20/2020 | -| Shady Nawara (ShadyNawara) 01/16/2023 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include +/*---------------------------------------------------------*\ +| ASRockPolychromeUSBController.h | +| | +| Driver for ASRock Polychrome USB motherboards | +| | +| Ed Kambulow (dredvard) 20 Dec 2020 | +| Shady Nawara (ShadyNawara) 16 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + /*----------------------------------------------------------------------------------------------*\ | Definitions for Polychrome USB | \*----------------------------------------------------------------------------------------------*/ @@ -154,12 +156,11 @@ protected: ); private: - unsigned int led_count; std::string device_name; unsigned char configtable[12]; bool rgswapconfig[8] = { 0 }; - void SetDeviceInfo(); + void SetDeviceInfo(); void ReadConfigTables(); void Commit(); }; diff --git a/Controllers/ASRockPolychromeUSBController/ASRockPolychromeUSBControllerDetect.cpp b/Controllers/ASRockPolychromeUSBController/ASRockPolychromeUSBControllerDetect.cpp index e3a32f1e..d0ff835f 100644 --- a/Controllers/ASRockPolychromeUSBController/ASRockPolychromeUSBControllerDetect.cpp +++ b/Controllers/ASRockPolychromeUSBController/ASRockPolychromeUSBControllerDetect.cpp @@ -1,13 +1,19 @@ +/*---------------------------------------------------------*\ +| ASRockPolychromeUSBControllerDetect.cpp | +| | +| Detector for ASRock Polychrome USB motherboards | +| | +| Ed Kambulow (dredvard) 20 Dec 2020 | +| Shady Nawara (ShadyNawara) 16 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "ASRockPolychromeUSBController.h" -#include "RGBController.h" #include "RGBController_ASRockPolychromeUSB.h" -#include "i2c_smbus.h" -#include "pci_ids.h" -#include -#include -#include -#include /*---------------------------------------------------------*\ | ASRock vendor ID | @@ -32,5 +38,5 @@ void DetectPolychromeUSBControllers(hid_device_info* info, const std::string& /* } } -REGISTER_HID_DETECTOR("ASRock Polychrome USB", DetectPolychromeUSBControllers, ASROCK_VID, ASROCK_MOTHERBOARD_1_PID); -REGISTER_HID_DETECTOR("ASRock Deskmini Addressable LED Strip", DetectPolychromeUSBControllers, ASROCK_VID, ASROCK_DESKMINI_ADDRESSABLE_LED_STRIP_PID); +REGISTER_HID_DETECTOR("ASRock Polychrome USB", DetectPolychromeUSBControllers, ASROCK_VID, ASROCK_MOTHERBOARD_1_PID); +REGISTER_HID_DETECTOR("ASRock Deskmini Addressable LED Strip", DetectPolychromeUSBControllers, ASROCK_VID, ASROCK_DESKMINI_ADDRESSABLE_LED_STRIP_PID); diff --git a/Controllers/ASRockPolychromeUSBController/RGBController_ASRockPolychromeUSB.cpp b/Controllers/ASRockPolychromeUSBController/RGBController_ASRockPolychromeUSB.cpp index 71fe9620..5d10dc46 100755 --- a/Controllers/ASRockPolychromeUSBController/RGBController_ASRockPolychromeUSB.cpp +++ b/Controllers/ASRockPolychromeUSBController/RGBController_ASRockPolychromeUSB.cpp @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_ASRockPolychromeUSB.cpp | -| | -| Generic RGB Interface for OpenRGB | -| ASRock Polychrome USB Driver | -| | -| Ed Kambulow (Dredvard) 12/26/2020 | -| Shady Nawara (ShadyNawara) 01/16/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ASRockPolychromeUSB.cpp | +| | +| RGBController for ASRock Polychrome USB motherboards | +| | +| Ed Kambulow (dredvard) 20 Dec 2020 | +| Shady Nawara (ShadyNawara) 16 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_ASRockPolychromeUSB.h" #include +#include "RGBController_ASRockPolychromeUSB.h" #define ASROCK_USB_MAX_ZONES 8 #define ASROCK_ADDRESSABLE_MAX_LEDS 100 @@ -293,7 +295,7 @@ void RGBController_PolychromeUSB::DeviceUpdateLEDs() set_mode = active_mode; } - controller->WriteZone(zone_idx, set_mode, zones_info[zone_idx].speed, zones[zone_idx].colors[0], false); + controller->WriteZone((unsigned char)zone_idx, set_mode, zones_info[zone_idx].speed, zones[zone_idx].colors[0], false); } } diff --git a/Controllers/ASRockPolychromeUSBController/RGBController_ASRockPolychromeUSB.h b/Controllers/ASRockPolychromeUSBController/RGBController_ASRockPolychromeUSB.h index d5cfa90d..06fb13c2 100755 --- a/Controllers/ASRockPolychromeUSBController/RGBController_ASRockPolychromeUSB.h +++ b/Controllers/ASRockPolychromeUSBController/RGBController_ASRockPolychromeUSB.h @@ -1,12 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_ASRockPolychromeUSB.h | -| | -| Generic RGB Interface for OpenRGB | -| ASRock Polychrome USB Driver | -| | -| Ed Kambulow (Dredvard) 12/26/2020 | -| Shady Nawara (ShadyNawara) 01/16/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ASRockPolychromeUSB.h | +| | +| RGBController for ASRock Polychrome USB motherboards | +| | +| Ed Kambulow (dredvard) 20 Dec 2020 | +| Shady Nawara (ShadyNawara) 16 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once @@ -29,7 +31,6 @@ public: void DeviceUpdateMode(); private: - bool initializedMode; PolychromeUSBController* controller; std::vector zones_info; diff --git a/Controllers/ASRockSMBusController/ASRockASRRGBSMBusController.cpp b/Controllers/ASRockSMBusController/ASRockASRRGBSMBusController/ASRockASRRGBSMBusController.cpp similarity index 84% rename from Controllers/ASRockSMBusController/ASRockASRRGBSMBusController.cpp rename to Controllers/ASRockSMBusController/ASRockASRRGBSMBusController/ASRockASRRGBSMBusController.cpp index 312496d9..52f44e87 100644 --- a/Controllers/ASRockSMBusController/ASRockASRRGBSMBusController.cpp +++ b/Controllers/ASRockSMBusController/ASRockASRRGBSMBusController/ASRockASRRGBSMBusController.cpp @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| ASRockPolychromeSMBusController.cpp | -| | -| Driver for for ASRock ASR LED and | -| Polychrome RGB lighting controller | -| | -| Adam Honse (CalcProgrammer1) 12/14/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| ASRockASRRGBSMBusController.cpp | +| | +| Driver for SMBus ASRock ASR RGB motherboards | +| | +| Adam Honse (CalcProgrammer1) 14 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "ASRockASRRGBSMBusController.h" #include -#include "dependencies/dmiinfo.h" +#include "dmiinfo.h" #include "LogManager.h" #define ASROCK_ZONE_LED_COUNT_MESSAGE_EN "[%s] Zone %i LED count: %02d" @@ -64,7 +66,7 @@ void ASRockASRRGBSMBusController::SetColorsAndSpeed(uint8_t led, uint8_t red, ui { uint8_t color_speed_pkt[4] = { red, green, blue, active_speed }; uint8_t select_led_pkt[1] = { led }; - + /*-----------------------------------------------------*\ | Select LED | \*-----------------------------------------------------*/ diff --git a/Controllers/ASRockSMBusController/ASRockASRRGBSMBusController.h b/Controllers/ASRockSMBusController/ASRockASRRGBSMBusController/ASRockASRRGBSMBusController.h similarity index 83% rename from Controllers/ASRockSMBusController/ASRockASRRGBSMBusController.h rename to Controllers/ASRockSMBusController/ASRockASRRGBSMBusController/ASRockASRRGBSMBusController.h index 3362ce5b..da573d6b 100644 --- a/Controllers/ASRockSMBusController/ASRockASRRGBSMBusController.h +++ b/Controllers/ASRockSMBusController/ASRockASRRGBSMBusController/ASRockASRRGBSMBusController.h @@ -1,18 +1,19 @@ -/*-----------------------------------------*\ -| ASRockASRRGBSMBusController.h | -| | -| Definitions and types for ASRock | -| ASR LED and Polychrome RGB lighting | -| controller | -| | -| Adam Honse (CalcProgrammer1) 12/13/2019 | -\*-----------------------------------------*/ - -#include "i2c_smbus.h" -#include +/*---------------------------------------------------------*\ +| ASRockASRRGBSMBusController.h | +| | +| Driver for SMBus ASRock ASR RGB motherboards | +| | +| Adam Honse (CalcProgrammer1) 13 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include "i2c_smbus.h" + typedef uint8_t polychrome_dev_id; #define ASROCK_ASR_CONTROLLER_NAME "ASRock ASR RGB SMBus Controller" @@ -63,7 +64,7 @@ public: uint8_t GetMode(); void SetColorsAndSpeed(uint8_t led, uint8_t red, uint8_t green, uint8_t blue); void SetMode(uint8_t zone, uint8_t mode, uint8_t speed); - + uint16_t fw_version; private: diff --git a/Controllers/ASRockSMBusController/RGBController_ASRockASRRGBSMBus.cpp b/Controllers/ASRockSMBusController/ASRockASRRGBSMBusController/RGBController_ASRockASRRGBSMBus.cpp similarity index 91% rename from Controllers/ASRockSMBusController/RGBController_ASRockASRRGBSMBus.cpp rename to Controllers/ASRockSMBusController/ASRockASRRGBSMBusController/RGBController_ASRockASRRGBSMBus.cpp index f662ee62..46d23b45 100644 --- a/Controllers/ASRockSMBusController/RGBController_ASRockASRRGBSMBus.cpp +++ b/Controllers/ASRockSMBusController/ASRockASRRGBSMBusController/RGBController_ASRockASRRGBSMBus.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_ASRockPolychromeSMBus.cpp | -| | -| Generic RGB Interface for OpenRGB | -| ASRock ASR LED and Polychrome RGB Driver | -| | -| Adam Honse (CalcProgrammer1) 12/15/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ASRRGBSMBus.cpp | +| | +| RGBController for SMBus ASRock ASR LED motherboards | +| | +| Adam Honse (CalcProgrammer1) 15 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_ASRockASRRGBSMBus.h" @@ -167,7 +169,7 @@ void RGBController_ASRockASRRGBSMBus::ResizeZone(int /*zone*/, int /*new_size*/) void RGBController_ASRockASRRGBSMBus::DeviceUpdateLEDs() { - for (std::size_t led = 0; led < colors.size(); led++) + for(unsigned int led = 0; led < colors.size(); led++) { UpdateSingleLED(led); } diff --git a/Controllers/ASRockSMBusController/ASRockASRRGBSMBusController/RGBController_ASRockASRRGBSMBus.h b/Controllers/ASRockSMBusController/ASRockASRRGBSMBusController/RGBController_ASRockASRRGBSMBus.h new file mode 100644 index 00000000..d8eae7ce --- /dev/null +++ b/Controllers/ASRockSMBusController/ASRockASRRGBSMBusController/RGBController_ASRockASRRGBSMBus.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_ASRRGBSMBus.h | +| | +| RGBController for SMBus ASRock ASR RGB motherboards | +| | +| Adam Honse (CalcProgrammer1) 15 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "ASRockASRRGBSMBusController.h" + +class RGBController_ASRockASRRGBSMBus : public RGBController +{ +public: + RGBController_ASRockASRRGBSMBus(ASRockASRRGBSMBusController* controller_ptr); + ~RGBController_ASRockASRRGBSMBus(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + ASRockASRRGBSMBusController* controller; +}; diff --git a/Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController.cpp b/Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController/ASRockPolychromeV1SMBusController.cpp similarity index 95% rename from Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController.cpp rename to Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController/ASRockPolychromeV1SMBusController.cpp index 7679d162..a1b84a8e 100644 --- a/Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController.cpp +++ b/Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController/ASRockPolychromeV1SMBusController.cpp @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| ASRockPolychromeV1SMBusController.cpp | -| | -| Driver for for ASRock ASR LED and | -| Polychrome RGB lighting controller | -| | -| Adam Honse (CalcProgrammer1) 12/14/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| ASRockPolychromeV1SMBusController.cpp | +| | +| Driver for SMBus ASRock Polychrome V1 motherboards | +| | +| Adam Honse (CalcProgrammer1) 14 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "ASRockPolychromeV1SMBusController.h" #include -#include "dependencies/dmiinfo.h" +#include "ASRockPolychromeV1SMBusController.h" +#include "dmiinfo.h" #include "LogManager.h" #define ASROCK_ZONE_LED_COUNT_MESSAGE_EN "[%s] Zone %i LED count: %02d" diff --git a/Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController.h b/Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController/ASRockPolychromeV1SMBusController.h similarity index 94% rename from Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController.h rename to Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController/ASRockPolychromeV1SMBusController.h index fa61ed58..bcde19e3 100644 --- a/Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController.h +++ b/Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController/ASRockPolychromeV1SMBusController.h @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| ASRockPolychromeV1SMBusController.h | -| | -| Definitions and types for ASRock | -| ASR LED and Polychrome RGB lighting | -| controller | -| | -| Adam Honse (CalcProgrammer1) 12/13/2019 | -\*-----------------------------------------*/ - -#include "i2c_smbus.h" -#include "RGBController.h" -#include +/*---------------------------------------------------------*\ +| ASRockPolychromeV1SMBusController.h | +| | +| Driver for SMBus ASRock Polychrome V1 motherboards | +| | +| Adam Honse (CalcProgrammer1) 13 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include "i2c_smbus.h" +#include "RGBController.h" + typedef uint8_t polychrome_dev_id; #define ASROCK_V1_CONTROLLER_NAME "ASRock Polychrome v1 SMBus Controller" diff --git a/Controllers/ASRockSMBusController/RGBController_ASRockPolychromeV1SMBus.cpp b/Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController/RGBController_ASRockPolychromeV1SMBus.cpp similarity index 95% rename from Controllers/ASRockSMBusController/RGBController_ASRockPolychromeV1SMBus.cpp rename to Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController/RGBController_ASRockPolychromeV1SMBus.cpp index 6faff3ca..400cad75 100644 --- a/Controllers/ASRockSMBusController/RGBController_ASRockPolychromeV1SMBus.cpp +++ b/Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController/RGBController_ASRockPolychromeV1SMBus.cpp @@ -1,11 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_ASRockPolychromeSMBus.cpp | -| | -| Generic RGB Interface for OpenRGB | -| ASRock ASR LED and Polychrome RGB Driver | -| | -| Adam Honse (CalcProgrammer1) 12/15/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ASRockPolychromeV1SMBus.cpp | +| | +| RGBController for SMBus ASRock Polychrome V1 | +| motherboards | +| | +| Adam Honse (CalcProgrammer1) 15 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "LogManager.h" #include "RGBController_ASRockPolychromeV1SMBus.h" diff --git a/Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController/RGBController_ASRockPolychromeV1SMBus.h b/Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController/RGBController_ASRockPolychromeV1SMBus.h new file mode 100644 index 00000000..8ba1728d --- /dev/null +++ b/Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController/RGBController_ASRockPolychromeV1SMBus.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------*\ +| RGBController_ASRockPolychromeV1SMBus.h | +| | +| RGBController for SMBus ASRock Polychrome V1 | +| motherboards | +| | +| Adam Honse (CalcProgrammer1) 15 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "ASRockPolychromeV1SMBusController.h" + +class RGBController_ASRockPolychromeV1SMBus : public RGBController +{ +public: + RGBController_ASRockPolychromeV1SMBus(ASRockPolychromeV1SMBusController* controller_ptr); + ~RGBController_ASRockPolychromeV1SMBus(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + ASRockPolychromeV1SMBusController* controller; + uint8_t getModeIndex(uint8_t mode_value); + std::vector zoneIndexMap; +}; diff --git a/Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController.cpp b/Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController/ASRockPolychromeV2SMBusController.cpp similarity index 90% rename from Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController.cpp rename to Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController/ASRockPolychromeV2SMBusController.cpp index 7cc9f406..829a0d1d 100644 --- a/Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController.cpp +++ b/Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController/ASRockPolychromeV2SMBusController.cpp @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| ASRockPolychromeV2SMBusController.cpp | -| | -| Driver for for ASRock ASR LED and | -| Polychrome RGB lighting controller | -| | -| Adam Honse (CalcProgrammer1) 12/14/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| ASRockPolychromeV2SMBusController.cpp | +| | +| Driver for SMBus ASRock Polychrome V2 motherboards | +| | +| Adam Honse (CalcProgrammer1) 14 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "ASRockPolychromeV2SMBusController.h" #include -#include "dependencies/dmiinfo.h" +#include "ASRockPolychromeV2SMBusController.h" +#include "dmiinfo.h" #include "LogManager.h" #define ASROCK_ZONE_LED_COUNT_MESSAGE_EN "[%s] Zone %i LED count: %02d" diff --git a/Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController.h b/Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController/ASRockPolychromeV2SMBusController.h similarity index 93% rename from Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController.h rename to Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController/ASRockPolychromeV2SMBusController.h index 7a27723c..dd356996 100644 --- a/Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController.h +++ b/Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController/ASRockPolychromeV2SMBusController.h @@ -1,18 +1,19 @@ -/*-----------------------------------------*\ -| ASRockPolychromeSMBusController.h | -| | -| Definitions and types for ASRock | -| ASR LED and Polychrome RGB lighting | -| controller | -| | -| Adam Honse (CalcProgrammer1) 12/13/2019 | -\*-----------------------------------------*/ - -#include "i2c_smbus.h" -#include +/*---------------------------------------------------------*\ +| ASRockPolychromeV2SMBusController.h | +| | +| Driver for SMBus ASRock Polychrome V2 motherboards | +| | +| Adam Honse (CalcProgrammer1) 13 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include "i2c_smbus.h" + typedef uint8_t polychrome_dev_id; #define ASROCK_V2_CONTROLLER_NAME "ASRock Polychrome v2 SMBus Controller" @@ -132,7 +133,7 @@ public: uint8_t zone_led_count[6]; uint16_t fw_version; - + private: std::string device_name; uint8_t active_zone; diff --git a/Controllers/ASRockSMBusController/RGBController_ASRockPolychromeV2SMBus.cpp b/Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController/RGBController_ASRockPolychromeV2SMBus.cpp similarity index 94% rename from Controllers/ASRockSMBusController/RGBController_ASRockPolychromeV2SMBus.cpp rename to Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController/RGBController_ASRockPolychromeV2SMBus.cpp index 0693e026..37c5a235 100644 --- a/Controllers/ASRockSMBusController/RGBController_ASRockPolychromeV2SMBus.cpp +++ b/Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController/RGBController_ASRockPolychromeV2SMBus.cpp @@ -1,11 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_ASRockPolychromeV2SMBus.cpp| -| | -| Generic RGB Interface for OpenRGB | -| ASRock ASR LED and Polychrome RGB Driver | -| | -| Adam Honse (CalcProgrammer1) 12/15/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ASRockPolychromeV2SMBus.cpp | +| | +| RGBController for SMBus ASRock Polychrome V2 | +| motherboards | +| | +| Adam Honse (CalcProgrammer1) 15 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_ASRockPolychromeV2SMBus.h" @@ -287,7 +290,7 @@ void RGBController_ASRockPolychromeV2SMBus::ResizeZone(int /*zone*/, int /*new_s void RGBController_ASRockPolychromeV2SMBus::DeviceUpdateLEDs() { - for (std::size_t led = 0; led < colors.size(); led++) + for(unsigned int led = 0; led < colors.size(); led++) { UpdateSingleLED(led); } diff --git a/Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController/RGBController_ASRockPolychromeV2SMBus.h b/Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController/RGBController_ASRockPolychromeV2SMBus.h new file mode 100644 index 00000000..75e85795 --- /dev/null +++ b/Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController/RGBController_ASRockPolychromeV2SMBus.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_ASRockPolychromeV2SMBus.h | +| | +| RGBController for SMBus ASRock Polychrome V2 | +| motherboards | +| | +| Adam Honse (CalcProgrammer1) 15 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "ASRockPolychromeV2SMBusController.h" + +class RGBController_ASRockPolychromeV2SMBus : public RGBController +{ +public: + RGBController_ASRockPolychromeV2SMBus(ASRockPolychromeV2SMBusController* controller_ptr); + ~RGBController_ASRockPolychromeV2SMBus(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + ASRockPolychromeV2SMBusController* controller; +}; diff --git a/Controllers/ASRockSMBusController/ASRockSMBusControllerDetect.cpp b/Controllers/ASRockSMBusController/ASRockSMBusControllerDetect.cpp index ee052755..9e7a0d1e 100644 --- a/Controllers/ASRockSMBusController/ASRockSMBusControllerDetect.cpp +++ b/Controllers/ASRockSMBusController/ASRockSMBusControllerDetect.cpp @@ -1,17 +1,26 @@ +/*---------------------------------------------------------*\ +| ASRockSMBusControllerDetect.cpp | +| | +| Detector for SMBus ASRock ASR RGB and Polychrome | +| motherboards | +| | +| Adam Honse (CalcProgrammer1) 14 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "ASRockASRRGBSMBusController.h" #include "ASRockPolychromeV1SMBusController.h" #include "ASRockPolychromeV2SMBusController.h" #include "LogManager.h" -#include "RGBController.h" #include "RGBController_ASRockASRRGBSMBus.h" #include "RGBController_ASRockPolychromeV1SMBus.h" #include "RGBController_ASRockPolychromeV2SMBus.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include /*******************************************************************************************\ * * diff --git a/Controllers/ASRockSMBusController/RGBController_ASRockASRRGBSMBus.h b/Controllers/ASRockSMBusController/RGBController_ASRockASRRGBSMBus.h deleted file mode 100644 index bcf16090..00000000 --- a/Controllers/ASRockSMBusController/RGBController_ASRockASRRGBSMBus.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_ASRockPolychromeSMBus.h | -| | -| Generic RGB Interface for OpenRGB | -| ASRock ASR LED and Polychrome RGB Driver | -| | -| Adam Honse (CalcProgrammer1) 12/15/2019 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "ASRockASRRGBSMBusController.h" - -class RGBController_ASRockASRRGBSMBus : public RGBController -{ -public: - RGBController_ASRockASRRGBSMBus(ASRockASRRGBSMBusController* controller_ptr); - ~RGBController_ASRockASRRGBSMBus(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - ASRockASRRGBSMBusController* controller; -}; diff --git a/Controllers/ASRockSMBusController/RGBController_ASRockPolychromeV1SMBus.h b/Controllers/ASRockSMBusController/RGBController_ASRockPolychromeV1SMBus.h deleted file mode 100644 index 7304d0f1..00000000 --- a/Controllers/ASRockSMBusController/RGBController_ASRockPolychromeV1SMBus.h +++ /dev/null @@ -1,35 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_ASRockPolychromeV1SMBus.h | -| | -| Generic RGB Interface for OpenRGB | -| ASRock ASR LED and Polychrome RGB Driver | -| | -| Adam Honse (CalcProgrammer1) 12/15/2019 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "ASRockPolychromeV1SMBusController.h" - -class RGBController_ASRockPolychromeV1SMBus : public RGBController -{ -public: - RGBController_ASRockPolychromeV1SMBus(ASRockPolychromeV1SMBusController* controller_ptr); - ~RGBController_ASRockPolychromeV1SMBus(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - ASRockPolychromeV1SMBusController* controller; - uint8_t getModeIndex(uint8_t mode_value); - std::vector zoneIndexMap; -}; diff --git a/Controllers/ASRockSMBusController/RGBController_ASRockPolychromeV2SMBus.h b/Controllers/ASRockSMBusController/RGBController_ASRockPolychromeV2SMBus.h deleted file mode 100644 index e35a856f..00000000 --- a/Controllers/ASRockSMBusController/RGBController_ASRockPolychromeV2SMBus.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_ASRockPolychromev2SMBus.h | -| | -| Generic RGB Interface for OpenRGB | -| ASRock ASR LED and Polychrome RGB Driver | -| | -| Adam Honse (CalcProgrammer1) 12/15/2019 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "ASRockPolychromeV2SMBusController.h" - -class RGBController_ASRockPolychromeV2SMBus : public RGBController -{ -public: - RGBController_ASRockPolychromeV2SMBus(ASRockPolychromeV2SMBusController* controller_ptr); - ~RGBController_ASRockPolychromeV2SMBus(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - ASRockPolychromeV2SMBusController* controller; -}; diff --git a/Controllers/AlienwareController/AlienwareController.cpp b/Controllers/AlienwareController/AlienwareController.cpp index ca6947ee..c7edec2e 100644 --- a/Controllers/AlienwareController/AlienwareController.cpp +++ b/Controllers/AlienwareController/AlienwareController.cpp @@ -1,13 +1,14 @@ -/*-----------------------------------------*\ -| AlienwareController.cpp | -| | -| Driver for Alienware lighting controller | -| | -| Gabriel Marcano (gemarcano) 4/21/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| AlienwareController.cpp | +| | +| Driver for Dell Alienware RGB USB controller | +| | +| Gabriel Marcano (gemarcano) 21 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController.h" -#include "AlienwareController.h" #include #include #include @@ -15,6 +16,10 @@ #include #include #include +#include "RGBController.h" +#include "AlienwareController.h" +#include "LogManager.h" +#include "StringUtils.h" typedef uint32_t alienware_platform_id; @@ -24,8 +29,11 @@ typedef uint32_t alienware_platform_id; \*---------------------------------------------------------*/ static const std::map zone_quirks_table = { - { 0x0C01, 4 }, // Dell G5 SE 5505 - { 0x0A01, 16 } // Dell G7 15 7500 + { 0x0C01, 4 }, // Dell G5 SE 5505 + { 0x0A01, 16 }, // Dell G7 15 7500 + { 0x0E03, 4 }, // Dell G15 5511 + { 0x0E0A, 4 } // Dell G15 5530 + }; /*---------------------------------------------------------*\ @@ -39,7 +47,9 @@ static const std::map> zone_name "Light Bar 1", "Light Bar 2", "Light Bar 3", "Light Bar 4", "Light Bar 5", "Light Bar 6", "Light Bar 7", "Light Bar 8", "Light Bar 9", - "Light Bar 10", "Light Bar 11", "Light Bar 12" } } + "Light Bar 10", "Light Bar 11", "Light Bar 12" } }, + { 0x0E03, { "Left", "Middle", "Right", "Numpad" } }, + { 0x0E0A, { "Left", "Middle", "Right", "Numpad" } } }; static void SendHIDReport(hid_device *dev, const unsigned char* usb_buf, size_t usb_buf_size) @@ -80,9 +90,7 @@ AlienwareController::AlienwareController(hid_device* dev_handle, const hid_devic /*-----------------------------------------------------*\ | Get serial number | \*-----------------------------------------------------*/ - std::wstring tmp_serial_number; - tmp_serial_number = info.serial_number; - serial_number = std::string(tmp_serial_number.begin(), tmp_serial_number.end()); + serial_number = StringUtils::wstring_to_string(info.serial_number); /*-----------------------------------------------------*\ | Get zone information by checking firmware | @@ -91,6 +99,11 @@ AlienwareController::AlienwareController(hid_device* dev_handle, const hid_devic report = Report(ALIENWARE_COMMAND_REPORT_CONFIG); alienware_platform_id platform_id = report.data[4] << 8 | report.data[5]; + /*-----------------------------------------------------*\ + | Check if the device reports the wrong number of zones | + \*-----------------------------------------------------*/ + unsigned number_of_zones = zone_quirks_table.count(platform_id) ? zone_quirks_table.at(platform_id) : report.data[6]; + /*-----------------------------------------------------*\ | Get firmware version | \*-----------------------------------------------------*/ @@ -101,11 +114,6 @@ AlienwareController::AlienwareController(hid_device* dev_handle, const hid_devic fw_string << static_cast(report.data[4]) << '.' << static_cast(report.data[5]) << '.' << static_cast(report.data[6]); version = fw_string.str(); - /*-----------------------------------------------------*\ - | Check if the device reports the wrong number of zones | - \*-----------------------------------------------------*/ - unsigned number_of_zones = zone_quirks_table.count(platform_id) ? zone_quirks_table.at(platform_id) : report.data[6]; - /*-----------------------------------------------------*\ | Initialize Alienware zones | \*-----------------------------------------------------*/ @@ -113,10 +121,13 @@ AlienwareController::AlienwareController(hid_device* dev_handle, const hid_devic if(zone_names_table.count(platform_id)) { + LOG_INFO("[%s] Known platform: %8X, Number of zones: %d", ALIENWARE_CONTROLLER_NAME, platform_id, number_of_zones); zone_names = zone_names_table.at(platform_id); } else { + LOG_WARNING("[%s] Unknown platform: %8X, Number of zones: %d", ALIENWARE_CONTROLLER_NAME, platform_id, number_of_zones); + /*-------------------------------------------------*\ | If this is an unknown controller, set the name of | | all regions to "Unknown" | @@ -160,7 +171,7 @@ AlienwareController::~AlienwareController() unsigned int AlienwareController::GetZoneCount() { - return(zones.size()); + return((unsigned int)zones.size()); } std::vector AlienwareController::GetZoneNames() @@ -265,7 +276,7 @@ bool AlienwareController::Dim(std::vector zones, double percent) /*-----------------------------------------------------*\ | Set up message packet with leading 00, per hidapi | \*-----------------------------------------------------*/ - uint16_t num_zones = zones.size(); + uint16_t num_zones = (uint16_t)zones.size(); usb_buf[0x00] = 0x00; usb_buf[0x01] = 0x03; @@ -369,7 +380,7 @@ bool AlienwareController::SelectZones(const std::vector& zones) /*-----------------------------------------------------*\ | Set up message packet with leading 00, per hidapi | \*-----------------------------------------------------*/ - uint16_t num_zones = zones.size(); + uint16_t num_zones = (uint16_t)zones.size(); usb_buf[0x00] = 0x00; usb_buf[0x01] = 0x03; @@ -508,7 +519,7 @@ bool AlienwareController::SetColorDirect(RGBColor color, std::vector zo /*-----------------------------------------------------*\ | Set up message packet with leading 00, per hidapi | \*-----------------------------------------------------*/ - uint16_t num_zones = zones.size(); + uint16_t num_zones = (uint16_t)zones.size(); usb_buf[0x00] = 0x00; usb_buf[0x01] = 0x03; @@ -644,7 +655,7 @@ void AlienwareController::UpdateDim() for(size_t i = 0; i < zones.size(); i++) { - dim_zone_map[zones[i].dim].emplace_back(i); + dim_zone_map[zones[i].dim].emplace_back((uint8_t)i); } for(std::pair> &pair : dim_zone_map) @@ -671,7 +682,7 @@ bool AlienwareController::UpdateDirect() for(size_t i = 0; i < zones.size(); i++) { - color_zone_map[zones[i].color[0]].emplace_back(i); + color_zone_map[zones[i].color[0]].emplace_back((uint8_t)i); } for(std::pair> &pair : color_zone_map) diff --git a/Controllers/AlienwareController/AlienwareController.h b/Controllers/AlienwareController/AlienwareController.h index 26e37b52..57be3d7e 100644 --- a/Controllers/AlienwareController/AlienwareController.h +++ b/Controllers/AlienwareController/AlienwareController.h @@ -1,25 +1,27 @@ -/*-----------------------------------------*\ -| AlienwareController.h | -| | -| Driver for Dell Alienware RGB USB | -| controller | -| | -| Gabriel Marcano (gemarcano) 4/19/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include +/*---------------------------------------------------------*\ +| AlienwareController.h | +| | +| Driver for Dell Alienware RGB USB controller | +| | +| Gabriel Marcano (gemarcano) 19 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + /*----------------------------------------------------------------------------------------------*\ | Definitions for Alienware Controller | \*----------------------------------------------------------------------------------------------*/ #define ALIENWARE_REPORT_SIZE 33 #define HIDAPI_ALIENWARE_REPORT_SIZE (ALIENWARE_REPORT_SIZE + 1) - +#define ALIENWARE_CONTROLLER_NAME "AlienWare Controller" enum { ALIENWARE_COMMAND_REPORT = 0x20, /* Set report type to get */ diff --git a/Controllers/AlienwareController/AlienwareControllerDetect.cpp b/Controllers/AlienwareController/AlienwareControllerDetect.cpp index f2099a62..e45af6e5 100644 --- a/Controllers/AlienwareController/AlienwareControllerDetect.cpp +++ b/Controllers/AlienwareController/AlienwareControllerDetect.cpp @@ -1,6 +1,14 @@ +/*---------------------------------------------------------*\ +| AlienwareControllerDetect.cpp | +| | +| Detector for Dell Alienware RGB USB controller | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "AlienwareController.h" -#include "RGBController.h" #include "RGBController_Alienware.h" /*---------------------------------------------------------*\ @@ -11,7 +19,8 @@ /*---------------------------------------------------------*\ | Alienware product ID | \*---------------------------------------------------------*/ -#define ALIENWARE_G_SERIES_PID 0x0550 +#define ALIENWARE_G_SERIES_PID1 0x0550 +#define ALIENWARE_G_SERIES_PID2 0x0551 void DetectAlienwareControllers(hid_device_info* info, const std::string& name) { @@ -26,4 +35,5 @@ void DetectAlienwareControllers(hid_device_info* info, const std::string& name) } } -REGISTER_HID_DETECTOR("Dell G Series LED Controller", DetectAlienwareControllers, ALIENWARE_VID, ALIENWARE_G_SERIES_PID); +REGISTER_HID_DETECTOR("Dell G Series LED Controller", DetectAlienwareControllers, ALIENWARE_VID, ALIENWARE_G_SERIES_PID1); +REGISTER_HID_DETECTOR("Dell G Series LED Controller", DetectAlienwareControllers, ALIENWARE_VID, ALIENWARE_G_SERIES_PID2); diff --git a/Controllers/AlienwareController/RGBController_Alienware.cpp b/Controllers/AlienwareController/RGBController_Alienware.cpp index 55f7b056..b02806b4 100644 --- a/Controllers/AlienwareController/RGBController_Alienware.cpp +++ b/Controllers/AlienwareController/RGBController_Alienware.cpp @@ -1,16 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_Alienware.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Alienware USB Driver | -| | -| Gabriel Marcano (gemarcano) 4/19/2021 | -\*-----------------------------------------*/ - -#include "RGBController_Alienware.h" +/*---------------------------------------------------------*\ +| RGBController_Alienware.cpp | +| | +| RGBController for Dell Alienware RGB USB controller | +| | +| Gabriel Marcano (gemarcano) 19 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include #include +#include "RGBController_Alienware.h" /**------------------------------------------------------------------*\ @name Alienware @@ -213,7 +214,7 @@ void RGBController_Alienware::DeviceUpdateMode() /*-----------------------------------------------------*\ | Setup state per zone | \*-----------------------------------------------------*/ - for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + for(uint8_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) { zone current_zone = zones[zone_idx]; diff --git a/Controllers/AlienwareController/RGBController_Alienware.h b/Controllers/AlienwareController/RGBController_Alienware.h index a3850a08..8edfbe93 100644 --- a/Controllers/AlienwareController/RGBController_Alienware.h +++ b/Controllers/AlienwareController/RGBController_Alienware.h @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| RGBController_Alienware.h | -| | -| Generic RGB Interface for OpenRGB | -| Alienware RGB USB Driver | -| | -| Gabriel Marcano (gemarcano) 4/19/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Alienware.h | +| | +| RGBController for Dell Alienware RGB USB controller | +| | +| Gabriel Marcano (gemarcano) 19 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include #include "RGBController.h" #include "AlienwareController.h" -#include - class RGBController_Alienware : public RGBController { public: diff --git a/Controllers/AlienwareKeyboardController/AlienwareAW410KController/AlienwareAW410KController.cpp b/Controllers/AlienwareKeyboardController/AlienwareAW410KController/AlienwareAW410KController.cpp new file mode 100644 index 00000000..ae86bc85 --- /dev/null +++ b/Controllers/AlienwareKeyboardController/AlienwareAW410KController/AlienwareAW410KController.cpp @@ -0,0 +1,453 @@ +/*---------------------------------------------------------*\ +| AlienwareAW410KController.cpp | +| | +| Driver for Alienware AW410K keyboard | +| | +| based on AW510K controller by Mohamad Sallal (msallal) | +| Dominik Mikolajczyk (dmiko) 23 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "AlienwareAW410KController.h" +#include "StringUtils.h" + +AlienwareAW410KController::AlienwareAW410KController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + + SendCommit(); +} + +AlienwareAW410KController::~AlienwareAW410KController() +{ + hid_close(dev); +} + +std::string AlienwareAW410KController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string AlienwareAW410KController::GetDeviceName() +{ + return(name); +} + +std::string AlienwareAW410KController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void AlienwareAW410KController::SendCommit() +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Commit packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x05; + usb_buf[0x02] = 0x01; + usb_buf[0x0A] = 0x10; + usb_buf[0x0B] = 0x0A; + usb_buf[0x0C] = 0x01; + usb_buf[0x0D] = 0x02; + usb_buf[0x0E] = 0x01; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); + + /*-----------------------------------------------------*\ + | Delay 20 milliseconds | + \*-----------------------------------------------------*/ + std::this_thread::sleep_for(std::chrono::milliseconds(20)); +} + +void AlienwareAW410KController::SendfeatureReport + ( + unsigned char first_byte, + unsigned char second_byte, + unsigned char third_byte, + unsigned char forth_byte + ) +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Feature report packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x00; + usb_buf[0x01] = first_byte; + usb_buf[0x02] = second_byte; + usb_buf[0x03] = third_byte; + usb_buf[0x04] = forth_byte; + + /*-----------------------------------------------------*\ + | Send Feature report packet | + \*-----------------------------------------------------*/ + hid_send_feature_report(dev, usb_buf, 65); + + /*-----------------------------------------------------*\ + | Delay 10 milliseconds | + \*-----------------------------------------------------*/ + std::this_thread::sleep_for(std::chrono::milliseconds(10)); +} + +void AlienwareAW410KController::SendEdit() +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Edit packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x01; + usb_buf[0x02] = 0x00; + usb_buf[0x03] = 0x01; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); + + /*-----------------------------------------------------*\ + | Delay 2 milliseconds | + \*-----------------------------------------------------*/ + std::this_thread::sleep_for(std::chrono::milliseconds(2)); +} + +void AlienwareAW410KController::SendInitialize() +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Commit packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x0E; + usb_buf[0x02] = 0x01; + usb_buf[0x03] = 0x00; + usb_buf[0x04] = 0x01; + usb_buf[0x05] = 0xAD; + usb_buf[0x06] = 0x80; + usb_buf[0x07] = 0x10; + usb_buf[0x08] = 0xA5; + usb_buf[0x0A] = 0x0A; + usb_buf[0x12] = 0x01; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); + + /*-----------------------------------------------------*\ + | Delay 2 milliseconds | + \*-----------------------------------------------------*/ + std::this_thread::sleep_for(std::chrono::milliseconds(2)); +} + +void AlienwareAW410KController::SetDirect + ( + unsigned char /*zone*/, + unsigned char r, + unsigned char g, + unsigned char b + ) +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Lighting Control packet | + \*-----------------------------------------------------*/ + + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x05; + usb_buf[0x02] = 0x01; + usb_buf[0x03] = 0x01; + usb_buf[0x04] = r; + usb_buf[0x05] = g; + usb_buf[0x06] = b; + usb_buf[0x0B] = 0x0A; + usb_buf[0x0D] = 0x01; + usb_buf[0x0E] = 0x01; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, (unsigned char *)usb_buf, 65); + + /*-----------------------------------------------------*\ + | Delay 2 milliseconds | + \*-----------------------------------------------------*/ + std::this_thread::sleep_for(std::chrono::milliseconds(2)); +} + +void AlienwareAW410KController::SendDirectOn + ( + std::vector &frame_data + ) +{ + SendfeatureReport(0x0E, (unsigned char)frame_data.size(), 0x00, 0x01); + + /*-----------------------------------------------*\ + | To Guarantee the data are always %4 =0 append | + | zeros at end of last packet | + \*-----------------------------------------------*/ + for(unsigned int i = 0; i < (frame_data.size() % 4); i++) + { + SelectedButtons key; + key.idx = 0x00; + key.red = 0x00; + key.green = 0x00; + key.blue = 0x00; + + frame_data.push_back(key); + } + + unsigned char usb_buf[65]; + unsigned int frame_idx = 0; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, 65); + + for(unsigned int packet_idx = 0; packet_idx < frame_data.size(); packet_idx++) + { + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x0E; + usb_buf[0x02] = 0x01; + usb_buf[0x03] = 0x00; + usb_buf[0x04] = ++frame_idx; + usb_buf[0x05] = frame_data[packet_idx].idx; + usb_buf[0x06] = 0x81; + usb_buf[0x07] = 0x00; + usb_buf[0x08] = 0xA5; + usb_buf[0x0A] = 0x0A; + usb_buf[0x0B] = frame_data[packet_idx].red; + usb_buf[0x0C] = frame_data[packet_idx].green; + usb_buf[0x0D] = frame_data[packet_idx].blue; + usb_buf[0x12] = 0x01; + + usb_buf[0x14] = frame_data[++packet_idx].idx; + usb_buf[0x15] = 0x81; + usb_buf[0x16] = 0x00; + usb_buf[0x17] = 0xA5; + usb_buf[0x19] = 0x0A; + usb_buf[0x1A] = frame_data[packet_idx].red; + usb_buf[0x1B] = frame_data[packet_idx].green; + usb_buf[0x1C] = frame_data[packet_idx].blue; + usb_buf[0x21] = 0x01; + + usb_buf[0x23] = frame_data[++packet_idx].idx; + usb_buf[0x24] = 0x81; + usb_buf[0x25] = 0x00; + usb_buf[0x26] = 0xA5; + usb_buf[0x28] = 0x0A; + usb_buf[0x29] = frame_data[packet_idx].red; + usb_buf[0x2A] = frame_data[packet_idx].green; + usb_buf[0x2B] = frame_data[packet_idx].blue; + usb_buf[0x30] = 0x01; + + usb_buf[0x32] = frame_data[++packet_idx].idx; + usb_buf[0x33] = 0x81; + usb_buf[0x34] = 0x00; + usb_buf[0x35] = 0xA5; + usb_buf[0x37] = 0x0A; + usb_buf[0x38] = frame_data[packet_idx].red; + usb_buf[0x39] = frame_data[packet_idx].green; + usb_buf[0x3A] = frame_data[packet_idx].blue; + usb_buf[0x3F] = 0x01; + + hid_write(dev, (unsigned char *)usb_buf, 65); + } +} + + +void AlienwareAW410KController::SetMode + ( + unsigned char mode, + unsigned char speed, + unsigned char direction, + unsigned char colorMode, + unsigned char red, + unsigned char green, + unsigned char blue + ) +{ + SendMode(ALIENWARE_AW410K_ZONE_MODE_KEYBOARD, mode, speed, direction, colorMode, red, green, blue); + SendCommit(); +} + +void AlienwareAW410KController::UpdateSingleLED + ( + unsigned char led, + unsigned char red, + unsigned char green, + unsigned char blue + ) +{ + SendfeatureReport(0x0E, 0x01, 0x00, 0x01); + + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Single LED packet | + \*-----------------------------------------------------*/ + + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x0E; + usb_buf[0x02] = 0x01; + usb_buf[0x03] = 0x00; + usb_buf[0x04] = 0x01; + usb_buf[0x05] = led; + usb_buf[0x06] = 0x81; + usb_buf[0x07] = 0x00; + usb_buf[0x08] = 0xA5; + usb_buf[0x09] = 0x00; + usb_buf[0x0A] = 0x0A; + usb_buf[0x0B] = red; + usb_buf[0x0C] = green; + usb_buf[0x0D] = blue; + usb_buf[0x12] = 0x01; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); + + /*-----------------------------------------------------*\ + | Delay 20 milliseconds | + \*-----------------------------------------------------*/ + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + +} +void AlienwareAW410KController::SendMode + ( + unsigned char /*zone*/, + unsigned char mode, + unsigned char speed, + unsigned char direction, + unsigned char colorMode, + unsigned char red, + unsigned char green, + unsigned char blue + ) +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Mode Control packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x05; + usb_buf[0x02] = 0x01; + usb_buf[0x03] = mode; + usb_buf[0x04] = red; + usb_buf[0x05] = green; + usb_buf[0x06] = blue; + usb_buf[0x0A] = speed; + usb_buf[0x0B] = 0x0A; + usb_buf[0x0D] = 0x01; + usb_buf[0x0E] = colorMode; + usb_buf[0x0F] = direction; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); +} + +void AlienwareAW410KController::SetMorphMode + ( + unsigned char mode, + unsigned char speed, + unsigned char red1, + unsigned char green1, + unsigned char blue1, + unsigned char red2, + unsigned char green2, + unsigned char blue2 + ) +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Morph Mode packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x05; + usb_buf[0x02] = 0x01; + usb_buf[0x03] = mode; + usb_buf[0x04] = red1; + usb_buf[0x05] = green1; + usb_buf[0x06] = blue1; + usb_buf[0x07] = red2; + usb_buf[0x08] = green2; + usb_buf[0x09] = blue2; + usb_buf[0x0E] = 0x02; + usb_buf[0x0A] = speed; + usb_buf[0x0B] = 0x0A; + usb_buf[0x0D] = 0x01; + usb_buf[0x0E] = ALIENWARE_AW410K_TWO_USER_DEFINED_COLOR_MODE; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); +} diff --git a/Controllers/AlienwareKeyboardController/AlienwareAW410KController/AlienwareAW410KController.h b/Controllers/AlienwareKeyboardController/AlienwareAW410KController/AlienwareAW410KController.h new file mode 100644 index 00000000..6d5f718c --- /dev/null +++ b/Controllers/AlienwareKeyboardController/AlienwareAW410KController/AlienwareAW410KController.h @@ -0,0 +1,157 @@ +/*---------------------------------------------------------*\ +| AlienwareAW410KController.h | +| | +| Driver for Alienware AW410K keyboard | +| | +| based on AW510K controller by Mohamad Sallal (msallal) | +| Dominik Mikolajczyk (dmiko) 23 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +enum +{ + ALIENWARE_AW410K_ZONE_MODE_KEYBOARD = 0x01, +}; + +enum +{ + ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD = 0x01, + ALIENWARE_AW410K_ZONE_DIRECT_MEDIA = 0x02, + ALIENWARE_AW410K_ZONE_DIRECT_INDICATORS = 0x40, +}; + +enum +{ + ALIENWARE_AW410K_MODE_OFF = 0x00, + ALIENWARE_AW410K_MODE_DIRECT = 0x01, + ALIENWARE_AW410K_MODE_PULSE = 0x02, + ALIENWARE_AW410K_MODE_MORPH = 0x03, + ALIENWARE_AW410K_MODE_BREATHING = 0x07, + ALIENWARE_AW410K_MODE_SPECTRUM = 0x08, + ALIENWARE_AW410K_MODE_SINGLE_WAVE = 0x0F, + ALIENWARE_AW410K_MODE_RAINBOW_WAVE = 0x10, + ALIENWARE_AW410K_MODE_SCANNER = 0x11, + ALIENWARE_AW410K_MODE_STATIC = 0x13, +}; + +enum +{ + ALIENWARE_AW410K_SPEED_SLOWEST = 0x2D, /* Slowest speed */ + ALIENWARE_AW410K_SPEED_NORMAL = 0x19, /* Normal speed */ + ALIENWARE_AW410K_SPEED_FASTEST = 0x0A, /* Fastest speed */ +}; + +enum +{ + ALIENWARE_AW410K_DIRECTION_LEFT_TO_RIGHT = 0x01, + ALIENWARE_AW410K_DIRECTION_RIGHT_TO_LEFT = 0x02, + ALIENWARE_AW410K_DIRECTION_TOP_TO_BOTTOM = 0x03, + ALIENWARE_AW410K_DIRECTION_BOTTOM_TO_TOP = 0x04, +}; + +enum +{ + ALIENWARE_AW410K_SINGLE_COLOR_MODE = 0x01, + ALIENWARE_AW410K_TWO_USER_DEFINED_COLOR_MODE= 0x02, + ALIENWARE_AW410K_RANBOW_COLOR_MODE = 0x03, +}; + +struct SelectedButtons +{ + unsigned char idx; + unsigned char red; + unsigned char green; + unsigned char blue; +}; + +class AlienwareAW410KController +{ +public: + AlienwareAW410KController(hid_device* dev_handle, const char* path, std::string dev_name); + ~AlienwareAW410KController(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + std::string GetSerialString(); + + void SendInitialize(); + void SendCommit(); + void SendfeatureReport + ( + unsigned char first_byte, + unsigned char second_byte, + unsigned char third_byte, + unsigned char forth_byte + ); + + void SendEdit(); + + void SetDirect + ( + unsigned char zone, + unsigned char r, + unsigned char g, + unsigned char b + ); + + void SendDirectOn + ( + std::vector &frame_data + ); + + void SetMode + ( + unsigned char mode, + unsigned char speed, + unsigned char direction, + unsigned char colorMode, + unsigned char red, + unsigned char green, + unsigned char blue + ); + + void SetMorphMode + ( + unsigned char mode, + unsigned char speed, + unsigned char red1, + unsigned char green1, + unsigned char blue1, + unsigned char red2, + unsigned char green2, + unsigned char blue2 + ); + + void UpdateSingleLED + ( + unsigned char led, + unsigned char red, + unsigned char green, + unsigned char blue + ); + +private: + hid_device* dev; + std::string location; + std::string name; + + void SendMode + ( + unsigned char zone, + unsigned char mode, + unsigned char speed, + unsigned char direction, + unsigned char colorMode, + unsigned char red, + unsigned char green, + unsigned char blue + ); +}; diff --git a/Controllers/AlienwareKeyboardController/AlienwareAW410KController/RGBController_AlienwareAW410K.cpp b/Controllers/AlienwareKeyboardController/AlienwareAW410KController/RGBController_AlienwareAW410K.cpp new file mode 100644 index 00000000..d98e9659 --- /dev/null +++ b/Controllers/AlienwareKeyboardController/AlienwareAW410KController/RGBController_AlienwareAW410K.cpp @@ -0,0 +1,482 @@ +/*---------------------------------------------------------*\ +| RGBController_AlienwareAW410K.cpp | +| | +| RGBController for Alienware AW410K keyboard | +| | +| based on AW510K controller by Mohamad Sallal (msallal) | +| Dominik Mikolajczyk (dmiko) 23 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RGBControllerKeyNames.h" +#include "RGBController_AlienwareAW410K.h" + +//0xFFFFFFFF indicates an unused entry in matrix +#define NA 0xFFFFFFFF + +int GetAW410K_WaveDirection(int input); + +static unsigned int matrix_map[6][24] = +{ { 0, NA, 1, 2, 3, 4, NA, 5, 6, 7, 8, 9, 10, 11, 12, NA, 13, 14, 15, NA, NA, 16, 17, 18 }, + { 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, NA, NA, 33, 34, 35, NA, 36, 37, 38, 39 }, + { 40, NA, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, NA, 54, 55, 56, NA, 57, 58, 59, 60 }, + { 61, NA, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, NA, 73, NA, NA, NA, NA, NA, 74, 75, 76, NA }, + { 77, NA, NA, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, NA, NA, NA, 89, NA, NA, 90, 91, 92, 93 }, + { 94, NA, 95, 96, NA, NA, NA, 97, NA, NA, NA, 98, 99, 100, 101, NA, 102, 103, 104, NA, 105, NA, 106, NA }}; + +static const char* zone_names[] = +{ + "AW410K", +}; + +static zone_type zone_types[] = +{ + ZONE_TYPE_MATRIX, +}; + +static const unsigned int zone_sizes[] = +{ + 107, +}; + +typedef struct +{ + const char * name; + const unsigned char zone; + const unsigned char idx; +} aw410k_led_type; + +static const aw410k_led_type led_names[] = +{ + /* Key Label Zone, Index */ + { KEY_EN_ESCAPE, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0xB0 }, + { KEY_EN_F1, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x98 }, + { KEY_EN_F2, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x90 }, + { KEY_EN_F3, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x88 }, + { KEY_EN_F4, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x80 }, + { KEY_EN_F5, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x70 }, + { KEY_EN_F6, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x68 }, + { KEY_EN_F7, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x60 }, + { KEY_EN_F8, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x58 }, + { KEY_EN_F9, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x50 }, + { KEY_EN_F10, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x48 }, + { KEY_EN_F11, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x40 }, + { KEY_EN_F12, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x38 }, + { KEY_EN_PRINT_SCREEN, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x30 }, + { KEY_EN_SCROLL_LOCK, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x28 }, + { KEY_EN_PAUSE_BREAK, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x20 }, + { KEY_EN_MEDIA_MUTE, ALIENWARE_AW410K_ZONE_DIRECT_MEDIA, 0x18 }, + { KEY_EN_MEDIA_VOLUME_DOWN, ALIENWARE_AW410K_ZONE_DIRECT_MEDIA, 0x10 }, + { KEY_EN_MEDIA_VOLUME_UP, ALIENWARE_AW410K_ZONE_DIRECT_MEDIA, 0x08 }, + { KEY_EN_BACK_TICK, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0xB1 }, + { KEY_EN_1, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0xA1 }, + { KEY_EN_2, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x99 }, + { KEY_EN_3, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x91 }, + { KEY_EN_4, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x89 }, + { KEY_EN_5, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x81 }, + { KEY_EN_6, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x79 }, + { KEY_EN_7, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x71 }, + { KEY_EN_8, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x69 }, + { KEY_EN_9, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x61 }, + { KEY_EN_0, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x59 }, + { KEY_EN_MINUS, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x51 }, + { KEY_EN_EQUALS, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x49 }, + { KEY_EN_BACKSPACE, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x39 }, + { KEY_EN_INSERT, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x31 }, + { KEY_EN_HOME, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x29 }, + { KEY_EN_PAGE_UP, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x21 }, + { KEY_EN_NUMPAD_LOCK, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x19 }, + { KEY_EN_NUMPAD_DIVIDE, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x11 }, + { KEY_EN_NUMPAD_TIMES, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x09 }, + { KEY_EN_NUMPAD_MINUS, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x01 }, + { KEY_EN_TAB, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0xB2 }, + { KEY_EN_Q, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0xA2 }, + { KEY_EN_W, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x9A }, + { KEY_EN_E, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x92 }, + { KEY_EN_R, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x8A }, + { KEY_EN_T, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x82 }, + { KEY_EN_Y, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x7A }, + { KEY_EN_U, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x72 }, + { KEY_EN_I, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x6A }, + { KEY_EN_O, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x62 }, + { KEY_EN_P, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x5A }, + { KEY_EN_LEFT_BRACKET, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x52 }, + { KEY_EN_RIGHT_BRACKET, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x4A }, + { KEY_EN_ANSI_BACK_SLASH, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x42 }, + { KEY_EN_DELETE, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x32 }, + { KEY_EN_END, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x2A }, + { KEY_EN_PAGE_DOWN, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x22 }, + { KEY_EN_NUMPAD_7, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x1A }, + { KEY_EN_NUMPAD_8, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x12 }, + { KEY_EN_NUMPAD_9, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x0A }, + { KEY_EN_NUMPAD_PLUS, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x03 }, + { KEY_EN_CAPS_LOCK, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0xB3 }, + { KEY_EN_A, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0xA3 }, + { KEY_EN_S, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x9B }, + { KEY_EN_D, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x93 }, + { KEY_EN_F, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x8B }, + { KEY_EN_G, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x83 }, + { KEY_EN_H, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x7B }, + { KEY_EN_J, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x73 }, + { KEY_EN_K, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x6B }, + { KEY_EN_L, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x63 }, + { KEY_EN_SEMICOLON, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x5B }, + { KEY_EN_QUOTE, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x53 }, + { KEY_EN_ANSI_ENTER, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x43 }, + { KEY_EN_NUMPAD_4, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x1B }, + { KEY_EN_NUMPAD_5, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x13 }, + { KEY_EN_NUMPAD_6, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x0B }, + { KEY_EN_LEFT_SHIFT, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0xB4 }, + { KEY_EN_Z, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0xA4 }, + { KEY_EN_X, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x9C }, + { KEY_EN_C, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x94 }, + { KEY_EN_V, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x8C }, + { KEY_EN_B, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x84 }, + { KEY_EN_N, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x7C }, + { KEY_EN_M, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x74 }, + { KEY_EN_COMMA, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x6C }, + { KEY_EN_PERIOD, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x64 }, + { KEY_EN_FORWARD_SLASH, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x5C }, + { KEY_EN_RIGHT_SHIFT, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x4C }, + { KEY_EN_UP_ARROW, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x2C }, + { KEY_EN_NUMPAD_1, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x1C }, + { KEY_EN_NUMPAD_2, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x14 }, + { KEY_EN_NUMPAD_3, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x0C }, + { KEY_EN_NUMPAD_ENTER, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x05 }, + { KEY_EN_LEFT_CONTROL, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0xB5 }, + { KEY_EN_LEFT_WINDOWS, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0xAD }, + { KEY_EN_LEFT_ALT, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0xA5 }, + { KEY_EN_SPACE, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x85 }, + { KEY_EN_RIGHT_ALT, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x65 }, + { KEY_EN_RIGHT_FUNCTION, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x5D }, + { KEY_EN_MENU, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x55 }, + { KEY_EN_RIGHT_CONTROL, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x4D }, + { KEY_EN_LEFT_ARROW, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x35 }, + { KEY_EN_DOWN_ARROW, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x2D }, + { KEY_EN_RIGHT_ARROW, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x25 }, + { KEY_EN_NUMPAD_0, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x1D }, + { KEY_EN_NUMPAD_PERIOD, ALIENWARE_AW410K_ZONE_DIRECT_KEYBOARD, 0x0D } +}; + +/**------------------------------------------------------------------*\ + @name Alienware AW410 Keyboard + @category Keyboard + @type USB + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectAlienwareAW410KControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_AlienwareAW410K::RGBController_AlienwareAW410K(AlienwareAW410KController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "Alienware"; + type = DEVICE_TYPE_KEYBOARD; + description = "Alienware AW410K Keyboard Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = ALIENWARE_AW410K_MODE_DIRECT; + 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 = ALIENWARE_AW410K_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Static.colors_min = 1; + Static.colors_max = 1; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors.resize(1); + modes.push_back(Static); + + mode Pulse; + Pulse.name = "Pulse"; + Pulse.value = ALIENWARE_AW410K_MODE_PULSE; + Pulse.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Pulse.color_mode = MODE_COLORS_MODE_SPECIFIC; + Pulse.speed_min = ALIENWARE_AW410K_SPEED_SLOWEST; + Pulse.speed_max = ALIENWARE_AW410K_SPEED_NORMAL; + Pulse.speed = ALIENWARE_AW410K_SPEED_NORMAL; + Pulse.colors_min = 1; + Pulse.colors_max = 1; + Pulse.colors.resize(1); + modes.push_back(Pulse); + + mode Morph; + Morph.name = "Morph"; + Morph.value = ALIENWARE_AW410K_MODE_MORPH; + Morph.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Morph.color_mode = MODE_COLORS_MODE_SPECIFIC; + Morph.speed_min = ALIENWARE_AW410K_SPEED_SLOWEST; + Morph.speed_max = ALIENWARE_AW410K_SPEED_NORMAL; + Morph.speed = ALIENWARE_AW410K_SPEED_NORMAL; + Morph.colors_min = 2; + Morph.colors_max = 2; + Morph.colors.resize(2); + modes.push_back(Morph); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = ALIENWARE_AW410K_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.colors.resize(1); + Breathing.speed_min = ALIENWARE_AW410K_SPEED_SLOWEST; + Breathing.speed_max = ALIENWARE_AW410K_SPEED_FASTEST; + Breathing.speed = ALIENWARE_AW410K_SPEED_NORMAL; + modes.push_back(Breathing); + + mode SingleWave; + SingleWave.name = "Single Wave"; + SingleWave.value = ALIENWARE_AW410K_MODE_SINGLE_WAVE; + SingleWave.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD; + SingleWave.speed_min = ALIENWARE_AW410K_SPEED_SLOWEST; + SingleWave.speed_max = ALIENWARE_AW410K_SPEED_FASTEST; + SingleWave.speed = ALIENWARE_AW410K_SPEED_NORMAL; + SingleWave.color_mode = MODE_COLORS_MODE_SPECIFIC; + SingleWave.colors_min = 1; + SingleWave.colors_max = 1; + SingleWave.colors.resize(1); + modes.push_back(SingleWave); + + mode RainbowWave; + RainbowWave.name = "Rainbow Wave"; + RainbowWave.value = ALIENWARE_AW410K_MODE_RAINBOW_WAVE; + RainbowWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD; + RainbowWave.speed_min = ALIENWARE_AW410K_SPEED_SLOWEST; + RainbowWave.speed_max = ALIENWARE_AW410K_SPEED_FASTEST; + RainbowWave.speed = ALIENWARE_AW410K_SPEED_NORMAL; + RainbowWave.colors_min = 1; + RainbowWave.colors_max = 1; + RainbowWave.color_mode = MODE_COLORS_MODE_SPECIFIC; + RainbowWave.colors.resize(1); + modes.push_back(RainbowWave); + + mode Off; + Off.name = "Off"; + Off.value = ALIENWARE_AW410K_MODE_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + SetupZones(); + std::copy(colors.begin(), colors.end(),std::back_inserter(current_colors)); +} + +RGBController_AlienwareAW410K::~RGBController_AlienwareAW410K() +{ + /*---------------------------------------------------------*\ + | Delete the matrix map | + \*---------------------------------------------------------*/ + 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; + } + } + + delete controller; +} + +void RGBController_AlienwareAW410K::SetupZones() +{ + /*---------------------------------------------------------*\ + | Set up zones | + \*---------------------------------------------------------*/ + unsigned int total_led_count = 0; + + for(unsigned int zone_idx = 0; zone_idx < 1; zone_idx++) + { + zone new_zone; + new_zone.name = zone_names[zone_idx]; + new_zone.type = zone_types[zone_idx]; + new_zone.leds_min = zone_sizes[zone_idx]; + new_zone.leds_max = zone_sizes[zone_idx]; + new_zone.leds_count = zone_sizes[zone_idx]; + + if(zone_types[zone_idx] == ZONE_TYPE_MATRIX) + { + new_zone.matrix_map = new matrix_map_type; + new_zone.matrix_map->height = 6; + new_zone.matrix_map->width = 24; + new_zone.matrix_map->map = (unsigned int *)&matrix_map; + } + else + { + new_zone.matrix_map = NULL; + } + + zones.push_back(new_zone); + + total_led_count += zone_sizes[zone_idx]; + } + + for(unsigned int led_idx = 0; led_idx < total_led_count; led_idx++) + { + led new_led; + new_led.name = led_names[led_idx].name; + new_led.value = led_names[led_idx].idx; + leds.push_back(new_led); + } + + SetupColors(); +} + +void RGBController_AlienwareAW410K::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_AlienwareAW410K::DeviceUpdateLEDs() +{ + std::vector frame_buf_keys; + std::vector new_colors; + + std::copy(colors.begin(), colors.end(),std::back_inserter(new_colors)); + + for(std::size_t led_idx = 0; led_idx < leds.size(); led_idx++) + { + SelectedButtons key; + + key.idx = (unsigned char)leds[led_idx].value; + key.red = RGBGetRValue(colors[led_idx]); + key.green = RGBGetGValue(colors[led_idx]); + key.blue = RGBGetBValue(colors[led_idx]); + + frame_buf_keys.push_back(key); + } + + controller->SendInitialize(); + controller->SendfeatureReport(0x05, 0x01, 0x51, 0x00); + controller->SendCommit(); + + if(frame_buf_keys.size() > 0) + { + controller->SendDirectOn(frame_buf_keys); + } + + std::copy(new_colors.begin(), new_colors.end(),current_colors.begin()); +} + +void RGBController_AlienwareAW410K::UpdateZoneLEDs(int zone) +{ + controller->SetDirect((unsigned char) zone, RGBGetRValue(zones[zone].colors[0]), RGBGetGValue(zones[zone].colors[0]), RGBGetBValue(zones[zone].colors[0])); +} + +void RGBController_AlienwareAW410K::UpdateSingleLED(int led) +{ + controller->UpdateSingleLED(leds[led].value, RGBGetRValue(colors[led]), RGBGetGValue(colors[led]), RGBGetBValue(colors[led])); +} + +void RGBController_AlienwareAW410K::DeviceUpdateMode() +{ + if(active_mode == 0xFFFF) + { + UpdateLEDs(); + return; + } + + controller->SendfeatureReport(0x05, 0x01, 0x51, 0x00); + unsigned char red = 0; + unsigned char grn = 0; + unsigned char blu = 0; + + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + red = RGBGetRValue(modes[active_mode].colors[0]); + grn = RGBGetGValue(modes[active_mode].colors[0]); + blu = RGBGetBValue(modes[active_mode].colors[0]); + } + + switch(modes[active_mode].value) + { + case ALIENWARE_AW410K_MODE_DIRECT: + /*-------------------------------------------------------------*\ + | Load LEDs again in case of profile load etc. | + \*-------------------------------------------------------------*/ + DeviceUpdateLEDs(); + break; + case ALIENWARE_AW410K_MODE_MORPH: + /*-------------------------------------------------------------*\ + | In case of morph it requires two colors (color1 and color2) | + \*-------------------------------------------------------------*/ + { + unsigned char red2 = RGBGetRValue(modes[active_mode].colors[1]); + unsigned char grn2 = RGBGetGValue(modes[active_mode].colors[1]); + unsigned char blu2 = RGBGetBValue(modes[active_mode].colors[1]); + + controller->SetMorphMode(modes[active_mode].value, modes[active_mode].speed, red, grn, blu, red2, grn2, blu2); + } + break; + + case ALIENWARE_AW410K_MODE_SPECTRUM: + /*-------------------------------------------------------------*\ + | Spectrum only set mode, speed and colorMode | + \*-------------------------------------------------------------*/ + controller->SetMode(modes[active_mode].value, modes[active_mode].speed, 0x00, ALIENWARE_AW410K_RANBOW_COLOR_MODE, 0x00, 0x00, 0x00); + break; + + case ALIENWARE_AW410K_MODE_SINGLE_WAVE: + /*-------------------------------------------------------------*\ + | Wave only set mode, speed, direction and colorMode | + \*-------------------------------------------------------------*/ + { + int waveDirection = GetAW410K_WaveDirection(modes[active_mode].direction); + controller->SetMode(modes[active_mode].value, modes[active_mode].speed, waveDirection, ALIENWARE_AW410K_SINGLE_COLOR_MODE, red, grn, blu); + } + break; + + case ALIENWARE_AW410K_MODE_RAINBOW_WAVE: + /*-------------------------------------------------------------*\ + | Wave only set mode, speed, direction and colorMode | + \*-------------------------------------------------------------*/ + { + int waveDirection = GetAW410K_WaveDirection(modes[active_mode].direction); + controller->SetMode(modes[active_mode].value, modes[active_mode].speed, waveDirection, ALIENWARE_AW410K_RANBOW_COLOR_MODE, 0x00, 0x00, 0x00); + } + break; + + + default: + controller->SetMode(modes[active_mode].value, modes[active_mode].speed, 0x00, ALIENWARE_AW410K_SINGLE_COLOR_MODE, red, grn, blu); + break; + } +} + +int GetAW410K_WaveDirection(int input) +{ + switch(input) + { + case MODE_DIRECTION_LEFT: + return(ALIENWARE_AW410K_DIRECTION_RIGHT_TO_LEFT); + + case MODE_DIRECTION_RIGHT: + return(ALIENWARE_AW410K_DIRECTION_LEFT_TO_RIGHT); + + case MODE_DIRECTION_UP: + return(ALIENWARE_AW410K_DIRECTION_BOTTOM_TO_TOP); + + case MODE_DIRECTION_DOWN: + return(ALIENWARE_AW410K_DIRECTION_TOP_TO_BOTTOM); + + default: + return(ALIENWARE_AW410K_DIRECTION_RIGHT_TO_LEFT); + } +} + diff --git a/Controllers/AlienwareKeyboardController/AlienwareAW410KController/RGBController_AlienwareAW410K.h b/Controllers/AlienwareKeyboardController/AlienwareAW410KController/RGBController_AlienwareAW410K.h new file mode 100644 index 00000000..312383ce --- /dev/null +++ b/Controllers/AlienwareKeyboardController/AlienwareAW410KController/RGBController_AlienwareAW410K.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------*\ +| RGBController_AlienwareAW410K.h | +| | +| RGBController for Alienware AW410K keyboard | +| | +| based on AW510K controller by Mohamad Sallal (msallal) | +| Dominik Mikolajczyk (dmiko) 23 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AlienwareAW410KController.h" + +class RGBController_AlienwareAW410K : public RGBController +{ +public: + RGBController_AlienwareAW410K(AlienwareAW410KController* controller_ptr); + ~RGBController_AlienwareAW410K(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + AlienwareAW410KController* controller; + std::vector current_colors; +}; diff --git a/Controllers/AlienwareKeyboardController/AlienwareAW510KController.cpp b/Controllers/AlienwareKeyboardController/AlienwareAW510KController/AlienwareAW510KController.cpp similarity index 90% rename from Controllers/AlienwareKeyboardController/AlienwareAW510KController.cpp rename to Controllers/AlienwareKeyboardController/AlienwareAW510KController/AlienwareAW510KController.cpp index 7f6136b8..13f8aaa5 100644 --- a/Controllers/AlienwareKeyboardController/AlienwareAW510KController.cpp +++ b/Controllers/AlienwareKeyboardController/AlienwareAW510KController/AlienwareAW510KController.cpp @@ -1,19 +1,23 @@ -/*-----------------------------------------*\ -| AlienwareAW510KController.cpp | -| | -| Driver for Alienware AW510K | -| keyboard light controller | -| | -| Mohamad Sallal - msallal 05/22/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| AlienwareAW510KController.cpp | +| | +| Driver for Alienware AW510K keyboard | +| | +| Mohamad Sallal (msallal) 22 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "AlienwareAW510KController.h" #include +#include "AlienwareAW510KController.h" +#include "StringUtils.h" -AlienwareAW510KController::AlienwareAW510KController(hid_device* dev_handle, const char* path) +AlienwareAW510KController::AlienwareAW510KController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; SendCommit(); } @@ -28,20 +32,27 @@ std::string AlienwareAW510KController::GetDeviceLocation() return("HID: " + location); } +std::string AlienwareAW510KController::GetDeviceName() +{ + return(name); +} + std::string AlienwareAW510KController::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); - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); + if(ret != 0) + { + return(""); + } - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void AlienwareAW510KController::SendCommit() { - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -63,7 +74,7 @@ void AlienwareAW510KController::SendCommit() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, 65); + hid_write(dev, usb_buf, 65); /*-----------------------------------------------------*\ | Delay 20 milliseconds | @@ -71,7 +82,6 @@ void AlienwareAW510KController::SendCommit() std::this_thread::sleep_for(std::chrono::milliseconds(20)); } - void AlienwareAW510KController::SendfeatureReport ( unsigned char first_byte, @@ -80,7 +90,7 @@ void AlienwareAW510KController::SendfeatureReport unsigned char forth_byte ) { - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -99,7 +109,7 @@ void AlienwareAW510KController::SendfeatureReport /*-----------------------------------------------------*\ | Send Feature report packet | \*-----------------------------------------------------*/ - hid_send_feature_report(dev, (unsigned char *)usb_buf, 65); + hid_send_feature_report(dev, usb_buf, 65); /*-----------------------------------------------------*\ | Delay 10 milliseconds | @@ -109,7 +119,7 @@ void AlienwareAW510KController::SendfeatureReport void AlienwareAW510KController::SendEdit() { - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -127,7 +137,7 @@ void AlienwareAW510KController::SendEdit() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, 65); + hid_write(dev, usb_buf, 65); /*-----------------------------------------------------*\ | Delay 2 milliseconds | @@ -137,7 +147,7 @@ void AlienwareAW510KController::SendEdit() void AlienwareAW510KController::SendInitialize() { - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -162,7 +172,7 @@ void AlienwareAW510KController::SendInitialize() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, 65); + hid_write(dev, usb_buf, 65); /*-----------------------------------------------------*\ | Delay 2 milliseconds | @@ -216,7 +226,7 @@ void AlienwareAW510KController::SendDirectOn std::vector &frame_data ) { - SendfeatureReport(0x0E, frame_data.size(), 0x00, 0x01); + SendfeatureReport(0x0E, (unsigned char)frame_data.size(), 0x00, 0x01); /*-----------------------------------------------*\ | To Guarantee the data are always %4 =0 append | @@ -296,7 +306,7 @@ void AlienwareAW510KController::SendDirectOn void AlienwareAW510KController::SetMode ( unsigned char mode, - unsigned short speed, + unsigned char speed, unsigned char direction, unsigned char colorMode, unsigned char red, @@ -318,7 +328,7 @@ void AlienwareAW510KController::UpdateSingleLED { SendfeatureReport(0x0E, 0x01, 0x00, 0x01); - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -348,7 +358,7 @@ void AlienwareAW510KController::UpdateSingleLED /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, 65); + hid_write(dev, usb_buf, 65); /*-----------------------------------------------------*\ | Delay 20 milliseconds | @@ -360,7 +370,7 @@ void AlienwareAW510KController::SendMode ( unsigned char /*zone*/, unsigned char mode, - unsigned short speed, + unsigned char speed, unsigned char direction, unsigned char colorMode, unsigned char red, @@ -368,7 +378,7 @@ void AlienwareAW510KController::SendMode unsigned char blue ) { - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -394,13 +404,13 @@ void AlienwareAW510KController::SendMode /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, 65); + hid_write(dev, usb_buf, 65); } void AlienwareAW510KController::SetMorphMode ( unsigned char mode, - unsigned short speed, + unsigned char speed, unsigned char red1, unsigned char green1, unsigned char blue1, @@ -409,7 +419,7 @@ void AlienwareAW510KController::SetMorphMode unsigned char blue2 ) { - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -438,5 +448,5 @@ void AlienwareAW510KController::SetMorphMode /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, 65); + hid_write(dev, usb_buf, 65); } diff --git a/Controllers/AlienwareKeyboardController/AlienwareAW510KController.h b/Controllers/AlienwareKeyboardController/AlienwareAW510KController/AlienwareAW510KController.h similarity index 83% rename from Controllers/AlienwareKeyboardController/AlienwareAW510KController.h rename to Controllers/AlienwareKeyboardController/AlienwareAW510KController/AlienwareAW510KController.h index b7c008d0..38e8998d 100644 --- a/Controllers/AlienwareKeyboardController/AlienwareAW510KController.h +++ b/Controllers/AlienwareKeyboardController/AlienwareAW510KController/AlienwareAW510KController.h @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| AlienwareAW510KController.h | -| | -| Definitions and types for alienware | -| AW510K Keyboard | -| | -| Mohamad Sallal - msallal 05/22/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| AlienwareAW510KController.h | +| | +| Driver for Alienware AW510K keyboard | +| | +| Mohamad Sallal (msallal) 22 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + enum { ALIENWARE_AW510K_ZONE_MODE_KEYBOARD = 0x01, @@ -76,10 +77,11 @@ struct SelectedKeys class AlienwareAW510KController { public: - AlienwareAW510KController(hid_device* dev_handle, const char* path); + AlienwareAW510KController(hid_device* dev_handle, const char* path, std::string dev_name); ~AlienwareAW510KController(); std::string GetDeviceLocation(); + std::string GetDeviceName(); std::string GetSerialString(); void SendInitialize(); @@ -110,7 +112,7 @@ public: void SetMode ( unsigned char mode, - unsigned short speed, + unsigned char speed, unsigned char direction, unsigned char colorMode, unsigned char red, @@ -121,7 +123,7 @@ public: void SetMorphMode ( unsigned char mode, - unsigned short speed, + unsigned char speed, unsigned char red1, unsigned char green1, unsigned char blue1, @@ -141,12 +143,13 @@ public: private: hid_device* dev; std::string location; + std::string name; void SendMode ( unsigned char zone, unsigned char mode, - unsigned short speed, + unsigned char speed, unsigned char direction, unsigned char colorMode, unsigned char red, diff --git a/Controllers/AlienwareKeyboardController/RGBController_AlienwareAW510K.cpp b/Controllers/AlienwareKeyboardController/AlienwareAW510KController/RGBController_AlienwareAW510K.cpp similarity index 96% rename from Controllers/AlienwareKeyboardController/RGBController_AlienwareAW510K.cpp rename to Controllers/AlienwareKeyboardController/AlienwareAW510KController/RGBController_AlienwareAW510K.cpp index 1477e422..551c9fd9 100644 --- a/Controllers/AlienwareKeyboardController/RGBController_AlienwareAW510K.cpp +++ b/Controllers/AlienwareKeyboardController/AlienwareAW510KController/RGBController_AlienwareAW510K.cpp @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_AlienwareAW510K.cpp | -| | -| Generic RGB Interface for alienware | -| AW510K Keyboard | -| | -| Mohamad Sallal - msallal 05/22/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AlienwareAW510K.cpp | +| | +| RGBController for Alienware AW510K keyboard | +| | +| Mohamad Sallal (msallal) 22 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include "RGBControllerKeyNames.h" #include "RGBController_AlienwareAW510K.h" -#include //0xFFFFFFFF indicates an unused entry in matrix #define NA 0xFFFFFFFF @@ -45,9 +47,9 @@ typedef struct const char * name; const unsigned char zone; const unsigned char idx; -} led_type; +} aw510k_led_type; -static const led_type led_names[] = +static const aw510k_led_type led_names[] = { /* Key Label Zone, Index */ { KEY_EN_ESCAPE, ALIENWARE_AW510K_ZONE_DIRECT_KEYBOARD, 0xB0 }, @@ -173,7 +175,7 @@ RGBController_AlienwareAW510K::RGBController_AlienwareAW510K(AlienwareAW510KCont { controller = controller_ptr; - name = "Alienware AW510K Keyboard Device"; + name = controller->GetDeviceName(); vendor = "Alienware"; type = DEVICE_TYPE_KEYBOARD; description = "Alienware AW510K Keyboard Device"; diff --git a/Controllers/AlienwareKeyboardController/AlienwareAW510KController/RGBController_AlienwareAW510K.h b/Controllers/AlienwareKeyboardController/AlienwareAW510KController/RGBController_AlienwareAW510K.h new file mode 100644 index 00000000..6f9dea3f --- /dev/null +++ b/Controllers/AlienwareKeyboardController/AlienwareAW510KController/RGBController_AlienwareAW510K.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_AlienwareAW510K.h | +| | +| RGBController for Alienware AW510K keyboard | +| | +| Mohamad Sallal (msallal) 22 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AlienwareAW510KController.h" + +class RGBController_AlienwareAW510K : public RGBController +{ +public: + RGBController_AlienwareAW510K(AlienwareAW510KController* controller_ptr); + ~RGBController_AlienwareAW510K(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + AlienwareAW510KController* controller; + std::vector current_colors; +}; diff --git a/Controllers/AlienwareKeyboardController/AlienwareKeyboardControllerDetect.cpp b/Controllers/AlienwareKeyboardController/AlienwareKeyboardControllerDetect.cpp index dbceb6ab..7ceb9e41 100644 --- a/Controllers/AlienwareKeyboardController/AlienwareKeyboardControllerDetect.cpp +++ b/Controllers/AlienwareKeyboardController/AlienwareKeyboardControllerDetect.cpp @@ -1,18 +1,29 @@ +/*---------------------------------------------------------*\ +| AlienwareKeyboardControllerDetect.cpp | +| | +| Detector for Alienware Keyboard | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "AlienwareAW510KController.h" -#include "RGBController.h" +#include "AlienwareAW410KController.h" #include "RGBController_AlienwareAW510K.h" -#include +#include "RGBController_AlienwareAW410K.h" /*-----------------------------------------------------*\ | Alienware vendor ID | \*-----------------------------------------------------*/ -#define ALIENWARE_VID 0x04F2 +#define ALIENWARE_VID 0x04F2 /*-----------------------------------------------------*\ | Keyboard product IDs | \*-----------------------------------------------------*/ -#define ALIENWARE_AW510K_PID 0x1830 +#define ALIENWARE_AW510K_PID 0x1830 +#define ALIENWARE_AW410K_PID 0x1968 /******************************************************************************************\ * * @@ -27,12 +38,25 @@ void DetectAlienwareAW510KControllers(hid_device_info* info, const std::string& hid_device* dev = hid_open_path(info->path); if( dev ) { - AlienwareAW510KController* controller = new AlienwareAW510KController(dev, info->path); + AlienwareAW510KController* controller = new AlienwareAW510KController(dev, info->path, name); RGBController_AlienwareAW510K* rgb_controller = new RGBController_AlienwareAW510K(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } -} /* DetectAlienwareKeyboardControllers() */ +} + +void DetectAlienwareAW410KControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + if( dev ) + { + AlienwareAW410KController* controller = new AlienwareAW410KController(dev, info->path, name); + RGBController_AlienwareAW410K* rgb_controller = new RGBController_AlienwareAW410K(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +}/* DetectAlienwareKeyboardControllers() */ REGISTER_HID_DETECTOR_IPU("Alienware AW510K", DetectAlienwareAW510KControllers, ALIENWARE_VID, ALIENWARE_AW510K_PID, 0x02, 0xFF00, 0x01); +REGISTER_HID_DETECTOR_IPU("Alienware AW410K", DetectAlienwareAW410KControllers, ALIENWARE_VID, ALIENWARE_AW410K_PID, 0x02, 0xFF00, 0x01); diff --git a/Controllers/AlienwareKeyboardController/RGBController_AlienwareAW510K.h b/Controllers/AlienwareKeyboardController/RGBController_AlienwareAW510K.h deleted file mode 100644 index 00c6f3ff..00000000 --- a/Controllers/AlienwareKeyboardController/RGBController_AlienwareAW510K.h +++ /dev/null @@ -1,34 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AlienwareAW510K.h | -| | -| Generic RGB Interface for Alienware | -| AW510K keyboard | -| | -| Mohamad Sallal - msallal 05/22/2021 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "AlienwareAW510KController.h" - -class RGBController_AlienwareAW510K : public RGBController -{ -public: - RGBController_AlienwareAW510K(AlienwareAW510KController* controller_ptr); - ~RGBController_AlienwareAW510K(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - AlienwareAW510KController* controller; - std::vector current_colors; -}; diff --git a/Controllers/AlienwareMonitorController/AlienwareAW3423DWFController.cpp b/Controllers/AlienwareMonitorController/AlienwareAW3423DWFController.cpp new file mode 100644 index 00000000..d839811c --- /dev/null +++ b/Controllers/AlienwareMonitorController/AlienwareAW3423DWFController.cpp @@ -0,0 +1,183 @@ +/*---------------------------------------------------------*\ +| AlienwareAW3423DWFController.cpp | +| | +| Driver for the Alienware AW3423DWF monitor | +| | +| Ferréol DUBOIS COLI (Fefe_du_973) 23 Jan 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include + +#include "AlienwareAW3423DWFController.h" +#include "StringUtils.h" + +AlienwareAW3423DWFController::AlienwareAW3423DWFController(hid_device *dev_handle, const char *path) : dev(dev_handle), location(path){} + +void AlienwareAW3423DWFController::SendControlPacket(const unsigned char *data, size_t length) +{ + unsigned char buffer[256] = {0x00}; + memcpy(buffer + 1, data, length); + + hid_write(dev, buffer, length + 1); +} + +std::vector AlienwareAW3423DWFController::GetReportResponse() +{ + uint8_t buffer[193]; + + memset(buffer, 0, 193); + + hid_get_input_report(dev, buffer, 193); + + return std::vector(buffer + 1, buffer + 18); +} + +void AlienwareAW3423DWFController::PerformLogin() +{ + unsigned char init_packet[64] = + { + 0x40, 0xE1, 0x01 + }; + SendControlPacket(init_packet, 4); + + std::vector response = GetReportResponse(); + + std::vector key = GenerateKey(response); + + unsigned char login_packet[192] = {0x00}; + login_packet[0] = 0x40; + login_packet[1] = 0xE1; + login_packet[2] = 0x02; + memcpy(login_packet + 64, key.data(), key.size()); + + SendControlPacket(login_packet, 192); +} + +void AlienwareAW3423DWFController::SendColor(unsigned char led_id, unsigned char r, unsigned char g, unsigned char b) +{ + unsigned char led_id_2 = (led_id == 0x01) ? 0xf6 : (led_id == 0x02) ? 0xf5 + : (led_id == 0x08) ? 0xff + : 0xfc; + PerformLogin(); + + unsigned char color_packet[192] = {0x00}; + + color_packet[0] = 0x40; + color_packet[1] = 0xC6; + color_packet[6] = 0x0A; + color_packet[8] = 0x6E; + color_packet[10] = 0x82; + color_packet[64] = 0x51; + color_packet[65] = 0x87; + color_packet[66] = 0xD0; + color_packet[67] = 0x04; + + color_packet[68] = led_id; + color_packet[69] = r; + color_packet[70] = g; + color_packet[71] = b; + color_packet[72] = 0x64; + color_packet[73] = led_id_2; + + SendControlPacket(color_packet, 192); + + std::this_thread::sleep_for(std::chrono::milliseconds(200)); +} + +std::vector AlienwareAW3423DWFController::GenerateKey( + const std::vector &response) +{ + std::vector syn_key(8, 0); + + const std::vector oem_key = { + 0xf5, 0x3f, 0xc1, 0x39, 0x44, 0x3a, 0x31, 0x79, 0x0d, 0xb1, 0x82, 0x76 + }; + + size_t sk_idx = 0, ok_idx = 0; + while(ok_idx < oem_key.size() && sk_idx < 8) + { + unsigned char ok_sub_len = (oem_key[ok_idx] & 1) + ((oem_key[ok_idx] & 0x10) >> 4); + + for(unsigned int i = 0; i < ok_sub_len && sk_idx < 8; i++) + { + syn_key[sk_idx] = oem_key[ok_idx + 1] ^ oem_key[ok_idx]; + ok_idx++; + sk_idx++; + } + ok_idx++; + } + + std::vector out_buffer; + + uint16_t v15 = static_cast(response[15]) | + (static_cast(response[0]) << 8); + bool parity_odd = (std::bitset<16>(v15).count() % 2 != 0); + + if(parity_odd) + { + size_t end = std::min(8, response.size()); + out_buffer = std::vector(response.begin(), response.begin() + end); + + if(response.size() > 14) + { + unsigned char idx = response[14] & 0x07; + if((idx + 8) < (unsigned char)response.size()) + { + out_buffer[idx] ^= response[idx + 8]; + } + } + } + else + { + size_t start = std::min(8, response.size()); + size_t end = std::min(start + 8, response.size()); + out_buffer = std::vector(response.begin() + start, response.begin() + end); + + if(response.size() > 6) + { + unsigned char idx = response[6] & 0x07; + if(idx < response.size()) + { + out_buffer[idx] ^= response[idx]; + } + } + } + + for(size_t i = 0; i < 8 && i < out_buffer.size(); i++) + { + syn_key[i] ^= out_buffer[i]; + } + + return syn_key; +} + +AlienwareAW3423DWFController::~AlienwareAW3423DWFController() +{ + if(dev) + { + hid_close(dev); + dev = nullptr; + } +} + +std::string AlienwareAW3423DWFController::GetLocation() +{ + return "HID: " + location; +} + +std::string AlienwareAW3423DWFController::GetSerialString() +{ + wchar_t serial[256]; + if(hid_get_serial_number_string(dev, serial, 256) >= 0) + { + std::wstring ws(serial); + return StringUtils::wstring_to_string(ws); + } + return ""; +} diff --git a/Controllers/AlienwareMonitorController/AlienwareAW3423DWFController.h b/Controllers/AlienwareMonitorController/AlienwareAW3423DWFController.h new file mode 100644 index 00000000..49e8362f --- /dev/null +++ b/Controllers/AlienwareMonitorController/AlienwareAW3423DWFController.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------*\ +| AlienwareAW3423DWFController.h | +| | +| Driver for the Alienware AW3423DWF monitor | +| | +| Ferréol DUBOIS COLI (Fefe_du_973) 23 Jan 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include + +class AlienwareAW3423DWFController +{ +public: + AlienwareAW3423DWFController(hid_device* dev_handle, const char* path); + ~AlienwareAW3423DWFController(); + + std::string GetLocation(); + std::string GetSerialString(); + void SendColor(unsigned char led_id, unsigned char r, unsigned char g, unsigned char b); + +private: + hid_device* dev; + std::string location; + + static const std::vector> OEM_KEYS; + + void PerformLogin(); + std::vector GenerateKey(const std::vector& response); + void SendControlPacket(const unsigned char* data, size_t length); + std::vector GetReportResponse(); +}; diff --git a/Controllers/AlienwareMonitorController/AlienwareMonitorController.cpp b/Controllers/AlienwareMonitorController/AlienwareMonitorController.cpp new file mode 100644 index 00000000..77984588 --- /dev/null +++ b/Controllers/AlienwareMonitorController/AlienwareMonitorController.cpp @@ -0,0 +1,146 @@ +/*---------------------------------------------------------*\ +| AlienwareMonitorController.cpp | +| | +| Detector for Alienware monitors | +| | +| Adam Honse (CalcProgrammer1) 08 May 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include + +#include "AlienwareMonitorController.h" + +AlienwareMonitorController::AlienwareMonitorController(hid_device *dev_handle, const char *path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + + Initialize(); +} + +AlienwareMonitorController::~AlienwareMonitorController() +{ + hid_close(dev); +} + +std::string AlienwareMonitorController::GetLocation() +{ + return("HID: " + location); +} + +std::string AlienwareMonitorController::GetName() +{ + return(name); +} + +std::string AlienwareMonitorController::GetSerialString() +{ + return(""); +} + +void fillInChecksum(unsigned char *packet) +{ + unsigned char checksum = 110; + + for(unsigned int index = 5; index <= 13; index++) + { + checksum ^= packet[index]; + } + + packet[14] = checksum; +} + +void AlienwareMonitorController::SendColor(unsigned char led_id, unsigned char r, unsigned char g, unsigned char b) +{ + unsigned char packet[65]; + + memset(packet, 0xFF, sizeof(packet)); + + packet[0] = 0x00; + packet[1] = 0x92; + packet[2] = 0x37; + packet[3] = 0x0a; + packet[4] = 0x00; + packet[5] = 0x51; + packet[6] = 0x87; + packet[7] = 0xd0; + packet[8] = 0x04; + + packet[9] = led_id; + packet[10] = r; + packet[11] = g; + packet[12] = b; + packet[13] = 0x64; + + fillInChecksum(packet); + + hid_write(dev, packet, sizeof(packet)); + + /*-----------------------------------------------------*\ + | Delay 50 milliseconds | + \*-----------------------------------------------------*/ + std::this_thread::sleep_for(std::chrono::milliseconds(50)); +} + +void AlienwareMonitorController::Initialize() +{ + unsigned char packet[65]; + + memset(packet, 0xFF, sizeof(packet)); + + packet[0] = 0x00; + packet[1] = 0x95; + packet[2] = 0x00; + packet[3] = 0x00; + packet[4] = 0x00; + + hid_write(dev, packet, sizeof(packet)); + + /*-----------------------------------------------------*\ + | Delay 50 milliseconds | + \*-----------------------------------------------------*/ + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + + memset(packet, 0xFF, sizeof(packet)); + + packet[0] = 0x00; + packet[1] = 0x92; + packet[2] = 0x37; + packet[3] = 0x08; + packet[4] = 0x00; + packet[5] = 0x51; + packet[6] = 0x85; + packet[7] = 0x01; + packet[8] = 0xFE; + packet[9] = 0x03; + packet[10] = 0x00; + packet[11] = 0x06; + packet[12] = 0x40; + + hid_write(dev, packet, sizeof(packet)); + + /*-----------------------------------------------------*\ + | Delay 50 milliseconds | + \*-----------------------------------------------------*/ + std::this_thread::sleep_for(std::chrono::milliseconds(50)); + + memset(packet, 0x00, sizeof(packet)); + + packet[0] = 0x00; + packet[1] = 0x93; + packet[2] = 0x37; + packet[3] = 0x12; + + hid_write(dev, packet, sizeof(packet)); + + /*-----------------------------------------------------*\ + | Delay 50 milliseconds | + \*-----------------------------------------------------*/ + std::this_thread::sleep_for(std::chrono::milliseconds(50)); +} diff --git a/Controllers/AlienwareMonitorController/AlienwareMonitorController.h b/Controllers/AlienwareMonitorController/AlienwareMonitorController.h new file mode 100644 index 00000000..bb52d61c --- /dev/null +++ b/Controllers/AlienwareMonitorController/AlienwareMonitorController.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| AlienwareMonitorController.h | +| | +| Detector for Alienware monitors | +| | +| Adam Honse (CalcProgrammer1) 08 May 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include + +class AlienwareMonitorController +{ +public: +AlienwareMonitorController(hid_device* dev_handle, const char* path, std::string dev_name); + ~AlienwareMonitorController(); + + std::string GetLocation(); + std::string GetName(); + std::string GetSerialString(); + void SendColor(unsigned char led_id, unsigned char r, unsigned char g, unsigned char b); + +private: + hid_device* dev; + std::string location; + std::string name; + + void Initialize(); +}; diff --git a/Controllers/AlienwareMonitorController/AlienwareMonitorControllerDetect.cpp b/Controllers/AlienwareMonitorController/AlienwareMonitorControllerDetect.cpp new file mode 100644 index 00000000..64d04afa --- /dev/null +++ b/Controllers/AlienwareMonitorController/AlienwareMonitorControllerDetect.cpp @@ -0,0 +1,66 @@ +/*---------------------------------------------------------*\ +| AlienwareMonitorControllerDetect.cpp | +| | +| Detector for Alienware monitors | +| | +| Adam Honse (CalcProgrammer1) 08 May 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "AlienwareAW3423DWFController.h" +#include "AlienwareMonitorController.h" +#include "RGBController_AlienwareAW3423DWF.h" +#include "RGBController_AlienwareMonitor.h" +#include + +/*---------------------------------------------------------*\ +| Alienware Vendor ID | +\*---------------------------------------------------------*/ +#define ALIENWARE_VID 0x187C + +/*---------------------------------------------------------*\ +| Alienware Vendor ID | +\*---------------------------------------------------------*/ +#define ALIENWARE_AW3423DWF_PID 0x100E +#define ALIENWARE_AW3225QF_PID 0x1013 +#define ALIENWARE_USAGE_PAGE 0xFFDA +#define ALIENWARE_USAGE 0x00DA + +/******************************************************************************************\ +* * +* AlienwareAW3423DWFControllerDetect * +* * +* Tests the USB address to see if an Alienware AW3423DWF exists there. * +* * +\******************************************************************************************/ + +void DetectAlienwareAW3423DWFControllers(hid_device_info* info, const std::string&) +{ + hid_device* dev = hid_open_path(info->path); + if(dev) + { + AlienwareAW3423DWFController* controller = new AlienwareAW3423DWFController(dev, info->path); + RGBController_AlienwareAW3423DWF* rgb_controller = new RGBController_AlienwareAW3423DWF(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectAlienwareMonitorControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + AlienwareMonitorController* controller = new AlienwareMonitorController(dev, info->path, name); + RGBController_AlienwareMonitor* rgb_controller = new RGBController_AlienwareMonitor(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR("Alienware AW3423DWF", DetectAlienwareAW3423DWFControllers, ALIENWARE_VID, ALIENWARE_AW3423DWF_PID); +REGISTER_HID_DETECTOR("Alienware AW3225QF", DetectAlienwareMonitorControllers, ALIENWARE_VID, ALIENWARE_AW3225QF_PID); diff --git a/Controllers/AlienwareMonitorController/RGBController_AlienwareAW3423DWF.cpp b/Controllers/AlienwareMonitorController/RGBController_AlienwareAW3423DWF.cpp new file mode 100644 index 00000000..0bb5e199 --- /dev/null +++ b/Controllers/AlienwareMonitorController/RGBController_AlienwareAW3423DWF.cpp @@ -0,0 +1,141 @@ +/*---------------------------------------------------------*\ +| RGBController_AlienwareAW3423DWF.cpp | +| | +| RGBController for the Alienware AW3423DWF monitor | +| | +| Ferréol DUBOIS COLI (Fefe_du_973) 23 Jan 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_AlienwareAW3423DWF.h" + +/**------------------------------------------------------------------*\ + @name AW3423DWF + @category Accessory + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectAlienwareAW3423DWFControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_AlienwareAW3423DWF::RGBController_AlienwareAW3423DWF(AlienwareAW3423DWFController* controller_ptr) +{ + controller = controller_ptr; + + name = "Alienware AW3423DWF"; + vendor = "Alienware"; + type = DEVICE_TYPE_MONITOR; + description = "Alienware AW3423DWF Monitor Device"; + location = controller->GetLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + active_mode = 0; + + SetupZones(); +} + +RGBController_AlienwareAW3423DWF::~RGBController_AlienwareAW3423DWF() +{ + delete controller; +} + +void RGBController_AlienwareAW3423DWF::SetupZones() +{ + zone Logo; + Logo.name = "Logo"; + Logo.type = ZONE_TYPE_SINGLE; + Logo.leds_min = 1; + Logo.leds_max = 1; + Logo.leds_count = 1; + Logo.matrix_map = NULL; + zones.push_back(Logo); + + led Logo_LED; + Logo_LED.name = "Logo"; + Logo_LED.value = 0x01; + leds.push_back(Logo_LED); + + zone Number; + Number.name = "Number"; + Number.type = ZONE_TYPE_SINGLE; + Number.leds_min = 1; + Number.leds_max = 1; + Number.leds_count = 1; + Number.matrix_map = NULL; + zones.push_back(Number); + + led Number_LED; + Number_LED.name = "Number"; + Number_LED.value = 0x02; + leds.push_back(Number_LED); + + zone PowerButton; + PowerButton.name = "Power Button"; + PowerButton.type = ZONE_TYPE_SINGLE; + PowerButton.leds_min = 1; + PowerButton.leds_max = 1; + PowerButton.leds_count = 1; + PowerButton.matrix_map = NULL; + zones.push_back(PowerButton); + + led PowerButton_LED; + PowerButton_LED.name = "Power Button"; + PowerButton_LED.value = 0x08; + leds.push_back(PowerButton_LED); + + SetupColors(); +} + +void RGBController_AlienwareAW3423DWF::ResizeZone(int /*zone*/, int /*new_size*/) +{ +} + +void RGBController_AlienwareAW3423DWF::DeviceUpdateLEDs() +{ + /*-----------------------------------------------------*\ + | If all three colors are the same value, speed up the | + | direct mode by using the ALL target (0x0B) instead of | + | setting each LED individually. | + \*-----------------------------------------------------*/ + if((colors[0] == colors[1]) && (colors[1] == colors[2])) + { + unsigned char red = RGBGetRValue(colors[0]); + unsigned char grn = RGBGetGValue(colors[0]); + unsigned char blu = RGBGetBValue(colors[0]); + controller->SendColor(0x0B, red, grn, blu); + } + else + { + for(unsigned int led_idx = 0; led_idx < leds.size(); led_idx++) + { + UpdateSingleLED(led_idx); + } + } +} + +void RGBController_AlienwareAW3423DWF::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_AlienwareAW3423DWF::UpdateSingleLED(int led) +{ + unsigned char red = RGBGetRValue(colors[led]); + unsigned char grn = RGBGetGValue(colors[led]); + unsigned char blu = RGBGetBValue(colors[led]); + controller->SendColor(leds[led].value, red, grn, blu); +} + +void RGBController_AlienwareAW3423DWF::DeviceUpdateMode() +{ +} diff --git a/Controllers/AlienwareMonitorController/RGBController_AlienwareAW3423DWF.h b/Controllers/AlienwareMonitorController/RGBController_AlienwareAW3423DWF.h new file mode 100644 index 00000000..84f713e4 --- /dev/null +++ b/Controllers/AlienwareMonitorController/RGBController_AlienwareAW3423DWF.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_AlienwareAW3423DWF.h | +| | +| RGBController for the Alienware AW3423DWF monitor | +| | +| Ferréol DUBOIS COLI (Fefe_du_973) 23 Jan 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "AlienwareAW3423DWFController.h" +#include "RGBController.h" + +class RGBController_AlienwareAW3423DWF : public RGBController +{ +public: + explicit RGBController_AlienwareAW3423DWF(AlienwareAW3423DWFController* controller_ptr); + ~RGBController_AlienwareAW3423DWF(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + AlienwareAW3423DWFController* controller; +}; diff --git a/Controllers/AlienwareMonitorController/RGBController_AlienwareMonitor.cpp b/Controllers/AlienwareMonitorController/RGBController_AlienwareMonitor.cpp new file mode 100644 index 00000000..7add26d3 --- /dev/null +++ b/Controllers/AlienwareMonitorController/RGBController_AlienwareMonitor.cpp @@ -0,0 +1,143 @@ +/*---------------------------------------------------------*\ +| RGBController_AlienwareMonitor.cpp | +| | +| RGBController for Alienware monitors | +| | +| Adam Honse (CalcProgrammer1) 08 May 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_AlienwareMonitor.h" + +/**------------------------------------------------------------------*\ + @name Alienware Monitor + @category Accessory + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectAlienwareMonitorControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_AlienwareMonitor::RGBController_AlienwareMonitor(AlienwareMonitorController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + description = "Alienware Monitor"; + vendor = "Alienware"; + type = DEVICE_TYPE_MONITOR; + location = controller->GetLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + active_mode = 0; + + SetupZones(); +} + +RGBController_AlienwareMonitor::~RGBController_AlienwareMonitor() +{ + delete controller; +} + +void RGBController_AlienwareMonitor::SetupZones() +{ + zone Logo; + Logo.name = "Logo"; + Logo.type = ZONE_TYPE_SINGLE; + Logo.leds_min = 1; + Logo.leds_max = 1; + Logo.leds_count = 1; + Logo.matrix_map = NULL; + zones.push_back(Logo); + + led Logo_LED; + Logo_LED.name = "Logo"; + Logo_LED.value = 0x01; + leds.push_back(Logo_LED); + + zone Number; + Number.name = "Number"; + Number.type = ZONE_TYPE_SINGLE; + Number.leds_min = 1; + Number.leds_max = 1; + Number.leds_count = 1; + Number.matrix_map = NULL; + zones.push_back(Number); + + led Number_LED; + Number_LED.name = "Number"; + Number_LED.value = 0x02; + leds.push_back(Number_LED); + + zone PowerButton; + PowerButton.name = "Power Button"; + PowerButton.type = ZONE_TYPE_SINGLE; + PowerButton.leds_min = 1; + PowerButton.leds_max = 1; + PowerButton.leds_count = 1; + PowerButton.matrix_map = NULL; + zones.push_back(PowerButton); + + led PowerButton_LED; + PowerButton_LED.name = "Power Button"; + PowerButton_LED.value = 0x08; + leds.push_back(PowerButton_LED); + + SetupColors(); +} + +void RGBController_AlienwareMonitor::ResizeZone(int /*zone*/, int /*new_size*/) +{ + +} + +void RGBController_AlienwareMonitor::DeviceUpdateLEDs() +{ + /*-----------------------------------------------------*\ + | If all three colors are the same value, speed up the | + | direct mode by using the ALL target (0x0B) instead of | + | setting each LED individually. | + \*-----------------------------------------------------*/ + if((colors[0] == colors[1]) && (colors[1] == colors[2])) + { + unsigned char red = RGBGetRValue(colors[0]); + unsigned char grn = RGBGetGValue(colors[0]); + unsigned char blu = RGBGetBValue(colors[0]); + controller->SendColor(0x0B, red, grn, blu); + } + else + { + for(unsigned int led_idx = 0; led_idx < leds.size(); led_idx++) + { + UpdateSingleLED(led_idx); + } + } +} + +void RGBController_AlienwareMonitor::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_AlienwareMonitor::UpdateSingleLED(int led) +{ + unsigned char red = RGBGetRValue(colors[led]); + unsigned char grn = RGBGetGValue(colors[led]); + unsigned char blu = RGBGetBValue(colors[led]); + controller->SendColor(leds[led].value, red, grn, blu); +} + +void RGBController_AlienwareMonitor::DeviceUpdateMode() +{ + +} diff --git a/Controllers/AlienwareMonitorController/RGBController_AlienwareMonitor.h b/Controllers/AlienwareMonitorController/RGBController_AlienwareMonitor.h new file mode 100644 index 00000000..80695b7e --- /dev/null +++ b/Controllers/AlienwareMonitorController/RGBController_AlienwareMonitor.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_AlienwareMonitor.h | +| | +| RGBController for Alienware monitors | +| | +| Adam Honse (CalcProgrammer1) 08 May 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AlienwareMonitorController.h" + +class RGBController_AlienwareMonitor : public RGBController +{ +public: +RGBController_AlienwareMonitor(AlienwareMonitorController* controller_ptr); + ~RGBController_AlienwareMonitor(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: +AlienwareMonitorController* controller; +}; diff --git a/Controllers/AnnePro2Controller/AnnePro2Controller.cpp b/Controllers/AnnePro2Controller/AnnePro2Controller.cpp index da44a796..7c1a48b9 100644 --- a/Controllers/AnnePro2Controller/AnnePro2Controller.cpp +++ b/Controllers/AnnePro2Controller/AnnePro2Controller.cpp @@ -1,32 +1,36 @@ -/*-----------------------------------------*\ -| AnnePro2Controller.cpp | -| | -| Driver for Obins Lab AnnePro2 keyboard | -| | -| Sergey Gavrilov (DrZlo13) 06/06/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| AnnePro2Controller.cpp | +| | +| Driver for Obins Lab AnnePro2 keyboard | +| | +| Sergey Gavrilov (DrZlo13) 06 Jun 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "AnnePro2Controller.h" +#include "StringUtils.h" using namespace std::chrono_literals; -AnnePro2Controller::AnnePro2Controller(hid_device* dev_handle, const char* path) +AnnePro2Controller::AnnePro2Controller(hid_device* dev_handle, const char* path) { dev = dev_handle; location = path; } -AnnePro2Controller::~AnnePro2Controller() +AnnePro2Controller::~AnnePro2Controller() { hid_close(dev); } -std::string AnnePro2Controller::GetDeviceLocation() +std::string AnnePro2Controller::GetDeviceLocation() { return("HID: " + location); } -std::string AnnePro2Controller::GetSerialString() +std::string AnnePro2Controller::GetSerialString() { wchar_t serial_string[128]; int ret = hid_get_serial_number_string(dev, serial_string, 128); @@ -36,13 +40,10 @@ std::string AnnePro2Controller::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } -void AnnePro2Controller::SendDirect(unsigned char frame_count, unsigned char * frame_data) +void AnnePro2Controller::SendDirect(unsigned char frame_count, unsigned char * frame_data) { /*-------------------------------------------------------------*\ | Reverse engineered by https://github.com/manualmanul/Annemone | @@ -74,7 +75,7 @@ void AnnePro2Controller::SendDirect(unsigned char frame_count, unsigned char * f { const unsigned char e = (messages_to_send_amount << 4) + p; const unsigned char a = ((messages_to_send_amount - 1) == p) ? val_2 + real_command_info_length : max_message_length + real_command_info_length; - + /*---------------------------------------------------------*\ | Service data | \*---------------------------------------------------------*/ diff --git a/Controllers/AnnePro2Controller/AnnePro2Controller.h b/Controllers/AnnePro2Controller/AnnePro2Controller.h index f09faf16..7d0f65fe 100644 --- a/Controllers/AnnePro2Controller/AnnePro2Controller.h +++ b/Controllers/AnnePro2Controller/AnnePro2Controller.h @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| AnnePro2Controller.h | -| | -| Driver for Obins Lab AnnePro2 keyboard | -| | -| Sergey Gavrilov (DrZlo13) 06/06/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| AnnePro2Controller.h | +| | +| Driver for Obins Lab AnnePro2 keyboard | +| | +| Sergey Gavrilov (DrZlo13) 06 Jun 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include "RGBController.h" #include #include -#include - -#pragma once +#include +#include "RGBController.h" class AnnePro2Controller { @@ -33,4 +34,4 @@ public: private: hid_device* dev; std::string location; -}; \ No newline at end of file +}; diff --git a/Controllers/AnnePro2Controller/AnnePro2ControllerDetect.cpp b/Controllers/AnnePro2Controller/AnnePro2ControllerDetect.cpp index 5015d8f7..9cb84c5d 100644 --- a/Controllers/AnnePro2Controller/AnnePro2ControllerDetect.cpp +++ b/Controllers/AnnePro2Controller/AnnePro2ControllerDetect.cpp @@ -1,14 +1,33 @@ +/*---------------------------------------------------------*\ +| AnnePro2ControllerDetect.cpp | +| | +| Detector for Obins Lab AnnePro2 keyboard | +| | +| Sergey Gavrilov (DrZlo13) 06 Jun 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "AnnePro2Controller.h" -#include "RGBController.h" #include "RGBController_AnnePro2.h" -#include +#include -#define ANNE_PRO_2_VID 0x04D9 -#define ANNE_PRO_2_PID_1 0x8008 -#define ANNE_PRO_2_PID_2 0x8009 -#define ANNE_PRO_2_PID_3 0xA292 -#define ANNE_PRO_2_PID_4 0xA293 +/*---------------------------------------------------------*\ +| Anne Pro 2 vendor IDs | +\*---------------------------------------------------------*/ +#define ANNE_PRO_2_VID_1 0x04D9 +#define ANNE_PRO_2_VID_2 0x3311 + +/*---------------------------------------------------------*\ +| Anne Pro 2 product IDs | +\*---------------------------------------------------------*/ +#define ANNE_PRO_2_PID_1 0x8008 +#define ANNE_PRO_2_PID_2 0x8009 +#define ANNE_PRO_2_PID_3 0xA292 +#define ANNE_PRO_2_PID_4 0xA293 +#define ANNE_PRO_2_PID_5 0xA297 /******************************************************************************************\ * * @@ -21,16 +40,18 @@ void DetectAnnePro2Controllers(hid_device_info* info, const std::string&) { hid_device* dev = hid_open_path(info->path); - if( dev ) + + if(dev) { AnnePro2Controller* controller = new AnnePro2Controller(dev, info->path); RGBController_AnnePro2* rgb_controller = new RGBController_AnnePro2(controller); - // Constructor sets the name + ResourceManager::get()->RegisterRGBController(rgb_controller); } } -REGISTER_HID_DETECTOR_I("Anne Pro 2", DetectAnnePro2Controllers, ANNE_PRO_2_VID, ANNE_PRO_2_PID_1, 1); -REGISTER_HID_DETECTOR_I("Anne Pro 2", DetectAnnePro2Controllers, ANNE_PRO_2_VID, ANNE_PRO_2_PID_2, 1); -REGISTER_HID_DETECTOR_I("Anne Pro 2", DetectAnnePro2Controllers, ANNE_PRO_2_VID, ANNE_PRO_2_PID_3, 1); -REGISTER_HID_DETECTOR_I("Anne Pro 2", DetectAnnePro2Controllers, ANNE_PRO_2_VID, ANNE_PRO_2_PID_4, 1); +REGISTER_HID_DETECTOR_I("Anne Pro 2", DetectAnnePro2Controllers, ANNE_PRO_2_VID_1, ANNE_PRO_2_PID_1, 1); +REGISTER_HID_DETECTOR_I("Anne Pro 2", DetectAnnePro2Controllers, ANNE_PRO_2_VID_1, ANNE_PRO_2_PID_2, 1); +REGISTER_HID_DETECTOR_I("Anne Pro 2", DetectAnnePro2Controllers, ANNE_PRO_2_VID_1, ANNE_PRO_2_PID_3, 1); +REGISTER_HID_DETECTOR_I("Anne Pro 2", DetectAnnePro2Controllers, ANNE_PRO_2_VID_1, ANNE_PRO_2_PID_4, 1); +REGISTER_HID_DETECTOR_I("Anne Pro 2", DetectAnnePro2Controllers, ANNE_PRO_2_VID_2, ANNE_PRO_2_PID_5, 1); diff --git a/Controllers/AnnePro2Controller/RGBController_AnnePro2.cpp b/Controllers/AnnePro2Controller/RGBController_AnnePro2.cpp index 790fd827..69a43a30 100644 --- a/Controllers/AnnePro2Controller/RGBController_AnnePro2.cpp +++ b/Controllers/AnnePro2Controller/RGBController_AnnePro2.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_AnnePro2.cpp | -| | -| Generic RGB Interface for Obins Lab | -| AnnePro2 keyboard | -| | -| Sergey Gavrilov (DrZlo13) 06/06/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AnnePro2.cpp | +| | +| RGBController for Obins Lab AnnePro2 keyboard | +| | +| Sergey Gavrilov (DrZlo13) 06 Jun 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_AnnePro2.h" @@ -40,9 +42,9 @@ typedef struct { const char * name; const unsigned char idx; -} led_type; +} annepro2_led_type; -static const led_type led_names[] = +static const annepro2_led_type led_names[] = { /* Key Label Index */ { KEY_EN_ESCAPE, 0 }, diff --git a/Controllers/AnnePro2Controller/RGBController_AnnePro2.h b/Controllers/AnnePro2Controller/RGBController_AnnePro2.h index 06dedf98..a959b978 100644 --- a/Controllers/AnnePro2Controller/RGBController_AnnePro2.h +++ b/Controllers/AnnePro2Controller/RGBController_AnnePro2.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_AnnePro2.h | -| | -| Generic RGB Interface for Obins Lab | -| AnnePro2 keyboard | -| | -| Sergey Gavrilov (DrZlo13) 06/06/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AnnePro2.h | +| | +| RGBController for Obins Lab AnnePro2 keyboard | +| | +| Sergey Gavrilov (DrZlo13) 06 Jun 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "AnnePro2Controller.h" diff --git a/Controllers/ArcticController/ArcticController.cpp b/Controllers/ArcticController/ArcticController.cpp new file mode 100644 index 00000000..8f7d2035 --- /dev/null +++ b/Controllers/ArcticController/ArcticController.cpp @@ -0,0 +1,158 @@ +/*---------------------------------------------------------*\ +| ArcticController.cpp | +| | +| Driver for Arctic devices | +| | +| Armin Wolf (Wer-Wolf) 09 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "ArcticController.h" + +using namespace std::chrono_literals; + +#define ARCTIC_COMMAND_SET_RGB 0x00 +#define ARCTIC_COMMAND_IDENTIFY 0x5C + +#define ARCTIC_RESPONSE_BUFFER_LENGTH 15 +#define ARCTIC_RESPONSE_COMMAND_OFFSET 0 +#define ARCTIC_RESPONSE_DATA_OFFSET 1 +#define ARCTIC_RESPONSE_DATA_LENGTH 12 +#define ARCTIC_RESPONSE_XOR_CSUM_OFFSET 13 +#define ARCTIC_RESPONSE_ADD_CSUM_OFFSET 14 + +#define ARCTIC_COMMAND_BUFFER_LENGTH(payload_size) (sizeof(header) + 1 + payload_size) +#define ARCTIC_COMMAND_COMMAND_OFFSET (sizeof(header)) +#define ARCTIC_COMMAND_PAYLOAD_OFFSET (sizeof(header) + 1) + +const unsigned char header[] = +{ + 0x01, + 0x02, + 0x03, + 0xFF, + 0x05, + 0xFF, + 0x02, + 0x03 +}; + +const unsigned char identify_payload[] = +{ + 0x01, + 0xFE, + 0x01, + 0xFE +}; + +ArcticController::ArcticController(const std::string &portname) +: serialport(portname.c_str(), 250000, SERIAL_PORT_PARITY_NONE, SERIAL_PORT_SIZE_8, SERIAL_PORT_STOP_BITS_2, false) +{ + port_name = portname; + serialport.serial_set_dtr(true); +} + +ArcticController::~ArcticController() +{ + serialport.serial_set_dtr(false); +} + +static void FormatCommandBuffer(char *buffer, char command) +{ + std::memcpy(buffer, header, sizeof(header)); + buffer[ARCTIC_COMMAND_COMMAND_OFFSET] = command; +} + +void ArcticController::SetChannels(std::vector colors) +{ + char* buffer = new char[ARCTIC_COMMAND_BUFFER_LENGTH(colors.size() * 3)]; + + FormatCommandBuffer(buffer, ARCTIC_COMMAND_SET_RGB); + + for(unsigned int channel = 0; channel < colors.size(); channel++) + { + const unsigned int offset = ARCTIC_COMMAND_PAYLOAD_OFFSET + channel * 3; + + buffer[offset + 0x00] = (char)std::min(254, RGBGetRValue(colors[channel])); + buffer[offset + 0x01] = (char)std::min(254, RGBGetGValue(colors[channel])); + buffer[offset + 0x02] = (char)std::min(254, RGBGetBValue(colors[channel])); + } + + serialport.serial_write(buffer, sizeof(buffer)); + + delete[] buffer; +} + +static char XORChecksum(char *data, int length) +{ + char sum = 0; + + for(int i = 0; i < length; i++) + { + sum ^= data[i]; + } + + return sum; +} + +static char AddChecksum(char *data, int length) +{ + char sum = 0; + + for(int i = 0; i < length; i++) + { + sum = (char)(sum + data[i]); + } + + return sum; +} + +bool ArcticController::IsPresent() +{ + char buffer[ARCTIC_COMMAND_BUFFER_LENGTH(sizeof(identify_payload))]; + char response[ARCTIC_RESPONSE_BUFFER_LENGTH]; + int ret; + + FormatCommandBuffer(buffer, ARCTIC_COMMAND_IDENTIFY); + std::memcpy(buffer + ARCTIC_COMMAND_PAYLOAD_OFFSET, identify_payload, sizeof(identify_payload)); + + serialport.serial_flush_rx(); + ret = serialport.serial_write(buffer, sizeof(buffer)); + if(ret != sizeof(buffer)) + { + return false; + } + + std::this_thread::sleep_for(100ms); + + ret = serialport.serial_read(response, sizeof(response)); + if(ret != sizeof(response)) + { + return false; + } + + if(response[ARCTIC_RESPONSE_COMMAND_OFFSET] != ARCTIC_COMMAND_IDENTIFY) + { + return false; + } + + if(response[ARCTIC_RESPONSE_XOR_CSUM_OFFSET] != XORChecksum(&response[ARCTIC_RESPONSE_DATA_OFFSET], ARCTIC_RESPONSE_DATA_LENGTH)) + { + return false; + } + + if(response[ARCTIC_RESPONSE_ADD_CSUM_OFFSET] != AddChecksum(&response[ARCTIC_RESPONSE_DATA_OFFSET], ARCTIC_RESPONSE_DATA_LENGTH)) + { + return false; + } + + return true; +} + +std::string ArcticController::GetLocation() +{ + return port_name; +} diff --git a/Controllers/ArcticController/ArcticController.h b/Controllers/ArcticController/ArcticController.h new file mode 100644 index 00000000..c8e7e699 --- /dev/null +++ b/Controllers/ArcticController/ArcticController.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------*\ +| ArcticController.h | +| | +| Driver for Arctic devices | +| | +| Armin Wolf (Wer-Wolf) 09 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "serial_port.h" + +class ArcticController +{ +public: + ArcticController(const std::string &portname); + ~ArcticController(); + + void SetChannels(std::vector colors); + bool IsPresent(); + + std::string GetLocation(); + +private: + std::string port_name; + serial_port serialport; +}; diff --git a/Controllers/ArcticController/ArcticControllerDetect.cpp b/Controllers/ArcticController/ArcticControllerDetect.cpp new file mode 100644 index 00000000..ccc7a9a2 --- /dev/null +++ b/Controllers/ArcticController/ArcticControllerDetect.cpp @@ -0,0 +1,48 @@ +/*---------------------------------------------------------*\ +| ArcticControllerDetect.cpp | +| | +| Detector for Arctic devices | +| | +| Armin Wolf (Wer-Wolf) 09 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "ArcticController.h" +#include "RGBController_Arctic.h" +#include "find_usb_serial_port.h" + +#define CH341_VID 0x1A86 +#define CH341_PID 0x7523 + +void DetectArcticControllers() +{ + std::vector ports = find_usb_serial_port(CH341_VID, CH341_PID); + + for(unsigned int device = 0; device < ports.size(); device++) + { + ArcticController *controller = new ArcticController(*ports[device]); + + if(controller->IsPresent()) + { + RGBController_Arctic *rgb_controller = new RGBController_Arctic(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + else + { + delete controller; + } + + delete ports[device]; + } +} + +REGISTER_DETECTOR("Arctic RGB controller", DetectArcticControllers); +/*---------------------------------------------------------------------------------------------------------*\ +| Entries for dynamic UDEV rules | +| | +| DUMMY_DEVICE_DETECTOR("Arctic RGB controller", DetectArcticControllers, 0x1A86, 0x7523 ) | +\*---------------------------------------------------------------------------------------------------------*/ diff --git a/Controllers/ArcticController/RGBController_Arctic.cpp b/Controllers/ArcticController/RGBController_Arctic.cpp new file mode 100644 index 00000000..8a92201f --- /dev/null +++ b/Controllers/ArcticController/RGBController_Arctic.cpp @@ -0,0 +1,134 @@ +/*---------------------------------------------------------*\ +| RGBController_Arctic.cpp | +| | +| RGBController for Arctic devices | +| | +| Armin Wolf (Wer-Wolf) 09 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RGBController_Arctic.h" + +using namespace std::chrono_literals; + +#define ARCTIC_NUM_CHANNELS 4 +#define ARCTIC_SLEEP_THRESHOLD 100ms +#define ARCTIC_KEEPALIVE_PERIOD 500ms /* Device requires at least 1s */ + +/**------------------------------------------------------------------*\ + @name Arctic RGB Controller Devices + @category LEDStrip + @type Serial + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectArcticControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_Arctic::RGBController_Arctic(ArcticController* controller_ptr) +{ + controller = controller_ptr; + + name = "Arctic RGB Controller"; + vendor = "Arctic"; + description = "Arctic 4-Channel RGB Controller"; + location = controller->GetLocation(); + type = DEVICE_TYPE_LEDSTRIP; + + mode DirectMode; + DirectMode.name = "Direct"; + DirectMode.value = 0; + DirectMode.flags = MODE_FLAG_HAS_PER_LED_COLOR; + DirectMode.color_mode = MODE_COLORS_PER_LED; + + modes.push_back(DirectMode); + + SetupZones(); + + keepalive_thread_run = true; + keepalive_thread = std::thread(&RGBController_Arctic::KeepaliveThreadFunction, this); +} + +RGBController_Arctic::~RGBController_Arctic() +{ + keepalive_thread_run = false; + keepalive_thread.join(); + delete controller; +} + +void RGBController_Arctic::SetupZones() +{ + for(int channel = 0; channel < ARCTIC_NUM_CHANNELS; channel++) + { + zone LedZone; + LedZone.name = "LED Strip " + std::to_string(channel); + LedZone.type = ZONE_TYPE_SINGLE; + LedZone.leds_count = 1; + LedZone.leds_min = 1; + LedZone.leds_max = 1; + LedZone.matrix_map = nullptr; + + led Led; + Led.name = LedZone.name + " LED"; + Led.value = channel; + + zones.push_back(LedZone); + leds.push_back(Led); + } + + SetupColors(); +} + +void RGBController_Arctic::ResizeZone(int /* zone */, int /* new_size */) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_Arctic::DeviceUpdateLEDs() +{ + last_update_time = std::chrono::steady_clock::now(); + + controller->SetChannels(colors); +} + +void RGBController_Arctic::UpdateZoneLEDs(int /* zone */) +{ + DeviceUpdateLEDs(); +} + +void RGBController_Arctic::UpdateSingleLED(int /* led */) +{ + DeviceUpdateLEDs(); +} + +void RGBController_Arctic::DeviceUpdateMode() +{ + /*---------------------------------------------------------*\ + | This device does not support mode updates | + \*---------------------------------------------------------*/ +} + +void RGBController_Arctic::KeepaliveThreadFunction() +{ + std::chrono::nanoseconds sleep_time; + + while(keepalive_thread_run.load()) + { + sleep_time = ARCTIC_KEEPALIVE_PERIOD - (std::chrono::steady_clock::now() - last_update_time); + if(sleep_time <= ARCTIC_SLEEP_THRESHOLD) + { + UpdateLEDs(); // Already protected thru a device update thread + std::this_thread::sleep_for(ARCTIC_KEEPALIVE_PERIOD); + } + else + { + std::this_thread::sleep_for(sleep_time); + } + } +} diff --git a/Controllers/ArcticController/RGBController_Arctic.h b/Controllers/ArcticController/RGBController_Arctic.h new file mode 100644 index 00000000..1a734cb8 --- /dev/null +++ b/Controllers/ArcticController/RGBController_Arctic.h @@ -0,0 +1,44 @@ +/*---------------------------------------------------------*\ +| RGBController_Arctic.h | +| | +| RGBController for Arctic devices | +| | +| Armin Wolf (Wer-Wolf) 09 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "ArcticController.h" +#include "RGBController.h" +#include "serial_port.h" + +class RGBController_Arctic : public RGBController +{ +public: + RGBController_Arctic(ArcticController* controller_ptr); + ~RGBController_Arctic(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + void KeepaliveThreadFunction(); + +private: + ArcticController* controller; + std::chrono::time_point last_update_time; + std::atomic keepalive_thread_run; + std::thread keepalive_thread; +}; + diff --git a/Controllers/AsusAuraCoreController/AsusAuraCoreController.cpp b/Controllers/AsusAuraCoreController/AsusAuraCoreController/AsusAuraCoreController.cpp similarity index 95% rename from Controllers/AsusAuraCoreController/AsusAuraCoreController.cpp rename to Controllers/AsusAuraCoreController/AsusAuraCoreController/AsusAuraCoreController.cpp index 79550d87..e7021974 100644 --- a/Controllers/AsusAuraCoreController/AsusAuraCoreController.cpp +++ b/Controllers/AsusAuraCoreController/AsusAuraCoreController/AsusAuraCoreController.cpp @@ -1,14 +1,17 @@ -/*-----------------------------------------*\ -| AsusAuraCoreController.cpp | -| | -| Driver for ASUS ROG Aura Core RGB | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 4/13/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| AsusAuraCoreController.cpp | +| | +| Driver for ASUS ROG Aura Core | +| | +| Adam Honse (CalcProgrammer1) 13 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "AsusAuraCoreController.h" #include +#include "AsusAuraCoreController.h" +#include "StringUtils.h" #define AURA_CORE_MAX_MESSAGE_SIZE 64 @@ -47,10 +50,7 @@ std::string AuraCoreController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void AuraCoreController::SendBrightness diff --git a/Controllers/AsusAuraCoreController/AsusAuraCoreController.h b/Controllers/AsusAuraCoreController/AsusAuraCoreController/AsusAuraCoreController.h similarity index 85% rename from Controllers/AsusAuraCoreController/AsusAuraCoreController.h rename to Controllers/AsusAuraCoreController/AsusAuraCoreController/AsusAuraCoreController.h index fa8933b8..434709c0 100644 --- a/Controllers/AsusAuraCoreController/AsusAuraCoreController.h +++ b/Controllers/AsusAuraCoreController/AsusAuraCoreController/AsusAuraCoreController.h @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| AsusAuraCoreController.h | -| | -| Definitions and types for ASUS ROG Aura | -| Core RGB lighting controller | -| | -| Adam Honse (CalcProgrammer1) 4/13/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| AsusAuraCoreController.h | +| | +| Driver for ASUS ROG Aura Core | +| | +| Adam Honse (CalcProgrammer1) 13 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + enum AuraCoreDeviceType { AURA_CORE_DEVICE_UNKNOWN = 0, @@ -119,5 +120,4 @@ private: void Handshake(); void SendIdString(); void SendQuery(); - }; diff --git a/Controllers/AsusAuraCoreController/RGBController_AsusAuraCore.cpp b/Controllers/AsusAuraCoreController/AsusAuraCoreController/RGBController_AsusAuraCore.cpp similarity index 90% rename from Controllers/AsusAuraCoreController/RGBController_AsusAuraCore.cpp rename to Controllers/AsusAuraCoreController/AsusAuraCoreController/RGBController_AsusAuraCore.cpp index 8de1e3de..580f8abf 100644 --- a/Controllers/AsusAuraCoreController/RGBController_AsusAuraCore.cpp +++ b/Controllers/AsusAuraCoreController/AsusAuraCoreController/RGBController_AsusAuraCore.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraCore.cpp | -| | -| Generic RGB Interface for ROG Aura Core | -| | -| Adam Honse (CalcProgrammer1) 4/17/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraCore.cpp | +| | +| RGBController for ASUS ROG Aura Core | +| | +| Adam Honse (CalcProgrammer1) 13 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_AsusAuraCore.h" diff --git a/Controllers/AsusAuraCoreController/AsusAuraCoreController/RGBController_AsusAuraCore.h b/Controllers/AsusAuraCoreController/AsusAuraCoreController/RGBController_AsusAuraCore.h new file mode 100644 index 00000000..4cee08a6 --- /dev/null +++ b/Controllers/AsusAuraCoreController/AsusAuraCoreController/RGBController_AsusAuraCore.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraCore.h | +| | +| RGBController for ASUS ROG Aura Core | +| | +| Adam Honse (CalcProgrammer1) 13 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AsusAuraCoreController.h" + +class RGBController_AuraCore : public RGBController +{ +public: + RGBController_AuraCore(AuraCoreController* controller_ptr); + ~RGBController_AuraCore(); + + void SetupKeyboard(); + void SetupGA15DH(); + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + AuraCoreController* controller; +}; diff --git a/Controllers/AsusAuraCoreController/AsusAuraCoreControllerDetect.cpp b/Controllers/AsusAuraCoreController/AsusAuraCoreControllerDetect.cpp index 0b16b32c..6cf78636 100644 --- a/Controllers/AsusAuraCoreController/AsusAuraCoreControllerDetect.cpp +++ b/Controllers/AsusAuraCoreController/AsusAuraCoreControllerDetect.cpp @@ -1,14 +1,24 @@ +/*---------------------------------------------------------*\ +| AsusAuraCoreControllerDetect.cpp | +| | +| Detector for ASUS ROG Aura Core | +| | +| Adam Honse (CalcProgrammer1) 13 Apr 2020 | +| Chris M (Dr_No) 28 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "AsusAuraCoreController.h" #include "RGBController.h" #include "RGBController_AsusAuraCore.h" #include "RGBController_AsusAuraCoreLaptop.h" -#include +#include #define AURA_CORE_VID 0x0B05 -#define AURA_STRIX_SCAR_15_PID 0x19B6 - /******************************************************************************************\ * * * DetectAuraCoreControllers * @@ -25,7 +35,7 @@ void DetectAsusAuraCoreControllers(hid_device_info* info, const std::string& /*n { AuraCoreController* controller = new AuraCoreController(dev, info->path); RGBController_AuraCore* rgb_controller = new RGBController_AuraCore(controller); - // Constructor sets the name + if(rgb_controller->type != DEVICE_TYPE_UNKNOWN) { ResourceManager::get()->RegisterRGBController(rgb_controller); @@ -45,7 +55,7 @@ void DetectAsusAuraCoreLaptopControllers(hid_device_info* info, const std::strin { AsusAuraCoreLaptopController* controller = new AsusAuraCoreLaptopController(dev, info->path); RGBController_AsusAuraCoreLaptop* rgb_controller = new RGBController_AsusAuraCoreLaptop(controller); - // Constructor sets the name + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -55,3 +65,4 @@ REGISTER_HID_DETECTOR ("ASUS Aura Core", DetectAsusAuraCoreContro REGISTER_HID_DETECTOR ("ASUS Aura Core", DetectAsusAuraCoreControllers, AURA_CORE_VID, 0x1866); REGISTER_HID_DETECTOR ("ASUS Aura Core", DetectAsusAuraCoreControllers, AURA_CORE_VID, 0x1869); REGISTER_HID_DETECTOR_PU("ASUS ROG Strix SCAR 15", DetectAsusAuraCoreLaptopControllers, AURA_CORE_VID, AURA_STRIX_SCAR_15_PID, 0xFF31, 0x79); +REGISTER_HID_DETECTOR_PU("ASUS ROG Strix SCAR 17", DetectAsusAuraCoreLaptopControllers, AURA_CORE_VID, 0x1866, 0xFF31, 0x79); diff --git a/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController.cpp b/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController.cpp deleted file mode 100644 index 5a2ee62b..00000000 --- a/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/*---------------------------------------------------------------------*\ -| AsusAuraCoreLaptopController.cpp | -| | -| Driver for Asus Aura Core Laptop USB Controller | -| | -| Chris M (Dr_No) 28 Jul 2022 | -| | -\*---------------------------------------------------------------------*/ - -#include "AsusAuraCoreLaptopController.h" - -static uint8_t packet_map[ASUSAURACORELAPTOP_KEYCOUNT + - ASUSAURACORELAPTOP_LIGHTBARCOUNT + - ASUSAURACORELAPTOP_LIDCOUNT ] = -{ -/*00 ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 */ - 21, 23, 24, 25, 26, 28, 29, 30, 31, 33, - -/*10 F10 F11 F12 DEL ` 1 2 3 4 5 */ - 34, 35, 36, 37, 42, 43, 44, 45, 46, 47, - -/*20 6 7 8 9 0 - = BSP BSP BSP */ - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, - -/*30 PLY TAB Q W E R T Y U I */ - 58, 63, 64, 65, 66, 67, 68, 69, 70, 71, - -/*40 O P [ ] \ STP CAP A S D */ - 72, 73, 74, 75, 76, 79, 84, 85, 86, 87, - -/*50 F G H J K L ; ' ENT PRV */ - 88, 89, 90, 91, 92, 93, 94, 95, 98, 100, - -/*60 LSH Z X C V B N M , . */ - 105, 107, 108, 109, 110, 111, 112, 113, 114, 115, - -/*70 / RSH UP NXT LCTL LFN LWIN LALT SPC RALT */ - 116, 119, 139, 121, 126, 127, 128, 129, 131, 135, - -/*80 RCTL LFT DWN RGT PRT KSTN VDN VUP MICM HPFN */ - 137, 159, 160, 161, 142, 175, 2, 3, 4, 5, - -/*90 ARMC LB1 LB2 LB3 LB4 LB5 LB6 LOGO LIDL LIDR */ - 6, 174, 173, 172, 171, 170, 169, 167, 176, 177, - -}; - -static std::string power_zones[ASUSAURACORELAPTOP_POWER_ZONES] = -{ - "Logo", - ZONE_EN_KEYBOARD, - "Lightbar", - "Lid Edges" -}; - -static std::string power_states[ASUSAURACORELAPTOP_POWER_STATES] = -{ - " when booting", - " when awake", - " when sleeping", - " when off", -}; - -AsusAuraCoreLaptopController::AsusAuraCoreLaptopController(hid_device* dev_handle, const char* path) -{ - const uint8_t sz = HID_MAX_STR; - wchar_t tmp[sz]; - - dev = dev_handle; - location = path; - - hid_get_manufacturer_string(dev, tmp, sz); - std::wstring wName = std::wstring(tmp); - device_name = std::string(wName.begin(), wName.end()); - - hid_get_product_string(dev, tmp, sz); - wName = std::wstring(tmp); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); - - SetPowerConfigFromJSON(); -} - -AsusAuraCoreLaptopController::~AsusAuraCoreLaptopController() -{ - hid_close(dev); -} - -std::string AsusAuraCoreLaptopController::GetDeviceName() -{ - return device_name; -} - -std::string AsusAuraCoreLaptopController::GetSerial() -{ - const uint8_t sz = HID_MAX_STR; - wchar_t tmp[sz]; - - int ret = hid_get_serial_number_string(dev, tmp, sz); - - if (ret != 0) - { - LOG_DEBUG("[%s] Get HID Serial string failed", device_name.c_str()); - return(""); - } - - std::wstring w_tmp = std::wstring(tmp); - std::string serial = std::string(w_tmp.begin(), w_tmp.end()); - - return serial; -} - -std::string AsusAuraCoreLaptopController::GetLocation() -{ - return("HID: " + location); -} - -void AsusAuraCoreLaptopController::SetMode(uint8_t mode, uint8_t speed, uint8_t brightness, RGBColor color1, RGBColor color2, uint8_t random, uint8_t direction) -{ - bool needs_update = !( (current_mode == mode ) && - (current_speed == speed ) && - (current_brightness == brightness ) && - (current_c1 == color1 ) && - (current_c2 == color2 ) && - (current_random == random ) && - (current_direction == direction ) ); - - if(needs_update) - { - current_mode = mode; - current_speed = speed; - current_brightness = brightness; - current_c1 = color1; - current_c2 = color2; - current_random = random; - current_direction = direction; - - SendUpdate(); - SendBrightness(); - } -} - -void AsusAuraCoreLaptopController::SetLedsDirect(std::vector colors) -{ - /*---------------------------------------------------------*\ - | The keyboard zone is a set of 168 keys (indexed from 0) | - | sent in 11 packets of 16 triplets. The Lid and Lightbar | - | zones are sent in one final packet afterwards. | - \*---------------------------------------------------------*/ - const uint8_t key_set = 167; - const uint8_t led_count = 178; - const uint16_t map_size = 3 * led_count; - const uint8_t leds_per_packet = 16; - uint8_t buffer[ASUSAURACORELAPTOP_WRITE_PACKET_SIZE] = { ASUSAURACORELAPTOP_REPORT_ID, ASUSAURACORELAPTOP_CMD_DIRECT, - 0x00, 0x01, 0x01, 0x01, 0x00, leds_per_packet, 0x00 }; - uint8_t key_buf[map_size]; - - memset(key_buf, 0, map_size); - - for(size_t led_index = 0; led_index < colors.size(); led_index++) - { - uint16_t offset = 3 * packet_map[led_index]; - - key_buf[offset] = RGBGetRValue(colors[led_index]); - key_buf[offset + 1] = RGBGetGValue(colors[led_index]); - key_buf[offset + 2] = RGBGetBValue(colors[led_index]); - } - - for(size_t i = 0; i < key_set; i+=leds_per_packet) - { - uint8_t leds_remaining = key_set - i; - - if(leds_remaining < leds_per_packet) - { - buffer[07] = leds_remaining; - } - - buffer[06] = i; - memcpy(&buffer[ASUSAURACORELAPTOP_DATA_BYTE], &key_buf[3 * i], (3 * buffer[07])); - - hid_send_feature_report(dev, buffer, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); - } - - buffer[4] = 0x04; - buffer[5] = 0x00; - buffer[6] = 0x00; - buffer[7] = 0x00; - memcpy(&buffer[ASUSAURACORELAPTOP_DATA_BYTE], &key_buf[3 * key_set], (3 * (led_count - key_set))); - - hid_send_feature_report(dev, buffer, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); -} - -void AsusAuraCoreLaptopController::SendBrightness() -{ - const uint8_t index = 2; - uint8_t buffer[ASUSAURACORELAPTOP_WRITE_PACKET_SIZE] = { ASUSAURACORELAPTOP_REPORT_ID, ASUSAURACORELAPTOP_CMD_BRIGHTNESS }; - - memset(&buffer[index], 0, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE - index); - buffer[4] = current_brightness; - - hid_send_feature_report(dev, buffer, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); -} - -void AsusAuraCoreLaptopController::SendUpdate() -{ - uint8_t buffer[ASUSAURACORELAPTOP_WRITE_PACKET_SIZE] = { ASUSAURACORELAPTOP_REPORT_ID, ASUSAURACORELAPTOP_CMD_UPDATE }; - - buffer[ASUSAURACORELAPTOP_ZONE_BYTE] = 0; - buffer[ASUSAURACORELAPTOP_MODE_BYTE] = current_mode; - buffer[ASUSAURACORELAPTOP_R1_BYTE] = RGBGetRValue(current_c1); - buffer[ASUSAURACORELAPTOP_G1_BYTE] = RGBGetGValue(current_c1); - buffer[ASUSAURACORELAPTOP_B1_BYTE] = RGBGetBValue(current_c1); - buffer[ASUSAURACORELAPTOP_SPEED_BYTE] = current_speed; - buffer[ASUSAURACORELAPTOP_DIRECTION_BYTE] = current_direction; - buffer[ASUSAURACORELAPTOP_DATA_BYTE] = current_random; - buffer[ASUSAURACORELAPTOP_R2_BYTE] = RGBGetRValue(current_c2); - buffer[ASUSAURACORELAPTOP_G2_BYTE] = RGBGetGValue(current_c2); - buffer[ASUSAURACORELAPTOP_B2_BYTE] = RGBGetBValue(current_c2); - - hid_send_feature_report(dev, buffer, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); - - SendApply(); -} - -void AsusAuraCoreLaptopController::SendApply() -{ - const uint8_t index = 2; - uint8_t buffer[ASUSAURACORELAPTOP_WRITE_PACKET_SIZE] = { ASUSAURACORELAPTOP_REPORT_ID, ASUSAURACORELAPTOP_CMD_APPLY }; - - memset(&buffer[index], 0, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE - index); - - hid_send_feature_report(dev, buffer, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); -} - -void AsusAuraCoreLaptopController::SendSet() -{ - const uint8_t index = 2; - uint8_t buffer[ASUSAURACORELAPTOP_WRITE_PACKET_SIZE] = { ASUSAURACORELAPTOP_REPORT_ID, ASUSAURACORELAPTOP_CMD_SET }; - - memset(&buffer[index], 0, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE - index); - - hid_send_feature_report(dev, buffer, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); -} - -std::vector AsusAuraCoreLaptopController::PowerConfigArray() -{ - std::vector temp; - - for(uint8_t zone_index = 0; zone_index < ASUSAURACORELAPTOP_POWER_ZONES; zone_index++) - { - for(uint8_t state_index = 0; state_index < ASUSAURACORELAPTOP_POWER_STATES; state_index++) - { - p_state new_state; - - new_state.zone = power_zones[zone_index] + power_states[state_index]; - new_state.state = true; - - temp.push_back(new_state); - } - } - - return temp; -} - -void AsusAuraCoreLaptopController::SetPowerConfigFromJSON() -{ - std::vector power_config = PowerConfigArray(); - const std::string section_power = "PowerConfig"; - const std::string detector_name = "Asus Aura Core Laptop"; - SettingsManager* settings_manager = ResourceManager::get()->GetSettingsManager(); - json device_settings = settings_manager->GetSettings(detector_name); - - /*---------------------------------------------------------*\ - | Get Power state config from the settings manager | - | If PowerConfig is not found then write it to settings | - \*---------------------------------------------------------*/ - if(!device_settings.contains(section_power)) - { - json pcfg; - - for(size_t i = 0; i < power_config.size(); i++) - { - pcfg[power_config[i].zone] = power_config[i].state; - } - - device_settings[section_power] = pcfg; - settings_manager->SetSettings(detector_name, device_settings); - settings_manager->SaveSettings(); - } - else - { - for(size_t i = 0; i < power_config.size(); i++) - { - std::string key_name = power_config[i].zone; - - if(device_settings[section_power].contains(key_name)) - { - power_config[i].state = device_settings[section_power][key_name]; - LOG_DEBUG("[%s] Reading power config for %s: %s", device_name.c_str(), key_name.c_str(), ((power_config[i].state) ? "On" : "Off")); - } - } - } - - /*-----------------------------------------------------------------------------*\ - | Power state flags are packed in zones but the order is inconsistent. | - | With thanks to AsusCtl for helping to decipher the packet captures | - | https://gitlab.com/asus-linux/asusctl/-/blob/main/rog-aura/src/usb.rs#L150 | - \*-----------------------------------------------------------------------------*/ - bool flag_array[] = - { - power_config[0].state, power_config[4].state, - power_config[1].state, power_config[5].state, - !power_config[2].state, !power_config[6].state, - !power_config[3].state, !power_config[7].state, - - false, power_config[8].state, - power_config[9].state, !power_config[10].state, - !power_config[11].state, false, - false, false, - - power_config[12].state, power_config[13].state, - !power_config[14].state, !power_config[15].state - }; - - uint32_t flags = PackPowerFlags(flag_array); - LOG_DEBUG("[%s] Sending power config Logo+KB: %02X Lightbar: %02X Lid Edges: %02X Raw: %08X", device_name.c_str(), (flags & 0xFF), ((flags >> 8) & 0xFF), ((flags >> 16) & 0xFF), flags); - SendPowerConfig(flags); -} - -void AsusAuraCoreLaptopController::SendPowerConfig(uint32_t flags) -{ - const uint8_t index = 6; - uint8_t buffer[ASUSAURACORELAPTOP_WRITE_PACKET_SIZE] = { ASUSAURACORELAPTOP_REPORT_ID, ASUSAURACORELAPTOP_CMD_POWER, 0x01, 0x00, 0x00, 0x0F }; - - memset(&buffer[index], 0, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE - index); - - buffer[3] = flags & 0xFF; - buffer[4] = (flags >> 8) & 0xFF; - buffer[5] = (flags >> 16) & 0xFF; - - hid_send_feature_report(dev, buffer, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); -} - -uint32_t AsusAuraCoreLaptopController::PackPowerFlags(bool flags[]) -{ - uint32_t temp = {}; - const uint8_t length = 32; - - for (size_t i = 0; i < length; ++i) - { - uint32_t flag = {flags[i]}; - flag <<= i; - temp |= flag; - } - - return temp; -} diff --git a/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController.h b/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController.h deleted file mode 100644 index c8bdfad5..00000000 --- a/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController.h +++ /dev/null @@ -1,135 +0,0 @@ -/*---------------------------------------------------------------------*\ -| AsusAuraCoreLaptopController.h | -| | -| Driver for AsusAuraCoreLaptop USB Controller | -| | -| Chris M (Dr_No) 28 Jul 2022 | -| | -\*---------------------------------------------------------------------*/ - -#include -#include -#include -#include "LogManager.h" -#include "RGBController.h" -#include "ResourceManager.h" -#include "SettingsManager.h" -#include "RGBControllerKeyNames.h" - -#pragma once - -#define NA 0xFFFFFFFF -#define HID_MAX_STR 255 -#define ASUSAURACORELAPTOP_TIMEOUT 250 -#define ASUSAURACORELAPTOP_READ_PACKET_SIZE 64 -#define ASUSAURACORELAPTOP_WRITE_PACKET_SIZE 64 //Buffer requires a prepended ReportID hence + 1 - -#define ASUSAURACORELAPTOP_KEYCOUNT 91 -#define ASUSAURACORELAPTOP_KEY_WIDTH 18 -#define ASUSAURACORELAPTOP_KEY_HEIGHT 7 -#define ASUSAURACORELAPTOP_LIGHTBARCOUNT 6 -#define ASUSAURACORELAPTOP_LIDCOUNT 3 -#define ASUSAURACORELAPTOP_POWER_ZONES 4 -#define ASUSAURACORELAPTOP_POWER_STATES 4 -#define ASUSAURACORELAPTOP_BRIGHTNESS_MIN 0 -#define ASUSAURACORELAPTOP_BRIGHTNESS_MAX 255 - -enum -{ - ASUSAURACORELAPTOP_MODE_OFF = 0x00, //Turn off - All leds off - ASUSAURACORELAPTOP_MODE_DIRECT = 0xFF, //Direct Led Control - Independently set LEDs in zone - ASUSAURACORELAPTOP_MODE_STATIC = 0x00, //Static Mode - Set entire zone to a single color. - ASUSAURACORELAPTOP_MODE_BREATHING = 0x01, //Breathing Mode - Fades between fully off and fully on. - ASUSAURACORELAPTOP_MODE_SPECTRUM = 0x02, //Spectrum Cycle Mode - Cycles through the color spectrum on all lights on the device - ASUSAURACORELAPTOP_MODE_RAINBOW = 0x03, //Rainbow Wave Mode - Cycle thru the color spectrum as a wave across all LEDs - ASUSAURACORELAPTOP_MODE_FLASHING = 0x0A, //Flashing Mode - Abruptly changing between fully off and fully on. - - /*-------------------------------------------------*\ - | Modes not implemented in the Armoury Crate | - | OEM software that were discovered. | - \*-------------------------------------------------*/ - ASUSAURACORELAPTOP_MODE_STARRY_NIGHT = 0x04, //Starry Night Mode - ASUSAURACORELAPTOP_MODE_RAIN = 0x05, //Rain Mode - ASUSAURACORELAPTOP_MODE_REACT_FADE = 0x06, //Reactive Fade Mode - ASUSAURACORELAPTOP_MODE_REACT_LASER = 0x07, //Reactive Laser Mode - ASUSAURACORELAPTOP_MODE_REACT_RIPPLE = 0x08, //Reactive Ripple Mode - ASUSAURACORELAPTOP_MODE_COMET = 0x0B, //Comet Mode - ASUSAURACORELAPTOP_MODE_FLASHNDASH = 0x0C, //Flash n Dash Mode - ASUSAURACORELAPTOP_MODE_KEYSTONE = 0x0D, //Keystone Mode -}; - -enum -{ - ASUSAURACORELAPTOP_ZONE_BYTE = 2, - ASUSAURACORELAPTOP_MODE_BYTE = 3, - ASUSAURACORELAPTOP_R1_BYTE = 4, - ASUSAURACORELAPTOP_G1_BYTE = 5, - ASUSAURACORELAPTOP_B1_BYTE = 6, - ASUSAURACORELAPTOP_SPEED_BYTE = 7, - ASUSAURACORELAPTOP_DIRECTION_BYTE = 8, - ASUSAURACORELAPTOP_DATA_BYTE = 9, - ASUSAURACORELAPTOP_R2_BYTE = 10, - ASUSAURACORELAPTOP_G2_BYTE = 11, - ASUSAURACORELAPTOP_B2_BYTE = 12, -}; - -enum -{ - ASUSAURACORELAPTOP_REPORT_ID = 0x5D, - ASUSAURACORELAPTOP_CMD_BRIGHTNESS = 0xBA, - ASUSAURACORELAPTOP_CMD_DIRECT = 0xBC, - ASUSAURACORELAPTOP_CMD_POWER = 0xBD, - ASUSAURACORELAPTOP_CMD_UPDATE = 0xB3, - ASUSAURACORELAPTOP_CMD_APPLY = 0xB4, - ASUSAURACORELAPTOP_CMD_SET = 0xB5, -}; - -enum -{ - ASUSAURACORELAPTOP_SPEED_SLOWEST = 0xE1, // Slowest speed - ASUSAURACORELAPTOP_SPEED_NORMAL = 0xEB, // Normal speed - ASUSAURACORELAPTOP_SPEED_FASTEST = 0xF5, // Fastest speed -}; - -struct p_state -{ - std::string zone; - bool state; -}; - -class AsusAuraCoreLaptopController -{ -public: - AsusAuraCoreLaptopController(hid_device* dev_handle, const char* path); - ~AsusAuraCoreLaptopController(); - - std::string GetDeviceName(); - std::string GetSerial(); - std::string GetLocation(); - - void SetMode(uint8_t mode, uint8_t speed, uint8_t brightness, RGBColor color1, RGBColor color2, uint8_t random, uint8_t direction); - void SetLedsDirect(std::vector colors); -private: - std::string device_name; - std::string location; - hid_device* dev; - - uint8_t current_mode; - uint8_t current_speed; - uint8_t current_direction; - - RGBColor current_c1; - RGBColor current_c2; - uint8_t current_brightness; - uint8_t current_random; - - void SendApply(); - void SendBrightness(); - void SendSet(); - void SendUpdate(); - - void SetPowerConfigFromJSON(); - void SendPowerConfig(uint32_t flags); - uint32_t PackPowerFlags(bool flags[]); - std::vector PowerConfigArray(); -}; diff --git a/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/AsusAuraCoreLaptopController.cpp b/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/AsusAuraCoreLaptopController.cpp new file mode 100644 index 00000000..7b4ce272 --- /dev/null +++ b/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/AsusAuraCoreLaptopController.cpp @@ -0,0 +1,446 @@ +/*---------------------------------------------------------*\ +| AsusAuraCoreLaptopController.cpp | +| | +| Driver for ASUS ROG Aura Core Laptop | +| | +| Chris M (Dr_No) 28 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "AsusAuraCoreLaptopController.h" +#include "dmiinfo.h" +#include "SettingsManager.h" +#include "StringUtils.h" + +static std::string power_zones[ASUSAURACORELAPTOP_POWER_ZONES] = +{ + "Logo", + ZONE_EN_KEYBOARD, + "Lightbar", + "Lid Edges" +}; + +static std::string power_states[ASUSAURACORELAPTOP_POWER_STATES] = +{ + " when booting", + " when awake", + " when sleeping", + " when off", +}; + +AsusAuraCoreLaptopController::AsusAuraCoreLaptopController(hid_device* dev_handle, const char* path) +{ + dev = dev_handle; + location = path; + + /*---------------------------------------------------------*\ + | The motherboard name will uniquely ID the laptop to | + | determine the metadata of the device. | + \*---------------------------------------------------------*/ + DMIInfo dmi_info; + std::string dmi_name = dmi_info.getMainboard(); + bool not_found = true; + + for(uint16_t i = 0; i < AURA_CORE_LAPTOP_DEVICE_COUNT; i++) + { + if(aura_core_laptop_device_list[i]->dmi_name == dmi_name) + { + /*---------------------------------------------------------*\ + | Set device ID | + \*---------------------------------------------------------*/ + not_found = false; + device_index = i; + break; + } + } + + if(not_found) + { + LOG_ERROR("[%s] device capabilities not found. Please creata a new device request.", + dmi_name.c_str()); + return; + } + + /*---------------------------------------------------------*\ + | Only set power config for known devices | + \*---------------------------------------------------------*/ + SetPowerConfigFromJSON(); + SendInitDirectMode(); +} + +AsusAuraCoreLaptopController::~AsusAuraCoreLaptopController() +{ + hid_close(dev); +} + +const aura_core_laptop_device* AsusAuraCoreLaptopController::GetDeviceData() +{ + return aura_core_laptop_device_list[device_index]; +} + +std::string AsusAuraCoreLaptopController::GetDeviceDescription() +{ + /*---------------------------------------------------------*\ + | Get device name from HID manufacturer and product strings | + \*---------------------------------------------------------*/ + wchar_t name_string[HID_MAX_STR]; + + hid_get_manufacturer_string(dev, name_string, HID_MAX_STR); + std::string name = StringUtils::wstring_to_string(name_string); + + hid_get_product_string(dev, name_string, HID_MAX_STR); + name.append(" ").append(StringUtils::wstring_to_string(name_string)); + return name; +} + +unsigned int AsusAuraCoreLaptopController::GetKeyboardLayout() +{ + const uint8_t index = 6; + uint8_t result = 0; + uint8_t rd_buf[ASUSAURACORELAPTOP_WRITE_PACKET_SIZE] = { ASUSAURACORELAPTOP_REPORT_ID }; + uint8_t buffer[ASUSAURACORELAPTOP_WRITE_PACKET_SIZE] = { ASUSAURACORELAPTOP_REPORT_ID, + ASUSAURACORELAPTOP_CMD_LAYOUT, + 0x20, + 0x31, + 0x00, + 0x10 }; + + /*---------------------------------------------------------*\ + | Clear the read buffer to ensure we read the right packet | + \*---------------------------------------------------------*/ + do + { + result = hid_read_timeout(dev, rd_buf, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE, 10); + } + while(result > 0); + + memset(&rd_buf[1], 0, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE - 1); + memset(&buffer[index], 0, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE - index); + + hid_send_feature_report(dev, buffer, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); + result = hid_get_feature_report(dev, rd_buf, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); + + LOG_DEBUG("[%s] GetKeyboardLayout %02X %02X %02X %02X %02X %02X %02X {%02X} %02X %02X %02X %02X", + aura_core_laptop_device_list[device_index]->dmi_name.c_str(), + rd_buf[5], rd_buf[6], rd_buf[7], rd_buf[8], rd_buf[9], rd_buf[10], + rd_buf[11], rd_buf[12], rd_buf[13], rd_buf[14], rd_buf[15], rd_buf[16]); + + if(result > 0) + { + return rd_buf[12]; + } + + LOG_DEBUG("[%s] GetKeyboardLayout: An error occurred! Setting layout to ANSI", + aura_core_laptop_device_list[device_index]->dmi_name.c_str()); + return ASUSAURACORELAPTOP_LAYOUT_ANSI; +} + +std::string AsusAuraCoreLaptopController::GetSerial() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + LOG_DEBUG("[%s] Get HID Serial string failed", + aura_core_laptop_device_list[device_index]->dmi_name.c_str()); + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string AsusAuraCoreLaptopController::GetLocation() +{ + return("HID: " + location); +} + +void AsusAuraCoreLaptopController::SetMode(uint8_t mode, uint8_t speed, uint8_t brightness, RGBColor color1, RGBColor color2, uint8_t random, uint8_t direction) +{ + bool needs_update = !( (current_mode == mode ) && + (current_speed == speed ) && + (current_brightness == brightness ) && + (current_c1 == color1 ) && + (current_c2 == color2 ) && + (current_random == random ) && + (current_direction == direction ) ); + + if(needs_update) + { + current_mode = mode; + current_speed = speed; + current_brightness = brightness; + current_c1 = color1; + current_c2 = color2; + current_random = random; + current_direction = direction; + + if(current_mode == ASUSAURACORELAPTOP_MODE_DIRECT) + { + SendBrightness(); + SendInitDirectMode(); + return; + } + + SendUpdate(); + SendBrightness(); + } +} + +void AsusAuraCoreLaptopController::SendInitDirectMode() +{ + uint8_t buffer[ASUSAURACORELAPTOP_WRITE_PACKET_SIZE] = { ASUSAURACORELAPTOP_REPORT_ID, ASUSAURACORELAPTOP_CMD_DIRECT }; + memset(&buffer[2], 0, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE - 2); + + LOG_DEBUG("[%s] Resetting device for direct control", aura_core_laptop_device_list[device_index]->dmi_name.c_str()); + hid_send_feature_report(dev, buffer, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); +} + +void AsusAuraCoreLaptopController::SetLedsDirect(std::vector colors) +{ + /*---------------------------------------------------------*\ + | The keyboard zone is a set of 168 keys (indexed from 0) | + | sent in 11 packets of 16 triplets. The Lid and Lightbar | + | zones are sent in one final packet afterwards. | + \*---------------------------------------------------------*/ + const uint8_t key_set = 167; + const uint8_t led_count = (uint8_t)colors.size(); + const uint16_t map_size = 3 * led_count; + const uint8_t leds_per_packet = 16; + uint8_t buffer[ASUSAURACORELAPTOP_WRITE_PACKET_SIZE] = { ASUSAURACORELAPTOP_REPORT_ID, ASUSAURACORELAPTOP_CMD_DIRECT, + 0x00, 0x01, 0x01, 0x01, 0x00, leds_per_packet, 0x00 }; + uint8_t* key_buf = new uint8_t[map_size]; + + memset(key_buf, 0, map_size); + + for(uint8_t led_index = 0; led_index < led_count; led_index++) + { + std::size_t buf_idx = (led_index * 3); + + key_buf[buf_idx] = RGBGetRValue(*colors[led_index]); + key_buf[buf_idx + 1] = RGBGetGValue(*colors[led_index]); + key_buf[buf_idx + 2] = RGBGetBValue(*colors[led_index]); + } + + for(uint8_t i = 0; i < key_set; i += leds_per_packet) + { + uint8_t leds_remaining = key_set - i; + + if(leds_remaining < leds_per_packet) + { + buffer[07] = leds_remaining; + + memset(&buffer[ASUSAURACORELAPTOP_DATA_BYTE], + 0, + ASUSAURACORELAPTOP_WRITE_PACKET_SIZE - ASUSAURACORELAPTOP_DATA_BYTE); + } + + buffer[06] = i; + memcpy(&buffer[ASUSAURACORELAPTOP_DATA_BYTE], &key_buf[3 * i], (3 * buffer[07])); + + LOG_DEBUG("[%s] Sending buffer @ index %d thru index %d", + aura_core_laptop_device_list[device_index]->dmi_name.c_str(), + i, + i + buffer[07]); + + hid_send_feature_report(dev, buffer, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); + } + + buffer[4] = 0x04; + buffer[5] = 0x00; + buffer[6] = 0x00; + buffer[7] = 0x00; + + memset(&buffer[ASUSAURACORELAPTOP_DATA_BYTE], + 0, + ASUSAURACORELAPTOP_WRITE_PACKET_SIZE - ASUSAURACORELAPTOP_DATA_BYTE); + + if(led_count > key_set) + { + memcpy(&buffer[ASUSAURACORELAPTOP_DATA_BYTE], + &key_buf[3 * key_set], + (3 * (led_count - key_set))); + } + + LOG_DEBUG("[%s] Sending buffer @ index %d thru index %d", + aura_core_laptop_device_list[device_index]->dmi_name.c_str(), + key_set, + led_count); + + hid_send_feature_report(dev, buffer, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); + delete[] key_buf; +} + +void AsusAuraCoreLaptopController::SendBrightness() +{ + const uint8_t index = 5; + uint8_t buffer[ASUSAURACORELAPTOP_WRITE_PACKET_SIZE] = { ASUSAURACORELAPTOP_REPORT_ID, ASUSAURACORELAPTOP_CMD_BRIGHTNESS, 0xC5, 0xC4}; + + memset(&buffer[index], 0, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE - index); + buffer[4] = current_brightness; + + hid_send_feature_report(dev, buffer, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); +} + +void AsusAuraCoreLaptopController::SendUpdate() +{ + uint8_t buffer[ASUSAURACORELAPTOP_WRITE_PACKET_SIZE] = { ASUSAURACORELAPTOP_REPORT_ID, ASUSAURACORELAPTOP_CMD_UPDATE }; + + buffer[ASUSAURACORELAPTOP_ZONE_BYTE] = 0; + buffer[ASUSAURACORELAPTOP_MODE_BYTE] = current_mode; + buffer[ASUSAURACORELAPTOP_R1_BYTE] = RGBGetRValue(current_c1); + buffer[ASUSAURACORELAPTOP_G1_BYTE] = RGBGetGValue(current_c1); + buffer[ASUSAURACORELAPTOP_B1_BYTE] = RGBGetBValue(current_c1); + buffer[ASUSAURACORELAPTOP_SPEED_BYTE] = current_speed; + buffer[ASUSAURACORELAPTOP_DIRECTION_BYTE] = current_direction; + buffer[ASUSAURACORELAPTOP_DATA_BYTE] = current_random; + buffer[ASUSAURACORELAPTOP_R2_BYTE] = RGBGetRValue(current_c2); + buffer[ASUSAURACORELAPTOP_G2_BYTE] = RGBGetGValue(current_c2); + buffer[ASUSAURACORELAPTOP_B2_BYTE] = RGBGetBValue(current_c2); + + hid_send_feature_report(dev, buffer, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); + + SendApply(); +} + +void AsusAuraCoreLaptopController::SendApply() +{ + const uint8_t index = 2; + uint8_t buffer[ASUSAURACORELAPTOP_WRITE_PACKET_SIZE] = { ASUSAURACORELAPTOP_REPORT_ID, ASUSAURACORELAPTOP_CMD_APPLY }; + + memset(&buffer[index], 0, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE - index); + + hid_send_feature_report(dev, buffer, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); +} + +void AsusAuraCoreLaptopController::SendSet() +{ + const uint8_t index = 2; + uint8_t buffer[ASUSAURACORELAPTOP_WRITE_PACKET_SIZE] = { ASUSAURACORELAPTOP_REPORT_ID, ASUSAURACORELAPTOP_CMD_SET }; + + memset(&buffer[index], 0, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE - index); + + hid_send_feature_report(dev, buffer, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); +} + +std::vector AsusAuraCoreLaptopController::PowerConfigArray() +{ + std::vector temp; + + for(uint8_t zone_index = 0; zone_index < ASUSAURACORELAPTOP_POWER_ZONES; zone_index++) + { + for(uint8_t state_index = 0; state_index < ASUSAURACORELAPTOP_POWER_STATES; state_index++) + { + p_state new_state; + + new_state.zone = power_zones[zone_index] + power_states[state_index]; + new_state.state = true; + + temp.push_back(new_state); + } + } + + return temp; +} + +void AsusAuraCoreLaptopController::SetPowerConfigFromJSON() +{ + std::vector power_config = PowerConfigArray(); + const std::string section_power = "PowerConfig"; + const std::string detector_name = "Asus Aura Core Laptop"; + SettingsManager* settings_manager = ResourceManager::get()->GetSettingsManager(); + json device_settings = settings_manager->GetSettings(detector_name); + + /*---------------------------------------------------------*\ + | Get Power state config from the settings manager | + | If PowerConfig is not found then write it to settings | + \*---------------------------------------------------------*/ + if(!device_settings.contains(section_power)) + { + json pcfg; + + for(size_t i = 0; i < power_config.size(); i++) + { + pcfg[power_config[i].zone] = power_config[i].state; + } + + device_settings[section_power] = pcfg; + settings_manager->SetSettings(detector_name, device_settings); + settings_manager->SaveSettings(); + LOG_DEBUG("[%s] default power config saved to openrgb.json", + aura_core_laptop_device_list[device_index]->dmi_name.c_str()); + } + else + { + for(size_t i = 0; i < power_config.size(); i++) + { + std::string key_name = power_config[i].zone; + + if(device_settings[section_power].contains(key_name)) + { + power_config[i].state = device_settings[section_power][key_name]; + LOG_DEBUG("[%s] Reading power config for %s: %s", + aura_core_laptop_device_list[device_index]->dmi_name.c_str(), + key_name.c_str(), ((power_config[i].state) ? "On" : "Off")); + } + } + } + + /*-----------------------------------------------------------------------------*\ + | Power state flags are packed in zones but the order is inconsistent. | + | With thanks to AsusCtl for helping to decipher the packet captures | + | https://gitlab.com/asus-linux/asusctl/-/blob/main/rog-aura/src/usb.rs#L150 | + \*-----------------------------------------------------------------------------*/ + bool flag_array[32] = + { + power_config[0].state, power_config[4].state, + power_config[1].state, power_config[5].state, + !power_config[2].state, !power_config[6].state, + !power_config[3].state, !power_config[7].state, + + false, power_config[8].state, + power_config[9].state, !power_config[10].state, + !power_config[11].state, false, + false, false, + + power_config[12].state, power_config[13].state, + !power_config[14].state, !power_config[15].state + }; + + uint32_t flags = PackPowerFlags(flag_array); + LOG_DEBUG("[%s] Sending power config Logo+KB: %02X Lightbar: %02X Lid Edges: %02X Raw: %08X", + aura_core_laptop_device_list[device_index]->dmi_name.c_str(), + (flags & 0xFF), ((flags >> 8) & 0xFF), ((flags >> 16) & 0xFF), flags); + SendPowerConfig(flags); +} + +void AsusAuraCoreLaptopController::SendPowerConfig(uint32_t flags) +{ + const uint8_t index = 6; + uint8_t buffer[ASUSAURACORELAPTOP_WRITE_PACKET_SIZE] = { ASUSAURACORELAPTOP_REPORT_ID, ASUSAURACORELAPTOP_CMD_POWER, 0x01, 0x00, 0x00, 0x0F }; + + memset(&buffer[index], 0, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE - index); + + buffer[3] = flags & 0xFF; + buffer[4] = (flags >> 8) & 0xFF; + buffer[5] = (flags >> 16) & 0xFF; + + hid_send_feature_report(dev, buffer, ASUSAURACORELAPTOP_WRITE_PACKET_SIZE); +} + +uint32_t AsusAuraCoreLaptopController::PackPowerFlags(bool flags[]) +{ + uint32_t temp = {}; + const uint8_t length = 32; + + for (size_t i = 0; i < length; ++i) + { + uint32_t flag = {flags[i]}; + flag <<= i; + temp |= flag; + } + + return temp; +} diff --git a/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/AsusAuraCoreLaptopController.h b/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/AsusAuraCoreLaptopController.h new file mode 100644 index 00000000..362ff630 --- /dev/null +++ b/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/AsusAuraCoreLaptopController.h @@ -0,0 +1,147 @@ +/*---------------------------------------------------------*\ +| AsusAuraCoreLaptopController.h | +| | +| Driver for ASUS ROG Aura Core Laptop | +| | +| Chris M (Dr_No) 28 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "LogManager.h" +#include "RGBController.h" +#include "ResourceManager.h" +#include "RGBControllerKeyNames.h" +#include "AsusAuraCoreLaptopDevices.h" + +#define NA 0xFFFFFFFF +#define HID_MAX_STR 255 +#define ASUSAURACORELAPTOP_TIMEOUT 250 +#define ASUSAURACORELAPTOP_READ_PACKET_SIZE 64 +#define ASUSAURACORELAPTOP_WRITE_PACKET_SIZE 64 //Buffer requires a prepended ReportID hence + 1 + +#define ASUSAURACORELAPTOP_KEYCOUNT 91 +#define ASUSAURACORELAPTOP_KEY_WIDTH 18 +#define ASUSAURACORELAPTOP_KEY_HEIGHT 7 +#define ASUSAURACORELAPTOP_LIGHTBARCOUNT 6 +#define ASUSAURACORELAPTOP_LIDCOUNT 3 +#define ASUSAURACORELAPTOP_POWER_ZONES 4 +#define ASUSAURACORELAPTOP_POWER_STATES 4 +#define ASUSAURACORELAPTOP_BRIGHTNESS_MIN 0 +#define ASUSAURACORELAPTOP_BRIGHTNESS_MAX 3 // No device has proven to have 256 keyboard brightness levels, only 0..3 + +enum +{ + ASUSAURACORELAPTOP_MODE_OFF = 0x00, //Turn off - All leds off + ASUSAURACORELAPTOP_MODE_DIRECT = 0xFF, //Direct Led Control - Independently set LEDs in zone + ASUSAURACORELAPTOP_MODE_STATIC = 0x00, //Static Mode - Set entire zone to a single color. + ASUSAURACORELAPTOP_MODE_BREATHING = 0x01, //Breathing Mode - Fades between fully off and fully on. + ASUSAURACORELAPTOP_MODE_SPECTRUM = 0x02, //Spectrum Cycle Mode - Cycles through the color spectrum on all lights on the device + ASUSAURACORELAPTOP_MODE_RAINBOW = 0x03, //Rainbow Wave Mode - Cycle thru the color spectrum as a wave across all LEDs + ASUSAURACORELAPTOP_MODE_FLASHING = 0x0A, //Flashing Mode - Abruptly changing between fully off and fully on. + + /*-------------------------------------------------*\ + | Modes not implemented in the Armoury Crate | + | OEM software that were discovered. | + \*-------------------------------------------------*/ + ASUSAURACORELAPTOP_MODE_STARRY_NIGHT = 0x04, //Starry Night Mode + ASUSAURACORELAPTOP_MODE_RAIN = 0x05, //Rain Mode + ASUSAURACORELAPTOP_MODE_REACT_FADE = 0x06, //Reactive Fade Mode + ASUSAURACORELAPTOP_MODE_REACT_LASER = 0x07, //Reactive Laser Mode + ASUSAURACORELAPTOP_MODE_REACT_RIPPLE = 0x08, //Reactive Ripple Mode + ASUSAURACORELAPTOP_MODE_COMET = 0x0B, //Comet Mode + ASUSAURACORELAPTOP_MODE_FLASHNDASH = 0x0C, //Flash n Dash Mode + ASUSAURACORELAPTOP_MODE_KEYSTONE = 0x0D, //Keystone Mode +}; + +enum +{ + ASUSAURACORELAPTOP_ZONE_BYTE = 2, + ASUSAURACORELAPTOP_MODE_BYTE = 3, + ASUSAURACORELAPTOP_R1_BYTE = 4, + ASUSAURACORELAPTOP_G1_BYTE = 5, + ASUSAURACORELAPTOP_B1_BYTE = 6, + ASUSAURACORELAPTOP_SPEED_BYTE = 7, + ASUSAURACORELAPTOP_DIRECTION_BYTE = 8, + ASUSAURACORELAPTOP_DATA_BYTE = 9, + ASUSAURACORELAPTOP_R2_BYTE = 10, + ASUSAURACORELAPTOP_G2_BYTE = 11, + ASUSAURACORELAPTOP_B2_BYTE = 12, +}; + +enum +{ + ASUSAURACORELAPTOP_REPORT_ID = 0x5D, + ASUSAURACORELAPTOP_CMD_BRIGHTNESS = 0xBA, + ASUSAURACORELAPTOP_CMD_DIRECT = 0xBC, + ASUSAURACORELAPTOP_CMD_POWER = 0xBD, + ASUSAURACORELAPTOP_CMD_UPDATE = 0xB3, + ASUSAURACORELAPTOP_CMD_APPLY = 0xB4, + ASUSAURACORELAPTOP_CMD_SET = 0xB5, + ASUSAURACORELAPTOP_CMD_LAYOUT = 0x05, +}; + +enum +{ + ASUSAURACORELAPTOP_SPEED_SLOWEST = 0xE1, // Slowest speed + ASUSAURACORELAPTOP_SPEED_NORMAL = 0xEB, // Normal speed + ASUSAURACORELAPTOP_SPEED_FASTEST = 0xF5, // Fastest speed +}; + +enum aura_core_laptop_layout +{ + ASUSAURACORELAPTOP_LAYOUT_ANSI = 0x01, /* US ANSI Layout */ + ASUSAURACORELAPTOP_LAYOUT_ISO = 0x02, /* EURO ISO Layout */ +}; + +struct p_state +{ + std::string zone; + bool state; +}; + +class AsusAuraCoreLaptopController +{ +public: + AsusAuraCoreLaptopController(hid_device* dev_handle, const char* path); + ~AsusAuraCoreLaptopController(); + + const aura_core_laptop_device* GetDeviceData(); + std::string GetDeviceDescription(); + std::string GetSerial(); + unsigned int GetKeyboardLayout(); + std::string GetLocation(); + + void SetMode(uint8_t mode, uint8_t speed, uint8_t brightness, RGBColor color1, RGBColor color2, uint8_t random, uint8_t direction); + void SetLedsDirect(std::vectorcolors); + void SendInitDirectMode(); +private: + hid_device* dev; + uint16_t device_index; + std::string location; + + uint8_t current_mode; + uint8_t current_speed; + uint8_t current_direction; + + RGBColor current_c1; + RGBColor current_c2; + uint8_t current_brightness; + uint8_t current_random; + + void SendApply(); + void SendBrightness(); + void SendSet(); + void SendUpdate(); + + void SetPowerConfigFromJSON(); + void SendPowerConfig(uint32_t flags); + uint32_t PackPowerFlags(bool flags[]); + std::vector PowerConfigArray(); +}; diff --git a/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/AsusAuraCoreLaptopDevices.cpp b/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/AsusAuraCoreLaptopDevices.cpp new file mode 100644 index 00000000..cfce2a1b --- /dev/null +++ b/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/AsusAuraCoreLaptopDevices.cpp @@ -0,0 +1,559 @@ +#include "AsusAuraCoreLaptopDevices.h" + +/*-------------------------------------------------------------------------*\ +| Aura Core Key Values | +| NULL values are keys that are handed to the KLM but are removed as | +| a part of customisation. They are included to maintain expected key | +| count is aligned to the value count. | +\*-------------------------------------------------------------------------*/ + +std::vector aura_core_laptop_15_values = +{ + /* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 DEL */ + 21, 23, 24, 25, 26, 28, 29, 30, 31, 33, 34, 35, 36, + /* BKTK 1 2 3 4 5 6 7 8 9 0 - = BSPC PLAY */ + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + /* TAB Q W E R T Y U I O P [ ] \ STOP */ + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + /* CPLK A S D F G H J K L ; " # ENTR PREV */ + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 98, + /* LSFT ISO\ Z X C V B N M , . / RSFT ARWU NEXT */ + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 119, + /* LCTL LWIN LALT SPC RALT RFNC RMNU RCTL ARWL ARWD ARWR */ + 126, 128, 129, 131, 135, 136, 136, 137, +}; + +std::vector aura_core_laptop_17_values = +{ + /* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 NULL NULL PAUS */ + 21, 23, 24, 25, 26, 28, 29, 30, 31, 33, 34, 35, 36, 0, 0, 39, + /* BKTK 1 2 3 4 5 6 7 8 9 0 - = BSPC NULL NULL NULL NMLK NMDV NMTM NMMI */ + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 56, 0, 0, 0, 59, 60, 61, 62, + /* TAB Q W E R T Y U I O P [ ] \ NULL NULL NULL NM7 NM8 NM9 NMPL */ + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 0, 0, 0, 80, 81, 82, 83, + /* CPLK A S D F G H J K L ; " # ENTR NM4 NM5 NM6 */ + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 98, 101, 102, 103, + /* LSFT ISO\ Z X C V B N M , . / RSFT ARWU NM1 NM2 NM3 NMER */ + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 119, 139, 122, 123, 124, 125, + /* LCTL LWIN LALT SPC RALT RFNC RMNU RCTL ARWL ARWD ARWR NM0 NMPD */ + 126, 128, 129, 131, 135, 136, 136, 137, 159, 160, 161, 144, 145, +}; + +std::vector aura_core_laptop_18_values = +{ + /* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 NULL NULL PAUS */ + 21, 23, 24, 25, 26, 28, 29, 30, 31, 33, 34, 35, 36, 0, 0, 39, + /* BKTK 1 2 3 4 5 6 7 8 9 0 - = BSPC NULL NULL NULL NMLK NMDV NMTM NMMI */ + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 56, 0, 0, 0, 59, 60, 61, 62, + /* TAB Q W E R T Y U I O P [ ] \ NULL NULL NULL NM7 NM8 NM9 NMPL */ + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 0, 0, 0, 80, 81, 82, 83, + /* CPLK A S D F G H J K L ; " # ENTR NM4 NM5 NM6 */ + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 98, 101, 102, 103, + /* LSFT ISO\ Z X C V B N M , . / RSFT ARWU NM1 NM2 NM3 NMER */ + 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 119, 121, 122, 123, 124, 125, + /* LCTL LWIN LALT SPC RALT RFNC RMNU RCTL ARWL ARWD ARWR NM0 NMPD */ + 126, 128, 129, 131, 135, 136, 136, 137, 141, 142, 143, 144, 145, +}; + +/*-------------------------------------------------------------------------*\ +| KEYMAPS | +\*-------------------------------------------------------------------------*/ +keyboard_keymap_overlay_values g533zm_layout +{ + KEYBOARD_SIZE_SEVENTY_FIVE, + { + aura_core_laptop_15_values, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 15, 37, KEY_EN_DELETE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Delete + { 0, 1, 15, 58, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Play / Pause + { 0, 2, 15, 79, KEY_EN_MEDIA_STOP, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Stop + { 0, 3, 15, 100, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Previous + { 0, 4, 13, 139, KEY_EN_UP_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Up Arrow + { 0, 4, 15, 121, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Next + { 0, 5, 12, 159, KEY_EN_LEFT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Left Arrow + { 0, 5, 13, 160, KEY_EN_DOWN_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Down Arrow + { 0, 5, 14, 161, KEY_EN_RIGHT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Right Arrow + } +}; + +keyboard_keymap_overlay_values g533zw_layout +{ + KEYBOARD_SIZE_SEVENTY_FIVE, + { + aura_core_laptop_15_values, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 15, 37, KEY_EN_DELETE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Delete + { 0, 1, 15, 58, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Play / Pause + { 0, 2, 15, 79, KEY_EN_MEDIA_STOP, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Stop + { 0, 3, 15, 100, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Previous + { 0, 4, 15, 121, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Media Next + { 0, 5, 1, 127, KEY_EN_LEFT_FUNCTION, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Left Function key + { 0, 5, 4, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Remove Unused key + { 0, 5, 11, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Remove Right Func key + { 0, 5, 11, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Remove Right Context key + { 0, 5, 13, 139, KEY_EN_UP_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Up Arrow + { 0, 5, 15, 142, KEY_EN_PRINT_SCREEN, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Print Screen + { 0, 5, 16, 175, "Keystone", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Keystone (Red only) + { 0, 6, 12, 159, KEY_EN_LEFT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Left Arrow on new row + { 0, 6, 13, 160, KEY_EN_DOWN_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Down Arrow + { 0, 6, 14, 161, KEY_EN_RIGHT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Right Arrow + { 0, 0, 2, 2, KEY_EN_MEDIA_VOLUME_DOWN, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, // Insert Row before function keys + { 0, 0, 3, 3, KEY_EN_MEDIA_VOLUME_UP, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Vol Up + { 0, 0, 4, 4, "Mic On / Off", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Mic On / Off + { 0, 0, 5, 5, "Hyperfan", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Hyperfan + { 0, 0, 6, 6, "Armoury Crate", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Armoury Crate + } +}; + +keyboard_keymap_overlay_values g533zw_lid_layout +{ + KEYBOARD_SIZE_EMPTY, + { + { /* Values not set in empty keyboard */ }, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 167, "Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar L1 + { 0, 0, 1, 176, "Vertical Cut Left", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar L2 + { 0, 0, 2, 177, "Vertical Cut Right", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar L3 + } +}; + +keyboard_keymap_overlay_values g533zw_lightbar_layout +{ + KEYBOARD_SIZE_EMPTY, + { + { /* Values not set in empty keyboard */ }, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 174, "Lightbar L1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar L1 + { 0, 0, 1, 173, "Lightbar L2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar L2 + { 0, 0, 2, 172, "Lightbar L3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar L3 + { 0, 0, 3, 171, "Lightbar R3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar R3 + { 0, 0, 4, 170, "Lightbar R2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar R2 + { 0, 0, 5, 169, "Lightbar R1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar R1 + } +}; + +keyboard_keymap_overlay_values g713rw_keyboard_layout +{ + KEYBOARD_SIZE_FULL, + { + aura_core_laptop_17_values, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 2, 2, KEY_EN_MEDIA_VOLUME_DOWN, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, // Insert Row and add Volume Down + { 0, 0, 3, 3, KEY_EN_MEDIA_VOLUME_UP, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Volume Up + { 0, 0, 4, 4, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Mute + { 0, 0, 5, 5, "Key: Fan", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert "Fan" key + { 0, 0, 6, 6, "Key: ROG", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert "ROG" key + { 0, 6, 1, 127, KEY_EN_LEFT_FUNCTION, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Left Fuction + { 0, 6, 8, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Remove part of Spacebar + { 0, 6, 8, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Remove part of Spacebar + { 0, 6, 10, 136, KEY_EN_RIGHT_FUNCTION, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Remove Right Fuction + { 0, 6, 10, 136, KEY_EN_RIGHT_WINDOWS, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Remove Right Win Key + + { 0, 1, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 1, 15, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // trim extra column before numpad + { 0, 1, 15, 38, KEY_EN_DELETE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert a Delete key + { 0, 1, 17, 40, KEY_EN_PRINT_SCREEN, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert a Print Screen key + { 0, 1, 18, 41, KEY_EN_HOME, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert a Home key + { 0, 2, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 2, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 3, 13, 76, KEY_EN_ANSI_BACK_SLASH, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Force ANSI | even on ISO layouts + { 0, 3, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 3, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 4, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 4, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 5, 12, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // gap before arrow up key + { 0, 5, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // trim extra column before numpad + + { 0, 6, 11, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // 1 empty key before arrow keys + { 0, 6, 15, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // trim extra column before numpad + { 0, 6, 16, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // 1 empty key between numpad 0 and . + + // Close numpad gap completely + { 0, 1, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 2, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 3, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 4, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 5, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 6, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + + // Move Arrow keys + { 0, 5, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Arrow Up + { 0, 6, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Arrow Down + { 0, 6, 12, 139, KEY_EN_UP_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Shift Arrow Up + { 0, 7, 11, 159, KEY_EN_LEFT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 7, 12, 160, KEY_EN_DOWN_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 7, 13, 161, KEY_EN_RIGHT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + } +}; + +keyboard_keymap_overlay_values g713rw_lightbar_layout +{ + KEYBOARD_SIZE_EMPTY, + { + { /* Values not set in empty keyboard */ }, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 174, "Lightbar L1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar L1 + { 0, 0, 1, 173, "Lightbar L2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar L2 + { 0, 0, 2, 172, "Lightbar L3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar L3 + { 0, 0, 3, 171, "Lightbar R3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar R3 + { 0, 0, 4, 170, "Lightbar R2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar R2 + { 0, 0, 5, 169, "Lightbar R1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar R1 + } +}; + +keyboard_keymap_overlay_values g713rw_test_layout +{ + KEYBOARD_SIZE_EMPTY, + { + { /* Values not set in empty keyboard */ }, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 7, "Test01", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 1, 8, "Test02", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 2, 9, "Test03", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 3, 10, "Test04", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 4, 11, "Test05", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 5, 12, "Test06", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 6, 13, "Test07", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 7, 14, "Test08", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 8, 15, "Test09", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 9, 16, "Test10", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 10, 17, "Test11", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 11, 18, "Test12", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 12, 19, "Test13", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 13, 20, "Test14", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 14, 22, "Test15", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 15, 27, "Test16", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 16, 55, "Test17", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 17, 57, "Test18", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 18, 58, "Test19", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 19, 77, "Test20", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 20, 78, "Test21", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 21, 79, "Test22", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 22, 96, "Test23", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 23, 97, "Test24", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 24, 99, "Test25", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 25, 100, "Test26", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 26, 104, "Test27", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 27, 117, "Test28", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 28, 118, "Test29", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 29, 120, "Test30", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 30, 121, "Test31", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 31, 130, "Test32", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 32, 132, "Test33", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 33, 133, "Test34", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 34, 134, "Test35", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 35, 138, "Test36", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 36, 140, "Test37", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 37, 141, "Test38", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 38, 142, "Test39", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 39, 143, "Test40", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 40, 146, "Test41", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 41, 147, "Test42", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 42, 148, "Test43", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 43, 149, "Test44", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 44, 150, "Test45", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 45, 151, "Test46", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 46, 152, "Test47", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 47, 153, "Test48", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 48, 154, "Test49", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 49, 155, "Test50", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 50, 156, "Test51", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 51, 157, "Test52", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 52, 158, "Test53", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 53, 162, "Test54", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 54, 163, "Test55", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 55, 164, "Test56", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 56, 165, "Test57", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 57, 166, "Test58", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 58, 167, "Test59", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + } +}; + +keyboard_keymap_overlay_values g733zm_layout +{ + KEYBOARD_SIZE_FULL, + { + aura_core_laptop_17_values, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + } +}; + +keyboard_keymap_overlay_values g814jv_keyboard_layout +{ + KEYBOARD_SIZE_FULL, + { + aura_core_laptop_18_values, + { + /* Add more regional layout fixes here */ + } + }, + { + /*------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 2, 2, KEY_EN_MEDIA_VOLUME_DOWN, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, // Insert Row and add Volume Down + { 0, 0, 3, 3, KEY_EN_MEDIA_VOLUME_UP, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Volume Up + { 0, 0, 4, 4, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Mute + { 0, 0, 5, 5, "Key: Fan", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert "Fan" key + { 0, 0, 6, 6, "Key: ROG", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert "ROG" key + { 0, 6, 8, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Remove part of Spacebar + { 0, 6, 8, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Remove part of Spacebar + { 0, 6, 1, 127, KEY_EN_LEFT_FUNCTION, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Left Fuction + { 0, 6, 10, 136, KEY_EN_PRINT_SCREEN, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Replace Right Fuction with PrtSc + { 0, 6, 11, 0, KEY_EN_RIGHT_WINDOWS, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Remove Right Win Key + { 0, 1, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 1, 14, 38, KEY_EN_DELETE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert a Delete key + { 0, 1, 16, 40, KEY_EN_PRINT_SCREEN, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert a Print Screen key + { 0, 1, 17, 41, KEY_EN_HOME, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert a Home key + { 0, 2, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 2, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 2, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 3, 13, 76, KEY_EN_ANSI_BACK_SLASH, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Force ANSI | even on ISO layouts + { 0, 3, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 3, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Numpad gap + { 0, 3, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 4, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 4, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 4, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 5, 12, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 5, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 5, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + { 0, 6, 15, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + } +}; + +keyboard_keymap_overlay_values g814jv_lightbar_layout +{ + KEYBOARD_SIZE_EMPTY, + { + { /* Values not set in empty keyboard */ }, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 173, "Lightbar L1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar L1 + { 0, 0, 1, 172, "Lightbar L2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar L2 + { 0, 0, 2, 170, "Lightbar R2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar R2 + { 0, 0, 3, 169, "Lightbar R1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lightbar R2 + } +}; + + +/*-------------------------------------------------------------------------*\ +| AURA CORE LAPTOP DEVICES | +\*-------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------*\ +| ASUS ROG Strix SCAR 15 G533ZM | +| | +| Zone "Keyboard" | +| Matrix | +| 7 Rows, 16 Columns | +\*-------------------------------------------------------------*/ +static const aura_core_laptop_zone g533zm_zone = +{ + ZONE_EN_KEYBOARD, + &g533zm_layout +}; + +static const aura_core_laptop_device g533zm_device = +{ + "G533ZM", + { + &g533zm_zone, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr + } +}; + +/*-------------------------------------------------------------*\ +| ASUS ROG Strix SCAR 15 G533ZW | +| | +| Zone "Keyboard" | +| Matrix | +| 7 Rows, 16 Columns | +\*-------------------------------------------------------------*/ +static const aura_core_laptop_zone g533zw_lid_zone = +{ + "Lid", + &g533zw_lid_layout +}; + +static const aura_core_laptop_zone g533zw_kb_zone = +{ + ZONE_EN_KEYBOARD, + &g533zw_layout +}; + +static const aura_core_laptop_zone g533zw_lightbar_zone = +{ + "Lightbar", + &g533zw_lightbar_layout +}; + +static const aura_core_laptop_device g533zw_device = +{ + "G533ZW", + { + &g533zw_kb_zone, + &g533zw_lid_zone, + &g533zw_lightbar_zone, + nullptr, + nullptr, + nullptr + } +}; + +/*-------------------------------------------------------------*\ +| ASUS ROG Strix SCAR G713RW | +| | +| Zone "Keyboard" | +| Matrix | +| 7 Rows, 20 Columns | +\*-------------------------------------------------------------*/ +static const aura_core_laptop_zone g713rw_keyboard_zone = +{ + ZONE_EN_KEYBOARD, + &g713rw_keyboard_layout +}; + +static const aura_core_laptop_zone g713rw_lightbar_zone = +{ + "Lightbar", + &g713rw_lightbar_layout +}; + +static const aura_core_laptop_device g713rw_device = +{ + "G713RW", + { + &g713rw_keyboard_zone, + &g713rw_lightbar_zone, + nullptr, + nullptr, + nullptr, + nullptr + } +}; +/*-------------------------------------------------------------*\ +| ASUS ROG Strix G18 (G814JV) | +| | +| Zone "Keyboard" | +| Matrix | +| 7 Rows, 16 Columns | +\*-------------------------------------------------------------*/ + +static const aura_core_laptop_zone g814rw_keyboard_zone = +{ + ZONE_EN_KEYBOARD, + &g814jv_keyboard_layout +}; + +static const aura_core_laptop_zone g814jv_lightbar_zone = +{ + "Lightbar", + &g814jv_lightbar_layout +}; + +static const aura_core_laptop_device g814jv_device = +{ + "G814JV", + { + &g814rw_keyboard_zone, + &g814jv_lightbar_zone, + nullptr, + nullptr, + nullptr, + nullptr + } +}; + +/*-------------------------------------------------------------------------*\ +| DEVICE MASTER LIST | +\*-------------------------------------------------------------------------*/ +const aura_core_laptop_device* aura_core_laptop_device_list_data[] = +{ +/*-----------------------------------------------------------------*\ +| KEYBOARDS | +\*-----------------------------------------------------------------*/ + &g533zm_device, + &g533zw_device, + &g713rw_device, + &g814jv_device, +}; + +const unsigned int AURA_CORE_LAPTOP_DEVICE_COUNT = (sizeof(aura_core_laptop_device_list_data) / sizeof(aura_core_laptop_device_list_data[ 0 ])); +const aura_core_laptop_device** aura_core_laptop_device_list = aura_core_laptop_device_list_data; diff --git a/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/AsusAuraCoreLaptopDevices.h b/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/AsusAuraCoreLaptopDevices.h new file mode 100644 index 00000000..d030db6d --- /dev/null +++ b/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/AsusAuraCoreLaptopDevices.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include +#include "RGBController.h" +#include "RGBControllerKeyNames.h" +#include "KeyboardLayoutManager.h" + +#define AURA_CORE_LAPTOP_ZONES_MAX 6 + +enum aura_core_kb_layout +{ + AURA_CORE_LAPTOP_KB_LAYOUT_ANSI = 0x01, /* US ANSI Layout */ + AURA_CORE_LAPTOP_KB_LAYOUT_ISO = 0x02, /* EURO ISO Layout */ + AURA_CORE_LAPTOP_KB_LAYOUT_ABNT = 0x03, /* Brazilian Layout */ + AURA_CORE_LAPTOP_KB_LAYOUT_JIS = 0x04, /* Japanese Layout */ +}; + +typedef struct +{ + std::string name; + keyboard_keymap_overlay_values* layout_new; +} aura_core_laptop_zone; + +typedef struct +{ + uint8_t zone; + uint8_t row; + uint8_t col; + uint8_t index; + const char* name; +} aura_core_laptop_led; + +typedef struct +{ + std::string dmi_name; + const aura_core_laptop_zone* zones[AURA_CORE_LAPTOP_ZONES_MAX]; +} aura_core_laptop_device; + +/*-----------------------------------------------------*\ +| Aura Core Laptop Protocol Keyboards | +\*-----------------------------------------------------*/ +#define AURA_STRIX_SCAR_15_PID 0x19B6 + +/*-----------------------------------------------------*\ +| These constant values are defined in | +| AsusAuraCoreLaptopDevices.cpp | +\*-----------------------------------------------------*/ +extern const unsigned int AURA_CORE_LAPTOP_DEVICE_COUNT; +extern const aura_core_laptop_device** aura_core_laptop_device_list; diff --git a/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/RGBController_AsusAuraCoreLaptop.cpp b/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/RGBController_AsusAuraCoreLaptop.cpp new file mode 100644 index 00000000..8f6adc3e --- /dev/null +++ b/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/RGBController_AsusAuraCoreLaptop.cpp @@ -0,0 +1,444 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraCoreLaptop.cpp | +| | +| RGBController for ASUS ROG Aura Core Laptop | +| | +| Chris M (Dr_No) 28 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_AsusAuraCoreLaptop.h" + +/**------------------------------------------------------------------*\ + @name AsusAuraCoreLaptop + @category DEVICE_TYPE_KEYBOARD + @type USB + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectAsusAuraCoreLaptopControllers + @comment Power profiles for this controller are set to `On` for all power + state and scan be adjusted in the JSON config file. + + For each zone available LEDs can be set as `On = true` or `Off = false` when + * Booting + * Awake (Normal Usage) + * Sleeping + * Shutdown / Power Off + + MatrixMaps can be found in ArmouryCrate (it needs a chance to download device data) + Default path is: + C:\ProgramData\ASUS\ROG Live Service\DeviceContent\\.csv + (Model name is the code like G814JV - can be found in the error in logs) +\*-------------------------------------------------------------------*/ + +RGBController_AsusAuraCoreLaptop::RGBController_AsusAuraCoreLaptop(AsusAuraCoreLaptopController *controller_ptr) +{ + controller = controller_ptr; + const aura_core_laptop_device* aura_dev = controller->GetDeviceData(); + + name = aura_dev->dmi_name; + vendor = "Asus"; + type = DEVICE_TYPE_LAPTOP; + description = controller->GetDeviceDescription(); + serial = controller->GetSerial(); + location = controller->GetLocation(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = ASUSAURACORELAPTOP_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; + Direct.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Direct.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Static; + Static.name = "Static"; + Static.value = ASUSAURACORELAPTOP_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.resize(Static.colors_max); + Static.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; + Static.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Static.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Static.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; + Static.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = ASUSAURACORELAPTOP_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Breathing.colors_min = 1; + Breathing.colors_max = 2; + Breathing.colors.resize(Breathing.colors_min); + Breathing.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; + Breathing.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Breathing.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Breathing.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; + Breathing.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; + modes.push_back(Breathing); + + mode Flashing; + Flashing.name = "Flashing"; + Flashing.value = ASUSAURACORELAPTOP_MODE_FLASHING; + Flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Flashing.colors_min = 1; + Flashing.colors_max = 1; + Flashing.colors.resize(Flashing.colors_max); + Flashing.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; + Flashing.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Flashing.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Flashing.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; + Flashing.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; + Flashing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Flashing.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; + modes.push_back(Flashing); + + mode Spectrum; + Spectrum.name = "Spectrum Cycle"; + Spectrum.value = ASUSAURACORELAPTOP_MODE_SPECTRUM; + Spectrum.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Spectrum.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; + Spectrum.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Spectrum.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Spectrum.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; + Spectrum.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; + Spectrum.color_mode = MODE_COLORS_NONE; + Spectrum.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; + modes.push_back(Spectrum); + + mode Rainbow; + Rainbow.name = "Rainbow Wave"; + Rainbow.value = ASUSAURACORELAPTOP_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD; + Rainbow.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; + Rainbow.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Rainbow.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Rainbow.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; + Rainbow.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; + Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; + modes.push_back(Rainbow); + + mode Starry; + Starry.name = "Starry Night"; + Starry.value = ASUSAURACORELAPTOP_MODE_STARRY_NIGHT; + Starry.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Starry.colors_min = 1; + Starry.colors_max = 2; + Starry.colors.resize(Starry.colors_min); + Starry.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; + Starry.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Starry.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Starry.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; + Starry.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; + Starry.color_mode = MODE_COLORS_MODE_SPECIFIC; + Starry.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; + modes.push_back(Starry); + + mode Rain; + Rain.name = "Rain"; + Rain.value = ASUSAURACORELAPTOP_MODE_RAIN; + Rain.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Rain.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; + Rain.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Rain.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Rain.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; + Rain.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; + Rain.color_mode = MODE_COLORS_NONE; + Rain.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; + modes.push_back(Rain); + + mode ReactFade; + ReactFade.name = "Reactive - Fade"; + ReactFade.value = ASUSAURACORELAPTOP_MODE_REACT_FADE; + ReactFade.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + ReactFade.colors_min = 1; + ReactFade.colors_max = 1; + ReactFade.colors.resize(ReactFade.colors_max); + ReactFade.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; + ReactFade.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + ReactFade.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + ReactFade.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; + ReactFade.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; + ReactFade.color_mode = MODE_COLORS_MODE_SPECIFIC; + ReactFade.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; + modes.push_back(ReactFade); + + mode ReactLaser; + ReactLaser.name = "Reactive - Laser"; + ReactLaser.value = ASUSAURACORELAPTOP_MODE_REACT_LASER; + ReactLaser.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + ReactLaser.colors_min = 1; + ReactLaser.colors_max = 1; + ReactLaser.colors.resize(ReactLaser.colors_max); + ReactLaser.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; + ReactLaser.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + ReactLaser.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + ReactLaser.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; + ReactLaser.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; + ReactLaser.color_mode = MODE_COLORS_MODE_SPECIFIC; + ReactLaser.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; + modes.push_back(ReactLaser); + + mode ReactRipple; + ReactRipple.name = "Reactive - Ripple"; + ReactRipple.value = ASUSAURACORELAPTOP_MODE_REACT_RIPPLE; + ReactRipple.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + ReactRipple.colors_min = 1; + ReactRipple.colors_max = 1; + ReactRipple.colors.resize(ReactRipple.colors_max); + ReactRipple.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; + ReactRipple.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + ReactRipple.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + ReactRipple.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; + ReactRipple.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; + ReactRipple.color_mode = MODE_COLORS_MODE_SPECIFIC; + ReactRipple.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; + modes.push_back(ReactRipple); + + mode Comet; + Comet.name = "Comet"; + Comet.value = ASUSAURACORELAPTOP_MODE_COMET; + Comet.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + Comet.colors_min = 1; + Comet.colors_max = 1; + Comet.colors.resize(Comet.colors_max); + Comet.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; + Comet.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Comet.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Comet.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; + Comet.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; + Comet.color_mode = MODE_COLORS_MODE_SPECIFIC; + Comet.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; + modes.push_back(Comet); + + mode FlashNDash; + FlashNDash.name = "Flash N Dash"; + FlashNDash.value = ASUSAURACORELAPTOP_MODE_FLASHNDASH; + FlashNDash.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + FlashNDash.colors_min = 1; + FlashNDash.colors_max = 1; + FlashNDash.colors.resize(FlashNDash.colors_max); + FlashNDash.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; + FlashNDash.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + FlashNDash.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + FlashNDash.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; + FlashNDash.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; + FlashNDash.color_mode = MODE_COLORS_MODE_SPECIFIC; + FlashNDash.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; + modes.push_back(FlashNDash); + + mode Keystone; + Keystone.name = "Keystone"; + Keystone.value = ASUSAURACORELAPTOP_MODE_KEYSTONE; + Keystone.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Keystone.colors_min = 1; + Keystone.colors_max = 1; + Keystone.colors.resize(Keystone.colors_max); + Keystone.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; + Keystone.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Keystone.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; + Keystone.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; + Keystone.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; + Keystone.color_mode = MODE_COLORS_MODE_SPECIFIC; + Keystone.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; + modes.push_back(Keystone); + + mode Off; + Off.name = "Off"; + Off.value = ASUSAURACORELAPTOP_MODE_OFF; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + SetupZones(); + + SetMode(active_mode); +} + +RGBController_AsusAuraCoreLaptop::~RGBController_AsusAuraCoreLaptop() +{ + delete controller; +} + +void RGBController_AsusAuraCoreLaptop::SetupZones() +{ + std::string physical_size; + KEYBOARD_LAYOUT new_layout; + unsigned int max_led_value = 0; + + const aura_core_laptop_device* aura_dev = controller->GetDeviceData(); + unsigned int layout = controller->GetKeyboardLayout(); + + switch(layout) + { + case ASUSAURACORELAPTOP_LAYOUT_ISO: + new_layout = KEYBOARD_LAYOUT_ISO_QWERTY; + break; + + case ASUSAURACORELAPTOP_LAYOUT_ANSI: + default: + new_layout = KEYBOARD_LAYOUT_ANSI_QWERTY; + break; + } + LOG_DEBUG("[%s] layout set as %d", description.c_str(), new_layout); + + /*---------------------------------------------------------*\ + | Fill in zones from the device data | + \*---------------------------------------------------------*/ + for(size_t i = 0; i < AURA_CORE_LAPTOP_ZONES_MAX; i++) + { + LOG_DEBUG("[%s] setting up zone %d", description.c_str(), i); + + if(aura_dev->zones[i] == NULL) + { + break; + } + else + { + zone new_zone; + + new_zone.name = aura_dev->zones[i]->name; + + if(aura_dev->zones[i]->layout_new != NULL) + { + KeyboardLayoutManager new_kb(new_layout, + aura_dev->zones[i]->layout_new->base_size, + aura_dev->zones[i]->layout_new->key_values); + + if(aura_dev->zones[i]->layout_new->base_size != KEYBOARD_SIZE_EMPTY || + aura_dev->zones[i]->layout_new->edit_keys.size() > 0) + { + /*---------------------------------------------------------*\ + | Minor adjustments to keyboard layout | + \*---------------------------------------------------------*/ + keyboard_keymap_overlay_values* temp = aura_dev->zones[i]->layout_new; + new_kb.ChangeKeys(*temp); + + if(new_kb.GetRowCount() == 1 || new_kb.GetColumnCount() == 1) + { + if(new_kb.GetKeyCount() == 1) + { + new_zone.type = ZONE_TYPE_SINGLE; + } + else + { + new_zone.type = ZONE_TYPE_LINEAR; + } + } + else + { + new_zone.type = ZONE_TYPE_MATRIX; + matrix_map_type * new_map = new matrix_map_type; + new_zone.matrix_map = new_map; + + /*---------------------------------------------------------*\ + | Trusting the layout handed to the KLM is correct use the | + | row & column counts to set the matrix height & width | + \*---------------------------------------------------------*/ + new_map->height = new_kb.GetRowCount(); + new_map->width = new_kb.GetColumnCount(); + new_map->map = new unsigned int[new_map->height * new_map->width]; + + new_kb.GetKeyMap(new_map->map, KEYBOARD_MAP_FILL_TYPE_COUNT); + } + + /*---------------------------------------------------------*\ + | Create LEDs for the Matrix zone | + | Place keys in the layout to populate the matrix | + \*---------------------------------------------------------*/ + new_zone.leds_count = new_kb.GetKeyCount(); + for(unsigned int led_idx = 0; led_idx < new_zone.leds_count; led_idx++) + { + led new_led; + + new_led.name = new_kb.GetKeyNameAt(led_idx); + new_led.value = new_kb.GetKeyValueAt(led_idx); + max_led_value = std::max(max_led_value, new_led.value); + leds.push_back(new_led); + } + } + + /*---------------------------------------------------------*\ + | Add 1 the max_led_value to account for the 0th index | + \*---------------------------------------------------------*/ + max_led_value++; + } + + LOG_DEBUG("[%s] Creating a %s zone: %s with %d LEDs", name.c_str(), + ((new_zone.type == ZONE_TYPE_MATRIX) ? "matrix": "linear"), + new_zone.name.c_str(), new_zone.leds_count); + new_zone.leds_min = new_zone.leds_count; + new_zone.leds_max = new_zone.leds_count; + zones.push_back(new_zone); + } + } + + SetupColors(); + + /*---------------------------------------------------------*\ + | Create a buffer map of pointers which contains the | + | layout order of colors the device expects. | + \*---------------------------------------------------------*/ + buffer_map.resize(max_led_value, &null_color); + + for(size_t led_idx = 0; led_idx < leds.size(); led_idx++) + { + buffer_map[leds[led_idx].value] = &colors[led_idx]; + } +} + +void RGBController_AsusAuraCoreLaptop::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_AsusAuraCoreLaptop::DeviceUpdateLEDs() +{ + for(size_t i = 85; i < leds.size(); i++) + { + LOG_DEBUG("[%s] Setting %s @ LED index %d and buffer index %d to R: %02X G: %02X B: %02X", + name.c_str(), + leds[i].name.c_str(), + i, + leds[i].value, + RGBGetRValue(colors[i]), + RGBGetGValue(colors[i]), + RGBGetBValue(colors[i])); + } + + controller->SetLedsDirect(buffer_map); +} + +void RGBController_AsusAuraCoreLaptop::UpdateZoneLEDs(int /*zone*/) +{ + controller->SetLedsDirect(buffer_map); +} + +void RGBController_AsusAuraCoreLaptop::UpdateSingleLED(int /*led*/) +{ + controller->SetLedsDirect(buffer_map); +} + +void RGBController_AsusAuraCoreLaptop::DeviceUpdateMode() +{ + mode set_mode = modes[active_mode]; + + uint8_t random = (set_mode.color_mode == MODE_COLORS_RANDOM) ? 0xFF : 0; + RGBColor color1 = (set_mode.colors.size() > 0) ? set_mode.colors[0] : 0; + RGBColor color2 = (set_mode.colors.size() > 1) ? set_mode.colors[1] : 0; + + controller->SetMode(set_mode.value, set_mode.speed, set_mode.brightness, color1, color2, random, set_mode.direction ); +} diff --git a/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/RGBController_AsusAuraCoreLaptop.h b/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/RGBController_AsusAuraCoreLaptop.h new file mode 100644 index 00000000..16e40a65 --- /dev/null +++ b/Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController/RGBController_AsusAuraCoreLaptop.h @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraCoreLaptop.h | +| | +| RGBController for ASUS ROG Aura Core Laptop | +| | +| Chris M (Dr_No) 28 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" +#include "AsusAuraCoreLaptopController.h" + +class RGBController_AsusAuraCoreLaptop : public RGBController +{ +public: + RGBController_AsusAuraCoreLaptop(AsusAuraCoreLaptopController* controller_ptr); + ~RGBController_AsusAuraCoreLaptop(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RGBColor null_color = 0; + std::vector buffer_map; + + AsusAuraCoreLaptopController* controller; +}; diff --git a/Controllers/AsusAuraCoreController/RGBController_AsusAuraCore.h b/Controllers/AsusAuraCoreController/RGBController_AsusAuraCore.h deleted file mode 100644 index 67f94f1c..00000000 --- a/Controllers/AsusAuraCoreController/RGBController_AsusAuraCore.h +++ /dev/null @@ -1,34 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraCore.h | -| | -| Generic RGB Interface for ROG Aura Core | -| | -| Adam Honse (CalcProgrammer1) 4/17/2020 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "AsusAuraCoreController.h" - -class RGBController_AuraCore : public RGBController -{ -public: - RGBController_AuraCore(AuraCoreController* controller_ptr); - ~RGBController_AuraCore(); - - void SetupKeyboard(); - void SetupGA15DH(); - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - AuraCoreController* controller; -}; diff --git a/Controllers/AsusAuraCoreController/RGBController_AsusAuraCoreLaptop.cpp b/Controllers/AsusAuraCoreController/RGBController_AsusAuraCoreLaptop.cpp deleted file mode 100644 index 8a6f2765..00000000 --- a/Controllers/AsusAuraCoreController/RGBController_AsusAuraCoreLaptop.cpp +++ /dev/null @@ -1,491 +0,0 @@ -/*---------------------------------------------------------------------*\ -| RGBController_AsusAuraCoreLaptop.cpp | -| | -| Driver for AsusAuraCoreLaptop USB Controller | -| | -| Chris M (Dr_No) 28 Jul 2022 | -| | -\*---------------------------------------------------------------------*/ - -#include "RGBController_AsusAuraCoreLaptop.h" - -static unsigned int matrix_map[ASUSAURACORELAPTOP_KEY_HEIGHT][ASUSAURACORELAPTOP_KEY_WIDTH] = -{ - { NA, NA, 86, 87, 88, 89, 90, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA }, - { 0, NA, 1, 2, 3, 4, NA, 5, 6, 7, 8, NA, 9, 10, 11, 12, 13, NA }, - { 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, NA }, - { 31, NA, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, NA, 45, NA }, - { 46, NA, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, NA, 58, NA, 59, NA }, - { 60, NA, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, NA, 72, NA, 73, NA }, - { 74, 75, 76, 77, NA, NA, NA, 78, NA, NA, NA, 79, 80, 81, 82, 83, 84, 85 } -}; - -static const char *led_names[] = -{ - KEY_EN_ESCAPE, //00 - KEY_EN_F1, - KEY_EN_F2, - KEY_EN_F3, - KEY_EN_F4, - KEY_EN_F5, - KEY_EN_F6, - KEY_EN_F7, - KEY_EN_F8, - KEY_EN_F9, - KEY_EN_F10, //10 - KEY_EN_F11, - KEY_EN_F12, - KEY_EN_DELETE, - - KEY_EN_BACK_TICK, - KEY_EN_1, - KEY_EN_2, - KEY_EN_3, - KEY_EN_4, - KEY_EN_5, - KEY_EN_6, //20 - KEY_EN_7, - KEY_EN_8, - KEY_EN_9, - KEY_EN_0, - KEY_EN_MINUS, - KEY_EN_EQUALS, - KEY_EN_BACKSPACE, - KEY_EN_BACKSPACE, - KEY_EN_BACKSPACE, - KEY_EN_MEDIA_PLAY_PAUSE, //30 - - KEY_EN_TAB, - KEY_EN_Q, - KEY_EN_W, - KEY_EN_E, - KEY_EN_R, - KEY_EN_T, - KEY_EN_Y, - KEY_EN_U, - KEY_EN_I, - KEY_EN_O, //40 - KEY_EN_P, - KEY_EN_LEFT_BRACKET, - KEY_EN_RIGHT_BRACKET, - KEY_EN_ANSI_BACK_SLASH, - KEY_EN_MEDIA_STOP, - - KEY_EN_CAPS_LOCK, - KEY_EN_A, - KEY_EN_S, - KEY_EN_D, - KEY_EN_F, //50 - KEY_EN_G, - KEY_EN_H, - KEY_EN_J, - KEY_EN_K, - KEY_EN_L, - KEY_EN_SEMICOLON, - KEY_EN_QUOTE, - KEY_EN_ANSI_ENTER, - KEY_EN_MEDIA_PREVIOUS, - - KEY_EN_LEFT_SHIFT, //60 - KEY_EN_Z, - KEY_EN_X, - KEY_EN_C, - KEY_EN_V, - KEY_EN_B, - KEY_EN_N, - KEY_EN_M, - KEY_EN_COMMA, - KEY_EN_PERIOD, - KEY_EN_FORWARD_SLASH, //70 - KEY_EN_RIGHT_SHIFT, - KEY_EN_UP_ARROW, - KEY_EN_MEDIA_NEXT, - - KEY_EN_LEFT_CONTROL, - KEY_EN_LEFT_FUNCTION, - KEY_EN_LEFT_WINDOWS, - KEY_EN_LEFT_ALT, - KEY_EN_SPACE, - KEY_EN_RIGHT_ALT, - KEY_EN_RIGHT_CONTROL, //80 - KEY_EN_LEFT_ARROW, - KEY_EN_DOWN_ARROW, - KEY_EN_RIGHT_ARROW, - KEY_EN_PRINT_SCREEN, - "Asus Keystone", - - KEY_EN_MEDIA_VOLUME_DOWN, - KEY_EN_MEDIA_VOLUME_UP, - "Key: Mic On/Off", - "Key: HyperFan", - "Key: Armoury Crate", //90 - - "Lightbar LED 1", - "Lightbar LED 2", - "Lightbar LED 3", - "Lightbar LED 4", - "Lightbar LED 5", - "Lightbar LED 6", - - "Logo", - "Lid Left", - "Lid Right", //99 -}; - -/**------------------------------------------------------------------*\ - @name AsusAuraCoreLaptop - @category DEVICE_TYPE_KEYBOARD - @type USB - @save :x: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectAsusAuraCoreLaptopControllers - @comment Power profiles for this controller are set to `On` for all power - state and scan be adjusted in the JSON config file. - - For each zone available LEDs can be set as `On = true` or `Off = false` when - * Booting - * Awake (Normal Usage) - * Sleeping - * Shutdown / Power Off -\*-------------------------------------------------------------------*/ - -RGBController_AsusAuraCoreLaptop::RGBController_AsusAuraCoreLaptop(AsusAuraCoreLaptopController *controller_ptr) -{ - controller = controller_ptr; - - name = "Asus Aura Core Laptop"; - vendor = "Asus"; - type = DEVICE_TYPE_KEYBOARD; - description = controller->GetDeviceName(); - serial = controller->GetSerial(); - location = controller->GetLocation(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = ASUSAURACORELAPTOP_MODE_DIRECT; - 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 = ASUSAURACORELAPTOP_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Static.colors_min = 1; - Static.colors_max = 1; - Static.colors.resize(Static.colors_max); - Static.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; - Static.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Static.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Static.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; - Static.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; - Static.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; - modes.push_back(Static); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = ASUSAURACORELAPTOP_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Breathing.colors_min = 1; - Breathing.colors_max = 2; - Breathing.colors.resize(Breathing.colors_min); - Breathing.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; - Breathing.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Breathing.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Breathing.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; - Breathing.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; - modes.push_back(Breathing); - - mode Flashing; - Flashing.name = "Flashing"; - Flashing.value = ASUSAURACORELAPTOP_MODE_FLASHING; - Flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Flashing.colors_min = 1; - Flashing.colors_max = 1; - Flashing.colors.resize(Flashing.colors_max); - Flashing.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; - Flashing.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Flashing.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Flashing.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; - Flashing.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; - Flashing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Flashing.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; - modes.push_back(Flashing); - - mode Spectrum; - Spectrum.name = "Spectrum Cycle"; - Spectrum.value = ASUSAURACORELAPTOP_MODE_SPECTRUM; - Spectrum.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; - Spectrum.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; - Spectrum.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Spectrum.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Spectrum.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; - Spectrum.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; - Spectrum.color_mode = MODE_COLORS_NONE; - Spectrum.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; - modes.push_back(Spectrum); - - mode Rainbow; - Rainbow.name = "Rainbow Wave"; - Rainbow.value = ASUSAURACORELAPTOP_MODE_RAINBOW; - Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD; - Rainbow.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; - Rainbow.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Rainbow.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Rainbow.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; - Rainbow.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; - Rainbow.color_mode = MODE_COLORS_NONE; - Rainbow.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; - modes.push_back(Rainbow); - - mode Starry; - Starry.name = "Starry Night"; - Starry.value = ASUSAURACORELAPTOP_MODE_STARRY_NIGHT; - Starry.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Starry.colors_min = 1; - Starry.colors_max = 2; - Starry.colors.resize(Starry.colors_min); - Starry.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; - Starry.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Starry.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Starry.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; - Starry.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; - Starry.color_mode = MODE_COLORS_MODE_SPECIFIC; - Starry.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; - modes.push_back(Starry); - - mode Rain; - Rain.name = "Rain"; - Rain.value = ASUSAURACORELAPTOP_MODE_RAIN; - Rain.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; - Rain.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; - Rain.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Rain.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Rain.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; - Rain.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; - Rain.color_mode = MODE_COLORS_NONE; - Rain.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; - modes.push_back(Rain); - - mode ReactFade; - ReactFade.name = "Reactive - Fade"; - ReactFade.value = ASUSAURACORELAPTOP_MODE_REACT_FADE; - ReactFade.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - ReactFade.colors_min = 1; - ReactFade.colors_max = 1; - ReactFade.colors.resize(ReactFade.colors_max); - ReactFade.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; - ReactFade.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - ReactFade.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - ReactFade.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; - ReactFade.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; - ReactFade.color_mode = MODE_COLORS_MODE_SPECIFIC; - ReactFade.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; - modes.push_back(ReactFade); - - mode ReactLaser; - ReactLaser.name = "Reactive - Laser"; - ReactLaser.value = ASUSAURACORELAPTOP_MODE_REACT_LASER; - ReactLaser.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - ReactLaser.colors_min = 1; - ReactLaser.colors_max = 1; - ReactLaser.colors.resize(ReactLaser.colors_max); - ReactLaser.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; - ReactLaser.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - ReactLaser.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - ReactLaser.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; - ReactLaser.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; - ReactLaser.color_mode = MODE_COLORS_MODE_SPECIFIC; - ReactLaser.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; - modes.push_back(ReactLaser); - - mode ReactRipple; - ReactRipple.name = "Reactive - Ripple"; - ReactRipple.value = ASUSAURACORELAPTOP_MODE_REACT_RIPPLE; - ReactRipple.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - ReactRipple.colors_min = 1; - ReactRipple.colors_max = 1; - ReactRipple.colors.resize(ReactRipple.colors_max); - ReactRipple.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; - ReactRipple.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - ReactRipple.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - ReactRipple.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; - ReactRipple.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; - ReactRipple.color_mode = MODE_COLORS_MODE_SPECIFIC; - ReactRipple.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; - modes.push_back(ReactRipple); - - mode Comet; - Comet.name = "Comet"; - Comet.value = ASUSAURACORELAPTOP_MODE_COMET; - Comet.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; - Comet.colors_min = 1; - Comet.colors_max = 1; - Comet.colors.resize(Comet.colors_max); - Comet.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; - Comet.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Comet.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Comet.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; - Comet.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; - Comet.color_mode = MODE_COLORS_MODE_SPECIFIC; - Comet.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; - modes.push_back(Comet); - - mode FlashNDash; - FlashNDash.name = "Flash N Dash"; - FlashNDash.value = ASUSAURACORELAPTOP_MODE_FLASHNDASH; - FlashNDash.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; - FlashNDash.colors_min = 1; - FlashNDash.colors_max = 1; - FlashNDash.colors.resize(FlashNDash.colors_max); - FlashNDash.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; - FlashNDash.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - FlashNDash.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - FlashNDash.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; - FlashNDash.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; - FlashNDash.color_mode = MODE_COLORS_MODE_SPECIFIC; - FlashNDash.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; - modes.push_back(FlashNDash); - - mode Keystone; - Keystone.name = "Keystone"; - Keystone.value = ASUSAURACORELAPTOP_MODE_KEYSTONE; - Keystone.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Keystone.colors_min = 1; - Keystone.colors_max = 1; - Keystone.colors.resize(Keystone.colors_max); - Keystone.brightness_min = ASUSAURACORELAPTOP_BRIGHTNESS_MIN; - Keystone.brightness_max = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Keystone.brightness = ASUSAURACORELAPTOP_BRIGHTNESS_MAX; - Keystone.speed_min = ASUSAURACORELAPTOP_SPEED_SLOWEST; - Keystone.speed_max = ASUSAURACORELAPTOP_SPEED_FASTEST; - Keystone.color_mode = MODE_COLORS_MODE_SPECIFIC; - Keystone.speed = ASUSAURACORELAPTOP_SPEED_NORMAL; - modes.push_back(Keystone); - - mode Off; - Off.name = "Off"; - Off.value = ASUSAURACORELAPTOP_MODE_OFF; - Off.color_mode = MODE_COLORS_NONE; - modes.push_back(Off); - - Init_Controller(); - SetupZones(); -} - -RGBController_AsusAuraCoreLaptop::~RGBController_AsusAuraCoreLaptop() -{ - delete controller; -} - -void RGBController_AsusAuraCoreLaptop::Init_Controller() -{ - /*-------------------------------------------------*\ - | Create the keyboard zone and add the matix map | - \*-------------------------------------------------*/ - zone KB_zone; - KB_zone.name = "Keyboard Zone"; - KB_zone.type = ZONE_TYPE_MATRIX; - KB_zone.leds_min = ASUSAURACORELAPTOP_KEYCOUNT; - KB_zone.leds_max = ASUSAURACORELAPTOP_KEYCOUNT; - KB_zone.leds_count = ASUSAURACORELAPTOP_KEYCOUNT; - - KB_zone.matrix_map = new matrix_map_type; - KB_zone.matrix_map->height = ASUSAURACORELAPTOP_KEY_HEIGHT; - KB_zone.matrix_map->width = ASUSAURACORELAPTOP_KEY_WIDTH; - KB_zone.matrix_map->map = (unsigned int *)&matrix_map; - zones.push_back(KB_zone); - - zone lightbar; - lightbar.name = "Lightbar Zone"; - lightbar.type = ZONE_TYPE_LINEAR; - lightbar.leds_min = ASUSAURACORELAPTOP_LIGHTBARCOUNT; - lightbar.leds_max = ASUSAURACORELAPTOP_LIGHTBARCOUNT; - lightbar.leds_count = ASUSAURACORELAPTOP_LIGHTBARCOUNT; - zones.push_back(lightbar); - - zone lid; - lid.name = "Lid Zone"; - lid.type = ZONE_TYPE_LINEAR; - lid.leds_min = ASUSAURACORELAPTOP_LIDCOUNT; - lid.leds_max = ASUSAURACORELAPTOP_LIDCOUNT; - lid.leds_count = ASUSAURACORELAPTOP_LIDCOUNT; - zones.push_back(lid); -} - -void RGBController_AsusAuraCoreLaptop::SetupZones() -{ - /*-------------------------------------------------*\ - | Clear any existing color/LED configuration | - \*-------------------------------------------------*/ - leds.clear(); - colors.clear(); - - /*---------------------------------------------------------*\ - | Set up zones | - \*---------------------------------------------------------*/ - for(std::size_t zone_index = 0; zone_index < zones.size(); zone_index++) - { - int zone_offset = leds.size(); - - for(unsigned int led_index = 0; led_index < zones[zone_index].leds_count; led_index++) - { - led new_led; - new_led.value = led_index + zone_offset; - new_led.name = led_names[new_led.value]; - leds.push_back(new_led); - } - } - - SetupColors(); -} - -void RGBController_AsusAuraCoreLaptop::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_AsusAuraCoreLaptop::DeviceUpdateLEDs() -{ - controller->SetLedsDirect(colors); -} - -void RGBController_AsusAuraCoreLaptop::UpdateZoneLEDs(int zone) -{ - std::vector colour; - for(size_t i = 0; i < zones[zone].leds_count; i++) - { - colour.push_back(zones[zone].colors[i]); - } - - controller->SetLedsDirect(colour); -} - -void RGBController_AsusAuraCoreLaptop::UpdateSingleLED(int led) -{ - std::vector colour; - colour.push_back(colors[led]); - - controller->SetLedsDirect(colour); -} - -void RGBController_AsusAuraCoreLaptop::DeviceUpdateMode() -{ - mode set_mode = modes[active_mode]; - - if(set_mode.value == ASUSAURACORELAPTOP_MODE_DIRECT) - { - return; - } - uint8_t random = (set_mode.color_mode == MODE_COLORS_RANDOM) ? 0xFF : 0; - RGBColor color1 = (set_mode.colors.size() > 0) ? set_mode.colors[0] : 0; - RGBColor color2 = (set_mode.colors.size() > 1) ? set_mode.colors[1] : 0; - - controller->SetMode(set_mode.value, set_mode.speed, set_mode.brightness, color1, color2, random, set_mode.direction ); -} diff --git a/Controllers/AsusAuraCoreController/RGBController_AsusAuraCoreLaptop.h b/Controllers/AsusAuraCoreController/RGBController_AsusAuraCoreLaptop.h deleted file mode 100644 index 6c18aa10..00000000 --- a/Controllers/AsusAuraCoreController/RGBController_AsusAuraCoreLaptop.h +++ /dev/null @@ -1,35 +0,0 @@ -/*---------------------------------------------------------------------*\ -| RGBController_AsusAuraCoreLaptop.h | -| | -| Driver for AsusAuraCoreLaptop USB Controller | -| | -| Chris M (Dr_No) 28 Jul 2022 | -| | -\*---------------------------------------------------------------------*/ - -#pragma once - -#include -#include "RGBController.h" -#include "AsusAuraCoreLaptopController.h" - -class RGBController_AsusAuraCoreLaptop : public RGBController -{ -public: - RGBController_AsusAuraCoreLaptop(AsusAuraCoreLaptopController* controller_ptr); - ~RGBController_AsusAuraCoreLaptop(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - void Init_Controller(); - - AsusAuraCoreLaptopController* controller; -}; diff --git a/Controllers/AsusAuraGPUController/AsusAuraGPUController.cpp b/Controllers/AsusAuraGPUController/AsusAuraGPUController.cpp index 1e7920b7..c8cfecf4 100644 --- a/Controllers/AsusAuraGPUController/AsusAuraGPUController.cpp +++ b/Controllers/AsusAuraGPUController/AsusAuraGPUController.cpp @@ -1,20 +1,23 @@ -/*-----------------------------------------*\ -| AsusAuraGPUController.cpp | -| | -| Driver for ASUS Aura RGB on GPUs | -| | -| Jan Rettig (Klapstuhl) 14.02.2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| AsusAuraGPUController.cpp | +| | +| Driver for ASUS Aura GPU | +| | +| Jan Rettig (Klapstuhl) 14 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "AsusAuraGPUController.h" #include +#include "AsusAuraGPUController.h" +#include "pci_ids.h" -AuraGPUController::AuraGPUController(i2c_smbus_interface* bus, aura_gpu_dev_id dev) +AuraGPUController::AuraGPUController(i2c_smbus_interface* bus, aura_gpu_dev_id dev, std::string dev_name) { - this->bus = bus; - this->dev = dev; - - strcpy(device_name, "ASUS Aura GPU"); // Would be nice to get the actual GPU name. Using this as a placeholder. + this->bus = bus; + this->dev = dev; + this->name = dev_name; } AuraGPUController::~AuraGPUController() @@ -24,7 +27,7 @@ AuraGPUController::~AuraGPUController() std::string AuraGPUController::GetDeviceName() { - return(device_name); + return(name); } std::string AuraGPUController::GetDeviceLocation() @@ -52,25 +55,16 @@ unsigned char AuraGPUController::GetLEDBlue() return(AuraGPURegisterRead(AURA_GPU_REG_BLUE)); } -void AuraGPUController::SetLEDColorsDirect(unsigned char red, unsigned char green, unsigned char blue) // Direct Mode is just Static Mode without applying color changes +void AuraGPUController::SetLEDColors(unsigned char red, unsigned char green, unsigned char blue) { AuraGPURegisterWrite(AURA_GPU_REG_RED, red); AuraGPURegisterWrite(AURA_GPU_REG_GREEN, green); AuraGPURegisterWrite(AURA_GPU_REG_BLUE, blue); } -void AuraGPUController::SetLEDColorsEffect(unsigned char red, unsigned char green, unsigned char blue) -{ - AuraGPURegisterWrite(AURA_GPU_REG_RED, red); - AuraGPURegisterWrite(AURA_GPU_REG_GREEN, green); - AuraGPURegisterWrite(AURA_GPU_REG_BLUE, blue); - AuraGPURegisterWrite(AURA_GPU_REG_APPLY, AURA_GPU_APPLY_VAL); -} - void AuraGPUController::SetMode(unsigned char mode) { AuraGPURegisterWrite(AURA_GPU_REG_MODE, mode); - AuraGPURegisterWrite(AURA_GPU_REG_APPLY, AURA_GPU_APPLY_VAL); } unsigned char AuraGPUController::AuraGPURegisterRead(unsigned char reg) @@ -81,4 +75,21 @@ unsigned char AuraGPUController::AuraGPURegisterRead(unsigned char reg) void AuraGPUController::AuraGPURegisterWrite(unsigned char reg, unsigned char val) { bus->i2c_smbus_write_byte_data(dev, reg, val); -} \ No newline at end of file +} + +bool AuraGPUController::SaveOnlyApplies() +{ + switch (bus->pci_subsystem_device) + { + case ASUS_VEGA64_STRIX: + return false; + } + // Behavior on other GPU models is unknown and needs to be tested. + // Assume the safest option to prevent damaage from excessive writes. + return false; +} + +void AuraGPUController::Save() +{ + AuraGPURegisterWrite(AURA_GPU_REG_APPLY, AURA_GPU_APPLY_VAL); +} diff --git a/Controllers/AsusAuraGPUController/AsusAuraGPUController.h b/Controllers/AsusAuraGPUController/AsusAuraGPUController.h index 4ab07e34..fa414342 100644 --- a/Controllers/AsusAuraGPUController/AsusAuraGPUController.h +++ b/Controllers/AsusAuraGPUController/AsusAuraGPUController.h @@ -1,16 +1,19 @@ -/*-----------------------------------------*\ -| AsusAuraGPUController.h | -| | -| Definitions for ASUS Aura RGB on GPUs | -| | -| Jan Rettig (Klapstuhl) 14.02.2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| AsusAuraGPUController.h | +| | +| Driver for ASUS Aura GPU | +| | +| Jan Rettig (Klapstuhl) 14 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" -#pragma once - typedef unsigned char aura_gpu_dev_id; #define AURA_GPU_MAGIC_VAL 0x1589 /* This magic value is present in all Aura GPU controllers */ @@ -23,7 +26,7 @@ enum AURA_GPU_REG_BLUE = 0x06, /* AURA GPU BLUE Register */ AURA_GPU_REG_MODE = 0x07, /* AURA GPU Mode Selection Register */ AURA_GPU_REG_SYNC = 0x0C, /* AURA GPU "Sync" Register */ - AURA_GPU_REG_APPLY = 0x0E, /* AURA GPU Apply Chnages Register */ + AURA_GPU_REG_APPLY = 0x0E, /* AURA GPU Save or Apply Register */ }; enum @@ -40,7 +43,7 @@ enum class AuraGPUController { public: - AuraGPUController(i2c_smbus_interface* bus, aura_gpu_dev_id); + AuraGPUController(i2c_smbus_interface* bus, aura_gpu_dev_id, std::string dev_name); ~AuraGPUController(); std::string GetDeviceName(); @@ -48,17 +51,18 @@ public: unsigned char GetLEDRed(); unsigned char GetLEDGreen(); unsigned char GetLEDBlue(); - void SetLEDColorsDirect(unsigned char red, unsigned char green, unsigned char blue); - void SetLEDColorsEffect(unsigned char red, unsigned char green, unsigned char blue); + void SetLEDColors(unsigned char red, unsigned char green, unsigned char blue); void SetMode(unsigned char mode); + void Save(); unsigned char AuraGPURegisterRead(unsigned char reg); void AuraGPURegisterWrite(unsigned char reg, unsigned char val); + bool SaveOnlyApplies(); bool direct = false; // Temporary solution to check if we are in "Direct" mode private: - char device_name[16]; i2c_smbus_interface * bus; aura_gpu_dev_id dev; -}; \ No newline at end of file + std::string name; +}; diff --git a/Controllers/AsusAuraGPUController/AsusAuraGPUControllerDetect.cpp b/Controllers/AsusAuraGPUController/AsusAuraGPUControllerDetect.cpp index 9ddb99b7..6e500892 100644 --- a/Controllers/AsusAuraGPUController/AsusAuraGPUControllerDetect.cpp +++ b/Controllers/AsusAuraGPUController/AsusAuraGPUControllerDetect.cpp @@ -1,21 +1,20 @@ -/*-----------------------------------------*\ -| AsusAuraGPUControllerDetect.cpp | -| | -| Driver for ASUS Aura RGB on GPUs | -| | -| Jan Rettig (Klapstuhl) 14.02.2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| AsusAuraGPUControllerDetect.cpp | +| | +| Detector for ASUS Aura GPU | +| | +| Jan Rettig (Klapstuhl) 14 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "Detector.h" #include "AsusAuraGPUController.h" #include "LogManager.h" -#include "RGBController.h" #include "RGBController_AsusAuraGPU.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include #define ASUSGPU_CONTROLLER_NAME "ASUS Aura GPU" @@ -57,80 +56,93 @@ void DetectAsusAuraGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, co { if(TestForAsusAuraGPUController(bus, i2c_addr)) { - AuraGPUController* controller = new AuraGPUController(bus, i2c_addr); + AuraGPUController* controller = new AuraGPUController(bus, i2c_addr, name); RGBController_AuraGPU* rgb_controller = new RGBController_AuraGPU(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } /* DetectAsusAuraGPUControllers() */ /*-----------------------------------------*\ -| NVidia GPUs | +| Nvidia GPUs | \*-----------------------------------------*/ -REGISTER_I2C_PCI_DETECTOR("ASUS ROG Strix GTX 1050 O2G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1050_DEV, ASUS_SUB_VEN, ASUS_GTX1050_STRIX_O2G_GAMING, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG Strix GTX 1050 TI 4G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1050TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1050TI_4G_GAMING, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG Strix GTX 1050 TI O4G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1050TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1050TI_O4G_GAMING, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG Strix GTX 1050 TI O4G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1050TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1050TI_O4G_GAMING_2, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS GTX 1060 Strix 6G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, ASUS_SUB_VEN, ASUS_GTX1060_STRIX_6G_GAMING, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS GTX 1060 Strix" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, ASUS_SUB_VEN, ASUS_GTX1060_STRIX, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS GTX 1070 Strix Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, ASUS_SUB_VEN, ASUS_GTX1070_STRIX_GAMING, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS GTX 1070 Strix OC" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, ASUS_SUB_VEN, ASUS_GTX1070_STRIX_OC, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG Strix GTX1070 Ti 8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1070TI_8G_GAMING, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG Strix GTX1070 Ti A8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1070TI_A8G_GAMING, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS GTX 1080 Strix OC" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, ASUS_SUB_VEN, ASUS_GTX1080_STRIX, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG Strix GTX1080 A8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080_A8G_GAMING, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG Strix GTX1080 O8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080_O8G_GAMING, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG Strix GTX1080 O8G 11Gbps" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080_O8G_11GBPS, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG Strix GTX1080 Ti Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080TI_GAMING, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG Strix GTX1080 Ti 11G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080TI_11G_GAMING, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG Strix GTX1080 Ti O11G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080TI_O11G_GAMING, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG Strix GTX1080 Ti O11G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080TI_O11G_GAMING_A02, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG Strix GTX 1650S OC 4G" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1650S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1650S_OC, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG Strix GTX 1660S O6G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1660S_O6G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG GTX 1660 Ti OC 6G" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660TI_DEV, ASUS_SUB_VEN, ASUS_ROG_GTX1660TI_OC, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2060 EVO Gaming 6G" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060_EVO_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2060 O6G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060_O6G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2060 O6G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060_O6G_GAMING_86D2, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2060 O6G EVO Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU104_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060_O6G_EVO_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2060S 8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060S_8G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2060S A8G EVO Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060S_A8G_EVO_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2060S O8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060S_O8G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2060S A8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060S_A8G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2070 A8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070_A8G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2070 O8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070_O8G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2070S A8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070S_A8G_GAMING_86FF, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2070S A8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070S_A8G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2070S A8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070S_A8G_GAMING_8706, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2070S O8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070S_O8G_GAMING_8729, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2070S 8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070S_8G_GAMING_8707, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2070S O8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070S_O8G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2080 8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080_8G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2080 O8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080_O8G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2080 O8G V2 Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080_O8G_V2_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2080S A8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080S_A8G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2080S O8G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080S_O8G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2080S O8G White" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080S_O8G_WHITE, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2080 Ti 11G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080TI_11G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2080 Ti 11G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080TI_11G_GAMING_866C, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2080 Ti A11G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080TI_A11G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 2080 Ti O11G Gaming" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080TI_O11G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3060 Ti 8G Gaming OC" , DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3060_TI_O8G_OC, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1050 Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1050_DEV, ASUS_SUB_VEN, ASUS_GTX1050_STRIX_O2G_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1050 Ti Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1050TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1050TI_4G_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1050 Ti Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1050TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1050TI_O4G_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1050 Ti Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1050TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1050TI_O4G_GAMING_2, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1060 Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1060_6G_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1060 Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1060, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1060 Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1060_865B, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1070 Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1070_8G_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1070 Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1070_O8G_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1070 OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1070_OC, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1070 Ti Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1070TI_8G_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1070 A8G Ti Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1070TI_A8G_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1080 Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, ASUS_SUB_VEN, ASUS_GTX1080_STRIX, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1080 A8G Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080_A8G_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1080 Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080_O8G_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1080 Gaming OC 11Gbps", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080_O8G_11GBPS, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1080 Ti Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080TI_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1080 Ti Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080TI_11G_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1080 Ti Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080TI_O11G_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1080 Ti Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1080TI_O11G_GAMING_A02, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG Poseidon GeForce GTX 1080 Ti", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_POSEIDON_GTX1080TI, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1650 SUPER A4G Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1650S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1650S_A4G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1650 SUPER Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1650S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1650S_OC, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1660 SUPER Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1660S_O6G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1660 SUPER Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_GTX1660S_6G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce GTX 1660 Ti Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660TI_DEV, ASUS_SUB_VEN, ASUS_ROG_GTX1660TI_OC, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2060 Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060_6G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2060 Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060_O6G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2060 Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060_O6G_GAMING_86D2, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2060 EVO Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060_EVO_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2060 EVO V2 Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060_06G_EVO_V2_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2060 EVO Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU104_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060_O6G_EVO_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2060 SUPER Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060S_8G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2060 SUPER A8G EVO Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060S_A8G_EVO_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2060 SUPER Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060S_O8G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2060 SUPER Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060S_8G_GAMING_8702, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2060 SUPER A8G Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060S_A8G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2060 SUPER A8G Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2060S_A8G_GAMING_86FD, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2070 A8G Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070_A8G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2070 Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070_O8G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2070 SUPER A8G Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070S_A8G_GAMING_86FF, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2070 SUPER A8G Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070S_A8G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2070 SUPER A8G Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070S_A8G_GAMING_8706, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2070 SUPER Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070S_O8G_GAMING_8729, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2070 SUPER Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070S_8G_GAMING_8707, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2070 SUPER Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2070S_O8G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2080 Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080_8G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2080 Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080_O8G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2080 V2 Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080_O8G_V2_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2080 SUPER A8G Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080S_A8G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2080 SUPER Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080S_O8G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2080 SUPER White OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080S_O8G_WHITE, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2080 Ti Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080TI_11G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2080 Ti Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080TI_11G_GAMING_866C, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2080 Ti A11G Gaming", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080TI_A11G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 2080 Ti Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX2080TI_O11G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3060 Ti Gaming OC", DetectAsusAuraGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3060TI_O8G_OC, 0x2A); /*-----------------------------------------*\ | AMD GPUs | \*-----------------------------------------*/ -REGISTER_I2C_PCI_DETECTOR("ASUS AREZ Strix RX Vega 56 O8G" , DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_VEGA10_DEV, ASUS_SUB_VEN, ASUS_AREZ_STRIX_VEGA56_08G_GAMING, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS Vega 64 Strix" , DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_VEGA10_DEV, ASUS_SUB_VEN, ASUS_VEGA64_STRIX, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS RX 5600XT Strix O6G Gaming" , DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_NAVI10_DEV, ASUS_SUB_VEN, ASUS_RX5600XT_STRIX_O6G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS RX 5700XT Strix Gaming OC" , DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_NAVI10_DEV, ASUS_SUB_VEN, ASUS_RX5700XT_STRIX_GAMING_OC, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS RX 5700XT Strix 08G Gaming" , DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_NAVI10_DEV, ASUS_SUB_VEN, ASUS_RX5700XT_STRIX_O8G_GAMING, 0x2A); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RX470 O4G Gaming" , DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS_DEV, ASUS_SUB_VEN, ASUS_RX470_STRIX_O4G_GAMING, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RX480 Gaming OC" , DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS_DEV, ASUS_SUB_VEN, ASUS_RX480_STRIX_GAMING_OC, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RX560 Gaming" , DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS11, ASUS_SUB_VEN, ASUS_RX560_STRIX_4G_GAMING, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS RX 570 Strix O4G Gaming OC" , DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS_DEV, ASUS_SUB_VEN, ASUS_RX570_STRIX_O4G_GAMING_OC, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS RX 570 Strix O8G Gaming OC" , DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS_DEV, ASUS_SUB_VEN, ASUS_RX570_STRIX_O8G_GAMING_OC, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS RX 580 Strix Gaming OC" , DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS_DEV, ASUS_SUB_VEN, ASUS_RX580_STRIX_GAMING_OC, 0x29); -REGISTER_I2C_PCI_DETECTOR("ASUS RX 580 Strix Gaming TOP" , DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS_DEV, ASUS_SUB_VEN, ASUS_RX580_STRIX_GAMING_TOP, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS AREZ STRIX Radeon RX Vega 56 Gaming OC", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_VEGA10_DEV, ASUS_SUB_VEN, ASUS_AREZ_STRIX_VEGA56_08G_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon Vega 64", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_VEGA10_DEV, ASUS_SUB_VEN, ASUS_VEGA64_STRIX, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 470 Gaming OC", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS_DEV, ASUS_SUB_VEN, ASUS_RX470_STRIX_O4G_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 480 Gaming", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS_DEV, ASUS_SUB_VEN, ASUS_RX480_STRIX_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 480 Gaming OC", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS_DEV, ASUS_SUB_VEN, ASUS_RX480_STRIX_GAMING_OC, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 560 Gaming", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS11, ASUS_SUB_VEN, ASUS_RX560_STRIX_4G_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 560 Gaming", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS11, ASUS_SUB_VEN, ASUS_RX560_STRIX_4G_GAMING_04BE, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 570 Gaming OC", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS_DEV, ASUS_SUB_VEN, ASUS_RX570_STRIX_O4G_GAMING_OC, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 570 Gaming OC", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS_DEV, ASUS_SUB_VEN, ASUS_RX570_STRIX_O8G_GAMING_OC, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 580 Gaming OC", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS_DEV, ASUS_SUB_VEN, ASUS_RX580_STRIX_GAMING_OC, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 580 Gaming TOP", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS_DEV, ASUS_SUB_VEN, ASUS_RX580_STRIX_GAMING_TOP, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 590 Gaming", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_POLARIS_DEV, ASUS_SUB_VEN, ASUS_RX590_STRIX_GAMING, 0x29); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 5600 XT Gaming OC", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_NAVI10_DEV, ASUS_SUB_VEN, ASUS_RX5600XT_STRIX_O6G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 5700 Gaming OC", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_NAVI10_DEV, ASUS_SUB_VEN, ASUS_RX5700_STRIX_GAMING_OC, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 5700 XT Gaming OC", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_NAVI10_DEV, ASUS_SUB_VEN, ASUS_RX5700XT_STRIX_GAMING_OC, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 5700 XT Gaming OC", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_NAVI10_DEV, ASUS_SUB_VEN, ASUS_RX5700XT_STRIX_O8G_GAMING, 0x2A); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 5700 XT Gaming OC", DetectAsusAuraGPUControllers, AMD_GPU_VEN, AMD_NAVI10_DEV, ASUS_SUB_VEN, ASUS_RX5700XT_STRIX_O8G_GAMING_05C3, 0x2A); diff --git a/Controllers/AsusAuraGPUController/RGBController_AsusAuraGPU.cpp b/Controllers/AsusAuraGPUController/RGBController_AsusAuraGPU.cpp index e1985a44..5f987e9b 100644 --- a/Controllers/AsusAuraGPUController/RGBController_AsusAuraGPU.cpp +++ b/Controllers/AsusAuraGPUController/RGBController_AsusAuraGPU.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraGPU.h | -| | -| Generic RGB Interface for Asus Aura GPU | -| | -| Jan Rettig (Klapstuhl) 14.02.2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraGPU.cpp | +| | +| RGBController for ASUS Aura GPU | +| | +| Jan Rettig (Klapstuhl) 14 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_AsusAuraGPU.h" @@ -29,7 +32,7 @@ int RGBController_AuraGPU::GetDeviceMode() break; } - for(std::size_t mode = 0; mode < modes.size(); mode++) + for(unsigned int mode = 0; mode < modes.size(); mode++) { if(modes[mode].value == dev_mode) { @@ -45,11 +48,15 @@ int RGBController_AuraGPU::GetDeviceMode() @name Asus Aura GPU @category GPU @type SMBus - @save :x: + @save :tools: @direct :white_check_mark: @effects :white_check_mark: @detectors DetectAsusAuraGPUControllers - @comment + @comment On some models save command might function like apply. + Known models with correctly working save: ASUS Vega 64 Strix. + This may result in changes not applying until user clicks + "save to device". Contact OpenRGB developers if you have one + of the affected models. \*-------------------------------------------------------------------*/ RGBController_AuraGPU::RGBController_AuraGPU(AuraGPUController * controller_ptr) @@ -69,38 +76,44 @@ RGBController_AuraGPU::RGBController_AuraGPU(AuraGPUController * controller_ptr) Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); + unsigned int save_flags = 0; + if(!controller->SaveOnlyApplies()) + { + save_flags |= MODE_FLAG_MANUAL_SAVE; + } + mode Off; Off.name = "Off"; Off.value = AURA_GPU_MODE_OFF; - Off.flags = 0; + Off.flags = save_flags; Off.color_mode = MODE_COLORS_NONE; modes.push_back(Off); mode Static; Static.name = "Static"; Static.value = AURA_GPU_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | save_flags; Static.color_mode = MODE_COLORS_PER_LED; modes.push_back(Static); mode Breathing; Breathing.name = "Breathing"; Breathing.value = AURA_GPU_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | save_flags; Breathing.color_mode = MODE_COLORS_PER_LED; modes.push_back(Breathing); mode Flashing; Flashing.name = "Flashing"; Flashing.value = AURA_GPU_MODE_FLASHING; - Flashing.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Flashing.flags = MODE_FLAG_HAS_PER_LED_COLOR | save_flags; Flashing.color_mode = MODE_COLORS_PER_LED; modes.push_back(Flashing); mode Spectrum_Cycle; Spectrum_Cycle.name = "Spectrum Cycle"; - Spectrum_Cycle.value = AURA_GPU_MODE_SPECTRUM_CYCLE; - Spectrum_Cycle.flags = 0; + Spectrum_Cycle.value = AURA_GPU_MODE_SPECTRUM_CYCLE ; + Spectrum_Cycle.flags = save_flags; Spectrum_Cycle.color_mode = MODE_COLORS_NONE; modes.push_back(Spectrum_Cycle); @@ -162,14 +175,11 @@ void RGBController_AuraGPU::DeviceUpdateLEDs() unsigned char grn = RGBGetGValue(colors[led]); unsigned char blu = RGBGetBValue(colors[led]); - if (GetMode() == 0) - { - controller->SetLEDColorsDirect(red, grn, blu); - } - else - { - controller->SetLEDColorsEffect(red, grn, blu); - } + controller->SetLEDColors(red, grn, blu); + } + if (controller->SaveOnlyApplies() && GetMode() != 0) + { + controller->Save(); } } @@ -192,7 +202,7 @@ void RGBController_AuraGPU::DeviceUpdateMode() { // Set all LEDs to 0 and Mode to static as a workaround for the non existing Off Mode case AURA_GPU_MODE_OFF: - controller->SetLEDColorsEffect(0, 0, 0); + controller->SetLEDColors(0, 0, 0); new_mode = AURA_GPU_MODE_STATIC; break; @@ -204,4 +214,13 @@ void RGBController_AuraGPU::DeviceUpdateMode() } controller->SetMode(new_mode); + if (controller->SaveOnlyApplies()) + { + controller->Save(); + } +} + +void RGBController_AuraGPU::DeviceSaveMode() +{ + controller->Save(); } diff --git a/Controllers/AsusAuraGPUController/RGBController_AsusAuraGPU.h b/Controllers/AsusAuraGPUController/RGBController_AsusAuraGPU.h index ee76b3b5..fbcd0779 100644 --- a/Controllers/AsusAuraGPUController/RGBController_AsusAuraGPU.h +++ b/Controllers/AsusAuraGPUController/RGBController_AsusAuraGPU.h @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraGPU.h | -| | -| Generic RGB Interface for Asus Aura GPU | -| | -| Jan Rettig (Klapstuhl) 14.02.2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraGPU.h | +| | +| RGBController for ASUS Aura GPU | +| | +| Jan Rettig (Klapstuhl) 14 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once @@ -26,6 +29,7 @@ public: void UpdateSingleLED(int led); void DeviceUpdateMode(); + void DeviceSaveMode(); private: AuraGPUController* controller; diff --git a/Controllers/AsusAuraUSBController/AsusAuraAddressableController.cpp b/Controllers/AsusAuraUSBController/AsusAuraAddressableController.cpp deleted file mode 100644 index 3b8c587d..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraAddressableController.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraAddressableController.cpp | -| | -| Driver for ASUS Aura RGB Addressable | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 1/18/2020 | -\*-----------------------------------------*/ - -#include "AsusAuraAddressableController.h" -#include - -AuraAddressableController::AuraAddressableController(hid_device* dev_handle, const char* path) : AuraUSBController(dev_handle, path) -{ - /*-----------------------------------------------------*\ - | Add addressable devices | - \*-----------------------------------------------------*/ - for(int i = 0; i < config_table[0x02]; ++i) - { - device_info.push_back({0x01, (unsigned char)i, 0x01, 0, AuraDeviceType::ADDRESSABLE}); - } -} - -AuraAddressableController::~AuraAddressableController() -{ - -} - -void AuraAddressableController::SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors) -{ - unsigned char led_data[60]; - unsigned int leds_sent = 0; - - while(leds_sent < num_colors) - { - unsigned int leds_to_send = 20; - - if((num_colors - leds_sent) < leds_to_send) - { - leds_to_send = num_colors - leds_sent; - } - - for(unsigned int led_idx = 0; led_idx < leds_to_send; led_idx++) - { - led_data[(led_idx * 3) + 0] = RGBGetRValue(colors[led_idx + leds_sent]); - led_data[(led_idx * 3) + 1] = RGBGetGValue(colors[led_idx + leds_sent]); - led_data[(led_idx * 3) + 2] = RGBGetBValue(colors[led_idx + leds_sent]); - } - - SendDirect - ( - channel, - leds_sent, - leds_to_send, - led_data - ); - - leds_sent += leds_to_send; - } - - SendDirectApply(channel); -} - -void AuraAddressableController::SetMode - ( - unsigned char channel, - unsigned char mode, - unsigned char red, - unsigned char grn, - unsigned char blu - ) -{ - SendEffect - ( - channel, - mode, - red, - grn, - blu - ); -} - -void AuraAddressableController::SendEffect - ( - unsigned char channel, - unsigned char mode, - unsigned char red, - unsigned char grn, - unsigned char blu - ) -{ - unsigned char usb_buf[65]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, sizeof(usb_buf)); - - /*-----------------------------------------------------*\ - | Set up message packet | - \*-----------------------------------------------------*/ - usb_buf[0x00] = 0xEC; - usb_buf[0x01] = AURA_ADDRESSABLE_CONTROL_MODE_EFFECT; - usb_buf[0x02] = channel; - usb_buf[0x03] = 0x00; - usb_buf[0x04] = mode; - - /*-----------------------------------------------------*\ - | Copy in color data bytes | - \*-----------------------------------------------------*/ - usb_buf[0x05] = red; - usb_buf[0x06] = grn; - usb_buf[0x07] = blu; - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); -} - -void AuraAddressableController::SendDirectApply - ( - unsigned char channel - ) -{ - unsigned char usb_buf[65]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, sizeof(usb_buf)); - - /*-----------------------------------------------------*\ - | Set up message packet | - \*-----------------------------------------------------*/ - usb_buf[0x00] = 0xEC; - usb_buf[0x01] = AURA_CONTROL_MODE_DIRECT; - usb_buf[0x02] = 0x80 | channel; - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); -} diff --git a/Controllers/AsusAuraUSBController/AsusAuraAddressableController.h b/Controllers/AsusAuraUSBController/AsusAuraAddressableController.h deleted file mode 100644 index f324219c..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraAddressableController.h +++ /dev/null @@ -1,60 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraAddressableController.h | -| | -| Definitions and types for ASUS Aura | -| Addressable RGB lighting controller | -| | -| Adam Honse (CalcProgrammer1) 1/18/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include "AsusAuraUSBController.h" - -#include -#include - -#pragma once - -enum -{ - AURA_ADDRESSABLE_CONTROL_MODE_EFFECT = 0x3B, /* Effect control mode */ -}; - -class AuraAddressableController : public AuraUSBController -{ -public: - AuraAddressableController(hid_device* dev_handle, const char* path); - ~AuraAddressableController(); - - void SetChannelLEDs - ( - unsigned char channel, - RGBColor * colors, - unsigned int num_colors - ); - - void SetMode - ( - unsigned char channel, - unsigned char mode, - unsigned char red, - unsigned char grn, - unsigned char blu - ); - -private: - - void SendEffect - ( - unsigned char channel, - unsigned char mode, - unsigned char red, - unsigned char grn, - unsigned char blu - ); - - void SendDirectApply - ( - unsigned char channel - ); -}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController.h b/Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController.h deleted file mode 100644 index 1cd1481c..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController.h +++ /dev/null @@ -1,62 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraHeadsetStandController.h | -| | -| Definitions and types for ASUS Aura | -| USB RGB lighting controller | -| | -| Mola19 06/04/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include - -#pragma once - -enum -{ - AURA_HEADSET_STAND_ZONE_UNDERGLOW = 0, - AURA_HEADSET_STAND_ZONE_LOGO = 1 -}; - -enum -{ - AURA_HEADSET_STAND_MODE_DIRECT = 0, - AURA_HEADSET_STAND_MODE_STATIC = 1, - AURA_HEADSET_STAND_MODE_BREATHING = 2, - AURA_HEADSET_STAND_MODE_STROBING = 3, - AURA_HEADSET_STAND_MODE_COLOR_CYCLE = 4, - AURA_HEADSET_STAND_MODE_RAINBOW = 5 -}; - -class AuraHeadsetStandController -{ -public: - AuraHeadsetStandController(hid_device* dev_handle, const char* path); - virtual ~AuraHeadsetStandController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - std::string GetVersion(); - - void UpdateLeds - ( - std::vector colors - ); - - void UpdateDevice - ( - unsigned char mode, - unsigned char red, - unsigned char grn, - unsigned char blu, - unsigned char speed, - unsigned char brightness - ); - - void SaveMode(); - -private: - hid_device* dev; - std::string location; -}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController.cpp b/Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController/AsusAuraHeadsetStandController.cpp similarity index 78% rename from Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController.cpp rename to Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController/AsusAuraHeadsetStandController.cpp index f99deab8..9d31a0eb 100644 --- a/Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController.cpp +++ b/Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController/AsusAuraHeadsetStandController.cpp @@ -1,20 +1,23 @@ -/*-----------------------------------------*\ -| AsusAuraHeadsetStandController.cpp | -| | -| Driver for ASUS Aura RGB USB | -| lighting controller | -| | -| Mola19 06/04/2021 | -\*-----------------------------------------*/ - -#include "AsusAuraHeadsetStandController.h" +/*---------------------------------------------------------*\ +| AsusAuraHeadsetStandController.cpp | +| | +| Driver for ASUS Aura headset stand | +| | +| Mola19 06 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "AsusAuraHeadsetStandController.h" +#include "StringUtils.h" -AuraHeadsetStandController::AuraHeadsetStandController(hid_device* dev_handle, const char* path) +AuraHeadsetStandController::AuraHeadsetStandController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } AuraHeadsetStandController::~AuraHeadsetStandController() @@ -27,6 +30,11 @@ std::string AuraHeadsetStandController::GetDeviceLocation() return("HID: " + location); } +std::string AuraHeadsetStandController::GetName() +{ + return(name); +} + std::string AuraHeadsetStandController::GetSerialString() { wchar_t serial_string[128]; @@ -37,10 +45,7 @@ std::string AuraHeadsetStandController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } std::string AuraHeadsetStandController::GetVersion() diff --git a/Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController/AsusAuraHeadsetStandController.h b/Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController/AsusAuraHeadsetStandController.h new file mode 100644 index 00000000..09411001 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController/AsusAuraHeadsetStandController.h @@ -0,0 +1,65 @@ +/*---------------------------------------------------------*\ +| AsusAuraHeadsetStandController.h | +| | +| Driver for ASUS Aura headset stand | +| | +| Mola19 06 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" + +enum +{ + AURA_HEADSET_STAND_ZONE_UNDERGLOW = 0, + AURA_HEADSET_STAND_ZONE_LOGO = 1 +}; + +enum +{ + AURA_HEADSET_STAND_MODE_DIRECT = 0, + AURA_HEADSET_STAND_MODE_STATIC = 1, + AURA_HEADSET_STAND_MODE_BREATHING = 2, + AURA_HEADSET_STAND_MODE_STROBING = 3, + AURA_HEADSET_STAND_MODE_COLOR_CYCLE = 4, + AURA_HEADSET_STAND_MODE_RAINBOW = 5 +}; + +class AuraHeadsetStandController +{ +public: + AuraHeadsetStandController(hid_device* dev_handle, const char* path, std::string dev_name); + virtual ~AuraHeadsetStandController(); + + std::string GetDeviceLocation(); + std::string GetName(); + std::string GetSerialString(); + std::string GetVersion(); + + void UpdateLeds + ( + std::vector colors + ); + + void UpdateDevice + ( + unsigned char mode, + unsigned char red, + unsigned char grn, + unsigned char blu, + unsigned char speed, + unsigned char brightness + ); + + void SaveMode(); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController/RGBController_AsusAuraHeadsetStand.cpp b/Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController/RGBController_AsusAuraHeadsetStand.cpp new file mode 100644 index 00000000..98993edf --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController/RGBController_AsusAuraHeadsetStand.cpp @@ -0,0 +1,211 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraHeadsetStand.cpp | +| | +| RGBController for ASUS Aura headset stand | +| | +| Mola19 06 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_AsusAuraHeadsetStand.h" + +/**------------------------------------------------------------------*\ + @name Asus Aura Headset Stand + @category HeadsetStand + @type USB + @save :white_check_mark: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectAsusAuraUSBHeadsetStand + @comment +\*-------------------------------------------------------------------*/ + +RGBController_AuraHeadsetStand::RGBController_AuraHeadsetStand(AuraHeadsetStandController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = "ASUS"; + type = DEVICE_TYPE_HEADSET_STAND; + description = "ASUS Aura Headset Stand Device"; + version = controller->GetVersion(); + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = AURA_HEADSET_STAND_MODE_DIRECT; + 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 = AURA_HEADSET_STAND_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Static.brightness_min = AURA_HEADSETSTAND_BRIGHTNESS_MIN; + Static.brightness_max = AURA_HEADSETSTAND_BRIGHTNESS_MAX; + Static.brightness = AURA_HEADSETSTAND_BRIGHTNESS_DEFAULT; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.resize(1); + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = AURA_HEADSET_STAND_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.speed_min = AURA_HEADSETSTAND_SPEED_MIN; + Breathing.speed_max = AURA_HEADSETSTAND_SPEED_MAX; + Breathing.speed = AURA_HEADSETSTAND_SPEED_DEFAULT; + Breathing.brightness_min = AURA_HEADSETSTAND_BRIGHTNESS_MIN; + Breathing.brightness_max = AURA_HEADSETSTAND_BRIGHTNESS_MAX; + Breathing.brightness = AURA_HEADSETSTAND_BRIGHTNESS_DEFAULT; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.colors.resize(1); + modes.push_back(Breathing); + + mode Strobing; + Strobing.name = "Flashing"; + Strobing.value = AURA_HEADSET_STAND_MODE_STROBING; + Strobing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Strobing.brightness_min = AURA_HEADSETSTAND_BRIGHTNESS_MIN; + Strobing.brightness_max = AURA_HEADSETSTAND_BRIGHTNESS_MAX; + Strobing.brightness = AURA_HEADSETSTAND_BRIGHTNESS_DEFAULT; + Strobing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Strobing.colors_min = 1; + Strobing.colors_max = 1; + Strobing.colors.resize(1); + modes.push_back(Strobing); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = AURA_HEADSET_STAND_MODE_COLOR_CYCLE; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + SpectrumCycle.speed_min = AURA_HEADSETSTAND_SPEED_MIN; + SpectrumCycle.speed_max = AURA_HEADSETSTAND_SPEED_MAX; + SpectrumCycle.speed = AURA_HEADSETSTAND_SPEED_DEFAULT; + SpectrumCycle.brightness_min = AURA_HEADSETSTAND_BRIGHTNESS_MIN; + SpectrumCycle.brightness_max = AURA_HEADSETSTAND_BRIGHTNESS_MAX; + SpectrumCycle.brightness = AURA_HEADSETSTAND_BRIGHTNESS_DEFAULT; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + modes.push_back(SpectrumCycle); + + mode Rainbow; + Rainbow.name = "Rainbow Wave"; + Rainbow.value = AURA_HEADSET_STAND_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Rainbow.speed_min = AURA_HEADSETSTAND_SPEED_MIN; + Rainbow.speed_max = AURA_HEADSETSTAND_SPEED_MAX; + Rainbow.speed = AURA_HEADSETSTAND_SPEED_DEFAULT; + Rainbow.brightness_min = AURA_HEADSETSTAND_BRIGHTNESS_MIN; + Rainbow.brightness_max = AURA_HEADSETSTAND_BRIGHTNESS_MAX; + Rainbow.brightness = AURA_HEADSETSTAND_BRIGHTNESS_DEFAULT; + modes.push_back(Rainbow); + SetupZones(); +} + +RGBController_AuraHeadsetStand::~RGBController_AuraHeadsetStand() +{ + delete controller; +} + +void RGBController_AuraHeadsetStand::SetupZones() +{ + zone underglow_zone; + + underglow_zone.name = "Underglow"; + underglow_zone.type = ZONE_TYPE_LINEAR; + underglow_zone.leds_min = 17; + underglow_zone.leds_max = 17; + underglow_zone.leds_count = 17; + underglow_zone.matrix_map = NULL; + + zones.push_back(underglow_zone); + + for(unsigned int i = 0; i < 17; i++) + { + led underglow_led; + + underglow_led.name = "Underglow LED " + std::to_string(i); + + leds.push_back(underglow_led); + } + + zone logo_zone; + + logo_zone.name = "Logo"; + logo_zone.type = ZONE_TYPE_SINGLE; + logo_zone.leds_min = 1; + logo_zone.leds_max = 1; + logo_zone.leds_count = 1; + logo_zone.matrix_map = NULL; + + zones.push_back(logo_zone); + + led logo_led; + + logo_led.name = "Logo LED"; + + leds.push_back(logo_led); + + SetupColors(); +} + +void RGBController_AuraHeadsetStand::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_AuraHeadsetStand::DeviceUpdateLEDs() +{ + controller->UpdateLeds(std::vector(colors)); +} + +void RGBController_AuraHeadsetStand::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_AuraHeadsetStand::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_AuraHeadsetStand::DeviceUpdateMode() +{ + unsigned char red = 0; + unsigned char grn = 0; + unsigned char blu = 0; + switch(modes[active_mode].value) + { + case 0: + controller->UpdateLeds(std::vector(colors)); + break; + case 1: + case 2: + case 3: + red = RGBGetRValue(modes[active_mode].colors[0]); + grn = RGBGetGValue(modes[active_mode].colors[0]); + blu = RGBGetBValue(modes[active_mode].colors[0]); + controller->UpdateDevice(modes[active_mode].value, red, grn, blu, modes[active_mode].speed, modes[active_mode].brightness); + break; + case 4: + case 5: + controller->UpdateDevice(modes[active_mode].value, red, grn, blu, modes[active_mode].speed, modes[active_mode].brightness); + break; + } +} + +void RGBController_AuraHeadsetStand::DeviceSaveMode() +{ + DeviceUpdateMode(); + controller->SaveMode(); +} diff --git a/Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController/RGBController_AsusAuraHeadsetStand.h b/Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController/RGBController_AsusAuraHeadsetStand.h new file mode 100644 index 00000000..40f8b5e1 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController/RGBController_AsusAuraHeadsetStand.h @@ -0,0 +1,46 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraHeadsetStand.h | +| | +| RGBController for ASUS Aura headset stand | +| | +| Mola19 06 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AsusAuraHeadsetStandController.h" + +enum +{ + AURA_HEADSETSTAND_BRIGHTNESS_MIN = 0, + AURA_HEADSETSTAND_BRIGHTNESS_MAX = 4, + AURA_HEADSETSTAND_BRIGHTNESS_DEFAULT = 4, + AURA_HEADSETSTAND_SPEED_MIN = 0, + AURA_HEADSETSTAND_SPEED_MAX = 255, + AURA_HEADSETSTAND_SPEED_DEFAULT = 127, +}; + +class RGBController_AuraHeadsetStand : public RGBController +{ +public: + RGBController_AuraHeadsetStand(AuraHeadsetStandController* controller_ptr); + ~RGBController_AuraHeadsetStand(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + AuraHeadsetStandController* controller; +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraKeyboardController.h b/Controllers/AsusAuraUSBController/AsusAuraKeyboardController.h deleted file mode 100644 index 141418f5..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraKeyboardController.h +++ /dev/null @@ -1,36 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraKeyboardController.h | -| | -| Definitions and types for ASUS Aura | -| USB RGB lighting controller | -| | -| Adam Honse (CalcProgrammer1) 3/19/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include -#include - -#pragma once - -class AuraKeyboardController -{ -public: - AuraKeyboardController(hid_device* dev_handle, const char* path); - virtual ~AuraKeyboardController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - - void SendDirect - ( - unsigned char frame_count, - unsigned char * frame_data - ); - -private: - hid_device* dev; - std::string location; -}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraKeyboardController.cpp b/Controllers/AsusAuraUSBController/AsusAuraKeyboardController/AsusAuraKeyboardController.cpp similarity index 79% rename from Controllers/AsusAuraUSBController/AsusAuraKeyboardController.cpp rename to Controllers/AsusAuraUSBController/AsusAuraKeyboardController/AsusAuraKeyboardController.cpp index 6712ccee..de4c382f 100644 --- a/Controllers/AsusAuraUSBController/AsusAuraKeyboardController.cpp +++ b/Controllers/AsusAuraUSBController/AsusAuraKeyboardController/AsusAuraKeyboardController.cpp @@ -1,20 +1,23 @@ -/*-----------------------------------------*\ -| AsusAuraKeyboardController.cpp | -| | -| Driver for ASUS Aura RGB USB | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 3/19/2020 | -\*-----------------------------------------*/ - -#include "AsusAuraKeyboardController.h" +/*---------------------------------------------------------*\ +| AsusAuraKeyboardController.cpp | +| | +| Driver for ASUS Aura keyboard | +| | +| Adam Honse (CalcProgrammer1) 19 Mar 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "AsusAuraKeyboardController.h" +#include "StringUtils.h" -AuraKeyboardController::AuraKeyboardController(hid_device* dev_handle, const char* path) +AuraKeyboardController::AuraKeyboardController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } AuraKeyboardController::~AuraKeyboardController() @@ -27,6 +30,11 @@ std::string AuraKeyboardController::GetDeviceLocation() return("HID: " + location); } +std::string AuraKeyboardController::GetNameString() +{ + return(name); +} + std::string AuraKeyboardController::GetSerialString() { wchar_t serial_string[128]; @@ -37,10 +45,7 @@ std::string AuraKeyboardController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void AuraKeyboardController::SendDirect diff --git a/Controllers/AsusAuraUSBController/AsusAuraKeyboardController/AsusAuraKeyboardController.h b/Controllers/AsusAuraUSBController/AsusAuraKeyboardController/AsusAuraKeyboardController.h new file mode 100644 index 00000000..7e890d22 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraKeyboardController/AsusAuraKeyboardController.h @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| AsusAuraKeyboardController.h | +| | +| Driver for ASUS Aura keyboard | +| | +| Adam Honse (CalcProgrammer1) 19 Mar 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" + +class AuraKeyboardController +{ +public: + AuraKeyboardController(hid_device* dev_handle, const char* path, std::string dev_name); + virtual ~AuraKeyboardController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SendDirect + ( + unsigned char frame_count, + unsigned char * frame_data + ); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraKeyboard.cpp b/Controllers/AsusAuraUSBController/AsusAuraKeyboardController/RGBController_AsusAuraKeyboard.cpp similarity index 93% rename from Controllers/AsusAuraUSBController/RGBController_AsusAuraKeyboard.cpp rename to Controllers/AsusAuraUSBController/AsusAuraKeyboardController/RGBController_AsusAuraKeyboard.cpp index a277caae..d7a3701a 100644 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraKeyboard.cpp +++ b/Controllers/AsusAuraUSBController/AsusAuraKeyboardController/RGBController_AsusAuraKeyboard.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraKeyboard.cpp | -| | -| Generic RGB Interface for Asus Aura | -| USB controller driver | -| | -| Adam Honse (CalcProgrammer1) 3/19/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraKeyboard.cpp | +| | +| RGBController for ASUS Aura keyboard | +| | +| Adam Honse (CalcProgrammer1) 19 Mar 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_AsusAuraKeyboard.h" @@ -44,7 +46,7 @@ static unsigned int falchion_matrix_map[5][16] = { 3, NA, 12, 17, 21, 25, 29, 34, 38, 42, 47, 52, 56, NA, 61, 66 }, { 4, 8, 13, NA, NA, NA, 30, NA, NA, NA, 43, 48, 53, 57, 62, 67 } }; -static const std::vector default_led_names = +static const std::vector default_led_names = { /* Key Label Index */ { KEY_EN_ESCAPE, 0x00 }, @@ -153,7 +155,7 @@ static const std::vector default_led_names = { KEY_EN_NUMPAD_ENTER, 0xB4 }, }; -static const std::vector default_tkl_led_names = +static const std::vector default_tkl_led_names = { /* Key Label Index */ { KEY_EN_ESCAPE, 0x00 }, @@ -270,7 +272,7 @@ static const std::vector default_tkl_led_names = { "Underglow 26", 0xCE }, }; -static const std::vector default_65pct_led_names = +static const std::vector default_65pct_led_names = { /* Key Label Index */ { KEY_EN_ESCAPE, 0x00 }, @@ -356,21 +358,21 @@ static const std::vector default_65pct_led_names = RGBController_AuraKeyboard::RGBController_AuraKeyboard(AuraKeyboardController* controller_ptr, AuraKeyboardMappingLayoutType keyboard_layout) { - controller = controller_ptr; - layout = keyboard_layout; + controller = controller_ptr; + layout = keyboard_layout; - name = "ASUS Aura Keyboard"; - vendor = "ASUS"; - type = DEVICE_TYPE_KEYBOARD; - description = "ASUS Aura Keyboard Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "ASUS"; + type = DEVICE_TYPE_KEYBOARD; + description = "ASUS Aura Keyboard Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + 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(); @@ -395,7 +397,7 @@ void RGBController_AuraKeyboard::SetupZones() | Set up zones | \*---------------------------------------------------------*/ std::vector led_zones; - std::vector led_names; + std::vector led_names; switch(layout) { @@ -514,7 +516,7 @@ void RGBController_AuraKeyboard::DeviceUpdateLEDs() frame_buf[(led_idx * 4) + 3] = RGBGetBValue(colors[led_idx]); } - controller->SendDirect(leds.size(), frame_buf.data()); + controller->SendDirect((unsigned char)leds.size(), frame_buf.data()); } void RGBController_AuraKeyboard::UpdateZoneLEDs(int /*zone*/) diff --git a/Controllers/AsusAuraUSBController/AsusAuraKeyboardController/RGBController_AsusAuraKeyboard.h b/Controllers/AsusAuraUSBController/AsusAuraKeyboardController/RGBController_AsusAuraKeyboard.h new file mode 100644 index 00000000..0d0d9de2 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraKeyboardController/RGBController_AsusAuraKeyboard.h @@ -0,0 +1,59 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraKeyboard.h | +| | +| RGBController for ASUS Aura keyboard | +| | +| Adam Honse (CalcProgrammer1) 19 Mar 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AsusAuraKeyboardController.h" + +enum AuraKeyboardMappingLayoutType +{ + FLARE_LAYOUT, + SCOPE_LAYOUT, + SCOPE_RX_LAYOUT, + SCOPE_TKL_LAYOUT, + FALCHION_LAYOUT, +}; + +typedef struct +{ + const char* name; + unsigned char idx; +} aura_keyboard_led; + +typedef struct +{ + const char* name; + const zone_type type; + const unsigned int size; + matrix_map_type* matrix; +} led_zone; + +class RGBController_AuraKeyboard : public RGBController +{ +public: + RGBController_AuraKeyboard(AuraKeyboardController* controller_ptr, AuraKeyboardMappingLayoutType keyboard_layout); + ~RGBController_AuraKeyboard(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + AuraKeyboardController* controller; + AuraKeyboardMappingLayoutType layout; +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraMainboardController.cpp b/Controllers/AsusAuraUSBController/AsusAuraMainboardController.cpp deleted file mode 100644 index 64b28d6d..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraMainboardController.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraMainboardController.cpp | -| | -| Driver for ASUS Aura RGB USB mainboard | -| lighting controller | -| | -| Martin Hartl (inlart) 4/25/2020 | -\*-----------------------------------------*/ - -#include "AsusAuraMainboardController.h" -#include - -AuraMainboardController::AuraMainboardController(hid_device* dev_handle, const char* path) : AuraUSBController(dev_handle, path), mode(AURA_MODE_DIRECT) -{ - unsigned char num_total_mainboard_leds = config_table[0x1B]; - unsigned char num_rgb_headers = config_table[0x1D]; - unsigned char num_addressable_headers = config_table[0x02]; - - if(num_total_mainboard_leds < num_rgb_headers) - { - num_rgb_headers = 0; - } - - /*-----------------------------------------------------*\ - | Add mainboard device | - \*-----------------------------------------------------*/ - device_info.push_back({0x00, 0x04, num_total_mainboard_leds, num_rgb_headers, AuraDeviceType::FIXED}); - - /*-----------------------------------------------------*\ - | Add addressable devices | - \*-----------------------------------------------------*/ - for(int i = 0; i < num_addressable_headers; i++) - { - device_info.push_back({0x01, (unsigned char)i, 0x01, 0, AuraDeviceType::ADDRESSABLE}); - } -} - -AuraMainboardController::~AuraMainboardController() -{ -} - -void AuraMainboardController::SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors) -{ - unsigned char led_data[60]; - unsigned int leds_sent = 0; - - while(leds_sent < num_colors) - { - unsigned int leds_to_send = 20; - - if((num_colors - leds_sent) < leds_to_send) - { - leds_to_send = num_colors - leds_sent; - } - - for(unsigned int led_idx = 0; led_idx < leds_to_send; led_idx++) - { - led_data[(led_idx * 3) + 0] = RGBGetRValue(colors[led_idx + leds_sent]); - led_data[(led_idx * 3) + 1] = RGBGetGValue(colors[led_idx + leds_sent]); - led_data[(led_idx * 3) + 2] = RGBGetBValue(colors[led_idx + leds_sent]); - } - - SendDirect - ( - device_info[channel].direct_channel, - leds_sent, - leds_to_send, - led_data, - leds_sent + leds_to_send >= num_colors - ); - - leds_sent += leds_to_send; - } -} - -void AuraMainboardController::SetMode - ( - unsigned char channel, - unsigned char mode, - unsigned char red, - unsigned char grn, - unsigned char blu - ) -{ - this->mode = mode; - RGBColor color = ToRGBColor(red, grn, blu); - - SendEffect(device_info[channel].effect_channel, mode); - if(mode == AURA_MODE_DIRECT) - { - return; - } - - unsigned char led_data[60]; - unsigned char start_led = 0; - - for(std::size_t i = 0; i < channel; ++i) - { - start_led += device_info[i].num_leds; - } - - for(std::size_t led_idx = 0; led_idx < device_info[channel].num_leds; led_idx++) - { - led_data[(led_idx * 3) + 0] = RGBGetRValue(color); - led_data[(led_idx * 3) + 1] = RGBGetGValue(color); - led_data[(led_idx * 3) + 2] = RGBGetBValue(color); - } - - SendColor - ( - channel, - start_led, - device_info[channel].num_leds, - led_data - ); -} - -unsigned short AuraMainboardController::GetMask(int start, int size) -{ - return(((1 << size) - 1) << start); -} - -void AuraMainboardController::SendEffect - ( - unsigned char channel, - unsigned char mode - ) -{ - unsigned char usb_buf[65]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, sizeof(usb_buf)); - - /*-----------------------------------------------------*\ - | Set up message packet | - \*-----------------------------------------------------*/ - usb_buf[0x00] = 0xEC; - usb_buf[0x01] = AURA_MAINBOARD_CONTROL_MODE_EFFECT; - usb_buf[0x02] = channel; - usb_buf[0x03] = 0x00; - usb_buf[0x04] = 0x00; - usb_buf[0x05] = mode; - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); -} - -void AuraMainboardController::SendColor - ( - unsigned char /*channel*/, - unsigned char start_led, - unsigned char led_count, - unsigned char* led_data - ) -{ - unsigned short mask = GetMask(start_led, led_count); - unsigned char usb_buf[65]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, sizeof(usb_buf)); - - /*-----------------------------------------------------*\ - | Set up message packet | - \*-----------------------------------------------------*/ - usb_buf[0x00] = 0xEC; - usb_buf[0x01] = AURA_MAINBOARD_CONTROL_MODE_EFFECT_COLOR; - usb_buf[0x02] = mask >> 8; - usb_buf[0x03] = mask & 0xff; - usb_buf[0x04] = 0x00; - - /*-----------------------------------------------------*\ - | Copy in color data bytes | - \*-----------------------------------------------------*/ - memcpy(&usb_buf[0x05 + 3 * start_led], led_data, led_count * 3); - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); -} - -void AuraMainboardController::SendCommit() -{ - unsigned char usb_buf[65]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, sizeof(usb_buf)); - - /*-----------------------------------------------------*\ - | Set up message packet | - \*-----------------------------------------------------*/ - usb_buf[0x00] = 0xEC; - usb_buf[0x01] = AURA_MAINBOARD_CONTROL_MODE_COMMIT; - usb_buf[0x02] = 0x55; - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); -} diff --git a/Controllers/AsusAuraUSBController/AsusAuraMainboardController.h b/Controllers/AsusAuraUSBController/AsusAuraMainboardController.h deleted file mode 100644 index 47788bcc..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraMainboardController.h +++ /dev/null @@ -1,67 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraMainboardController.h | -| | -| Definitions and types for ASUS Aura | -| USB Mainboard RGB lighting controller | -| | -| Martin Hartl (inlart) 4/25/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include "AsusAuraUSBController.h" - -#include -#include - -#pragma once - -enum -{ - AURA_MAINBOARD_CONTROL_MODE_EFFECT = 0x35, /* Effect control mode */ - AURA_MAINBOARD_CONTROL_MODE_EFFECT_COLOR = 0x36, /* Effect color control mode */ - AURA_MAINBOARD_CONTROL_MODE_COMMIT = 0x3F, /* Commit mode */ -}; - -class AuraMainboardController : public AuraUSBController -{ -public: - AuraMainboardController(hid_device* dev_handle, const char* path); - ~AuraMainboardController(); - - void SetChannelLEDs - ( - unsigned char channel, - RGBColor * colors, - unsigned int num_colors - ); - - void SetMode - ( - unsigned char channel, - unsigned char mode, - unsigned char red, - unsigned char grn, - unsigned char blu - ); - -private: - unsigned int mode; - - unsigned short GetMask(int start, int size); - - void SendEffect - ( - unsigned char channel, - unsigned char mode - ); - - void SendColor - ( - unsigned char channel, - unsigned char start_led, - unsigned char led_count, - unsigned char* led_data - ); - - void SendCommit(); -}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraMonitorController.cpp b/Controllers/AsusAuraUSBController/AsusAuraMonitorController.cpp deleted file mode 100644 index 5d139227..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraMonitorController.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraMonitorController.cpp | -| | -| Driver for ASUS Aura RGB USB | -| lighting controller | -| | -| Mola19 08/03/2021 | -\*-----------------------------------------*/ - -#include "AsusAuraMonitorController.h" - -#include -#include "LogManager.h" - -AuraMonitorController::AuraMonitorController(hid_device* dev_handle, const char* path, uint16_t pid) -{ - dev = dev_handle; - location = path; - device_pid = pid; -} - -AuraMonitorController::~AuraMonitorController() -{ - hid_close(dev); -} - -std::string AuraMonitorController::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string AuraMonitorController::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 AuraMonitorController::BeginUpdate() -{ - unsigned char usb_buf[8]; - - if (device_pid == AURA_ROG_PG32UQ_PID) - { - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x03; - usb_buf[0x01] = 0x02; - usb_buf[0x02] = 0xA1; - usb_buf[0x03] = 0x80; - - usb_buf[0x04] = 0x20; - hid_send_feature_report(dev, usb_buf, 8); - - usb_buf[0x04] = 0x30; - hid_send_feature_report(dev, usb_buf, 8); - } -} - -void AuraMonitorController::UpdateLed - ( - int led, - unsigned char red, - unsigned char green, - unsigned char blue - ) -{ - unsigned char usb_buf[8]; - - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x03; - usb_buf[0x01] = 0x02; - usb_buf[0x02] = 0xA1; - usb_buf[0x03] = 0x80; - - unsigned char offset = (device_pid == AURA_ROG_STRIX_XG279Q_PID) ? 0 : 16; - - usb_buf[0x04] = offset + led * 3; - usb_buf[0x05] = red; - - hid_send_feature_report(dev, usb_buf, 8); - - usb_buf[0x04] = offset + led * 3 + 1; - usb_buf[0x05] = blue; - - hid_send_feature_report(dev, usb_buf, 8); - - usb_buf[0x04] = offset + led * 3 + 2; - usb_buf[0x05] = green; - - hid_send_feature_report(dev, usb_buf, 8); -} - -void AuraMonitorController::ApplyChanges() -{ - unsigned char usb_buf[8]; - - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x03; - usb_buf[0x01] = 0x02; - usb_buf[0x02] = 0xA1; - usb_buf[0x03] = 0x80; - usb_buf[0x04] = 0xA0; - usb_buf[0x05] = 0x01; - - hid_send_feature_report(dev, usb_buf, 8); -} diff --git a/Controllers/AsusAuraUSBController/AsusAuraMonitorController.h b/Controllers/AsusAuraUSBController/AsusAuraMonitorController.h deleted file mode 100644 index fcc92c36..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraMonitorController.h +++ /dev/null @@ -1,44 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraMonitorController.h | -| | -| Definitions and types for ASUS Aura | -| USB RGB lighting controller | -| | -| Mola19 08/03/2023 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include - -#pragma once - -enum -{ - AURA_ROG_STRIX_XG27AQ_PID = 0x198C, - AURA_ROG_STRIX_XG27AQM_PID = 0x19BB, - AURA_ROG_STRIX_XG279Q_PID = 0x1919, - AURA_ROG_STRIX_XG27W_PID = 0x1933, - AURA_ROG_PG32UQ_PID = 0x19B9, -}; - - -class AuraMonitorController -{ -public: - AuraMonitorController(hid_device* dev_handle, const char* path, uint16_t pid); - virtual ~AuraMonitorController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - - void BeginUpdate(); - void UpdateLed(int led, unsigned char red, unsigned char green, unsigned char blue); - void ApplyChanges(); - - uint16_t device_pid; - -private: - hid_device* dev; - std::string location; -}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraMonitorController/AsusAuraMonitorController.cpp b/Controllers/AsusAuraUSBController/AsusAuraMonitorController/AsusAuraMonitorController.cpp new file mode 100644 index 00000000..ffc86c99 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMonitorController/AsusAuraMonitorController.cpp @@ -0,0 +1,123 @@ +/*---------------------------------------------------------*\ +| AsusAuraMonitorController.cpp | +| | +| Driver for ASUS Aura monitor | +| | +| Mola19 08 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "AsusAuraMonitorController.h" +#include "LogManager.h" +#include "StringUtils.h" + +AuraMonitorController::AuraMonitorController(hid_device* dev_handle, const char* path, uint16_t pid, std::string dev_name) +{ + dev = dev_handle; + location = path; + device_pid = pid; + name = dev_name; +} + +AuraMonitorController::~AuraMonitorController() +{ + hid_close(dev); +} + +std::string AuraMonitorController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string AuraMonitorController::GetNameString() +{ + return(name); +} + +std::string AuraMonitorController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void AuraMonitorController::BeginUpdate() +{ + unsigned char usb_buf[8]; + + if (device_pid == AURA_ROG_PG32UQ_PID || device_pid == AURA_ROG_STRIX_XG32VC_PID) + { + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x03; + usb_buf[0x01] = 0x02; + usb_buf[0x02] = 0xA1; + usb_buf[0x03] = 0x80; + + usb_buf[0x04] = 0x20; + hid_send_feature_report(dev, usb_buf, 8); + + usb_buf[0x04] = 0x30; + hid_send_feature_report(dev, usb_buf, 8); + } +} + +void AuraMonitorController::UpdateLed + ( + int led, + unsigned char red, + unsigned char green, + unsigned char blue + ) +{ + unsigned char usb_buf[8]; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x03; + usb_buf[0x01] = 0x02; + usb_buf[0x02] = 0xA1; + usb_buf[0x03] = 0x80; + + unsigned char offset = (device_pid == AURA_ROG_STRIX_XG279Q_PID) ? 0 : 16; + + usb_buf[0x04] = offset + led * 3; + usb_buf[0x05] = red; + + hid_send_feature_report(dev, usb_buf, 8); + + usb_buf[0x04] = offset + led * 3 + 1; + usb_buf[0x05] = blue; + + hid_send_feature_report(dev, usb_buf, 8); + + usb_buf[0x04] = offset + led * 3 + 2; + usb_buf[0x05] = green; + + hid_send_feature_report(dev, usb_buf, 8); +} + +void AuraMonitorController::ApplyChanges() +{ + unsigned char usb_buf[8]; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x03; + usb_buf[0x01] = 0x02; + usb_buf[0x02] = 0xA1; + usb_buf[0x03] = 0x80; + usb_buf[0x04] = 0xA0; + usb_buf[0x05] = 0x01; + + hid_send_feature_report(dev, usb_buf, 8); +} diff --git a/Controllers/AsusAuraUSBController/AsusAuraMonitorController/AsusAuraMonitorController.h b/Controllers/AsusAuraUSBController/AsusAuraMonitorController/AsusAuraMonitorController.h new file mode 100644 index 00000000..4843cf86 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMonitorController/AsusAuraMonitorController.h @@ -0,0 +1,47 @@ +/*---------------------------------------------------------*\ +| AsusAuraMonitorController.h | +| | +| Driver for ASUS Aura monitor | +| | +| Mola19 08 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" + +enum +{ + AURA_ROG_STRIX_XG27AQ_PID = 0x198C, + AURA_ROG_STRIX_XG27AQM_PID = 0x19BB, + AURA_ROG_STRIX_XG279Q_PID = 0x1919, + AURA_ROG_STRIX_XG27W_PID = 0x1933, + AURA_ROG_STRIX_XG32VC_PID = 0x1968, + AURA_ROG_PG32UQ_PID = 0x19B9, +}; + +class AuraMonitorController +{ +public: + AuraMonitorController(hid_device* dev_handle, const char* path, uint16_t pid, std::string dev_name); + virtual ~AuraMonitorController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void BeginUpdate(); + void UpdateLed(int led, unsigned char red, unsigned char green, unsigned char blue); + void ApplyChanges(); + + uint16_t device_pid; + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraMonitorController/RGBController_AsusAuraMonitor.cpp b/Controllers/AsusAuraUSBController/AsusAuraMonitorController/RGBController_AsusAuraMonitor.cpp new file mode 100644 index 00000000..4000f701 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMonitorController/RGBController_AsusAuraMonitor.cpp @@ -0,0 +1,129 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraMonitor.cpp | +| | +| RGBController for ASUS Aura monitor | +| | +| Mola19 08 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_AsusAuraMonitor.h" + +/**------------------------------------------------------------------*\ + @name Asus Aura Monitor + @category Accessory + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectAsusAuraUSBMonitor + @comment +\*-------------------------------------------------------------------*/ + +RGBController_AuraMonitor::RGBController_AuraMonitor(AuraMonitorController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "ASUS"; + type = DEVICE_TYPE_MONITOR; + description = "ASUS Aura Monitor Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + 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(); +} + +RGBController_AuraMonitor::~RGBController_AuraMonitor() +{ + delete controller; +} + +void RGBController_AuraMonitor::SetupZones() +{ + zone underglow_zone; + + underglow_zone.name = "Backlight"; + underglow_zone.type = ZONE_TYPE_LINEAR; + underglow_zone.leds_min = 3; + underglow_zone.leds_max = 3; + underglow_zone.leds_count = 3; + underglow_zone.matrix_map = NULL; + + zones.push_back(underglow_zone); + + for(unsigned int i = 0; i < 3; i++) + { + led underglow_led; + + underglow_led.name = "Backlight LED " + std::to_string(i + 1); + + leds.push_back(underglow_led); + } + + SetupColors(); +} + +void RGBController_AuraMonitor::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_AuraMonitor::DeviceUpdateLEDs() +{ + controller->BeginUpdate(); + + for (int i = 0; i < 3; i++) + { + unsigned char red = RGBGetRValue(colors[i]); + unsigned char green = RGBGetGValue(colors[i]); + unsigned char blue = RGBGetBValue(colors[i]); + + controller->UpdateLed(i, red, green, blue); + } + + controller->ApplyChanges(); +} + +void RGBController_AuraMonitor::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_AuraMonitor::UpdateSingleLED(int led) +{ + controller->BeginUpdate(); + + unsigned char red = RGBGetRValue(colors[led]); + unsigned char green = RGBGetGValue(colors[led]); + unsigned char blue = RGBGetBValue(colors[led]); + + controller->UpdateLed(led, red, green, blue); + + controller->ApplyChanges(); +} + +void RGBController_AuraMonitor::DeviceUpdateMode() +{ + /*---------------------------------------------------------*\ + | This device does not support Mode changing | + \*---------------------------------------------------------*/ +} + +void RGBController_AuraMonitor::DeviceSaveMode() +{ + /*---------------------------------------------------------*\ + | This device does not support Mode saving | + \*---------------------------------------------------------*/ +} diff --git a/Controllers/AsusAuraUSBController/AsusAuraMonitorController/RGBController_AsusAuraMonitor.h b/Controllers/AsusAuraUSBController/AsusAuraMonitorController/RGBController_AsusAuraMonitor.h new file mode 100644 index 00000000..8adcde29 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMonitorController/RGBController_AsusAuraMonitor.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraMonitor.h | +| | +| RGBController for ASUS Aura monitor | +| | +| Mola19 08 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AsusAuraMonitorController.h" + +class RGBController_AuraMonitor : public RGBController +{ +public: + RGBController_AuraMonitor(AuraMonitorController* controller_ptr); + ~RGBController_AuraMonitor(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + AuraMonitorController* controller; +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraMouseController.cpp b/Controllers/AsusAuraUSBController/AsusAuraMouseController.cpp deleted file mode 100644 index 28954f9b..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraMouseController.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraMouseController.cpp | -| | -| Driver for ASUS Aura RGB USB | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 10/23/2020 | -\*-----------------------------------------*/ - -#include "AsusAuraMouseController.h" - -#include - -AuraMouseController::AuraMouseController(hid_device* dev_handle, const char* path, uint16_t pid) -{ - dev = dev_handle; - location = path; - device_pid = pid; -} - -AuraMouseController::~AuraMouseController() -{ - hid_close(dev); -} - -std::string AuraMouseController::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string AuraMouseController::GetSerialString() -{ - wchar_t serial_string[HID_MAX_STR]; - int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); - - if(ret != 0) - { - return(""); - } - - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); -} - -std::string AuraMouseController::GetVersion(bool wireless, int protocol) -{ - unsigned char usb_buf[ASUS_AURA_MOUSE_PACKET_SIZE]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0x12; - hid_write(dev, usb_buf, ASUS_AURA_MOUSE_PACKET_SIZE); - - unsigned char usb_buf_out[ASUS_AURA_MOUSE_PACKET_SIZE]; - hid_read(dev, usb_buf_out, ASUS_AURA_MOUSE_PACKET_SIZE); - - std::string str; - - switch(protocol) - { - case 0: - { - unsigned char* offset = usb_buf_out + (wireless ? 13 : 4); - str = std::string(offset, offset + 4); - } - break; - - case 1: - case 2: - { - char version[9]; - int wireless_offset = (protocol == 2 ? 14 : 13); - int offset = (wireless ? wireless_offset : 4); - snprintf(version, 9, "%2X.%02X.%02X", usb_buf_out[offset + 2], usb_buf_out[offset + 1], usb_buf_out[offset]); - str = std::string(version); - } - break; - - case 3: - { - unsigned char* offset = usb_buf_out + (wireless ? 13 : 4); - str = std::string(offset, offset + 4); - str = "0." + str.substr(0, 2) + "." + str.substr(2, 2); - } - break; - - case 4: - { - char version[16]; - int offset = (wireless ? 13 : 4); - snprintf(version, 16, "%2d.%02d.%02d", usb_buf_out[offset + 1], usb_buf_out[offset + 2], usb_buf_out[offset + 3]); - str = std::string(version); - } - break; - } - - return str; -} - -void AuraMouseController::SaveMode() -{ - unsigned char usb_save_buf[ASUS_AURA_MOUSE_PACKET_SIZE] = { 0x00, 0x50, 0x03 }; - - hid_write(dev, usb_save_buf, ASUS_AURA_MOUSE_PACKET_SIZE); -} - -void AuraMouseController::SendUpdate - ( - unsigned char zone, - unsigned char mode, - unsigned char red, - unsigned char grn, - unsigned char blu, - unsigned char dir, - bool random, - unsigned char speed, - unsigned char brightness - ) -{ - int bytes_read = 1; - unsigned char usb_buf_flush[ASUS_AURA_MOUSE_PACKET_SIZE]; - - while(bytes_read > 0) - { - bytes_read = hid_read_timeout(dev, usb_buf_flush, ASUS_AURA_MOUSE_PACKET_SIZE, 0); - } - - unsigned char usb_buf[ASUS_AURA_MOUSE_PACKET_SIZE]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, ASUS_AURA_MOUSE_PACKET_SIZE); - - /*-----------------------------------------------------*\ - | Set up message packet | - \*-----------------------------------------------------*/ - - if (device_pid == AURA_ROG_GLADIUS_II_ORIGIN_PNK_LTD_PID) - { - // this device supports 2 color for breathing, - // but since this mode is per led and openrgb doesn't support 2 colors per led this feature is not implemented - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0x51; - usb_buf[0x02] = 0x28; - usb_buf[0x03] = zone; - usb_buf[0x04] = 0x00; - usb_buf[0x05] = mode; - usb_buf[0x06] = brightness; - usb_buf[0x07] = 0x00; // boolean signaling if the 2nd set of colors is in use - usb_buf[0x08] = red; - usb_buf[0x09] = grn; - usb_buf[0x0A] = blu; - usb_buf[0x0B] = 0; // 2nd red - usb_buf[0x0C] = 0; // 2nd green - usb_buf[0x0D] = 0; // 2nd blue - usb_buf[0x0E] = dir; - usb_buf[0x0F] = random; - usb_buf[0x10] = speed; - } - else - { - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0x51; - usb_buf[0x02] = 0x28; - usb_buf[0x03] = zone; - usb_buf[0x04] = 0x00; - usb_buf[0x05] = mode; - usb_buf[0x06] = brightness; - usb_buf[0x07] = red; - usb_buf[0x08] = grn; - usb_buf[0x09] = blu; - usb_buf[0x0A] = dir; - usb_buf[0x0B] = random; - usb_buf[0x0C] = speed; - } - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, ASUS_AURA_MOUSE_PACKET_SIZE); - - unsigned char usb_buf_out[ASUS_AURA_MOUSE_PACKET_SIZE]; - hid_read_timeout(dev, usb_buf_out, ASUS_AURA_MOUSE_PACKET_SIZE, 10); -} diff --git a/Controllers/AsusAuraUSBController/AsusAuraMouseController.h b/Controllers/AsusAuraUSBController/AsusAuraMouseController.h deleted file mode 100644 index 4dd4520a..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraMouseController.h +++ /dev/null @@ -1,50 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraMouseController.h | -| | -| Definitions and types for ASUS Aura | -| USB RGB lighting controller | -| | -| Adam Honse (CalcProgrammer1) 10/23/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include "AsusAuraMouseDevices.h" - -#include -#include - -#pragma once - -#define ASUS_AURA_MOUSE_PACKET_SIZE 65 -#define HID_MAX_STR 255 - -class AuraMouseController -{ -public: - AuraMouseController(hid_device* dev_handle, const char* path, uint16_t pid); - virtual ~AuraMouseController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - std::string GetVersion(bool wireless, int protocol); - - void SaveMode(); - void SendUpdate - ( - unsigned char zone, - unsigned char mode, - unsigned char red, - unsigned char grn, - unsigned char blu, - unsigned char dir, - bool random, - unsigned char speed, - unsigned char brightness - ); - - uint16_t device_pid; - -private: - hid_device* dev; - std::string location; -}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraMouseController/AsusAuraMouseController.cpp b/Controllers/AsusAuraUSBController/AsusAuraMouseController/AsusAuraMouseController.cpp new file mode 100644 index 00000000..511d15f5 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMouseController/AsusAuraMouseController.cpp @@ -0,0 +1,264 @@ +/*---------------------------------------------------------*\ +| AsusAuraMouseController.cpp | +| | +| Driver for ASUS Aura mouse | +| | +| Adam Honse (CalcProgrammer1) 23 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "AsusAuraMouseController.h" +#include "StringUtils.h" + +#define HID_MAX_STR 255 + +AuraMouseController::AuraMouseController(hid_device* dev_handle, const char* path, uint16_t pid, std::string dev_name) +{ + dev = dev_handle; + location = path; + device_pid = pid; + name = dev_name; +} + +AuraMouseController::~AuraMouseController() +{ + hid_close(dev); +} + +std::string AuraMouseController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string AuraMouseController::GetName() +{ + return(name); +} + +std::string AuraMouseController::GetSerialString() +{ + wchar_t serial_string[HID_MAX_STR]; + int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string AuraMouseController::GetVersion(bool wireless, int protocol) +{ + unsigned char usb_buf[ASUS_AURA_MOUSE_PACKET_SIZE]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x12; + hid_write(dev, usb_buf, ASUS_AURA_MOUSE_PACKET_SIZE); + + unsigned char usb_buf_out[ASUS_AURA_MOUSE_PACKET_SIZE]; + hid_read(dev, usb_buf_out, ASUS_AURA_MOUSE_PACKET_SIZE); + + std::string str; + + switch(protocol) + { + case 0: + { + unsigned char* offset = usb_buf_out + (wireless ? 13 : 4); + str = std::string(offset, offset + 4); + } + break; + + case 1: + case 2: + { + char version[9]; + int wireless_offset = (protocol == 2 ? 14 : 13); + int offset = (wireless ? wireless_offset : 4); + snprintf(version, 9, "%2X.%02X.%02X", usb_buf_out[offset + 2], usb_buf_out[offset + 1], usb_buf_out[offset]); + str = std::string(version); + } + break; + + case 3: + { + unsigned char* offset = usb_buf_out + (wireless ? 13 : 4); + str = std::string(offset, offset + 4); + str = "0." + str.substr(0, 2) + "." + str.substr(2, 2); + } + break; + + case 4: + { + char version[16]; + int offset = (wireless ? 13 : 4); + snprintf(version, 16, "%2d.%02d.%02d", usb_buf_out[offset + 1], usb_buf_out[offset + 2], usb_buf_out[offset + 3]); + str = std::string(version); + } + break; + } + + return str; +} + +std::string AuraMouseController::CleanSerial(const std::wstring& wstr) +{ + /*---------------------------------------------------------------*\ + | Cleans garbage at the end of serial numbers | + | (apparently 2 characters too much, but maybe variable) | + | Limited to new devices, old ones don't even have serial numbers | + \*---------------------------------------------------------------*/ + std::string result; + for(wchar_t c : wstr) + { + /*-----------------------------------------------------*\ + | Forbid anything besides digits and upper case letters | + \*-----------------------------------------------------*/ + bool isUpperCaseLetter = (c >= 64 && c <= 90); + bool isDigit = (c >= 48 && c <= 57); + if(!isUpperCaseLetter && !isDigit) + { + break; + } + + result += (char)c; + } + + return(result); +} + +void AuraMouseController::SaveMode() +{ + unsigned char usb_save_buf[ASUS_AURA_MOUSE_PACKET_SIZE] = { 0x00, 0x50, 0x03 }; + + hid_write(dev, usb_save_buf, ASUS_AURA_MOUSE_PACKET_SIZE); +} + +void AuraMouseController::SendUpdate + ( + unsigned char zone, + unsigned char mode, + unsigned char red, + unsigned char grn, + unsigned char blu, + unsigned char dir, + bool random, + unsigned char speed, + unsigned char brightness + ) +{ + int bytes_read = 1; + unsigned char usb_buf_flush[ASUS_AURA_MOUSE_PACKET_SIZE]; + + while(bytes_read > 0) + { + bytes_read = hid_read_timeout(dev, usb_buf_flush, ASUS_AURA_MOUSE_PACKET_SIZE, 0); + } + + unsigned char usb_buf[ASUS_AURA_MOUSE_PACKET_SIZE]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, ASUS_AURA_MOUSE_PACKET_SIZE); + + /*-----------------------------------------------------*\ + | Set up message packet | + \*-----------------------------------------------------*/ + + if (device_pid == AURA_ROG_GLADIUS_II_ORIGIN_PNK_LTD_PID) + { + // this device supports 2 color for breathing, + // but since this mode is per led and openrgb doesn't support 2 colors per led this feature is not implemented + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x51; + usb_buf[0x02] = 0x28; + usb_buf[0x03] = zone; + usb_buf[0x04] = 0x00; + usb_buf[0x05] = mode; + usb_buf[0x06] = brightness; + usb_buf[0x07] = 0x00; // boolean signaling if the 2nd set of colors is in use + usb_buf[0x08] = red; + usb_buf[0x09] = grn; + usb_buf[0x0A] = blu; + usb_buf[0x0B] = 0; // 2nd red + usb_buf[0x0C] = 0; // 2nd green + usb_buf[0x0D] = 0; // 2nd blue + usb_buf[0x0E] = dir; + usb_buf[0x0F] = random; + usb_buf[0x10] = speed; + } + else + { + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x51; + usb_buf[0x02] = 0x28; + usb_buf[0x03] = zone; + usb_buf[0x04] = 0x00; + usb_buf[0x05] = mode; + usb_buf[0x06] = brightness; + usb_buf[0x07] = red; + usb_buf[0x08] = grn; + usb_buf[0x09] = blu; + usb_buf[0x0A] = dir; + usb_buf[0x0B] = random; + usb_buf[0x0C] = speed; + } + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, ASUS_AURA_MOUSE_PACKET_SIZE); + + unsigned char usb_buf_out[ASUS_AURA_MOUSE_PACKET_SIZE]; + hid_read_timeout(dev, usb_buf_out, ASUS_AURA_MOUSE_PACKET_SIZE, 10); +} + +void AuraMouseController::SendDirect + ( + std::vector zone_colors + ) +{ + std::vector colors = {}; + colors.resize(aura_mouse_led_maps[device_pid].led_amount); + + for(unsigned char zone = 0; zone < zone_colors.size(); zone++) + { + std::vector zone_map = aura_mouse_led_maps[device_pid].map[zone]; + for(unsigned char led = 0; led < zone_map.size(); led++) + { + colors[zone_map[led]] = zone_colors[zone]; + } + } + + /*-----------------------------------------------------*\ + | Only 5 colors can be sent in each packet | + \*-----------------------------------------------------*/ + for(unsigned char led = 0; led < aura_mouse_led_maps[device_pid].led_amount; led += 5) + { + unsigned char usb_buf[ASUS_AURA_MOUSE_PACKET_SIZE]; + memset(usb_buf, 0x00, ASUS_AURA_MOUSE_PACKET_SIZE); + + unsigned char colors_in_packet = (aura_mouse_led_maps[device_pid].led_amount >= led + 5) ? 5 : aura_mouse_led_maps[device_pid].led_amount - led; + + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x51; + usb_buf[0x02] = 0x29; + usb_buf[0x03] = colors_in_packet; // colors in this packet + usb_buf[0x04] = 0x00; + usb_buf[0x05] = led; // offset + + for(unsigned char color = 0; color < colors_in_packet; color++) + { + usb_buf[0x06 + color * 3] = RGBGetRValue(colors[led + color]); + usb_buf[0x07 + color * 3] = RGBGetGValue(colors[led + color]); + usb_buf[0x08 + color * 3] = RGBGetBValue(colors[led + color]); + } + + hid_write(dev, usb_buf, ASUS_AURA_MOUSE_PACKET_SIZE); + } +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraMouseController/AsusAuraMouseController.h b/Controllers/AsusAuraUSBController/AsusAuraMouseController/AsusAuraMouseController.h new file mode 100644 index 00000000..e34eb781 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMouseController/AsusAuraMouseController.h @@ -0,0 +1,58 @@ +/*---------------------------------------------------------*\ +| AsusAuraMouseController.h | +| | +| Driver for ASUS Aura mouse | +| | +| Adam Honse (CalcProgrammer1) 23 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" +#include "AsusAuraMouseDevices.h" + +#define ASUS_AURA_MOUSE_PACKET_SIZE 65 + +class AuraMouseController +{ +public: + AuraMouseController(hid_device* dev_handle, const char* path, uint16_t pid, std::string dev_name); + virtual ~AuraMouseController(); + + std::string GetDeviceLocation(); + std::string GetName(); + std::string GetSerialString(); + std::string GetVersion(bool wireless, int protocol); + + std::string CleanSerial(const std::wstring& wstr); + + void SaveMode(); + void SendUpdate + ( + unsigned char zone, + unsigned char mode, + unsigned char red, + unsigned char grn, + unsigned char blu, + unsigned char dir, + bool random, + unsigned char speed, + unsigned char brightness + ); + void SendDirect + ( + std::vector zone_colors + ); + + uint16_t device_pid; + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraMouseController/AsusAuraMouseDevices.h b/Controllers/AsusAuraUSBController/AsusAuraMouseController/AsusAuraMouseDevices.h new file mode 100644 index 00000000..f6f3a29e --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMouseController/AsusAuraMouseDevices.h @@ -0,0 +1,791 @@ +/*---------------------------------------------------------*\ +| AsusAuraMouseDevices.h | +| | +| Device list for ASUS Aura mouse | +| | +| Chris M (Dr_No) 11 Jul 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include + +#define AURA_ROG_GLADIUS_II_CORE_PID 0x18DD +#define AURA_ROG_GLADIUS_II_PID 0x1845 +#define AURA_ROG_GLADIUS_II_ORIGIN_PID 0x1877 +#define AURA_ROG_GLADIUS_II_ORIGIN_PNK_LTD_PID 0x18CD +#define AURA_ROG_GLADIUS_II_ORIGIN_COD_PID 0x18B1 +#define AURA_ROG_GLADIUS_II_WIRELESS_1_PID 0x189E +#define AURA_ROG_GLADIUS_II_WIRELESS_2_PID 0x18A0 +#define AURA_ROG_GLADIUS_III_PID 0x197B +#define AURA_ROG_GLADIUS_III_WIRELESS_USB_PID 0x197D +#define AURA_ROG_GLADIUS_III_WIRELESS_2_4_PID 0x197F +#define AURA_ROG_GLADIUS_III_WIRELESS_BT_PID 0x1981 +#define AURA_ROG_GLADIUS_III_WIRELESS_AIMPOINT_USB_PID 0x1A70 +#define AURA_ROG_GLADIUS_III_WIRELESS_AIMPOINT_2_4_PID 0x1A72 +#define AURA_ROG_GLADIUS_III_WIRELESS_AIMPOINT_BT_PID 0x1A74 +#define AURA_ROG_CHAKRAM_WIRELESS_PID 0x18E5 +#define AURA_ROG_CHAKRAM_WIRED_1_PID 0x18E3 +#define AURA_ROG_CHAKRAM_CORE_PID 0x1958 +#define AURA_ROG_CHAKRAM_X_USB_PID 0x1A18 +#define AURA_ROG_CHAKRAM_X_2_4_PID 0x1A1A +#define AURA_ROG_SPATHA_X_USB_PID 0x1977 +#define AURA_ROG_SPATHA_X_2_4_PID 0x1979 +#define AURA_ROG_SPATHA_X_DOCK_PID 0x1979 +#define AURA_ROG_PUGIO_PID 0x1846 +#define AURA_ROG_PUGIO_II_WIRED_PID 0x1906 +#define AURA_ROG_PUGIO_II_WIRELESS_PID 0x1908 +#define AURA_ROG_STRIX_IMPACT_PID 0x1847 +#define AURA_ROG_STRIX_IMPACT_II_PID 0x18E1 +#define AURA_ROG_STRIX_IMPACT_II_GUNDAM_PID 0x189E +#define AURA_ROG_STRIX_IMPACT_II_PUNK_PID 0x1956 +#define AURA_ROG_STRIX_IMPACT_II_WHITE_PID 0x19D2 +#define AURA_ROG_STRIX_IMPACT_II_WIRELESS_USB_PID 0x1947 +#define AURA_ROG_STRIX_IMPACT_II_WIRELESS_2_4_PID 0x1949 +#define AURA_ROG_STRIX_IMPACT_III_PID 0x1A88 +#define AURA_ROG_KERIS 0x195C +#define AURA_ROG_KERIS_WIRELESS_USB_PID 0x195E +#define AURA_ROG_KERIS_WIRELESS_2_4_PID 0x1960 +#define AURA_ROG_KERIS_WIRELESS_BT_PID 0x1962 +#define AURA_ROG_KERIS_WIRELESS_AIMPOINT_USB_PID 0x1A66 +#define AURA_ROG_KERIS_WIRELESS_AIMPOINT_2_4_PID 0x1A68 +#define AURA_ROG_KERIS_WIRELESS_AIMPOINT_BT_PID 0x1A6A +#define AURA_TUF_M3_PID 0x1910 +#define AURA_TUF_M3_GEN_II_PID 0x1A9B +#define AURA_TUF_M5_PID 0x1898 + +#define AURA_ROG_SPATHA_X_DOCK_FAKE_PID 0xFFFF + +enum +{ + AURA_MOUSE_ZONE_LOGO = 0, + AURA_MOUSE_ZONE_SCROLL = 1, + AURA_MOUSE_ZONE_UNDERGLOW = 2, + AURA_MOUSE_ZONE_ALL = 3, + AURA_MOUSE_ZONE_DOCK = 4, +}; + +enum +{ + AURA_MOUSE_MODE_STATIC = 0, + AURA_MOUSE_MODE_BREATHING = 1, + AURA_MOUSE_MODE_SPECTRUM = 2, + AURA_MOUSE_MODE_WAVE = 3, + AURA_MOUSE_MODE_REACTIVE = 4, + AURA_MOUSE_MODE_COMET = 5, + AURA_MOUSE_MODE_BATTERY = 6, + AURA_MOUSE_MODE_DIRECT = 254, + AURA_MOUSE_MODE_NONE = 255, +}; + +typedef struct +{ + uint8_t speed_min; + uint8_t speed_max; + uint8_t brightness_min; + uint8_t brightness_max; + bool wireless; + int version_protocol; + bool direct; + std::vector mouse_zones; + std::vector mouse_modes; +} mouse_type; + +/*-----------------------------------------------------------------*\ +| DEVICE MAP | +| | +| This structure maps the OpenRGB modes to the mode values | +| sent to each mouse. As not all modes are present on each | +| mouse the "mode index" is different. Eg. "Reactive" is mode | +| 4 on the Gladius II and mode 3 on the Gladius II wireless | +\*-----------------------------------------------------------------*/ +static std::map aura_mouse_devices = +{ + { + AURA_ROG_GLADIUS_II_CORE_PID, // ROG Gladius II Core + { + 0, // Speed Min - The Asus Mouse protocol defines larger numbers as slow + 0, // Speed Max + 0, // Brightness Min + 4, // Brightness Max + false, // is wireless? (important for fetching the version) + 1, // version protocol + false, // direct - defines whether the mouse has a native direct mode or just uses static as direct (only present on newer devices) + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } + } + }, + { + AURA_ROG_GLADIUS_II_PID, // ROG Gladius II + { + 255, + 1, + 0, + 4, + false, + 0, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET } + } + }, + { + AURA_ROG_GLADIUS_II_ORIGIN_PID, // ROG Gladius II Origin + { + 255, + 1, + 0, + 4, + false, + 0, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET } + } + }, + { + AURA_ROG_GLADIUS_II_ORIGIN_COD_PID, // ROG Gladius II COD + { + 255, + 1, + 0, + 4, + false, + 0, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET } + } + }, + { + AURA_ROG_GLADIUS_II_ORIGIN_PNK_LTD_PID, // ROG Gladius II PNK LTD + { + 255, + 1, + 0, + 4, + false, + 0, + false, + { AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET } + } + }, + { + AURA_ROG_GLADIUS_II_WIRELESS_1_PID, // ROG Gladius II Wireless + { + 0, + 0, + 0, + 4, + true, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_GLADIUS_II_WIRELESS_2_PID, // ROG Gladius II Wireless + { + 0, + 0, + 0, + 4, + true, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_GLADIUS_III_PID, // ROG Gladius III + { + 255, + 1, + 0, + 100, + false, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_GLADIUS_III_WIRELESS_USB_PID, // ROG Gladius III Wireless USB + { + 255, + 1, + 0, + 100, + false, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_GLADIUS_III_WIRELESS_2_4_PID, // ROG Gladius III Wireless 2.4 GHz Dongle + { + 255, + 1, + 0, + 100, + true, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_GLADIUS_III_WIRELESS_BT_PID, // ROG Gladius III Wireless Bluetooth + { + 255, + 1, + 0, + 100, + true, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_GLADIUS_III_WIRELESS_AIMPOINT_USB_PID, // ROG Gladius III Wireless AimPoint USB + { + 255, + 1, + 0, + 100, + false, + 2, + true, + { AURA_MOUSE_ZONE_LOGO }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_GLADIUS_III_WIRELESS_AIMPOINT_2_4_PID, // ROG Gladius III Wireless AimPoint 2.4 GHz Dongle + { + 255, + 1, + 0, + 100, + true, + 2, + true, + { AURA_MOUSE_ZONE_LOGO }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_CHAKRAM_WIRELESS_PID, // ROG Chakram Wireless + { + 15, + 1, + 0, + 4, + true, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_CHAKRAM_WIRED_1_PID, // ROG Chakram Wired 1 + { + 15, + 1, + 0, + 4, + false, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_CHAKRAM_CORE_PID, // ROG Chakram Core + { + 0, + 0, + 0, + 4, + false, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } + } + }, + { + AURA_ROG_CHAKRAM_X_USB_PID, // ROG Chakram X USB + { + 15, // technically until 255, but unusably slow after 15 + 1, + 0, + 100, + false, + 2, + true, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_CHAKRAM_X_2_4_PID, // ROG Chakram X 2.4GHz Dongle + { + 15, // technically until 255, but unusably slow after 15 + 1, + 0, + 100, + true, + 2, + true, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_SPATHA_X_USB_PID, // ROG Spatha X USB + { + 15, // technically until 255, but unusably slow after 15 + 1, + 0, + 100, + false, + 1, + true, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_SPATHA_X_2_4_PID, // ROG Spatha X 2.4GHz Dock + { + 15, // technically until 255, but unusably slow after 15 + 1, + 0, + 100, + true, + 1, + true, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_PUGIO_PID, // ROG Pugio + { + 255, + 1, + 0, + 4, + false, + 0, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET } + } + }, + { + AURA_ROG_PUGIO_II_WIRED_PID, // ROG Pugio II Wired + { + 15, + 1, + 0, + 4, + false, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_PUGIO_II_WIRELESS_PID, // ROG Pugio II Wireless + { + 15, + 1, + 0, + 4, + true, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_STRIX_IMPACT_PID, // ROG Strix Impact + { + 0, + 0, + 0, + 4, + false, + 4, + false, + { AURA_MOUSE_ZONE_LOGO }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE } + } + }, + { + AURA_ROG_STRIX_IMPACT_II_PID, // ROG Strix Impact II + { + 0, + 0, + 0, + 4, + false, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } + } + }, + { + AURA_ROG_STRIX_IMPACT_II_GUNDAM_PID, // ROG Strix Impact II Gundam + { + 0, + 0, + 0, + 4, + false, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } + } + }, + { + AURA_ROG_STRIX_IMPACT_II_PUNK_PID, // ROG Strix Impact II Electro Punk + { + 0, + 0, + 0, + 4, + false, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } + } + }, + { + AURA_ROG_STRIX_IMPACT_II_WHITE_PID, // ROG Strix Impact II Moonlight White + { + 0, + 0, + 0, + 4, + false, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } + } + }, + { + AURA_ROG_STRIX_IMPACT_II_WIRELESS_USB_PID, // ROG Strix Impact II Wireless USB + { + 0, + 0, + 0, + 4, + false, + 1, // not tested, but likely same as ROG Strix Impact II non wireless + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_STRIX_IMPACT_II_WIRELESS_2_4_PID, // ROG Strix Impact II Wireless 2.4 GHz Dongle + { + 0, + 0, + 0, + 4, + true, + 1, // not tested, but likely same as ROG Strix Impact II non wireless + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_STRIX_IMPACT_III_PID, // ROG Strix Impact III + { + 0, + 0, + 0, + 100, + false, + 1, + true, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE } + } + }, + { + AURA_ROG_KERIS, // ROG Keris + { + 0, + 0, + 0, + 4, + false, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } + } + }, + { + AURA_ROG_KERIS_WIRELESS_USB_PID, // ROG Keris + { + 0, + 0, + 0, + 4, + false, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_KERIS_WIRELESS_2_4_PID, // ROG Keris + { + 0, + 0, + 0, + 4, + true, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_KERIS_WIRELESS_BT_PID, // ROG Keris + { + 0, + 0, + 0, + 4, + true, + 1, + false, + { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_KERIS_WIRELESS_AIMPOINT_USB_PID, // ROG Keris Wireless AimPoint + { + 0, + 0, + 0, + 100, + false, + 1, + true, + { AURA_MOUSE_ZONE_LOGO }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_ROG_KERIS_WIRELESS_AIMPOINT_2_4_PID, // ROG Keris Wireless AimPoint + { + 0, + 0, + 0, + 100, + true, + 2, + true, + { AURA_MOUSE_ZONE_LOGO }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } + } + }, + { + AURA_TUF_M3_PID, // TUF M3 + { + 0, + 0, + 0, + 4, + false, + 1, + false, + { AURA_MOUSE_ZONE_LOGO }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } + } + }, + { + AURA_TUF_M3_GEN_II_PID, // TUF M3 Gen II + { + 0, + 0, + 0, + 100, + false, + 1, + false, + { AURA_MOUSE_ZONE_LOGO }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } + } + }, + { + AURA_TUF_M5_PID, // TUF M5 + { + 0, + 0, + 0, + 4, + false, + 3, + false, + { AURA_MOUSE_ZONE_LOGO }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } + } + }, + { + AURA_ROG_SPATHA_X_DOCK_FAKE_PID, // Asus ROG Spatha X Dock (only in wireless mode) + { + 0, + 0, + 0, + 100, + false, + 1, + false, + { AURA_MOUSE_ZONE_DOCK }, + { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } + } + }, +}; + +typedef struct +{ + unsigned char led_amount; + std::map< unsigned char, std::vector> map; +} led_map; + +/*-----------------------------------------------------------------*\ +| LED MAP | +| | +| This maps the LEDs to the correct zone. | +| This is necessary, because openrgb doesn't support per-zone | +| lighting. To allow for per-zone color of modes like breathing, | +| the leds defined need to be the zones, which means the actual | +| LEDs can't be implemented. | +\*-----------------------------------------------------------------*/ +static std::map aura_mouse_led_maps = +{ + { + AURA_ROG_GLADIUS_III_WIRELESS_AIMPOINT_USB_PID, + { + 1, + { + { AURA_MOUSE_ZONE_LOGO, { 0 } }, + } + } + }, + { + AURA_ROG_GLADIUS_III_WIRELESS_AIMPOINT_2_4_PID, + { + 1, + { + { AURA_MOUSE_ZONE_LOGO, { 0 } }, + } + } + }, + { + AURA_ROG_KERIS_WIRELESS_AIMPOINT_USB_PID, + { + 1, + { + { AURA_MOUSE_ZONE_LOGO, { 0 } }, + } + } + }, + { + AURA_ROG_KERIS_WIRELESS_AIMPOINT_2_4_PID, + { + 1, + { + { AURA_MOUSE_ZONE_LOGO, { 0 } }, + } + } + }, + { + AURA_ROG_SPATHA_X_2_4_PID, + { + 5, + { + { AURA_MOUSE_ZONE_LOGO, { 0 } }, + { AURA_MOUSE_ZONE_SCROLL, { 1 } }, + { AURA_MOUSE_ZONE_UNDERGLOW, { 2, 3, 4 } }, + } + } + }, + { + AURA_ROG_SPATHA_X_USB_PID, + { + 5, + { + { AURA_MOUSE_ZONE_LOGO, { 0 } }, + { AURA_MOUSE_ZONE_SCROLL, { 1 } }, + { AURA_MOUSE_ZONE_UNDERGLOW, { 2, 3, 4 } }, + } + } + }, + { + AURA_ROG_CHAKRAM_X_USB_PID, + { + 9, + { + { AURA_MOUSE_ZONE_LOGO, { 7 } }, + { AURA_MOUSE_ZONE_SCROLL, { 8 } }, + { AURA_MOUSE_ZONE_UNDERGLOW, { 0, 1, 2, 3, 4, 5, 6 } }, + } + } + }, + { + AURA_ROG_CHAKRAM_X_2_4_PID, + { + 9, + { + { AURA_MOUSE_ZONE_LOGO, { 7 } }, + { AURA_MOUSE_ZONE_SCROLL, { 8 } }, + { AURA_MOUSE_ZONE_UNDERGLOW, { 0, 1, 2, 3, 4, 5, 6 } }, + } + } + }, + { + AURA_ROG_STRIX_IMPACT_III_PID, + { + 2, + { + { AURA_MOUSE_ZONE_LOGO, { 0 } }, + { AURA_MOUSE_ZONE_SCROLL, { 1 } }, + } + } + } +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraMouseController/RGBController_AsusAuraMouse.cpp b/Controllers/AsusAuraUSBController/AsusAuraMouseController/RGBController_AsusAuraMouse.cpp new file mode 100644 index 00000000..323d43a1 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMouseController/RGBController_AsusAuraMouse.cpp @@ -0,0 +1,304 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraMouse.cpp | +| | +| RGBController for ASUS Aura mouse | +| | +| Adam Honse (CalcProgrammer1) 25 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_AsusAuraMouse.h" + +static std::string aura_mouse_zone_names[5] +{ + "Logo", + "Scroll Wheel", + "Underglow", + "All", + "Dock" +}; + +/**------------------------------------------------------------------*\ + @name Asus Aura Mouse + @category Mouse + @type USB + @save :white_check_mark: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectAsusAuraUSBMice + @comment +\*-------------------------------------------------------------------*/ + +RGBController_AuraMouse::RGBController_AuraMouse(AuraMouseController* controller_ptr) +{ + controller = controller_ptr; + + pid = controller->device_pid; + + name = controller->GetName(); + vendor = "ASUS"; + type = DEVICE_TYPE_MOUSE; + description = "ASUS Aura Mouse Device"; + version = controller->GetVersion(aura_mouse_devices[pid].wireless, aura_mouse_devices[pid].version_protocol); + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + std::vector mm = aura_mouse_devices[pid].mouse_modes; + + if(aura_mouse_devices[pid].direct) + { + mode Direct; + Direct.name = "Direct"; + Direct.value = 254; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + } + + int mode_value = 0; + + for(std::vector::iterator it = mm.begin(); it != mm.end(); it++) + { + switch(*it) + { + case AURA_MOUSE_MODE_STATIC: + /*-----------------------------------------------------------------*\ + | If there is no direct mode, this mode can be used as direct | + | (Asus does it the same way). | + | The acutal direct mode is only found on new devices and on | + | these devices static can't be used as direct anymore as it is | + | too slow. The Spatha X's dock can't be controlled, because | + | static is too slow and it can't be adressed in direct | + \*-----------------------------------------------------------------*/ + { + mode Static; + Static.name = (aura_mouse_devices[pid].direct || pid == AURA_ROG_SPATHA_X_DOCK_FAKE_PID)? "Static" : "Direct"; + Static.value = mode_value; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Static.brightness_min = aura_mouse_devices[pid].brightness_min; + Static.brightness_max = aura_mouse_devices[pid].brightness_max; + Static.brightness = aura_mouse_devices[pid].brightness_max; + Static.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Static); + } + break; + + case AURA_MOUSE_MODE_BREATHING: + { + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = mode_value; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Breathing.brightness_min = aura_mouse_devices[pid].brightness_min; + Breathing.brightness_max = aura_mouse_devices[pid].brightness_max; + Breathing.brightness = aura_mouse_devices[pid].brightness_max; + Breathing.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Breathing); + } + break; + + case AURA_MOUSE_MODE_SPECTRUM: + { + mode ColorCycle; + ColorCycle.name = "Spectrum Cycle"; + ColorCycle.value = mode_value; + ColorCycle.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE ; + ColorCycle.brightness_min = aura_mouse_devices[pid].brightness_min; + ColorCycle.brightness_max = aura_mouse_devices[pid].brightness_max; + ColorCycle.brightness = aura_mouse_devices[pid].brightness_max; + ColorCycle.color_mode = MODE_COLORS_NONE; + modes.push_back(ColorCycle); + } + break; + + case AURA_MOUSE_MODE_WAVE: + { + mode Wave; + Wave.name = "Rainbow Wave"; + Wave.value = mode_value; + Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Wave.direction = 0; + Wave.speed_min = aura_mouse_devices[pid].speed_min; + Wave.speed_max = aura_mouse_devices[pid].speed_max; + Wave.speed = (aura_mouse_devices[pid].speed_min + aura_mouse_devices[pid].speed_max) / 2; + Wave.brightness_min = aura_mouse_devices[pid].brightness_min; + Wave.brightness_max = aura_mouse_devices[pid].brightness_max; + Wave.brightness = aura_mouse_devices[pid].brightness_max; + Wave.color_mode = MODE_COLORS_NONE; + modes.push_back(Wave); + } + break; + + case AURA_MOUSE_MODE_REACTIVE: + { + mode Reactive; + Reactive.name = "Reactive"; + Reactive.value = mode_value; + Reactive.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Reactive.brightness_min = aura_mouse_devices[pid].brightness_min; + Reactive.brightness_max = aura_mouse_devices[pid].brightness_max; + Reactive.brightness = aura_mouse_devices[pid].brightness_max; + Reactive.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Reactive); + } + break; + + case AURA_MOUSE_MODE_COMET: + { + mode Comet; + Comet.name = "Comet"; + Comet.value = mode_value; + Comet.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Comet.brightness_min = aura_mouse_devices[pid].brightness_min; + Comet.brightness_max = aura_mouse_devices[pid].brightness_max; + Comet.brightness = aura_mouse_devices[pid].brightness_max; + Comet.color_mode = MODE_COLORS_MODE_SPECIFIC; + Comet.direction = 0; + Comet.colors_min = 1; + Comet.colors_max = 1; + Comet.colors.resize(1); + modes.push_back(Comet); + } + break; + + case AURA_MOUSE_MODE_BATTERY: + { + mode BatteryMode; + BatteryMode.name = "Battery"; + BatteryMode.value = mode_value; + BatteryMode.flags = MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + BatteryMode.brightness_min = aura_mouse_devices[pid].brightness_min; + BatteryMode.brightness_max = aura_mouse_devices[pid].brightness_max; + BatteryMode.brightness = aura_mouse_devices[pid].brightness_max; + BatteryMode.color_mode = MODE_COLORS_NONE; + modes.push_back(BatteryMode); + } + break; + } + mode_value++; + } + + SetupZones(); +} + +RGBController_AuraMouse::~RGBController_AuraMouse() +{ + delete controller; +} + +void RGBController_AuraMouse::SetupZones() +{ + for(std::vector::iterator zone_it = aura_mouse_devices[pid].mouse_zones.begin(); zone_it != aura_mouse_devices[pid].mouse_zones.end(); zone_it++) + { + zone mouse_zone; + + mouse_zone.name = aura_mouse_zone_names[*zone_it]; + mouse_zone.type = ZONE_TYPE_SINGLE; + mouse_zone.leds_min = 1; + mouse_zone.leds_max = 1; + mouse_zone.leds_count = 1; + mouse_zone.matrix_map = NULL; + + zones.push_back(mouse_zone); + + led mouse_led; + + mouse_led.name = mouse_zone.name + " LED"; + mouse_led.value = *zone_it; + + leds.push_back(mouse_led); + } + + SetupColors(); +} + +void RGBController_AuraMouse::ResizeZone(int /*zone*/, int /*new_size*/) +{ + +} + +void RGBController_AuraMouse::DeviceUpdateLEDs() +{ + if(modes[active_mode].value == AURA_MOUSE_MODE_DIRECT) + { + controller->SendDirect(colors); + } + else + { + for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++) + { + UpdateSingleLED(zone_index); + } + } +} + +void RGBController_AuraMouse::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_AuraMouse::UpdateSingleLED(int led) +{ + if(modes[active_mode].value == AURA_MOUSE_MODE_DIRECT) + { + DeviceUpdateLEDs(); + return; + } + + uint8_t red = RGBGetRValue(colors[led]); + uint8_t grn = RGBGetGValue(colors[led]); + uint8_t blu = RGBGetBValue(colors[led]); + + controller->SendUpdate(leds[led].value, modes[active_mode].value, red, grn, blu, 0, false, 0, modes[active_mode].brightness); +} + +void RGBController_AuraMouse::DeviceUpdateMode() +{ + if(modes[active_mode].value == AURA_MOUSE_MODE_DIRECT) + { + return; + } + + if(modes[active_mode].color_mode == MODE_COLORS_PER_LED) + { + DeviceUpdateLEDs(); + } + else + { + unsigned char red = 0; + unsigned char grn = 0; + unsigned char blu = 0; + + if (modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + red = RGBGetRValue(modes[active_mode].colors[0]); + grn = RGBGetGValue(modes[active_mode].colors[0]); + blu = RGBGetBValue(modes[active_mode].colors[0]); + } + + + if(pid == AURA_ROG_SPATHA_X_DOCK_FAKE_PID) + { + controller->SendUpdate(AURA_MOUSE_ZONE_DOCK, modes[active_mode].value, red, grn, blu, modes[active_mode].direction, modes[active_mode].color_mode == MODE_COLORS_RANDOM, modes[active_mode].speed, modes[active_mode].brightness); + } + else if(pid == AURA_ROG_STRIX_IMPACT_PID) + { + /*-----------------------------------------------------------------*\ + | The ROG Impact doesn't accept AURA_MOUSE_ZONE_ALL | + \*-----------------------------------------------------------------*/ + controller->SendUpdate(AURA_MOUSE_ZONE_LOGO, modes[active_mode].value, red, grn, blu, modes[active_mode].direction, modes[active_mode].color_mode == MODE_COLORS_RANDOM, modes[active_mode].speed, modes[active_mode].brightness); + } + else + { + controller->SendUpdate(AURA_MOUSE_ZONE_ALL, modes[active_mode].value, red, grn, blu, modes[active_mode].direction, modes[active_mode].color_mode == MODE_COLORS_RANDOM, modes[active_mode].speed, modes[active_mode].brightness); + } + } +} + +void RGBController_AuraMouse::DeviceSaveMode() +{ + DeviceUpdateMode(); + controller->SaveMode(); +} diff --git a/Controllers/AsusAuraUSBController/AsusAuraMouseController/RGBController_AsusAuraMouse.h b/Controllers/AsusAuraUSBController/AsusAuraMouseController/RGBController_AsusAuraMouse.h new file mode 100644 index 00000000..eb752b4c --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMouseController/RGBController_AsusAuraMouse.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraMouse.h | +| | +| RGBController for ASUS Aura mouse | +| | +| Adam Honse (CalcProgrammer1) 25 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AsusAuraMouseController.h" + +class RGBController_AuraMouse : public RGBController +{ +public: + RGBController_AuraMouse(AuraMouseController* controller_ptr); + ~RGBController_AuraMouse(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + AuraMouseController* controller; + uint16_t pid; +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraMouseDevices.h b/Controllers/AsusAuraUSBController/AsusAuraMouseDevices.h deleted file mode 100644 index ee4fd827..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraMouseDevices.h +++ /dev/null @@ -1,549 +0,0 @@ -/*-------------------------------------------------------------------*\ -| AsusAuraMouseDevices.h | -| | -| Asus Aura Mouse definitions and mapping | -| | -| Chris M (Dr_No) 11th July 2021 | -\*-------------------------------------------------------------------*/ - -#include -#include - -#pragma once - -#define AURA_ROG_GLADIUS_II_CORE_PID 0x18DD -#define AURA_ROG_GLADIUS_II_PID 0x1845 -#define AURA_ROG_GLADIUS_II_ORIGIN_PID 0x1877 -#define AURA_ROG_GLADIUS_II_ORIGIN_PNK_LTD_PID 0x18CD -#define AURA_ROG_GLADIUS_II_ORIGIN_COD_PID 0x18B1 -#define AURA_ROG_GLADIUS_II_WIRELESS_1_PID 0x189E -#define AURA_ROG_GLADIUS_II_WIRELESS_2_PID 0x18A0 -#define AURA_ROG_GLADIUS_III_PID 0x197B -#define AURA_ROG_GLADIUS_III_WIRELESS_USB_PID 0x197D -#define AURA_ROG_GLADIUS_III_WIRELESS_2_4_PID 0x197F -#define AURA_ROG_GLADIUS_III_WIRELESS_BT_PID 0x1981 -#define AURA_ROG_CHAKRAM_WIRELESS_PID 0x18E5 -#define AURA_ROG_CHAKRAM_WIRED_1_PID 0x18E3 -#define AURA_ROG_CHAKRAM_CORE_PID 0x1958 -#define AURA_ROG_CHAKRAM_X_USB_PID 0x1A18 -#define AURA_ROG_CHAKRAM_X_2_4_PID 0x1A1A -#define AURA_ROG_SPATHA_X_USB_PID 0x1977 -#define AURA_ROG_SPATHA_X_2_4_PID 0x1979 -#define AURA_ROG_PUGIO_PID 0x1846 -#define AURA_ROG_PUGIO_II_WIRED_PID 0x1906 -#define AURA_ROG_PUGIO_II_WIRELESS_PID 0x1908 -#define AURA_ROG_STRIX_IMPACT_PID 0x1847 -#define AURA_ROG_STRIX_IMPACT_II_PID 0x18E1 -#define AURA_ROG_STRIX_IMPACT_II_GUNDAM_PID 0x189E -#define AURA_ROG_STRIX_IMPACT_II_PUNK_PID 0x1956 -#define AURA_ROG_STRIX_IMPACT_II_WHITE_PID 0x19D2 -#define AURA_ROG_STRIX_IMPACT_II_WIRELESS_USB_PID 0x1947 -#define AURA_ROG_STRIX_IMPACT_II_WIRELESS_2_4_PID 0x1949 -#define AURA_ROG_KERIS 0x195C -#define AURA_ROG_KERIS_WIRELESS_USB_PID 0x195E -#define AURA_ROG_KERIS_WIRELESS_2_4_PID 0x1960 -#define AURA_ROG_KERIS_WIRELESS_BT_PID 0x1962 -#define AURA_TUF_M3_PID 0x1910 -#define AURA_TUF_M5_PID 0x1898 - -#define AURA_ROG_SPATHA_X_DOCK_FAKE_PID 0xFFFF - -enum -{ - AURA_MOUSE_ZONE_LOGO = 0, - AURA_MOUSE_ZONE_SCROLL = 1, - AURA_MOUSE_ZONE_UNDERGLOW = 2, - AURA_MOUSE_ZONE_ALL = 3, - AURA_MOUSE_ZONE_DOCK = 4, -}; - -enum -{ - AURA_MOUSE_MODE_STATIC = 0, - AURA_MOUSE_MODE_BREATHING = 1, - AURA_MOUSE_MODE_SPECTRUM = 2, - AURA_MOUSE_MODE_WAVE = 3, - AURA_MOUSE_MODE_REACTIVE = 4, - AURA_MOUSE_MODE_COMET = 5, - AURA_MOUSE_MODE_BATTERY = 6, - AURA_MOUSE_MODE_NONE = 255, -}; - -typedef struct -{ - uint8_t speed_min; - uint8_t speed_max; - uint8_t brightness_min; - uint8_t brightness_max; - bool wireless; - int version_protocol; - std::vector mouse_zones; - std::vector mouse_modes; -} mouse_type; - -/*-----------------------------------------------------------------*\ -| DEVICE MAP | -| | -| This structure maps the OpenRGB modes to the mode values | -| sent to each mouse. As not all modes are present on each | -| mouse the "mode index" is different. Eg. "Reactive" is mode | -| 4 on the Gladius II and mode 3 on the Gladius II wireless | -\*-----------------------------------------------------------------*/ -static std::map aura_mouse_devices = -{ - { - AURA_ROG_GLADIUS_II_CORE_PID, // ROG Gladius II Core - { - 0, // Speed Min - The Asus Mouse protocol defines larger numbers as slow - 0, // Speed Max - 0, // Brightness Min - 4, // Brightness Max - false, // is wireless? (important for fetching the version) - 1, // version protocol - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } - } - }, - { - AURA_ROG_GLADIUS_II_PID, // ROG Gladius II - { - 255, - 1, - 0, - 4, - false, - 0, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET } - } - }, - { - AURA_ROG_GLADIUS_II_ORIGIN_PID, // ROG Gladius II Origin - { - 255, - 1, - 0, - 4, - false, - 0, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET } - } - }, - { - AURA_ROG_GLADIUS_II_ORIGIN_COD_PID, // ROG Gladius II COD - { - 255, - 1, - 0, - 4, - false, - 0, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET } - } - }, - { - AURA_ROG_GLADIUS_II_ORIGIN_PNK_LTD_PID, // ROG Gladius II PNK LTD - { - 255, - 1, - 0, - 4, - false, - 0, - { AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET } - } - }, - { - AURA_ROG_GLADIUS_II_WIRELESS_1_PID, // ROG Gladius II Wireless - { - 0, - 0, - 0, - 4, - true, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_GLADIUS_II_WIRELESS_2_PID, // ROG Gladius II Wireless - { - 0, - 0, - 0, - 4, - true, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_GLADIUS_III_PID, // ROG Gladius III - { - 255, - 1, - 0, - 64, - false, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_GLADIUS_III_WIRELESS_USB_PID, // ROG Gladius III Wireless USB - { - 255, - 1, - 0, - 64, - false, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_GLADIUS_III_WIRELESS_2_4_PID, // ROG Gladius III Wireless 2.4 GHz Dongle - { - 255, - 1, - 0, - 64, - true, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_GLADIUS_III_WIRELESS_BT_PID, // ROG Gladius III Wireless Bluetooth - { - 255, - 1, - 0, - 64, - true, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_CHAKRAM_WIRELESS_PID, // ROG Chakram Wireless - { - 15, - 1, - 0, - 4, - true, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_CHAKRAM_WIRED_1_PID, // ROG Chakram Wired 1 - { - 15, - 1, - 0, - 4, - false, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_CHAKRAM_CORE_PID, // ROG Chakram Core - { - 0, - 0, - 0, - 4, - false, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } - } - }, - { - AURA_ROG_CHAKRAM_X_USB_PID, // ROG Chakram X USB - { - 15, // technically until 255, but unusably slow after 15 - 1, - 0, - 64, - false, - 2, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_CHAKRAM_X_2_4_PID, // ROG Chakram X 2.4GHz Dongle - { - 15, // technically until 255, but unusably slow after 15 - 1, - 0, - 64, - true, - 2, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_SPATHA_X_USB_PID, // ROG Spatha X USB - { - 15, // technically until 255, but unusably slow after 15 - 1, - 0, - 64, - false, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_SPATHA_X_2_4_PID, // ROG Spatha X 2.4GHz Dock - { - 15, // technically until 255, but unusably slow after 15 - 1, - 0, - 64, - true, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_PUGIO_PID, // ROG Pugio - { - 255, - 1, - 0, - 4, - false, - 0, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET } - } - }, - { - AURA_ROG_PUGIO_II_WIRED_PID, // ROG Pugio II Wired - { - 15, - 1, - 0, - 4, - false, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_PUGIO_II_WIRELESS_PID, // ROG Pugio II Wireless - { - 15, - 1, - 0, - 4, - true, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_WAVE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_COMET, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_STRIX_IMPACT_PID, // ROG Strix Impact - { - 0, - 0, - 0, - 4, - false, - 4, - { AURA_MOUSE_ZONE_LOGO }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE } - } - }, - { - AURA_ROG_STRIX_IMPACT_II_PID, // ROG Strix Impact II - { - 0, - 0, - 0, - 4, - false, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } - } - }, - { - AURA_ROG_STRIX_IMPACT_II_GUNDAM_PID, // ROG Strix Impact II Gundam - { - 0, - 0, - 0, - 4, - false, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } - } - }, - { - AURA_ROG_STRIX_IMPACT_II_PUNK_PID, // ROG Strix Impact II Electro Punk - { - 0, - 0, - 0, - 4, - false, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } - } - }, - { - AURA_ROG_STRIX_IMPACT_II_WHITE_PID, // ROG Strix Impact II Moonlight White - { - 0, - 0, - 0, - 4, - false, - 1, - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL, AURA_MOUSE_ZONE_UNDERGLOW }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } - } - }, - { - AURA_ROG_STRIX_IMPACT_II_WIRELESS_USB_PID, // ROG Strix Impact II Wireless USB - { - 0, - 0, - 0, - 4, - false, - 1, // not tested, but likely same as ROG Strix Impact II non wireless - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_STRIX_IMPACT_II_WIRELESS_2_4_PID, // ROG Strix Impact II Wireless 2.4 GHz Dongle - { - 0, - 0, - 0, - 4, - true, - 1, // not tested, but likely same as ROG Strix Impact II non wireless - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_KERIS, // ROG Keris - { - 0, - 0, - 0, - 4, - false, - 1, // might be the wrong protocol for version - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } - } - }, - { - AURA_ROG_KERIS_WIRELESS_USB_PID, // ROG Keris - { - 0, - 0, - 0, - 4, - true, - 1, // might be the wrong protocol for version - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_KERIS_WIRELESS_2_4_PID, // ROG Keris - { - 0, - 0, - 0, - 4, - true, - 1, // might be the wrong protocol for version - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_ROG_KERIS_WIRELESS_BT_PID, // ROG Keris - { - 0, - 0, - 0, - 4, - true, - 1, // might be the wrong protocol for version - { AURA_MOUSE_ZONE_LOGO, AURA_MOUSE_ZONE_SCROLL }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } - } - }, - { - AURA_TUF_M3_PID, // TUF M3 - { - 0, - 0, - 0, - 4, - false, - 1, - { AURA_MOUSE_ZONE_LOGO }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } - } - }, - { - AURA_TUF_M5_PID, // TUF M5 - { - 0, - 0, - 0, - 4, - false, - 3, - { AURA_MOUSE_ZONE_LOGO }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_REACTIVE } - } - }, - { - AURA_ROG_SPATHA_X_DOCK_FAKE_PID, // Asus ROG Spatha X Dock (only in wireless mode) - { - 0, - 0, - 0, - 100, - false, - 1, - { AURA_MOUSE_ZONE_DOCK }, - { AURA_MOUSE_MODE_STATIC, AURA_MOUSE_MODE_BREATHING, AURA_MOUSE_MODE_SPECTRUM, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_REACTIVE, AURA_MOUSE_MODE_NONE, AURA_MOUSE_MODE_BATTERY } - } - }, -}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/AsusAuraMouseGen1Controller.cpp b/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/AsusAuraMouseGen1Controller.cpp new file mode 100644 index 00000000..6026aef4 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/AsusAuraMouseGen1Controller.cpp @@ -0,0 +1,181 @@ +/*---------------------------------------------------------*\ +| AsusAuraMouseGen1Controller.cpp | +| | +| Driver for ASUS Aura gen 1 mouse | +| | +| Mola19 30 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include "AsusAuraMouseGen1Controller.h" +#include "StringUtils.h" + +AsusAuraMouseGen1Controller::AsusAuraMouseGen1Controller(hid_device* dev_handle, const char* path, uint16_t pid, std::string dev_name) +{ + dev = dev_handle; + location = path; + device_pid = pid; + name = dev_name; +} + +AsusAuraMouseGen1Controller::~AsusAuraMouseGen1Controller() +{ + hid_close(dev); +} + +std::string AsusAuraMouseGen1Controller::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string AsusAuraMouseGen1Controller::GetName() +{ + return(name); +} + +std::string AsusAuraMouseGen1Controller::GetSerialString() +{ + wchar_t serial_string[HID_MAX_STR]; + int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string AsusAuraMouseGen1Controller::GetVersion() +{ + unsigned char usb_buf[9] = { 0x0C, 0xC4, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + usb_buf[3] = (device_pid == 0x1824) ? 0x02 : 0x00; + hid_send_feature_report(dev, usb_buf, 9); + + unsigned char usb_buf_out[9] = { 0x0C }; + hid_get_feature_report(dev, usb_buf_out, 9); + + return std::string("1." + std::to_string(usb_buf_out[3])); +} + +int AsusAuraMouseGen1Controller::GetActiveProfile() +{ + unsigned char profile; + + unsigned char profile_amount = 0; + unsigned char profile_key = 0; + + switch(device_pid) + { + case 0x185B: + profile_amount = 3; + profile_key = 0xF0; + break; + case 0x181C: + case 0x1824: + default: + profile_amount = 6; + profile_key = 0x60; + break; + } + + do + { + unsigned char usb_buf[9] = { 0x0C, 0xDF, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + hid_send_feature_report(dev, usb_buf, 9); + + unsigned char usb_buf_out[9] = { 0x0C }; + hid_get_feature_report(dev, usb_buf_out, 9); + + profile = usb_buf_out[4]; + } while(profile < profile_key || profile > profile_key + profile_amount - 1); + + return (profile % 16) + 1; +} + +void AsusAuraMouseGen1Controller::SendUpdate + ( + unsigned char key, + unsigned char value + ) +{ + unsigned char usb_buf[9]; + + memset(usb_buf, 0x00, 9); + + usb_buf[0x00] = 0x0C; + usb_buf[0x01] = 0xC4; + usb_buf[0x02] = 0x0F; + usb_buf[0x03] = 0x00; + usb_buf[0x04] = key; + usb_buf[0x05] = value; + hid_send_feature_report(dev, usb_buf, 9); + + unsigned char buf_in[9]; + buf_in[0] = 0x0C; + hid_get_feature_report(dev, buf_in, 9); + + std::this_thread::sleep_for(std::chrono::milliseconds(15)); +} + + +void AsusAuraMouseGen1Controller::UpdateProfile + ( + unsigned char key, + unsigned char profile, + unsigned char value + ) +{ + unsigned char usb_buf[9]; + + memset(usb_buf, 0x00, 9); + + usb_buf[0x00] = 0x0C; + usb_buf[0x01] = 0xDE; + usb_buf[0x02] = key; + usb_buf[0x03] = profile; + usb_buf[0x04] = value; + hid_send_feature_report(dev, usb_buf, 9); + + unsigned char buf_in[9]; + buf_in[0] = 0x0C; + hid_get_feature_report(dev, buf_in, 9); +} + +void AsusAuraMouseGen1Controller::SendDirectSpatha(std::vector colors) +{ + unsigned char usb_buf[33]; + + memset(usb_buf, 0x00, 33); + + usb_buf[0x00] = 0x10; + usb_buf[0x01] = 0x00; + usb_buf[0x02] = 0xF0; + usb_buf[0x03] = 0x00; + + for(unsigned char i = 0; i < 3; i++) + { + usb_buf[4 + i * 3] = RGBGetRValue(colors[i]); + usb_buf[5 + i * 3] = RGBGetGValue(colors[i]); + usb_buf[6 + i * 3] = RGBGetBValue(colors[i]); + } + + hid_send_feature_report(dev, usb_buf, 33); +} + +void AsusAuraMouseGen1Controller::ResetToSavedLighting() +{ + unsigned char usb_buf[9]; + + memset(usb_buf, 0x00, 9); + + usb_buf[0x00] = 0x0C; + usb_buf[0x01] = 0xC4; + + hid_send_feature_report(dev, usb_buf, 9); +} diff --git a/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/AsusAuraMouseGen1Controller.h b/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/AsusAuraMouseGen1Controller.h new file mode 100644 index 00000000..a4b8e943 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/AsusAuraMouseGen1Controller.h @@ -0,0 +1,57 @@ +/*---------------------------------------------------------*\ +| AsusAuraMouseGen1Controller.h | +| | +| Driver for ASUS Aura gen 1 mouse | +| | +| Mola19 30 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" + +#define HID_MAX_STR 255 + +class AsusAuraMouseGen1Controller +{ +public: + AsusAuraMouseGen1Controller(hid_device* dev_handle, const char* path, uint16_t pid, std::string dev_name); + virtual ~AsusAuraMouseGen1Controller(); + + std::string GetDeviceLocation(); + std::string GetName(); + std::string GetSerialString(); + std::string GetVersion(); + + int GetActiveProfile(); + + void SendUpdate + ( + unsigned char key, + unsigned char value + ); + + void UpdateProfile + ( + unsigned char key, + unsigned char profile, + unsigned char value + ); + + void SendDirectSpatha(std::vector colors); + + void ResetToSavedLighting(); + + uint16_t device_pid; + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/RGBController_AsusROGSpatha.cpp b/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/RGBController_AsusROGSpatha.cpp new file mode 100644 index 00000000..7161e7b6 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/RGBController_AsusROGSpatha.cpp @@ -0,0 +1,274 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusROGSpatha.cpp | +| | +| RGBController for ASUS ROG Spatha | +| | +| Mola19 05 Nov 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_AsusROGSpatha.h" + +/**------------------------------------------------------------------*\ + @name Asus Aura Spatha + @category Mouse + @type USB + @save :white_check_mark: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectAsusAuraUSBSpatha + @comment This device allows indiviual modes for each zone, + which currently can't be implemented in OpenRGB. + Also there seem to be a firmware bug which causes static + to use a random colorand random to use a static color + that was previously set. This can be worked around by saving +\*-------------------------------------------------------------------*/ + +RGBController_AsusROGSpatha::RGBController_AsusROGSpatha(AsusAuraMouseGen1Controller* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = "ASUS"; + type = DEVICE_TYPE_MOUSE; + description = "ASUS Aura Mouse Device"; + version = controller->GetVersion(); + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = ASUS_ROG_SPATHA_MODE_DIRECT; + 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 = ASUS_ROG_SPATHA_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Static.brightness_min = ASUS_ROG_SPATHA_BRIGHTNESS_MIN; + Static.brightness_max = ASUS_ROG_SPATHA_BRIGHTNESS_MAX; + Static.brightness = ASUS_ROG_SPATHA_BRIGHTNESS_DEFAULT; + Static.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = ASUS_ROG_SPATHA_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Breathing.brightness_min = ASUS_ROG_SPATHA_BRIGHTNESS_MIN; + Breathing.brightness_max = ASUS_ROG_SPATHA_BRIGHTNESS_MAX; + Breathing.brightness = ASUS_ROG_SPATHA_BRIGHTNESS_DEFAULT; + Breathing.colors_min = 2; + Breathing.colors_max = 2; + Breathing.colors.resize(2); + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + modes.push_back(Breathing); + + mode ColorCycle; + ColorCycle.name = "Spectrum Cycle"; + ColorCycle.value = ASUS_ROG_SPATHA_MODE_SPECTRUM_CYCLE; + ColorCycle.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + ColorCycle.brightness_min = ASUS_ROG_SPATHA_BRIGHTNESS_MIN; + ColorCycle.brightness_max = ASUS_ROG_SPATHA_BRIGHTNESS_MAX; + ColorCycle.brightness = ASUS_ROG_SPATHA_BRIGHTNESS_DEFAULT; + ColorCycle.colors_min = 12; + ColorCycle.colors_max = 12; + ColorCycle.colors.resize(12); + ColorCycle.color_mode = MODE_COLORS_MODE_SPECIFIC; + modes.push_back(ColorCycle); + + mode Random; + Random.name = "Random"; + Random.value = ASUS_ROG_SPATHA_MODE_RANDOM; + Random.flags = MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Random.brightness_min = ASUS_ROG_SPATHA_BRIGHTNESS_MIN; + Random.brightness_max = ASUS_ROG_SPATHA_BRIGHTNESS_MAX; + Random.brightness = ASUS_ROG_SPATHA_BRIGHTNESS_DEFAULT; + Random.color_mode = MODE_COLORS_NONE; + modes.push_back(Random); + + mode Reactive; + Reactive.name = "Reactive"; + Reactive.value = ASUS_ROG_SPATHA_MODE_REACTIVE; + Reactive.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Reactive.brightness_min = ASUS_ROG_SPATHA_BRIGHTNESS_MIN; + Reactive.brightness_max = ASUS_ROG_SPATHA_BRIGHTNESS_MAX; + Reactive.brightness = ASUS_ROG_SPATHA_BRIGHTNESS_DEFAULT; + Reactive.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Reactive); + + mode Battery; + Battery.name = "Battery"; + Battery.value = ASUS_ROG_SPATHA_MODE_BATTERY; + Battery.flags = MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Battery.brightness_min = ASUS_ROG_SPATHA_BRIGHTNESS_MIN; + Battery.brightness_max = ASUS_ROG_SPATHA_BRIGHTNESS_MAX; + Battery.brightness = ASUS_ROG_SPATHA_BRIGHTNESS_DEFAULT; + Battery.color_mode = MODE_COLORS_NONE; + modes.push_back(Battery); + + SetupZones(); +} + +RGBController_AsusROGSpatha::~RGBController_AsusROGSpatha() +{ + delete controller; +} + +void RGBController_AsusROGSpatha::SetupZones() +{ + + std::string zones_names[3] = {"Side", "Scroll Wheel", "Logo"}; + + for(unsigned char i = 0; i < 3; i++) + { + zone spatha_zone; + + spatha_zone.name = zones_names[i]; + spatha_zone.type = ZONE_TYPE_SINGLE; + spatha_zone.leds_min = 1; + spatha_zone.leds_max = 1; + spatha_zone.leds_count = 1; + spatha_zone.matrix_map = NULL; + + zones.push_back(spatha_zone); + + led spatha_led; + + spatha_led.name = zones_names[i]; + spatha_led.value = 1; + + leds.push_back(spatha_led); + } + + SetupColors(); +} + +void RGBController_AsusROGSpatha::ResizeZone(int /*zone*/, int /*new_size*/) +{ + +} + +void RGBController_AsusROGSpatha::DeviceUpdateLEDs() +{ + if(modes[active_mode].value == ASUS_ROG_SPATHA_MODE_DIRECT) + { + controller->SendDirectSpatha(colors); + } + else + { + UpdateSingleLED(0); + UpdateSingleLED(1); + UpdateSingleLED(2); + } +} + +void RGBController_AsusROGSpatha::UpdateZoneLEDs(int zone) +{ + if(modes[active_mode].value == ASUS_ROG_SPATHA_MODE_DIRECT) + { + controller->SendDirectSpatha(colors); + } + else + { + UpdateSingleLED(zone); + } +} + +void RGBController_AsusROGSpatha::UpdateSingleLED(int led) +{ + if(modes[active_mode].value == ASUS_ROG_SPATHA_MODE_DIRECT) + { + controller->SendDirectSpatha(colors); + } + else + { + controller->SendUpdate(0x13 + led * 38, RGBGetRValue(colors[led])); + controller->SendUpdate(0x14 + led * 38, RGBGetGValue(colors[led])); + controller->SendUpdate(0x15 + led * 38, RGBGetBValue(colors[led])); + } +} + +void RGBController_AsusROGSpatha::DeviceUpdateMode() +{ + if(modes[active_mode].value == ASUS_ROG_SPATHA_MODE_DIRECT) + { + return; + } + + /*-----------------------------------------------------*\ + | Needed to overwrite direct | + \*-----------------------------------------------------*/ + controller->ResetToSavedLighting(); + + /*-----------------------------------------------------*\ + | Send data to all 3 zones | + \*-----------------------------------------------------*/ + for(int i = 0; i < 3; i++) + { + controller->SendUpdate(0x11 + i * 38, modes[active_mode].value); + + /*------------------------------------------------------------------*\ + | This mouse has independent brightness for wired and wireless. | + | Each is 4-bit in the same byte (wireless is the first/bigger one). | + | OpenRGB misses that feature, hence both are the same | + \*------------------------------------------------------------------*/ + controller->SendUpdate(0x12 + i * 38, (modes[active_mode].brightness << 4) + modes[active_mode].brightness); + + if(modes[active_mode].value == ASUS_ROG_SPATHA_MODE_SPECTRUM_CYCLE || modes[active_mode].value == ASUS_ROG_SPATHA_MODE_BREATHING) + { + for(unsigned int j = 0; j < modes[active_mode].colors.size(); j++) + { + controller->SendUpdate(0x13 + j * 3 + i * 38, RGBGetRValue(modes[active_mode].colors[j])); + controller->SendUpdate(0x14 + j * 3 + i * 38, RGBGetGValue(modes[active_mode].colors[j])); + controller->SendUpdate(0x15 + j * 3 + i * 38, RGBGetBValue(modes[active_mode].colors[j])); + } + } + } +} + +void RGBController_AsusROGSpatha::DeviceSaveMode() +{ + if(modes[active_mode].value == ASUS_ROG_SPATHA_MODE_DIRECT) + { + return; + } + + unsigned int profile = controller->GetActiveProfile(); + + /*-----------------------------------------------------*\ + | Send data to all 3 zones | + \*-----------------------------------------------------*/ + for(int i = 0; i < 3; i++) + { + controller->UpdateProfile(0x11 + i * 38, profile, modes[active_mode].value); + /*------------------------------------------------------------------*\ + | This mouse has independent brightness for wired and wireless. | + | Each is 4-bit in the same byte (wireless is the first/bigger one). | + | OpenRGB misses that feature, hence both are the same | + \*------------------------------------------------------------------*/ + controller->UpdateProfile(0x12 + i * 38, profile, (modes[active_mode].brightness << 4) + modes[active_mode].brightness); + + if(modes[active_mode].value == ASUS_ROG_SPATHA_MODE_SPECTRUM_CYCLE || modes[active_mode].value == ASUS_ROG_SPATHA_MODE_BREATHING) + { + for(unsigned int j = 0; j < modes[active_mode].colors.size(); j++) + { + controller->UpdateProfile(0x13 + j * 3 + i * 38, profile, RGBGetRValue(modes[active_mode].colors[j])); + controller->UpdateProfile(0x14 + j * 3 + i * 38, profile, RGBGetGValue(modes[active_mode].colors[j])); + controller->UpdateProfile(0x15 + j * 3 + i * 38, profile, RGBGetBValue(modes[active_mode].colors[j])); + } + } + else if(modes[active_mode].value == ASUS_ROG_SPATHA_MODE_STATIC || modes[active_mode].value == ASUS_ROG_SPATHA_MODE_REACTIVE) + { + controller->UpdateProfile(0x13 + i * 38, profile, RGBGetRValue(colors[i])); + controller->UpdateProfile(0x14 + i * 38, profile, RGBGetGValue(colors[i])); + controller->UpdateProfile(0x15 + i * 38, profile, RGBGetBValue(colors[i])); + } + } + + controller->ResetToSavedLighting(); +} diff --git a/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/RGBController_AsusROGSpatha.h b/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/RGBController_AsusROGSpatha.h new file mode 100644 index 00000000..d532177c --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/RGBController_AsusROGSpatha.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusROGSpatha.h | +| | +| RGBController for ASUS ROG Spatha | +| | +| Mola19 05 Nov 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AsusAuraMouseGen1Controller.h" + +enum +{ + ASUS_ROG_SPATHA_BRIGHTNESS_MIN = 0, + ASUS_ROG_SPATHA_BRIGHTNESS_MAX = 15, + ASUS_ROG_SPATHA_BRIGHTNESS_DEFAULT = 15 +}; + +enum +{ + ASUS_ROG_SPATHA_MODE_DIRECT = 0xFF, + ASUS_ROG_SPATHA_MODE_STATIC = 0x01, + ASUS_ROG_SPATHA_MODE_SPECTRUM_CYCLE = 0x05, + ASUS_ROG_SPATHA_MODE_RANDOM = 0x06, + ASUS_ROG_SPATHA_MODE_BREATHING = 0x0A, + ASUS_ROG_SPATHA_MODE_BATTERY = 0x0B, + ASUS_ROG_SPATHA_MODE_REACTIVE = 0x0C, +}; + +class RGBController_AsusROGSpatha : public RGBController +{ +public: + RGBController_AsusROGSpatha(AsusAuraMouseGen1Controller* controller_ptr); + ~RGBController_AsusROGSpatha(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + AsusAuraMouseGen1Controller* controller; +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/RGBController_AsusROGStrixEvolve.cpp b/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/RGBController_AsusROGStrixEvolve.cpp new file mode 100644 index 00000000..aadbcb8c --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/RGBController_AsusROGStrixEvolve.cpp @@ -0,0 +1,152 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusROGStrixEvolve.cpp | +| | +| RGBController for ASUS ROG Evolve | +| | +| Mola19 30 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_AsusROGStrixEvolve.h" + +/**------------------------------------------------------------------*\ + @name Asus Aura Strix Evolve + @category Mouse + @type USB + @save :white_check_mark: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectAsusAuraUSBStrixEvolve + @comment +\*-------------------------------------------------------------------*/ + +RGBController_AsusROGStrixEvolve::RGBController_AsusROGStrixEvolve(AsusAuraMouseGen1Controller* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = "ASUS"; + type = DEVICE_TYPE_MOUSE; + description = "ASUS Aura Mouse Device"; + version = controller->GetVersion(); + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = ASUS_ROG_STRIX_EVOLVE_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Direct.brightness_min = ASUS_ROG_STRIX_EVOLVE_BRIGHTNESS_MIN; + Direct.brightness_max = ASUS_ROG_STRIX_EVOLVE_BRIGHTNESS_MAX; + Direct.brightness = ASUS_ROG_STRIX_EVOLVE_BRIGHTNESS_DEFAULT; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = ASUS_ROG_STRIX_EVOLVE_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Breathing.brightness_min = ASUS_ROG_STRIX_EVOLVE_BRIGHTNESS_MIN; + Breathing.brightness_max = ASUS_ROG_STRIX_EVOLVE_BRIGHTNESS_MAX; + Breathing.brightness = ASUS_ROG_STRIX_EVOLVE_BRIGHTNESS_DEFAULT; + Breathing.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Breathing); + + mode ColorCycle; + ColorCycle.name = "Spectrum Cycle"; + ColorCycle.value = ASUS_ROG_STRIX_EVOLVE_MODE_SPECTRUM_CYCLE; + ColorCycle.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + ColorCycle.brightness_min = ASUS_ROG_STRIX_EVOLVE_BRIGHTNESS_MIN; + ColorCycle.brightness_max = ASUS_ROG_STRIX_EVOLVE_BRIGHTNESS_MAX; + ColorCycle.brightness = ASUS_ROG_STRIX_EVOLVE_BRIGHTNESS_DEFAULT; + ColorCycle.color_mode = MODE_COLORS_NONE; + modes.push_back(ColorCycle); + + mode Reactive; + Reactive.name = "Reactive"; + Reactive.value = ASUS_ROG_STRIX_EVOLVE_MODE_REACTIVE; + Reactive.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Reactive.brightness_min = ASUS_ROG_STRIX_EVOLVE_BRIGHTNESS_MIN; + Reactive.brightness_max = ASUS_ROG_STRIX_EVOLVE_BRIGHTNESS_MAX; + Reactive.brightness = ASUS_ROG_STRIX_EVOLVE_BRIGHTNESS_DEFAULT; + Reactive.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Reactive); + + SetupZones(); +} + +RGBController_AsusROGStrixEvolve::~RGBController_AsusROGStrixEvolve() +{ + delete controller; +} + +void RGBController_AsusROGStrixEvolve::SetupZones() +{ + zone mouse_zone; + + mouse_zone.name = "Underglow"; + mouse_zone.type = ZONE_TYPE_SINGLE; + mouse_zone.leds_min = 1; + mouse_zone.leds_max = 1; + mouse_zone.leds_count = 1; + mouse_zone.matrix_map = NULL; + + zones.push_back(mouse_zone); + + led mouse_led; + + mouse_led.name = "Underglow"; + mouse_led.value = 1; + + leds.push_back(mouse_led); + + SetupColors(); +} + +void RGBController_AsusROGStrixEvolve::ResizeZone(int /*zone*/, int /*new_size*/) +{ + +} + +void RGBController_AsusROGStrixEvolve::DeviceUpdateLEDs() +{ + UpdateSingleLED(0); +} + +void RGBController_AsusROGStrixEvolve::UpdateZoneLEDs(int zone) +{ + UpdateSingleLED(zone); +} + +void RGBController_AsusROGStrixEvolve::UpdateSingleLED(int /*led*/) +{ + controller->SendUpdate(0x1C, RGBGetRValue(colors[0])); + controller->SendUpdate(0x1D, RGBGetGValue(colors[0])); + controller->SendUpdate(0x1E, RGBGetBValue(colors[0])); +} + +void RGBController_AsusROGStrixEvolve::DeviceUpdateMode() +{ + controller->SendUpdate(0x19, modes[active_mode].value); + controller->SendUpdate(0x1A, modes[active_mode].brightness); +} + +void RGBController_AsusROGStrixEvolve::DeviceSaveMode() +{ + unsigned int profile = controller->GetActiveProfile(); + + + controller->UpdateProfile(0x19, profile, modes[active_mode].value); + controller->UpdateProfile(0x1A, profile, modes[active_mode].brightness); + + if(modes[active_mode].value != ASUS_ROG_STRIX_EVOLVE_MODE_SPECTRUM_CYCLE) + { + controller->UpdateProfile(0x1C, profile, RGBGetRValue(colors[0])); + controller->UpdateProfile(0x1D, profile, RGBGetGValue(colors[0])); + controller->UpdateProfile(0x1E, profile, RGBGetBValue(colors[0])); + } + + controller->ResetToSavedLighting(); +} diff --git a/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/RGBController_AsusROGStrixEvolve.h b/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/RGBController_AsusROGStrixEvolve.h new file mode 100644 index 00000000..30315278 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMouseGen1Controller/RGBController_AsusROGStrixEvolve.h @@ -0,0 +1,51 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusROGStrixEvolve.h | +| | +| RGBController for ASUS ROG Evolve | +| | +| Mola19 30 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AsusAuraMouseGen1Controller.h" + +enum +{ + ASUS_ROG_STRIX_EVOLVE_BRIGHTNESS_MIN = 0, + ASUS_ROG_STRIX_EVOLVE_BRIGHTNESS_MAX = 255, + ASUS_ROG_STRIX_EVOLVE_BRIGHTNESS_DEFAULT = 255, +}; + +enum +{ + ASUS_ROG_STRIX_EVOLVE_MODE_DIRECT = 0x01, + ASUS_ROG_STRIX_EVOLVE_MODE_BREATHING = 0x02, + ASUS_ROG_STRIX_EVOLVE_MODE_SPECTRUM_CYCLE = 0x03, + ASUS_ROG_STRIX_EVOLVE_MODE_REACTIVE = 0x04, +}; + +class RGBController_AsusROGStrixEvolve : public RGBController +{ +public: + RGBController_AsusROGStrixEvolve(AsusAuraMouseGen1Controller* controller_ptr); + ~RGBController_AsusROGStrixEvolve(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + AsusAuraMouseGen1Controller* controller; +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraMousematController.cpp b/Controllers/AsusAuraUSBController/AsusAuraMousematController.cpp deleted file mode 100644 index c9eb8716..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraMousematController.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraMousematController.cpp | -| | -| Driver for ASUS Aura RGB USB | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 1/10/2022 | -\*-----------------------------------------*/ - -#include "AsusAuraMousematController.h" -#include - -AuraMousematController::AuraMousematController(hid_device* dev_handle, const char* path) -{ - dev = dev_handle; - location = path; -} - -AuraMousematController::~AuraMousematController() -{ - hid_close(dev); -} - -std::string AuraMousematController::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string AuraMousematController::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); -} - -std::string AuraMousematController::GetVersion() -{ - unsigned char usb_buf[65]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - usb_buf[0x00] = 0xEE; - usb_buf[0x01] = 0x12; - usb_buf[0x02] = 0x00; - - hid_write(dev, usb_buf, 65); - - unsigned char usb_buf_out[65]; - hid_read(dev, usb_buf_out, 65); - - char version[9]; - snprintf(version, 9, "%X.%02X.%02X", usb_buf_out[6], usb_buf_out[7], usb_buf_out[8]); - return std::string(version); -} - -void AuraMousematController::UpdateLeds - ( - std::vector colors - ) -{ - unsigned char usb_buf[65]; - - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0xEE; - usb_buf[0x01] = 0xC0; - usb_buf[0x02] = 0x81; - usb_buf[0x03] = 0x00; - usb_buf[0x04] = 0x00; - - for(unsigned int i = 0; i < 60; i += 4) - { - usb_buf[5 + i] = 0x00; - usb_buf[6 + i] = RGBGetRValue(colors[i / 4]); - usb_buf[7 + i] = RGBGetGValue(colors[i / 4]); - usb_buf[8 + i] = RGBGetBValue(colors[i / 4]); - } - - hid_write(dev, usb_buf, 65); -} - -void AuraMousematController::UpdateDevice - ( - unsigned char mode, - std::vector colors, - unsigned char speed, - unsigned char brightness, - unsigned char pattern - ) -{ - unsigned char usb_buf[65]; - - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0xEE; - usb_buf[0x01] = 0x51; - usb_buf[0x02] = 0x28; - usb_buf[0x03] = 0x00; - usb_buf[0x04] = 0x00; - usb_buf[0x05] = mode; - usb_buf[0x06] = speed; - usb_buf[0x07] = brightness; - usb_buf[0x08] = pattern; - usb_buf[0x09] = 0x00; - - for(unsigned int i = 0; i < colors.size(); i++) - { - usb_buf[0x0a + i * 3] = RGBGetRValue(colors[i]); - usb_buf[0x0b + i * 3] = RGBGetGValue(colors[i]); - usb_buf[0x0c + i * 3] = RGBGetBValue(colors[i]); - } - - hid_write(dev, usb_buf, 65); -} - -void AuraMousematController::SaveMode() -{ - unsigned char usb_save_buf[65]; - - memset(usb_save_buf, 0x00, sizeof(usb_save_buf)); - - usb_save_buf[0x00] = 0xEE; - usb_save_buf[0x01] = 0x50; - usb_save_buf[0x02] = 0x03; - - hid_write(dev, usb_save_buf, 65); -} diff --git a/Controllers/AsusAuraUSBController/AsusAuraMousematController.h b/Controllers/AsusAuraUSBController/AsusAuraMousematController.h deleted file mode 100644 index 37b03e1e..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraMousematController.h +++ /dev/null @@ -1,59 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraMousematController.h | -| | -| Definitions and types for ASUS Aura | -| USB RGB lighting controller | -| | -| Adam Honse (CalcProgrammer1) 1/10/2022 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include - -#pragma once - - -enum -{ - AURA_MOUSEMAT_MODE_STATIC = 0, - AURA_MOUSEMAT_MODE_BREATHING = 1, - AURA_MOUSEMAT_MODE_COLOR_CYCLE = 2, - AURA_MOUSEMAT_MODE_WAVE = 3, - AURA_MOUSEMAT_MODE_WAVE_PLANE = 4, - AURA_MOUSEMAT_MODE_COMET = 5, - AURA_MOUSEMAT_MODE_GLOWING_YOYO = 6, - AURA_MOUSEMAT_MODE_CROSS = 7, - AURA_MOUSEMAT_MODE_STARRY_NIGHT = 8, - AURA_MOUSEMAT_MODE_DIRECT = 0xFF, -}; - -class AuraMousematController -{ -public: - AuraMousematController(hid_device* dev_handle, const char* path); - virtual ~AuraMousematController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - std::string GetVersion(); - - void UpdateLeds - ( - std::vector colors - ); - - void UpdateDevice - ( - unsigned char mode, - std::vector colors, - unsigned char speed, - unsigned char brightness, - unsigned char pattern - ); - - void SaveMode(); - -private: - hid_device* dev; - std::string location; -}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraMousematController/AsusAuraMousematController.cpp b/Controllers/AsusAuraUSBController/AsusAuraMousematController/AsusAuraMousematController.cpp new file mode 100644 index 00000000..b1406c4d --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMousematController/AsusAuraMousematController.cpp @@ -0,0 +1,140 @@ +/*---------------------------------------------------------*\ +| AsusAuraMousematController.cpp | +| | +| Driver for ASUS Aura mousemat | +| | +| Adam Honse (CalcProgrammer1) 10 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "AsusAuraMousematController.h" +#include "StringUtils.h" + +AuraMousematController::AuraMousematController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; +} + +AuraMousematController::~AuraMousematController() +{ + hid_close(dev); +} + +std::string AuraMousematController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string AuraMousematController::GetName() +{ + return(name); +} + +std::string AuraMousematController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string AuraMousematController::GetVersion() +{ + unsigned char usb_buf[65]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + usb_buf[0x00] = 0xEE; + usb_buf[0x01] = 0x12; + usb_buf[0x02] = 0x00; + + hid_write(dev, usb_buf, 65); + + unsigned char usb_buf_out[65]; + hid_read(dev, usb_buf_out, 65); + + char version[9]; + snprintf(version, 9, "%X.%02X.%02X", usb_buf_out[6], usb_buf_out[7], usb_buf_out[8]); + return std::string(version); +} + +void AuraMousematController::UpdateLeds + ( + std::vector colors + ) +{ + unsigned char usb_buf[65]; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0xEE; + usb_buf[0x01] = 0xC0; + usb_buf[0x02] = 0x81; + usb_buf[0x03] = 0x00; + usb_buf[0x04] = 0x00; + + for(unsigned int i = 0; i < 60; i += 4) + { + usb_buf[5 + i] = 0x00; + usb_buf[6 + i] = RGBGetRValue(colors[i / 4]); + usb_buf[7 + i] = RGBGetGValue(colors[i / 4]); + usb_buf[8 + i] = RGBGetBValue(colors[i / 4]); + } + + hid_write(dev, usb_buf, 65); +} + +void AuraMousematController::UpdateDevice + ( + unsigned char mode, + std::vector colors, + unsigned char speed, + unsigned char brightness, + unsigned char pattern + ) +{ + unsigned char usb_buf[65]; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0xEE; + usb_buf[0x01] = 0x51; + usb_buf[0x02] = 0x28; + usb_buf[0x03] = 0x00; + usb_buf[0x04] = 0x00; + usb_buf[0x05] = mode; + usb_buf[0x06] = speed; + usb_buf[0x07] = brightness; + usb_buf[0x08] = pattern; + usb_buf[0x09] = 0x00; + + for(unsigned int i = 0; i < colors.size(); i++) + { + usb_buf[0x0a + i * 3] = RGBGetRValue(colors[i]); + usb_buf[0x0b + i * 3] = RGBGetGValue(colors[i]); + usb_buf[0x0c + i * 3] = RGBGetBValue(colors[i]); + } + + hid_write(dev, usb_buf, 65); +} + +void AuraMousematController::SaveMode() +{ + unsigned char usb_save_buf[65]; + + memset(usb_save_buf, 0x00, sizeof(usb_save_buf)); + + usb_save_buf[0x00] = 0xEE; + usb_save_buf[0x01] = 0x50; + usb_save_buf[0x02] = 0x03; + + hid_write(dev, usb_save_buf, 65); +} diff --git a/Controllers/AsusAuraUSBController/AsusAuraMousematController/AsusAuraMousematController.h b/Controllers/AsusAuraUSBController/AsusAuraMousematController/AsusAuraMousematController.h new file mode 100644 index 00000000..5da8851a --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMousematController/AsusAuraMousematController.h @@ -0,0 +1,62 @@ +/*---------------------------------------------------------*\ +| AsusAuraMousematController.h | +| | +| Driver for ASUS Aura mousemat | +| | +| Adam Honse (CalcProgrammer1) 10 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" + +enum +{ + AURA_MOUSEMAT_MODE_STATIC = 0, + AURA_MOUSEMAT_MODE_BREATHING = 1, + AURA_MOUSEMAT_MODE_COLOR_CYCLE = 2, + AURA_MOUSEMAT_MODE_WAVE = 3, + AURA_MOUSEMAT_MODE_WAVE_PLANE = 4, + AURA_MOUSEMAT_MODE_COMET = 5, + AURA_MOUSEMAT_MODE_GLOWING_YOYO = 6, + AURA_MOUSEMAT_MODE_CROSS = 7, + AURA_MOUSEMAT_MODE_STARRY_NIGHT = 8, + AURA_MOUSEMAT_MODE_DIRECT = 0xFF, +}; + +class AuraMousematController +{ +public: + AuraMousematController(hid_device* dev_handle, const char* path, std::string dev_name); + virtual ~AuraMousematController(); + + std::string GetDeviceLocation(); + std::string GetName(); + std::string GetSerialString(); + std::string GetVersion(); + + void UpdateLeds + ( + std::vector colors + ); + + void UpdateDevice + ( + unsigned char mode, + std::vector colors, + unsigned char speed, + unsigned char brightness, + unsigned char pattern + ); + + void SaveMode(); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraMousemat.cpp b/Controllers/AsusAuraUSBController/AsusAuraMousematController/RGBController_AsusAuraMousemat.cpp similarity index 91% rename from Controllers/AsusAuraUSBController/RGBController_AsusAuraMousemat.cpp rename to Controllers/AsusAuraUSBController/AsusAuraMousematController/RGBController_AsusAuraMousemat.cpp index 442803e2..fd459ad6 100644 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraMousemat.cpp +++ b/Controllers/AsusAuraUSBController/AsusAuraMousematController/RGBController_AsusAuraMousemat.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraMousemat.cpp | -| | -| Generic RGB Interface for Asus Aura | -| USB controller driver | -| | -| Adam Honse (CalcProgrammer1) 1/10/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraMousemat.cpp | +| | +| RGBController for ASUS Aura mousemat | +| | +| Adam Honse (CalcProgrammer1) 10 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_AsusAuraMousemat.h" @@ -24,7 +26,7 @@ RGBController_AuraMousemat::RGBController_AuraMousemat(AuraMousematController* c { controller = controller_ptr; - name = "ASUS Aura Mousemat"; + name = controller->GetName(); vendor = "ASUS"; type = DEVICE_TYPE_MOUSEMAT; description = "ASUS Aura Mousemat Device"; @@ -249,11 +251,11 @@ void RGBController_AuraMousemat::DeviceUpdateMode() } else { - pattern = modes[active_mode].colors.size() - 1; + pattern = (int)modes[active_mode].colors.size() - 1; } break; case AURA_MOUSEMAT_MODE_WAVE: - pattern = modes[active_mode].colors.size() * 16 + modes[active_mode].direction; + pattern = (int)modes[active_mode].colors.size() * 16 + modes[active_mode].direction; break; case AURA_MOUSEMAT_MODE_WAVE_PLANE: switch(modes[active_mode].direction) diff --git a/Controllers/AsusAuraUSBController/AsusAuraMousematController/RGBController_AsusAuraMousemat.h b/Controllers/AsusAuraUSBController/AsusAuraMousematController/RGBController_AsusAuraMousemat.h new file mode 100644 index 00000000..825da0a6 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraMousematController/RGBController_AsusAuraMousemat.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraMousemat.h | +| | +| RGBController for ASUS Aura mousemat | +| | +| Mola19 06 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AsusAuraMousematController.h" + +enum +{ + AURA_MOUSEMAT_BRIGHTNESS_MIN = 0, + AURA_MOUSEMAT_BRIGHTNESS_MAX = 4, + AURA_MOUSEMAT_BRIGHTNESS_DEFAULT = 4, + AURA_MOUSEMAT_SPEED_MIN = 127, + AURA_MOUSEMAT_SPEED_MAX = 0, + AURA_MOUSEMAT_SPEED_DEFAULT_STATIC = 0, + AURA_MOUSEMAT_SPEED_DEFAULT_BREATHING = 1, + AURA_MOUSEMAT_SPEED_DEFAULT_COLOR_CYCLE = 1, + AURA_MOUSEMAT_SPEED_DEFAULT_WAVE = 14, + AURA_MOUSEMAT_SPEED_DEFAULT_WAVE_PLANE = 2, + AURA_MOUSEMAT_SPEED_DEFAULT_COMET = 2, + AURA_MOUSEMAT_SPEED_DEFAULT_GLOWING_YOYO = 4, + AURA_MOUSEMAT_SPEED_DEFAULT_CROSS = 12, + AURA_MOUSEMAT_SPEED_DEFAULT_STARRY_NIGHT = 2, +}; + +class RGBController_AuraMousemat : public RGBController +{ +public: + RGBController_AuraMousemat(AuraMousematController* controller_ptr); + ~RGBController_AuraMousemat(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + AuraMousematController* controller; +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController.cpp b/Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController.cpp deleted file mode 100644 index 68542a22..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/*-------------------------------------------------------------------*\ -| AsusAuraRyuoAIOController.cpp | -| | -| Driver for the ASUS Aura Ryuo AIO | -| lighting controller | -| | -| Cooper Hall (geobot19 / Geo_bot) 08 Apr 2022 | -| using snipets from Chris M (Dr.No) | -\*-------------------------------------------------------------------*/ - -#include "AsusAuraRyuoAIOController.h" - -AsusAuraRyuoAIOController::AsusAuraRyuoAIOController(hid_device* dev_handle, const char* path) : AuraUSBController(dev_handle, path) -{ - /*-----------------------------------------------------*\ - | Add addressable devices | - | Manually adding device info for now | - | TODO: Implement config table accurately | - \*-----------------------------------------------------*/ - device_info.push_back({0x00, 0x00, 12, 0, AuraDeviceType::FIXED}); -} - -AsusAuraRyuoAIOController::~AsusAuraRyuoAIOController() -{ - hid_close(dev); -} - -std::string AsusAuraRyuoAIOController::GetLocation() -{ - return("HID: " + location); -} - -void AsusAuraRyuoAIOController::SetMode(unsigned char /*channel*/, unsigned char /*mode*/, unsigned char /*red*/, unsigned char /*grn*/, unsigned char /*blu*/) -{ - /*---------------------------------------------------------*\ - | This interface is not used in this controller however is | - | required by the abstract class | - \*---------------------------------------------------------*/ -} - -void AsusAuraRyuoAIOController::SetMode(unsigned char mode, unsigned char speed, unsigned char direction, RGBColor colour) -{ - //check if update is needed - if(!((current_mode == mode) && (ToRGBColor(current_red, current_green, current_blue) == colour) && (current_speed == speed) && (current_direction == direction))) - { - current_mode = mode; - current_speed = speed; - current_direction = direction; - current_red = RGBGetRValue(colour); - current_green = RGBGetGValue(colour); - current_blue = RGBGetBValue(colour); - SendUpdate(); - } -} - -void AsusAuraRyuoAIOController::SetChannelLEDs(unsigned char /*channel*/, RGBColor* /*colors*/, unsigned int /*num_colors*/) -{ - /*---------------------------------------------------------*\ - | This interface is not used in this controller however is | - | required by the abstract class | - \*---------------------------------------------------------*/ -} - -void AsusAuraRyuoAIOController::SetLedsDirect(RGBColor * led_colours, uint8_t led_count) -{ - uint8_t buffer[write_packet_size] = { 0xEC, 0x40, 0x80, 0x00, led_count }; - - /*---------------------------------------------------------*\ - | Set the colour bytes in the packet | - \*---------------------------------------------------------*/ - for(uint8_t index = 0; index < led_count; index++) - { - uint8_t offset = (index * 3) + RED_BYTE; - - buffer[offset + 0] = RGBGetRValue(led_colours[index]); - buffer[offset + 1] = RGBGetGValue(led_colours[index]); - buffer[offset + 2] = RGBGetBValue(led_colours[index]); - } - - hid_write(dev, buffer, write_packet_size); -} - -void AsusAuraRyuoAIOController::GetStatus() -{ - uint8_t buffer[write_packet_size] = { 0xEC, 0x01, 0x02 }; - - hid_write(dev, buffer, write_packet_size); - hid_read_timeout(dev, buffer, read_packet_size, ASUSAURARYUOAIOCONTROLLER_TIMEOUT); - - current_red = buffer[RED_BYTE - 1]; - current_green = buffer[GREEN_BYTE - 1]; - current_blue = buffer[BLUE_BYTE - 1]; -} - -void AsusAuraRyuoAIOController::SendUpdate() -{ - uint8_t buffer[write_packet_size]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(buffer, 0x00, write_packet_size); - - buffer[REPORTID_BYTE] = reportid; - buffer[COMMAND_BYTE] = modefx; - buffer[ZONE_BYTE] = 0; - buffer[PROGRAM_ID_BYTE] = program_id; - buffer[MODE_BYTE] = current_mode; - buffer[RED_BYTE] = current_red; - buffer[GREEN_BYTE] = current_green; - buffer[BLUE_BYTE] = current_blue; - - buffer[DIRECTION_BYTE]= current_direction; - buffer[SPEED_BYTE] = current_speed; - - hid_write(dev, buffer, write_packet_size); -} - diff --git a/Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController/AsusAuraRyuoAIOController.cpp b/Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController/AsusAuraRyuoAIOController.cpp new file mode 100644 index 00000000..8e870451 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController/AsusAuraRyuoAIOController.cpp @@ -0,0 +1,122 @@ +/*---------------------------------------------------------*\ +| AsusAuraRyuoAIOController.cpp | +| | +| Driver for ASUS Aura Ryuo | +| | +| Cooper Hall (geobot19 / Geo_bot) 08 Apr 2022 | +| using snipets from Chris M (Dr.No) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "AsusAuraRyuoAIOController.h" + +AsusAuraRyuoAIOController::AsusAuraRyuoAIOController(hid_device* dev_handle, const char* path, std::string dev_name) : AuraUSBController(dev_handle, path, dev_name) +{ + /*-----------------------------------------------------*\ + | Add addressable devices | + | Manually adding device info for now | + | TODO: Implement config table accurately | + \*-----------------------------------------------------*/ + device_info.push_back({0x00, 0x00, 12, 0, AuraDeviceType::FIXED}); +} + +AsusAuraRyuoAIOController::~AsusAuraRyuoAIOController() +{ + /*---------------------------------------------------------*\ + | HID device is closed in the base class | + \*---------------------------------------------------------*/ +} + +std::string AsusAuraRyuoAIOController::GetLocation() +{ + return("HID: " + location); +} + +void AsusAuraRyuoAIOController::SetMode(unsigned char /*channel*/, unsigned char /*mode*/, unsigned char /*red*/, unsigned char /*grn*/, unsigned char /*blu*/) +{ + /*---------------------------------------------------------*\ + | This interface is not used in this controller however is | + | required by the abstract class | + \*---------------------------------------------------------*/ +} + +void AsusAuraRyuoAIOController::SetMode(unsigned char mode, unsigned char speed, unsigned char direction, RGBColor colour) +{ + //check if update is needed + if(!((current_mode == mode) && (ToRGBColor(current_red, current_green, current_blue) == colour) && (current_speed == speed) && (current_direction == direction))) + { + current_mode = mode; + current_speed = speed; + current_direction = direction; + current_red = RGBGetRValue(colour); + current_green = RGBGetGValue(colour); + current_blue = RGBGetBValue(colour); + SendUpdate(); + } +} + +void AsusAuraRyuoAIOController::SetChannelLEDs(unsigned char /*channel*/, RGBColor* /*colors*/, unsigned int /*num_colors*/) +{ + /*---------------------------------------------------------*\ + | This interface is not used in this controller however is | + | required by the abstract class | + \*---------------------------------------------------------*/ +} + +void AsusAuraRyuoAIOController::SetLedsDirect(RGBColor * led_colours, uint8_t led_count) +{ + uint8_t buffer[write_packet_size] = { 0xEC, 0x40, 0x80, 0x00, led_count }; + + /*---------------------------------------------------------*\ + | Set the colour bytes in the packet | + \*---------------------------------------------------------*/ + for(uint8_t index = 0; index < led_count; index++) + { + uint8_t offset = (index * 3) + RED_BYTE; + + buffer[offset + 0] = RGBGetRValue(led_colours[index]); + buffer[offset + 1] = RGBGetGValue(led_colours[index]); + buffer[offset + 2] = RGBGetBValue(led_colours[index]); + } + + hid_write(dev, buffer, write_packet_size); +} + +void AsusAuraRyuoAIOController::GetStatus() +{ + uint8_t buffer[write_packet_size] = { 0xEC, 0x01, 0x02 }; + + hid_write(dev, buffer, write_packet_size); + hid_read_timeout(dev, buffer, read_packet_size, ASUSAURARYUOAIOCONTROLLER_TIMEOUT); + + current_red = buffer[RED_BYTE - 1]; + current_green = buffer[GREEN_BYTE - 1]; + current_blue = buffer[BLUE_BYTE - 1]; +} + +void AsusAuraRyuoAIOController::SendUpdate() +{ + uint8_t buffer[write_packet_size]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(buffer, 0x00, write_packet_size); + + buffer[REPORTID_BYTE] = reportid; + buffer[COMMAND_BYTE] = modefx; + buffer[ZONE_BYTE] = 0; + buffer[PROGRAM_ID_BYTE] = program_id; + buffer[MODE_BYTE] = current_mode; + buffer[RED_BYTE] = current_red; + buffer[GREEN_BYTE] = current_green; + buffer[BLUE_BYTE] = current_blue; + + buffer[DIRECTION_BYTE]= current_direction; + buffer[SPEED_BYTE] = current_speed; + + hid_write(dev, buffer, write_packet_size); +} + diff --git a/Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController.h b/Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController/AsusAuraRyuoAIOController.h similarity index 81% rename from Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController.h rename to Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController/AsusAuraRyuoAIOController.h index 40696949..bb07f90a 100644 --- a/Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController.h +++ b/Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController/AsusAuraRyuoAIOController.h @@ -1,20 +1,22 @@ -/*-------------------------------------------------------------------*\ -| AsusAuraRyuoAIOController.h | -| | -| Driver for the ASUS Aura Ryuo AIO | -| lighting controller | -| | -| Cooper Hall (geobot19 / Geo_bot) 08 Apr 2022 | -| using snipets from Chris M (Dr.No) | -\*-------------------------------------------------------------------*/ - -#include -#include -#include "RGBController.h" -#include "AsusAuraUSBController.h" +/*---------------------------------------------------------*\ +| AsusAuraRyuoAIOController.h | +| | +| Driver for ASUS Aura Ryuo | +| | +| Cooper Hall (geobot19 / Geo_bot) 08 Apr 2022 | +| using snipets from Chris M (Dr.No) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" +#include "AsusAuraUSBController.h" + #define ASUSAURARYUOAIOCONTROLLER_TIMEOUT 250 #define ASUSAURARYUOAIOCONTROLLER_HID_MAX_STR 255 @@ -58,7 +60,7 @@ public: SPEED_FASTEST = 0x00, // Fastest speed }; - AsusAuraRyuoAIOController(hid_device* dev_handle, const char* path); + AsusAuraRyuoAIOController(hid_device* dev_handle, const char* path, std::string dev_name); ~AsusAuraRyuoAIOController(); std::string GetLocation(); diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraRyuoAIO.cpp b/Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController/RGBController_AsusAuraRyuoAIO.cpp similarity index 88% rename from Controllers/AsusAuraUSBController/RGBController_AsusAuraRyuoAIO.cpp rename to Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController/RGBController_AsusAuraRyuoAIO.cpp index 23c21304..700b2110 100644 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraRyuoAIO.cpp +++ b/Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController/RGBController_AsusAuraRyuoAIO.cpp @@ -1,23 +1,25 @@ -/*-------------------------------------------------------------------*\ -| RGBController_AsusAuraRyuoAIO.cpp | -| | -| Driver for the ASUS Aura Ryuo AIO | -| lighting controller | -| | -| Cooper Hall (geobot19 / Geo_bot) 08 Apr 2022 | -| using snipets from Chris M (Dr.No) | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraRyuoAIO.cpp | +| | +| RGBController for ASUS Aura Ryuo | +| | +| Cooper Hall (geobot19 / Geo_bot) 08 Apr 2022 | +| using snipets from Chris M (Dr.No) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_AsusAuraRyuoAIO.h" /**------------------------------------------------------------------*\ - @name Asus Aura Ryuo AIO + @name Asus Aura Ryuo AIO @type USB @save :white_check_mark: @direct :white_check_mark: @effects :white_check_mark: - @detectors DetectAsusAuraUSBMousemats + @detectors DetectAsusAuraUSBRyuoAIO @category Cooler @comment \*-------------------------------------------------------------------*/ @@ -27,7 +29,7 @@ RGBController_AsusAuraRyuoAIO::RGBController_AsusAuraRyuoAIO(AsusAuraRyuoAIOCont controller = controller_ptr; uint8_t speed = controller->SPEED_NORMAL; - name = "ROG Ryuo AIO"; + name = controller->GetDeviceName(); vendor = "ASUS"; type = DEVICE_TYPE_COOLER; description = "ASUS Liquid Cooler with 120mm and 240mm radiators."; @@ -178,7 +180,7 @@ void RGBController_AsusAuraRyuoAIO::ResizeZone(int /*zone*/, int /*new_size*/) void RGBController_AsusAuraRyuoAIO::DeviceUpdateLEDs() { - for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++) { UpdateZoneLEDs(zone_idx); } @@ -203,16 +205,16 @@ void RGBController_AsusAuraRyuoAIO::DeviceUpdateMode() int RGBController_AsusAuraRyuoAIO::GetLED_Zone(int led_idx) { - for(size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++) { int zone_start = zones[zone_idx].start_idx; int zone_end = zone_start + zones[zone_idx].leds_count - 1; - if( zone_start <= led_idx && zone_end >= led_idx) + if(zone_start <= led_idx && zone_end >= led_idx) { return(zone_idx); } } - return -1; + return(-1); } diff --git a/Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController/RGBController_AsusAuraRyuoAIO.h b/Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController/RGBController_AsusAuraRyuoAIO.h new file mode 100644 index 00000000..98d6a65e --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController/RGBController_AsusAuraRyuoAIO.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraRyuoAIO.h | +| | +| RGBController for ASUS Aura Ryuo | +| | +| Cooper Hall (geobot19 / Geo_bot) 08 Apr 2022 | +| using snipets from Chris M (Dr.No) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "LogManager.h" +#include "RGBController.h" +#include "AsusAuraRyuoAIOController.h" + +class RGBController_AsusAuraRyuoAIO : public RGBController +{ +public: + RGBController_AsusAuraRyuoAIO(AsusAuraRyuoAIOController* controller_ptr); + ~RGBController_AsusAuraRyuoAIO(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + int GetDeviceMode(); + int GetLED_Zone(int led_idx); + + AsusAuraRyuoAIOController* controller; +}; + diff --git a/Controllers/AsusAuraUSBController/AsusAuraStrixEvolveController.cpp b/Controllers/AsusAuraUSBController/AsusAuraStrixEvolveController.cpp deleted file mode 100644 index fe3474e1..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraStrixEvolveController.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraStrixEvolveController.cpp | -| | -| Driver for ASUS Aura RGB USB | -| lighting controller | -| | -| Mola19 11/30/2021 | -\*-----------------------------------------*/ - -#include "AsusAuraStrixEvolveController.h" - -#include -#include -#include - -AuraStrixEvolveController::AuraStrixEvolveController(hid_device* dev_handle, const char* path, uint16_t pid) -{ - dev = dev_handle; - location = path; - device_pid = pid; -} - -AuraStrixEvolveController::~AuraStrixEvolveController() -{ - hid_close(dev); -} - -std::string AuraStrixEvolveController::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string AuraStrixEvolveController::GetSerialString() -{ - wchar_t serial_string[HID_MAX_STR]; - int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); - - if(ret != 0) - { - return(""); - } - - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); -} - -std::string AuraStrixEvolveController::GetVersion() -{ - unsigned char usb_buf[9] = { 0x0c, 0xc4, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - hid_send_feature_report(dev, usb_buf, 9); - - unsigned char usb_buf_out[9] = { 0x0c }; - hid_get_feature_report(dev, usb_buf_out, 9); - - return std::string("1." + std::to_string(usb_buf_out[3])); -} - -int AuraStrixEvolveController::GetActiveProfile() -{ - int profile; - - do - { - unsigned char usb_buf[9] = { 0x0c, 0xdf, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - hid_send_feature_report(dev, usb_buf, 9); - - unsigned char usb_buf_out[9] = { 0x0c }; - hid_get_feature_report(dev, usb_buf_out, 9); - - profile = usb_buf_out[4] % 16; - } while (profile > 2); - - return profile + 1; -} - -void AuraStrixEvolveController::SendUpdate - ( - unsigned char key, - unsigned char value - ) -{ - unsigned char usb_buf[9]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, 9); - - /*-----------------------------------------------------*\ - | Set up message packet | - \*-----------------------------------------------------*/ - usb_buf[0x00] = 0x0c; - usb_buf[0x01] = 0xc4; - usb_buf[0x02] = 0x0f; - usb_buf[0x03] = 0x00; - usb_buf[0x04] = key; - usb_buf[0x05] = value; - hid_send_feature_report(dev, usb_buf, 9); -} - - -void AuraStrixEvolveController::UpdateProfile - ( - unsigned char key, - unsigned char profile, - unsigned char value - ) -{ - unsigned char usb_buf[9]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, 9); - - /*-----------------------------------------------------*\ - | Set up message packet | - \*-----------------------------------------------------*/ - usb_buf[0x00] = 0x0c; - usb_buf[0x01] = 0xde; - usb_buf[0x02] = key; - usb_buf[0x03] = profile; - usb_buf[0x04] = value; - hid_send_feature_report(dev, usb_buf, 9); - std::this_thread::sleep_for(std::chrono::milliseconds(5)); -} - -void AuraStrixEvolveController::SendSavePacket() -{ - unsigned char usb_buf[9]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, 9); - - /*-----------------------------------------------------*\ - | Set up message packet | - \*-----------------------------------------------------*/ - usb_buf[0x00] = 0x0c; - usb_buf[0x01] = 0xc4; - - hid_send_feature_report(dev, usb_buf, 9); -} diff --git a/Controllers/AsusAuraUSBController/AsusAuraStrixEvolveController.h b/Controllers/AsusAuraUSBController/AsusAuraStrixEvolveController.h deleted file mode 100644 index ec2f71a7..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraStrixEvolveController.h +++ /dev/null @@ -1,50 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraStrixEvolveController.h | -| | -| Definitions and types for ASUS Aura | -| USB RGB lighting controller | -| | -| Mola19 11/30/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include - -#pragma once - -#define HID_MAX_STR 255 - -class AuraStrixEvolveController -{ -public: - AuraStrixEvolveController(hid_device* dev_handle, const char* path, uint16_t pid); - virtual ~AuraStrixEvolveController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - std::string GetVersion(); - int GetActiveProfile(); - - void SendUpdate - ( - unsigned char key, - unsigned char value - ); - - void UpdateProfile - ( - unsigned char key, - unsigned char profile, - unsigned char value - ); - - void SendSavePacket(); - - uint16_t device_pid; - -private: - hid_device* dev; - std::string location; -}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController.cpp b/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController.cpp deleted file mode 100644 index be085b50..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController.cpp +++ /dev/null @@ -1,543 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraTUFKeyboardController.cpp | -| | -| Driver for ASUS Aura RGB USB | -| lighting controller | -| | -| Mola19 03/03/2021 | -\*-----------------------------------------*/ - -#include "AsusAuraTUFKeyboardController.h" - -#include -#include -#include -#include -#include -#include -#include - -AuraTUFKeyboardController::AuraTUFKeyboardController(hid_device* dev_handle, const char* path, uint16_t pid, unsigned short version) -{ - dev = dev_handle; - location = path; - device_pid = pid; - rev_version = version; - - is_per_led_keyboard = (pid != AURA_TUF_K1_GAMING_PID && pid != AURA_TUF_K5_GAMING_PID); -} - -AuraTUFKeyboardController::~AuraTUFKeyboardController() -{ - hid_close(dev); -} - -std::string AuraTUFKeyboardController::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string AuraTUFKeyboardController::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); -} - -std::string AuraTUFKeyboardController::GetVersion() -{ - if(device_pid != AURA_ROG_CLAYMORE_PID) - { - unsigned char usb_buf[65]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0x12; - usb_buf[0x02] = 0x00; - - ClearResponses(); - - hid_write(dev, usb_buf, 65); - - unsigned char usb_buf_out[65]; - hid_read(dev, usb_buf_out, 65); - - char version[9]; - if(device_pid == AURA_TUF_K3_GAMING_PID) - { - snprintf(version, 9, "%02X.%02X.%02X", usb_buf_out[6], usb_buf_out[5], usb_buf_out[4]); - } - else - { - snprintf(version, 9, "%02X.%02X.%02X", usb_buf_out[5], usb_buf_out[6], usb_buf_out[7]); - } - - return std::string(version); - } - else - { - unsigned char usb_buf[65]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0x10; - usb_buf[0x02] = 0x01; - usb_buf[0x03] = 0x00; - usb_buf[0x04] = 0x00; - usb_buf[0x05] = 0x00; // set to 1 to get firmware version of numpad - - ClearResponses(); - hid_write(dev, usb_buf, 65); - AwaitResponse(20); - - unsigned char usb_buf1[65]; - memset(usb_buf1, 0x00, sizeof(usb_buf1)); - usb_buf1[0x00] = 0x00; - usb_buf1[0x01] = 0x12; - usb_buf1[0x02] = 0x22; - - ClearResponses(); - hid_write(dev, usb_buf1, 65); - - unsigned char usb_buf_out[65]; - hid_read(dev, usb_buf_out, 65); - - char version[9]; - snprintf(version, 9, "%02X.%02X.%02X", usb_buf_out[8], usb_buf_out[9], usb_buf_out[10]); - - return std::string(version); - } -} - -int AuraTUFKeyboardController::GetLayout() -{ - if(device_pid != AURA_ROG_CLAYMORE_PID) - { - unsigned char usb_buf[65]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0x12; - usb_buf[0x02] = 0x12; - - ClearResponses(); - hid_write(dev, usb_buf, 65); - - unsigned char usb_buf_out[65]; - hid_read(dev, usb_buf_out, 65); - - return(usb_buf_out[4] * 100 + usb_buf_out[5]); - } - else - { - switch(rev_version >> 0b1100) - { - case 1: - return 117; - case 2: - return 204; - case 3: - return 221; - case 4: - return 117; - default: - return 117; - } - } -} - -/*---------------------------------------------------------*\ -| only needed for Claymore | -\*---------------------------------------------------------*/ -int AuraTUFKeyboardController::GetNumpadLocation() -{ - unsigned char usb_buf[65]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0x40; - usb_buf[0x02] = 0x60; - - ClearResponses(); - hid_write(dev, usb_buf, 65); - - unsigned char usb_buf_out[65]; - hid_read(dev, usb_buf_out, 65); - - return(usb_buf_out[5] * 2 + usb_buf_out[4]); -} - -void AuraTUFKeyboardController::SaveMode() -{ - unsigned char usb_save_buf[65]; - memset(usb_save_buf, 0x00, sizeof(usb_save_buf)); - - usb_save_buf[0x00] = 0x00; - usb_save_buf[0x01] = 0x50; - usb_save_buf[0x02] = 0x55; - - ClearResponses(); - hid_write(dev, usb_save_buf, 65); - AwaitResponse(60); -} - -/*---------------------------------------------------------*\ -| only needed for Claymore | -\*---------------------------------------------------------*/ -void AuraTUFKeyboardController::AllowRemoteControl(unsigned char type) -{ - unsigned char usb_buf[65]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0x41; - usb_buf[0x02] = type; - - ClearResponses(); - hid_write(dev, usb_buf, 65); - AwaitResponse(20); -} - -void AuraTUFKeyboardController::UpdateSingleLed - ( - int led, - unsigned char red, - unsigned char green, - unsigned char blue - ) -{ - /*-----------------------------------------------------*\ - | Set up message packet for single LED | - \*-----------------------------------------------------*/ - unsigned char usb_buf[65]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0] = 0x00; - usb_buf[1] = 0xC0; - usb_buf[2] = 0x81; - usb_buf[3] = 0x01; - usb_buf[4] = 0x00; - - /*-----------------------------------------------------*\ - | Convert LED index | - \*-----------------------------------------------------*/ - usb_buf[5] = led; - usb_buf[6] = red; - usb_buf[7] = green; - usb_buf[8] = blue; - - ClearResponses(); - hid_write(dev, usb_buf, 65); - AwaitResponse(20); -} - -void AuraTUFKeyboardController::UpdateLeds - ( - std::vector colors - ) -{ - int packets = ceil((float) colors.size() / 15); - - for(int i = 0; i < packets; i++) - { - unsigned char usb_buf[65]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - - int remaining = colors.size() - i * 15; - - int leds = (remaining > 0x0F) ? 0x0F : remaining; - - usb_buf[0] = 0x00; - usb_buf[1] = 0xC0; - usb_buf[2] = 0x81; - usb_buf[3] = leds; - usb_buf[4] = 0x00; - - for(int j = 0; j < leds; j++) - { - usb_buf[j * 4 + 5] = (is_per_led_keyboard) ? colors[i * 15 + j].value : 0x00; - usb_buf[j * 4 + 6] = RGBGetRValue(colors[i * 15 + j].color); - usb_buf[j * 4 + 7] = RGBGetGValue(colors[i * 15 + j].color); - usb_buf[j * 4 + 8] = RGBGetBValue(colors[i * 15 + j].color); - } - - ClearResponses(); - hid_write(dev, usb_buf, 65); - AwaitResponse(20); - } -} - -void AuraTUFKeyboardController::UpdateK1Wave - ( - std::vector colors, - unsigned char direction, - unsigned char speed, - unsigned char brightness - ) -{ - unsigned char usb_buf[65]; - - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0x51; - usb_buf[0x02] = 0x2C; - usb_buf[0x03] = 0x03; - usb_buf[0x04] = 0x00; - usb_buf[0x05] = speed; - usb_buf[0x06] = brightness; - usb_buf[0x07] = 0x00; - usb_buf[0x08] = direction; - usb_buf[0x09] = 0x00; - - usb_buf[10] = 5; - usb_buf[11] = RGBGetRValue(colors[4]); - usb_buf[12] = RGBGetGValue(colors[4]); - usb_buf[13] = RGBGetBValue(colors[4]); - - ClearResponses(); - hid_write(dev, usb_buf, 65); - AwaitResponse(20); - - for(unsigned int i = 0; i < 4; i ++) - { - usb_buf[10 + i * 4] = i + 1; - usb_buf[11 + i * 4] = RGBGetRValue(colors[i]); - usb_buf[12 + i * 4] = RGBGetGValue(colors[i]); - usb_buf[13 + i * 4] = RGBGetBValue(colors[i]); - } - - ClearResponses(); - hid_write(dev, usb_buf, 65); - AwaitResponse(20); -} - -void AuraTUFKeyboardController::UpdateDevice - ( - unsigned char mode, - std::vector colors, - unsigned char direction, - unsigned char color_mode, - unsigned char speed, - unsigned char brightness - ) -{ - if(device_pid == AURA_TUF_K1_GAMING_PID && mode == AURA_KEYBOARD_MODE_WAVE) - { - return UpdateK1Wave(colors, direction, speed, brightness); - } - - unsigned char usb_buf[65]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0x51; - usb_buf[0x02] = 0x2C; - - if(device_pid != AURA_ROG_CLAYMORE_PID) - { - usb_buf[0x03] = mode; - usb_buf[0x04] = 0x00; - usb_buf[0x05] = speed; - usb_buf[0x06] = brightness; - usb_buf[0x07] = color_mode; - usb_buf[0x08] = direction; - - if(is_per_led_keyboard) - { - usb_buf[0x09] = 0x02; - - if(mode == AURA_KEYBOARD_MODE_WAVE || mode == AURA_KEYBOARD_MODE_RIPPLE) - { - usb_buf[0x0A] = colors.size(); - - /*-----------------------------------------------------*\ - | Loop over every color given | - \*-----------------------------------------------------*/ - for(unsigned int i = 0; i < colors.size(); i ++) - { - if(colors[i]) - { - usb_buf[11 + i * 4] = 100/(double)colors.size()*(i+1); - usb_buf[12 + i * 4] = RGBGetRValue(colors[i]); - usb_buf[13 + i * 4] = RGBGetGValue(colors[i]); - usb_buf[14 + i * 4] = RGBGetBValue(colors[i]); - } - } - } - else - { - /*-----------------------------------------------------*\ - | Loop over Color1, Color2 and Background if there | - \*-----------------------------------------------------*/ - for(unsigned int i = 0; i != colors.size(); i++) - { - if(colors[i]) - { - usb_buf[10 + i * 3] = RGBGetRValue(colors[i]); - usb_buf[11 + i * 3] = RGBGetGValue(colors[i]); - usb_buf[12 + i * 3] = RGBGetBValue(colors[i]); - } - } - - } - } - else - { - /*-----------------------------------------------------------------*\ - | Only handles K5 Rainbow. | - | K1 is filtered out earlier and is executed in `UpdateK1Wave()` | - \*-----------------------------------------------------------------*/ - if(mode == AURA_KEYBOARD_MODE_WAVE) - { - usb_buf[0x09] = 0x05; - - for(unsigned int i = 0; i < 5; i ++) - { - usb_buf[10 + i * 4] = i + 1; - usb_buf[11 + i * 4] = RGBGetRValue(colors[i]); - usb_buf[12 + i * 4] = RGBGetGValue(colors[i]); - usb_buf[13 + i * 4] = RGBGetBValue(colors[i]); - } - } - else - { - /*-----------------------------------------------------*\ - | Loop over Color1, Color2 and Background if there | - \*-----------------------------------------------------*/ - for(unsigned int i = 0; i != colors.size(); i++) - { - if(colors[i]) - { - usb_buf[ 9 + i * 3] = RGBGetRValue(colors[i]); - usb_buf[10 + i * 3] = RGBGetGValue(colors[i]); - usb_buf[11 + i * 3] = RGBGetBValue(colors[i]); - } - } - } - } - } - else - { - usb_buf[0x03] = 0x00; - usb_buf[0x04] = 0x00; - usb_buf[0x05] = mode; - usb_buf[0x06] = speed; - - bool random = (color_mode == 1); - bool pattern = (color_mode == 2); - - usb_buf[0x07] = random * 128 + pattern * 32 + direction; - usb_buf[0x08] = 0xFF; // "byteExt1" unknown usage - usb_buf[0x09] = 0xFF; // "byteExt2" unknown usage - usb_buf[0x0A] = (mode == 2) ? 0x80 : 0xFF; // "Lightness" (not Brightness) - - if(mode == 7) - { - UpdateQuicksandColors(colors); - } - else - { - if(mode == 4 && color_mode == 0) - { - usb_buf[11] = 0xFF; - usb_buf[12] = 0xFF; - usb_buf[13] = 0xFF; - } - - for(unsigned int i = 0; i < colors.size(); i ++) - { - if(colors[i]) - { - usb_buf[11 + i * 3] = RGBGetRValue(colors[i]); - usb_buf[12 + i * 3] = RGBGetGValue(colors[i]); - usb_buf[13 + i * 3] = RGBGetBValue(colors[i]); - } - } - } - - for(int i = 1; i < 5; i++) - { - usb_buf[5 + i * 12] = 0xFF; - } - } - - ClearResponses(); - hid_write(dev, usb_buf, 65); - AwaitResponse(20); -} - -/*---------------------------------------------------------*\ -| only needed for Claymore | -\*---------------------------------------------------------*/ -void AuraTUFKeyboardController::UpdateQuicksandColors - ( - std::vector colors - ) -{ - unsigned char usb_buf[65]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0x51; - usb_buf[0x02] = 0x91; - - for(unsigned int i = 0; i < 6; i++) - { - if(colors[i]) - { - usb_buf[5 + i * 3] = RGBGetRValue(colors[i]); - usb_buf[6 + i * 3] = RGBGetGValue(colors[i]); - usb_buf[7 + i * 3] = RGBGetBValue(colors[i]); - } - } - - ClearResponses(); - hid_write(dev, usb_buf, 65); - AwaitResponse(20); -} - -/*---------------------------------------------------------*\ -| only needed for Claymore | -\*---------------------------------------------------------*/ -void AuraTUFKeyboardController::UpdateMode(unsigned char mode) -{ - unsigned char usb_buf[65]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0x51; - usb_buf[0x02] = 0x28; - usb_buf[0x03] = 0x00; - usb_buf[0x04] = 0x00; - usb_buf[0x05] = mode; - - ClearResponses(); - hid_write(dev, usb_buf, 65); - AwaitResponse(20); -} - -void AuraTUFKeyboardController::AwaitResponse(int ms) -{ - unsigned char usb_buf_out[65]; - hid_read_timeout(dev, usb_buf_out, 65, ms); -} - -void AuraTUFKeyboardController::ClearResponses() -{ - int result = 1; - unsigned char usb_buf_flush[65]; - while(result > 0) - { - result = hid_read_timeout(dev, usb_buf_flush, 65, 0); - } -} - diff --git a/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController.h b/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController.h deleted file mode 100644 index c6edb1fa..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController.h +++ /dev/null @@ -1,108 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraTUFKeyboardController.h | -| | -| Definitions and types for ASUS Aura | -| USB RGB lighting controller | -| | -| Mola19 03/03/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include "AsusAuraTUFKeyboardLayouts.h" - -#include -#include -#include - -#pragma once - -enum -{ - AURA_KEYBOARD_MODE_STATIC = 0, - AURA_KEYBOARD_MODE_BREATHING = 1, - AURA_KEYBOARD_MODE_COLOR_CYCLE = 2, - AURA_KEYBOARD_MODE_REACTIVE = 3, - AURA_KEYBOARD_MODE_WAVE = 4, - AURA_KEYBOARD_MODE_RIPPLE = 5, - AURA_KEYBOARD_MODE_STARRY_NIGHT = 6, - AURA_KEYBOARD_MODE_QUICKSAND = 7, - AURA_KEYBOARD_MODE_CURRENT = 8, - AURA_KEYBOARD_MODE_RAIN_DROP = 9, - AURA_KEYBOARD_MODE_DIRECT = 15, -}; - -enum -{ - AURA_ROG_FALCHION_WIRED_PID = 0x193C, - AURA_ROG_FALCHION_WIRELESS_PID = 0x193E, - AURA_TUF_K1_GAMING_PID = 0x1945, - AURA_TUF_K3_GAMING_PID = 0x194B, - AURA_TUF_K5_GAMING_PID = 0x1899, - AURA_TUF_K7_GAMING_PID = 0x18AA, - AURA_ROG_CLAYMORE_PID = 0x184D, -}; - -struct led_color -{ - unsigned int value; - RGBColor color; -}; - -class AuraTUFKeyboardController -{ -public: - AuraTUFKeyboardController(hid_device* dev_handle, const char* path, uint16_t pid, unsigned short version); - ~AuraTUFKeyboardController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - std::string GetVersion(); - int GetLayout(); - int GetNumpadLocation(); - void SaveMode(); - void AllowRemoteControl(unsigned char type); - - void UpdateSingleLed - ( - int led, - unsigned char red, - unsigned char green, - unsigned char blue - ); - - void UpdateLeds - ( - std::vector colors - ); - - void UpdateK1Wave - ( - std::vector colors, - unsigned char direction, - unsigned char speed, - unsigned char brightness - ); - - void UpdateDevice - ( - unsigned char mode, - std::vector colors, - unsigned char direction, - unsigned char color_mode, - unsigned char speed, - unsigned char brightness - ); - void UpdateQuicksandColors(std::vector colors); - void UpdateMode(unsigned char mode); - void AwaitResponse(int ms); - void ClearResponses(); - - uint16_t device_pid; - bool is_per_led_keyboard; - -private: - hid_device* dev; - std::string location; - unsigned short rev_version; -}; - diff --git a/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController/AsusAuraTUFKeyboardController.cpp b/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController/AsusAuraTUFKeyboardController.cpp new file mode 100644 index 00000000..e78feb26 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController/AsusAuraTUFKeyboardController.cpp @@ -0,0 +1,730 @@ +/*---------------------------------------------------------*\ +| AsusAuraTUFKeyboardController.cpp | +| | +| Driver for ASUS Aura TUF keyboard | +| | +| Mola19 03 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include "AsusAuraTUFKeyboardController.h" +#include "StringUtils.h" + +#define HID_MAX_STR 128 + +AuraTUFKeyboardController::AuraTUFKeyboardController(hid_device* dev_handle, const char* path, uint16_t pid, unsigned short version, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + device_pid = pid; + rev_version = version; + + is_per_led_keyboard = (pid != AURA_TUF_K1_GAMING_PID && pid != AURA_TUF_K5_GAMING_PID); +} + +AuraTUFKeyboardController::~AuraTUFKeyboardController() +{ + hid_close(dev); +} + +std::string AuraTUFKeyboardController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string AuraTUFKeyboardController::GetName() +{ + return(name); +} + +std::string AuraTUFKeyboardController::GetSerialString() +{ + wchar_t serial_string[HID_MAX_STR]; + memset(serial_string, 0, sizeof(serial_string)); + + int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); + if(ret != 0) + { + return(""); + } + + /*-------------------------------------------------------------------------*\ + | Skip non-ASCII, trailing garbage in serial numbers. Required by the | + | Scope II 96, whose original firmware outputs garbage, which even differs | + | after computer reboots and therefore breaks OpenRGB profile matching. | + \*-------------------------------------------------------------------------*/ + switch(device_pid) + { + case AURA_ROG_STRIX_SCOPE_II_96_WIRELESS_USB_PID: + serial_string[12] = L'\0'; + break; + default: + break; + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string AuraTUFKeyboardController::GetVersion() +{ + if(device_pid != AURA_ROG_CLAYMORE_PID) + { + unsigned char usb_buf[65]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x12; + usb_buf[0x02] = 0x00; + + ClearResponses(); + + hid_write(dev, usb_buf, 65); + + unsigned char usb_buf_out[65]; + hid_read(dev, usb_buf_out, 65); + + char version[9]; + + switch(device_pid) + { + case AURA_ROG_AZOTH_USB_PID: + case AURA_ROG_AZOTH_2_4_PID: + case AURA_TUF_K3_GAMING_PID: + case AURA_ROG_STRIX_FLARE_II_ANIMATE_PID: + case AURA_ROG_STRIX_SCOPE_NX_WIRELESS_DELUXE_USB_PID: + case AURA_ROG_STRIX_SCOPE_II_PID: + case AURA_ROG_STRIX_SCOPE_II_RX_PID: + case AURA_ROG_STRIX_SCOPE_II_96_WIRELESS_USB_PID: + snprintf(version, 9, "%02X.%02X.%02X", usb_buf_out[6], usb_buf_out[5], usb_buf_out[4]); + break; + case AURA_ROG_STRIX_SCOPE_NX_WIRELESS_DELUXE_2_4_PID: + snprintf(version, 9, "%02X.%02X.%02X", usb_buf_out[13], usb_buf_out[12], usb_buf_out[11]); + break; + default: + snprintf(version, 9, "%02X.%02X.%02X", usb_buf_out[5], usb_buf_out[6], usb_buf_out[7]); + } + + return std::string(version); + } + else + { + unsigned char usb_buf[65]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x10; + usb_buf[0x02] = 0x01; + usb_buf[0x03] = 0x00; + usb_buf[0x04] = 0x00; + usb_buf[0x05] = 0x00; // set to 1 to get firmware version of numpad + + ClearResponses(); + hid_write(dev, usb_buf, 65); + AwaitResponse(20); + + unsigned char usb_buf1[65]; + memset(usb_buf1, 0x00, sizeof(usb_buf1)); + usb_buf1[0x00] = 0x00; + usb_buf1[0x01] = 0x12; + usb_buf1[0x02] = 0x22; + + ClearResponses(); + hid_write(dev, usb_buf1, 65); + + unsigned char usb_buf_out[65]; + hid_read(dev, usb_buf_out, 65); + + char version[9]; + snprintf(version, 9, "%02X.%02X.%02X", usb_buf_out[8], usb_buf_out[9], usb_buf_out[10]); + + return std::string(version); + } +} + +int AuraTUFKeyboardController::GetLayout() +{ + if(device_pid != AURA_ROG_CLAYMORE_PID) + { + unsigned char usb_buf[65]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x12; + usb_buf[0x02] = 0x12; + + ClearResponses(); + hid_write(dev, usb_buf, 65); + + unsigned char usb_buf_out[65]; + hid_read(dev, usb_buf_out, 65); + + return(usb_buf_out[4] * 100 + usb_buf_out[5]); + } + else + { + switch(rev_version >> 0b1100) + { + case 1: + return 117; + case 2: + return 204; + case 3: + return 221; + case 4: + return 117; + default: + return 117; + } + } +} + +/*---------------------------------------------------------*\ +| only needed for Claymore | +\*---------------------------------------------------------*/ +int AuraTUFKeyboardController::GetNumpadLocation() +{ + unsigned char usb_buf[65]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x40; + usb_buf[0x02] = 0x60; + + ClearResponses(); + hid_write(dev, usb_buf, 65); + + unsigned char usb_buf_out[65]; + hid_read(dev, usb_buf_out, 65); + + return(usb_buf_out[5] * 2 + usb_buf_out[4]); +} + +void AuraTUFKeyboardController::SaveMode() +{ + unsigned char usb_save_buf[65]; + memset(usb_save_buf, 0x00, sizeof(usb_save_buf)); + + usb_save_buf[0x00] = 0x00; + usb_save_buf[0x01] = 0x50; + usb_save_buf[0x02] = 0x55; + + ClearResponses(); + hid_write(dev, usb_save_buf, 65); + AwaitResponse(60); +} + +/*---------------------------------------------------------*\ +| only needed for Claymore | +\*---------------------------------------------------------*/ +void AuraTUFKeyboardController::AllowRemoteControl(unsigned char type) +{ + unsigned char usb_buf[65]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x41; + usb_buf[0x02] = type; + + ClearResponses(); + hid_write(dev, usb_buf, 65); + AwaitResponse(20); +} + +void AuraTUFKeyboardController::UpdateSingleLed + ( + int led, + unsigned char red, + unsigned char green, + unsigned char blue + ) +{ + /*-----------------------------------------------------*\ + | Set up message packet for single LED | + \*-----------------------------------------------------*/ + unsigned char usb_buf[65]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0] = 0x00; + usb_buf[1] = 0xC0; + usb_buf[2] = 0x81; + usb_buf[3] = 0x01; + usb_buf[4] = 0x00; + + /*-----------------------------------------------------*\ + | Convert LED index | + \*-----------------------------------------------------*/ + usb_buf[5] = led; + usb_buf[6] = red; + usb_buf[7] = green; + usb_buf[8] = blue; + + ClearResponses(); + hid_write(dev, usb_buf, 65); + AwaitResponse(20); +} + +void AuraTUFKeyboardController::UpdateLeds + ( + std::vector colors + ) +{ + int packets = (int)ceil((float)colors.size() / 15.0f); + + for(int i = 0; i < packets; i++) + { + unsigned char usb_buf[65]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + + int remaining = (int)colors.size() - i * 15; + + int leds = (remaining > 0x0F) ? 0x0F : remaining; + + usb_buf[0] = 0x00; + usb_buf[1] = 0xC0; + usb_buf[2] = 0x81; + usb_buf[3] = leds; + usb_buf[4] = 0x00; + + for(int j = 0; j < leds; j++) + { + usb_buf[j * 4 + 5] = (is_per_led_keyboard) ? colors[i * 15 + j].value : 0x00; + usb_buf[j * 4 + 6] = RGBGetRValue(colors[i * 15 + j].color); + usb_buf[j * 4 + 7] = RGBGetGValue(colors[i * 15 + j].color); + usb_buf[j * 4 + 8] = RGBGetBValue(colors[i * 15 + j].color); + } + + ClearResponses(); + hid_write(dev, usb_buf, 65); + AwaitResponse(20); + } +} + +void AuraTUFKeyboardController::UpdateK1Wave + ( + std::vector colors, + unsigned char direction, + unsigned char speed, + unsigned char brightness + ) +{ + unsigned char usb_buf[65]; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x51; + usb_buf[0x02] = 0x2C; + usb_buf[0x03] = 0x03; + usb_buf[0x04] = 0x00; + usb_buf[0x05] = speed; + usb_buf[0x06] = brightness; + usb_buf[0x07] = 0x00; + usb_buf[0x08] = direction; + usb_buf[0x09] = 0x00; + + usb_buf[10] = 5; + usb_buf[11] = RGBGetRValue(colors[4]); + usb_buf[12] = RGBGetGValue(colors[4]); + usb_buf[13] = RGBGetBValue(colors[4]); + + ClearResponses(); + hid_write(dev, usb_buf, 65); + AwaitResponse(20); + + for(unsigned int i = 0; i < 4; i ++) + { + usb_buf[10 + i * 4] = i + 1; + usb_buf[11 + i * 4] = RGBGetRValue(colors[i]); + usb_buf[12 + i * 4] = RGBGetGValue(colors[i]); + usb_buf[13 + i * 4] = RGBGetBValue(colors[i]); + } + + ClearResponses(); + hid_write(dev, usb_buf, 65); + AwaitResponse(20); +} + +void AuraTUFKeyboardController::UpdateScopeIIRainbowRipple + ( + unsigned char mode, + std::vector colors, + unsigned char direction, + unsigned char color_mode, + unsigned char speed, + unsigned char brightness + ) +{ + unsigned char usb_buf[65]; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x51; + usb_buf[0x02] = 0x2C; + usb_buf[0x03] = mode; + usb_buf[0x04] = 0x02; + usb_buf[0x05] = speed; + usb_buf[0x06] = brightness; + usb_buf[0x07] = color_mode; + usb_buf[0x08] = direction; + usb_buf[0x09] = 0x02; + usb_buf[0x0A] = (unsigned char)colors.size(); + + for(unsigned int i = 0; i < 2; i++) + { + if(i >= colors.size()) + { + continue; + } + + usb_buf[11 + i * 4] = (unsigned char)(100.0f / (float)colors.size() * (i + 1)); + usb_buf[12 + i * 4] = RGBGetRValue(colors[i]); + usb_buf[13 + i * 4] = RGBGetGValue(colors[i]); + usb_buf[14 + i * 4] = RGBGetBValue(colors[i]); + } + + ClearResponses(); + hid_write(dev, usb_buf, 65); + AwaitResponse(20); + + memset(usb_buf + 4, 0x00, sizeof(usb_buf) - 4); + + usb_buf[0x04] = 0x01; + + for(unsigned int i = 0; i < 4; i++) + { + if((i + 2) >= colors.size()) + { + continue; + } + usb_buf[5 + i * 4] = (unsigned char)(100.0f / (float)colors.size() * (i + 1 + 2)); + usb_buf[6 + i * 4] = RGBGetRValue(colors[i + 2]); + usb_buf[7 + i * 4] = RGBGetGValue(colors[i + 2]); + usb_buf[8 + i * 4] = RGBGetBValue(colors[i + 2]); + } + + ClearResponses(); + hid_write(dev, usb_buf, 65); + AwaitResponse(20); + + memset(usb_buf + 4, 0x00, sizeof(usb_buf) - 4); + + usb_buf[0x04] = 0x00; + + for(unsigned int i = 0; i < 1; i ++) + { + if((i + 6) >= colors.size()) + { + continue; + } + + usb_buf[5 + i * 4] = (unsigned char)(100.0f / (float)colors.size() * (i + 1 + 6)); + usb_buf[6 + i * 4] = RGBGetRValue(colors[i + 6]); + usb_buf[7 + i * 4] = RGBGetGValue(colors[i + 6]); + usb_buf[8 + i * 4] = RGBGetBValue(colors[i + 6]); + } + + ClearResponses(); + hid_write(dev, usb_buf, 65); + AwaitResponse(20); +} + +void AuraTUFKeyboardController::UpdateScopeIIQuicksand + ( + std::vector colors, + unsigned char direction, + unsigned char color_mode, + unsigned char speed, + unsigned char brightness + ) +{ + unsigned char usb_buf[65]; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x51; + usb_buf[0x02] = 0x2C; + usb_buf[0x03] = 0x07; + usb_buf[0x04] = 0x01; + usb_buf[0x05] = speed; + usb_buf[0x06] = brightness; + usb_buf[0x07] = color_mode; + usb_buf[0x08] = direction; + usb_buf[0x09] = 0x02; + + for(unsigned int i = 0; i < 3; i ++) + { + usb_buf[10 + i * 3] = RGBGetRValue(colors[i]); + usb_buf[11 + i * 3] = RGBGetGValue(colors[i]); + usb_buf[12 + i * 3] = RGBGetBValue(colors[i]); + } + + ClearResponses(); + hid_write(dev, usb_buf, 65); + AwaitResponse(20); + + memset(usb_buf + 4, 0x00, sizeof(usb_buf) - 4); + + usb_buf[0x04] = 0x00; + + for(unsigned int i = 0; i < 3; i ++) + { + usb_buf[5 + i * 3] = RGBGetRValue(colors[i+3]); + usb_buf[6 + i * 3] = RGBGetGValue(colors[i+3]); + usb_buf[7 + i * 3] = RGBGetBValue(colors[i+3]); + } + + ClearResponses(); + hid_write(dev, usb_buf, 65); + AwaitResponse(20); +} + +void AuraTUFKeyboardController::UpdateDevice + ( + unsigned char mode, + std::vector colors, + unsigned char direction, + unsigned char color_mode, + unsigned char speed, + unsigned char brightness + ) +{ + if(device_pid == AURA_TUF_K1_GAMING_PID && mode == AURA_KEYBOARD_MODE_WAVE) + { + return UpdateK1Wave(colors, direction, speed, brightness); + } + + if(device_pid == AURA_ROG_AZOTH_USB_PID + || device_pid == AURA_ROG_AZOTH_2_4_PID + || device_pid == AURA_ROG_STRIX_SCOPE_NX_WIRELESS_DELUXE_USB_PID + || device_pid == AURA_ROG_STRIX_SCOPE_NX_WIRELESS_DELUXE_2_4_PID + || device_pid == AURA_ROG_STRIX_SCOPE_II_PID + || device_pid == AURA_ROG_STRIX_SCOPE_II_RX_PID + || device_pid == AURA_ROG_STRIX_SCOPE_II_96_WIRELESS_USB_PID) + { + if(mode == AURA_KEYBOARD_MODE_WAVE || mode == AURA_KEYBOARD_MODE_RIPPLE) + { + return UpdateScopeIIRainbowRipple(mode, colors, direction, color_mode, speed, brightness); + } + else if (mode == AURA_KEYBOARD_MODE_QUICKSAND) + { + return UpdateScopeIIQuicksand(colors, direction, color_mode, speed, brightness); + } + } + + unsigned char usb_buf[65]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x51; + usb_buf[0x02] = 0x2C; + + if(device_pid != AURA_ROG_CLAYMORE_PID) + { + usb_buf[0x03] = mode; + usb_buf[0x04] = 0x00; + usb_buf[0x05] = speed; + usb_buf[0x06] = brightness; + usb_buf[0x07] = color_mode; + usb_buf[0x08] = direction; + + if(is_per_led_keyboard) + { + usb_buf[0x09] = 0x02; + + if(mode == AURA_KEYBOARD_MODE_WAVE || mode == AURA_KEYBOARD_MODE_RIPPLE) + { + usb_buf[0x0A] = (unsigned char)colors.size(); + + /*-----------------------------------------------------*\ + | Loop over every color given | + \*-----------------------------------------------------*/ + for(unsigned int i = 0; i < colors.size(); i ++) + { + if(colors[i]) + { + usb_buf[11 + i * 4] = (unsigned char)(100.0f / (float)colors.size() * (i + 1)); + usb_buf[12 + i * 4] = RGBGetRValue(colors[i]); + usb_buf[13 + i * 4] = RGBGetGValue(colors[i]); + usb_buf[14 + i * 4] = RGBGetBValue(colors[i]); + } + } + } + else + { + /*-----------------------------------------------------*\ + | Loop over Color1, Color2 and Background if there | + \*-----------------------------------------------------*/ + for(unsigned int i = 0; i != colors.size(); i++) + { + if(colors[i]) + { + usb_buf[10 + i * 3] = RGBGetRValue(colors[i]); + usb_buf[11 + i * 3] = RGBGetGValue(colors[i]); + usb_buf[12 + i * 3] = RGBGetBValue(colors[i]); + } + } + + } + } + else + { + /*-----------------------------------------------------------------*\ + | Only handles K5 Rainbow. | + | K1 is filtered out earlier and is executed in `UpdateK1Wave()` | + \*-----------------------------------------------------------------*/ + if(mode == AURA_KEYBOARD_MODE_WAVE) + { + usb_buf[0x09] = 0x05; + + for(unsigned int i = 0; i < 5; i ++) + { + usb_buf[10 + i * 4] = i + 1; + usb_buf[11 + i * 4] = RGBGetRValue(colors[i]); + usb_buf[12 + i * 4] = RGBGetGValue(colors[i]); + usb_buf[13 + i * 4] = RGBGetBValue(colors[i]); + } + } + else + { + /*-----------------------------------------------------*\ + | Loop over Color1, Color2 and Background if there | + \*-----------------------------------------------------*/ + for(unsigned int i = 0; i != colors.size(); i++) + { + if(colors[i]) + { + usb_buf[ 9 + i * 3] = RGBGetRValue(colors[i]); + usb_buf[10 + i * 3] = RGBGetGValue(colors[i]); + usb_buf[11 + i * 3] = RGBGetBValue(colors[i]); + } + } + } + } + } + else + { + usb_buf[0x03] = 0x00; + usb_buf[0x04] = 0x00; + usb_buf[0x05] = mode; + usb_buf[0x06] = speed; + + bool random = (color_mode == 1); + bool pattern = (color_mode == 2); + + usb_buf[0x07] = random * 128 + pattern * 32 + direction; + usb_buf[0x08] = 0xFF; // "byteExt1" unknown usage + usb_buf[0x09] = 0xFF; // "byteExt2" unknown usage + usb_buf[0x0A] = (mode == 2) ? 0x80 : 0xFF; // "Lightness" (not Brightness) + + if(mode == 7) + { + UpdateQuicksandColors(colors); + } + else + { + if(mode == 4 && color_mode == 0) + { + usb_buf[11] = 0xFF; + usb_buf[12] = 0xFF; + usb_buf[13] = 0xFF; + } + + for(unsigned int i = 0; i < colors.size(); i ++) + { + if(colors[i]) + { + usb_buf[11 + i * 3] = RGBGetRValue(colors[i]); + usb_buf[12 + i * 3] = RGBGetGValue(colors[i]); + usb_buf[13 + i * 3] = RGBGetBValue(colors[i]); + } + } + } + + for(int i = 1; i < 5; i++) + { + usb_buf[5 + i * 12] = 0xFF; + } + } + + ClearResponses(); + hid_write(dev, usb_buf, 65); + AwaitResponse(20); +} + +/*---------------------------------------------------------*\ +| only needed for Claymore | +\*---------------------------------------------------------*/ +void AuraTUFKeyboardController::UpdateQuicksandColors + ( + std::vector colors + ) +{ + unsigned char usb_buf[65]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x51; + usb_buf[0x02] = 0x91; + + for(unsigned int i = 0; i < 6; i++) + { + if(colors[i]) + { + usb_buf[5 + i * 3] = RGBGetRValue(colors[i]); + usb_buf[6 + i * 3] = RGBGetGValue(colors[i]); + usb_buf[7 + i * 3] = RGBGetBValue(colors[i]); + } + } + + ClearResponses(); + hid_write(dev, usb_buf, 65); + AwaitResponse(20); +} + +/*---------------------------------------------------------*\ +| only needed for Claymore | +\*---------------------------------------------------------*/ +void AuraTUFKeyboardController::UpdateMode(unsigned char mode) +{ + unsigned char usb_buf[65]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x51; + usb_buf[0x02] = 0x28; + usb_buf[0x03] = 0x00; + usb_buf[0x04] = 0x00; + usb_buf[0x05] = mode; + + ClearResponses(); + hid_write(dev, usb_buf, 65); + AwaitResponse(20); +} + +void AuraTUFKeyboardController::AwaitResponse(int ms) +{ + unsigned char usb_buf_out[65]; + hid_read_timeout(dev, usb_buf_out, 65, ms); +} + +void AuraTUFKeyboardController::ClearResponses() +{ + int result = 1; + unsigned char usb_buf_flush[65]; + while(result > 0) + { + result = hid_read_timeout(dev, usb_buf_flush, 65, 0); + } +} + diff --git a/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController/AsusAuraTUFKeyboardController.h b/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController/AsusAuraTUFKeyboardController.h new file mode 100644 index 00000000..457568cb --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController/AsusAuraTUFKeyboardController.h @@ -0,0 +1,147 @@ +/*---------------------------------------------------------*\ +| AsusAuraTUFKeyboardController.h | +| | +| Driver for ASUS Aura TUF keyboard | +| | +| Mola19 03 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" +#include "AsusAuraTUFKeyboardLayouts.h" + +enum +{ + AURA_KEYBOARD_MODE_STATIC = 0, + AURA_KEYBOARD_MODE_BREATHING = 1, + AURA_KEYBOARD_MODE_COLOR_CYCLE = 2, + AURA_KEYBOARD_MODE_REACTIVE = 3, + AURA_KEYBOARD_MODE_WAVE = 4, + AURA_KEYBOARD_MODE_RIPPLE = 5, + AURA_KEYBOARD_MODE_STARRY_NIGHT = 6, + AURA_KEYBOARD_MODE_QUICKSAND = 7, + AURA_KEYBOARD_MODE_CURRENT = 8, + AURA_KEYBOARD_MODE_RAIN_DROP = 9, + AURA_KEYBOARD_MODE_DIRECT = 15, +}; + +enum +{ + AURA_ROG_AZOTH_USB_PID = 0x1A83, + AURA_ROG_AZOTH_2_4_PID = 0x1A85, + AURA_ROG_CLAYMORE_PID = 0x184D, + AURA_ROG_FALCHION_WIRED_PID = 0x193C, + AURA_ROG_FALCHION_WIRELESS_PID = 0x193E, + AURA_ROG_STRIX_FLARE_PID = 0x1875, + AURA_ROG_STRIX_FLARE_PNK_LTD_PID = 0x18CF, + AURA_ROG_STRIX_FLARE_COD_BO4_PID = 0x18AF, + AURA_ROG_STRIX_FLARE_II_PID = 0x19FE, + AURA_ROG_STRIX_FLARE_II_ANIMATE_PID = 0x19FC, + AURA_ROG_STRIX_SCOPE_PID = 0x18F8, + AURA_ROG_STRIX_SCOPE_RX_PID = 0x1951, + AURA_ROG_STRIX_SCOPE_RX_EVA_02_PID = 0x1B12, + AURA_ROG_STRIX_SCOPE_NX_WIRELESS_DELUXE_USB_PID = 0x19F6, + AURA_ROG_STRIX_SCOPE_NX_WIRELESS_DELUXE_2_4_PID = 0x19F8, + AURA_ROG_STRIX_SCOPE_II_PID = 0x1AB3, + AURA_ROG_STRIX_SCOPE_II_RX_PID = 0x1AB5, + AURA_ROG_STRIX_SCOPE_II_96_WIRELESS_USB_PID = 0x1AAE, + AURA_TUF_K1_GAMING_PID = 0x1945, + AURA_TUF_K3_GAMING_PID = 0x194B, + AURA_TUF_K5_GAMING_PID = 0x1899, + AURA_TUF_K7_GAMING_PID = 0x18AA, +}; + +struct led_color +{ + unsigned int value; + RGBColor color; +}; + +class AuraTUFKeyboardController +{ +public: + AuraTUFKeyboardController(hid_device* dev_handle, const char* path, uint16_t pid, unsigned short version, std::string dev_name); + ~AuraTUFKeyboardController(); + + std::string GetDeviceLocation(); + std::string GetName(); + std::string GetSerialString(); + std::string GetVersion(); + + int GetLayout(); + int GetNumpadLocation(); + void SaveMode(); + void AllowRemoteControl(unsigned char type); + + void UpdateSingleLed + ( + int led, + unsigned char red, + unsigned char green, + unsigned char blue + ); + + void UpdateLeds + ( + std::vector colors + ); + + void UpdateK1Wave + ( + std::vector colors, + unsigned char direction, + unsigned char speed, + unsigned char brightness + ); + + void UpdateScopeIIRainbowRipple + ( + unsigned char mode, + std::vector colors, + unsigned char direction, + unsigned char color_mode, + unsigned char speed, + unsigned char brightness + ); + + void UpdateScopeIIQuicksand + ( + std::vector colors, + unsigned char direction, + unsigned char color_mode, + unsigned char speed, + unsigned char brightness + ); + + void UpdateDevice + ( + unsigned char mode, + std::vector colors, + unsigned char direction, + unsigned char color_mode, + unsigned char speed, + unsigned char brightness + ); + + void UpdateQuicksandColors(std::vector colors); + void UpdateMode(unsigned char mode); + void AwaitResponse(int ms); + void ClearResponses(); + + uint16_t device_pid; + bool is_per_led_keyboard; + +private: + hid_device* dev; + std::string location; + std::string name; + unsigned short rev_version; +}; + diff --git a/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController/AsusAuraTUFKeyboardLayouts.h b/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController/AsusAuraTUFKeyboardLayouts.h new file mode 100644 index 00000000..15f8bac9 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController/AsusAuraTUFKeyboardLayouts.h @@ -0,0 +1,3589 @@ +/*---------------------------------------------------------*\ +| AsusAuraTUFKeyboardLayouts.h | +| | +| Layouts for ASUS Aura TUF keyboard | +| | +| Mola19 02 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBControllerKeyNames.h" +#include "RGBController.h" + +enum +{ + ASUS_TUF_K7_LAYOUT_CA = 1, + ASUS_TUF_K7_LAYOUT_AR = 2, + ASUS_TUF_K7_LAYOUT_DE = 3, + ASUS_TUF_K7_LAYOUT_UK = 4, + ASUS_TUF_K7_LAYOUT_FR = 5, + ASUS_TUF_K7_LAYOUT_CN = 6, + ASUS_TUF_K7_LAYOUT_HU = 7, + ASUS_TUF_K7_LAYOUT_IT = 8, + ASUS_TUF_K7_LAYOUT_TH = 9, + ASUS_TUF_K7_LAYOUT_UA = 10, + ASUS_TUF_K7_LAYOUT_NO = 11, + ASUS_TUF_K7_LAYOUT_PT = 12, + ASUS_TUF_K7_LAYOUT_HE = 13, + ASUS_TUF_K7_LAYOUT_RU = 14, + ASUS_TUF_K7_LAYOUT_ES = 15, + ASUS_TUF_K7_LAYOUT_TW = 16, + ASUS_TUF_K7_LAYOUT_US = 17, + ASUS_TUF_K7_LAYOUT_TR = 18, + ASUS_TUF_K7_LAYOUT_CZ = 19, + ASUS_TUF_K7_LAYOUT_BE = 20, + ASUS_TUF_K7_LAYOUT_JP = 21, + ASUS_TUF_K7_LAYOUT_KR = 22, + ASUS_TUF_K7_LAYOUT_IS = 23, + ASUS_TUF_K7_LAYOUT_WB = 24, + ASUS_TUF_K7_LAYOUT_SW_CH = 25 +}; + +#define NA 0xFFFFFFFF + +struct led_value +{ + const char* name; + unsigned char id; +}; + +struct layout_info +{ + unsigned int* matrix_map; + int size; + int rows; + int cols; + std::vector led_names; +}; + +static unsigned int ASUS_TUF_K7_LAYOUT_KEYS_ANSI[6][24] = +{ + { 0, NA, 8, 14, 19, 24, NA, 34, 39, 44, 49, 55, 61, 66, 70, NA, 74, 78, 83, NA, NA, NA, NA, NA }, + { 1, 6, 9, 15, 20, 25, 29, 35, 40, 45, 50, 56, 62, 67, NA, NA, 75, 79, 84, NA, 87, 92, 96, 101 }, + { 2, NA, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, 71, NA, 76, 80, 85, NA, 88, 93, 97, 102 }, + { 3, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, NA, 72, NA, NA, NA, NA, NA, 89, 94, 98, NA }, + { 4, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, NA, 69, NA, NA, NA, 81, NA, NA, 90, 95, 99, 103 }, + { 5, 7, 13, NA, NA, NA, 33, NA, NA, NA, 54, 60, 65, NA, 73, NA, 77, 82, 86, NA, 91, NA, 100, NA } +}; + +static unsigned int ASUS_TUF_K7_LAYOUT_KEYS_ISO[6][24] = +{ + { 0, NA, 9, 15, 20, 25, NA, 35, 40, 45, 50, 56, 62, 67, 72, NA, 75, 79, 84, NA, NA, NA, NA, NA }, + { 1, 6, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, NA, NA, 76, 80, 85, NA, 88, 93, 97, 102 }, + { 2, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, 69, NA, NA, 77, 81, 86, NA, 89, 94, 98, 103 }, + { 3, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, 65, 70, 73, NA, NA, NA, NA, NA, 90, 95, 99, NA }, + { 4, 7, 13, 19, 24, 29, 33, 39, 44, 49, 54, 60, NA, 71, NA, NA, NA, 82, NA, NA, 91, 96, 100, 104 }, + { 5, 8, 14, NA, NA, NA, 34, NA, NA, NA, 55, 61, 66, NA, 74, NA, 78, 83, 87, NA, 92, NA, 101, NA } +}; + +static unsigned int ASUS_ROG_AZOTH_LAYOUT_KEYS_US[6][16] = { + { 0, 6, 9, 15, 20, 25, 30, 36, 41, 46, 51, 57, 63, NA, NA, NA }, + { 1, 7, 10, 16, 21, 26, 31, 37, 42, 47, 52, 58, 64, 69, NA, 76 }, + { 2, NA, 11, 17, 22, 27, 32, 38, 43, 48, 53, 59, 65, 70, 72, 77 }, + { 3, NA, 12, 18, 23, 28, 33, 39, 44, 49, 54, 60, 66, NA, 73, 78 }, + { 4, NA, 13, 19, 24, 29, 34, 40, 45, 50, 55, 61, 67, NA, 74, 79 }, + { 5, 8, 14, NA, NA, NA, 35, NA, NA, NA, 56, 62, 68, 71, 75, 80 } +}; + +static unsigned int ASUS_ROG_AZOTH_LAYOUT_KEYS_UK[6][16] = { + { 0, 6, 10, 16, 21, 26, 31, 37, 42, 47, 52, 58, 64, NA, NA, NA }, + { 1, 7, 11, 17, 22, 27, 32, 38, 43, 48, 53, 59, 65, 70, NA, 77 }, + { 2, NA, 12, 18, 23, 28, 33, 39, 44, 49, 54, 60, 66, 71, NA, 78 }, + { 3, NA, 13, 19, 24, 29, 34, 40, 45, 50, 55, 61, 67, 72, 74, 79 }, + { 4, 8, 14, 20, 25, 30, 35, 41, 46, 51, 56, 62, 68, NA, 75, 80 }, + { 5, 9, 15, NA, NA, NA, 36, NA, NA, NA, 57, 63, 69, 73, 76, 81 } +}; + +static unsigned int ASUS_ROG_STRIX_SCOPE_LAYOUT_KEYS_ANSI[6][24] = +{ + { 0, NA, 8, 14, 19, 24, NA, 34, 39, 44, 49, 55, 61, 66, 70, NA, 74, 78, 83, NA, NA, NA, 104, 105 }, + { 1, 6, 9, 15, 20, 25, 29, 35, 40, 45, 50, 56, 62, 67, NA, NA, 75, 79, 84, NA, 87, 92, 96, 101 }, + { 2, NA, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, 71, NA, 76, 80, 85, NA, 88, 93, 97, 102 }, + { 3, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, NA, 72, NA, NA, NA, NA, NA, 89, 94, 98, NA }, + { 4, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, NA, 69, NA, NA, NA, 81, NA, NA, 90, 95, 99, 103 }, + { 5, 7, 13, NA, NA, NA, 33, NA, NA, NA, 54, 60, 65, NA, 73, NA, 77, 82, 86, NA, 91, NA, 100, NA } +}; + + +static unsigned int ASUS_ROG_STRIX_SCOPE_LAYOUT_KEYS_ISO[6][24] = +{ + { 0, NA, 9, 15, 20, 25, NA, 35, 40, 45, 50, 56, 62, 67, 72, NA, 75, 79, 84, NA, NA, NA, 105, 106 }, + { 1, 6, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, NA, NA, 76, 80, 85, NA, 88, 93, 97, 102 }, + { 2, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, 69, NA, NA, 77, 81, 86, NA, 89, 94, 98, 103 }, + { 3, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, 65, 70, 73, NA, NA, NA, NA, NA, 90, 95, 99, NA }, + { 4, 7, 13, 19, 24, 29, 33, 39, 44, 49, 54, 60, NA, 71, NA, NA, NA, 82, NA, NA, 91, 96, 100, 104 }, + { 5, 8, 14, NA, NA, NA, 34, NA, NA, NA, 55, 61, 66, NA, 74, NA, 78, 83, 87, NA, 92, NA, 101, NA } +}; + +static unsigned int ASUS_ROG_STRIX_SCOPE_II_LAYOUT_KEYS_ANSI[6][24] = +{ + { 0, NA, 8, 14, 19, 24, NA, 35, 41, 46, 51, 57, 63, 68, 72, NA, 76, 80, 85, NA, NA, 94, NA, NA }, + { 1, 6, 9, 15, 20, 25, 30, 36, 42, 47, 52, 58, 64, 69, NA, NA, 77, 81, 86, NA, 89, 95, 99, 104 }, + { 2, NA, 10, 16, 21, 26, 31, 37, 43, 48, 53, 59, 65, 70, 73, NA, 78, 82, 87, NA, 90, 96, 100, 105 }, + { 3, NA, 11, 17, 22, 27, 32, 38, 44, 49, 54, 60, 66, NA, 74, NA, NA, NA, NA, NA, 91, 97, 101, NA }, + { 4, NA, 12, 18, 23, 28, 33, 39, 45, 50, 55, 61, NA, 71, NA, NA, NA, 83, NA, NA, 92, 98, 102, 106 }, + { 5, 7, 13, NA, NA, 29, 34, 40, NA, NA, 56, 62, 67, NA, 75, NA, 79, 84, 88, NA, 93, NA, 103, NA } +}; + + +static unsigned int ASUS_ROG_STRIX_SCOPE_II_LAYOUT_KEYS_ISO[6][24] = +{ + { 0, NA, 9, 15, 20, 25, NA, 36, 42, 47, 52, 58, 64, 69, 74, NA, 77, 81, 86, NA, NA, 95, NA, NA }, + { 1, 6, 10, 16, 21, 26, 31, 37, 43, 48, 53, 59, 65, 70, NA, NA, 78, 82, 87, NA, 90, 96, 100, 105 }, + { 2, NA, 11, 17, 22, 27, 32, 38, 44, 49, 54, 60, 66, 71, NA, NA, 79, 83, 88, NA, 91, 97, 101, 106 }, + { 3, NA, 12, 18, 23, 28, 33, 39, 45, 50, 55, 61, 67, 72, 75, NA, NA, NA, NA, NA, 92, 98, 102, NA }, + { 4, 7, 13, 19, 24, 29, 34, 40, 46, 51, 56, 62, NA, 73, NA, NA, NA, 84, NA, NA, 93, 99, 103, 107 }, + { 5, 8, 14, NA, NA, 30, 35, 41, NA, NA, 57, 63, 68, NA, 76, NA, 80, 85, 89, NA, 94, NA, 104, NA } +}; + +static unsigned int ASUS_ROG_STRIX_SCOPE_II_96_WIRELESS_LAYOUT_KEYS_ANSI[6][19] = +{ + { 0, 6, 11, 17, 22, 27, 33, 39, 45, 50, 55, 61, 67, 72, 77, 80, 86, NA, 97 }, + { 1, 7, 12, 18, 23, 28, 34, 40, 46, 51, 56, 62, 68, 73, NA, 81, 87, 92, 98 }, + { 2, 8, 13, 19, 24, 29, 35, 41, 47, 52, 57, 63, 69, 74, NA, 82, 88, 93, 99 }, + { 3, 9, 14, 20, 25, 30, 36, 42, 48, 53, 58, 64, NA, 75, NA, 83, 89, 94, NA }, + { 4, NA, 15, 21, 26, 31, 37, 43, 49, 54, 59, 65, 70, NA, 78, 84, 90, 95, 100 }, + { 5, 10, 16, NA, NA, 32, 38, 44, NA, NA, 60, 66, 71, 76, 79, 85, 91, 96, NA } +}; + +static unsigned int ASUS_ROG_STRIX_SCOPE_II_96_WIRELESS_LAYOUT_KEYS_ISO[6][19] = +{ + { 0, 6, 12, 18, 23, 28, 34, 40, 46, 51, 56, 62, 68, 74, 78, 81, 87, NA, 98 }, + { 1, 7, 13, 19, 24, 29, 35, 41, 47, 52, 57, 63, 69, 75, NA, 82, 88, 93, 99 }, + { 2, 8, 14, 20, 25, 30, 36, 42, 48, 53, 58, 64, 70, NA, NA, 83, 89, 94, 100 }, + { 3, 9, 15, 21, 26, 31, 37, 43, 49, 54, 59, 65, 71, 76, NA, 84, 90, 95, NA }, + { 4, 10, 16, 22, 27, 32, 38, 44, 50, 55, 60, 66, 72, NA, 79, 85, 91, 96, 101 }, + { 5, 11, 17, NA, NA, 33, 39, 45, NA, NA, 61, 67, 73, 77, 80, 86, 92, 97, NA } +}; + +static unsigned int ASUS_ROG_STRIX_FLARE_LAYOUT_KEYS_ANSI[6][26] = +{ + { NA, 0, NA, 8, 14, 19, 24, NA, 34, 39, 44, 49, 55, 61, 66, 70, NA, 74, 78, 83, NA, 104, NA, NA, NA, NA }, + { NA, 1, 6, 9, 15, 20, 25, 29, 35, 40, 45, 50, 56, 62, 67, NA, NA, 75, 79, 84, NA, 87, 92, 96, 101, NA }, + { NA, 2, NA, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, 71, NA, 76, 80, 85, NA, 88, 93, 97, 102, NA }, + { 105, 3, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, NA, 72, NA, NA, NA, NA, NA, 89, 94, 98, NA, 106 }, + { NA, 4, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, NA, 69, NA, NA, NA, 81, NA, NA, 90, 95, 99, 103, NA }, + { NA, 5, 7, 13, NA, NA, NA, 33, NA, NA, NA, 54, 60, 65, NA, 73, NA, 77, 82, 86, NA, 91, NA, 100, NA, NA } +}; + +static unsigned int ASUS_ROG_STRIX_FLARE_LAYOUT_KEYS_ISO[6][26] = +{ + { NA, 0, NA, 9, 15, 20, 25, NA, 35, 40, 45, 50, 56, 62, 67, 72, NA, 75, 79, 84, NA, 105, NA, NA, NA, NA }, + { NA, 1, 6, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, NA, NA, 76, 80, 85, NA, 88, 93, 97, 102, NA }, + { NA, 2, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, 69, NA, NA, 77, 81, 86, NA, 89, 94, 98, 103, NA }, + { 106, 3, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, 65, 70, 73, NA, NA, NA, NA, NA, 90, 95, 99, NA, 107 }, + { NA, 4, 7, 13, 19, 24, 29, 33, 39, 44, 49, 54, 60, NA, 71, NA, NA, NA, 82, NA, NA, 91, 96, 100, 104, NA }, + { NA, 5, 8, 14, NA, NA, NA, 34, NA, NA, NA, 55, 61, 66, NA, 74, NA, 78, 83, 87, NA, 92, NA, 101, NA, NA } +}; + +static unsigned int ASUS_ROG_STRIX_FLARE_II_LAYOUT_KEYS_ANSI[7][30] = +{ + { NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 104, 105, NA, NA }, + { 0, NA, 8, 14, 19, 24, NA, 34, 39, 44, 49, 55, 61, 66, 70, NA, NA, NA, NA, 74, 78, 83, NA, NA, NA, NA, NA, NA, NA, NA }, + { 1, 6, 9, 15, 20, 25, 29, 35, 40, 45, 50, 56, 62, 67, NA, NA, NA, NA, NA, 75, 79, 84, NA, NA, NA, NA, 87, 92, 96, 101 }, + { 2, NA, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, 71, NA, NA, NA, NA, 76, 80, 85, NA, NA, NA, NA, 88, 93, 97, 102 }, + { 3, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, NA, 72, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 89, 94, 98, NA }, + { 4, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, NA, 69, NA, NA, NA, NA, NA, NA, 81, NA, NA, NA, NA, NA, 90, 95, 99, 103 }, + { 5, 7, 13, NA, NA, NA, 33, NA, NA, NA, 54, 60, 65, NA, 73, NA, NA, NA, NA, 77, 82, 86, NA, NA, NA, NA, 91, NA, 100, NA }, +}; + +static unsigned int ASUS_ROG_STRIX_FLARE_II_LAYOUT_KEYS_ISO[7][30] = +{ + { NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 105, 106, NA, NA }, + { 0, NA, 9, 15, 20, 25, NA, 35, 40, 45, 50, 56, 62, 67, 72, NA, NA, NA, NA, 75, 79, 84, NA, NA, NA, NA, NA, NA, NA, NA }, + { 1, 6, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, NA, NA, NA, NA, NA, 76, 80, 85, NA, NA, NA, NA, 88, 93, 97, 102 }, + { 2, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, 69, NA, NA, NA, NA, NA, 77, 81, 86, NA, NA, NA, NA, 89, 94, 98, 103 }, + { 3, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, 65, 70, 73, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 90, 95, 99, NA }, + { 4, 7, 13, 19, 24, 29, 33, 39, 44, 49, 54, 60, NA, 71, NA, NA, NA, NA, NA, NA, 82, NA, NA, NA, NA, NA, 91, 96, 100, 104 }, + { 5, 8, 14, NA, NA, NA, 34, NA, NA, NA, 55, 61, 66, NA, 74, NA, NA, NA, NA, 78, 83, 87, NA, NA, NA, NA, 92, NA, 101, NA }, +}; + +static unsigned int ASUS_ROG_STRIX_FLARE_II_ANIMATE_LAYOUT_KEYS_ANSI[7][30] = +{ + { 0, NA, 8, 14, 19, 24, NA, 34, 39, 44, 49, 55, 61, 66, 70, NA, NA, NA, NA, 74, 78, 83, NA, NA, NA, NA, NA, NA, NA, NA }, + { 1, 6, 9, 15, 20, 25, 29, 35, 40, 45, 50, 56, 62, 67, NA, NA, NA, NA, NA, 75, 79, 84, NA, NA, NA, NA, 87, 92, 96, 101 }, + { 2, NA, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, 71, NA, NA, NA, NA, 76, 80, 85, NA, NA, NA, NA, 88, 93, 97, 102 }, + { 3, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, NA, 72, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 89, 94, 98, NA }, + { 4, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, NA, 69, NA, NA, NA, NA, NA, NA, 81, NA, NA, NA, NA, NA, 90, 95, 99, 103 }, + { 5, 7, 13, NA, NA, NA, 33, NA, NA, NA, 54, 60, 65, NA, 73, NA, NA, NA, NA, 77, 82, 86, NA, NA, NA, NA, 91, NA, 100, NA }, + { 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 } +}; + +static unsigned int ASUS_ROG_STRIX_FLARE_II_ANIMATE_LAYOUT_KEYS_ISO[7][30] = +{ + { 0, NA, 9, 15, 20, 25, NA, 35, 40, 45, 50, 56, 62, 67, 72, NA, NA, NA, NA, 75, 79, 84, NA, NA, NA, NA, NA, NA, NA, NA }, + { 1, 6, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, NA, NA, NA, NA, NA, 76, 80, 85, NA, NA, NA, NA, 88, 93, 97, 102 }, + { 2, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, 69, NA, NA, NA, NA, NA, 77, 81, 86, NA, NA, NA, NA, 89, 94, 98, 103 }, + { 3, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, 65, 70, 73, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 90, 95, 99, NA }, + { 4, 7, 13, 19, 24, 29, 33, 39, 44, 49, 54, 60, NA, 71, NA, NA, NA, NA, NA, NA, 82, NA, NA, NA, NA, NA, 91, 96, 100, 104 }, + { 5, 8, 14, NA, NA, NA, 34, NA, NA, NA, 55, 61, 66, NA, 74, NA, NA, NA, NA, 78, 83, 87, NA, NA, NA, NA, 92, NA, 101, NA }, + { 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 } +}; + +static unsigned int ASUS_FALCHION_LAYOUT_KEYS_ANSI[5][16] = +{ + { 0, 5, 7, 12, 16, 20, 24, 29, 33, 37, 41, 46, 51, 56, NA, 63 }, + { 1, NA, 8, 13, 17, 21, 25, 30, 34, 38, 42, 47, 52, 57, 59, 64 }, + { 2, NA, 9, 14, 18, 22, 26, 31, 35, 39, 43, 48, 53, NA, 60, 65 }, + { 3, NA, 10, 15, 19, 23, 27, 32, 36, 40, 44, 49, 54, NA, 61, 66 }, + { 4, 6, 11, NA, NA, NA, 28, NA, NA, NA, 45, 50, 55, 58, 62, 67 } +}; + +static unsigned int ASUS_FALCHION_LAYOUT_KEYS_ISO[5][16] = +{ + { 0, 5, 8, 13, 17, 21, 25, 30, 34, 38, 42, 47, 52, 57, NA, 64 }, + { 1, NA, 9, 14, 18, 22, 26, 31, 35, 39, 43, 48, 53, 58, NA, 65 }, + { 2, NA, 10, 15, 19, 23, 27, 32, 36, 40, 44, 49, 54, 59, 61, 66 }, + { 3, 6, 11, 16, 20, 24, 28, 33, 37, 41, 45, 50, 55, NA, 62, 67 }, + { 4, 7, 12, NA, NA, NA, 29, NA, NA, NA, 46, 51, 56, 60, 63, 68 } +}; + +static unsigned int ASUS_CLAYMORE_NO_NUMPAD_LAYOUT_KEYS_ANSI[7][19] = +{ + { 0, NA, 8, 14, 19, 24, NA, 34, 39, 45, 50, 56, 62, 67, 71, NA, 75, 79, 84 }, + { 1, 6, 9, 15, 20, 25, 29, 35, 40, 46, 51, 57, 63, 68, NA, NA, 76, 80, 85 }, + { 2, NA, 10, 16, 21, 26, 30, 36, 41, 47, 52, 58, 64, 69, 72, NA, 77, 81, 86 }, + { 3, NA, 11, 17, 22, 27, 31, 37, 42, 48, 53, 59, 65, NA, 73, NA, NA, NA, NA }, + { 4, NA, 12, 18, 23, 28, 32, 38, 43, 49, 54, 60, NA, 70, NA, NA, NA, 82, NA }, + { 5, 7, 13, NA, NA, NA, 33, NA, NA, NA, 55, 61, 66, NA, 74, NA, 78, 83, 87 }, + { NA, NA, NA, NA, NA, NA, NA, NA, 44, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA } +}; + +static unsigned int ASUS_CLAYMORE_NO_NUMPAD_LAYOUT_KEYS_ISO[7][19] = +{ + { 0, NA, 9, 15, 20, 25, NA, 35, 40, 46, 51, 57, 63, 68, 73, NA, 76, 80, 85 }, + { 1, 6, 10, 16, 21, 26, 30, 36, 41, 47, 52, 58, 64, 69, NA, NA, 77, 81, 86 }, + { 2, NA, 11, 17, 22, 27, 31, 37, 42, 48, 53, 59, 65, 70, NA, NA, 78, 82, 87 }, + { 3, NA, 12, 18, 23, 28, 32, 38, 43, 49, 54, 60, 66, 71, 74, NA, NA, NA, NA }, + { 4, 7, 13, 19, 24, 29, 33, 39, 44, 50, 55, 61, NA, 72, NA, NA, NA, 83, NA }, + { 5, 8, 14, NA, NA, NA, 34, NA, NA, NA, 56, 62, 67, NA, 75, NA, 79, 84, 88 }, + { NA, NA, NA, NA, NA, NA, NA, NA, 45, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA } +}; + +static unsigned int ASUS_CLAYMORE_NUMPAD_RIGHT_LAYOUT_KEYS_ANSI[7][24] = +{ + { 0, NA, 8, 14, 19, 24, NA, 34, 39, 45, 50, 56, 62, 67, 71, NA, 75, 79, 84, NA, NA, NA, NA, NA }, + { 1, 6, 9, 15, 20, 25, 29, 35, 40, 46, 51, 57, 63, 68, NA, NA, 76, 80, 85, NA, 88, 93, 97, 102 }, + { 2, NA, 10, 16, 21, 26, 30, 36, 41, 47, 52, 58, 64, 69, 72, NA, 77, 81, 86, NA, 89, 94, 98, 103 }, + { 3, NA, 11, 17, 22, 27, 31, 37, 42, 48, 53, 59, 65, NA, 73, NA, NA, NA, NA, NA, 90, 95, 99, NA }, + { 4, NA, 12, 18, 23, 28, 32, 38, 43, 49, 54, 60, NA, 70, NA, NA, NA, 82, NA, NA, 91, 96, 100, 104 }, + { 5, 7, 13, NA, NA, NA, 33, NA, NA, NA, 55, 61, 66, NA, 74, NA, 78, 83, 87, NA, 92, NA, 101, NA }, + { NA, NA, NA, NA, NA, NA, NA, NA, 44, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA } +}; + +static unsigned int ASUS_CLAYMORE_NUMPAD_RIGHT_LAYOUT_KEYS_ISO[7][24] = +{ + { 0, NA, 9, 15, 20, 25, NA, 35, 40, 46, 51, 57, 63, 68, 73, NA, 76, 80, 85, NA, NA, NA, NA, NA }, + { 1, 6, 10, 16, 21, 26, 30, 36, 41, 47, 52, 58, 64, 69, NA, NA, 77, 81, 86, NA, 89, 94, 98, 103 }, + { 2, NA, 11, 17, 22, 27, 31, 37, 42, 48, 53, 59, 65, 70, NA, NA, 78, 82, 87, NA, 90, 95, 99, 104 }, + { 3, NA, 12, 18, 23, 28, 32, 38, 43, 49, 54, 60, 66, 71, 74, NA, NA, NA, NA, NA, 91, 96, 100, NA }, + { 4, 7, 13, 19, 24, 29, 33, 39, 44, 50, 55, 61, NA, 72, NA, NA, NA, 83, NA, NA, 92, 97, 101, 105 }, + { 5, 8, 14, NA, NA, NA, 34, NA, NA, NA, 56, 62, 67, NA, 75, NA, 79, 84, 88, NA, 93, NA, 102, NA }, + { NA, NA, NA, NA, NA, NA, NA, NA, 45, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA } +}; + +static unsigned int ASUS_CLAYMORE_NUMPAD_LEFT_LAYOUT_KEYS_ANSI[7][24] = +{ + { NA, NA, NA, NA, NA, 17, NA, 25, 31, 36, 41, NA, 51, 56, 62, 67, 73, 79, 84, 88, NA, 92, 96, 101 }, + { 0, 5, 9, 14, NA, 18, 23, 26, 32, 37, 42, 46, 52, 57, 63, 68, 74, 80, 85, NA, NA, 93, 97, 102 }, + { 1, 6, 10, 15, NA, 19, NA, 27, 33, 38, 43, 47, 53, 58, 64, 69, 75, 81, 86, 89, NA, 94, 98, 103 }, + { 2, 7, 11, NA, NA, 20, NA, 28, 34, 39, 44, 48, 54, 59, 65, 70, 76, 82, NA, 90, NA, NA, NA, NA }, + { 3, 8, 12, 16, NA, 21, NA, 29, 35, 40, 45, 49, 55, 60, 66, 71, 77, NA, 87, NA, NA, NA, 99, NA }, + { 4, NA, 13, NA, NA, 22, 24, 30, NA, NA, NA, 50, NA, NA, NA, 72, 78, 83, NA, 91, NA, 95, 100, 104 }, + { NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 61, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA } +}; + +static unsigned int ASUS_CLAYMORE_NUMPAD_LEFT_LAYOUT_KEYS_ISO[7][24] = +{ + { NA, NA, NA, NA, NA, 17, NA, 26, 32, 37, 42, NA, 52, 57, 63, 68, 74, 80, 85, 90, NA, 93, 97, 102 }, + { 0, 5, 9, 14, NA, 18, 23, 27, 33, 38, 43, 47, 53, 58, 64, 69, 75, 81, 86, NA, NA, 94, 98, 103 }, + { 1, 6, 10, 15, NA, 19, NA, 28, 34, 39, 44, 48, 54, 59, 65, 70, 76, 82, 87, NA, NA, 95, 99, 104 }, + { 2, 7, 11, NA, NA, 20, NA, 29, 35, 40, 45, 49, 55, 60, 66, 71, 77, 83, 88, 91, NA, NA, NA, NA }, + { 3, 8, 12, 16, NA, 21, 24, 30, 36, 41, 46, 50, 56, 61, 67, 72, 78, NA, 89, NA, NA, NA, 100, NA }, + { 4, NA, 13, NA, NA, 22, 25, 31, NA, NA, NA, 51, NA, NA, NA, 73, 79, 84, NA, 92, NA, 96, 101, 105 }, + { NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 62, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA } +}; + +static unsigned int ASUS_TUF_K1_LAYOUT_KEYS[1][5] = +{ + { 0, 1, 2, 3, 4 }, +}; + +static std::map AsusTUFK7Layouts = +{ + { + ASUS_TUF_K7_LAYOUT_UK, + { + *ASUS_TUF_K7_LAYOUT_KEYS_ISO, + 105, + 6, + 24, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_1, 0x11 }, + { KEY_EN_ISO_BACK_SLASH, 0x0C }, + { KEY_EN_LEFT_WINDOWS, 0x0D }, + + { KEY_EN_F1, 0x18 }, + { KEY_EN_2, 0x19 }, + { KEY_EN_Q, 0x12 }, + { KEY_EN_A, 0x13 }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x15 }, + + { KEY_EN_F2, 0x20 }, + { KEY_EN_3, 0x21 }, + { KEY_EN_W, 0x1A }, + { KEY_EN_S, 0x1B }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F3, 0x28 }, + { KEY_EN_4, 0x29 }, + { KEY_EN_E, 0x22 }, + { KEY_EN_D, 0x23 }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F4, 0x30 }, + { KEY_EN_5, 0x31 }, + { KEY_EN_R, 0x2A }, + { KEY_EN_F, 0x2B }, + { KEY_EN_V, 0x2C }, + + { KEY_EN_6, 0x39 }, + { KEY_EN_T, 0x32 }, + { KEY_EN_G, 0x33 }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F5, 0x40 }, + { KEY_EN_7, 0x41 }, + { KEY_EN_Y, 0x3A }, + { KEY_EN_H, 0x3B }, + { KEY_EN_N, 0x3C }, + + { KEY_EN_F6, 0x48 }, + { KEY_EN_8, 0x49 }, + { KEY_EN_U, 0x42 }, + { KEY_EN_J, 0x43 }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F7, 0x50 }, + { KEY_EN_9, 0x51 }, + { KEY_EN_I, 0x4A }, + { KEY_EN_K, 0x4B }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F8, 0x58 }, + { KEY_EN_0, 0x59 }, + { KEY_EN_O, 0x52 }, + { KEY_EN_L, 0x53 }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x4D }, + + { KEY_EN_F9, 0x60 }, + { KEY_EN_MINUS, 0x61 }, + { KEY_EN_P, 0x5A }, + { KEY_EN_SEMICOLON, 0x5B }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F10, 0x68 }, + { KEY_EN_EQUALS, 0x69 }, + { KEY_EN_LEFT_BRACKET, 0x62 }, + { KEY_EN_QUOTE, 0x63 }, + { KEY_EN_MENU, 0x65 }, + + { KEY_EN_F11, 0x70 }, + { KEY_EN_BACKSPACE, 0x79 }, + { KEY_EN_RIGHT_BRACKET, 0x6A }, + { KEY_EN_POUND, 0x6B }, + { KEY_EN_RIGHT_SHIFT, 0x7C }, + + { KEY_EN_F12, 0x78 }, + { KEY_EN_ISO_ENTER, 0x7B }, + { KEY_EN_RIGHT_CONTROL, 0x7D }, + + { KEY_EN_PRINT_SCREEN, 0x80 }, + { KEY_EN_INSERT, 0x81 }, + { KEY_EN_DELETE, 0x82 }, + { KEY_EN_LEFT_ARROW, 0x85 }, + + { KEY_EN_SCROLL_LOCK, 0x88 }, + { KEY_EN_HOME, 0x89 }, + { KEY_EN_END, 0x8A }, + { KEY_EN_UP_ARROW, 0x8C }, + { KEY_EN_DOWN_ARROW, 0x8D }, + + { KEY_EN_PAUSE_BREAK, 0x90 }, + { KEY_EN_PAGE_UP, 0x91 }, + { KEY_EN_PAGE_DOWN, 0x92 }, + { KEY_EN_RIGHT_ARROW, 0x95 }, + + { KEY_EN_NUMPAD_LOCK, 0x99 }, + { KEY_EN_NUMPAD_7, 0x9A }, + { KEY_EN_NUMPAD_4, 0x9B }, + { KEY_EN_NUMPAD_1, 0x9C }, + { KEY_EN_NUMPAD_0, 0x9D }, + + { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, + { KEY_EN_NUMPAD_8, 0xA2 }, + { KEY_EN_NUMPAD_5, 0xA3 }, + { KEY_EN_NUMPAD_2, 0xA4 }, + + { KEY_EN_NUMPAD_TIMES, 0xA9 }, + { KEY_EN_NUMPAD_9, 0xAA }, + { KEY_EN_NUMPAD_6, 0xAB }, + { KEY_EN_NUMPAD_3, 0xAC }, + { KEY_EN_NUMPAD_PERIOD, 0xAD }, + + { KEY_EN_NUMPAD_MINUS, 0xB1 }, + { KEY_EN_NUMPAD_PLUS, 0xB2 }, + { KEY_EN_NUMPAD_ENTER, 0xB4 } + } + } + }, + { + ASUS_TUF_K7_LAYOUT_US, + { + *ASUS_TUF_K7_LAYOUT_KEYS_ANSI, + 104, + 6, + 24, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_1, 0x11 }, + { KEY_EN_LEFT_WINDOWS, 0x0D }, + + { KEY_EN_F1, 0x18 }, + { KEY_EN_2, 0x19 }, + { KEY_EN_Q, 0x12 }, + { KEY_EN_A, 0x13 }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x15 }, + + { KEY_EN_F2, 0x20 }, + { KEY_EN_3, 0x21 }, + { KEY_EN_W, 0x1A }, + { KEY_EN_S, 0x1B }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F3, 0x28 }, + { KEY_EN_4, 0x29 }, + { KEY_EN_E, 0x22 }, + { KEY_EN_D, 0x23 }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F4, 0x30 }, + { KEY_EN_5, 0x31 }, + { KEY_EN_R, 0x2A }, + { KEY_EN_F, 0x2B }, + { KEY_EN_V, 0x2C }, + + { KEY_EN_6, 0x39 }, + { KEY_EN_T, 0x32 }, + { KEY_EN_G, 0x33 }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F5, 0x40 }, + { KEY_EN_7, 0x41 }, + { KEY_EN_Y, 0x3A }, + { KEY_EN_H, 0x3B }, + { KEY_EN_N, 0x3C }, + + { KEY_EN_F6, 0x48 }, + { KEY_EN_8, 0x49 }, + { KEY_EN_U, 0x42 }, + { KEY_EN_J, 0x43 }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F7, 0x50 }, + { KEY_EN_9, 0x51 }, + { KEY_EN_I, 0x4A }, + { KEY_EN_K, 0x4B }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F8, 0x58 }, + { KEY_EN_0, 0x59 }, + { KEY_EN_O, 0x52 }, + { KEY_EN_L, 0x53 }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x4D }, + + { KEY_EN_F9, 0x60 }, + { KEY_EN_MINUS, 0x61 }, + { KEY_EN_P, 0x5A }, + { KEY_EN_SEMICOLON, 0x5B }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F10, 0x68 }, + { KEY_EN_EQUALS, 0x69 }, + { KEY_EN_LEFT_BRACKET, 0x62 }, + { KEY_EN_QUOTE, 0x63 }, + { KEY_EN_MENU, 0x65 }, + + { KEY_EN_F11, 0x70 }, + { KEY_EN_BACKSPACE, 0x79 }, + { KEY_EN_RIGHT_BRACKET, 0x6A }, + { KEY_EN_RIGHT_SHIFT, 0x7C }, + + { KEY_EN_F12, 0x78 }, + { KEY_EN_ANSI_BACK_SLASH, 0x7A }, + { KEY_EN_ANSI_ENTER, 0x7B }, + { KEY_EN_RIGHT_CONTROL, 0x7D }, + + { KEY_EN_PRINT_SCREEN, 0x80 }, + { KEY_EN_INSERT, 0x81 }, + { KEY_EN_DELETE, 0x82 }, + { KEY_EN_LEFT_ARROW, 0x85 }, + + { KEY_EN_SCROLL_LOCK, 0x88 }, + { KEY_EN_HOME, 0x89 }, + { KEY_EN_END, 0x8A }, + { KEY_EN_UP_ARROW, 0x8C }, + { KEY_EN_DOWN_ARROW, 0x8D }, + + { KEY_EN_PAUSE_BREAK, 0x90 }, + { KEY_EN_PAGE_UP, 0x91 }, + { KEY_EN_PAGE_DOWN, 0x92 }, + { KEY_EN_RIGHT_ARROW, 0x95 }, + + { KEY_EN_NUMPAD_LOCK, 0x99 }, + { KEY_EN_NUMPAD_7, 0x9A }, + { KEY_EN_NUMPAD_4, 0x9B }, + { KEY_EN_NUMPAD_1, 0x9C }, + { KEY_EN_NUMPAD_0, 0x9D }, + + { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, + { KEY_EN_NUMPAD_8, 0xA2 }, + { KEY_EN_NUMPAD_5, 0xA3 }, + { KEY_EN_NUMPAD_2, 0xA4 }, + + { KEY_EN_NUMPAD_TIMES, 0xA9 }, + { KEY_EN_NUMPAD_9, 0xAA }, + { KEY_EN_NUMPAD_6, 0xAB }, + { KEY_EN_NUMPAD_3, 0xAC }, + { KEY_EN_NUMPAD_PERIOD, 0xAD }, + + { KEY_EN_NUMPAD_MINUS, 0xB1 }, + { KEY_EN_NUMPAD_PLUS, 0xB2 }, + { KEY_EN_NUMPAD_ENTER, 0xB4 } + } + } + }, +}; + +static std::map AsusROGAzothLayouts = +{ + { + ASUS_TUF_K7_LAYOUT_UK, + { + *ASUS_ROG_AZOTH_LAYOUT_KEYS_UK, + 82, + 6, + 16, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_F1, 0x08 }, + { KEY_EN_1, 0x09 }, + { KEY_EN_ISO_BACK_SLASH, 0x0C }, + { KEY_EN_LEFT_WINDOWS, 0x0D }, + + { KEY_EN_F2, 0x10 }, + { KEY_EN_2, 0x11 }, + { KEY_EN_Q, 0x0A }, + { KEY_EN_A, 0x0B }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x15 }, + + { KEY_EN_F3, 0x18 }, + { KEY_EN_3, 0x19 }, + { KEY_EN_W, 0x12 }, + { KEY_EN_S, 0x13 }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F4, 0x20 }, + { KEY_EN_4, 0x21 }, + { KEY_EN_E, 0x1A }, + { KEY_EN_D, 0x1B }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F5, 0x28 }, + { KEY_EN_5, 0x29 }, + { KEY_EN_R, 0x22 }, + { KEY_EN_F, 0x23 }, + { KEY_EN_V, 0x2C }, + + { KEY_EN_F6, 0x30 }, + { KEY_EN_6, 0x31 }, + { KEY_EN_T, 0x2A }, + { KEY_EN_G, 0x2B }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F7, 0x38 }, + { KEY_EN_7, 0x39 }, + { KEY_EN_Y, 0x32 }, + { KEY_EN_H, 0x33 }, + { KEY_EN_N, 0x3C }, + + { KEY_EN_F8, 0x40 }, + { KEY_EN_8, 0x41 }, + { KEY_EN_U, 0x3A }, + { KEY_EN_J, 0x3B }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F9, 0x48 }, + { KEY_EN_9, 0x49 }, + { KEY_EN_I, 0x42 }, + { KEY_EN_K, 0x43 }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F10, 0x50 }, + { KEY_EN_0, 0x51 }, + { KEY_EN_O, 0x4A }, + { KEY_EN_L, 0x4B }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x55 }, + + { KEY_EN_F11, 0x58 }, + { KEY_EN_MINUS, 0x59 }, + { KEY_EN_P, 0x52 }, + { KEY_EN_SEMICOLON, 0x53 }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F12, 0x60 }, + { KEY_EN_EQUALS, 0x61 }, + { KEY_EN_LEFT_BRACKET, 0x5A }, + { KEY_EN_QUOTE, 0x5B }, + { KEY_EN_RIGHT_SHIFT, 0x64 }, + { KEY_EN_RIGHT_CONTROL, 0x65 }, + + { KEY_EN_BACKSPACE, 0x69 }, + { KEY_EN_RIGHT_BRACKET, 0x62 }, + { KEY_EN_POUND, 0x6B }, + { KEY_EN_LEFT_ARROW, 0x6D }, + + { KEY_EN_ISO_ENTER, 0x6A }, + { KEY_EN_UP_ARROW, 0x74 }, + { KEY_EN_DOWN_ARROW, 0x75 }, + + { KEY_EN_INSERT, 0x79 }, + { KEY_EN_DELETE, 0x7A }, + { KEY_EN_PAGE_UP, 0x7B }, + { KEY_EN_PAGE_DOWN, 0x7C }, + { KEY_EN_RIGHT_ARROW, 0x7D }, + } + } + }, + { + ASUS_TUF_K7_LAYOUT_US, + { + *ASUS_ROG_AZOTH_LAYOUT_KEYS_US, + 81, + 6, + 16, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_F1, 0x08 }, + { KEY_EN_1, 0x09 }, + { KEY_EN_LEFT_WINDOWS, 0x0D }, + + { KEY_EN_F2, 0x10 }, + { KEY_EN_2, 0x11 }, + { KEY_EN_Q, 0x0A }, + { KEY_EN_A, 0x0B }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x15 }, + + { KEY_EN_F3, 0x18 }, + { KEY_EN_3, 0x19 }, + { KEY_EN_W, 0x12 }, + { KEY_EN_S, 0x13 }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F4, 0x20 }, + { KEY_EN_4, 0x21 }, + { KEY_EN_E, 0x1A }, + { KEY_EN_D, 0x1B }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F5, 0x28 }, + { KEY_EN_5, 0x29 }, + { KEY_EN_R, 0x22 }, + { KEY_EN_F, 0x23 }, + { KEY_EN_V, 0x2C }, + + { KEY_EN_F6, 0x30 }, + { KEY_EN_6, 0x31 }, + { KEY_EN_T, 0x2A }, + { KEY_EN_G, 0x2B }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F7, 0x38 }, + { KEY_EN_7, 0x39 }, + { KEY_EN_Y, 0x32 }, + { KEY_EN_H, 0x33 }, + { KEY_EN_N, 0x3C }, + + { KEY_EN_F8, 0x40 }, + { KEY_EN_8, 0x41 }, + { KEY_EN_U, 0x3A }, + { KEY_EN_J, 0x3B }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F9, 0x48 }, + { KEY_EN_9, 0x49 }, + { KEY_EN_I, 0x42 }, + { KEY_EN_K, 0x43 }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F10, 0x50 }, + { KEY_EN_0, 0x51 }, + { KEY_EN_O, 0x4A }, + { KEY_EN_L, 0x4B }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x55 }, + + { KEY_EN_F11, 0x58 }, + { KEY_EN_MINUS, 0x59 }, + { KEY_EN_P, 0x52 }, + { KEY_EN_SEMICOLON, 0x53 }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F12, 0x60 }, + { KEY_EN_EQUALS, 0x61 }, + { KEY_EN_LEFT_BRACKET, 0x5A }, + { KEY_EN_QUOTE, 0x5B }, + { KEY_EN_RIGHT_SHIFT, 0x64 }, + { KEY_EN_RIGHT_CONTROL, 0x65 }, + + { KEY_EN_BACKSPACE, 0x69 }, + { KEY_EN_RIGHT_BRACKET, 0x62 }, + { KEY_EN_LEFT_ARROW, 0x6D }, + + { KEY_EN_ANSI_BACK_SLASH, 0x6A }, + { KEY_EN_ANSI_ENTER, 0x6B }, + { KEY_EN_UP_ARROW, 0x74 }, + { KEY_EN_DOWN_ARROW, 0x75 }, + + { KEY_EN_INSERT, 0x79 }, + { KEY_EN_DELETE, 0x7A }, + { KEY_EN_PAGE_UP, 0x7B }, + { KEY_EN_PAGE_DOWN, 0x7C }, + { KEY_EN_RIGHT_ARROW, 0x7D }, + } + } + }, +}; + +static std::map AsusROGStrixScopeLayouts = +{ + { + ASUS_TUF_K7_LAYOUT_UK, + { + *ASUS_ROG_STRIX_SCOPE_LAYOUT_KEYS_ISO, + 107, + 6, + 24, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_1, 0x11 }, + { KEY_EN_ISO_BACK_SLASH, 0x0C }, + { KEY_EN_LEFT_WINDOWS, 0x15 }, + + { KEY_EN_F1, 0x18 }, + { KEY_EN_2, 0x19 }, + { KEY_EN_Q, 0x12 }, + { KEY_EN_A, 0x13 }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x1D }, + + { KEY_EN_F2, 0x20 }, + { KEY_EN_3, 0x21 }, + { KEY_EN_W, 0x1A }, + { KEY_EN_S, 0x1B }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F3, 0x28 }, + { KEY_EN_4, 0x29 }, + { KEY_EN_E, 0x22 }, + { KEY_EN_D, 0x23 }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F4, 0x30 }, + { KEY_EN_5, 0x31 }, + { KEY_EN_R, 0x2A }, + { KEY_EN_F, 0x2B }, + { KEY_EN_V, 0x2C }, + + { KEY_EN_6, 0x39 }, + { KEY_EN_T, 0x32 }, + { KEY_EN_G, 0x33 }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F5, 0x40 }, + { KEY_EN_7, 0x41 }, + { KEY_EN_Y, 0x3A }, + { KEY_EN_H, 0x3B }, + { KEY_EN_N, 0x3C }, + + { KEY_EN_F6, 0x48 }, + { KEY_EN_8, 0x49 }, + { KEY_EN_U, 0x42 }, + { KEY_EN_J, 0x43 }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F7, 0x50 }, + { KEY_EN_9, 0x51 }, + { KEY_EN_I, 0x4A }, + { KEY_EN_K, 0x4B }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F8, 0x58 }, + { KEY_EN_0, 0x59 }, + { KEY_EN_O, 0x52 }, + { KEY_EN_L, 0x53 }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x4D }, + + { KEY_EN_F9, 0x60 }, + { KEY_EN_MINUS, 0x61 }, + { KEY_EN_P, 0x5A }, + { KEY_EN_SEMICOLON, 0x5B }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F10, 0x68 }, + { KEY_EN_EQUALS, 0x69 }, + { KEY_EN_LEFT_BRACKET, 0x62 }, + { KEY_EN_QUOTE, 0x63 }, + { KEY_EN_MENU, 0x65 }, + + { KEY_EN_F11, 0x70 }, + { KEY_EN_BACKSPACE, 0x79 }, + { KEY_EN_RIGHT_BRACKET, 0x6A }, + { KEY_EN_POUND, 0x6B }, + { KEY_EN_RIGHT_SHIFT, 0x7C }, + + { KEY_EN_F12, 0x78 }, + { KEY_EN_ISO_ENTER, 0x7B }, + { KEY_EN_RIGHT_CONTROL, 0x7D }, + + { KEY_EN_PRINT_SCREEN, 0x80 }, + { KEY_EN_INSERT, 0x81 }, + { KEY_EN_DELETE, 0x82 }, + { KEY_EN_LEFT_ARROW, 0x85 }, + + { KEY_EN_SCROLL_LOCK, 0x88 }, + { KEY_EN_HOME, 0x89 }, + { KEY_EN_END, 0x8A }, + { KEY_EN_UP_ARROW, 0x8C }, + { KEY_EN_DOWN_ARROW, 0x8D }, + + { KEY_EN_PAUSE_BREAK, 0x90 }, + { KEY_EN_PAGE_UP, 0x91 }, + { KEY_EN_PAGE_DOWN, 0x92 }, + { KEY_EN_RIGHT_ARROW, 0x95 }, + + { KEY_EN_NUMPAD_LOCK, 0x99 }, + { KEY_EN_NUMPAD_7, 0x9A }, + { KEY_EN_NUMPAD_4, 0x9B }, + { KEY_EN_NUMPAD_1, 0x9C }, + { KEY_EN_NUMPAD_0, 0x9D }, + + { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, + { KEY_EN_NUMPAD_8, 0xA2 }, + { KEY_EN_NUMPAD_5, 0xA3 }, + { KEY_EN_NUMPAD_2, 0xA4 }, + + { KEY_EN_NUMPAD_TIMES, 0xA9 }, + { KEY_EN_NUMPAD_9, 0xAA }, + { KEY_EN_NUMPAD_6, 0xAB }, + { KEY_EN_NUMPAD_3, 0xAC }, + { KEY_EN_NUMPAD_PERIOD, 0xAD }, + + { KEY_EN_NUMPAD_MINUS, 0xB1 }, + { KEY_EN_NUMPAD_PLUS, 0xB2 }, + { KEY_EN_NUMPAD_ENTER, 0xB4 }, + + { "Logo 1", 0xA8 }, + { "Logo 2", 0xB0 }, + } + } + }, + { + ASUS_TUF_K7_LAYOUT_US, + { + *ASUS_ROG_STRIX_SCOPE_LAYOUT_KEYS_ANSI, + 106, + 6, + 24, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_1, 0x11 }, + { KEY_EN_LEFT_WINDOWS, 0x15 }, + + { KEY_EN_F1, 0x18 }, + { KEY_EN_2, 0x19 }, + { KEY_EN_Q, 0x12 }, + { KEY_EN_A, 0x13 }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x1D }, + + { KEY_EN_F2, 0x20 }, + { KEY_EN_3, 0x21 }, + { KEY_EN_W, 0x1A }, + { KEY_EN_S, 0x1B }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F3, 0x28 }, + { KEY_EN_4, 0x29 }, + { KEY_EN_E, 0x22 }, + { KEY_EN_D, 0x23 }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F4, 0x30 }, + { KEY_EN_5, 0x31 }, + { KEY_EN_R, 0x2A }, + { KEY_EN_F, 0x2B }, + { KEY_EN_V, 0x2C }, + + { KEY_EN_6, 0x39 }, + { KEY_EN_T, 0x32 }, + { KEY_EN_G, 0x33 }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F5, 0x40 }, + { KEY_EN_7, 0x41 }, + { KEY_EN_Y, 0x3A }, + { KEY_EN_H, 0x3B }, + { KEY_EN_N, 0x3C }, + + { KEY_EN_F6, 0x48 }, + { KEY_EN_8, 0x49 }, + { KEY_EN_U, 0x42 }, + { KEY_EN_J, 0x43 }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F7, 0x50 }, + { KEY_EN_9, 0x51 }, + { KEY_EN_I, 0x4A }, + { KEY_EN_K, 0x4B }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F8, 0x58 }, + { KEY_EN_0, 0x59 }, + { KEY_EN_O, 0x52 }, + { KEY_EN_L, 0x53 }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x4D }, + + { KEY_EN_F9, 0x60 }, + { KEY_EN_MINUS, 0x61 }, + { KEY_EN_P, 0x5A }, + { KEY_EN_SEMICOLON, 0x5B }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F10, 0x68 }, + { KEY_EN_EQUALS, 0x69 }, + { KEY_EN_LEFT_BRACKET, 0x62 }, + { KEY_EN_QUOTE, 0x63 }, + { KEY_EN_MENU, 0x65 }, + + { KEY_EN_F11, 0x70 }, + { KEY_EN_BACKSPACE, 0x79 }, + { KEY_EN_RIGHT_BRACKET, 0x6A }, + { KEY_EN_RIGHT_SHIFT, 0x7C }, + + { KEY_EN_F12, 0x78 }, + { KEY_EN_ANSI_BACK_SLASH, 0x7A }, + { KEY_EN_ANSI_ENTER, 0x7B }, + { KEY_EN_RIGHT_CONTROL, 0x7D }, + + { KEY_EN_PRINT_SCREEN, 0x80 }, + { KEY_EN_INSERT, 0x81 }, + { KEY_EN_DELETE, 0x82 }, + { KEY_EN_LEFT_ARROW, 0x85 }, + + { KEY_EN_SCROLL_LOCK, 0x88 }, + { KEY_EN_HOME, 0x89 }, + { KEY_EN_END, 0x8A }, + { KEY_EN_UP_ARROW, 0x8C }, + { KEY_EN_DOWN_ARROW, 0x8D }, + + { KEY_EN_PAUSE_BREAK, 0x90 }, + { KEY_EN_PAGE_UP, 0x91 }, + { KEY_EN_PAGE_DOWN, 0x92 }, + { KEY_EN_RIGHT_ARROW, 0x95 }, + + { KEY_EN_NUMPAD_LOCK, 0x99 }, + { KEY_EN_NUMPAD_7, 0x9A }, + { KEY_EN_NUMPAD_4, 0x9B }, + { KEY_EN_NUMPAD_1, 0x9C }, + { KEY_EN_NUMPAD_0, 0x9D }, + + { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, + { KEY_EN_NUMPAD_8, 0xA2 }, + { KEY_EN_NUMPAD_5, 0xA3 }, + { KEY_EN_NUMPAD_2, 0xA4 }, + + { KEY_EN_NUMPAD_TIMES, 0xA9 }, + { KEY_EN_NUMPAD_9, 0xAA }, + { KEY_EN_NUMPAD_6, 0xAB }, + { KEY_EN_NUMPAD_3, 0xAC }, + { KEY_EN_NUMPAD_PERIOD, 0xAD }, + + { KEY_EN_NUMPAD_MINUS, 0xB1 }, + { KEY_EN_NUMPAD_PLUS, 0xB2 }, + { KEY_EN_NUMPAD_ENTER, 0xB4 }, + + { "Logo 1", 0xA8 }, + { "Logo 2", 0xB0 }, + } + } + }, +}; + +static std::map AsusROGStrixScopeIILayouts = +{ + { + ASUS_TUF_K7_LAYOUT_UK, + { + *ASUS_ROG_STRIX_SCOPE_II_LAYOUT_KEYS_ISO, + 108, + 6, + 24, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_1, 0x11 }, + { KEY_EN_ISO_BACK_SLASH, 0x0C }, + { KEY_EN_LEFT_WINDOWS, 0x0D }, + + { KEY_EN_F1, 0x18 }, + { KEY_EN_2, 0x19 }, + { KEY_EN_Q, 0x12 }, + { KEY_EN_A, 0x13 }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x15 }, + + { KEY_EN_F2, 0x20 }, + { KEY_EN_3, 0x21 }, + { KEY_EN_W, 0x1A }, + { KEY_EN_S, 0x1B }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F3, 0x28 }, + { KEY_EN_4, 0x29 }, + { KEY_EN_E, 0x22 }, + { KEY_EN_D, 0x23 }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F4, 0x30 }, + { KEY_EN_5, 0x31 }, + { KEY_EN_R, 0x2A }, + { KEY_EN_F, 0x2B }, + { KEY_EN_V, 0x2C }, + { KEY_EN_SPACE, 0x2D }, + + { KEY_EN_6, 0x39 }, + { KEY_EN_T, 0x32 }, + { KEY_EN_G, 0x33 }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F5, 0x40 }, + { KEY_EN_7, 0x41 }, + { KEY_EN_Y, 0x3A }, + { KEY_EN_H, 0x3B }, + { KEY_EN_N, 0x3C }, + { KEY_EN_SPACE, 0x3D }, + + { KEY_EN_F6, 0x48 }, + { KEY_EN_8, 0x49 }, + { KEY_EN_U, 0x42 }, + { KEY_EN_J, 0x43 }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F7, 0x50 }, + { KEY_EN_9, 0x51 }, + { KEY_EN_I, 0x4A }, + { KEY_EN_K, 0x4B }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F8, 0x58 }, + { KEY_EN_0, 0x59 }, + { KEY_EN_O, 0x52 }, + { KEY_EN_L, 0x53 }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x4D }, + + { KEY_EN_F9, 0x60 }, + { KEY_EN_MINUS, 0x61 }, + { KEY_EN_P, 0x5A }, + { KEY_EN_SEMICOLON, 0x5B }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F10, 0x68 }, + { KEY_EN_EQUALS, 0x69 }, + { KEY_EN_LEFT_BRACKET, 0x62 }, + { KEY_EN_QUOTE, 0x63 }, + { KEY_EN_MENU, 0x65 }, + + { KEY_EN_F11, 0x70 }, + { KEY_EN_BACKSPACE, 0x79 }, + { KEY_EN_RIGHT_BRACKET, 0x6A }, + { KEY_EN_POUND, 0x6B }, + { KEY_EN_RIGHT_SHIFT, 0x7C }, + + { KEY_EN_F12, 0x78 }, + { KEY_EN_ISO_ENTER, 0x7B }, + { KEY_EN_RIGHT_CONTROL, 0x7D }, + + { KEY_EN_PRINT_SCREEN, 0x80 }, + { KEY_EN_INSERT, 0x81 }, + { KEY_EN_DELETE, 0x82 }, + { KEY_EN_LEFT_ARROW, 0x85 }, + + { KEY_EN_SCROLL_LOCK, 0x88 }, + { KEY_EN_HOME, 0x89 }, + { KEY_EN_END, 0x8A }, + { KEY_EN_UP_ARROW, 0x8C }, + { KEY_EN_DOWN_ARROW, 0x8D }, + + { KEY_EN_PAUSE_BREAK, 0x90 }, + { KEY_EN_PAGE_UP, 0x91 }, + { KEY_EN_PAGE_DOWN, 0x92 }, + { KEY_EN_RIGHT_ARROW, 0x95 }, + + { KEY_EN_NUMPAD_LOCK, 0x99 }, + { KEY_EN_NUMPAD_7, 0x9A }, + { KEY_EN_NUMPAD_4, 0x9B }, + { KEY_EN_NUMPAD_1, 0x9C }, + { KEY_EN_NUMPAD_0, 0x9D }, + + { "Logo", 0xA0 }, + { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, + { KEY_EN_NUMPAD_8, 0xA2 }, + { KEY_EN_NUMPAD_5, 0xA3 }, + { KEY_EN_NUMPAD_2, 0xA4 }, + + { KEY_EN_NUMPAD_TIMES, 0xA9 }, + { KEY_EN_NUMPAD_9, 0xAA }, + { KEY_EN_NUMPAD_6, 0xAB }, + { KEY_EN_NUMPAD_3, 0xAC }, + { KEY_EN_NUMPAD_PERIOD, 0xAD }, + + { KEY_EN_NUMPAD_MINUS, 0xB1 }, + { KEY_EN_NUMPAD_PLUS, 0xB2 }, + { KEY_EN_NUMPAD_ENTER, 0xB4 }, + + } + } + }, + { + ASUS_TUF_K7_LAYOUT_US, + { + *ASUS_ROG_STRIX_SCOPE_II_LAYOUT_KEYS_ANSI, + 107, + 6, + 24, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_1, 0x11 }, + { KEY_EN_LEFT_WINDOWS, 0x0D }, + + { KEY_EN_F1, 0x18 }, + { KEY_EN_2, 0x19 }, + { KEY_EN_Q, 0x12 }, + { KEY_EN_A, 0x13 }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x15 }, + + { KEY_EN_F2, 0x20 }, + { KEY_EN_3, 0x21 }, + { KEY_EN_W, 0x1A }, + { KEY_EN_S, 0x1B }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F3, 0x28 }, + { KEY_EN_4, 0x29 }, + { KEY_EN_E, 0x22 }, + { KEY_EN_D, 0x23 }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F4, 0x30 }, + { KEY_EN_5, 0x31 }, + { KEY_EN_R, 0x2A }, + { KEY_EN_F, 0x2B }, + { KEY_EN_V, 0x2C }, + { KEY_EN_SPACE, 0x2D }, + + { KEY_EN_6, 0x39 }, + { KEY_EN_T, 0x32 }, + { KEY_EN_G, 0x33 }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F5, 0x40 }, + { KEY_EN_7, 0x41 }, + { KEY_EN_Y, 0x3A }, + { KEY_EN_H, 0x3B }, + { KEY_EN_N, 0x3C }, + { KEY_EN_SPACE, 0x3D }, + + { KEY_EN_F6, 0x48 }, + { KEY_EN_8, 0x49 }, + { KEY_EN_U, 0x42 }, + { KEY_EN_J, 0x43 }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F7, 0x50 }, + { KEY_EN_9, 0x51 }, + { KEY_EN_I, 0x4A }, + { KEY_EN_K, 0x4B }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F8, 0x58 }, + { KEY_EN_0, 0x59 }, + { KEY_EN_O, 0x52 }, + { KEY_EN_L, 0x53 }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x4D }, + + { KEY_EN_F9, 0x60 }, + { KEY_EN_MINUS, 0x61 }, + { KEY_EN_P, 0x5A }, + { KEY_EN_SEMICOLON, 0x5B }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F10, 0x68 }, + { KEY_EN_EQUALS, 0x69 }, + { KEY_EN_LEFT_BRACKET, 0x62 }, + { KEY_EN_QUOTE, 0x63 }, + { KEY_EN_MENU, 0x65 }, + + { KEY_EN_F11, 0x70 }, + { KEY_EN_BACKSPACE, 0x79 }, + { KEY_EN_RIGHT_BRACKET, 0x6A }, + { KEY_EN_RIGHT_SHIFT, 0x7C }, + + { KEY_EN_F12, 0x78 }, + { KEY_EN_ANSI_BACK_SLASH, 0x7A }, + { KEY_EN_ANSI_ENTER, 0x7B }, + { KEY_EN_RIGHT_CONTROL, 0x7D }, + + { KEY_EN_PRINT_SCREEN, 0x80 }, + { KEY_EN_INSERT, 0x81 }, + { KEY_EN_DELETE, 0x82 }, + { KEY_EN_LEFT_ARROW, 0x85 }, + + { KEY_EN_SCROLL_LOCK, 0x88 }, + { KEY_EN_HOME, 0x89 }, + { KEY_EN_END, 0x8A }, + { KEY_EN_UP_ARROW, 0x8C }, + { KEY_EN_DOWN_ARROW, 0x8D }, + + { KEY_EN_PAUSE_BREAK, 0x90 }, + { KEY_EN_PAGE_UP, 0x91 }, + { KEY_EN_PAGE_DOWN, 0x92 }, + { KEY_EN_RIGHT_ARROW, 0x95 }, + + { KEY_EN_NUMPAD_LOCK, 0x99 }, + { KEY_EN_NUMPAD_7, 0x9A }, + { KEY_EN_NUMPAD_4, 0x9B }, + { KEY_EN_NUMPAD_1, 0x9C }, + { KEY_EN_NUMPAD_0, 0x9D }, + + { "Logo", 0xA0 }, + { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, + { KEY_EN_NUMPAD_8, 0xA2 }, + { KEY_EN_NUMPAD_5, 0xA3 }, + { KEY_EN_NUMPAD_2, 0xA4 }, + + { KEY_EN_NUMPAD_TIMES, 0xA9 }, + { KEY_EN_NUMPAD_9, 0xAA }, + { KEY_EN_NUMPAD_6, 0xAB }, + { KEY_EN_NUMPAD_3, 0xAC }, + { KEY_EN_NUMPAD_PERIOD, 0xAD }, + + { KEY_EN_NUMPAD_MINUS, 0xB1 }, + { KEY_EN_NUMPAD_PLUS, 0xB2 }, + { KEY_EN_NUMPAD_ENTER, 0xB4 }, + } + } + }, +}; + +static std::map AsusROGStrixScopeII96WirelessLayouts = +{ + { + ASUS_TUF_K7_LAYOUT_NO, + { + *ASUS_ROG_STRIX_SCOPE_II_96_WIRELESS_LAYOUT_KEYS_ISO, + 102, + 6, + 19, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_NORD_HALF, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_F1, 0x08 }, + { KEY_EN_1, 0x09 }, + { KEY_EN_Q, 0x0A }, + { KEY_EN_A, 0x0B }, + { KEY_NORD_ANGLE_BRACKET, 0x0C }, + { KEY_EN_LEFT_WINDOWS, 0x0D }, + + { KEY_EN_F2, 0x10 }, + { KEY_EN_2, 0x11 }, + { KEY_EN_W, 0x12 }, + { KEY_EN_S, 0x13 }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x15 }, + + { KEY_EN_F3, 0x18 }, + { KEY_EN_3, 0x19 }, + { KEY_EN_E, 0x1A }, + { KEY_EN_D, 0x1B }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F4, 0x20 }, + { KEY_EN_4, 0x21 }, + { KEY_EN_R, 0x22 }, + { KEY_EN_F, 0x23 }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F5, 0x28 }, + { KEY_EN_5, 0x29 }, + { KEY_EN_T, 0x2A }, + { KEY_EN_G, 0x2B }, + { KEY_EN_V, 0x2C }, + { KEY_EN_SPACE, 0x2D }, + + { KEY_EN_F6, 0x30 }, + { KEY_EN_6, 0x31 }, + { KEY_EN_Y, 0x32 }, + { KEY_EN_H, 0x33 }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F7, 0x38 }, + { KEY_EN_7, 0x39 }, + { KEY_EN_U, 0x3A }, + { KEY_EN_J, 0x3B }, + { KEY_EN_N, 0x3C }, + { KEY_EN_SPACE, 0x3D }, + + { KEY_EN_F8, 0x40 }, + { KEY_EN_8, 0x41 }, + { KEY_EN_I, 0x42 }, + { KEY_EN_K, 0x43 }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F9, 0x48 }, + { KEY_EN_9, 0x49 }, + { KEY_EN_O, 0x4A }, + { KEY_EN_L, 0x4B }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F10, 0x50 }, + { KEY_EN_0, 0x51 }, + { KEY_EN_P, 0x52 }, + { KEY_NORD_O_AE, 0x53 }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x55 }, + + { KEY_EN_F11, 0x58 }, + { KEY_NORD_PLUS_QUESTION, 0x59 }, + { KEY_NORD_AAL, 0x5A }, + { KEY_NORD_A_OE, 0x5B }, + { KEY_NORD_HYPHEN, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F12, 0x60 }, + { KEY_NORD_ACUTE_GRAVE, 0x61 }, + { KEY_NORD_DOTS_CARET, 0x62 }, + { KEY_NORD_QUOTE, 0x63 }, + { KEY_EN_RIGHT_SHIFT, 0x64 }, + { KEY_EN_RIGHT_CONTROL, 0x65 }, + + { KEY_EN_INSERT, 0x68 }, + { KEY_EN_BACKSPACE, 0x69 }, + { KEY_EN_ISO_ENTER, 0x6B }, + { KEY_EN_LEFT_ARROW, 0x6D }, + + { KEY_EN_DELETE, 0x70 }, + { KEY_EN_UP_ARROW, 0x74 }, + { KEY_EN_DOWN_ARROW, 0x75 }, + + { KEY_EN_PAGE_UP, 0x78 }, + { KEY_EN_NUMPAD_LOCK, 0x79 }, + { KEY_EN_NUMPAD_7, 0x7A }, + { KEY_EN_NUMPAD_4, 0x7B }, + { KEY_EN_NUMPAD_1, 0x7C }, + { KEY_EN_RIGHT_ARROW, 0x7D }, + + { KEY_EN_PAGE_DOWN, 0x80 }, + { KEY_EN_NUMPAD_DIVIDE, 0x81 }, + { KEY_EN_NUMPAD_8, 0x82 }, + { KEY_EN_NUMPAD_5, 0x83 }, + { KEY_EN_NUMPAD_2, 0x84 }, + { KEY_EN_NUMPAD_0, 0x85 }, + + { KEY_EN_NUMPAD_TIMES, 0x89 }, + { KEY_EN_NUMPAD_9, 0x8A }, + { KEY_EN_NUMPAD_6, 0x8B }, + { KEY_EN_NUMPAD_3, 0x8C }, + { KEY_EN_NUMPAD_PERIOD, 0x8D }, + + { "Logo", 0x88 }, + { KEY_EN_NUMPAD_MINUS, 0x91 }, + { KEY_EN_NUMPAD_PLUS, 0x92 }, + { KEY_EN_NUMPAD_ENTER, 0x94 } + } + } + }, + { + ASUS_TUF_K7_LAYOUT_UK, + { + *ASUS_ROG_STRIX_SCOPE_II_96_WIRELESS_LAYOUT_KEYS_ISO, + 102, + 6, + 19, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_F1, 0x08 }, + { KEY_EN_1, 0x09 }, + { KEY_EN_Q, 0x0A }, + { KEY_EN_A, 0x0B }, + { KEY_EN_ISO_BACK_SLASH, 0x0C }, + { KEY_EN_LEFT_WINDOWS, 0x0D }, + + { KEY_EN_F2, 0x10 }, + { KEY_EN_2, 0x11 }, + { KEY_EN_W, 0x12 }, + { KEY_EN_S, 0x13 }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x15 }, + + { KEY_EN_F3, 0x18 }, + { KEY_EN_3, 0x19 }, + { KEY_EN_E, 0x1A }, + { KEY_EN_D, 0x1B }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F4, 0x20 }, + { KEY_EN_4, 0x21 }, + { KEY_EN_R, 0x22 }, + { KEY_EN_F, 0x23 }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F5, 0x28 }, + { KEY_EN_5, 0x29 }, + { KEY_EN_T, 0x2A }, + { KEY_EN_G, 0x2B }, + { KEY_EN_V, 0x2C }, + { KEY_EN_SPACE, 0x2D }, + + { KEY_EN_F6, 0x30 }, + { KEY_EN_6, 0x31 }, + { KEY_EN_Y, 0x32 }, + { KEY_EN_H, 0x33 }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F7, 0x38 }, + { KEY_EN_7, 0x39 }, + { KEY_EN_U, 0x3A }, + { KEY_EN_J, 0x3B }, + { KEY_EN_N, 0x3C }, + { KEY_EN_SPACE, 0x3D }, + + { KEY_EN_F8, 0x40 }, + { KEY_EN_8, 0x41 }, + { KEY_EN_I, 0x42 }, + { KEY_EN_K, 0x43 }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F9, 0x48 }, + { KEY_EN_9, 0x49 }, + { KEY_EN_O, 0x4A }, + { KEY_EN_L, 0x4B }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F10, 0x50 }, + { KEY_EN_0, 0x51 }, + { KEY_EN_P, 0x52 }, + { KEY_EN_SEMICOLON, 0x53 }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x55 }, + + { KEY_EN_F11, 0x58 }, + { KEY_EN_MINUS, 0x59 }, + { KEY_EN_LEFT_BRACKET, 0x5A }, + { KEY_EN_QUOTE, 0x5B }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F12, 0x60 }, + { KEY_EN_EQUALS, 0x61 }, + { KEY_EN_RIGHT_BRACKET, 0x62 }, + { KEY_EN_POUND, 0x63 }, + { KEY_EN_RIGHT_SHIFT, 0x64 }, + { KEY_EN_RIGHT_CONTROL, 0x65 }, + + { KEY_EN_INSERT, 0x68 }, + { KEY_EN_BACKSPACE, 0x69 }, + { KEY_EN_ISO_ENTER, 0x6B }, + { KEY_EN_LEFT_ARROW, 0x6D }, + + { KEY_EN_DELETE, 0x70 }, + { KEY_EN_UP_ARROW, 0x74 }, + { KEY_EN_DOWN_ARROW, 0x75 }, + + { KEY_EN_PAGE_UP, 0x78 }, + { KEY_EN_NUMPAD_LOCK, 0x79 }, + { KEY_EN_NUMPAD_7, 0x7A }, + { KEY_EN_NUMPAD_4, 0x7B }, + { KEY_EN_NUMPAD_1, 0x7C }, + { KEY_EN_RIGHT_ARROW, 0x7D }, + + { KEY_EN_PAGE_DOWN, 0x80 }, + { KEY_EN_NUMPAD_DIVIDE, 0x81 }, + { KEY_EN_NUMPAD_8, 0x82 }, + { KEY_EN_NUMPAD_5, 0x83 }, + { KEY_EN_NUMPAD_2, 0x84 }, + { KEY_EN_NUMPAD_0, 0x85 }, + + { KEY_EN_NUMPAD_TIMES, 0x89 }, + { KEY_EN_NUMPAD_9, 0x8A }, + { KEY_EN_NUMPAD_6, 0x8B }, + { KEY_EN_NUMPAD_3, 0x8C }, + { KEY_EN_NUMPAD_PERIOD, 0x8D }, + + { "Logo", 0x88 }, + { KEY_EN_NUMPAD_MINUS, 0x91 }, + { KEY_EN_NUMPAD_PLUS, 0x92 }, + { KEY_EN_NUMPAD_ENTER, 0x94 } + } + } + }, + { + ASUS_TUF_K7_LAYOUT_US, + { + *ASUS_ROG_STRIX_SCOPE_II_96_WIRELESS_LAYOUT_KEYS_ANSI, + 101, + 6, + 19, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_F1, 0x08 }, + { KEY_EN_1, 0x09 }, + { KEY_EN_Q, 0x0A }, + { KEY_EN_A, 0x0B }, + { KEY_EN_LEFT_WINDOWS, 0x0D }, + + { KEY_EN_F2, 0x10 }, + { KEY_EN_2, 0x11 }, + { KEY_EN_W, 0x12 }, + { KEY_EN_S, 0x13 }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x15 }, + + { KEY_EN_F3, 0x18 }, + { KEY_EN_3, 0x19 }, + { KEY_EN_E, 0x1A }, + { KEY_EN_D, 0x1B }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F4, 0x20 }, + { KEY_EN_4, 0x21 }, + { KEY_EN_R, 0x22 }, + { KEY_EN_F, 0x23 }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F5, 0x28 }, + { KEY_EN_5, 0x29 }, + { KEY_EN_T, 0x2A }, + { KEY_EN_G, 0x2B }, + { KEY_EN_V, 0x2C }, + { KEY_EN_SPACE, 0x2D }, + + { KEY_EN_F6, 0x30 }, + { KEY_EN_6, 0x31 }, + { KEY_EN_Y, 0x32 }, + { KEY_EN_H, 0x33 }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F7, 0x38 }, + { KEY_EN_7, 0x39 }, + { KEY_EN_U, 0x3A }, + { KEY_EN_J, 0x3B }, + { KEY_EN_N, 0x3C }, + { KEY_EN_SPACE, 0x3D }, + + { KEY_EN_F8, 0x40 }, + { KEY_EN_8, 0x41 }, + { KEY_EN_I, 0x42 }, + { KEY_EN_K, 0x43 }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F9, 0x48 }, + { KEY_EN_9, 0x49 }, + { KEY_EN_O, 0x4A }, + { KEY_EN_L, 0x4B }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F10, 0x50 }, + { KEY_EN_0, 0x51 }, + { KEY_EN_P, 0x52 }, + { KEY_EN_SEMICOLON, 0x53 }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x55 }, + + { KEY_EN_F11, 0x58 }, + { KEY_EN_MINUS, 0x59 }, + { KEY_EN_LEFT_BRACKET, 0x5A }, + { KEY_EN_QUOTE, 0x5B }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F12, 0x60 }, + { KEY_EN_EQUALS, 0x61 }, + { KEY_EN_RIGHT_BRACKET, 0x62 }, + { KEY_EN_RIGHT_SHIFT, 0x64 }, + { KEY_EN_RIGHT_CONTROL, 0x65 }, + + { KEY_EN_INSERT, 0x68 }, + { KEY_EN_BACKSPACE, 0x69 }, + { KEY_EN_ANSI_BACK_SLASH, 0x6A }, + { KEY_EN_ANSI_ENTER, 0x6B }, + { KEY_EN_LEFT_ARROW, 0x6D }, + + { KEY_EN_DELETE, 0x70 }, + { KEY_EN_UP_ARROW, 0x74 }, + { KEY_EN_DOWN_ARROW, 0x75 }, + + { KEY_EN_PAGE_UP, 0x78 }, + { KEY_EN_NUMPAD_LOCK, 0x79 }, + { KEY_EN_NUMPAD_7, 0x7A }, + { KEY_EN_NUMPAD_4, 0x7B }, + { KEY_EN_NUMPAD_1, 0x7C }, + { KEY_EN_RIGHT_ARROW, 0x7D }, + + { KEY_EN_PAGE_DOWN, 0x80 }, + { KEY_EN_NUMPAD_DIVIDE, 0x81 }, + { KEY_EN_NUMPAD_8, 0x82 }, + { KEY_EN_NUMPAD_5, 0x83 }, + { KEY_EN_NUMPAD_2, 0x84 }, + { KEY_EN_NUMPAD_0, 0x85 }, + + { KEY_EN_NUMPAD_TIMES, 0x89 }, + { KEY_EN_NUMPAD_9, 0x8A }, + { KEY_EN_NUMPAD_6, 0x8B }, + { KEY_EN_NUMPAD_3, 0x8C }, + { KEY_EN_NUMPAD_PERIOD, 0x8D }, + + { "Logo", 0x88 }, + { KEY_EN_NUMPAD_MINUS, 0x91 }, + { KEY_EN_NUMPAD_PLUS, 0x92 }, + { KEY_EN_NUMPAD_ENTER, 0x94 } + } + } + }, +}; + +static std::map AsusROGStrixFlareLayouts = +{ + { + ASUS_TUF_K7_LAYOUT_UK, + { + *ASUS_ROG_STRIX_FLARE_LAYOUT_KEYS_ISO, + 108, + 6, + 26, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_1, 0x11 }, + { KEY_EN_ISO_BACK_SLASH, 0x0C }, + { KEY_EN_LEFT_WINDOWS, 0x0D }, + + { KEY_EN_F1, 0x18 }, + { KEY_EN_2, 0x19 }, + { KEY_EN_Q, 0x12 }, + { KEY_EN_A, 0x13 }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x15 }, + + { KEY_EN_F2, 0x20 }, + { KEY_EN_3, 0x21 }, + { KEY_EN_W, 0x1A }, + { KEY_EN_S, 0x1B }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F3, 0x28 }, + { KEY_EN_4, 0x29 }, + { KEY_EN_E, 0x22 }, + { KEY_EN_D, 0x23 }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F4, 0x30 }, + { KEY_EN_5, 0x31 }, + { KEY_EN_R, 0x2A }, + { KEY_EN_F, 0x2B }, + { KEY_EN_V, 0x2C }, + + { KEY_EN_6, 0x39 }, + { KEY_EN_T, 0x32 }, + { KEY_EN_G, 0x33 }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F5, 0x40 }, + { KEY_EN_7, 0x41 }, + { KEY_EN_Y, 0x3A }, + { KEY_EN_H, 0x3B }, + { KEY_EN_N, 0x3C }, + + { KEY_EN_F6, 0x48 }, + { KEY_EN_8, 0x49 }, + { KEY_EN_U, 0x42 }, + { KEY_EN_J, 0x43 }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F7, 0x50 }, + { KEY_EN_9, 0x51 }, + { KEY_EN_I, 0x4A }, + { KEY_EN_K, 0x4B }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F8, 0x58 }, + { KEY_EN_0, 0x59 }, + { KEY_EN_O, 0x52 }, + { KEY_EN_L, 0x53 }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x4D }, + + { KEY_EN_F9, 0x60 }, + { KEY_EN_MINUS, 0x61 }, + { KEY_EN_P, 0x5A }, + { KEY_EN_SEMICOLON, 0x5B }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F10, 0x68 }, + { KEY_EN_EQUALS, 0x69 }, + { KEY_EN_LEFT_BRACKET, 0x62 }, + { KEY_EN_QUOTE, 0x63 }, + { KEY_EN_MENU, 0x65 }, + + { KEY_EN_F11, 0x70 }, + { KEY_EN_BACKSPACE, 0x79 }, + { KEY_EN_RIGHT_BRACKET, 0x6A }, + { KEY_EN_POUND, 0x6B }, + { KEY_EN_RIGHT_SHIFT, 0x7C }, + + { KEY_EN_F12, 0x78 }, + { KEY_EN_ISO_ENTER, 0x7B }, + { KEY_EN_RIGHT_CONTROL, 0x7D }, + + { KEY_EN_PRINT_SCREEN, 0x80 }, + { KEY_EN_INSERT, 0x81 }, + { KEY_EN_DELETE, 0x82 }, + { KEY_EN_LEFT_ARROW, 0x85 }, + + { KEY_EN_SCROLL_LOCK, 0x88 }, + { KEY_EN_HOME, 0x89 }, + { KEY_EN_END, 0x8A }, + { KEY_EN_UP_ARROW, 0x8C }, + { KEY_EN_DOWN_ARROW, 0x8D }, + + { KEY_EN_PAUSE_BREAK, 0x90 }, + { KEY_EN_PAGE_UP, 0x91 }, + { KEY_EN_PAGE_DOWN, 0x92 }, + { KEY_EN_RIGHT_ARROW, 0x95 }, + + { KEY_EN_NUMPAD_LOCK, 0x99 }, + { KEY_EN_NUMPAD_7, 0x9A }, + { KEY_EN_NUMPAD_4, 0x9B }, + { KEY_EN_NUMPAD_1, 0x9C }, + { KEY_EN_NUMPAD_0, 0x9D }, + + { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, + { KEY_EN_NUMPAD_8, 0xA2 }, + { KEY_EN_NUMPAD_5, 0xA3 }, + { KEY_EN_NUMPAD_2, 0xA4 }, + + { KEY_EN_NUMPAD_TIMES, 0xA9 }, + { KEY_EN_NUMPAD_9, 0xAA }, + { KEY_EN_NUMPAD_6, 0xAB }, + { KEY_EN_NUMPAD_3, 0xAC }, + { KEY_EN_NUMPAD_PERIOD, 0xAD }, + + { KEY_EN_NUMPAD_MINUS, 0xB1 }, + { KEY_EN_NUMPAD_PLUS, 0xB2 }, + { KEY_EN_NUMPAD_ENTER, 0xB4 }, + + { "Logo", 0xB8 }, + { "Underglow left", 0xB9 }, + { "Underglow right", 0xBA } + } + } + }, + { + ASUS_TUF_K7_LAYOUT_US, + { + *ASUS_ROG_STRIX_FLARE_LAYOUT_KEYS_ANSI, + 107, + 6, + 26, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_1, 0x11 }, + { KEY_EN_LEFT_WINDOWS, 0x0D }, + + { KEY_EN_F1, 0x18 }, + { KEY_EN_2, 0x19 }, + { KEY_EN_Q, 0x12 }, + { KEY_EN_A, 0x13 }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x15 }, + + { KEY_EN_F2, 0x20 }, + { KEY_EN_3, 0x21 }, + { KEY_EN_W, 0x1A }, + { KEY_EN_S, 0x1B }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F3, 0x28 }, + { KEY_EN_4, 0x29 }, + { KEY_EN_E, 0x22 }, + { KEY_EN_D, 0x23 }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F4, 0x30 }, + { KEY_EN_5, 0x31 }, + { KEY_EN_R, 0x2A }, + { KEY_EN_F, 0x2B }, + { KEY_EN_V, 0x2C }, + + { KEY_EN_6, 0x39 }, + { KEY_EN_T, 0x32 }, + { KEY_EN_G, 0x33 }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F5, 0x40 }, + { KEY_EN_7, 0x41 }, + { KEY_EN_Y, 0x3A }, + { KEY_EN_H, 0x3B }, + { KEY_EN_N, 0x3C }, + + { KEY_EN_F6, 0x48 }, + { KEY_EN_8, 0x49 }, + { KEY_EN_U, 0x42 }, + { KEY_EN_J, 0x43 }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F7, 0x50 }, + { KEY_EN_9, 0x51 }, + { KEY_EN_I, 0x4A }, + { KEY_EN_K, 0x4B }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F8, 0x58 }, + { KEY_EN_0, 0x59 }, + { KEY_EN_O, 0x52 }, + { KEY_EN_L, 0x53 }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x4D }, + + { KEY_EN_F9, 0x60 }, + { KEY_EN_MINUS, 0x61 }, + { KEY_EN_P, 0x5A }, + { KEY_EN_SEMICOLON, 0x5B }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F10, 0x68 }, + { KEY_EN_EQUALS, 0x69 }, + { KEY_EN_LEFT_BRACKET, 0x62 }, + { KEY_EN_QUOTE, 0x63 }, + { KEY_EN_MENU, 0x65 }, + + { KEY_EN_F11, 0x70 }, + { KEY_EN_BACKSPACE, 0x79 }, + { KEY_EN_RIGHT_BRACKET, 0x6A }, + { KEY_EN_RIGHT_SHIFT, 0x7C }, + + { KEY_EN_F12, 0x78 }, + { KEY_EN_ANSI_BACK_SLASH, 0x7A }, + { KEY_EN_ANSI_ENTER, 0x7B }, + { KEY_EN_RIGHT_CONTROL, 0x7D }, + + { KEY_EN_PRINT_SCREEN, 0x80 }, + { KEY_EN_INSERT, 0x81 }, + { KEY_EN_DELETE, 0x82 }, + { KEY_EN_LEFT_ARROW, 0x85 }, + + { KEY_EN_SCROLL_LOCK, 0x88 }, + { KEY_EN_HOME, 0x89 }, + { KEY_EN_END, 0x8A }, + { KEY_EN_UP_ARROW, 0x8C }, + { KEY_EN_DOWN_ARROW, 0x8D }, + + { KEY_EN_PAUSE_BREAK, 0x90 }, + { KEY_EN_PAGE_UP, 0x91 }, + { KEY_EN_PAGE_DOWN, 0x92 }, + { KEY_EN_RIGHT_ARROW, 0x95 }, + + { KEY_EN_NUMPAD_LOCK, 0x99 }, + { KEY_EN_NUMPAD_7, 0x9A }, + { KEY_EN_NUMPAD_4, 0x9B }, + { KEY_EN_NUMPAD_1, 0x9C }, + { KEY_EN_NUMPAD_0, 0x9D }, + + { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, + { KEY_EN_NUMPAD_8, 0xA2 }, + { KEY_EN_NUMPAD_5, 0xA3 }, + { KEY_EN_NUMPAD_2, 0xA4 }, + + { KEY_EN_NUMPAD_TIMES, 0xA9 }, + { KEY_EN_NUMPAD_9, 0xAA }, + { KEY_EN_NUMPAD_6, 0xAB }, + { KEY_EN_NUMPAD_3, 0xAC }, + { KEY_EN_NUMPAD_PERIOD, 0xAD }, + + { KEY_EN_NUMPAD_MINUS, 0xB1 }, + { KEY_EN_NUMPAD_PLUS, 0xB2 }, + { KEY_EN_NUMPAD_ENTER, 0xB4 }, + + { "Logo", 0xB8 }, + { "Underglow left", 0xB9 }, + { "Underglow right", 0xBA } + } + } + }, +}; + +static std::map AsusROGStrixFlareIILayouts = +{ + { + ASUS_TUF_K7_LAYOUT_UK, + { + *ASUS_ROG_STRIX_FLARE_II_LAYOUT_KEYS_ISO, + 107, + 7, + 30, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_1, 0x11 }, + { KEY_EN_ISO_BACK_SLASH, 0x0C }, + { KEY_EN_LEFT_WINDOWS, 0x15 }, + + { KEY_EN_F1, 0x18 }, + { KEY_EN_2, 0x19 }, + { KEY_EN_Q, 0x12 }, + { KEY_EN_A, 0x13 }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x1D }, + + { KEY_EN_F2, 0x20 }, + { KEY_EN_3, 0x21 }, + { KEY_EN_W, 0x1A }, + { KEY_EN_S, 0x1B }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F3, 0x28 }, + { KEY_EN_4, 0x29 }, + { KEY_EN_E, 0x22 }, + { KEY_EN_D, 0x23 }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F4, 0x30 }, + { KEY_EN_5, 0x31 }, + { KEY_EN_R, 0x2A }, + { KEY_EN_F, 0x2B }, + { KEY_EN_V, 0x2C }, + + { KEY_EN_6, 0x39 }, + { KEY_EN_T, 0x32 }, + { KEY_EN_G, 0x33 }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F5, 0x40 }, + { KEY_EN_7, 0x41 }, + { KEY_EN_Y, 0x3A }, + { KEY_EN_H, 0x3B }, + { KEY_EN_N, 0x3C }, + + { KEY_EN_F6, 0x48 }, + { KEY_EN_8, 0x49 }, + { KEY_EN_U, 0x42 }, + { KEY_EN_J, 0x43 }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F7, 0x50 }, + { KEY_EN_9, 0x51 }, + { KEY_EN_I, 0x4A }, + { KEY_EN_K, 0x4B }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F8, 0x58 }, + { KEY_EN_0, 0x59 }, + { KEY_EN_O, 0x52 }, + { KEY_EN_L, 0x53 }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x4D }, + + { KEY_EN_F9, 0x60 }, + { KEY_EN_MINUS, 0x61 }, + { KEY_EN_P, 0x5A }, + { KEY_EN_SEMICOLON, 0x5B }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F10, 0x68 }, + { KEY_EN_EQUALS, 0x69 }, + { KEY_EN_LEFT_BRACKET, 0x62 }, + { KEY_EN_QUOTE, 0x63 }, + { KEY_EN_MENU, 0x65 }, + + { KEY_EN_F11, 0x70 }, + { KEY_EN_BACKSPACE, 0x79 }, + { KEY_EN_RIGHT_BRACKET, 0x6A }, + { KEY_EN_POUND, 0x6B }, + { KEY_EN_RIGHT_SHIFT, 0x7C }, + + { KEY_EN_F12, 0x78 }, + { KEY_EN_ISO_ENTER, 0x7B }, + { KEY_EN_RIGHT_CONTROL, 0x7D }, + + { KEY_EN_PRINT_SCREEN, 0x80 }, + { KEY_EN_INSERT, 0x81 }, + { KEY_EN_DELETE, 0x82 }, + { KEY_EN_LEFT_ARROW, 0x85 }, + + { KEY_EN_SCROLL_LOCK, 0x88 }, + { KEY_EN_HOME, 0x89 }, + { KEY_EN_END, 0x8A }, + { KEY_EN_UP_ARROW, 0x8C }, + { KEY_EN_DOWN_ARROW, 0x8D }, + + { KEY_EN_PAUSE_BREAK, 0x90 }, + { KEY_EN_PAGE_UP, 0x91 }, + { KEY_EN_PAGE_DOWN, 0x92 }, + { KEY_EN_RIGHT_ARROW, 0x95 }, + + { KEY_EN_NUMPAD_LOCK, 0x99 }, + { KEY_EN_NUMPAD_7, 0x9A }, + { KEY_EN_NUMPAD_4, 0x9B }, + { KEY_EN_NUMPAD_1, 0x9C }, + { KEY_EN_NUMPAD_0, 0x9D }, + + { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, + { KEY_EN_NUMPAD_8, 0xA2 }, + { KEY_EN_NUMPAD_5, 0xA3 }, + { KEY_EN_NUMPAD_2, 0xA4 }, + + { KEY_EN_NUMPAD_TIMES, 0xA9 }, + { KEY_EN_NUMPAD_9, 0xAA }, + { KEY_EN_NUMPAD_6, 0xAB }, + { KEY_EN_NUMPAD_3, 0xAC }, + { KEY_EN_NUMPAD_PERIOD, 0xAD }, + + { KEY_EN_NUMPAD_MINUS, 0xB1 }, + { KEY_EN_NUMPAD_PLUS, 0xB2 }, + { KEY_EN_NUMPAD_ENTER, 0xB4 }, + + { "Logo 1", 0xB0 }, + { "Logo 2", 0xA8 }, + } + } + }, + { + ASUS_TUF_K7_LAYOUT_US, + { + *ASUS_ROG_STRIX_FLARE_II_LAYOUT_KEYS_ANSI, + 106, + 7, + 30, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_1, 0x11 }, + { KEY_EN_LEFT_WINDOWS, 0x15 }, + + { KEY_EN_F1, 0x18 }, + { KEY_EN_2, 0x19 }, + { KEY_EN_Q, 0x12 }, + { KEY_EN_A, 0x13 }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x1D }, + + { KEY_EN_F2, 0x20 }, + { KEY_EN_3, 0x21 }, + { KEY_EN_W, 0x1A }, + { KEY_EN_S, 0x1B }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F3, 0x28 }, + { KEY_EN_4, 0x29 }, + { KEY_EN_E, 0x22 }, + { KEY_EN_D, 0x23 }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F4, 0x30 }, + { KEY_EN_5, 0x31 }, + { KEY_EN_R, 0x2A }, + { KEY_EN_F, 0x2B }, + { KEY_EN_V, 0x2C }, + + { KEY_EN_6, 0x39 }, + { KEY_EN_T, 0x32 }, + { KEY_EN_G, 0x33 }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F5, 0x40 }, + { KEY_EN_7, 0x41 }, + { KEY_EN_Y, 0x3A }, + { KEY_EN_H, 0x3B }, + { KEY_EN_N, 0x3C }, + + { KEY_EN_F6, 0x48 }, + { KEY_EN_8, 0x49 }, + { KEY_EN_U, 0x42 }, + { KEY_EN_J, 0x43 }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F7, 0x50 }, + { KEY_EN_9, 0x51 }, + { KEY_EN_I, 0x4A }, + { KEY_EN_K, 0x4B }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F8, 0x58 }, + { KEY_EN_0, 0x59 }, + { KEY_EN_O, 0x52 }, + { KEY_EN_L, 0x53 }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x4D }, + + { KEY_EN_F9, 0x60 }, + { KEY_EN_MINUS, 0x61 }, + { KEY_EN_P, 0x5A }, + { KEY_EN_SEMICOLON, 0x5B }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F10, 0x68 }, + { KEY_EN_EQUALS, 0x69 }, + { KEY_EN_LEFT_BRACKET, 0x62 }, + { KEY_EN_QUOTE, 0x63 }, + { KEY_EN_MENU, 0x65 }, + + { KEY_EN_F11, 0x70 }, + { KEY_EN_BACKSPACE, 0x79 }, + { KEY_EN_RIGHT_BRACKET, 0x6A }, + { KEY_EN_RIGHT_SHIFT, 0x7C }, + + { KEY_EN_F12, 0x78 }, + { KEY_EN_ANSI_BACK_SLASH, 0x7A }, + { KEY_EN_ANSI_ENTER, 0x7B }, + { KEY_EN_RIGHT_CONTROL, 0x7D }, + + { KEY_EN_PRINT_SCREEN, 0x80 }, + { KEY_EN_INSERT, 0x81 }, + { KEY_EN_DELETE, 0x82 }, + { KEY_EN_LEFT_ARROW, 0x85 }, + + { KEY_EN_SCROLL_LOCK, 0x88 }, + { KEY_EN_HOME, 0x89 }, + { KEY_EN_END, 0x8A }, + { KEY_EN_UP_ARROW, 0x8C }, + { KEY_EN_DOWN_ARROW, 0x8D }, + + { KEY_EN_PAUSE_BREAK, 0x90 }, + { KEY_EN_PAGE_UP, 0x91 }, + { KEY_EN_PAGE_DOWN, 0x92 }, + { KEY_EN_RIGHT_ARROW, 0x95 }, + + { KEY_EN_NUMPAD_LOCK, 0x99 }, + { KEY_EN_NUMPAD_7, 0x9A }, + { KEY_EN_NUMPAD_4, 0x9B }, + { KEY_EN_NUMPAD_1, 0x9C }, + { KEY_EN_NUMPAD_0, 0x9D }, + + { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, + { KEY_EN_NUMPAD_8, 0xA2 }, + { KEY_EN_NUMPAD_5, 0xA3 }, + { KEY_EN_NUMPAD_2, 0xA4 }, + + { KEY_EN_NUMPAD_TIMES, 0xA9 }, + { KEY_EN_NUMPAD_9, 0xAA }, + { KEY_EN_NUMPAD_6, 0xAB }, + { KEY_EN_NUMPAD_3, 0xAC }, + { KEY_EN_NUMPAD_PERIOD, 0xAD }, + + { KEY_EN_NUMPAD_MINUS, 0xB1 }, + { KEY_EN_NUMPAD_PLUS, 0xB2 }, + { KEY_EN_NUMPAD_ENTER, 0xB4 }, + + { "Logo 1", 0xB0 }, + { "Logo 2", 0xA8 }, + } + } + }, +}; + +static std::map AsusROGStrixFlareIIAnimateLayouts = +{ + { + ASUS_TUF_K7_LAYOUT_UK, + { + *ASUS_ROG_STRIX_FLARE_II_ANIMATE_LAYOUT_KEYS_ISO, + 135, + 7, + 30, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_1, 0x11 }, + { KEY_EN_ISO_BACK_SLASH, 0x0C }, + { KEY_EN_LEFT_WINDOWS, 0x15 }, + + { KEY_EN_F1, 0x18 }, + { KEY_EN_2, 0x19 }, + { KEY_EN_Q, 0x12 }, + { KEY_EN_A, 0x13 }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x1D }, + + { KEY_EN_F2, 0x20 }, + { KEY_EN_3, 0x21 }, + { KEY_EN_W, 0x1A }, + { KEY_EN_S, 0x1B }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F3, 0x28 }, + { KEY_EN_4, 0x29 }, + { KEY_EN_E, 0x22 }, + { KEY_EN_D, 0x23 }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F4, 0x30 }, + { KEY_EN_5, 0x31 }, + { KEY_EN_R, 0x2A }, + { KEY_EN_F, 0x2B }, + { KEY_EN_V, 0x2C }, + + { KEY_EN_6, 0x39 }, + { KEY_EN_T, 0x32 }, + { KEY_EN_G, 0x33 }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F5, 0x40 }, + { KEY_EN_7, 0x41 }, + { KEY_EN_Y, 0x3A }, + { KEY_EN_H, 0x3B }, + { KEY_EN_N, 0x3C }, + + { KEY_EN_F6, 0x48 }, + { KEY_EN_8, 0x49 }, + { KEY_EN_U, 0x42 }, + { KEY_EN_J, 0x43 }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F7, 0x50 }, + { KEY_EN_9, 0x51 }, + { KEY_EN_I, 0x4A }, + { KEY_EN_K, 0x4B }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F8, 0x58 }, + { KEY_EN_0, 0x59 }, + { KEY_EN_O, 0x52 }, + { KEY_EN_L, 0x53 }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x4D }, + + { KEY_EN_F9, 0x60 }, + { KEY_EN_MINUS, 0x61 }, + { KEY_EN_P, 0x5A }, + { KEY_EN_SEMICOLON, 0x5B }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F10, 0x68 }, + { KEY_EN_EQUALS, 0x69 }, + { KEY_EN_LEFT_BRACKET, 0x62 }, + { KEY_EN_QUOTE, 0x63 }, + { KEY_EN_MENU, 0x65 }, + + { KEY_EN_F11, 0x70 }, + { KEY_EN_BACKSPACE, 0x79 }, + { KEY_EN_RIGHT_BRACKET, 0x6A }, + { KEY_EN_POUND, 0x6B }, + { KEY_EN_RIGHT_SHIFT, 0x7C }, + + { KEY_EN_F12, 0x78 }, + { KEY_EN_ISO_ENTER, 0x7B }, + { KEY_EN_RIGHT_CONTROL, 0x7D }, + + { KEY_EN_PRINT_SCREEN, 0x80 }, + { KEY_EN_INSERT, 0x81 }, + { KEY_EN_DELETE, 0x82 }, + { KEY_EN_LEFT_ARROW, 0x85 }, + + { KEY_EN_SCROLL_LOCK, 0x88 }, + { KEY_EN_HOME, 0x89 }, + { KEY_EN_END, 0x8A }, + { KEY_EN_UP_ARROW, 0x8C }, + { KEY_EN_DOWN_ARROW, 0x8D }, + + { KEY_EN_PAUSE_BREAK, 0x90 }, + { KEY_EN_PAGE_UP, 0x91 }, + { KEY_EN_PAGE_DOWN, 0x92 }, + { KEY_EN_RIGHT_ARROW, 0x95 }, + + { KEY_EN_NUMPAD_LOCK, 0x99 }, + { KEY_EN_NUMPAD_7, 0x9A }, + { KEY_EN_NUMPAD_4, 0x9B }, + { KEY_EN_NUMPAD_1, 0x9C }, + { KEY_EN_NUMPAD_0, 0x9D }, + + { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, + { KEY_EN_NUMPAD_8, 0xA2 }, + { KEY_EN_NUMPAD_5, 0xA3 }, + { KEY_EN_NUMPAD_2, 0xA4 }, + + { KEY_EN_NUMPAD_TIMES, 0xA9 }, + { KEY_EN_NUMPAD_9, 0xAA }, + { KEY_EN_NUMPAD_6, 0xAB }, + { KEY_EN_NUMPAD_3, 0xAC }, + { KEY_EN_NUMPAD_PERIOD, 0xAD }, + + { KEY_EN_NUMPAD_MINUS, 0xB1 }, + { KEY_EN_NUMPAD_PLUS, 0xB2 }, + { KEY_EN_NUMPAD_ENTER, 0xB4 }, + + { "Underglow LED 1", 0x06 }, + { "Underglow LED 2", 0x0E }, + { "Underglow LED 3", 0x16 }, + { "Underglow LED 4", 0x1E }, + { "Underglow LED 5", 0x26 }, + { "Underglow LED 6", 0x2E }, + { "Underglow LED 7", 0x36 }, + { "Underglow LED 8", 0x3E }, + { "Underglow LED 9", 0x46 }, + { "Underglow LED 10", 0x4E }, + { "Underglow LED 11", 0x56 }, + { "Underglow LED 12", 0x5E }, + { "Underglow LED 13", 0x66 }, + { "Underglow LED 14", 0x6E }, + { "Underglow LED 15", 0x76 }, + { "Underglow LED 16", 0x7E }, + { "Underglow LED 17", 0x86 }, + { "Underglow LED 18", 0x8E }, + { "Underglow LED 19", 0x96 }, + { "Underglow LED 20", 0x9E }, + { "Underglow LED 21", 0xA6 }, + { "Underglow LED 22", 0xAE }, + { "Underglow LED 23", 0xB6 }, + { "Underglow LED 24", 0xBE }, + { "Underglow LED 25", 0xC6 }, + { "Underglow LED 26", 0xCE }, + { "Underglow LED 27", 0xD6 }, + { "Underglow LED 28", 0xDE }, + { "Underglow LED 29", 0xE6 }, + { "Underglow LED 30", 0xEE }, + } + } + }, + { + ASUS_TUF_K7_LAYOUT_US, + { + *ASUS_ROG_STRIX_FLARE_II_ANIMATE_LAYOUT_KEYS_ANSI, + 134, + 7, + 30, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_1, 0x11 }, + { KEY_EN_LEFT_WINDOWS, 0x15 }, + + { KEY_EN_F1, 0x18 }, + { KEY_EN_2, 0x19 }, + { KEY_EN_Q, 0x12 }, + { KEY_EN_A, 0x13 }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x1D }, + + { KEY_EN_F2, 0x20 }, + { KEY_EN_3, 0x21 }, + { KEY_EN_W, 0x1A }, + { KEY_EN_S, 0x1B }, + { KEY_EN_X, 0x1C }, + + { KEY_EN_F3, 0x28 }, + { KEY_EN_4, 0x29 }, + { KEY_EN_E, 0x22 }, + { KEY_EN_D, 0x23 }, + { KEY_EN_C, 0x24 }, + + { KEY_EN_F4, 0x30 }, + { KEY_EN_5, 0x31 }, + { KEY_EN_R, 0x2A }, + { KEY_EN_F, 0x2B }, + { KEY_EN_V, 0x2C }, + + { KEY_EN_6, 0x39 }, + { KEY_EN_T, 0x32 }, + { KEY_EN_G, 0x33 }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x35 }, + + { KEY_EN_F5, 0x40 }, + { KEY_EN_7, 0x41 }, + { KEY_EN_Y, 0x3A }, + { KEY_EN_H, 0x3B }, + { KEY_EN_N, 0x3C }, + + { KEY_EN_F6, 0x48 }, + { KEY_EN_8, 0x49 }, + { KEY_EN_U, 0x42 }, + { KEY_EN_J, 0x43 }, + { KEY_EN_M, 0x44 }, + + { KEY_EN_F7, 0x50 }, + { KEY_EN_9, 0x51 }, + { KEY_EN_I, 0x4A }, + { KEY_EN_K, 0x4B }, + { KEY_EN_COMMA, 0x4C }, + + { KEY_EN_F8, 0x58 }, + { KEY_EN_0, 0x59 }, + { KEY_EN_O, 0x52 }, + { KEY_EN_L, 0x53 }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x4D }, + + { KEY_EN_F9, 0x60 }, + { KEY_EN_MINUS, 0x61 }, + { KEY_EN_P, 0x5A }, + { KEY_EN_SEMICOLON, 0x5B }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x5D }, + + { KEY_EN_F10, 0x68 }, + { KEY_EN_EQUALS, 0x69 }, + { KEY_EN_LEFT_BRACKET, 0x62 }, + { KEY_EN_QUOTE, 0x63 }, + { KEY_EN_MENU, 0x65 }, + + { KEY_EN_F11, 0x70 }, + { KEY_EN_BACKSPACE, 0x79 }, + { KEY_EN_RIGHT_BRACKET, 0x6A }, + { KEY_EN_RIGHT_SHIFT, 0x7C }, + + { KEY_EN_F12, 0x78 }, + { KEY_EN_ANSI_BACK_SLASH, 0x7A }, + { KEY_EN_ANSI_ENTER, 0x7B }, + { KEY_EN_RIGHT_CONTROL, 0x7D }, + + { KEY_EN_PRINT_SCREEN, 0x80 }, + { KEY_EN_INSERT, 0x81 }, + { KEY_EN_DELETE, 0x82 }, + { KEY_EN_LEFT_ARROW, 0x85 }, + + { KEY_EN_SCROLL_LOCK, 0x88 }, + { KEY_EN_HOME, 0x89 }, + { KEY_EN_END, 0x8A }, + { KEY_EN_UP_ARROW, 0x8C }, + { KEY_EN_DOWN_ARROW, 0x8D }, + + { KEY_EN_PAUSE_BREAK, 0x90 }, + { KEY_EN_PAGE_UP, 0x91 }, + { KEY_EN_PAGE_DOWN, 0x92 }, + { KEY_EN_RIGHT_ARROW, 0x95 }, + + { KEY_EN_NUMPAD_LOCK, 0x99 }, + { KEY_EN_NUMPAD_7, 0x9A }, + { KEY_EN_NUMPAD_4, 0x9B }, + { KEY_EN_NUMPAD_1, 0x9C }, + { KEY_EN_NUMPAD_0, 0x9D }, + + { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, + { KEY_EN_NUMPAD_8, 0xA2 }, + { KEY_EN_NUMPAD_5, 0xA3 }, + { KEY_EN_NUMPAD_2, 0xA4 }, + + { KEY_EN_NUMPAD_TIMES, 0xA9 }, + { KEY_EN_NUMPAD_9, 0xAA }, + { KEY_EN_NUMPAD_6, 0xAB }, + { KEY_EN_NUMPAD_3, 0xAC }, + { KEY_EN_NUMPAD_PERIOD, 0xAD }, + + { KEY_EN_NUMPAD_MINUS, 0xB1 }, + { KEY_EN_NUMPAD_PLUS, 0xB2 }, + { KEY_EN_NUMPAD_ENTER, 0xB4 }, + + { "Underglow LED 1", 0x06 }, + { "Underglow LED 2", 0x0E }, + { "Underglow LED 3", 0x16 }, + { "Underglow LED 4", 0x1E }, + { "Underglow LED 5", 0x26 }, + { "Underglow LED 6", 0x2E }, + { "Underglow LED 7", 0x36 }, + { "Underglow LED 8", 0x3E }, + { "Underglow LED 9", 0x46 }, + { "Underglow LED 10", 0x4E }, + { "Underglow LED 11", 0x56 }, + { "Underglow LED 12", 0x5E }, + { "Underglow LED 13", 0x66 }, + { "Underglow LED 14", 0x6E }, + { "Underglow LED 15", 0x76 }, + { "Underglow LED 16", 0x7E }, + { "Underglow LED 17", 0x86 }, + { "Underglow LED 18", 0x8E }, + { "Underglow LED 19", 0x96 }, + { "Underglow LED 20", 0x9E }, + { "Underglow LED 21", 0xA6 }, + { "Underglow LED 22", 0xAE }, + { "Underglow LED 23", 0xB6 }, + { "Underglow LED 24", 0xBE }, + { "Underglow LED 25", 0xC6 }, + { "Underglow LED 26", 0xCE }, + { "Underglow LED 27", 0xD6 }, + { "Underglow LED 28", 0xDE }, + { "Underglow LED 29", 0xE6 }, + { "Underglow LED 30", 0xEE }, + } + } + }, +}; + +static std::map AsusFalchionLayouts = +{ + { + ASUS_TUF_K7_LAYOUT_UK, + { + *ASUS_FALCHION_LAYOUT_KEYS_ISO, + 69, + 5, + 16, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_TAB, 0x01 }, + { KEY_EN_CAPS_LOCK, 0x02 }, + { KEY_EN_LEFT_SHIFT, 0x03 }, + { KEY_EN_LEFT_CONTROL, 0x04 }, + + { KEY_EN_1, 0x08 }, + { KEY_EN_ISO_BACK_SLASH, 0x0B }, + { KEY_EN_LEFT_WINDOWS, 0x0C }, + + { KEY_EN_2, 0x10 }, + { KEY_EN_Q, 0x09 }, + { KEY_EN_A, 0x0A }, + { KEY_EN_Z, 0x13 }, + { KEY_EN_LEFT_ALT, 0x14 }, + + { KEY_EN_3, 0x18 }, + { KEY_EN_W, 0x11 }, + { KEY_EN_S, 0x12 }, + { KEY_EN_X, 0x1B }, + + { KEY_EN_4, 0x20 }, + { KEY_EN_E, 0x19 }, + { KEY_EN_D, 0x1A }, + { KEY_EN_C, 0x23 }, + + { KEY_EN_5, 0x28 }, + { KEY_EN_R, 0x21 }, + { KEY_EN_F, 0x22 }, + { KEY_EN_V, 0x2B }, + + { KEY_EN_6, 0x30 }, + { KEY_EN_T, 0x29 }, + { KEY_EN_G, 0x2A }, + { KEY_EN_B, 0x33 }, + { KEY_EN_SPACE, 0x34 }, + + { KEY_EN_7, 0x38 }, + { KEY_EN_Y, 0x31 }, + { KEY_EN_H, 0x32 }, + { KEY_EN_N, 0x3B }, + + { KEY_EN_8, 0x40 }, + { KEY_EN_U, 0x39 }, + { KEY_EN_J, 0x3A }, + { KEY_EN_M, 0x43 }, + + { KEY_EN_9, 0x48 }, + { KEY_EN_I, 0x41 }, + { KEY_EN_K, 0x42 }, + { KEY_EN_COMMA, 0x4B }, + + { KEY_EN_0, 0x50 }, + { KEY_EN_O, 0x49 }, + { KEY_EN_L, 0x4A }, + { KEY_EN_PERIOD, 0x53 }, + { KEY_EN_RIGHT_ALT, 0x4C }, + + { KEY_EN_MINUS, 0x58 }, + { KEY_EN_P, 0x51 }, + { KEY_EN_SEMICOLON, 0x52 }, + { KEY_EN_FORWARD_SLASH, 0x5B }, + { KEY_EN_RIGHT_FUNCTION, 0x54 }, + + { KEY_EN_EQUALS, 0x60 }, + { KEY_EN_LEFT_BRACKET, 0x59 }, + { KEY_EN_QUOTE, 0x5A }, + { KEY_EN_RIGHT_SHIFT, 0x63 }, + { KEY_EN_RIGHT_CONTROL, 0x5C }, + + { KEY_EN_BACKSPACE, 0x68 }, + { KEY_EN_RIGHT_BRACKET, 0x61 }, + { KEY_EN_POUND, 0x62 }, + { KEY_EN_LEFT_ARROW, 0x64 }, + + { KEY_EN_ISO_ENTER, 0x6A }, + { KEY_EN_UP_ARROW, 0x6B }, + { KEY_EN_DOWN_ARROW, 0x6C }, + + { KEY_EN_INSERT, 0x70 }, + { KEY_EN_DELETE, 0x71 }, + { KEY_EN_PAGE_UP, 0x72 }, + { KEY_EN_PAGE_DOWN, 0x73 }, + { KEY_EN_RIGHT_ARROW, 0x74 }, + } + } + }, + { + ASUS_TUF_K7_LAYOUT_US, + { + *ASUS_FALCHION_LAYOUT_KEYS_ANSI, + 68, + 5, + 16, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_TAB, 0x01 }, + { KEY_EN_CAPS_LOCK, 0x02 }, + { KEY_EN_LEFT_SHIFT, 0x03 }, + { KEY_EN_LEFT_CONTROL, 0x04 }, + + { KEY_EN_1, 0x08 }, + { KEY_EN_LEFT_WINDOWS, 0x0C }, + + { KEY_EN_2, 0x10 }, + { KEY_EN_Q, 0x09 }, + { KEY_EN_A, 0x0A }, + { KEY_EN_Z, 0x13 }, + { KEY_EN_LEFT_ALT, 0x14 }, + + { KEY_EN_3, 0x18 }, + { KEY_EN_W, 0x11 }, + { KEY_EN_S, 0x12 }, + { KEY_EN_X, 0x1B }, + + { KEY_EN_4, 0x20 }, + { KEY_EN_E, 0x19 }, + { KEY_EN_D, 0x1A }, + { KEY_EN_C, 0x23 }, + + { KEY_EN_5, 0x28 }, + { KEY_EN_R, 0x21 }, + { KEY_EN_F, 0x22 }, + { KEY_EN_V, 0x2B }, + + { KEY_EN_6, 0x30 }, + { KEY_EN_T, 0x29 }, + { KEY_EN_G, 0x2A }, + { KEY_EN_B, 0x33 }, + { KEY_EN_SPACE, 0x34 }, + + { KEY_EN_7, 0x38 }, + { KEY_EN_Y, 0x31 }, + { KEY_EN_H, 0x32 }, + { KEY_EN_N, 0x3B }, + + { KEY_EN_8, 0x40 }, + { KEY_EN_U, 0x39 }, + { KEY_EN_J, 0x3A }, + { KEY_EN_M, 0x43 }, + + { KEY_EN_9, 0x48 }, + { KEY_EN_I, 0x41 }, + { KEY_EN_K, 0x42 }, + { KEY_EN_COMMA, 0x4B }, + + { KEY_EN_0, 0x50 }, + { KEY_EN_O, 0x49 }, + { KEY_EN_L, 0x4A }, + { KEY_EN_PERIOD, 0x53 }, + { KEY_EN_RIGHT_ALT, 0x4C }, + + { KEY_EN_MINUS, 0x58 }, + { KEY_EN_P, 0x51 }, + { KEY_EN_SEMICOLON, 0x52 }, + { KEY_EN_FORWARD_SLASH, 0x5B }, + { KEY_EN_RIGHT_FUNCTION, 0x54 }, + + { KEY_EN_EQUALS, 0x60 }, + { KEY_EN_LEFT_BRACKET, 0x59 }, + { KEY_EN_QUOTE, 0x5A }, + { KEY_EN_RIGHT_SHIFT, 0x63 }, + { KEY_EN_RIGHT_CONTROL, 0x5C }, + + { KEY_EN_BACKSPACE, 0x68 }, + { KEY_EN_RIGHT_BRACKET, 0x61 }, + { KEY_EN_LEFT_ARROW, 0x64 }, + + { KEY_EN_ANSI_BACK_SLASH, 0x69 }, + { KEY_EN_ANSI_ENTER, 0x6A }, + { KEY_EN_UP_ARROW, 0x6B }, + { KEY_EN_DOWN_ARROW, 0x6C }, + + { KEY_EN_INSERT, 0x70 }, + { KEY_EN_DELETE, 0x71 }, + { KEY_EN_PAGE_UP, 0x72 }, + { KEY_EN_PAGE_DOWN, 0x73 }, + { KEY_EN_RIGHT_ARROW, 0x74 }, + } + } + }, +}; + + +static std::map AsusClaymoreNoNumpadLayouts = +{ + { + ASUS_TUF_K7_LAYOUT_UK, + { + *ASUS_CLAYMORE_NO_NUMPAD_LAYOUT_KEYS_ISO, + 89, + 7, + 19, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + { KEY_EN_1, 0x09 }, + { KEY_EN_ISO_BACK_SLASH, 0x0C }, + { KEY_EN_LEFT_WINDOWS, 0x0D }, + { KEY_EN_F1, 0x10 }, + { KEY_EN_2, 0x11 }, + { KEY_EN_Q, 0x0A }, + { KEY_EN_A, 0x0B }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x15 }, + { KEY_EN_F2, 0x18 }, + { KEY_EN_3, 0x19 }, + { KEY_EN_W, 0x12 }, + { KEY_EN_S, 0x13 }, + { KEY_EN_X, 0x1C }, + { KEY_EN_F3, 0x20 }, + { KEY_EN_4, 0x21 }, + { KEY_EN_E, 0x1A }, + { KEY_EN_D, 0x1B }, + { KEY_EN_C, 0x24 }, + { KEY_EN_F4, 0x28 }, + { KEY_EN_5, 0x29 }, + { KEY_EN_R, 0x22 }, + { KEY_EN_F, 0x23 }, + { KEY_EN_V, 0x2C }, + { KEY_EN_6, 0x31 }, + { KEY_EN_T, 0x2A }, + { KEY_EN_G, 0x2B }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x25 }, + { KEY_EN_F5, 0x38 }, + { KEY_EN_7, 0x39 }, + { KEY_EN_Y, 0x32 }, + { KEY_EN_H, 0x33 }, + { KEY_EN_N, 0x3C }, + { KEY_EN_F6, 0x40 }, + { KEY_EN_8, 0x41 }, + { KEY_EN_U, 0x3A }, + { KEY_EN_J, 0x3B }, + { KEY_EN_M, 0x44 }, + { "Logo", 0x45 }, + { KEY_EN_F7, 0x48 }, + { KEY_EN_9, 0x49 }, + { KEY_EN_I, 0x42 }, + { KEY_EN_K, 0x43 }, + { KEY_EN_COMMA, 0x4C }, + { KEY_EN_F8, 0x50 }, + { KEY_EN_0, 0x51 }, + { KEY_EN_O, 0x4A }, + { KEY_EN_L, 0x4B }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x4D }, + { KEY_EN_F9, 0x60 }, + { KEY_EN_MINUS, 0x59 }, + { KEY_EN_P, 0x52 }, + { KEY_EN_SEMICOLON, 0x53 }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x55 }, + { KEY_EN_F10, 0x68 }, + { KEY_EN_EQUALS, 0x61 }, + { KEY_EN_LEFT_BRACKET, 0x5A }, + { KEY_EN_QUOTE, 0x5B }, + { KEY_EN_MENU, 0x5D }, + { KEY_EN_F11, 0x70 }, + { KEY_EN_BACKSPACE, 0x69 }, + { KEY_EN_RIGHT_BRACKET, 0x62 }, + { KEY_EN_POUND, 0x63 }, + { KEY_EN_RIGHT_SHIFT, 0x6C }, + { KEY_EN_F12, 0x78 }, + { KEY_EN_ISO_ENTER, 0x6B }, + { KEY_EN_RIGHT_CONTROL, 0x6D }, + { KEY_EN_PRINT_SCREEN, 0x80 }, + { KEY_EN_INSERT, 0x81 }, + { KEY_EN_DELETE, 0x82 }, + { KEY_EN_LEFT_ARROW, 0x85 }, + { KEY_EN_SCROLL_LOCK, 0x88 }, + { KEY_EN_HOME, 0x89 }, + { KEY_EN_END, 0x8A }, + { KEY_EN_UP_ARROW, 0x8C }, + { KEY_EN_DOWN_ARROW, 0x8D }, + { KEY_EN_PAUSE_BREAK, 0x90 }, + { KEY_EN_PAGE_UP, 0x91 }, + { KEY_EN_PAGE_DOWN, 0x92 }, + { KEY_EN_RIGHT_ARROW, 0x95 } + } + } + }, + { + ASUS_TUF_K7_LAYOUT_US, + { + *ASUS_CLAYMORE_NO_NUMPAD_LAYOUT_KEYS_ANSI, + 88, + 7, + 19, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + { KEY_EN_1, 0x09 }, + { KEY_EN_LEFT_WINDOWS, 0x0D }, + { KEY_EN_F1, 0x10 }, + { KEY_EN_2, 0x11 }, + { KEY_EN_Q, 0x0A }, + { KEY_EN_A, 0x0B }, + { KEY_EN_Z, 0x0C }, + { KEY_EN_LEFT_ALT, 0x15 }, + { KEY_EN_F2, 0x18 }, + { KEY_EN_3, 0x19 }, + { KEY_EN_W, 0x12 }, + { KEY_EN_S, 0x13 }, + { KEY_EN_X, 0x14 }, + { KEY_EN_F3, 0x20 }, + { KEY_EN_4, 0x21 }, + { KEY_EN_E, 0x1A }, + { KEY_EN_D, 0x1B }, + { KEY_EN_C, 0x1C }, + { KEY_EN_F4, 0x28 }, + { KEY_EN_5, 0x29 }, + { KEY_EN_R, 0x22 }, + { KEY_EN_F, 0x23 }, + { KEY_EN_V, 0x24 }, + { KEY_EN_6, 0x31 }, + { KEY_EN_T, 0x2A }, + { KEY_EN_G, 0x2B }, + { KEY_EN_B, 0x2C }, + { KEY_EN_SPACE, 0x25 }, + { KEY_EN_F5, 0x38 }, + { KEY_EN_7, 0x39 }, + { KEY_EN_Y, 0x32 }, + { KEY_EN_H, 0x33 }, + { KEY_EN_N, 0x34 }, + { KEY_EN_F6, 0x40 }, + { KEY_EN_8, 0x41 }, + { KEY_EN_U, 0x3A }, + { KEY_EN_J, 0x3B }, + { KEY_EN_M, 0x3C }, + { "Logo", 0x3D }, + { KEY_EN_F7, 0x48 }, + { KEY_EN_9, 0x49 }, + { KEY_EN_I, 0x42 }, + { KEY_EN_K, 0x43 }, + { KEY_EN_COMMA, 0x44 }, + { KEY_EN_F8, 0x50 }, + { KEY_EN_0, 0x51 }, + { KEY_EN_O, 0x4A }, + { KEY_EN_L, 0x4B }, + { KEY_EN_PERIOD, 0x4C }, + { KEY_EN_RIGHT_ALT, 0x4D }, + { KEY_EN_F9, 0x60 }, + { KEY_EN_MINUS, 0x59 }, + { KEY_EN_P, 0x52 }, + { KEY_EN_SEMICOLON, 0x53 }, + { KEY_EN_FORWARD_SLASH, 0x54 }, + { KEY_EN_RIGHT_FUNCTION, 0x55 }, + { KEY_EN_F10, 0x68 }, + { KEY_EN_EQUALS, 0x61 }, + { KEY_EN_LEFT_BRACKET, 0x5A }, + { KEY_EN_QUOTE, 0x5B }, + { KEY_EN_MENU, 0x5D }, + { KEY_EN_F11, 0x70 }, + { KEY_EN_BACKSPACE, 0x69 }, + { KEY_EN_RIGHT_BRACKET, 0x62 }, + { KEY_EN_RIGHT_SHIFT, 0x6C }, + { KEY_EN_F12, 0x78 }, + { KEY_EN_ANSI_BACK_SLASH, 0x6A }, + { KEY_EN_ANSI_ENTER, 0x6B }, + { KEY_EN_RIGHT_CONTROL, 0x6D }, + { KEY_EN_PRINT_SCREEN, 0x80 }, + { KEY_EN_INSERT, 0x81 }, + { KEY_EN_DELETE, 0x82 }, + { KEY_EN_LEFT_ARROW, 0x85 }, + { KEY_EN_SCROLL_LOCK, 0x88 }, + { KEY_EN_HOME, 0x89 }, + { KEY_EN_END, 0x8A }, + { KEY_EN_UP_ARROW, 0x8C }, + { KEY_EN_DOWN_ARROW, 0x8D }, + { KEY_EN_PAUSE_BREAK, 0x90 }, + { KEY_EN_PAGE_UP, 0x91 }, + { KEY_EN_PAGE_DOWN, 0x92 }, + { KEY_EN_RIGHT_ARROW, 0x95 } + } + } + }, +}; + +static std::map AsusClaymoreNumpadRightLayouts = +{ + { + ASUS_TUF_K7_LAYOUT_UK, + { + *ASUS_CLAYMORE_NUMPAD_RIGHT_LAYOUT_KEYS_ISO, + 106, + 7, + 24, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + { KEY_EN_1, 0x09 }, + { KEY_EN_ISO_BACK_SLASH, 0x0C }, + { KEY_EN_LEFT_WINDOWS, 0x0D }, + { KEY_EN_F1, 0x10 }, + { KEY_EN_2, 0x11 }, + { KEY_EN_Q, 0x0A }, + { KEY_EN_A, 0x0B }, + { KEY_EN_Z, 0x14 }, + { KEY_EN_LEFT_ALT, 0x15 }, + { KEY_EN_F2, 0x18 }, + { KEY_EN_3, 0x19 }, + { KEY_EN_W, 0x12 }, + { KEY_EN_S, 0x13 }, + { KEY_EN_X, 0x1C }, + { KEY_EN_F3, 0x20 }, + { KEY_EN_4, 0x21 }, + { KEY_EN_E, 0x1A }, + { KEY_EN_D, 0x1B }, + { KEY_EN_C, 0x24 }, + { KEY_EN_F4, 0x28 }, + { KEY_EN_5, 0x29 }, + { KEY_EN_R, 0x22 }, + { KEY_EN_F, 0x23 }, + { KEY_EN_V, 0x2C }, + { KEY_EN_6, 0x31 }, + { KEY_EN_T, 0x2A }, + { KEY_EN_G, 0x2B }, + { KEY_EN_B, 0x34 }, + { KEY_EN_SPACE, 0x25 }, + { KEY_EN_F5, 0x38 }, + { KEY_EN_7, 0x39 }, + { KEY_EN_Y, 0x32 }, + { KEY_EN_H, 0x33 }, + { KEY_EN_N, 0x3C }, + { KEY_EN_F6, 0x40 }, + { KEY_EN_8, 0x41 }, + { KEY_EN_U, 0x3A }, + { KEY_EN_J, 0x3B }, + { KEY_EN_M, 0x44 }, + { "Logo", 0x45 }, + { KEY_EN_F7, 0x48 }, + { KEY_EN_9, 0x49 }, + { KEY_EN_I, 0x42 }, + { KEY_EN_K, 0x43 }, + { KEY_EN_COMMA, 0x4C }, + { KEY_EN_F8, 0x50 }, + { KEY_EN_0, 0x51 }, + { KEY_EN_O, 0x4A }, + { KEY_EN_L, 0x4B }, + { KEY_EN_PERIOD, 0x54 }, + { KEY_EN_RIGHT_ALT, 0x4D }, + { KEY_EN_F9, 0x60 }, + { KEY_EN_MINUS, 0x59 }, + { KEY_EN_P, 0x52 }, + { KEY_EN_SEMICOLON, 0x53 }, + { KEY_EN_FORWARD_SLASH, 0x5C }, + { KEY_EN_RIGHT_FUNCTION, 0x55 }, + { KEY_EN_F10, 0x68 }, + { KEY_EN_EQUALS, 0x61 }, + { KEY_EN_LEFT_BRACKET, 0x5A }, + { KEY_EN_QUOTE, 0x5B }, + { KEY_EN_MENU, 0x5D }, + { KEY_EN_F11, 0x70 }, + { KEY_EN_BACKSPACE, 0x69 }, + { KEY_EN_RIGHT_BRACKET, 0x62 }, + { KEY_EN_POUND, 0x63 }, + { KEY_EN_RIGHT_SHIFT, 0x6C }, + { KEY_EN_F12, 0x78 }, + { KEY_EN_ISO_ENTER, 0x6B }, + { KEY_EN_RIGHT_CONTROL, 0x6D }, + { KEY_EN_PRINT_SCREEN, 0x80 }, + { KEY_EN_INSERT, 0x81 }, + { KEY_EN_DELETE, 0x82 }, + { KEY_EN_LEFT_ARROW, 0x85 }, + { KEY_EN_SCROLL_LOCK, 0x88 }, + { KEY_EN_HOME, 0x89 }, + { KEY_EN_END, 0x8A }, + { KEY_EN_UP_ARROW, 0x8C }, + { KEY_EN_DOWN_ARROW, 0x8D }, + { KEY_EN_PAUSE_BREAK, 0x90 }, + { KEY_EN_PAGE_UP, 0x91 }, + { KEY_EN_PAGE_DOWN, 0x92 }, + { KEY_EN_RIGHT_ARROW, 0x95 }, + { KEY_EN_NUMPAD_LOCK, 0x99 }, + { KEY_EN_NUMPAD_7, 0x9A }, + { KEY_EN_NUMPAD_4, 0x9B }, + { KEY_EN_NUMPAD_1, 0x9C }, + { KEY_EN_NUMPAD_0, 0x9D }, + { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, + { KEY_EN_NUMPAD_8, 0xA2 }, + { KEY_EN_NUMPAD_5, 0xA3 }, + { KEY_EN_NUMPAD_2, 0xA4 }, + { KEY_EN_NUMPAD_TIMES, 0xA9 }, + { KEY_EN_NUMPAD_9, 0xAA }, + { KEY_EN_NUMPAD_6, 0xAB }, + { KEY_EN_NUMPAD_3, 0xAC }, + { KEY_EN_NUMPAD_PERIOD, 0xAD }, + { KEY_EN_NUMPAD_MINUS, 0xB1 }, + { KEY_EN_NUMPAD_PLUS, 0xB2 }, + { KEY_EN_NUMPAD_ENTER, 0xB4 } + } + } + }, + { + ASUS_TUF_K7_LAYOUT_US, + { + *ASUS_CLAYMORE_NUMPAD_RIGHT_LAYOUT_KEYS_ANSI, + 105, + 7, + 24, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + { KEY_EN_1, 0x09 }, + { KEY_EN_LEFT_WINDOWS, 0x0D }, + { KEY_EN_F1, 0x10 }, + { KEY_EN_2, 0x11 }, + { KEY_EN_Q, 0x0A }, + { KEY_EN_A, 0x0B }, + { KEY_EN_Z, 0x0C }, + { KEY_EN_LEFT_ALT, 0x15 }, + { KEY_EN_F2, 0x18 }, + { KEY_EN_3, 0x19 }, + { KEY_EN_W, 0x12 }, + { KEY_EN_S, 0x13 }, + { KEY_EN_X, 0x14 }, + { KEY_EN_F3, 0x20 }, + { KEY_EN_4, 0x21 }, + { KEY_EN_E, 0x1A }, + { KEY_EN_D, 0x1B }, + { KEY_EN_C, 0x1C }, + { KEY_EN_F4, 0x28 }, + { KEY_EN_5, 0x29 }, + { KEY_EN_R, 0x22 }, + { KEY_EN_F, 0x23 }, + { KEY_EN_V, 0x24 }, + { KEY_EN_6, 0x31 }, + { KEY_EN_T, 0x2A }, + { KEY_EN_G, 0x2B }, + { KEY_EN_B, 0x2C }, + { KEY_EN_SPACE, 0x25 }, + { KEY_EN_F5, 0x38 }, + { KEY_EN_7, 0x39 }, + { KEY_EN_Y, 0x32 }, + { KEY_EN_H, 0x33 }, + { KEY_EN_N, 0x34 }, + { KEY_EN_F6, 0x40 }, + { KEY_EN_8, 0x41 }, + { KEY_EN_U, 0x3A }, + { KEY_EN_J, 0x3B }, + { KEY_EN_M, 0x3C }, + { "Logo", 0x3D }, + { KEY_EN_F7, 0x48 }, + { KEY_EN_9, 0x49 }, + { KEY_EN_I, 0x42 }, + { KEY_EN_K, 0x43 }, + { KEY_EN_COMMA, 0x44 }, + { KEY_EN_F8, 0x50 }, + { KEY_EN_0, 0x51 }, + { KEY_EN_O, 0x4A }, + { KEY_EN_L, 0x4B }, + { KEY_EN_PERIOD, 0x4C }, + { KEY_EN_RIGHT_ALT, 0x4D }, + { KEY_EN_F9, 0x60 }, + { KEY_EN_MINUS, 0x59 }, + { KEY_EN_P, 0x52 }, + { KEY_EN_SEMICOLON, 0x53 }, + { KEY_EN_FORWARD_SLASH, 0x54 }, + { KEY_EN_RIGHT_FUNCTION, 0x55 }, + { KEY_EN_F10, 0x68 }, + { KEY_EN_EQUALS, 0x61 }, + { KEY_EN_LEFT_BRACKET, 0x5A }, + { KEY_EN_QUOTE, 0x5B }, + { KEY_EN_MENU, 0x5D }, + { KEY_EN_F11, 0x70 }, + { KEY_EN_BACKSPACE, 0x69 }, + { KEY_EN_RIGHT_BRACKET, 0x62 }, + { KEY_EN_RIGHT_SHIFT, 0x6C }, + { KEY_EN_F12, 0x78 }, + { KEY_EN_ANSI_BACK_SLASH, 0x6A }, + { KEY_EN_ANSI_ENTER, 0x6B }, + { KEY_EN_RIGHT_CONTROL, 0x6D }, + { KEY_EN_PRINT_SCREEN, 0x80 }, + { KEY_EN_INSERT, 0x81 }, + { KEY_EN_DELETE, 0x82 }, + { KEY_EN_LEFT_ARROW, 0x85 }, + { KEY_EN_SCROLL_LOCK, 0x88 }, + { KEY_EN_HOME, 0x89 }, + { KEY_EN_END, 0x8A }, + { KEY_EN_UP_ARROW, 0x8C }, + { KEY_EN_DOWN_ARROW, 0x8D }, + { KEY_EN_PAUSE_BREAK, 0x90 }, + { KEY_EN_PAGE_UP, 0x91 }, + { KEY_EN_PAGE_DOWN, 0x92 }, + { KEY_EN_RIGHT_ARROW, 0x95 }, + { KEY_EN_NUMPAD_LOCK, 0x99 }, + { KEY_EN_NUMPAD_7, 0x9A }, + { KEY_EN_NUMPAD_4, 0x9B }, + { KEY_EN_NUMPAD_1, 0x9C }, + { KEY_EN_NUMPAD_0, 0x9D }, + { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, + { KEY_EN_NUMPAD_8, 0xA2 }, + { KEY_EN_NUMPAD_5, 0xA3 }, + { KEY_EN_NUMPAD_2, 0xA4 }, + { KEY_EN_NUMPAD_TIMES, 0xA9 }, + { KEY_EN_NUMPAD_9, 0xAA }, + { KEY_EN_NUMPAD_6, 0xAB }, + { KEY_EN_NUMPAD_3, 0xAC }, + { KEY_EN_NUMPAD_PERIOD, 0xAD }, + { KEY_EN_NUMPAD_MINUS, 0xB1 }, + { KEY_EN_NUMPAD_PLUS, 0xB2 }, + { KEY_EN_NUMPAD_ENTER, 0xB4 } + } + } + }, +}; + +static std::map AsusClaymoreNumpadLeftLayouts = +{ + { + ASUS_TUF_K7_LAYOUT_UK, + { + *ASUS_CLAYMORE_NUMPAD_LEFT_LAYOUT_KEYS_ISO, + 106, + 7, + 24, + { + { KEY_EN_NUMPAD_LOCK, 0x01 }, + { KEY_EN_NUMPAD_7, 0x02 }, + { KEY_EN_NUMPAD_4, 0x03 }, + { KEY_EN_NUMPAD_1, 0x04 }, + { KEY_EN_NUMPAD_0, 0x05 }, + { KEY_EN_NUMPAD_DIVIDE, 0x09 }, + { KEY_EN_NUMPAD_8, 0x0A }, + { KEY_EN_NUMPAD_5, 0x0B }, + { KEY_EN_NUMPAD_2, 0x0C }, + { KEY_EN_NUMPAD_TIMES, 0x11 }, + { KEY_EN_NUMPAD_9, 0x12 }, + { KEY_EN_NUMPAD_6, 0x13 }, + { KEY_EN_NUMPAD_3, 0x14 }, + { KEY_EN_NUMPAD_PERIOD, 0x15 }, + { KEY_EN_NUMPAD_MINUS, 0x19 }, + { KEY_EN_NUMPAD_PLUS, 0x1A }, + { KEY_EN_NUMPAD_ENTER, 0x1C }, + { KEY_EN_ESCAPE, 0x20 }, + { KEY_EN_BACK_TICK, 0x21 }, + { KEY_EN_TAB, 0x22 }, + { KEY_EN_CAPS_LOCK, 0x23 }, + { KEY_EN_LEFT_SHIFT, 0x24 }, + { KEY_EN_LEFT_CONTROL, 0x25 }, + { KEY_EN_1, 0x29 }, + { KEY_EN_ISO_BACK_SLASH, 0x2C }, + { KEY_EN_LEFT_WINDOWS, 0x2D }, + { KEY_EN_F1, 0x30 }, + { KEY_EN_2, 0x31 }, + { KEY_EN_Q, 0x2A }, + { KEY_EN_A, 0x2B }, + { KEY_EN_Z, 0x34 }, + { KEY_EN_LEFT_ALT, 0x35 }, + { KEY_EN_F2, 0x38 }, + { KEY_EN_3, 0x39 }, + { KEY_EN_W, 0x32 }, + { KEY_EN_S, 0x33 }, + { KEY_EN_X, 0x3C }, + { KEY_EN_F3, 0x40 }, + { KEY_EN_4, 0x41 }, + { KEY_EN_E, 0x3A }, + { KEY_EN_D, 0x3B }, + { KEY_EN_C, 0x44 }, + { KEY_EN_F4, 0x48 }, + { KEY_EN_5, 0x49 }, + { KEY_EN_R, 0x42 }, + { KEY_EN_F, 0x43 }, + { KEY_EN_V, 0x4C }, + { KEY_EN_6, 0x51 }, + { KEY_EN_T, 0x4A }, + { KEY_EN_G, 0x4B }, + { KEY_EN_B, 0x54 }, + { KEY_EN_SPACE, 0x45 }, + { KEY_EN_F5, 0x58 }, + { KEY_EN_7, 0x59 }, + { KEY_EN_Y, 0x52 }, + { KEY_EN_H, 0x53 }, + { KEY_EN_N, 0x5C }, + { KEY_EN_F6, 0x60 }, + { KEY_EN_8, 0x61 }, + { KEY_EN_U, 0x5A }, + { KEY_EN_J, 0x5B }, + { KEY_EN_M, 0x64 }, + { "Logo", 0x65 }, + { KEY_EN_F7, 0x68 }, + { KEY_EN_9, 0x69 }, + { KEY_EN_I, 0x62 }, + { KEY_EN_K, 0x63 }, + { KEY_EN_COMMA, 0x6C }, + { KEY_EN_F8, 0x70 }, + { KEY_EN_0, 0x71 }, + { KEY_EN_O, 0x6A }, + { KEY_EN_L, 0x6B }, + { KEY_EN_PERIOD, 0x74 }, + { KEY_EN_RIGHT_ALT, 0x6D }, + { KEY_EN_F9, 0x80 }, + { KEY_EN_MINUS, 0x79 }, + { KEY_EN_P, 0x72 }, + { KEY_EN_SEMICOLON, 0x73 }, + { KEY_EN_FORWARD_SLASH, 0x7C }, + { KEY_EN_RIGHT_FUNCTION, 0x75 }, + { KEY_EN_F10, 0x88 }, + { KEY_EN_EQUALS, 0x81 }, + { KEY_EN_LEFT_BRACKET, 0x7A }, + { KEY_EN_QUOTE, 0x7B }, + { KEY_EN_MENU, 0x7D }, + { KEY_EN_F11, 0x90 }, + { KEY_EN_BACKSPACE, 0x89 }, + { KEY_EN_RIGHT_BRACKET, 0x82 }, + { KEY_EN_POUND, 0x83 }, + { KEY_EN_RIGHT_SHIFT, 0x8C }, + { KEY_EN_F12, 0x98 }, + { KEY_EN_ISO_ENTER, 0x8B }, + { KEY_EN_RIGHT_CONTROL, 0x8D }, + { KEY_EN_PRINT_SCREEN, 0xA0 }, + { KEY_EN_INSERT, 0xA1 }, + { KEY_EN_DELETE, 0xA2 }, + { KEY_EN_LEFT_ARROW, 0xA5 }, + { KEY_EN_SCROLL_LOCK, 0xA8 }, + { KEY_EN_HOME, 0xA9 }, + { KEY_EN_END, 0xAA }, + { KEY_EN_UP_ARROW, 0xAC }, + { KEY_EN_DOWN_ARROW, 0xAD }, + { KEY_EN_PAUSE_BREAK, 0xB0 }, + { KEY_EN_PAGE_UP, 0xB1 }, + { KEY_EN_PAGE_DOWN, 0xB2 }, + { KEY_EN_RIGHT_ARROW, 0xB5 } + } + } + }, + { + ASUS_TUF_K7_LAYOUT_US, + { + *ASUS_CLAYMORE_NUMPAD_LEFT_LAYOUT_KEYS_ANSI, + 105, + 7, + 24, + { + { KEY_EN_NUMPAD_LOCK, 0x01 }, + { KEY_EN_NUMPAD_7, 0x02 }, + { KEY_EN_NUMPAD_4, 0x03 }, + { KEY_EN_NUMPAD_1, 0x04 }, + { KEY_EN_NUMPAD_0, 0x05 }, + { KEY_EN_NUMPAD_DIVIDE, 0x09 }, + { KEY_EN_NUMPAD_8, 0x0A }, + { KEY_EN_NUMPAD_5, 0x0B }, + { KEY_EN_NUMPAD_2, 0x0C }, + { KEY_EN_NUMPAD_TIMES, 0x11 }, + { KEY_EN_NUMPAD_9, 0x12 }, + { KEY_EN_NUMPAD_6, 0x13 }, + { KEY_EN_NUMPAD_3, 0x14 }, + { KEY_EN_NUMPAD_PERIOD, 0x15 }, + { KEY_EN_NUMPAD_MINUS, 0x19 }, + { KEY_EN_NUMPAD_PLUS, 0x1A }, + { KEY_EN_NUMPAD_ENTER, 0x1C }, + { KEY_EN_ESCAPE, 0x20 }, + { KEY_EN_BACK_TICK, 0x21 }, + { KEY_EN_TAB, 0x22 }, + { KEY_EN_CAPS_LOCK, 0x23 }, + { KEY_EN_LEFT_SHIFT, 0x24 }, + { KEY_EN_LEFT_CONTROL, 0x25 }, + { KEY_EN_1, 0x29 }, + { KEY_EN_LEFT_WINDOWS, 0x2D }, + { KEY_EN_F1, 0x30 }, + { KEY_EN_2, 0x31 }, + { KEY_EN_Q, 0x2A }, + { KEY_EN_A, 0x2B }, + { KEY_EN_Z, 0x2C }, + { KEY_EN_LEFT_ALT, 0x35 }, + { KEY_EN_F2, 0x38 }, + { KEY_EN_3, 0x39 }, + { KEY_EN_W, 0x32 }, + { KEY_EN_S, 0x33 }, + { KEY_EN_X, 0x34 }, + { KEY_EN_F3, 0x40 }, + { KEY_EN_4, 0x41 }, + { KEY_EN_E, 0x3A }, + { KEY_EN_D, 0x3B }, + { KEY_EN_C, 0x3C }, + { KEY_EN_F4, 0x48 }, + { KEY_EN_5, 0x49 }, + { KEY_EN_R, 0x42 }, + { KEY_EN_F, 0x43 }, + { KEY_EN_V, 0x44 }, + { KEY_EN_6, 0x51 }, + { KEY_EN_T, 0x4A }, + { KEY_EN_G, 0x4B }, + { KEY_EN_B, 0x4C }, + { KEY_EN_SPACE, 0x45 }, + { KEY_EN_F5, 0x58 }, + { KEY_EN_7, 0x59 }, + { KEY_EN_Y, 0x52 }, + { KEY_EN_H, 0x53 }, + { KEY_EN_N, 0x54 }, + { KEY_EN_F6, 0x60 }, + { KEY_EN_8, 0x61 }, + { KEY_EN_U, 0x5A }, + { KEY_EN_J, 0x5B }, + { KEY_EN_M, 0x5C }, + { "Logo", 0x5D }, + { KEY_EN_F7, 0x68 }, + { KEY_EN_9, 0x69 }, + { KEY_EN_I, 0x62 }, + { KEY_EN_K, 0x63 }, + { KEY_EN_COMMA, 0x64 }, + { KEY_EN_F8, 0x70 }, + { KEY_EN_0, 0x71 }, + { KEY_EN_O, 0x6A }, + { KEY_EN_L, 0x6B }, + { KEY_EN_PERIOD, 0x6C }, + { KEY_EN_RIGHT_ALT, 0x6D }, + { KEY_EN_F9, 0x80 }, + { KEY_EN_MINUS, 0x79 }, + { KEY_EN_P, 0x72 }, + { KEY_EN_SEMICOLON, 0x73 }, + { KEY_EN_FORWARD_SLASH, 0x74 }, + { KEY_EN_RIGHT_FUNCTION, 0x75 }, + { KEY_EN_F10, 0x88 }, + { KEY_EN_EQUALS, 0x81 }, + { KEY_EN_LEFT_BRACKET, 0x7A }, + { KEY_EN_QUOTE, 0x7B }, + { KEY_EN_MENU, 0x7D }, + { KEY_EN_F11, 0x90 }, + { KEY_EN_BACKSPACE, 0x89 }, + { KEY_EN_RIGHT_BRACKET, 0x82 }, + { KEY_EN_RIGHT_SHIFT, 0x8C }, + { KEY_EN_F12, 0x98 }, + { KEY_EN_ANSI_BACK_SLASH, 0x8A }, + { KEY_EN_ANSI_ENTER, 0x8B }, + { KEY_EN_RIGHT_CONTROL, 0x8D }, + { KEY_EN_PRINT_SCREEN, 0xA0 }, + { KEY_EN_INSERT, 0xA1 }, + { KEY_EN_DELETE, 0xA2 }, + { KEY_EN_LEFT_ARROW, 0xA5 }, + { KEY_EN_SCROLL_LOCK, 0xA8 }, + { KEY_EN_HOME, 0xA9 }, + { KEY_EN_END, 0xAA }, + { KEY_EN_UP_ARROW, 0xAC }, + { KEY_EN_DOWN_ARROW, 0xAD }, + { KEY_EN_PAUSE_BREAK, 0xB0 }, + { KEY_EN_PAGE_UP, 0xB1 }, + { KEY_EN_PAGE_DOWN, 0xB2 }, + { KEY_EN_RIGHT_ARROW, 0xB5 } + } + } + }, +}; + +static std::map AsusTufK1Layouts = +{ + { + ASUS_TUF_K7_LAYOUT_UK, + { + *ASUS_TUF_K1_LAYOUT_KEYS, + 5, + 1, + 5, + { + { "Keyboard LED 1", 0x00 }, + { "Keyboard LED 2", 0x01 }, + { "Keyboard LED 3", 0x02 }, + { "Keyboard LED 4", 0x03 }, + { "Keyboard LED 5", 0x04 }, + } + } + }, + { + ASUS_TUF_K7_LAYOUT_US, + { + *ASUS_TUF_K1_LAYOUT_KEYS, + 5, + 1, + 5, + { + { "Keyboard LED 1", 0x00 }, + { "Keyboard LED 2", 0x01 }, + { "Keyboard LED 3", 0x02 }, + { "Keyboard LED 4", 0x03 }, + { "Keyboard LED 5", 0x04 }, + } + } + }, +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController/RGBController_AsusAuraTUFKeyboard.cpp b/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController/RGBController_AsusAuraTUFKeyboard.cpp new file mode 100644 index 00000000..032bc748 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController/RGBController_AsusAuraTUFKeyboard.cpp @@ -0,0 +1,663 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraTUFKeyboard.cpp | +| | +| RGBController for ASUS Aura TUF keyboard | +| | +| Mola19 03 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "RGBController_AsusAuraTUFKeyboard.h" + +/**------------------------------------------------------------------*\ + @name Asus Aura TUF Keyboard + @category Keyboard + @type USB + @save :white_check_mark: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectAsusAuraTUFUSBKeyboard + @comment +\*-------------------------------------------------------------------*/ + +RGBController_AuraTUFKeyboard::RGBController_AuraTUFKeyboard(AuraTUFKeyboardController* controller_ptr) +{ + controller = controller_ptr; + + pid = controller->device_pid; + + if(pid != AURA_ROG_CLAYMORE_PID) + { + name = controller->GetName(); + vendor = "ASUS"; + type = DEVICE_TYPE_KEYBOARD; + description = "ASUS Aura Keyboard Device"; + version = controller->GetVersion(); + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + unsigned char AURA_KEYBOARD_SPEED_MIN = 0; + unsigned char AURA_KEYBOARD_SPEED_MAX = 0; + unsigned char AURA_KEYBOARD_SPEED_DEFAULT = 0; + + switch(pid) + { + case AURA_TUF_K1_GAMING_PID: + AURA_KEYBOARD_SPEED_MIN = 0; + AURA_KEYBOARD_SPEED_MAX = 2; + AURA_KEYBOARD_SPEED_DEFAULT = 1; + break; + + case AURA_ROG_STRIX_FLARE_PID: + case AURA_ROG_STRIX_FLARE_PNK_LTD_PID: + case AURA_ROG_STRIX_FLARE_COD_BO4_PID: + case AURA_TUF_K3_GAMING_PID: + case AURA_TUF_K7_GAMING_PID: + AURA_KEYBOARD_SPEED_MIN = 15; + AURA_KEYBOARD_SPEED_MAX = 0; + AURA_KEYBOARD_SPEED_DEFAULT = 8; + break; + + case AURA_ROG_AZOTH_USB_PID: + case AURA_ROG_AZOTH_2_4_PID: + case AURA_ROG_FALCHION_WIRED_PID: + case AURA_ROG_FALCHION_WIRELESS_PID: + case AURA_ROG_STRIX_FLARE_II_PID: + case AURA_ROG_STRIX_FLARE_II_ANIMATE_PID: + case AURA_ROG_STRIX_SCOPE_RX_PID: + case AURA_ROG_STRIX_SCOPE_RX_EVA_02_PID: + case AURA_ROG_STRIX_SCOPE_PID: + case AURA_ROG_STRIX_SCOPE_NX_WIRELESS_DELUXE_2_4_PID: + case AURA_ROG_STRIX_SCOPE_NX_WIRELESS_DELUXE_USB_PID: + case AURA_ROG_STRIX_SCOPE_II_PID: + case AURA_ROG_STRIX_SCOPE_II_RX_PID: + case AURA_ROG_STRIX_SCOPE_II_96_WIRELESS_USB_PID: + case AURA_TUF_K5_GAMING_PID: + AURA_KEYBOARD_SPEED_MIN = 255; + AURA_KEYBOARD_SPEED_MAX = 0; + AURA_KEYBOARD_SPEED_DEFAULT = 30; + break; + + default: + AURA_KEYBOARD_SPEED_MIN = 15; + AURA_KEYBOARD_SPEED_MAX = 0; + AURA_KEYBOARD_SPEED_DEFAULT = 8; + break; + } + + mode Direct; + Direct.name = "Direct"; + Direct.value = AURA_KEYBOARD_MODE_DIRECT; + 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 = AURA_KEYBOARD_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Static.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; + Static.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; + Static.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.resize(1); + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = AURA_KEYBOARD_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + if(controller->is_per_led_keyboard) + { + Breathing.flags |= MODE_FLAG_HAS_RANDOM_COLOR; + } + Breathing.speed_min = AURA_KEYBOARD_SPEED_MIN; + Breathing.speed_max = AURA_KEYBOARD_SPEED_MAX; + Breathing.speed = AURA_KEYBOARD_SPEED_DEFAULT; + Breathing.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; + Breathing.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; + Breathing.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.colors_min = 1; + Breathing.colors_max = 2; + Breathing.colors.resize(1); + modes.push_back(Breathing); + + mode Color_Cycle; + Color_Cycle.name = "Spectrum Cycle"; + Color_Cycle.value = AURA_KEYBOARD_MODE_COLOR_CYCLE; + Color_Cycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Color_Cycle.speed_min = AURA_KEYBOARD_SPEED_MIN; + Color_Cycle.speed_max = AURA_KEYBOARD_SPEED_MAX; + Color_Cycle.speed = AURA_KEYBOARD_SPEED_DEFAULT; + Color_Cycle.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; + Color_Cycle.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; + Color_Cycle.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; + Color_Cycle.color_mode = MODE_COLORS_NONE; + modes.push_back(Color_Cycle); + + mode Wave; + Wave.name = "Rainbow Wave"; + Wave.value = AURA_KEYBOARD_MODE_WAVE; + Wave.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_HV | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + if(controller->is_per_led_keyboard) + { + Wave.flags |= MODE_FLAG_HAS_DIRECTION_UD; + } + Wave.speed_min = AURA_KEYBOARD_SPEED_MIN; + Wave.speed_max = AURA_KEYBOARD_SPEED_MAX; + Wave.speed = AURA_KEYBOARD_SPEED_DEFAULT; + Wave.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; + Wave.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; + Wave.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; + Wave.direction = MODE_DIRECTION_LEFT; + Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; + + if(!controller->is_per_led_keyboard) + { + Wave.colors_min = 5; + Wave.colors_max = 5; + } + else + { + Wave.colors_min = 1; + Wave.colors_max = 7; + } + + Wave.colors.resize(Wave.colors_max); + modes.push_back(Wave); + + if(controller->is_per_led_keyboard) + { + mode Reactive; + Reactive.name = "Reactive"; + Reactive.value = AURA_KEYBOARD_MODE_REACTIVE; + Reactive.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Reactive.speed_min = AURA_KEYBOARD_SPEED_MIN; + Reactive.speed_max = AURA_KEYBOARD_SPEED_MAX; + Reactive.speed = AURA_KEYBOARD_SPEED_DEFAULT; + Reactive.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; + Reactive.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; + Reactive.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; + Reactive.color_mode = MODE_COLORS_MODE_SPECIFIC; + Reactive.colors_min = 1; + Reactive.colors_max = 2; + Reactive.colors.resize(1); + modes.push_back(Reactive); + + mode Ripple; + Ripple.name = "Ripple"; + Ripple.value = AURA_KEYBOARD_MODE_RIPPLE; + Ripple.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Ripple.speed_min = AURA_KEYBOARD_SPEED_MIN; + Ripple.speed_max = AURA_KEYBOARD_SPEED_MAX; + Ripple.speed = AURA_KEYBOARD_SPEED_DEFAULT; + Ripple.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; + Ripple.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; + Ripple.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; + Ripple.color_mode = MODE_COLORS_MODE_SPECIFIC; + Ripple.colors_min = 1; + Ripple.colors_max = 8; + Ripple.colors.resize(7); + modes.push_back(Ripple); + + mode Starry_Night; + Starry_Night.name = "Starry Night"; + Starry_Night.value = AURA_KEYBOARD_MODE_STARRY_NIGHT; + Starry_Night.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Starry_Night.speed_min = AURA_KEYBOARD_SPEED_MIN; + Starry_Night.speed_max = AURA_KEYBOARD_SPEED_MAX; + Starry_Night.speed = AURA_KEYBOARD_SPEED_DEFAULT; + Starry_Night.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; + Starry_Night.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; + Starry_Night.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; + Starry_Night.color_mode = MODE_COLORS_MODE_SPECIFIC; + Starry_Night.colors_min = 1; + Starry_Night.colors_max = 3; + Starry_Night.colors.resize(1); + modes.push_back(Starry_Night); + + mode Quicksand; + Quicksand.name = "Quicksand"; + Quicksand.value = AURA_KEYBOARD_MODE_QUICKSAND; + Quicksand.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Quicksand.direction = MODE_DIRECTION_DOWN; + Quicksand.speed_min = AURA_KEYBOARD_SPEED_MIN; + Quicksand.speed_max = AURA_KEYBOARD_SPEED_MAX; + Quicksand.speed = AURA_KEYBOARD_SPEED_DEFAULT; + Quicksand.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; + Quicksand.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; + Quicksand.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; + Quicksand.color_mode = MODE_COLORS_MODE_SPECIFIC; + Quicksand.colors_min = 6; + Quicksand.colors_max = 6; + Quicksand.colors.resize(6); + modes.push_back(Quicksand); + + mode Current; + Current.name = "Current"; + Current.value = AURA_KEYBOARD_MODE_CURRENT; + Current.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Current.speed_min = AURA_KEYBOARD_SPEED_MIN; + Current.speed_max = AURA_KEYBOARD_SPEED_MAX; + Current.speed = AURA_KEYBOARD_SPEED_DEFAULT; + Current.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; + Current.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; + Current.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; + Current.color_mode = MODE_COLORS_MODE_SPECIFIC; + Current.colors_min = 1; + Current.colors_max = 3; + Current.colors.resize(1); + modes.push_back(Current); + + mode Rain_Drop; + Rain_Drop.name = "Rain Drop"; + Rain_Drop.value = AURA_KEYBOARD_MODE_RAIN_DROP; + Rain_Drop.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Rain_Drop.speed_min = AURA_KEYBOARD_SPEED_MIN; + Rain_Drop.speed_max = AURA_KEYBOARD_SPEED_MAX; + Rain_Drop.speed = AURA_KEYBOARD_SPEED_DEFAULT; + Rain_Drop.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; + Rain_Drop.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; + Rain_Drop.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; + Rain_Drop.color_mode = MODE_COLORS_MODE_SPECIFIC; + Rain_Drop.colors_min = 1; + Rain_Drop.colors_max = 3; + Rain_Drop.colors.resize(1); + modes.push_back(Rain_Drop); + } + } + else + { + + name = controller->GetName(); + vendor = "ASUS"; + type = DEVICE_TYPE_KEYBOARD; + description = "ASUS Aura Keyboard Device"; + version = controller->GetVersion(); + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = AURA_KEYBOARD_MODE_DIRECT; + 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 = AURA_KEYBOARD_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.resize(1); + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = AURA_KEYBOARD_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.speed_min = AURA_CLAYMORE_SPEED_MIN; + Breathing.speed_max = AURA_CLAYMORE_SPEED_MAX; + Breathing.speed = AURA_CLAYMORE_SPEED_DEFAULT_BREATHING; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.colors_min = 1; + Breathing.colors_max = 2; + Breathing.colors.resize(2); + modes.push_back(Breathing); + + mode Color_Cycle; + Color_Cycle.name = "Spectrum Cycle"; + Color_Cycle.value = AURA_KEYBOARD_MODE_COLOR_CYCLE; + Color_Cycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Color_Cycle.speed_min = AURA_CLAYMORE_SPEED_MIN; + Color_Cycle.speed_max = AURA_CLAYMORE_SPEED_MAX; + Color_Cycle.speed = AURA_CLAYMORE_SPEED_DEFAULT_COLOR_CYCLE; + Color_Cycle.color_mode = MODE_COLORS_NONE; + modes.push_back(Color_Cycle); + + mode Reactive; + Reactive.name = "Reactive"; + Reactive.value = AURA_KEYBOARD_MODE_REACTIVE; + Reactive.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Reactive.speed_min = AURA_CLAYMORE_SPEED_MIN; + Reactive.speed_max = AURA_CLAYMORE_SPEED_MAX; + Reactive.speed = AURA_CLAYMORE_SPEED_DEFAULT_REACTIVE; + Reactive.color_mode = MODE_COLORS_MODE_SPECIFIC; + Reactive.colors_min = 1; + Reactive.colors_max = 2; + Reactive.colors.resize(2); + modes.push_back(Reactive); + + mode Wave; + Wave.name = "Rainbow Wave"; + Wave.value = AURA_KEYBOARD_MODE_WAVE; + Wave.flags = MODE_COLORS_NONE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_AUTOMATIC_SAVE; + Wave.speed_min = AURA_CLAYMORE_SPEED_MIN; + Wave.speed_max = AURA_CLAYMORE_SPEED_MAX; + Wave.speed = AURA_CLAYMORE_SPEED_DEFAULT_WAVE; + Wave.direction = MODE_DIRECTION_LEFT; + Wave.color_mode = MODE_COLORS_NONE; + modes.push_back(Wave); + + mode Color_Wave; + Color_Wave.name = "Color Wave"; + Color_Wave.value = AURA_KEYBOARD_MODE_WAVE; + Color_Wave.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_AUTOMATIC_SAVE; + Color_Wave.speed_min = AURA_CLAYMORE_SPEED_MIN; + Color_Wave.speed_max = AURA_CLAYMORE_SPEED_MAX; + Color_Wave.speed = AURA_CLAYMORE_SPEED_DEFAULT_WAVE; + Color_Wave.direction = MODE_DIRECTION_LEFT; + Color_Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; + Color_Wave.colors_min = 1; + Color_Wave.colors_max = 2; + Color_Wave.colors.resize(2); + modes.push_back(Color_Wave); + + mode Ripple; + Ripple.name = "Ripple"; + Ripple.value = AURA_KEYBOARD_MODE_RIPPLE; + Ripple.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Ripple.speed_min = AURA_CLAYMORE_SPEED_MIN; + Ripple.speed_max = AURA_CLAYMORE_SPEED_MAX; + Ripple.speed = AURA_CLAYMORE_SPEED_DEFAULT_RIPPLE; + Ripple.color_mode = MODE_COLORS_MODE_SPECIFIC; + Ripple.colors_min = 1; + Ripple.colors_max = 2; + Ripple.colors.resize(2); + modes.push_back(Ripple); + + mode Starry_Night; + Starry_Night.name = "Starry Night"; + Starry_Night.value = AURA_KEYBOARD_MODE_STARRY_NIGHT; + Starry_Night.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Starry_Night.speed_min = AURA_CLAYMORE_SPEED_MIN; + Starry_Night.speed_max = AURA_CLAYMORE_SPEED_MAX; + Starry_Night.speed = AURA_CLAYMORE_SPEED_DEFAULT_STARRY_NIGHT; + Starry_Night.color_mode = MODE_COLORS_MODE_SPECIFIC; + Starry_Night.colors_min = 1; + Starry_Night.colors_max = 2; + Starry_Night.colors.resize(2); + modes.push_back(Starry_Night); + + mode Quicksand; + Quicksand.name = "Quicksand"; + Quicksand.value = AURA_KEYBOARD_MODE_QUICKSAND; + Quicksand.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Quicksand.direction = MODE_DIRECTION_DOWN; + Quicksand.speed_min = AURA_CLAYMORE_SPEED_MIN; + Quicksand.speed_max = AURA_CLAYMORE_SPEED_MAX; + Quicksand.speed = AURA_CLAYMORE_SPEED_DEFAULT_QUICKSAND; + Quicksand.color_mode = MODE_COLORS_MODE_SPECIFIC; + Quicksand.colors_min = 6; + Quicksand.colors_max = 6; + Quicksand.colors.resize(6); + modes.push_back(Quicksand); + } + + SetupZones(); +} + +RGBController_AuraTUFKeyboard::~RGBController_AuraTUFKeyboard() +{ + delete controller; +} + +void RGBController_AuraTUFKeyboard::SetupZones() +{ + std::map * keyboard_ptr; + + switch(pid) + { + case AURA_ROG_STRIX_FLARE_PID: + case AURA_ROG_STRIX_FLARE_PNK_LTD_PID: + case AURA_ROG_STRIX_FLARE_COD_BO4_PID: + keyboard_ptr = &AsusROGStrixFlareLayouts; + break; + case AURA_TUF_K3_GAMING_PID: + case AURA_TUF_K7_GAMING_PID: + keyboard_ptr = &AsusTUFK7Layouts; + break; + case AURA_ROG_STRIX_SCOPE_PID: + case AURA_ROG_STRIX_SCOPE_RX_PID: + case AURA_ROG_STRIX_SCOPE_RX_EVA_02_PID: + case AURA_ROG_STRIX_SCOPE_NX_WIRELESS_DELUXE_USB_PID: + case AURA_ROG_STRIX_SCOPE_NX_WIRELESS_DELUXE_2_4_PID: + keyboard_ptr = &AsusROGStrixScopeLayouts; + break; + case AURA_ROG_STRIX_SCOPE_II_PID: + case AURA_ROG_STRIX_SCOPE_II_RX_PID: + keyboard_ptr = &AsusROGStrixScopeIILayouts; + break; + case AURA_ROG_STRIX_SCOPE_II_96_WIRELESS_USB_PID: + keyboard_ptr = &AsusROGStrixScopeII96WirelessLayouts; + break; + case AURA_ROG_STRIX_FLARE_II_PID: + keyboard_ptr = &AsusROGStrixFlareIILayouts; + break; + case AURA_ROG_STRIX_FLARE_II_ANIMATE_PID: + keyboard_ptr = &AsusROGStrixFlareIIAnimateLayouts; + break; + case AURA_ROG_AZOTH_USB_PID: + case AURA_ROG_AZOTH_2_4_PID: + keyboard_ptr = &AsusROGAzothLayouts; + break; + case AURA_ROG_FALCHION_WIRED_PID: + case AURA_ROG_FALCHION_WIRELESS_PID: + keyboard_ptr = &AsusFalchionLayouts; + break; + case AURA_ROG_CLAYMORE_PID: + unsigned char numpad; + numpad = controller->GetNumpadLocation(); + switch(numpad) + { + case 0: + keyboard_ptr = &AsusClaymoreNoNumpadLayouts; + break; + case 2: + keyboard_ptr = &AsusClaymoreNumpadRightLayouts; + break; + case 3: + keyboard_ptr = &AsusClaymoreNumpadLeftLayouts; + break; + default: + keyboard_ptr = &AsusClaymoreNoNumpadLayouts; + } + break; + case AURA_TUF_K1_GAMING_PID: + case AURA_TUF_K5_GAMING_PID: + keyboard_ptr = &AsusTufK1Layouts; + break; + default: + keyboard_ptr = &AsusTUFK7Layouts; + } + + std::map & keyboard = *keyboard_ptr; + + unsigned char layout = controller->GetLayout(); + + if(keyboard.find(layout % 100) == keyboard.end()) + { + /*---------------------------------------------------------*\ + | If Layout not found, take uk or us | + \*---------------------------------------------------------*/ + layout = std::floor(layout/100) == 2 ? ASUS_TUF_K7_LAYOUT_UK : ASUS_TUF_K7_LAYOUT_US; + } + else + { + layout = layout % 100; + } + + zone keyboard_zone; + keyboard_zone.name = "Keyboard"; + keyboard_zone.type = ZONE_TYPE_MATRIX; + keyboard_zone.leds_min = keyboard[layout].size; + keyboard_zone.leds_max = keyboard[layout].size; + keyboard_zone.leds_count = keyboard[layout].size; + keyboard_zone.matrix_map = new matrix_map_type; + keyboard_zone.matrix_map->height = keyboard[layout].rows; + keyboard_zone.matrix_map->width = keyboard[layout].cols; + keyboard_zone.matrix_map->map = keyboard[layout].matrix_map; + zones.push_back(keyboard_zone); + + for(int led_id = 0; led_id < keyboard[layout].size; led_id++) + { + led new_led; + new_led.name = keyboard[layout].led_names[led_id].name; + new_led.value = keyboard[layout].led_names[led_id].id; + leds.push_back(new_led); + } + + SetupColors(); + + /*---------------------------------------------------------*\ + | sends the init packet for the default mode (direct) | + \*---------------------------------------------------------*/ + DeviceUpdateMode(); +} + +void RGBController_AuraTUFKeyboard::ResizeZone(int /*zone*/, int /*new_size*/) +{ + +} + +void RGBController_AuraTUFKeyboard::DeviceUpdateLEDs() +{ + std::vector led_color_list = {}; + + for(size_t i = 0; i < colors.size(); i++) + { + led_color_list.push_back({ leds[i].value, colors[i] }); + } + + controller->UpdateLeds(led_color_list); +} + +void RGBController_AuraTUFKeyboard::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_AuraTUFKeyboard::UpdateSingleLED(int led) +{ + if(!controller->is_per_led_keyboard) + { + return DeviceUpdateLEDs(); + } + + unsigned char red = RGBGetRValue(colors[led]); + unsigned char green = RGBGetGValue(colors[led]); + unsigned char blue = RGBGetBValue(colors[led]); + + controller->UpdateSingleLed(leds[led].value, red, green, blue); +} + +static const uint8_t direction_map[2][6] = +{ + { 4, 0, 6, 2, 8, 1 }, // Default directions Left, Right, Up, Down, Horizontal, Vertical + { 0, 4, 6, 2, 0xFF, 0xFF }, // AURA_ROG_CLAYMORE directions Left, Right, Up, Down +}; + +void RGBController_AuraTUFKeyboard::DeviceUpdateMode() +{ + if(pid == AURA_ROG_CLAYMORE_PID) + { + controller->AllowRemoteControl(1); + } + + unsigned char color_mode = 0; + unsigned char direction = 0; + unsigned char brightness = 0; + + if(modes[active_mode].value == AURA_KEYBOARD_MODE_DIRECT) + { + if(pid == AURA_ROG_CLAYMORE_PID) controller->AllowRemoteControl(3); + return; + }; + + if(pid != AURA_ROG_CLAYMORE_PID) + { + brightness = modes[active_mode].brightness * 25; + + switch(modes[active_mode].value) + { + case AURA_KEYBOARD_MODE_BREATHING: + case AURA_KEYBOARD_MODE_REACTIVE: + case AURA_KEYBOARD_MODE_STARRY_NIGHT: + case AURA_KEYBOARD_MODE_CURRENT: + case AURA_KEYBOARD_MODE_RAIN_DROP: + if(!controller->is_per_led_keyboard && modes[active_mode].colors.size() > 1) + { + color_mode = 1; + break; + } + + bool color_is_black = (modes[active_mode].colors.size() > 1 && modes[active_mode].colors[1] == 000); + + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC && !color_is_black) + { + color_mode = 16; + } + break; + } + + if(modes[active_mode].color_mode == MODE_COLORS_RANDOM) + { + color_mode = 1; + } + + if(modes[active_mode].value == AURA_KEYBOARD_MODE_WAVE || modes[active_mode].value == AURA_KEYBOARD_MODE_QUICKSAND) + { + /*----------------------------------------------------------*\ + | converting openrgb direction value to keyboard directions | + \*----------------------------------------------------------*/ + direction = direction_map[0][modes[active_mode].direction]; + } + } + else + { + if(modes[active_mode].color_mode == MODE_COLORS_RANDOM) + { + color_mode = 1; + } + + if(modes[active_mode].value == AURA_KEYBOARD_MODE_WAVE) { + if (modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) color_mode = 2; + + /*----------------------------------------------------------*\ + | converting openrgb direction value to keyboard directions | + \*----------------------------------------------------------*/ + direction = direction_map[1][modes[active_mode].direction]; + } + } + + + controller->UpdateDevice(modes[active_mode].value, std::vector(modes[active_mode].colors), direction, color_mode, modes[active_mode].speed, brightness); + + if(pid == AURA_ROG_CLAYMORE_PID) + { + controller->UpdateMode(modes[active_mode].value); + controller->SaveMode(); + controller->AllowRemoteControl(0); + } +} + +void RGBController_AuraTUFKeyboard::DeviceSaveMode() +{ + /*----------------------------------------------------------*\ + | not available for Claymore | + \*----------------------------------------------------------*/ + if(pid != AURA_ROG_CLAYMORE_PID) + { + DeviceUpdateMode(); + controller->SaveMode(); + } +} diff --git a/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController/RGBController_AsusAuraTUFKeyboard.h b/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController/RGBController_AsusAuraTUFKeyboard.h new file mode 100644 index 00000000..982aea26 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController/RGBController_AsusAuraTUFKeyboard.h @@ -0,0 +1,58 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraTUFKeyboard.h | +| | +| RGBController for ASUS Aura TUF keyboard | +| | +| Mola19 03 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AsusAuraTUFKeyboardController.h" + +enum +{ + AURA_KEYBOARD_BRIGHTNESS_MIN = 0, + AURA_KEYBOARD_BRIGHTNESS_MAX = 4, + AURA_KEYBOARD_BRIGHTNESS_DEFAULT = 4, +}; + +enum +{ + AURA_CLAYMORE_SPEED_MIN = 254, + AURA_CLAYMORE_SPEED_MAX = 0, + AURA_CLAYMORE_SPEED_DEFAULT_STATIC = 0, + AURA_CLAYMORE_SPEED_DEFAULT_BREATHING = 107, + AURA_CLAYMORE_SPEED_DEFAULT_COLOR_CYCLE = 121, + AURA_CLAYMORE_SPEED_DEFAULT_REACTIVE = 56, + AURA_CLAYMORE_SPEED_DEFAULT_WAVE = 50, + AURA_CLAYMORE_SPEED_DEFAULT_RIPPLE = 108, + AURA_CLAYMORE_SPEED_DEFAULT_STARRY_NIGHT = 54, + AURA_CLAYMORE_SPEED_DEFAULT_QUICKSAND = 103 +}; + +class RGBController_AuraTUFKeyboard : public RGBController +{ +public: + RGBController_AuraTUFKeyboard(AuraTUFKeyboardController* controller_ptr); + ~RGBController_AuraTUFKeyboard(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + AuraTUFKeyboardController* controller; + uint16_t pid; +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardLayouts.h b/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardLayouts.h deleted file mode 100644 index 76f5f760..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardLayouts.h +++ /dev/null @@ -1,1355 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraTUFKeyboardController.h | -| | -| Definitions and types for ASUS Aura | -| USB RGB lighting controller | -| | -| Mola19 10/02/2021 | -\*-----------------------------------------*/ - -#include "RGBControllerKeyNames.h" -#include -#include -#include "RGBController.h" - -#pragma once - -enum -{ - ASUS_TUF_K7_LAYOUT_CA = 1, - ASUS_TUF_K7_LAYOUT_AR = 2, - ASUS_TUF_K7_LAYOUT_DE = 3, - ASUS_TUF_K7_LAYOUT_UK = 4, - ASUS_TUF_K7_LAYOUT_FR = 5, - ASUS_TUF_K7_LAYOUT_CN = 6, - ASUS_TUF_K7_LAYOUT_HU = 7, - ASUS_TUF_K7_LAYOUT_IT = 8, - ASUS_TUF_K7_LAYOUT_TH = 9, - ASUS_TUF_K7_LAYOUT_UA = 10, - ASUS_TUF_K7_LAYOUT_NO = 11, - ASUS_TUF_K7_LAYOUT_PT = 12, - ASUS_TUF_K7_LAYOUT_HE = 13, - ASUS_TUF_K7_LAYOUT_RU = 14, - ASUS_TUF_K7_LAYOUT_ES = 15, - ASUS_TUF_K7_LAYOUT_TW = 16, - ASUS_TUF_K7_LAYOUT_US = 17, - ASUS_TUF_K7_LAYOUT_TR = 18, - ASUS_TUF_K7_LAYOUT_CZ = 19, - ASUS_TUF_K7_LAYOUT_BE = 20, - ASUS_TUF_K7_LAYOUT_JP = 21, - ASUS_TUF_K7_LAYOUT_KR = 22, - ASUS_TUF_K7_LAYOUT_IS = 23, - ASUS_TUF_K7_LAYOUT_WB = 24, - ASUS_TUF_K7_LAYOUT_SW_CH = 25 -}; - -#define NA 0xFFFFFFFF - -struct led_value -{ - const char* name; - unsigned char id; -}; - -struct layout_info -{ - unsigned int* matrix_map; - int size; - int rows; - int cols; - std::vector led_names; -}; - -static unsigned int ASUS_TUF_K7_LAYOUT_KEYS_US[6][24] = -{ - { 0, NA, 8, 14, 19, 24, NA, 34, 39, 44, 49, 55, 61, 66, 70, NA, 74, 78, 83, NA, NA, NA, NA, NA }, - { 1, 6, 9, 15, 20, 25, 29, 35, 40, 45, 50, 56, 62, 67, NA, NA, 75, 79, 84, NA, 87, 92, 96, 101 }, - { 2, NA, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, 71, NA, 76, 80, 85, NA, 88, 93, 97, 102 }, - { 3, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, NA, 72, NA, NA, NA, NA, NA, 89, 94, 98, NA }, - { 4, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, NA, 69, NA, NA, NA, 81, NA, NA, 90, 95, 99, 103 }, - { 5, 7, 13, NA, NA, NA, 33, NA, NA, NA, 54, 60, 65, NA, 73, NA, 77, 82, 86, NA, 91, NA, 100, NA } -}; - - -static unsigned int ASUS_TUF_K7_LAYOUT_KEYS_UK[6][24] = -{ - { 0, NA, 9, 15, 20, 25, NA, 35, 40, 45, 50, 56, 62, 67, 72, NA, 75, 79, 84, NA, NA, NA, NA, NA }, - { 1, 6, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, NA, NA, 76, 80, 85, NA, 88, 93, 97, 102 }, - { 2, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, 69, NA, NA, 77, 81, 86, NA, 89, 94, 98, 103 }, - { 3, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, 65, 70, 73, NA, NA, NA, NA, NA, 90, 95, 99, NA }, - { 4, 7, 13, 19, 24, 29, 33, 39, 44, 49, 54, 60, NA, 71, NA, NA, NA, 82, NA, NA, 91, 96, 100, 104 }, - { 5, 8, 14, NA, NA, NA, 34, NA, NA, NA, 55, 61, 66, NA, 74, NA, 78, 83, 87, NA, 92, NA, 101, NA } -}; - -static unsigned int ASUS_FALCHION_LAYOUT_KEYS_US[5][16] = -{ - { 0, 5, 7, 12, 16, 20, 24, 29, 33, 37, 41, 46, 51, 56, NA, 63 }, - { 1, NA, 8, 13, 17, 21, 25, 30, 34, 38, 42, 47, 52, 57, 59, 64 }, - { 2, NA, 9, 14, 18, 22, 26, 31, 35, 39, 43, 48, 53, NA, 60, 65 }, - { 3, NA, 10, 15, 19, 23, 27, 32, 36, 40, 44, 49, 54, NA, 61, 66 }, - { 4, 6, 11, NA, NA, NA, 28, NA, NA, NA, 45, 50, 55, 58, 62, 67 } -}; - -static unsigned int ASUS_FALCHION_LAYOUT_KEYS_UK[5][16] = -{ - { 0, 5, 8, 13, 17, 21, 25, 30, 34, 38, 42, 47, 52, 57, NA, 64 }, - { 1, NA, 9, 14, 18, 22, 26, 31, 35, 39, 43, 48, 53, 58, 61, 65 }, - { 2, NA, 10, 15, 19, 23, 27, 32, 36, 40, 44, 49, 54, 59, NA, 66 }, - { 3, 6, 11, 16, 20, 24, 28, 33, 37, 41, 45, 50, 55, NA, 62, 67 }, - { 4, 7, 12, NA, NA, NA, 29, NA, NA, NA, 46, 51, 56, 60, 63, 68 } -}; - -static unsigned int ASUS_CLAYMORE_NO_NUMPAD_LAYOUT_KEYS_US[7][19] = -{ - { 0, NA, 8, 14, 19, 24, NA, 34, 39, 45, 50, 56, 62, 67, 71, NA, 75, 79, 84 }, - { 1, 6, 9, 15, 20, 25, 29, 35, 40, 46, 51, 57, 63, 68, NA, NA, 76, 80, 85 }, - { 2, NA, 10, 16, 21, 26, 30, 36, 41, 47, 52, 58, 64, 69, 72, NA, 77, 81, 86 }, - { 3, NA, 11, 17, 22, 27, 31, 37, 42, 48, 53, 59, 65, NA, 73, NA, NA, NA, NA }, - { 4, NA, 12, 18, 23, 28, 32, 38, 43, 49, 54, 60, NA, 70, NA, NA, NA, 82, NA }, - { 5, 7, 13, NA, NA, NA, 33, NA, NA, NA, 55, 61, 66, NA, 74, NA, 78, 83, 87 }, - { NA, NA, NA, NA, NA, NA, NA, NA, 44, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA } -}; - -static unsigned int ASUS_CLAYMORE_NO_NUMPAD_LAYOUT_KEYS_UK[7][19] = -{ - { 0, NA, 9, 15, 20, 25, NA, 35, 40, 46, 51, 57, 63, 68, 73, NA, 76, 80, 85 }, - { 1, 6, 10, 16, 21, 26, 30, 36, 41, 47, 52, 58, 64, 69, NA, NA, 77, 81, 86 }, - { 2, NA, 11, 17, 22, 27, 31, 37, 42, 48, 53, 59, 65, 70, NA, NA, 78, 82, 87 }, - { 3, NA, 12, 18, 23, 28, 32, 38, 43, 49, 54, 60, 66, 71, 74, NA, NA, NA, NA }, - { 4, 7, 13, 19, 24, 29, 33, 39, 44, 50, 55, 61, NA, 72, NA, NA, NA, 83, NA }, - { 5, 8, 14, NA, NA, NA, 34, NA, NA, NA, 56, 62, 67, NA, 75, NA, 79, 84, 88 }, - { NA, NA, NA, NA, NA, NA, NA, NA, 45, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA } -}; - -static unsigned int ASUS_CLAYMORE_NUMPAD_RIGHT_LAYOUT_KEYS_US[7][24] = -{ - { 0, NA, 8, 14, 19, 24, NA, 34, 39, 45, 50, 56, 62, 67, 71, NA, 75, 79, 84, NA, NA, NA, NA, NA }, - { 1, 6, 9, 15, 20, 25, 29, 35, 40, 46, 51, 57, 63, 68, NA, NA, 76, 80, 85, NA, 88, 93, 97, 102 }, - { 2, NA, 10, 16, 21, 26, 30, 36, 41, 47, 52, 58, 64, 69, 72, NA, 77, 81, 86, NA, 89, 94, 98, 103 }, - { 3, NA, 11, 17, 22, 27, 31, 37, 42, 48, 53, 59, 65, NA, 73, NA, NA, NA, NA, NA, 90, 95, 99, NA }, - { 4, NA, 12, 18, 23, 28, 32, 38, 43, 49, 54, 60, NA, 70, NA, NA, NA, 82, NA, NA, 91, 96, 100, 104 }, - { 5, 7, 13, NA, NA, NA, 33, NA, NA, NA, 55, 61, 66, NA, 74, NA, 78, 83, 87, NA, 92, NA, 101, NA }, - { NA, NA, NA, NA, NA, NA, NA, NA, 44, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA } -}; - -static unsigned int ASUS_CLAYMORE_NUMPAD_RIGHT_LAYOUT_KEYS_UK[7][24] = -{ - { 0, NA, 9, 15, 20, 25, NA, 35, 40, 46, 51, 57, 63, 68, 73, NA, 76, 80, 85, NA, NA, NA, NA, NA }, - { 1, 6, 10, 16, 21, 26, 30, 36, 41, 47, 52, 58, 64, 69, NA, NA, 77, 81, 86, NA, 89, 94, 98, 103 }, - { 2, NA, 11, 17, 22, 27, 31, 37, 42, 48, 53, 59, 65, 70, NA, NA, 78, 82, 87, NA, 90, 95, 99, 104 }, - { 3, NA, 12, 18, 23, 28, 32, 38, 43, 49, 54, 60, 66, 71, 74, NA, NA, NA, NA, NA, 91, 96, 100, NA }, - { 4, 7, 13, 19, 24, 29, 33, 39, 44, 50, 55, 61, NA, 72, NA, NA, NA, 83, NA, NA, 92, 97, 101, 105 }, - { 5, 8, 14, NA, NA, NA, 34, NA, NA, NA, 56, 62, 67, NA, 75, NA, 79, 84, 88, NA, 93, NA, 102, NA }, - { NA, NA, NA, NA, NA, NA, NA, NA, 45, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA } -}; - -static unsigned int ASUS_CLAYMORE_NUMPAD_LEFT_LAYOUT_KEYS_US[7][24] = -{ - { NA, NA, NA, NA, NA, 17, NA, 25, 31, 36, 41, NA, 51, 56, 62, 67, 73, 79, 84, 88, NA, 92, 96, 101 }, - { 0, 5, 9, 14, NA, 18, 23, 26, 32, 37, 42, 46, 52, 57, 63, 68, 74, 80, 85, NA, NA, 93, 97, 102 }, - { 1, 6, 10, 15, NA, 19, NA, 27, 33, 38, 43, 47, 53, 58, 64, 69, 75, 81, 86, 89, NA, 94, 98, 103 }, - { 2, 7, 11, NA, NA, 20, NA, 28, 34, 39, 44, 48, 54, 59, 65, 70, 76, 82, NA, 90, NA, NA, NA, NA }, - { 3, 8, 12, 16, NA, 21, NA, 29, 35, 40, 45, 49, 55, 60, 66, 71, 77, NA, 87, NA, NA, NA, 99, NA }, - { 4, NA, 13, NA, NA, 22, 24, 30, NA, NA, NA, 50, NA, NA, NA, 72, 78, 83, NA, 91, NA, 95, 100, 104 }, - { NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 61, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA } -}; - -static unsigned int ASUS_CLAYMORE_NUMPAD_LEFT_LAYOUT_KEYS_UK[7][24] = -{ - { NA, NA, NA, NA, NA, 17, NA, 26, 32, 37, 42, NA, 52, 57, 63, 68, 74, 80, 85, 90, NA, 93, 97, 102 }, - { 0, 5, 9, 14, NA, 18, 23, 27, 33, 38, 43, 47, 53, 58, 64, 69, 75, 81, 86, NA, NA, 94, 98, 103 }, - { 1, 6, 10, 15, NA, 19, NA, 28, 34, 39, 44, 48, 54, 59, 65, 70, 76, 82, 87, NA, NA, 95, 99, 104 }, - { 2, 7, 11, NA, NA, 20, NA, 29, 35, 40, 45, 49, 55, 60, 66, 71, 77, 83, 88, 91, NA, NA, NA, NA }, - { 3, 8, 12, 16, NA, 21, 24, 30, 36, 41, 46, 50, 56, 61, 67, 72, 78, NA, 89, NA, NA, NA, 100, NA }, - { 4, NA, 13, NA, NA, 22, 25, 31, NA, NA, NA, 51, NA, NA, NA, 73, 79, 84, NA, 92, NA, 96, 101, 105 }, - { NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 62, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA } -}; - -static unsigned int ASUS_TUF_K1_LAYOUT_KEYS[1][5] = -{ - { 0, 1, 2, 3, 4 }, -}; - -static std::map AsusTUFK7Layouts = -{ - { - ASUS_TUF_K7_LAYOUT_UK, - { - *ASUS_TUF_K7_LAYOUT_KEYS_UK, - 105, - 6, - 24, - { - { KEY_EN_ESCAPE, 0x00 }, - { KEY_EN_BACK_TICK, 0x01 }, - { KEY_EN_TAB, 0x02 }, - { KEY_EN_CAPS_LOCK, 0x03 }, - { KEY_EN_LEFT_SHIFT, 0x04 }, - { KEY_EN_LEFT_CONTROL, 0x05 }, - - { KEY_EN_1, 0x11 }, - { KEY_EN_ISO_BACK_SLASH, 0x0C }, - { KEY_EN_LEFT_WINDOWS, 0x0D }, - - { KEY_EN_F1, 0x18 }, - { KEY_EN_2, 0x19 }, - { KEY_EN_Q, 0x12 }, - { KEY_EN_A, 0x13 }, - { KEY_EN_Z, 0x14 }, - { KEY_EN_LEFT_ALT, 0x15 }, - - { KEY_EN_F2, 0x20 }, - { KEY_EN_3, 0x21 }, - { KEY_EN_W, 0x1A }, - { KEY_EN_S, 0x1B }, - { KEY_EN_X, 0x1C }, - - { KEY_EN_F3, 0x28 }, - { KEY_EN_4, 0x29 }, - { KEY_EN_E, 0x22 }, - { KEY_EN_D, 0x23 }, - { KEY_EN_C, 0x24 }, - - { KEY_EN_F4, 0x30 }, - { KEY_EN_5, 0x31 }, - { KEY_EN_R, 0x2A }, - { KEY_EN_F, 0x2B }, - { KEY_EN_V, 0x2C }, - - { KEY_EN_6, 0x39 }, - { KEY_EN_T, 0x32 }, - { KEY_EN_G, 0x33 }, - { KEY_EN_B, 0x34 }, - { KEY_EN_SPACE, 0x35 }, - - { KEY_EN_F5, 0x40 }, - { KEY_EN_7, 0x41 }, - { KEY_EN_Y, 0x3A }, - { KEY_EN_H, 0x3B }, - { KEY_EN_N, 0x3C }, - - { KEY_EN_F6, 0x48 }, - { KEY_EN_8, 0x49 }, - { KEY_EN_U, 0x42 }, - { KEY_EN_J, 0x43 }, - { KEY_EN_M, 0x44 }, - - { KEY_EN_F7, 0x50 }, - { KEY_EN_9, 0x51 }, - { KEY_EN_I, 0x4A }, - { KEY_EN_K, 0x4B }, - { KEY_EN_COMMA, 0x4C }, - - { KEY_EN_F8, 0x58 }, - { KEY_EN_0, 0x59 }, - { KEY_EN_O, 0x52 }, - { KEY_EN_L, 0x53 }, - { KEY_EN_PERIOD, 0x54 }, - { KEY_EN_RIGHT_ALT, 0x4D }, - - { KEY_EN_F9, 0x60 }, - { KEY_EN_MINUS, 0x61 }, - { KEY_EN_P, 0x5A }, - { KEY_EN_SEMICOLON, 0x5B }, - { KEY_EN_FORWARD_SLASH, 0x5C }, - { KEY_EN_RIGHT_FUNCTION, 0x5D }, - - { KEY_EN_F10, 0x68 }, - { KEY_EN_EQUALS, 0x69 }, - { KEY_EN_LEFT_BRACKET, 0x62 }, - { KEY_EN_QUOTE, 0x63 }, - { KEY_EN_MENU, 0x65 }, - - { KEY_EN_F11, 0x70 }, - { KEY_EN_BACKSPACE, 0x79 }, - { KEY_EN_RIGHT_BRACKET, 0x6A }, - { KEY_EN_POUND, 0x6B }, - { KEY_EN_RIGHT_SHIFT, 0x7C }, - - { KEY_EN_F12, 0x78 }, - { KEY_EN_ISO_ENTER, 0x7B }, - { KEY_EN_RIGHT_CONTROL, 0x7D }, - - { KEY_EN_PRINT_SCREEN, 0x80 }, - { KEY_EN_INSERT, 0x81 }, - { KEY_EN_DELETE, 0x82 }, - { KEY_EN_LEFT_ARROW, 0x85 }, - - { KEY_EN_SCROLL_LOCK, 0x88 }, - { KEY_EN_HOME, 0x89 }, - { KEY_EN_END, 0x8A }, - { KEY_EN_UP_ARROW, 0x8C }, - { KEY_EN_DOWN_ARROW, 0x8D }, - - { KEY_EN_PAUSE_BREAK, 0x90 }, - { KEY_EN_PAGE_UP, 0x91 }, - { KEY_EN_PAGE_DOWN, 0x92 }, - { KEY_EN_RIGHT_ARROW, 0x95 }, - - { KEY_EN_NUMPAD_LOCK, 0x99 }, - { KEY_EN_NUMPAD_7, 0x9A }, - { KEY_EN_NUMPAD_4, 0x9B }, - { KEY_EN_NUMPAD_1, 0x9C }, - { KEY_EN_NUMPAD_0, 0x9D }, - - { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, - { KEY_EN_NUMPAD_8, 0xA2 }, - { KEY_EN_NUMPAD_5, 0xA3 }, - { KEY_EN_NUMPAD_2, 0xA4 }, - - { KEY_EN_NUMPAD_TIMES, 0xA9 }, - { KEY_EN_NUMPAD_9, 0xAA }, - { KEY_EN_NUMPAD_6, 0xAB }, - { KEY_EN_NUMPAD_3, 0xAC }, - { KEY_EN_NUMPAD_PERIOD, 0xAD }, - - { KEY_EN_NUMPAD_MINUS, 0xB1 }, - { KEY_EN_NUMPAD_PLUS, 0xB2 }, - { KEY_EN_NUMPAD_ENTER, 0xB4 } - } - } - }, - { - ASUS_TUF_K7_LAYOUT_US, - { - *ASUS_TUF_K7_LAYOUT_KEYS_US, - 104, - 6, - 24, - { - { KEY_EN_ESCAPE, 0x00 }, - { KEY_EN_BACK_TICK, 0x01 }, - { KEY_EN_TAB, 0x02 }, - { KEY_EN_CAPS_LOCK, 0x03 }, - { KEY_EN_LEFT_SHIFT, 0x04 }, - { KEY_EN_LEFT_CONTROL, 0x05 }, - - { KEY_EN_1, 0x11 }, - { KEY_EN_LEFT_WINDOWS, 0x0D }, - - { KEY_EN_F1, 0x18 }, - { KEY_EN_2, 0x19 }, - { KEY_EN_Q, 0x12 }, - { KEY_EN_A, 0x13 }, - { KEY_EN_Z, 0x14 }, - { KEY_EN_LEFT_ALT, 0x15 }, - - { KEY_EN_F2, 0x20 }, - { KEY_EN_3, 0x21 }, - { KEY_EN_W, 0x1A }, - { KEY_EN_S, 0x1B }, - { KEY_EN_X, 0x1C }, - - { KEY_EN_F3, 0x28 }, - { KEY_EN_4, 0x29 }, - { KEY_EN_E, 0x22 }, - { KEY_EN_D, 0x23 }, - { KEY_EN_C, 0x24 }, - - { KEY_EN_F4, 0x30 }, - { KEY_EN_5, 0x31 }, - { KEY_EN_R, 0x2A }, - { KEY_EN_F, 0x2B }, - { KEY_EN_V, 0x2C }, - - { KEY_EN_6, 0x39 }, - { KEY_EN_T, 0x32 }, - { KEY_EN_G, 0x33 }, - { KEY_EN_B, 0x34 }, - { KEY_EN_SPACE, 0x35 }, - - { KEY_EN_F5, 0x40 }, - { KEY_EN_7, 0x41 }, - { KEY_EN_Y, 0x3A }, - { KEY_EN_H, 0x3B }, - { KEY_EN_N, 0x3C }, - - { KEY_EN_F6, 0x48 }, - { KEY_EN_8, 0x49 }, - { KEY_EN_U, 0x42 }, - { KEY_EN_J, 0x43 }, - { KEY_EN_M, 0x44 }, - - { KEY_EN_F7, 0x50 }, - { KEY_EN_9, 0x51 }, - { KEY_EN_I, 0x4A }, - { KEY_EN_K, 0x4B }, - { KEY_EN_COMMA, 0x4C }, - - { KEY_EN_F8, 0x58 }, - { KEY_EN_0, 0x59 }, - { KEY_EN_O, 0x52 }, - { KEY_EN_L, 0x53 }, - { KEY_EN_PERIOD, 0x54 }, - { KEY_EN_RIGHT_ALT, 0x4D }, - - { KEY_EN_F9, 0x60 }, - { KEY_EN_MINUS, 0x61 }, - { KEY_EN_P, 0x5A }, - { KEY_EN_SEMICOLON, 0x5B }, - { KEY_EN_FORWARD_SLASH, 0x5C }, - { KEY_EN_RIGHT_FUNCTION, 0x5D }, - - { KEY_EN_F10, 0x68 }, - { KEY_EN_EQUALS, 0x69 }, - { KEY_EN_LEFT_BRACKET, 0x62 }, - { KEY_EN_QUOTE, 0x63 }, - { KEY_EN_MENU, 0x65 }, - - { KEY_EN_F11, 0x70 }, - { KEY_EN_BACKSPACE, 0x79 }, - { KEY_EN_RIGHT_BRACKET, 0x6A }, - { KEY_EN_RIGHT_SHIFT, 0x7C }, - - { KEY_EN_F12, 0x78 }, - { KEY_EN_ANSI_BACK_SLASH, 0x7A }, - { KEY_EN_ANSI_ENTER, 0x7B }, - { KEY_EN_RIGHT_CONTROL, 0x7D }, - - { KEY_EN_PRINT_SCREEN, 0x80 }, - { KEY_EN_INSERT, 0x81 }, - { KEY_EN_DELETE, 0x82 }, - { KEY_EN_LEFT_ARROW, 0x85 }, - - { KEY_EN_SCROLL_LOCK, 0x88 }, - { KEY_EN_HOME, 0x89 }, - { KEY_EN_END, 0x8A }, - { KEY_EN_UP_ARROW, 0x8C }, - { KEY_EN_DOWN_ARROW, 0x8D }, - - { KEY_EN_PAUSE_BREAK, 0x90 }, - { KEY_EN_PAGE_UP, 0x91 }, - { KEY_EN_PAGE_DOWN, 0x92 }, - { KEY_EN_RIGHT_ARROW, 0x95 }, - - { KEY_EN_NUMPAD_LOCK, 0x99 }, - { KEY_EN_NUMPAD_7, 0x9A }, - { KEY_EN_NUMPAD_4, 0x9B }, - { KEY_EN_NUMPAD_1, 0x9C }, - { KEY_EN_NUMPAD_0, 0x9D }, - - { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, - { KEY_EN_NUMPAD_8, 0xA2 }, - { KEY_EN_NUMPAD_5, 0xA3 }, - { KEY_EN_NUMPAD_2, 0xA4 }, - - { KEY_EN_NUMPAD_TIMES, 0xA9 }, - { KEY_EN_NUMPAD_9, 0xAA }, - { KEY_EN_NUMPAD_6, 0xAB }, - { KEY_EN_NUMPAD_3, 0xAC }, - { KEY_EN_NUMPAD_PERIOD, 0xAD }, - - { KEY_EN_NUMPAD_MINUS, 0xB1 }, - { KEY_EN_NUMPAD_PLUS, 0xB2 }, - { KEY_EN_NUMPAD_ENTER, 0xB4 } - } - } - }, -}; - -static std::map AsusFalchionLayouts = -{ - { - ASUS_TUF_K7_LAYOUT_UK, - { - *ASUS_FALCHION_LAYOUT_KEYS_UK, - 69, - 5, - 16, - { - { KEY_EN_ESCAPE, 0x00 }, - { KEY_EN_TAB, 0x01 }, - { KEY_EN_CAPS_LOCK, 0x02 }, - { KEY_EN_LEFT_SHIFT, 0x03 }, - { KEY_EN_LEFT_CONTROL, 0x04 }, - - { KEY_EN_1, 0x08 }, - { KEY_EN_ISO_BACK_SLASH, 0x0B }, - { KEY_EN_LEFT_WINDOWS, 0x0C }, - - { KEY_EN_2, 0x10 }, - { KEY_EN_Q, 0x09 }, - { KEY_EN_A, 0x0A }, - { KEY_EN_Z, 0x13 }, - { KEY_EN_LEFT_ALT, 0x14 }, - - { KEY_EN_3, 0x18 }, - { KEY_EN_W, 0x11 }, - { KEY_EN_S, 0x12 }, - { KEY_EN_X, 0x1B }, - - { KEY_EN_4, 0x20 }, - { KEY_EN_E, 0x19 }, - { KEY_EN_D, 0x1A }, - { KEY_EN_C, 0x23 }, - - { KEY_EN_5, 0x28 }, - { KEY_EN_R, 0x21 }, - { KEY_EN_F, 0x22 }, - { KEY_EN_V, 0x2B }, - - { KEY_EN_6, 0x30 }, - { KEY_EN_T, 0x29 }, - { KEY_EN_G, 0x2A }, - { KEY_EN_B, 0x33 }, - { KEY_EN_SPACE, 0x34 }, - - { KEY_EN_7, 0x38 }, - { KEY_EN_Y, 0x31 }, - { KEY_EN_H, 0x32 }, - { KEY_EN_N, 0x3B }, - - { KEY_EN_8, 0x40 }, - { KEY_EN_U, 0x39 }, - { KEY_EN_J, 0x3A }, - { KEY_EN_M, 0x43 }, - - { KEY_EN_9, 0x48 }, - { KEY_EN_I, 0x41 }, - { KEY_EN_K, 0x42 }, - { KEY_EN_COMMA, 0x4B }, - - { KEY_EN_0, 0x50 }, - { KEY_EN_O, 0x49 }, - { KEY_EN_L, 0x4A }, - { KEY_EN_PERIOD, 0x53 }, - { KEY_EN_RIGHT_ALT, 0x4C }, - - { KEY_EN_MINUS, 0x58 }, - { KEY_EN_P, 0x51 }, - { KEY_EN_SEMICOLON, 0x52 }, - { KEY_EN_FORWARD_SLASH, 0x5B }, - { KEY_EN_RIGHT_FUNCTION, 0x54 }, - - { KEY_EN_EQUALS, 0x60 }, - { KEY_EN_LEFT_BRACKET, 0x59 }, - { KEY_EN_QUOTE, 0x5A }, - { KEY_EN_RIGHT_SHIFT, 0x63 }, - { KEY_EN_RIGHT_CONTROL, 0x5C }, - - { KEY_EN_BACKSPACE, 0x68 }, - { KEY_EN_RIGHT_BRACKET, 0x61 }, - { KEY_EN_POUND, 0x62 }, - { KEY_EN_LEFT_ARROW, 0x64 }, - - { KEY_EN_ISO_ENTER, 0x6A }, - { KEY_EN_UP_ARROW, 0x6B }, - { KEY_EN_DOWN_ARROW, 0x6C }, - - { KEY_EN_INSERT, 0x70 }, - { KEY_EN_DELETE, 0x71 }, - { KEY_EN_PAGE_UP, 0x72 }, - { KEY_EN_PAGE_DOWN, 0x73 }, - { KEY_EN_RIGHT_ARROW, 0x74 }, - } - } - }, - { - ASUS_TUF_K7_LAYOUT_US, - { - *ASUS_FALCHION_LAYOUT_KEYS_US, - 68, - 5, - 16, - { - { KEY_EN_ESCAPE, 0x00 }, - { KEY_EN_TAB, 0x01 }, - { KEY_EN_CAPS_LOCK, 0x02 }, - { KEY_EN_LEFT_SHIFT, 0x03 }, - { KEY_EN_LEFT_CONTROL, 0x04 }, - - { KEY_EN_1, 0x08 }, - { KEY_EN_LEFT_WINDOWS, 0x0C }, - - { KEY_EN_2, 0x10 }, - { KEY_EN_Q, 0x09 }, - { KEY_EN_A, 0x0A }, - { KEY_EN_Z, 0x13 }, - { KEY_EN_LEFT_ALT, 0x14 }, - - { KEY_EN_3, 0x18 }, - { KEY_EN_W, 0x11 }, - { KEY_EN_S, 0x12 }, - { KEY_EN_X, 0x1B }, - - { KEY_EN_4, 0x20 }, - { KEY_EN_E, 0x19 }, - { KEY_EN_D, 0x1A }, - { KEY_EN_C, 0x23 }, - - { KEY_EN_5, 0x28 }, - { KEY_EN_R, 0x21 }, - { KEY_EN_F, 0x22 }, - { KEY_EN_V, 0x2B }, - - { KEY_EN_6, 0x30 }, - { KEY_EN_T, 0x29 }, - { KEY_EN_G, 0x2A }, - { KEY_EN_B, 0x33 }, - { KEY_EN_SPACE, 0x34 }, - - { KEY_EN_7, 0x38 }, - { KEY_EN_Y, 0x31 }, - { KEY_EN_H, 0x32 }, - { KEY_EN_N, 0x3B }, - - { KEY_EN_8, 0x40 }, - { KEY_EN_U, 0x39 }, - { KEY_EN_J, 0x3A }, - { KEY_EN_M, 0x43 }, - - { KEY_EN_9, 0x48 }, - { KEY_EN_I, 0x41 }, - { KEY_EN_K, 0x42 }, - { KEY_EN_COMMA, 0x4B }, - - { KEY_EN_0, 0x50 }, - { KEY_EN_O, 0x49 }, - { KEY_EN_L, 0x4A }, - { KEY_EN_PERIOD, 0x53 }, - { KEY_EN_RIGHT_ALT, 0x4C }, - - { KEY_EN_MINUS, 0x58 }, - { KEY_EN_P, 0x51 }, - { KEY_EN_SEMICOLON, 0x52 }, - { KEY_EN_FORWARD_SLASH, 0x5B }, - { KEY_EN_RIGHT_FUNCTION, 0x54 }, - - { KEY_EN_EQUALS, 0x60 }, - { KEY_EN_LEFT_BRACKET, 0x59 }, - { KEY_EN_QUOTE, 0x5A }, - { KEY_EN_RIGHT_SHIFT, 0x63 }, - { KEY_EN_RIGHT_CONTROL, 0x5C }, - - { KEY_EN_BACKSPACE, 0x68 }, - { KEY_EN_RIGHT_BRACKET, 0x61 }, - { KEY_EN_LEFT_ARROW, 0x64 }, - - { KEY_EN_ANSI_BACK_SLASH, 0x69 }, - { KEY_EN_ANSI_ENTER, 0x6A }, - { KEY_EN_UP_ARROW, 0x6B }, - { KEY_EN_DOWN_ARROW, 0x6C }, - - { KEY_EN_INSERT, 0x70 }, - { KEY_EN_DELETE, 0x71 }, - { KEY_EN_PAGE_UP, 0x72 }, - { KEY_EN_PAGE_DOWN, 0x73 }, - { KEY_EN_RIGHT_ARROW, 0x74 }, - } - } - }, -}; - - -static std::map AsusClaymoreNoNumpadLayouts = -{ - { - ASUS_TUF_K7_LAYOUT_UK, - { - *ASUS_CLAYMORE_NO_NUMPAD_LAYOUT_KEYS_UK, - 89, - 7, - 19, - { - { KEY_EN_ESCAPE, 0x00 }, - { KEY_EN_BACK_TICK, 0x01 }, - { KEY_EN_TAB, 0x02 }, - { KEY_EN_CAPS_LOCK, 0x03 }, - { KEY_EN_LEFT_SHIFT, 0x04 }, - { KEY_EN_LEFT_CONTROL, 0x05 }, - { KEY_EN_1, 0x09 }, - { KEY_EN_ISO_BACK_SLASH, 0x0C }, - { KEY_EN_LEFT_WINDOWS, 0x0D }, - { KEY_EN_F1, 0x10 }, - { KEY_EN_2, 0x11 }, - { KEY_EN_Q, 0x0A }, - { KEY_EN_A, 0x0B }, - { KEY_EN_Z, 0x14 }, - { KEY_EN_LEFT_ALT, 0x15 }, - { KEY_EN_F2, 0x18 }, - { KEY_EN_3, 0x19 }, - { KEY_EN_W, 0x12 }, - { KEY_EN_S, 0x13 }, - { KEY_EN_X, 0x1C }, - { KEY_EN_F3, 0x20 }, - { KEY_EN_4, 0x21 }, - { KEY_EN_E, 0x1A }, - { KEY_EN_D, 0x1B }, - { KEY_EN_C, 0x24 }, - { KEY_EN_F4, 0x28 }, - { KEY_EN_5, 0x29 }, - { KEY_EN_R, 0x22 }, - { KEY_EN_F, 0x23 }, - { KEY_EN_V, 0x2C }, - { KEY_EN_6, 0x31 }, - { KEY_EN_T, 0x2A }, - { KEY_EN_G, 0x2B }, - { KEY_EN_B, 0x34 }, - { KEY_EN_SPACE, 0x25 }, - { KEY_EN_F5, 0x38 }, - { KEY_EN_7, 0x39 }, - { KEY_EN_Y, 0x32 }, - { KEY_EN_H, 0x33 }, - { KEY_EN_N, 0x3C }, - { KEY_EN_F6, 0x40 }, - { KEY_EN_8, 0x41 }, - { KEY_EN_U, 0x3A }, - { KEY_EN_J, 0x3B }, - { KEY_EN_M, 0x44 }, - { "Logo", 0x45 }, - { KEY_EN_F7, 0x48 }, - { KEY_EN_9, 0x49 }, - { KEY_EN_I, 0x42 }, - { KEY_EN_K, 0x43 }, - { KEY_EN_COMMA, 0x4C }, - { KEY_EN_F8, 0x50 }, - { KEY_EN_0, 0x51 }, - { KEY_EN_O, 0x4A }, - { KEY_EN_L, 0x4B }, - { KEY_EN_PERIOD, 0x54 }, - { KEY_EN_RIGHT_ALT, 0x4D }, - { KEY_EN_F9, 0x60 }, - { KEY_EN_MINUS, 0x59 }, - { KEY_EN_P, 0x52 }, - { KEY_EN_SEMICOLON, 0x53 }, - { KEY_EN_FORWARD_SLASH, 0x5C }, - { KEY_EN_RIGHT_FUNCTION, 0x55 }, - { KEY_EN_F10, 0x68 }, - { KEY_EN_EQUALS, 0x61 }, - { KEY_EN_LEFT_BRACKET, 0x5A }, - { KEY_EN_QUOTE, 0x5B }, - { KEY_EN_MENU, 0x5D }, - { KEY_EN_F11, 0x70 }, - { KEY_EN_BACKSPACE, 0x69 }, - { KEY_EN_RIGHT_BRACKET, 0x62 }, - { KEY_EN_POUND, 0x63 }, - { KEY_EN_RIGHT_SHIFT, 0x6C }, - { KEY_EN_F12, 0x78 }, - { KEY_EN_ISO_ENTER, 0x6B }, - { KEY_EN_RIGHT_CONTROL, 0x6D }, - { KEY_EN_PRINT_SCREEN, 0x80 }, - { KEY_EN_INSERT, 0x81 }, - { KEY_EN_DELETE, 0x82 }, - { KEY_EN_LEFT_ARROW, 0x85 }, - { KEY_EN_SCROLL_LOCK, 0x88 }, - { KEY_EN_HOME, 0x89 }, - { KEY_EN_END, 0x8A }, - { KEY_EN_UP_ARROW, 0x8C }, - { KEY_EN_DOWN_ARROW, 0x8D }, - { KEY_EN_PAUSE_BREAK, 0x90 }, - { KEY_EN_PAGE_UP, 0x91 }, - { KEY_EN_PAGE_DOWN, 0x92 }, - { KEY_EN_RIGHT_ARROW, 0x95 } - } - } - }, - { - ASUS_TUF_K7_LAYOUT_US, - { - *ASUS_CLAYMORE_NO_NUMPAD_LAYOUT_KEYS_US, - 88, - 7, - 19, - { - { KEY_EN_ESCAPE, 0x00 }, - { KEY_EN_BACK_TICK, 0x01 }, - { KEY_EN_TAB, 0x02 }, - { KEY_EN_CAPS_LOCK, 0x03 }, - { KEY_EN_LEFT_SHIFT, 0x04 }, - { KEY_EN_LEFT_CONTROL, 0x05 }, - { KEY_EN_1, 0x09 }, - { KEY_EN_LEFT_WINDOWS, 0x0D }, - { KEY_EN_F1, 0x10 }, - { KEY_EN_2, 0x11 }, - { KEY_EN_Q, 0x0A }, - { KEY_EN_A, 0x0B }, - { KEY_EN_Z, 0x0C }, - { KEY_EN_LEFT_ALT, 0x15 }, - { KEY_EN_F2, 0x18 }, - { KEY_EN_3, 0x19 }, - { KEY_EN_W, 0x12 }, - { KEY_EN_S, 0x13 }, - { KEY_EN_X, 0x14 }, - { KEY_EN_F3, 0x20 }, - { KEY_EN_4, 0x21 }, - { KEY_EN_E, 0x1A }, - { KEY_EN_D, 0x1B }, - { KEY_EN_C, 0x1C }, - { KEY_EN_F4, 0x28 }, - { KEY_EN_5, 0x29 }, - { KEY_EN_R, 0x22 }, - { KEY_EN_F, 0x23 }, - { KEY_EN_V, 0x24 }, - { KEY_EN_6, 0x31 }, - { KEY_EN_T, 0x2A }, - { KEY_EN_G, 0x2B }, - { KEY_EN_B, 0x2C }, - { KEY_EN_SPACE, 0x25 }, - { KEY_EN_F5, 0x38 }, - { KEY_EN_7, 0x39 }, - { KEY_EN_Y, 0x32 }, - { KEY_EN_H, 0x33 }, - { KEY_EN_N, 0x34 }, - { KEY_EN_F6, 0x40 }, - { KEY_EN_8, 0x41 }, - { KEY_EN_U, 0x3A }, - { KEY_EN_J, 0x3B }, - { KEY_EN_M, 0x3C }, - { "Logo", 0x3D }, - { KEY_EN_F7, 0x48 }, - { KEY_EN_9, 0x49 }, - { KEY_EN_I, 0x42 }, - { KEY_EN_K, 0x43 }, - { KEY_EN_COMMA, 0x44 }, - { KEY_EN_F8, 0x50 }, - { KEY_EN_0, 0x51 }, - { KEY_EN_O, 0x4A }, - { KEY_EN_L, 0x4B }, - { KEY_EN_PERIOD, 0x4C }, - { KEY_EN_RIGHT_ALT, 0x4D }, - { KEY_EN_F9, 0x60 }, - { KEY_EN_MINUS, 0x59 }, - { KEY_EN_P, 0x52 }, - { KEY_EN_SEMICOLON, 0x53 }, - { KEY_EN_FORWARD_SLASH, 0x54 }, - { KEY_EN_RIGHT_FUNCTION, 0x55 }, - { KEY_EN_F10, 0x68 }, - { KEY_EN_EQUALS, 0x61 }, - { KEY_EN_LEFT_BRACKET, 0x5A }, - { KEY_EN_QUOTE, 0x5B }, - { KEY_EN_MENU, 0x5D }, - { KEY_EN_F11, 0x70 }, - { KEY_EN_BACKSPACE, 0x69 }, - { KEY_EN_RIGHT_BRACKET, 0x62 }, - { KEY_EN_RIGHT_SHIFT, 0x6C }, - { KEY_EN_F12, 0x78 }, - { KEY_EN_ANSI_BACK_SLASH, 0x6A }, - { KEY_EN_ANSI_ENTER, 0x6B }, - { KEY_EN_RIGHT_CONTROL, 0x6D }, - { KEY_EN_PRINT_SCREEN, 0x80 }, - { KEY_EN_INSERT, 0x81 }, - { KEY_EN_DELETE, 0x82 }, - { KEY_EN_LEFT_ARROW, 0x85 }, - { KEY_EN_SCROLL_LOCK, 0x88 }, - { KEY_EN_HOME, 0x89 }, - { KEY_EN_END, 0x8A }, - { KEY_EN_UP_ARROW, 0x8C }, - { KEY_EN_DOWN_ARROW, 0x8D }, - { KEY_EN_PAUSE_BREAK, 0x90 }, - { KEY_EN_PAGE_UP, 0x91 }, - { KEY_EN_PAGE_DOWN, 0x92 }, - { KEY_EN_RIGHT_ARROW, 0x95 } - } - } - }, -}; - -static std::map AsusClaymoreNumpadRightLayouts = -{ - { - ASUS_TUF_K7_LAYOUT_UK, - { - *ASUS_CLAYMORE_NUMPAD_RIGHT_LAYOUT_KEYS_UK, - 106, - 7, - 24, - { - { KEY_EN_ESCAPE, 0x00 }, - { KEY_EN_BACK_TICK, 0x01 }, - { KEY_EN_TAB, 0x02 }, - { KEY_EN_CAPS_LOCK, 0x03 }, - { KEY_EN_LEFT_SHIFT, 0x04 }, - { KEY_EN_LEFT_CONTROL, 0x05 }, - { KEY_EN_1, 0x09 }, - { KEY_EN_ISO_BACK_SLASH, 0x0C }, - { KEY_EN_LEFT_WINDOWS, 0x0D }, - { KEY_EN_F1, 0x10 }, - { KEY_EN_2, 0x11 }, - { KEY_EN_Q, 0x0A }, - { KEY_EN_A, 0x0B }, - { KEY_EN_Z, 0x14 }, - { KEY_EN_LEFT_ALT, 0x15 }, - { KEY_EN_F2, 0x18 }, - { KEY_EN_3, 0x19 }, - { KEY_EN_W, 0x12 }, - { KEY_EN_S, 0x13 }, - { KEY_EN_X, 0x1C }, - { KEY_EN_F3, 0x20 }, - { KEY_EN_4, 0x21 }, - { KEY_EN_E, 0x1A }, - { KEY_EN_D, 0x1B }, - { KEY_EN_C, 0x24 }, - { KEY_EN_F4, 0x28 }, - { KEY_EN_5, 0x29 }, - { KEY_EN_R, 0x22 }, - { KEY_EN_F, 0x23 }, - { KEY_EN_V, 0x2C }, - { KEY_EN_6, 0x31 }, - { KEY_EN_T, 0x2A }, - { KEY_EN_G, 0x2B }, - { KEY_EN_B, 0x34 }, - { KEY_EN_SPACE, 0x25 }, - { KEY_EN_F5, 0x38 }, - { KEY_EN_7, 0x39 }, - { KEY_EN_Y, 0x32 }, - { KEY_EN_H, 0x33 }, - { KEY_EN_N, 0x3C }, - { KEY_EN_F6, 0x40 }, - { KEY_EN_8, 0x41 }, - { KEY_EN_U, 0x3A }, - { KEY_EN_J, 0x3B }, - { KEY_EN_M, 0x44 }, - { "Logo", 0x45 }, - { KEY_EN_F7, 0x48 }, - { KEY_EN_9, 0x49 }, - { KEY_EN_I, 0x42 }, - { KEY_EN_K, 0x43 }, - { KEY_EN_COMMA, 0x4C }, - { KEY_EN_F8, 0x50 }, - { KEY_EN_0, 0x51 }, - { KEY_EN_O, 0x4A }, - { KEY_EN_L, 0x4B }, - { KEY_EN_PERIOD, 0x54 }, - { KEY_EN_RIGHT_ALT, 0x4D }, - { KEY_EN_F9, 0x60 }, - { KEY_EN_MINUS, 0x59 }, - { KEY_EN_P, 0x52 }, - { KEY_EN_SEMICOLON, 0x53 }, - { KEY_EN_FORWARD_SLASH, 0x5C }, - { KEY_EN_RIGHT_FUNCTION, 0x55 }, - { KEY_EN_F10, 0x68 }, - { KEY_EN_EQUALS, 0x61 }, - { KEY_EN_LEFT_BRACKET, 0x5A }, - { KEY_EN_QUOTE, 0x5B }, - { KEY_EN_MENU, 0x5D }, - { KEY_EN_F11, 0x70 }, - { KEY_EN_BACKSPACE, 0x69 }, - { KEY_EN_RIGHT_BRACKET, 0x62 }, - { KEY_EN_POUND, 0x63 }, - { KEY_EN_RIGHT_SHIFT, 0x6C }, - { KEY_EN_F12, 0x78 }, - { KEY_EN_ISO_ENTER, 0x6B }, - { KEY_EN_RIGHT_CONTROL, 0x6D }, - { KEY_EN_PRINT_SCREEN, 0x80 }, - { KEY_EN_INSERT, 0x81 }, - { KEY_EN_DELETE, 0x82 }, - { KEY_EN_LEFT_ARROW, 0x85 }, - { KEY_EN_SCROLL_LOCK, 0x88 }, - { KEY_EN_HOME, 0x89 }, - { KEY_EN_END, 0x8A }, - { KEY_EN_UP_ARROW, 0x8C }, - { KEY_EN_DOWN_ARROW, 0x8D }, - { KEY_EN_PAUSE_BREAK, 0x90 }, - { KEY_EN_PAGE_UP, 0x91 }, - { KEY_EN_PAGE_DOWN, 0x92 }, - { KEY_EN_RIGHT_ARROW, 0x95 }, - { KEY_EN_NUMPAD_LOCK, 0x99 }, - { KEY_EN_NUMPAD_7, 0x9A }, - { KEY_EN_NUMPAD_4, 0x9B }, - { KEY_EN_NUMPAD_1, 0x9C }, - { KEY_EN_NUMPAD_0, 0x9D }, - { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, - { KEY_EN_NUMPAD_8, 0xA2 }, - { KEY_EN_NUMPAD_5, 0xA3 }, - { KEY_EN_NUMPAD_2, 0xA4 }, - { KEY_EN_NUMPAD_TIMES, 0xA9 }, - { KEY_EN_NUMPAD_9, 0xAA }, - { KEY_EN_NUMPAD_6, 0xAB }, - { KEY_EN_NUMPAD_3, 0xAC }, - { KEY_EN_NUMPAD_PERIOD, 0xAD }, - { KEY_EN_NUMPAD_MINUS, 0xB1 }, - { KEY_EN_NUMPAD_PLUS, 0xB2 }, - { KEY_EN_NUMPAD_ENTER, 0xB4 } - } - } - }, - { - ASUS_TUF_K7_LAYOUT_US, - { - *ASUS_CLAYMORE_NUMPAD_RIGHT_LAYOUT_KEYS_US, - 105, - 7, - 24, - { - { KEY_EN_ESCAPE, 0x00 }, - { KEY_EN_BACK_TICK, 0x01 }, - { KEY_EN_TAB, 0x02 }, - { KEY_EN_CAPS_LOCK, 0x03 }, - { KEY_EN_LEFT_SHIFT, 0x04 }, - { KEY_EN_LEFT_CONTROL, 0x05 }, - { KEY_EN_1, 0x09 }, - { KEY_EN_LEFT_WINDOWS, 0x0D }, - { KEY_EN_F1, 0x10 }, - { KEY_EN_2, 0x11 }, - { KEY_EN_Q, 0x0A }, - { KEY_EN_A, 0x0B }, - { KEY_EN_Z, 0x0C }, - { KEY_EN_LEFT_ALT, 0x15 }, - { KEY_EN_F2, 0x18 }, - { KEY_EN_3, 0x19 }, - { KEY_EN_W, 0x12 }, - { KEY_EN_S, 0x13 }, - { KEY_EN_X, 0x14 }, - { KEY_EN_F3, 0x20 }, - { KEY_EN_4, 0x21 }, - { KEY_EN_E, 0x1A }, - { KEY_EN_D, 0x1B }, - { KEY_EN_C, 0x1C }, - { KEY_EN_F4, 0x28 }, - { KEY_EN_5, 0x29 }, - { KEY_EN_R, 0x22 }, - { KEY_EN_F, 0x23 }, - { KEY_EN_V, 0x24 }, - { KEY_EN_6, 0x31 }, - { KEY_EN_T, 0x2A }, - { KEY_EN_G, 0x2B }, - { KEY_EN_B, 0x2C }, - { KEY_EN_SPACE, 0x25 }, - { KEY_EN_F5, 0x38 }, - { KEY_EN_7, 0x39 }, - { KEY_EN_Y, 0x32 }, - { KEY_EN_H, 0x33 }, - { KEY_EN_N, 0x34 }, - { KEY_EN_F6, 0x40 }, - { KEY_EN_8, 0x41 }, - { KEY_EN_U, 0x3A }, - { KEY_EN_J, 0x3B }, - { KEY_EN_M, 0x3C }, - { "Logo", 0x3D }, - { KEY_EN_F7, 0x48 }, - { KEY_EN_9, 0x49 }, - { KEY_EN_I, 0x42 }, - { KEY_EN_K, 0x43 }, - { KEY_EN_COMMA, 0x44 }, - { KEY_EN_F8, 0x50 }, - { KEY_EN_0, 0x51 }, - { KEY_EN_O, 0x4A }, - { KEY_EN_L, 0x4B }, - { KEY_EN_PERIOD, 0x4C }, - { KEY_EN_RIGHT_ALT, 0x4D }, - { KEY_EN_F9, 0x60 }, - { KEY_EN_MINUS, 0x59 }, - { KEY_EN_P, 0x52 }, - { KEY_EN_SEMICOLON, 0x53 }, - { KEY_EN_FORWARD_SLASH, 0x54 }, - { KEY_EN_RIGHT_FUNCTION, 0x55 }, - { KEY_EN_F10, 0x68 }, - { KEY_EN_EQUALS, 0x61 }, - { KEY_EN_LEFT_BRACKET, 0x5A }, - { KEY_EN_QUOTE, 0x5B }, - { KEY_EN_MENU, 0x5D }, - { KEY_EN_F11, 0x70 }, - { KEY_EN_BACKSPACE, 0x69 }, - { KEY_EN_RIGHT_BRACKET, 0x62 }, - { KEY_EN_RIGHT_SHIFT, 0x6C }, - { KEY_EN_F12, 0x78 }, - { KEY_EN_ANSI_BACK_SLASH, 0x6A }, - { KEY_EN_ANSI_ENTER, 0x6B }, - { KEY_EN_RIGHT_CONTROL, 0x6D }, - { KEY_EN_PRINT_SCREEN, 0x80 }, - { KEY_EN_INSERT, 0x81 }, - { KEY_EN_DELETE, 0x82 }, - { KEY_EN_LEFT_ARROW, 0x85 }, - { KEY_EN_SCROLL_LOCK, 0x88 }, - { KEY_EN_HOME, 0x89 }, - { KEY_EN_END, 0x8A }, - { KEY_EN_UP_ARROW, 0x8C }, - { KEY_EN_DOWN_ARROW, 0x8D }, - { KEY_EN_PAUSE_BREAK, 0x90 }, - { KEY_EN_PAGE_UP, 0x91 }, - { KEY_EN_PAGE_DOWN, 0x92 }, - { KEY_EN_RIGHT_ARROW, 0x95 }, - { KEY_EN_NUMPAD_LOCK, 0x99 }, - { KEY_EN_NUMPAD_7, 0x9A }, - { KEY_EN_NUMPAD_4, 0x9B }, - { KEY_EN_NUMPAD_1, 0x9C }, - { KEY_EN_NUMPAD_0, 0x9D }, - { KEY_EN_NUMPAD_DIVIDE, 0xA1 }, - { KEY_EN_NUMPAD_8, 0xA2 }, - { KEY_EN_NUMPAD_5, 0xA3 }, - { KEY_EN_NUMPAD_2, 0xA4 }, - { KEY_EN_NUMPAD_TIMES, 0xA9 }, - { KEY_EN_NUMPAD_9, 0xAA }, - { KEY_EN_NUMPAD_6, 0xAB }, - { KEY_EN_NUMPAD_3, 0xAC }, - { KEY_EN_NUMPAD_PERIOD, 0xAD }, - { KEY_EN_NUMPAD_MINUS, 0xB1 }, - { KEY_EN_NUMPAD_PLUS, 0xB2 }, - { KEY_EN_NUMPAD_ENTER, 0xB4 } - } - } - }, -}; - -static std::map AsusClaymoreNumpadLeftLayouts = -{ - { - ASUS_TUF_K7_LAYOUT_UK, - { - *ASUS_CLAYMORE_NUMPAD_LEFT_LAYOUT_KEYS_UK, - 106, - 7, - 24, - { - { KEY_EN_NUMPAD_LOCK, 0x01 }, - { KEY_EN_NUMPAD_7, 0x02 }, - { KEY_EN_NUMPAD_4, 0x03 }, - { KEY_EN_NUMPAD_1, 0x04 }, - { KEY_EN_NUMPAD_0, 0x05 }, - { KEY_EN_NUMPAD_DIVIDE, 0x09 }, - { KEY_EN_NUMPAD_8, 0x0A }, - { KEY_EN_NUMPAD_5, 0x0B }, - { KEY_EN_NUMPAD_2, 0x0C }, - { KEY_EN_NUMPAD_TIMES, 0x11 }, - { KEY_EN_NUMPAD_9, 0x12 }, - { KEY_EN_NUMPAD_6, 0x13 }, - { KEY_EN_NUMPAD_3, 0x14 }, - { KEY_EN_NUMPAD_PERIOD, 0x15 }, - { KEY_EN_NUMPAD_MINUS, 0x19 }, - { KEY_EN_NUMPAD_PLUS, 0x1A }, - { KEY_EN_NUMPAD_ENTER, 0x1C }, - { KEY_EN_ESCAPE, 0x20 }, - { KEY_EN_BACK_TICK, 0x21 }, - { KEY_EN_TAB, 0x22 }, - { KEY_EN_CAPS_LOCK, 0x23 }, - { KEY_EN_LEFT_SHIFT, 0x24 }, - { KEY_EN_LEFT_CONTROL, 0x25 }, - { KEY_EN_1, 0x29 }, - { KEY_EN_ISO_BACK_SLASH, 0x2C }, - { KEY_EN_LEFT_WINDOWS, 0x2D }, - { KEY_EN_F1, 0x30 }, - { KEY_EN_2, 0x31 }, - { KEY_EN_Q, 0x2A }, - { KEY_EN_A, 0x2B }, - { KEY_EN_Z, 0x34 }, - { KEY_EN_LEFT_ALT, 0x35 }, - { KEY_EN_F2, 0x38 }, - { KEY_EN_3, 0x39 }, - { KEY_EN_W, 0x32 }, - { KEY_EN_S, 0x33 }, - { KEY_EN_X, 0x3C }, - { KEY_EN_F3, 0x40 }, - { KEY_EN_4, 0x41 }, - { KEY_EN_E, 0x3A }, - { KEY_EN_D, 0x3B }, - { KEY_EN_C, 0x44 }, - { KEY_EN_F4, 0x48 }, - { KEY_EN_5, 0x49 }, - { KEY_EN_R, 0x42 }, - { KEY_EN_F, 0x43 }, - { KEY_EN_V, 0x4C }, - { KEY_EN_6, 0x51 }, - { KEY_EN_T, 0x4A }, - { KEY_EN_G, 0x4B }, - { KEY_EN_B, 0x54 }, - { KEY_EN_SPACE, 0x45 }, - { KEY_EN_F5, 0x58 }, - { KEY_EN_7, 0x59 }, - { KEY_EN_Y, 0x52 }, - { KEY_EN_H, 0x53 }, - { KEY_EN_N, 0x5C }, - { KEY_EN_F6, 0x60 }, - { KEY_EN_8, 0x61 }, - { KEY_EN_U, 0x5A }, - { KEY_EN_J, 0x5B }, - { KEY_EN_M, 0x64 }, - { "Logo", 0x65 }, - { KEY_EN_F7, 0x68 }, - { KEY_EN_9, 0x69 }, - { KEY_EN_I, 0x62 }, - { KEY_EN_K, 0x63 }, - { KEY_EN_COMMA, 0x6C }, - { KEY_EN_F8, 0x70 }, - { KEY_EN_0, 0x71 }, - { KEY_EN_O, 0x6A }, - { KEY_EN_L, 0x6B }, - { KEY_EN_PERIOD, 0x74 }, - { KEY_EN_RIGHT_ALT, 0x6D }, - { KEY_EN_F9, 0x80 }, - { KEY_EN_MINUS, 0x79 }, - { KEY_EN_P, 0x72 }, - { KEY_EN_SEMICOLON, 0x73 }, - { KEY_EN_FORWARD_SLASH, 0x7C }, - { KEY_EN_RIGHT_FUNCTION, 0x75 }, - { KEY_EN_F10, 0x88 }, - { KEY_EN_EQUALS, 0x81 }, - { KEY_EN_LEFT_BRACKET, 0x7A }, - { KEY_EN_QUOTE, 0x7B }, - { KEY_EN_MENU, 0x7D }, - { KEY_EN_F11, 0x90 }, - { KEY_EN_BACKSPACE, 0x89 }, - { KEY_EN_RIGHT_BRACKET, 0x82 }, - { KEY_EN_POUND, 0x83 }, - { KEY_EN_RIGHT_SHIFT, 0x8C }, - { KEY_EN_F12, 0x98 }, - { KEY_EN_ISO_ENTER, 0x8B }, - { KEY_EN_RIGHT_CONTROL, 0x8D }, - { KEY_EN_PRINT_SCREEN, 0xA0 }, - { KEY_EN_INSERT, 0xA1 }, - { KEY_EN_DELETE, 0xA2 }, - { KEY_EN_LEFT_ARROW, 0xA5 }, - { KEY_EN_SCROLL_LOCK, 0xA8 }, - { KEY_EN_HOME, 0xA9 }, - { KEY_EN_END, 0xAA }, - { KEY_EN_UP_ARROW, 0xAC }, - { KEY_EN_DOWN_ARROW, 0xAD }, - { KEY_EN_PAUSE_BREAK, 0xB0 }, - { KEY_EN_PAGE_UP, 0xB1 }, - { KEY_EN_PAGE_DOWN, 0xB2 }, - { KEY_EN_RIGHT_ARROW, 0xB5 } - } - } - }, - { - ASUS_TUF_K7_LAYOUT_US, - { - *ASUS_CLAYMORE_NUMPAD_LEFT_LAYOUT_KEYS_US, - 105, - 7, - 24, - { - { KEY_EN_NUMPAD_LOCK, 0x01 }, - { KEY_EN_NUMPAD_7, 0x02 }, - { KEY_EN_NUMPAD_4, 0x03 }, - { KEY_EN_NUMPAD_1, 0x04 }, - { KEY_EN_NUMPAD_0, 0x05 }, - { KEY_EN_NUMPAD_DIVIDE, 0x09 }, - { KEY_EN_NUMPAD_8, 0x0A }, - { KEY_EN_NUMPAD_5, 0x0B }, - { KEY_EN_NUMPAD_2, 0x0C }, - { KEY_EN_NUMPAD_TIMES, 0x11 }, - { KEY_EN_NUMPAD_9, 0x12 }, - { KEY_EN_NUMPAD_6, 0x13 }, - { KEY_EN_NUMPAD_3, 0x14 }, - { KEY_EN_NUMPAD_PERIOD, 0x15 }, - { KEY_EN_NUMPAD_MINUS, 0x19 }, - { KEY_EN_NUMPAD_PLUS, 0x1A }, - { KEY_EN_NUMPAD_ENTER, 0x1C }, - { KEY_EN_ESCAPE, 0x20 }, - { KEY_EN_BACK_TICK, 0x21 }, - { KEY_EN_TAB, 0x22 }, - { KEY_EN_CAPS_LOCK, 0x23 }, - { KEY_EN_LEFT_SHIFT, 0x24 }, - { KEY_EN_LEFT_CONTROL, 0x25 }, - { KEY_EN_1, 0x29 }, - { KEY_EN_LEFT_WINDOWS, 0x2D }, - { KEY_EN_F1, 0x30 }, - { KEY_EN_2, 0x31 }, - { KEY_EN_Q, 0x2A }, - { KEY_EN_A, 0x2B }, - { KEY_EN_Z, 0x2C }, - { KEY_EN_LEFT_ALT, 0x35 }, - { KEY_EN_F2, 0x38 }, - { KEY_EN_3, 0x39 }, - { KEY_EN_W, 0x32 }, - { KEY_EN_S, 0x33 }, - { KEY_EN_X, 0x34 }, - { KEY_EN_F3, 0x40 }, - { KEY_EN_4, 0x41 }, - { KEY_EN_E, 0x3A }, - { KEY_EN_D, 0x3B }, - { KEY_EN_C, 0x3C }, - { KEY_EN_F4, 0x48 }, - { KEY_EN_5, 0x49 }, - { KEY_EN_R, 0x42 }, - { KEY_EN_F, 0x43 }, - { KEY_EN_V, 0x44 }, - { KEY_EN_6, 0x51 }, - { KEY_EN_T, 0x4A }, - { KEY_EN_G, 0x4B }, - { KEY_EN_B, 0x4C }, - { KEY_EN_SPACE, 0x45 }, - { KEY_EN_F5, 0x58 }, - { KEY_EN_7, 0x59 }, - { KEY_EN_Y, 0x52 }, - { KEY_EN_H, 0x53 }, - { KEY_EN_N, 0x54 }, - { KEY_EN_F6, 0x60 }, - { KEY_EN_8, 0x61 }, - { KEY_EN_U, 0x5A }, - { KEY_EN_J, 0x5B }, - { KEY_EN_M, 0x5C }, - { "Logo", 0x5D }, - { KEY_EN_F7, 0x68 }, - { KEY_EN_9, 0x69 }, - { KEY_EN_I, 0x62 }, - { KEY_EN_K, 0x63 }, - { KEY_EN_COMMA, 0x64 }, - { KEY_EN_F8, 0x70 }, - { KEY_EN_0, 0x71 }, - { KEY_EN_O, 0x6A }, - { KEY_EN_L, 0x6B }, - { KEY_EN_PERIOD, 0x6C }, - { KEY_EN_RIGHT_ALT, 0x6D }, - { KEY_EN_F9, 0x80 }, - { KEY_EN_MINUS, 0x79 }, - { KEY_EN_P, 0x72 }, - { KEY_EN_SEMICOLON, 0x73 }, - { KEY_EN_FORWARD_SLASH, 0x74 }, - { KEY_EN_RIGHT_FUNCTION, 0x75 }, - { KEY_EN_F10, 0x88 }, - { KEY_EN_EQUALS, 0x81 }, - { KEY_EN_LEFT_BRACKET, 0x7A }, - { KEY_EN_QUOTE, 0x7B }, - { KEY_EN_MENU, 0x7D }, - { KEY_EN_F11, 0x90 }, - { KEY_EN_BACKSPACE, 0x89 }, - { KEY_EN_RIGHT_BRACKET, 0x82 }, - { KEY_EN_RIGHT_SHIFT, 0x8C }, - { KEY_EN_F12, 0x98 }, - { KEY_EN_ANSI_BACK_SLASH, 0x8A }, - { KEY_EN_ANSI_ENTER, 0x8B }, - { KEY_EN_RIGHT_CONTROL, 0x8D }, - { KEY_EN_PRINT_SCREEN, 0xA0 }, - { KEY_EN_INSERT, 0xA1 }, - { KEY_EN_DELETE, 0xA2 }, - { KEY_EN_LEFT_ARROW, 0xA5 }, - { KEY_EN_SCROLL_LOCK, 0xA8 }, - { KEY_EN_HOME, 0xA9 }, - { KEY_EN_END, 0xAA }, - { KEY_EN_UP_ARROW, 0xAC }, - { KEY_EN_DOWN_ARROW, 0xAD }, - { KEY_EN_PAUSE_BREAK, 0xB0 }, - { KEY_EN_PAGE_UP, 0xB1 }, - { KEY_EN_PAGE_DOWN, 0xB2 }, - { KEY_EN_RIGHT_ARROW, 0xB5 } - } - } - }, -}; - -static std::map AsusTufK1Layouts = -{ - { - ASUS_TUF_K7_LAYOUT_UK, - { - *ASUS_TUF_K1_LAYOUT_KEYS, - 5, - 1, - 5, - { - { "Keyboard LED 1", 0x00 }, - { "Keyboard LED 2", 0x01 }, - { "Keyboard LED 3", 0x02 }, - { "Keyboard LED 4", 0x03 }, - { "Keyboard LED 5", 0x04 }, - } - } - }, - { - ASUS_TUF_K7_LAYOUT_US, - { - *ASUS_TUF_K1_LAYOUT_KEYS, - 5, - 1, - 5, - { - { "Keyboard LED 1", 0x00 }, - { "Keyboard LED 2", 0x01 }, - { "Keyboard LED 3", 0x02 }, - { "Keyboard LED 4", 0x03 }, - { "Keyboard LED 5", 0x04 }, - } - } - }, -}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraUSBController.cpp b/Controllers/AsusAuraUSBController/AsusAuraUSBController.cpp deleted file mode 100644 index 0bd38ff8..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraUSBController.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraUSBController.cpp | -| | -| Driver for ASUS Aura RGB USB | -| lighting controller | -| | -| Martin Hartl (inlart) 4/25/2020 | -\*-----------------------------------------*/ - -#include "AsusAuraUSBController.h" -#include "LogManager.h" - -#include -#include - -AuraUSBController::AuraUSBController(hid_device* dev_handle, const char* path) -{ - dev = dev_handle; - location = path; - - GetFirmwareVersion(); - GetConfigTable(); -} - -AuraUSBController::~AuraUSBController() -{ - hid_close(dev); -} - -unsigned int AuraUSBController::GetChannelCount() -{ - return(device_info.size()); -} - -std::string AuraUSBController::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string AuraUSBController::GetDeviceName() -{ - return(device_name); -} - -std::string AuraUSBController::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); -} - -const std::vector& AuraUSBController::GetAuraDevices() const -{ - return(device_info); -} - -void AuraUSBController::GetConfigTable() -{ - unsigned char usb_buf[65]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, sizeof(usb_buf)); - - /*-----------------------------------------------------*\ - | Set up config table request packet | - \*-----------------------------------------------------*/ - usb_buf[0x00] = 0xEC; - usb_buf[0x01] = AURA_REQUEST_CONFIG_TABLE; - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); - hid_read(dev, usb_buf, 65); - - /*-----------------------------------------------------*\ - | Copy the firmware string if the reply ID is correct | - \*-----------------------------------------------------*/ - if(usb_buf[1] == 0x30) - { - memcpy(config_table, &usb_buf[4], 60); - - LOG_DEBUG("[%s] ASUS Aura USB config table:", device_name); - - for(int i = 0; i < 60; i+=6) - { - LOG_DEBUG("[%s] %02X %02X %02X %02X %02X %02X", device_name, - config_table[i + 0], - config_table[i + 1], - config_table[i + 2], - config_table[i + 3], - config_table[i + 4], - config_table[i + 5]); - } - } - else - { - LOG_INFO("[%s] Could not read config table, can not add device", device_name); - delete this; - } -} - -void AuraUSBController::GetFirmwareVersion() -{ - unsigned char usb_buf[65]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, sizeof(usb_buf)); - - /*-----------------------------------------------------*\ - | Set up firmware version request packet | - \*-----------------------------------------------------*/ - usb_buf[0x00] = 0xEC; - usb_buf[0x01] = AURA_REQUEST_FIRMWARE_VERSION; - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); - hid_read(dev, usb_buf, 65); - - /*-----------------------------------------------------*\ - | Copy the firmware string if the reply ID is correct | - \*-----------------------------------------------------*/ - if(usb_buf[1] == 0x02) - { - memcpy(device_name, &usb_buf[2], 16); - } -} - -void AuraUSBController::SendDirect - ( - unsigned char device, - unsigned char start_led, - unsigned char led_count, - unsigned char* led_data, - bool apply /* = false */ - ) -{ - unsigned char usb_buf[65]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, sizeof(usb_buf)); - - /*-----------------------------------------------------*\ - | Set up message packet | - \*-----------------------------------------------------*/ - usb_buf[0x00] = 0xEC; - usb_buf[0x01] = AURA_CONTROL_MODE_DIRECT; - usb_buf[0x02] = apply ? 0x80 : 0x00; - usb_buf[0x02] |= device; - usb_buf[0x03] = start_led; - usb_buf[0x04] = led_count; - - /*-----------------------------------------------------*\ - | Copy in color data bytes | - \*-----------------------------------------------------*/ - memcpy(&usb_buf[0x05], led_data, led_count * 3); - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); -} diff --git a/Controllers/AsusAuraUSBController/AsusAuraUSBController.h b/Controllers/AsusAuraUSBController/AsusAuraUSBController.h deleted file mode 100644 index fb005504..00000000 --- a/Controllers/AsusAuraUSBController/AsusAuraUSBController.h +++ /dev/null @@ -1,112 +0,0 @@ -/*-----------------------------------------*\ -| AsusAuraUSBController.h | -| | -| Definitions and types for ASUS Aura | -| USB RGB lighting controller | -| | -| Martin Hartl (inlart) 4/25/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include "LogManager.h" - -#include -#include -#include - -#pragma once - -enum -{ - AURA_MODE_OFF = 0, /* OFF mode */ - AURA_MODE_STATIC = 1, /* Static color mode */ - AURA_MODE_BREATHING = 2, /* Breathing effect mode */ - AURA_MODE_FLASHING = 3, /* Flashing effect mode */ - AURA_MODE_SPECTRUM_CYCLE = 4, /* Spectrum Cycle mode */ - AURA_MODE_RAINBOW = 5, /* Rainbow effect mode */ - AURA_MODE_SPECTRUM_CYCLE_BREATHING = 6, /* Rainbow Breathing effect mode */ - AURA_MODE_CHASE_FADE = 7, /* Chase with Fade effect mode */ - AURA_MODE_SPECTRUM_CYCLE_CHASE_FADE = 8, /* Chase with Fade, Rainbow effect mode */ - AURA_MODE_CHASE = 9, /* Chase effect mode */ - AURA_MODE_SPECTRUM_CYCLE_CHASE = 10, /* Chase with Rainbow effect mode */ - AURA_MODE_SPECTRUM_CYCLE_WAVE = 11, /* Wave effect mode */ - AURA_MODE_CHASE_RAINBOW_PULSE = 12, /* Chase with Rainbow Pulse effect mode*/ - AURA_MODE_RANDOM_FLICKER = 13, /* Random flicker effect mode */ - AURA_MODE_MUSIC = 14, /* Music effect mode */ - AURA_MODE_DIRECT = 0xFF, /* Direct control mode */ -}; - -enum -{ - AURA_REQUEST_FIRMWARE_VERSION = 0x82, /* Request firmware string */ - AURA_REQUEST_CONFIG_TABLE = 0xB0, /* Request configuration table */ - AURA_CONTROL_MODE_DIRECT = 0x40, /* Direct control mode */ -}; - -enum class AuraDeviceType -{ - FIXED, - ADDRESSABLE, -}; - -struct AuraDeviceInfo -{ - unsigned char effect_channel; - unsigned char direct_channel; - unsigned char num_leds; - unsigned char num_headers; - AuraDeviceType device_type; -}; - -class AuraUSBController -{ -public: - AuraUSBController(hid_device* dev_handle, const char* path); - virtual ~AuraUSBController(); - - unsigned int GetChannelCount(); - - std::string GetDeviceLocation(); - std::string GetDeviceName(); - std::string GetSerialString(); - - const std::vector& GetAuraDevices() const; - - virtual void SetChannelLEDs - ( - unsigned char channel, - RGBColor * colors, - unsigned int num_colors - ) = 0; - - virtual void SetMode - ( - unsigned char channel, - unsigned char mode, - unsigned char red, - unsigned char grn, - unsigned char blu - ) = 0; - -protected: - hid_device* dev; - unsigned char config_table[60]; - std::vector device_info; - std::string location; - - void SendDirect - ( - unsigned char device, - unsigned char start_led, - unsigned char led_count, - unsigned char* led_data, - bool apply = false - ); -private: - char device_name[16]; - unsigned int led_count; - - void GetConfigTable(); - - void GetFirmwareVersion(); -}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraAddressableController.cpp b/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraAddressableController.cpp new file mode 100644 index 00000000..b7f1d077 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraAddressableController.cpp @@ -0,0 +1,96 @@ +/*---------------------------------------------------------*\ +| AsusAuraAddressableController.cpp | +| | +| Driver for ASUS Aura addressable controller | +| | +| Adam Honse (CalcProgrammer1) 18 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "AsusAuraAddressableController.h" + +AuraAddressableController::AuraAddressableController(hid_device* dev_handle, const char* path, std::string dev_name) : AuraUSBController(dev_handle, path, dev_name) +{ + /*-----------------------------------------------------*\ + | Add addressable devices | + \*-----------------------------------------------------*/ + for(int i = 0; i < config_table[0x02]; ++i) + { + device_info.push_back({0x01, (unsigned char)i, 0x01, 0, AuraDeviceType::ADDRESSABLE}); + } +} + +AuraAddressableController::~AuraAddressableController() +{ + +} + +void AuraAddressableController::SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors) +{ + SendDirect + ( + device_info[channel].direct_channel, + num_colors, + colors + ); +} + +void AuraAddressableController::SetMode + ( + unsigned char channel, + unsigned char mode, + unsigned char red, + unsigned char grn, + unsigned char blu + ) +{ + SendEffect + ( + channel, + mode, + red, + grn, + blu + ); +} + +void AuraAddressableController::SendEffect + ( + unsigned char channel, + unsigned char mode, + unsigned char red, + unsigned char grn, + unsigned char blu + ) +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up message packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0xEC; + usb_buf[0x01] = AURA_ADDRESSABLE_CONTROL_MODE_EFFECT; + usb_buf[0x02] = channel; + usb_buf[0x03] = 0x00; + usb_buf[0x04] = mode; + + /*-----------------------------------------------------*\ + | Copy in color data bytes | + \*-----------------------------------------------------*/ + usb_buf[0x05] = red; + usb_buf[0x06] = grn; + usb_buf[0x07] = blu; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); +} diff --git a/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraAddressableController.h b/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraAddressableController.h new file mode 100644 index 00000000..e27db876 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraAddressableController.h @@ -0,0 +1,56 @@ +/*---------------------------------------------------------*\ +| AsusAuraAddressableController.h | +| | +| Driver for ASUS Aura addressable controller | +| | +| Adam Honse (CalcProgrammer1) 18 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" +#include "AsusAuraUSBController.h" + +enum +{ + AURA_ADDRESSABLE_CONTROL_MODE_EFFECT = 0x3B, /* Effect control mode */ +}; + +class AuraAddressableController : public AuraUSBController +{ +public: + AuraAddressableController(hid_device* dev_handle, const char* path, std::string dev_name); + ~AuraAddressableController(); + + void SetChannelLEDs + ( + unsigned char channel, + RGBColor * colors, + unsigned int num_colors + ); + + void SetMode + ( + unsigned char channel, + unsigned char mode, + unsigned char red, + unsigned char grn, + unsigned char blu + ); + +private: + + void SendEffect + ( + unsigned char channel, + unsigned char mode, + unsigned char red, + unsigned char grn, + unsigned char blu + ); +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraMainboardController.cpp b/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraMainboardController.cpp new file mode 100644 index 00000000..0660ac22 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraMainboardController.cpp @@ -0,0 +1,209 @@ +/*---------------------------------------------------------*\ +| AsusAuraMainboardController.cpp | +| | +| Driver for ASUS Aura mainboard | +| | +| Martin Hartl (inlart) 25 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "AsusAuraMainboardController.h" + +AuraMainboardController::AuraMainboardController(hid_device* dev_handle, const char* path, std::string dev_name) : AuraUSBController(dev_handle, path, dev_name), mode(AURA_MODE_DIRECT) +{ + unsigned char num_total_mainboard_leds = config_table[0x1B]; + unsigned char num_rgb_headers = config_table[0x1D]; + unsigned char num_addressable_headers = config_table[0x02]; + unsigned char effect_channel = 0; + + if(num_total_mainboard_leds < num_rgb_headers) + { + num_rgb_headers = 0; + } + + /*-----------------------------------------------------*\ + | Add mainboard device | + \*-----------------------------------------------------*/ + if(num_total_mainboard_leds > 0) + { + device_info.push_back({effect_channel, 0x04, num_total_mainboard_leds, num_rgb_headers, AuraDeviceType::FIXED}); + effect_channel++; + } + + /*-----------------------------------------------------*\ + | Add addressable devices | + \*-----------------------------------------------------*/ + for(int i = 0; i < num_addressable_headers; i++) + { + device_info.push_back({effect_channel, (unsigned char)i, 0x01, 0, AuraDeviceType::ADDRESSABLE}); + effect_channel++; + } +} + +AuraMainboardController::~AuraMainboardController() +{ +} + +void AuraMainboardController::SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors) +{ + SendDirect + ( + device_info[channel].direct_channel, + num_colors, + colors + ); + +} + +void AuraMainboardController::SetMode + ( + unsigned char channel, + unsigned char mode, + unsigned char red, + unsigned char grn, + unsigned char blu + ) +{ + SetMode(channel, mode, red, grn, blu, false); +} + +void AuraMainboardController::SetMode + ( + unsigned char channel, + unsigned char mode, + unsigned char red, + unsigned char grn, + unsigned char blu, + bool shutdown_effect + ) +{ + this->mode = mode; + RGBColor color = ToRGBColor(red, grn, blu); + + SendEffect(device_info[channel].effect_channel, mode, shutdown_effect); + if(mode == AURA_MODE_DIRECT) + { + return; + } + + unsigned char led_data[60]; + unsigned char start_led = 0; + + for(std::size_t i = 0; i < channel; ++i) + { + start_led += device_info[i].num_leds; + } + + for(std::size_t led_idx = 0; led_idx < device_info[channel].num_leds; led_idx++) + { + led_data[(led_idx * 3) + 0] = RGBGetRValue(color); + led_data[(led_idx * 3) + 1] = RGBGetGValue(color); + led_data[(led_idx * 3) + 2] = RGBGetBValue(color); + } + + SendColor + ( + channel, + start_led, + device_info[channel].num_leds, + led_data, + shutdown_effect + ); +} + +unsigned short AuraMainboardController::GetMask(int start, int size) +{ + return(((1 << size) - 1) << start); +} + +void AuraMainboardController::SendEffect + ( + unsigned char channel, + unsigned char mode, + bool shutdown_effect + ) +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up message packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0xEC; + usb_buf[0x01] = AURA_MAINBOARD_CONTROL_MODE_EFFECT; + usb_buf[0x02] = channel; + usb_buf[0x03] = 0x00; + usb_buf[0x04] = shutdown_effect ? 0x01 : 0x00; + usb_buf[0x05] = mode; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); +} + +void AuraMainboardController::SendColor + ( + unsigned char /*channel*/, + unsigned char start_led, + unsigned char led_count, + unsigned char* led_data, + bool shutdown_effect + ) +{ + unsigned short mask = GetMask(start_led, led_count); + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up message packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0xEC; + usb_buf[0x01] = AURA_MAINBOARD_CONTROL_MODE_EFFECT_COLOR; + usb_buf[0x02] = mask >> 8; + usb_buf[0x03] = mask & 0xff; + usb_buf[0x04] = shutdown_effect ? 0x01 : 0x00; + + /*-----------------------------------------------------*\ + | Copy in color data bytes | + \*-----------------------------------------------------*/ + memcpy(&usb_buf[0x05 + 3 * start_led], led_data, led_count * 3); + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); +} + +void AuraMainboardController::SendCommit() +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up message packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0xEC; + usb_buf[0x01] = AURA_MAINBOARD_CONTROL_MODE_COMMIT; + usb_buf[0x02] = 0x55; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); +} diff --git a/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraMainboardController.h b/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraMainboardController.h new file mode 100644 index 00000000..095be43e --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraMainboardController.h @@ -0,0 +1,80 @@ +/*---------------------------------------------------------*\ +| AsusAuraMainboardController.h | +| | +| Driver for ASUS Aura mainboard | +| | +| Martin Hartl (inlart) 25 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" +#include "AsusAuraUSBController.h" + +enum +{ + AURA_MAINBOARD_CONTROL_MODE_EFFECT = 0x35, /* Effect control mode */ + AURA_MAINBOARD_CONTROL_MODE_EFFECT_COLOR = 0x36, /* Effect color control mode */ + AURA_MAINBOARD_CONTROL_MODE_COMMIT = 0x3F, /* Commit mode */ +}; + +class AuraMainboardController : public AuraUSBController +{ +public: + AuraMainboardController(hid_device* dev_handle, const char* path, std::string dev_name); + ~AuraMainboardController(); + + void SetChannelLEDs + ( + unsigned char channel, + RGBColor * colors, + unsigned int num_colors + ); + + void SetMode + ( + unsigned char channel, + unsigned char mode, + unsigned char red, + unsigned char grn, + unsigned char blu + ); + + void SetMode + ( + unsigned char channel, + unsigned char mode, + unsigned char red, + unsigned char grn, + unsigned char blu, + bool shutdown_effect + ); + + void SendCommit(); + +private: + unsigned int mode; + + unsigned short GetMask(int start, int size); + + void SendEffect + ( + unsigned char channel, + unsigned char mode, + bool shutdown_effect + ); + + void SendColor + ( + unsigned char channel, + unsigned char start_led, + unsigned char led_count, + unsigned char* led_data, + bool shutdown_effect + ); +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraUSBController.cpp b/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraUSBController.cpp new file mode 100644 index 00000000..b70aa96e --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraUSBController.cpp @@ -0,0 +1,203 @@ +/*---------------------------------------------------------*\ +| AsusAuraUSBController.cpp | +| | +| Driver for ASUS Aura USB device | +| | +| Martin Hartl (inlart) 25 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "AsusAuraUSBController.h" +#include "LogManager.h" +#include "StringUtils.h" + +AuraUSBController::AuraUSBController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + + GetFirmwareVersion(); + GetConfigTable(); +} + +AuraUSBController::~AuraUSBController() +{ + hid_close(dev); +} + +unsigned int AuraUSBController::GetChannelCount() +{ + return((unsigned int)device_info.size()); +} + +std::string AuraUSBController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string AuraUSBController::GetDeviceName() +{ + return(name); +} + +std::string AuraUSBController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string AuraUSBController::GetDeviceVersion() +{ + return(std::string(version)); +} + +const std::vector& AuraUSBController::GetAuraDevices() const +{ + return(device_info); +} + +void AuraUSBController::GetConfigTable() +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up config table request packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0xEC; + usb_buf[0x01] = AURA_REQUEST_CONFIG_TABLE; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); + hid_read(dev, usb_buf, 65); + + /*-----------------------------------------------------*\ + | Copy the firmware string if the reply ID is correct | + \*-----------------------------------------------------*/ + if(usb_buf[1] == 0x30) + { + memcpy(config_table, &usb_buf[4], 60); + + LOG_DEBUG("[%s] ASUS Aura USB config table:", version); + + for(int i = 0; i < 60; i+=6) + { + LOG_DEBUG("[%s] %02X %02X %02X %02X %02X %02X", version, + config_table[i + 0], + config_table[i + 1], + config_table[i + 2], + config_table[i + 3], + config_table[i + 4], + config_table[i + 5]); + } + } + else + { + LOG_INFO("[%s] Could not read config table, can not add device", version); + delete this; + } +} + +void AuraUSBController::GetFirmwareVersion() +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up firmware version request packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0xEC; + usb_buf[0x01] = AURA_REQUEST_FIRMWARE_VERSION; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); + hid_read(dev, usb_buf, 65); + + /*-----------------------------------------------------*\ + | Copy the firmware string if the reply ID is correct | + \*-----------------------------------------------------*/ + if(usb_buf[1] == 0x02) + { + memcpy(version, &usb_buf[2], 16); + } +} + +void AuraUSBController::SendDirect + ( + unsigned char device, + unsigned char led_count, + RGBColor* colors + ) +{ + unsigned char usb_buf[65]; + unsigned char offset = 0x00; + unsigned char sent_led_count = LEDS_PER_PACKET; + bool apply = false; + while(!apply) + { + if(offset + sent_led_count > led_count) + { + sent_led_count = led_count - offset; + } + + + if(offset + sent_led_count == led_count) + { + apply = true; + } + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up message packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0xEC; + usb_buf[0x01] = AURA_CONTROL_MODE_DIRECT; + usb_buf[0x02] = (apply ? 0x80 : 0x00) | device; + usb_buf[0x03] = offset; + usb_buf[0x04] = sent_led_count; + + /*-----------------------------------------------------*\ + | Copy in color data bytes | + \*-----------------------------------------------------*/ + for(unsigned char led_idx = 0; led_idx < sent_led_count; led_idx++) + { + + usb_buf[0x05 + (led_idx * 3)] = RGBGetRValue(colors[offset + led_idx]); + usb_buf[0x06 + (led_idx * 3)] = RGBGetGValue(colors[offset + led_idx]); + usb_buf[0x07 + (led_idx * 3)] = RGBGetBValue(colors[offset + led_idx]); + } + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); + + offset += sent_led_count; + } +} diff --git a/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraUSBController.h b/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraUSBController.h new file mode 100644 index 00000000..a6931caa --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraUSBController/AsusAuraUSBController.h @@ -0,0 +1,113 @@ +/*---------------------------------------------------------*\ +| AsusAuraUSBController.h | +| | +| Driver for ASUS Aura USB device | +| | +| Martin Hartl (inlart) 25 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" +#include "LogManager.h" + +enum +{ + AURA_MODE_OFF = 0, /* OFF mode */ + AURA_MODE_STATIC = 1, /* Static color mode */ + AURA_MODE_BREATHING = 2, /* Breathing effect mode */ + AURA_MODE_FLASHING = 3, /* Flashing effect mode */ + AURA_MODE_SPECTRUM_CYCLE = 4, /* Spectrum Cycle mode */ + AURA_MODE_RAINBOW = 5, /* Rainbow effect mode */ + AURA_MODE_SPECTRUM_CYCLE_BREATHING = 6, /* Rainbow Breathing effect mode */ + AURA_MODE_CHASE_FADE = 7, /* Chase with Fade effect mode */ + AURA_MODE_SPECTRUM_CYCLE_CHASE_FADE = 8, /* Chase with Fade, Rainbow effect mode */ + AURA_MODE_CHASE = 9, /* Chase effect mode */ + AURA_MODE_SPECTRUM_CYCLE_CHASE = 10, /* Chase with Rainbow effect mode */ + AURA_MODE_SPECTRUM_CYCLE_WAVE = 11, /* Wave effect mode */ + AURA_MODE_CHASE_RAINBOW_PULSE = 12, /* Chase with Rainbow Pulse effect mode*/ + AURA_MODE_RANDOM_FLICKER = 13, /* Random flicker effect mode */ + AURA_MODE_MUSIC = 14, /* Music effect mode */ + AURA_MODE_DIRECT = 0xFF, /* Direct control mode */ +}; + +enum +{ + AURA_REQUEST_FIRMWARE_VERSION = 0x82, /* Request firmware string */ + AURA_REQUEST_CONFIG_TABLE = 0xB0, /* Request configuration table */ + AURA_CONTROL_MODE_DIRECT = 0x40, /* Direct control mode */ +}; + +enum class AuraDeviceType +{ + FIXED, + ADDRESSABLE, +}; + +#define LEDS_PER_PACKET 0x14; + +struct AuraDeviceInfo +{ + unsigned char effect_channel; + unsigned char direct_channel; + unsigned char num_leds; + unsigned char num_headers; + AuraDeviceType device_type; +}; + +class AuraUSBController +{ +public: + AuraUSBController(hid_device* dev_handle, const char* path, std::string dev_name); + virtual ~AuraUSBController(); + + unsigned int GetChannelCount(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + std::string GetSerialString(); + std::string GetDeviceVersion(); + + const std::vector& GetAuraDevices() const; + + virtual void SetChannelLEDs + ( + unsigned char channel, + RGBColor * colors, + unsigned int num_colors + ) = 0; + + virtual void SetMode + ( + unsigned char channel, + unsigned char mode, + unsigned char red, + unsigned char grn, + unsigned char blu + ) = 0; + +protected: + hid_device* dev; + unsigned char config_table[60]; + std::vector device_info; + std::string location; + std::string name; + char version[16]; + + void SendDirect + ( + unsigned char device, + unsigned char led_count, + RGBColor * colors + ); + +private: + void GetConfigTable(); + void GetFirmwareVersion(); +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraUSBController/RGBController_AsusAuraMainboard.cpp b/Controllers/AsusAuraUSBController/AsusAuraUSBController/RGBController_AsusAuraMainboard.cpp new file mode 100644 index 00000000..76517eee --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraUSBController/RGBController_AsusAuraMainboard.cpp @@ -0,0 +1,77 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraMainboard.cpp | +| | +| RGBController for ASUS Aura mainboard | +| | +| rytypete 30 Aug 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_AsusAuraMainboard.h" + +/**------------------------------------------------------------------*\ + @name Asus Aura USB Mainboard + @category Motherboard + @type USB + @save :white_check_mark: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectAsusAuraUSBMotherboards + @comment The Asus Aura USB Mainboard controller applies to most + AMD and Intel mainboards from the x570 chipset onwards. +\*-------------------------------------------------------------------*/ + +RGBController_AuraMainboard::RGBController_AuraMainboard(AuraMainboardController* controller_ptr) : + RGBController_AuraUSB(controller_ptr) +{ + description = "ASUS Aura USB Mainboard Device"; + + /*-------------------------------------------------------*\ + | Add manual save flag to all modes except direct mode | + \*-------------------------------------------------------*/ + for(unsigned int mode_idx = 0; mode_idx < modes.size(); mode_idx++) + { + mode Mode = modes[mode_idx]; + if(Mode.value != AURA_MODE_DIRECT) + { + Mode.flags |= MODE_FLAG_MANUAL_SAVE; + modes[mode_idx] = Mode; + } + } +} + +void RGBController_AuraMainboard::DeviceUpdateShutdownEffect() +{ + unsigned char red = 0; + unsigned char grn = 0; + unsigned char blu = 0; + + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + red = RGBGetRValue(modes[active_mode].colors[0]); + grn = RGBGetGValue(modes[active_mode].colors[0]); + blu = RGBGetBValue(modes[active_mode].colors[0]); + } + + for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + AuraDeviceInfo device_info = controller->GetAuraDevices()[zone_idx]; + + /*---------------------------------------------------*\ + | Shutdown effect only works with onboard lighting | + \*---------------------------------------------------*/ + if(device_info.device_type == AuraDeviceType::FIXED && zones[zone_idx].leds_count > 0) + { + ((AuraMainboardController*) controller)->SetMode(zone_idx, modes[active_mode].value, red, grn, blu, true); + } + } +} + +void RGBController_AuraMainboard::DeviceSaveMode() +{ + DeviceUpdateMode(); + DeviceUpdateShutdownEffect(); + ((AuraMainboardController*) controller)->SendCommit(); +} diff --git a/Controllers/AsusAuraUSBController/AsusAuraUSBController/RGBController_AsusAuraMainboard.h b/Controllers/AsusAuraUSBController/AsusAuraUSBController/RGBController_AsusAuraMainboard.h new file mode 100644 index 00000000..aabcfad8 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraUSBController/RGBController_AsusAuraMainboard.h @@ -0,0 +1,26 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraMainboard.h | +| | +| RGBController for ASUS Aura mainboard | +| | +| rytypete 30 Aug 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController_AsusAuraUSB.h" +#include "AsusAuraMainboardController.h" + +class RGBController_AuraMainboard : public RGBController_AuraUSB +{ +public: + RGBController_AuraMainboard(AuraMainboardController* controller_ptr); + + void DeviceSaveMode(); + +private: + void DeviceUpdateShutdownEffect(); +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraUSBController/RGBController_AsusAuraUSB.cpp b/Controllers/AsusAuraUSBController/AsusAuraUSBController/RGBController_AsusAuraUSB.cpp new file mode 100644 index 00000000..49e15b47 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraUSBController/RGBController_AsusAuraUSB.cpp @@ -0,0 +1,275 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraUSB.cpp | +| | +| RGBController for ASUS Aura USB device | +| | +| Adam Honse (CalcProgrammer1) 18 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_AsusAuraUSB.h" + +/**------------------------------------------------------------------*\ + @name Asus Aura USB + @category Motherboard + @type USB + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectAsusAuraUSBTerminal,DetectAsusAuraUSBAddressable + @comment The Asus Aura USB controller applies to most AMD and + Intel mainboards from the x470 and z390 chipset generations. +\*-------------------------------------------------------------------*/ + +RGBController_AuraUSB::RGBController_AuraUSB(AuraUSBController* controller_ptr) : + initializedMode(false) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "ASUS"; + type = DEVICE_TYPE_MOTHERBOARD; + description = "ASUS Aura USB Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + version = controller->GetDeviceVersion(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = AURA_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Off; + Off.name = "Off"; + Off.value = AURA_MODE_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Static; + Static.name = "Static"; + Static.value = AURA_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Static.colors_min = 1; + Static.colors_max = 1; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors.resize(1); + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = AURA_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.colors.resize(1); + modes.push_back(Breathing); + + mode Flashing; + Flashing.name = "Flashing"; + Flashing.value = AURA_MODE_FLASHING; + Flashing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Flashing.colors_min = 1; + Flashing.colors_max = 1; + Flashing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Flashing.colors.resize(1); + modes.push_back(Flashing); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = AURA_MODE_SPECTRUM_CYCLE; + SpectrumCycle.flags = 0; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + modes.push_back(SpectrumCycle); + + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = AURA_MODE_RAINBOW; + Rainbow.flags = 0; + Rainbow.color_mode = MODE_COLORS_NONE; + modes.push_back(Rainbow); + + mode ChaseFade; + ChaseFade.name = "Chase Fade"; + ChaseFade.value = AURA_MODE_CHASE_FADE; + ChaseFade.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + ChaseFade.colors_min = 1; + ChaseFade.colors_max = 1; + ChaseFade.color_mode = MODE_COLORS_MODE_SPECIFIC; + ChaseFade.colors.resize(1); + modes.push_back(ChaseFade); + + mode Chase; + Chase.name = "Chase"; + Chase.value = AURA_MODE_CHASE; + Chase.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Chase.colors_min = 1; + Chase.colors_max = 1; + Chase.color_mode = MODE_COLORS_MODE_SPECIFIC; + Chase.colors.resize(1); + modes.push_back(Chase); + + SetupZones(); +} + +RGBController_AuraUSB::~RGBController_AuraUSB() +{ + delete controller; +} + +void RGBController_AuraUSB::SetupZones() +{ + /*-------------------------------------------------*\ + | Only set LED count on the first run | + \*-------------------------------------------------*/ + bool first_run = false; + + if(zones.size() == 0) + { + first_run = true; + } + + /*-------------------------------------------------*\ + | Clear any existing color/LED configuration | + \*-------------------------------------------------*/ + leds.clear(); + colors.clear(); + zones.resize(controller->GetChannelCount()); + + /*-------------------------------------------------*\ + | Set zones and leds | + \*-------------------------------------------------*/ + int addressableCounter = 1; + for (unsigned int channel_idx = 0; channel_idx < zones.size(); channel_idx++) + { + AuraDeviceInfo device_info = controller->GetAuraDevices()[channel_idx]; + + zones[channel_idx].type = ZONE_TYPE_LINEAR; + + if(device_info.device_type == AuraDeviceType::FIXED) + { + zones[channel_idx].name = "Aura Mainboard"; + zones[channel_idx].leds_min = device_info.num_leds; + zones[channel_idx].leds_max = device_info.num_leds; + zones[channel_idx].leds_count = device_info.num_leds; + } + else + { + zones[channel_idx].name = "Aura Addressable "; + zones[channel_idx].name.append(std::to_string(addressableCounter)); + zones[channel_idx].leds_min = 0; + zones[channel_idx].leds_max = AURA_ADDRESSABLE_MAX_LEDS; + + addressableCounter++; + + if(first_run) + { + zones[channel_idx].leds_count = 0; + } + } + + unsigned int num_mainboard_leds = device_info.num_leds - device_info.num_headers; + for (unsigned int led_ch_idx = 0; led_ch_idx < zones[channel_idx].leds_count; led_ch_idx++) + { + unsigned led_idx = led_ch_idx + 1; + led new_led; + + new_led.name = zones[channel_idx].name; + if(device_info.device_type == AuraDeviceType::FIXED && led_ch_idx >= num_mainboard_leds) + { + new_led.name.append(", RGB Header "); + led_idx -= num_mainboard_leds; + } + else + { + new_led.name.append(", LED "); + } + new_led.name.append(std::to_string(led_idx)); + + new_led.value = channel_idx; + + leds.push_back(new_led); + } + + zones[channel_idx].matrix_map = NULL; + } + + SetupColors(); +} + +void RGBController_AuraUSB::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_AuraUSB::DeviceUpdateLEDs() +{ + if(!initializedMode) + { + DeviceUpdateMode(); + } + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + controller->SetChannelLEDs((unsigned char)zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); + } +} + +void RGBController_AuraUSB::UpdateZoneLEDs(int zone) +{ + if(!initializedMode) + { + DeviceUpdateMode(); + } + + controller->SetChannelLEDs(zone, zones[zone].colors, zones[zone].leds_count); +} + +void RGBController_AuraUSB::UpdateSingleLED(int led) +{ + if(!initializedMode) + { + DeviceUpdateMode(); + } + + unsigned int channel = leds[led].value; + + controller->SetChannelLEDs(channel, zones[channel].colors, zones[channel].leds_count); +} + +void RGBController_AuraUSB::DeviceUpdateMode() +{ + initializedMode = true; + unsigned char red = 0; + unsigned char grn = 0; + unsigned char blu = 0; + + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + red = RGBGetRValue(modes[active_mode].colors[0]); + grn = RGBGetGValue(modes[active_mode].colors[0]); + blu = RGBGetBValue(modes[active_mode].colors[0]); + } + + for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + if(zones[zone_idx].leds_count > 0) + { + controller->SetMode(zone_idx, modes[active_mode].value, red, grn, blu); + } + } +} diff --git a/Controllers/AsusAuraUSBController/AsusAuraUSBController/RGBController_AsusAuraUSB.h b/Controllers/AsusAuraUSBController/AsusAuraUSBController/RGBController_AsusAuraUSB.h new file mode 100644 index 00000000..8082e9ea --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusAuraUSBController/RGBController_AsusAuraUSB.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusAuraUSB.h | +| | +| RGBController for ASUS Aura USB device | +| | +| Adam Honse (CalcProgrammer1) 18 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AsusAuraUSBController.h" + +#define AURA_ADDRESSABLE_MAX_LEDS 120 + +class RGBController_AuraUSB : public RGBController +{ +public: + RGBController_AuraUSB(AuraUSBController* controller_ptr); + ~RGBController_AuraUSB(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +protected: + AuraUSBController* controller; + +private: + std::vector leds_channel; + std::vector zones_channel; + bool initializedMode; +}; diff --git a/Controllers/AsusAuraUSBController/AsusAuraUSBControllerDetect.cpp b/Controllers/AsusAuraUSBController/AsusAuraUSBControllerDetect.cpp index 70e04a3e..80b95970 100644 --- a/Controllers/AsusAuraUSBController/AsusAuraUSBControllerDetect.cpp +++ b/Controllers/AsusAuraUSBController/AsusAuraUSBControllerDetect.cpp @@ -1,3 +1,14 @@ +/*---------------------------------------------------------*\ +| AsusAuraUSBControllerDetect.cpp | +| | +| Detector for ASUS Aura USB devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include #include "Detector.h" #include "AsusAuraAddressableController.h" #include "AsusAuraHeadsetStandController.h" @@ -5,106 +16,113 @@ #include "AsusAuraTUFKeyboardController.h" #include "AsusAuraMainboardController.h" #include "AsusAuraMouseController.h" -#include "AsusAuraMousematController.h" #include "AsusROGAllyController.h" -#include "AsusAuraStrixEvolveController.h" +#include "AsusROGStrixLCController.h" +#include "AsusAuraMouseGen1Controller.h" +#include "AsusAuraMousematController.h" #include "AsusAuraMonitorController.h" #include "AsusAuraRyuoAIOController.h" -#include "RGBController.h" #include "RGBController_AsusAuraUSB.h" #include "RGBController_AsusAuraHeadsetStand.h" #include "RGBController_AsusAuraKeyboard.h" #include "RGBController_AsusAuraTUFKeyboard.h" +#include "RGBController_AsusAuraMainboard.h" #include "RGBController_AsusAuraMouse.h" #include "RGBController_AsusAuraMousemat.h" #include "RGBController_AsusROGAlly.h" -#include "RGBController_ROGStrixLC_Controller.h" -#include "RGBController_AsusAuraStrixEvolve.h" +#include "RGBController_AsusROGStrixLC.h" +#include "RGBController_AsusROGSpatha.h" +#include "RGBController_AsusROGStrixEvolve.h" #include "RGBController_AsusAuraMonitor.h" #include "RGBController_AsusAuraRyuoAIO.h" -#include -#include -#include "dependencies/dmiinfo.h" +#include "dmiinfo.h" -#define AURA_USB_VID 0x0B05 +#define AURA_USB_VID 0x0B05 /*-----------------------------------------------------------------*\ | MOTHERBOARDS | \*-----------------------------------------------------------------*/ -#define AURA_ADDRESSABLE_1_PID 0x1867 -#define AURA_ADDRESSABLE_2_PID 0x1872 -#define AURA_ADDRESSABLE_3_PID 0x18A3 -#define AURA_ADDRESSABLE_4_PID 0x18A5 -#define AURA_MOTHERBOARD_1_PID 0x18F3 -#define AURA_MOTHERBOARD_2_PID 0x1939 -#define AURA_MOTHERBOARD_3_PID 0x19AF +#define AURA_ADDRESSABLE_1_PID 0x1867 +#define AURA_ADDRESSABLE_2_PID 0x1872 +#define AURA_ADDRESSABLE_3_PID 0x18A3 +#define AURA_ADDRESSABLE_4_PID 0x18A5 +#define AURA_MOTHERBOARD_1_PID 0x18F3 +#define AURA_MOTHERBOARD_2_PID 0x1939 +#define AURA_MOTHERBOARD_3_PID 0x19AF +#define AURA_MOTHERBOARD_4_PID 0x1AA6 /*-----------------------------------------------------------------*\ | KEYBOARDS | \*-----------------------------------------------------------------*/ -#define AURA_ROG_FALCHION_WIRED_PID 0x193C -#define AURA_ROG_FALCHION_WIRELESS_PID 0x193E -#define AURA_ROG_STRIX_FLARE_PID 0x1875 -#define AURA_ROG_STRIX_FLARE_PNK_LTD_PID 0x18CF -#define AURA_ROG_STRIX_FLARE_COD_BO4_PID 0x18AF -#define AURA_ROG_STRIX_SCOPE_PID 0x18F8 -#define AURA_ROG_STRIX_SCOPE_RX_PID 0x1951 -#define AURA_ROG_STRIX_SCOPE_TKL_PID 0x190C -#define AURA_ROG_STRIX_SCOPE_RX_TKL_DELUXE_PID 0x1A05 -#define AURA_ROG_STRIX_SCOPE_TKL_PNK_LTD_PID 0x1954 -#define AURA_ROG_CLAYMORE_PID 0x184D -#define AURA_TUF_K1_GAMING_PID 0x1945 -#define AURA_TUF_K3_GAMING_PID 0x194B -#define AURA_TUF_K5_GAMING_PID 0x1899 -#define AURA_TUF_K7_GAMING_PID 0x18AA +#define AURA_ROG_AZOTH_USB_PID 0x1A83 +#define AURA_ROG_AZOTH_2_4_PID 0x1A85 +#define AURA_ROG_CLAYMORE_PID 0x184D +#define AURA_ROG_FALCHION_WIRED_PID 0x193C +#define AURA_ROG_FALCHION_WIRELESS_PID 0x193E +#define AURA_ROG_STRIX_FLARE_PID 0x1875 +#define AURA_ROG_STRIX_FLARE_PNK_LTD_PID 0x18CF +#define AURA_ROG_STRIX_FLARE_COD_BO4_PID 0x18AF +#define AURA_ROG_STRIX_FLARE_II_ANIMATE_PID 0x19FC +#define AURA_ROG_STRIX_FLARE_II_PID 0x19FE +#define AURA_ROG_STRIX_SCOPE_PID 0x18F8 +#define AURA_ROG_STRIX_SCOPE_TKL_PID 0x190C +#define AURA_ROG_STRIX_SCOPE_TKL_PNK_LTD_PID 0x1954 +#define AURA_ROG_STRIX_SCOPE_RX_PID 0x1951 +#define AURA_ROG_STRIX_SCOPE_RX_EVA_02_PID 0x1B12 +#define AURA_ROG_STRIX_SCOPE_RX_TKL_DELUXE_PID 0x1A05 +#define AURA_ROG_STRIX_SCOPE_NX_WIRELESS_DELUXE_USB_PID 0x19F6 +#define AURA_ROG_STRIX_SCOPE_NX_WIRELESS_DELUXE_2_4_PID 0x19F8 +#define AURA_ROG_STRIX_SCOPE_II_PID 0x1AB3 +#define AURA_ROG_STRIX_SCOPE_II_RX_PID 0x1AB5 +#define AURA_ROG_STRIX_SCOPE_II_96_WIRELESS_USB_PID 0x1AAE +#define AURA_TUF_K1_GAMING_PID 0x1945 +#define AURA_TUF_K3_GAMING_PID 0x194B +#define AURA_TUF_K5_GAMING_PID 0x1899 +#define AURA_TUF_K7_GAMING_PID 0x18AA /*-----------------------------------------------------------------*\ | MICE - defined in AsusAuraMouseDevices.h | \*-----------------------------------------------------------------*/ - -#define AURA_ROG_STRIX_EVOLVE_PID 0x185B +#define AURA_ROG_STRIX_EVOLVE_PID 0x185B +#define AURA_ROG_SPATHA_WIRED_PID 0x181C +#define AURA_ROG_SPATHA_WIRELESS_PID 0x1824 /*-----------------------------------------------------------------*\ | MOUSEMATS | \*-----------------------------------------------------------------*/ -#define AURA_ROG_BALTEUS_PID 0x1891 -#define AURA_ROG_BALTEUS_QI_PID 0x1890 +#define AURA_ROG_BALTEUS_PID 0x1891 +#define AURA_ROG_BALTEUS_QI_PID 0x1890 /*-----------------------------------------------------------------*\ | MONITORS | \*-----------------------------------------------------------------*/ - -#define AURA_ROG_STRIX_XG27AQ_PID 0x198C -#define AURA_ROG_STRIX_XG27AQM_PID 0x19BB -#define AURA_ROG_STRIX_XG279Q_PID 0x1919 -#define AURA_ROG_STRIX_XG27W_PID 0x1933 -#define AURA_ROG_PG32UQ_PID 0x19B9 +#define AURA_ROG_STRIX_XG27AQ_PID 0x198C +#define AURA_ROG_STRIX_XG27AQM_PID 0x19BB +#define AURA_ROG_STRIX_XG279Q_PID 0x1919 +#define AURA_ROG_STRIX_XG27W_PID 0x1933 +#define AURA_ROG_STRIX_XG32VC_PID 0x1968 +#define AURA_ROG_PG32UQ_PID 0x19B9 /*-----------------------------------------------------------------*\ -| HEADSETSTANDS | +| HEADSET STANDS | \*-----------------------------------------------------------------*/ - -#define AURA_ROG_THRONE_PID 0x18D9 -#define AURA_ROG_THRONE_QI_PID 0x18C5 -#define AURA_ROG_THRONE_QI_GUNDAM_PID 0x1994 +#define AURA_ROG_THRONE_PID 0x18D9 +#define AURA_ROG_THRONE_QI_PID 0x18C5 +#define AURA_ROG_THRONE_QI_GUNDAM_PID 0x1994 /*-----------------------------------------------------------------*\ | OTHER | \*-----------------------------------------------------------------*/ -#define AURA_TERMINAL_PID 0x1889 -#define ROG_STRIX_LC120_PID 0x879E -#define AURA_RYUO_AIO_PID 0x1887 -#define ASUS_ROG_ALLY_PID 0x1ABE +#define AURA_TERMINAL_PID 0x1889 +#define ROG_STRIX_LC120_PID 0x879E +#define AURA_RYUO_AIO_PID 0x1887 +#define ASUS_ROG_ALLY_PID 0x1ABE +#define ASUS_ROG_ALLY_X_PID 0x1B4C AuraKeyboardMappingLayoutType GetKeyboardMappingLayoutType(int pid) { switch(pid) { - case AURA_ROG_STRIX_FLARE_PID: - case AURA_ROG_STRIX_FLARE_PNK_LTD_PID: - case AURA_ROG_STRIX_FLARE_COD_BO4_PID: - return FLARE_LAYOUT; - case AURA_ROG_STRIX_SCOPE_PID: return SCOPE_LAYOUT; @@ -127,9 +145,9 @@ void DetectAsusAuraUSBTerminal(hid_device_info* info, const std::string& name) if(dev) { - AuraAddressableController* controller = new AuraAddressableController(dev, info->path); + AuraAddressableController* controller = new AuraAddressableController(dev, info->path, name); RGBController_AuraUSB* rgb_controller = new RGBController_AuraUSB(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -140,10 +158,10 @@ void DetectAsusAuraUSBAddressable(hid_device_info* info, const std::string& /*na if(dev) { - DMIInfo dmi; - AuraAddressableController* controller = new AuraAddressableController(dev, info->path); + DMIInfo dmi; + AuraAddressableController* controller = new AuraAddressableController(dev, info->path, "ASUS " + dmi.getMainboard() + " Addressable"); RGBController_AuraUSB* rgb_controller = new RGBController_AuraUSB(controller); - rgb_controller->name = "ASUS " + dmi.getMainboard() + " Addressable"; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -156,10 +174,10 @@ void DetectAsusAuraUSBMotherboards(hid_device_info* info, const std::string& /*n { try { - DMIInfo dmi; - AuraMainboardController* controller = new AuraMainboardController(dev, info->path); - RGBController_AuraUSB* rgb_controller = new RGBController_AuraUSB(controller); - rgb_controller->name = "ASUS " + dmi.getMainboard(); + DMIInfo dmi; + AuraMainboardController* controller = new AuraMainboardController(dev, info->path, "ASUS " + dmi.getMainboard()); + RGBController_AuraMainboard* rgb_controller = new RGBController_AuraMainboard(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); } catch(const std::runtime_error& ex) @@ -176,10 +194,10 @@ void DetectAsusAuraUSBKeyboards(hid_device_info* info, const std::string& name) if(dev) { - AuraKeyboardController* controller = new AuraKeyboardController(dev, info->path); + AuraKeyboardController* controller = new AuraKeyboardController(dev, info->path, name); AuraKeyboardMappingLayoutType layout = GetKeyboardMappingLayoutType(info->product_id); RGBController_AuraKeyboard* rgb_controller = new RGBController_AuraKeyboard(controller, layout); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -190,19 +208,11 @@ void DetectAsusAuraUSBMice(hid_device_info* info, const std::string& name) if(dev) { - AuraMouseController* controller = new AuraMouseController(dev, info->path, info->product_id); + uint16_t pid = (name == "Asus ROG Spatha X Dock") ? AURA_ROG_SPATHA_X_DOCK_FAKE_PID : info->product_id; + AuraMouseController* controller = new AuraMouseController(dev, info->path, pid, name); RGBController_AuraMouse* rgb_controller = new RGBController_AuraMouse(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - // adding the mouse dock for the ASUS ROG Spatha X - if(info->product_id == AURA_ROG_SPATHA_X_2_4_PID) - { - AuraMouseController* dock_controller = new AuraMouseController(dev, info->path, AURA_ROG_SPATHA_X_DOCK_FAKE_PID); - RGBController_AuraMouse* rgb_controller_dock = new RGBController_AuraMouse(dock_controller); - rgb_controller_dock->name = "Asus ROG Spatha X Dock"; - ResourceManager::get()->RegisterRGBController(rgb_controller_dock); - } + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -212,9 +222,9 @@ void DetectAsusAuraUSBMousemats(hid_device_info* info, const std::string& name) if(dev) { - AuraMousematController* controller = new AuraMousematController(dev, info->path); + AuraMousematController* controller = new AuraMousematController(dev, info->path, name); RGBController_AuraMousemat* rgb_controller = new RGBController_AuraMousemat(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -225,9 +235,9 @@ void DetectAsusAuraUSBROGStrixLC(hid_device_info* info, const std::string& name) if(dev) { - ROGStrixLC_Controller* controller = new ROGStrixLC_Controller(dev, info->path); - RGBController_ROGStrixLC_Controller* rgb_controller = new RGBController_ROGStrixLC_Controller(controller); - rgb_controller->name = name; + AsusROGStrixLCController* controller = new AsusROGStrixLCController(dev, info->path, name); + RGBController_AsusROGStrixLC* rgb_controller = new RGBController_AsusROGStrixLC(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -238,9 +248,9 @@ void DetectAsusAuraUSBRyuoAIO(hid_device_info* info, const std::string& name) if(dev) { - AsusAuraRyuoAIOController* controller = new AsusAuraRyuoAIOController(dev, info->path); + AsusAuraRyuoAIOController* controller = new AsusAuraRyuoAIOController(dev, info->path, name); RGBController_AsusAuraRyuoAIO* rgb_controller = new RGBController_AsusAuraRyuoAIO(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -251,9 +261,22 @@ void DetectAsusAuraUSBStrixEvolve(hid_device_info* info, const std::string& name if(dev) { - AuraStrixEvolveController* controller = new AuraStrixEvolveController(dev, info->path, info->product_id); - RGBController_AuraStrixEvolve* rgb_controller = new RGBController_AuraStrixEvolve(controller); - rgb_controller->name = name; + AsusAuraMouseGen1Controller* controller = new AsusAuraMouseGen1Controller(dev, info->path, info->product_id, name); + RGBController_AsusROGStrixEvolve* rgb_controller = new RGBController_AsusROGStrixEvolve(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectAsusAuraUSBSpatha(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + AsusAuraMouseGen1Controller* controller = new AsusAuraMouseGen1Controller(dev, info->path, info->product_id, name); + RGBController_AsusROGSpatha* rgb_controller = new RGBController_AsusROGSpatha(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -264,9 +287,9 @@ void DetectAsusAuraUSBHeadsetStand(hid_device_info* info, const std::string& nam if(dev) { - AuraHeadsetStandController* controller = new AuraHeadsetStandController(dev, info->path); + AuraHeadsetStandController* controller = new AuraHeadsetStandController(dev, info->path, name); RGBController_AuraHeadsetStand* rgb_controller = new RGBController_AuraHeadsetStand(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -277,9 +300,9 @@ void DetectAsusAuraTUFUSBKeyboard(hid_device_info* info, const std::string& name if(dev) { - AuraTUFKeyboardController* controller = new AuraTUFKeyboardController(dev, info->path, info->product_id, info->release_number); + AuraTUFKeyboardController* controller = new AuraTUFKeyboardController(dev, info->path, info->product_id, info->release_number, name); RGBController_AuraTUFKeyboard* rgb_controller = new RGBController_AuraTUFKeyboard(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -290,9 +313,9 @@ void DetectAsusAuraUSBMonitor(hid_device_info* info, const std::string& name) if(dev) { - AuraMonitorController* controller = new AuraMonitorController(dev, info->path, info->product_id); + AuraMonitorController* controller = new AuraMonitorController(dev, info->path, info->product_id, name); RGBController_AuraMonitor* rgb_controller = new RGBController_AuraMonitor(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -303,9 +326,9 @@ void DetectAsusROGAlly(hid_device_info* info, const std::string& name) if(dev) { - ROGAllyController* controller = new ROGAllyController(dev, info->path); + ROGAllyController* controller = new ROGAllyController(dev, info->path, name); RGBController_AsusROGAlly* rgb_controller = new RGBController_AsusROGAlly(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -320,65 +343,85 @@ REGISTER_HID_DETECTOR ("ASUS Aura Addressable", DetectAs REGISTER_HID_DETECTOR ("ASUS Aura Motherboard", DetectAsusAuraUSBMotherboards, AURA_USB_VID, AURA_MOTHERBOARD_1_PID); REGISTER_HID_DETECTOR ("ASUS Aura Motherboard", DetectAsusAuraUSBMotherboards, AURA_USB_VID, AURA_MOTHERBOARD_2_PID); REGISTER_HID_DETECTOR ("ASUS Aura Motherboard", DetectAsusAuraUSBMotherboards, AURA_USB_VID, AURA_MOTHERBOARD_3_PID); +REGISTER_HID_DETECTOR ("ASUS Aura Motherboard", DetectAsusAuraUSBMotherboards, AURA_USB_VID, AURA_MOTHERBOARD_4_PID); /*-----------------------------------------------------------------*\ | KEYBOARDS | \*-----------------------------------------------------------------*/ -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 CoD Black Ops 4 Edition",DetectAsusAuraUSBKeyboards, AURA_USB_VID, AURA_ROG_STRIX_FLARE_COD_BO4_PID, 1, 0xFF00); -REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope", DetectAsusAuraUSBKeyboards, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_PID, 1, 0xFF00); -REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope RX", DetectAsusAuraUSBKeyboards, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_RX_PID, 1, 0xFF00); -REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope TKL", DetectAsusAuraUSBKeyboards, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_TKL_PID, 1, 0xFF00); -REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope RX TKL Wireless Deluxe", DetectAsusAuraUSBKeyboards, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_RX_TKL_DELUXE_PID, 1, 0xFF00); -REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope TKL PNK LTD", DetectAsusAuraUSBKeyboards, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_TKL_PNK_LTD_PID, 1, 0xFF00); -REGISTER_HID_DETECTOR_IP("ASUS ROG Claymore", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_CLAYMORE_PID, 1, 0xFF00); -REGISTER_HID_DETECTOR_IP("ASUS ROG Falchion (Wired)", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_FALCHION_WIRED_PID, 1, 0xFF00); -REGISTER_HID_DETECTOR_IP("ASUS ROG Falchion (Wireless)", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_FALCHION_WIRELESS_PID, 1, 0xFF00); -REGISTER_HID_DETECTOR_IP("ASUS TUF Gaming K1", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_TUF_K1_GAMING_PID, 2, 0xFF00); -REGISTER_HID_DETECTOR_IP("ASUS TUF Gaming K3", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_TUF_K3_GAMING_PID, 1, 0xFF00); -REGISTER_HID_DETECTOR_IP("ASUS TUF Gaming K5", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_TUF_K5_GAMING_PID, 2, 0xFF00); -REGISTER_HID_DETECTOR_IP("ASUS TUF Gaming K7", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_TUF_K7_GAMING_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope TKL", DetectAsusAuraUSBKeyboards, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_TKL_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope RX TKL Wireless Deluxe", DetectAsusAuraUSBKeyboards, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_RX_TKL_DELUXE_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope TKL PNK LTD", DetectAsusAuraUSBKeyboards, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_TKL_PNK_LTD_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Azoth USB", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_AZOTH_USB_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Azoth 2.4GHz", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_AZOTH_2_4_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Claymore", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_CLAYMORE_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Falchion (Wired)", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_FALCHION_WIRED_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Falchion (Wireless)", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_FALCHION_WIRELESS_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Flare", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_STRIX_FLARE_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Flare PNK LTD", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_STRIX_FLARE_PNK_LTD_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Flare CoD Black Ops 4 Edition", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_STRIX_FLARE_COD_BO4_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Flare II Animate", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_STRIX_FLARE_II_ANIMATE_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Flare II", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_STRIX_FLARE_II_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope RX", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_RX_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope RX EVA-02 Edition", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_RX_EVA_02_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope NX Wireless Deluxe USB", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_NX_WIRELESS_DELUXE_USB_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope NX Wireless Deluxe 2.4GHz", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_NX_WIRELESS_DELUXE_2_4_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope II", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_II_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope II RX", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_II_RX_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Scope II 96 Wireless USB", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_ROG_STRIX_SCOPE_II_96_WIRELESS_USB_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS TUF Gaming K1", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_TUF_K1_GAMING_PID, 2, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS TUF Gaming K3", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_TUF_K3_GAMING_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS TUF Gaming K5", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_TUF_K5_GAMING_PID, 2, 0xFF00); +REGISTER_HID_DETECTOR_IP("ASUS TUF Gaming K7", DetectAsusAuraTUFUSBKeyboard, AURA_USB_VID, AURA_TUF_K7_GAMING_PID, 1, 0xFF00); /*-----------------------------------------------------------------*\ | MICE | \*-----------------------------------------------------------------*/ -REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Core", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_CORE_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_PID, 2, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Origin", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_ORIGIN_PID, 2, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Origin PNK LTD", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_ORIGIN_PNK_LTD_PID, 2, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Origin COD", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_ORIGIN_COD_PID, 2, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Wireless", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_WIRELESS_1_PID, 1, 0xFF13); -REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Wireless", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_WIRELESS_2_PID, 2, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless USB", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_USB_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless 2.4Ghz", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_2_4_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless Bluetooth", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_BT_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Chakram (Wireless)", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_CHAKRAM_WIRELESS_PID, 0, 0xFF01); -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 Core", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_CHAKRAM_CORE_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("Asus ROG Chakram X USB", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_CHAKRAM_X_USB_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("Asus ROG Chakram X 2.4GHz", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_CHAKRAM_X_2_4_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("Asus ROG Spatha X USB", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_SPATHA_X_USB_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("Asus ROG Spatha X 2.4GHz", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_SPATHA_X_2_4_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Pugio", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_PUGIO_PID, 2, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Pugio II (Wired)", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_PUGIO_II_WIRED_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Pugio II (Wireless)", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_PUGIO_II_WIRELESS_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Impact", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_STRIX_IMPACT_PID, 2, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Impact II", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_STRIX_IMPACT_II_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Impact II Gundam", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_STRIX_IMPACT_II_GUNDAM_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Impact II Electro Punk", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_STRIX_IMPACT_II_PUNK_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Impact II Moonlight White", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_STRIX_IMPACT_II_WHITE_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Impact II Wireless USB", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_STRIX_IMPACT_II_WIRELESS_USB_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Impact II Wireless 2.4 Ghz", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_STRIX_IMPACT_II_WIRELESS_2_4_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Keris", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_KERIS, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Keris Wireless USB", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_KERIS_WIRELESS_USB_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Keris Wireless 2.4Ghz", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_KERIS_WIRELESS_2_4_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS ROG Keris Wireless Bluetooth", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_KERIS_WIRELESS_BT_PID, 0, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS TUF Gaming M3", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_TUF_M3_PID, 1, 0xFF01); -REGISTER_HID_DETECTOR_IP("ASUS TUF Gaming M5", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_TUF_M5_PID, 2, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Core", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_CORE_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_PID, 2, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Origin", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_ORIGIN_PID, 2, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Origin PNK LTD", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_ORIGIN_PNK_LTD_PID, 2, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Origin COD", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_ORIGIN_COD_PID, 2, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Wireless", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_WIRELESS_1_PID, 1, 0xFF13); +REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius II Wireless", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_II_WIRELESS_2_PID, 2, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless USB", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_USB_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless 2.4Ghz", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_2_4_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless Bluetooth", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_BT_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless AimPoint USB", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_AIMPOINT_USB_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Gladius III Wireless AimPoint 2.4Ghz", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_GLADIUS_III_WIRELESS_AIMPOINT_2_4_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Chakram (Wireless)", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_CHAKRAM_WIRELESS_PID, 0, 0xFF01); +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 Core", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_CHAKRAM_CORE_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("Asus ROG Chakram X USB", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_CHAKRAM_X_USB_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("Asus ROG Chakram X 2.4GHz", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_CHAKRAM_X_2_4_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("Asus ROG Spatha X USB", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_SPATHA_X_USB_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("Asus ROG Spatha X 2.4GHz", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_SPATHA_X_2_4_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("Asus ROG Spatha X Dock", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_SPATHA_X_DOCK_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Pugio", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_PUGIO_PID, 2, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Pugio II (Wired)", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_PUGIO_II_WIRED_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Pugio II (Wireless)", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_PUGIO_II_WIRELESS_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Impact", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_STRIX_IMPACT_PID, 2, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Impact II", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_STRIX_IMPACT_II_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Impact II Gundam", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_STRIX_IMPACT_II_GUNDAM_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Impact II Electro Punk", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_STRIX_IMPACT_II_PUNK_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Impact II Moonlight White", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_STRIX_IMPACT_II_WHITE_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Impact II Wireless USB", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_STRIX_IMPACT_II_WIRELESS_USB_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Impact II Wireless 2.4 Ghz", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_STRIX_IMPACT_II_WIRELESS_2_4_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Impact III", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_STRIX_IMPACT_III_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Keris", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_KERIS, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Keris Wireless USB", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_KERIS_WIRELESS_USB_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Keris Wireless 2.4Ghz", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_KERIS_WIRELESS_2_4_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Keris Wireless Bluetooth", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_KERIS_WIRELESS_BT_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Keris Wireless AimPoint USB", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_KERIS_WIRELESS_AIMPOINT_USB_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS ROG Keris Wireless AimPoint 2.4Ghz", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_ROG_KERIS_WIRELESS_AIMPOINT_2_4_PID, 0, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS TUF Gaming M3", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_TUF_M3_PID, 1, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS TUF Gaming M3 Gen II", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_TUF_M3_GEN_II_PID, 2, 0xFF01); +REGISTER_HID_DETECTOR_IP("ASUS TUF Gaming M5", DetectAsusAuraUSBMice, AURA_USB_VID, AURA_TUF_M5_PID, 2, 0xFF01); REGISTER_HID_DETECTOR_IP("ASUS ROG Strix Evolve", DetectAsusAuraUSBStrixEvolve, AURA_USB_VID, AURA_ROG_STRIX_EVOLVE_PID, 1, 0x0008); +REGISTER_HID_DETECTOR_IP("ASUS ROG Spatha Wired", DetectAsusAuraUSBSpatha, AURA_USB_VID, AURA_ROG_SPATHA_WIRED_PID, 1, 0x0008); +REGISTER_HID_DETECTOR_IP("ASUS ROG Spatha Wireless", DetectAsusAuraUSBSpatha, AURA_USB_VID, AURA_ROG_SPATHA_WIRELESS_PID, 1, 0x0008); /*-----------------------------------------------------------------*\ | MOUSEMATS | @@ -393,6 +436,7 @@ REGISTER_HID_DETECTOR_PU("ASUS ROG Strix XG27AQ", DetectAs REGISTER_HID_DETECTOR_PU("ASUS ROG Strix XG27AQM", DetectAsusAuraUSBMonitor, AURA_USB_VID, AURA_ROG_STRIX_XG27AQM_PID, 0xFFA0, 1); REGISTER_HID_DETECTOR_PU("ASUS ROG Strix XG279Q", DetectAsusAuraUSBMonitor, AURA_USB_VID, AURA_ROG_STRIX_XG279Q_PID, 0xFFA0, 1); REGISTER_HID_DETECTOR_PU("ASUS ROG Strix XG27W", DetectAsusAuraUSBMonitor, AURA_USB_VID, AURA_ROG_STRIX_XG27W_PID, 0xFFA0, 1); +REGISTER_HID_DETECTOR_PU("ASUS ROG Strix XG32VC", DetectAsusAuraUSBMonitor, AURA_USB_VID, AURA_ROG_STRIX_XG32VC_PID, 0xFFA0, 1); REGISTER_HID_DETECTOR_PU("ASUS ROG PG32UQ", DetectAsusAuraUSBMonitor, AURA_USB_VID, AURA_ROG_PG32UQ_PID, 0xFFA0, 1); /*-----------------------------------------------------------------*\ @@ -405,3 +449,4 @@ REGISTER_HID_DETECTOR_I ("ASUS ROG Throne", DetectAs REGISTER_HID_DETECTOR_I ("ASUS ROG Throne QI", DetectAsusAuraUSBHeadsetStand, AURA_USB_VID, AURA_ROG_THRONE_QI_PID, 0); REGISTER_HID_DETECTOR_I ("ASUS ROG Throne QI GUNDAM", DetectAsusAuraUSBHeadsetStand, AURA_USB_VID, AURA_ROG_THRONE_QI_GUNDAM_PID, 0); REGISTER_HID_DETECTOR_IPU("ASUS ROG Ally", DetectAsusROGAlly, AURA_USB_VID, ASUS_ROG_ALLY_PID, 2, 0xFF31, 0x0076); +REGISTER_HID_DETECTOR_IPU("ASUS ROG Ally X", DetectAsusROGAlly, AURA_USB_VID, ASUS_ROG_ALLY_X_PID, 2, 0xFF31, 0x0076); diff --git a/Controllers/AsusAuraUSBController/AsusROGAllyController.cpp b/Controllers/AsusAuraUSBController/AsusROGAllyController.cpp deleted file mode 100644 index 966e8606..00000000 --- a/Controllers/AsusAuraUSBController/AsusROGAllyController.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/*-----------------------------------------*\ -| AsusROGAllyController.cpp | -| | -| Driver for ASUS ROG Ally lighting | -| controller | -| | -| Adam Honse (CalcProgrammer1) 6/12/2023 | -\*-----------------------------------------*/ - -#include "AsusROGAllyController.h" -#include - -ROGAllyController::ROGAllyController(hid_device* dev_handle, const char* path) -{ - dev = dev_handle; - location = path; -} - -ROGAllyController::~ROGAllyController() -{ - hid_close(dev); -} - -std::string ROGAllyController::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string ROGAllyController::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); -} - -std::string ROGAllyController::GetVersion() -{ - return(""); -} - -void ROGAllyController::UpdateLeds - ( - std::vector colors - ) -{ - unsigned char usb_buf[64]; - - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x5A; - usb_buf[0x01] = 0xD1; - usb_buf[0x02] = 0x08; - usb_buf[0x03] = 0x0C; - - for(unsigned int color_idx = 0; color_idx < colors.size(); color_idx++) - { - usb_buf[color_idx * 3 + 4] = RGBGetRValue(colors[color_idx]); - usb_buf[color_idx * 3 + 5] = RGBGetGValue(colors[color_idx]); - usb_buf[color_idx * 3 + 6] = RGBGetBValue(colors[color_idx]); - } - - hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); -} - -void ROGAllyController::UpdateDevice - ( - unsigned char mode, - std::vector colors, - unsigned char speed, - unsigned char /*brightness*/, - unsigned char direction - ) -{ - unsigned char usb_buf[64]; - - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x5A; - usb_buf[0x01] = 0xB3; - usb_buf[0x02] = 0x00; - usb_buf[0x03] = mode; - if(colors.size() > 0) - { - usb_buf[0x04] = RGBGetRValue(colors[0]); - usb_buf[0x05] = RGBGetGValue(colors[0]); - usb_buf[0x06] = RGBGetBValue(colors[0]); - } - usb_buf[0x07] = speed; - usb_buf[0x08] = direction; - if(colors.size() > 1) - { - usb_buf[0x0A] = RGBGetRValue(colors[1]); - usb_buf[0x0B] = RGBGetGValue(colors[1]); - usb_buf[0x0C] = RGBGetBValue(colors[1]); - } - - hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); - - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x5A; - usb_buf[0x01] = 0xB5; - - hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); -} - -void ROGAllyController::SaveMode() -{ - unsigned char usb_buf[64]; - - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x5A; - usb_buf[0x01] = 0xB4; - - hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); -} - diff --git a/Controllers/AsusAuraUSBController/AsusROGAllyController.h b/Controllers/AsusAuraUSBController/AsusROGAllyController.h deleted file mode 100644 index 903b0da3..00000000 --- a/Controllers/AsusAuraUSBController/AsusROGAllyController.h +++ /dev/null @@ -1,67 +0,0 @@ -/*-----------------------------------------*\ -| AsusROGAllyController.h | -| | -| Definitions and types for ASUS ROG Ally | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 6/12/2023 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include - -#pragma once - -enum -{ - ROG_ALLY_MODE_STATIC = 0, - ROG_ALLY_MODE_BREATHING = 1, - ROG_ALLY_MODE_COLOR_CYCLE = 2, - ROG_ALLY_MODE_RAINBOW = 3, - ROG_ALLY_MODE_STROBING = 10, - ROG_ALLY_MODE_DIRECT = 0xFF, -}; - -enum -{ - ROG_ALLY_SPEED_MIN = 0xE1, - ROG_ALLY_SPEED_MED = 0xEB, - ROG_ALLY_SPEED_MAX = 0xF5 -}; - -enum -{ - ROG_ALLY_DIRECTION_RIGHT = 0x00, - ROG_ALLY_DIRECTION_LEFT = 0x01 -}; - -class ROGAllyController -{ -public: - ROGAllyController(hid_device* dev_handle, const char* path); - virtual ~ROGAllyController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - std::string GetVersion(); - - void UpdateLeds - ( - std::vector colors - ); - - void UpdateDevice - ( - unsigned char mode, - std::vector colors, - unsigned char speed, - unsigned char brightness, - unsigned char direction - ); - - void SaveMode(); - -private: - hid_device* dev; - std::string location; -}; diff --git a/Controllers/AsusAuraUSBController/AsusROGAllyController/AsusROGAllyController.cpp b/Controllers/AsusAuraUSBController/AsusROGAllyController/AsusROGAllyController.cpp new file mode 100644 index 00000000..04598d2c --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusROGAllyController/AsusROGAllyController.cpp @@ -0,0 +1,183 @@ +/*---------------------------------------------------------*\ +| AsusROGAllyController.cpp | +| | +| Driver for ASUS ROG Ally | +| | +| Adam Honse (CalcProgrammer1) 12 Jul 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "AsusROGAllyController.h" +#include "StringUtils.h" + +ROGAllyController::ROGAllyController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + + SendInitialization(); +} + +ROGAllyController::~ROGAllyController() +{ + hid_close(dev); +} + +std::string ROGAllyController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string ROGAllyController::GetName() +{ + return(name); +} + +std::string ROGAllyController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string ROGAllyController::GetVersion() +{ + return(""); +} + +void ROGAllyController::SendInitialization() +{ + unsigned char usb_buf[64]; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x5D; + usb_buf[0x01] = 0xB9; + + hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x5D; + usb_buf[0x01] = 0x41; + usb_buf[0x02] = 0x53; + usb_buf[0x03] = 0x55; + usb_buf[0x04] = 0x53; + usb_buf[0x05] = 0x20; + usb_buf[0x06] = 0x54; + usb_buf[0x07] = 0x65; + usb_buf[0x08] = 0x63; + usb_buf[0x09] = 0x68; + usb_buf[0x0A] = 0x2E; + usb_buf[0x0B] = 0x49; + usb_buf[0x0C] = 0x6E; + usb_buf[0x0D] = 0x63; + usb_buf[0x0E] = 0x2E; + + hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); +} + +void ROGAllyController::UpdateBrightness + ( + unsigned char brightness + ) +{ + unsigned char usb_buf[64]; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x5A; + usb_buf[0x01] = 0xBA; + usb_buf[0x02] = 0xC5; + usb_buf[0x03] = 0xC4; + usb_buf[0x04] = brightness; + + hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); +} + +void ROGAllyController::UpdateLeds + ( + std::vector colors + ) +{ + unsigned char usb_buf[64]; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x5A; + usb_buf[0x01] = 0xD1; + usb_buf[0x02] = 0x08; + usb_buf[0x03] = 0x0C; + + for(unsigned int color_idx = 0; color_idx < colors.size(); color_idx++) + { + usb_buf[color_idx * 3 + 4] = RGBGetRValue(colors[color_idx]); + usb_buf[color_idx * 3 + 5] = RGBGetGValue(colors[color_idx]); + usb_buf[color_idx * 3 + 6] = RGBGetBValue(colors[color_idx]); + } + + hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); +} + +void ROGAllyController::UpdateDevice + ( + unsigned char mode, + std::vector colors, + unsigned char speed, + unsigned char direction + ) +{ + unsigned char usb_buf[64]; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x5A; + usb_buf[0x01] = 0xB3; + usb_buf[0x02] = 0x00; + usb_buf[0x03] = mode; + if(colors.size() > 0) + { + usb_buf[0x04] = RGBGetRValue(colors[0]); + usb_buf[0x05] = RGBGetGValue(colors[0]); + usb_buf[0x06] = RGBGetBValue(colors[0]); + } + usb_buf[0x07] = speed; + usb_buf[0x08] = direction; + if(colors.size() > 1) + { + usb_buf[0x0A] = RGBGetRValue(colors[1]); + usb_buf[0x0B] = RGBGetGValue(colors[1]); + usb_buf[0x0C] = RGBGetBValue(colors[1]); + } + + hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x5A; + usb_buf[0x01] = 0xB5; + + hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); +} + +void ROGAllyController::SaveMode() +{ + unsigned char usb_buf[64]; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x5A; + usb_buf[0x01] = 0xB4; + + hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); +} diff --git a/Controllers/AsusAuraUSBController/AsusROGAllyController/AsusROGAllyController.h b/Controllers/AsusAuraUSBController/AsusROGAllyController/AsusROGAllyController.h new file mode 100644 index 00000000..2d6973f7 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusROGAllyController/AsusROGAllyController.h @@ -0,0 +1,77 @@ +/*---------------------------------------------------------*\ +| AsusROGAllyController.h | +| | +| Driver for ASUS ROG Ally | +| | +| Adam Honse (CalcProgrammer1) 12 Jul 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" + +enum +{ + ROG_ALLY_MODE_STATIC = 0, + ROG_ALLY_MODE_BREATHING = 1, + ROG_ALLY_MODE_COLOR_CYCLE = 2, + ROG_ALLY_MODE_RAINBOW = 3, + ROG_ALLY_MODE_STROBING = 10, + ROG_ALLY_MODE_DIRECT = 0xFF, +}; + +enum +{ + ROG_ALLY_SPEED_MIN = 0xE1, + ROG_ALLY_SPEED_MED = 0xEB, + ROG_ALLY_SPEED_MAX = 0xF5 +}; + +enum +{ + ROG_ALLY_DIRECTION_RIGHT = 0x00, + ROG_ALLY_DIRECTION_LEFT = 0x01 +}; + +class ROGAllyController +{ +public: + ROGAllyController(hid_device* dev_handle, const char* path, std::string dev_name); + virtual ~ROGAllyController(); + + std::string GetDeviceLocation(); + std::string GetName(); + std::string GetSerialString(); + std::string GetVersion(); + + void SendInitialization(); + + void UpdateBrightness + ( + unsigned char brightness + ); + + void UpdateLeds + ( + std::vector colors + ); + + void UpdateDevice + ( + unsigned char mode, + std::vector colors, + unsigned char speed, + unsigned char direction + ); + + void SaveMode(); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/AsusAuraUSBController/AsusROGAllyController/RGBController_AsusROGAlly.cpp b/Controllers/AsusAuraUSBController/AsusROGAllyController/RGBController_AsusROGAlly.cpp new file mode 100644 index 00000000..710820dd --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusROGAllyController/RGBController_AsusROGAlly.cpp @@ -0,0 +1,218 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusROGAlly.cpp | +| | +| RGBController for ASUS ROG Ally | +| | +| Adam Honse (CalcProgrammer1) 12 Jul 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_AsusROGAlly.h" + +/**------------------------------------------------------------------*\ + @name Asus ROG Ally + @category Gamepad + @type USB + @save :white_check_mark: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectAsusROGAlly + @comment +\*-------------------------------------------------------------------*/ + +RGBController_AsusROGAlly::RGBController_AsusROGAlly(ROGAllyController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = "ASUS"; + type = DEVICE_TYPE_GAMEPAD; + description = "ASUS ROG Ally Device"; + version = controller->GetVersion(); + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = ROG_ALLY_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = 0; + Direct.brightness_max = 3; + Direct.brightness = 3; + modes.push_back(Direct); + + mode Static; + Static.name = "Static"; + Static.value = ROG_ALLY_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.resize(1); + Static.brightness_min = 0; + Static.brightness_max = 3; + Static.brightness = 3; + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = ROG_ALLY_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.speed_min = ROG_ALLY_SPEED_MIN; + Breathing.speed_max = ROG_ALLY_SPEED_MAX; + Breathing.speed = ROG_ALLY_SPEED_MED; + Breathing.colors_min = 2; + Breathing.colors_max = 2; + Breathing.colors.resize(2); + Breathing.brightness_min = 0; + Breathing.brightness_max = 3; + Breathing.brightness = 3; + modes.push_back(Breathing); + + mode ColorCycle; + ColorCycle.name = "Spectrum Cycle"; + ColorCycle.value = ROG_ALLY_MODE_COLOR_CYCLE; + ColorCycle.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + ColorCycle.color_mode = MODE_COLORS_RANDOM; + ColorCycle.speed_min = ROG_ALLY_SPEED_MIN; + ColorCycle.speed_max = ROG_ALLY_SPEED_MAX; + ColorCycle.speed = ROG_ALLY_SPEED_MED; + ColorCycle.brightness_min = 0; + ColorCycle.brightness_max = 3; + ColorCycle.brightness = 3; + modes.push_back(ColorCycle); + + mode Rainbow; + Rainbow.name = "Rainbow Wave"; + Rainbow.value = ROG_ALLY_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_BRIGHTNESS; + Rainbow.color_mode = MODE_COLORS_RANDOM; + Rainbow.speed_min = ROG_ALLY_SPEED_MIN; + Rainbow.speed_max = ROG_ALLY_SPEED_MAX; + Rainbow.speed = ROG_ALLY_SPEED_MED; + Rainbow.brightness_min = 0; + Rainbow.brightness_max = 3; + Rainbow.brightness = 3; + modes.push_back(Rainbow); + + mode Strobing; + Strobing.name = "Strobing"; + Strobing.value = ROG_ALLY_MODE_STROBING; + Strobing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Strobing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Strobing.colors_min = 1; + Strobing.colors_max = 1; + Strobing.brightness_min = 0; + Strobing.brightness_max = 3; + Strobing.brightness = 3; + Strobing.colors.resize(1); + modes.push_back(Strobing); + + SetupZones(); +} + +RGBController_AsusROGAlly::~RGBController_AsusROGAlly() +{ + delete controller; +} + +void RGBController_AsusROGAlly::SetupZones() +{ + zone left_stick_zone; + + left_stick_zone.name = "Left Stick"; + left_stick_zone.type = ZONE_TYPE_SINGLE; + left_stick_zone.leds_min = 2; + left_stick_zone.leds_max = 2; + left_stick_zone.leds_count = 2; + left_stick_zone.matrix_map = NULL; + + zones.push_back(left_stick_zone); + + for(unsigned int i = 0; i < 2; i++) + { + led left_stick_led; + + left_stick_led.name = "Left Stick LED " + std::to_string(i); + + leds.push_back(left_stick_led); + } + + zone right_stick_zone; + + right_stick_zone.name = "Right Stick"; + right_stick_zone.type = ZONE_TYPE_SINGLE; + right_stick_zone.leds_min = 2; + right_stick_zone.leds_max = 2; + right_stick_zone.leds_count = 2; + right_stick_zone.matrix_map = NULL; + + zones.push_back(right_stick_zone); + + for(unsigned int i = 0; i < 2; i++) + { + led right_stick_led; + + right_stick_led.name = "Right Stick LED " + std::to_string(i); + + leds.push_back(right_stick_led); + } + + SetupColors(); +} + +void RGBController_AsusROGAlly::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_AsusROGAlly::DeviceUpdateLEDs() +{ + if(modes[active_mode].value == ROG_ALLY_MODE_DIRECT) + { + controller->UpdateLeds(std::vector(colors)); + } +} + +void RGBController_AsusROGAlly::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_AsusROGAlly::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_AsusROGAlly::DeviceUpdateMode() +{ + controller->UpdateBrightness(modes[active_mode].brightness); + + if(modes[active_mode].value == ROG_ALLY_MODE_DIRECT) + { + DeviceUpdateLEDs(); + } + else + { + unsigned int rog_ally_direction = ROG_ALLY_DIRECTION_RIGHT; + + if((modes[active_mode].flags & MODE_FLAG_HAS_DIRECTION_LR) && (modes[active_mode].direction == MODE_DIRECTION_LEFT)) + { + rog_ally_direction = ROG_ALLY_DIRECTION_LEFT; + } + + controller->UpdateDevice(modes[active_mode].value, modes[active_mode].colors, modes[active_mode].speed, rog_ally_direction); + } +} + +void RGBController_AsusROGAlly::DeviceSaveMode() +{ + DeviceUpdateMode(); + controller->SaveMode(); +} diff --git a/Controllers/AsusAuraUSBController/AsusROGAllyController/RGBController_AsusROGAlly.h b/Controllers/AsusAuraUSBController/AsusROGAllyController/RGBController_AsusROGAlly.h new file mode 100644 index 00000000..e6c2f269 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusROGAllyController/RGBController_AsusROGAlly.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusROGAlly.h | +| | +| RGBController for ASUS ROG Ally | +| | +| Adam Honse (CalcProgrammer1) 12 Jul 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AsusROGAllyController.h" + +class RGBController_AsusROGAlly : public RGBController +{ +public: + RGBController_AsusROGAlly(ROGAllyController* controller_ptr); + ~RGBController_AsusROGAlly(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + ROGAllyController* controller; +}; diff --git a/Controllers/AsusAuraUSBController/AsusROGStrixLCController/AsusROGStrixLCController.cpp b/Controllers/AsusAuraUSBController/AsusROGStrixLCController/AsusROGStrixLCController.cpp new file mode 100644 index 00000000..82bc9e42 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusROGStrixLCController/AsusROGStrixLCController.cpp @@ -0,0 +1,128 @@ +/*---------------------------------------------------------*\ +| AsusROGStrixLCController.cpp | +| | +| Driver for ASUS Aura liquid cooler | +| | +| Chris M (Dr_No) 17 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "AsusROGStrixLCController.h" + +AsusROGStrixLCController::AsusROGStrixLCController(hid_device* dev_handle, const char* path, std::string dev_name) : AuraUSBController(dev_handle, path, dev_name) +{ + /*-----------------------------------------------------*\ + | Add addressable devices | + | Manually adding device info for now | + | TODO: Implement config table accurately | + | LC120 - 1F FF 05 05 04 00 00 00 | + \*-----------------------------------------------------*/ + device_info.push_back({0x00, 0x00, 4, 0, AuraDeviceType::FIXED}); +} + +AsusROGStrixLCController::~AsusROGStrixLCController() +{ + // Device will close at AuraUSBController destructor +} + +std::string AsusROGStrixLCController::GetLocation() +{ + return("HID: " + location); +} + +void AsusROGStrixLCController::SetMode(unsigned char /*channel*/, unsigned char /*mode*/, unsigned char /*red*/, unsigned char /*grn*/, unsigned char /*blu*/) +{ + /*---------------------------------------------------------*\ + | This interface is not used in this controller however is | + | required by the abstract class | + \*---------------------------------------------------------*/ +} + +void AsusROGStrixLCController::SetMode(unsigned char mode, unsigned char speed, unsigned char direction, RGBColor colour) +{ + bool needs_update = !( (current_mode == mode) && (ToRGBColor(current_red, current_green, current_blue) == colour) && (current_speed == speed) && (current_direction == direction)); + + if (needs_update) + { + current_mode = mode; + current_speed = speed; + current_direction = direction; + current_red = RGBGetRValue(colour); + current_green = RGBGetGValue(colour); + current_blue = RGBGetBValue(colour); + SendUpdate(); + } +} + +void AsusROGStrixLCController::SetChannelLEDs(unsigned char /*channel*/, RGBColor* /*colors*/, unsigned int /*num_colors*/) +{ + /*---------------------------------------------------------*\ + | This interface is not used in this controller however is | + | required by the abstract class | + \*---------------------------------------------------------*/ +} + +void AsusROGStrixLCController::SetLedsDirect(RGBColor * led_colours, uint8_t led_count) +{ + uint8_t buffer[write_packet_size] = { 0xEC, 0x40, 0x00, 0xFF, led_count }; + + /*---------------------------------------------------------*\ + | Set the colour bytes in the packet | + \*---------------------------------------------------------*/ + for(uint8_t index = 0; index < led_count; index++) + { + uint8_t offset = (index * 3) + ROGSTRIXLC_GREEN_BYTE; + + buffer[offset + 0] = RGBGetRValue(led_colours[index]); + buffer[offset + 1] = RGBGetGValue(led_colours[index]); + buffer[offset + 2] = RGBGetBValue(led_colours[index]); + } + + /*---------------------------------------------------------*\ + | These 3 bytes might be timing bytes | + \*---------------------------------------------------------*/ + uint8_t offset = led_count * 3 + ROGSTRIXLC_GREEN_BYTE; + buffer[offset + 0] = 0x77; + buffer[offset + 1] = 0x10; + buffer[offset + 2] = 0xF3; + + hid_write(dev, buffer, write_packet_size); +} + +void AsusROGStrixLCController::GetStatus() +{ + uint8_t buffer[write_packet_size] = { 0xEC, 0x01, 0x02 }; + + hid_write(dev, buffer, write_packet_size); + hid_read_timeout(dev, buffer, read_packet_size, ROGSTRIXLC_CONTROLLER_TIMEOUT); + + current_red = buffer[ROGSTRIXLC_RED_BYTE - 1]; + current_green = buffer[ROGSTRIXLC_GREEN_BYTE - 1]; + current_blue = buffer[ROGSTRIXLC_BLUE_BYTE - 1]; +} + +void AsusROGStrixLCController::SendUpdate() +{ + uint8_t buffer[write_packet_size]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(buffer, 0x00, write_packet_size); + + buffer[ROGSTRIXLC_REPORTID_BYTE] = rogstrixlc_reportid; + buffer[ROGSTRIXLC_COMMAND_BYTE] = rogstrixlc_modefx; + buffer[ROGSTRIXLC_ZONE_BYTE] = 0; + buffer[ROGSTRIXLC_MODE_BYTE] = current_mode; + buffer[ROGSTRIXLC_RED_BYTE] = current_red; + buffer[ROGSTRIXLC_GREEN_BYTE] = current_green; + buffer[ROGSTRIXLC_BLUE_BYTE] = current_blue; + + buffer[ROGSTRIXLC_DIRECTION_BYTE] = current_direction; + buffer[ROGSTRIXLC_SPEED_BYTE] = current_speed; + + hid_write(dev, buffer, write_packet_size); +} + diff --git a/Controllers/AsusAuraUSBController/AsusROGStrixLCController/AsusROGStrixLCController.h b/Controllers/AsusAuraUSBController/AsusROGStrixLCController/AsusROGStrixLCController.h new file mode 100644 index 00000000..9a74abb6 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusROGStrixLCController/AsusROGStrixLCController.h @@ -0,0 +1,93 @@ +/*---------------------------------------------------------*\ +| AsusROGStrixLCController.h | +| | +| Driver for ASUS Aura liquid cooler | +| | +| Chris M (Dr_No) 17 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" +#include "AsusAuraUSBController.h" + +#define ROGSTRIXLC_CONTROLLER_TIMEOUT 250 +#define HID_MAX_STR 255 + +#define ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MIN 0 +#define ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX 255 + +enum +{ + ROGSTRIXLC_CONTROLLER_MODE_DIRECT = 0xFF, //Direct Led Control - Independently set LEDs in zone + ROGSTRIXLC_CONTROLLER_MODE_STATIC = 0x01, //Static Mode - Set entire zone to a single color. + ROGSTRIXLC_CONTROLLER_MODE_BREATHING = 0x02, //Breathing Mode - Fades between fully off and fully on. + ROGSTRIXLC_CONTROLLER_MODE_FLASHING = 0x03, //Flashing Mode - Abruptly changing between fully off and fully on. + ROGSTRIXLC_CONTROLLER_MODE_SPECTRUM = 0x04, //Spectrum Cycle Mode - Cycles through the color spectrum on all lights on the device + ROGSTRIXLC_CONTROLLER_MODE_RAINBOW = 0x05, //Rainbow Wave Mode - Cycle thru the color spectrum as a wave across all LEDs + ROGSTRIXLC_CONTROLLER_MODE_FLASHANDDASH = 0x0A, //Flash n Dash - Flash twice and then flash in direction +}; + +enum AsusAuraStrixLC_PacketMap +{ + ROGSTRIXLC_REPORTID_BYTE = 0, + ROGSTRIXLC_COMMAND_BYTE = 1, + ROGSTRIXLC_ZONE_BYTE = 2, + ROGSTRIXLC_MODE_BYTE = 3, + ROGSTRIXLC_RED_BYTE = 4, + ROGSTRIXLC_GREEN_BYTE = 5, + ROGSTRIXLC_BLUE_BYTE = 6, + ROGSTRIXLC_DIRECTION_BYTE = 7, + ROGSTRIXLC_SPEED_BYTE = 8, +}; + +enum +{ + ROGSTRIXLC_CONTROLLER_SPEED_SLOWEST = 0x04, // Slowest speed + ROGSTRIXLC_CONTROLLER_SPEED_SLOW = 0x03, // Slower speed + ROGSTRIXLC_CONTROLLER_SPEED_NORMAL = 0x02, // Normal speed + ROGSTRIXLC_CONTROLLER_SPEED_FAST = 0x01, // Fast speed + ROGSTRIXLC_CONTROLLER_SPEED_FASTEST = 0x00, // Fastest speed +}; + +class AsusROGStrixLCController : public AuraUSBController +{ +public: + AsusROGStrixLCController(hid_device* dev_handle, const char* path, std::string dev_name); + ~AsusROGStrixLCController(); + + std::string GetLocation(); + + void SetChannelLEDs(unsigned char channel, RGBColor *colors, unsigned int num_colors); + void SetLedsDirect(RGBColor * led_colours, uint8_t led_count); + + void SetMode(unsigned char channel, unsigned char mode, unsigned char red, unsigned char grn, unsigned char blu); + void SetMode(unsigned char mode, unsigned char speed, unsigned char direction, RGBColor colour); +private: + static const uint8_t read_packet_size = 64; + static const uint8_t write_packet_size = read_packet_size + 1; + static const uint8_t rogstrixlc_modefx = 0x3B; + static const uint8_t rogstrixlc_direct = 0x40; + static const uint8_t rogstrixlc_reportid = 0xEC; + + std::string location; + + uint8_t zone_index; + uint8_t current_mode; + uint8_t current_speed; + + uint8_t current_red; + uint8_t current_green; + uint8_t current_blue; + uint8_t current_direction; + + void GetStatus(); + void SendUpdate(); + void SendEffect(unsigned char channel, unsigned char mode, unsigned char red, unsigned char grn, unsigned char blu); + void SendDirectApply(unsigned char channel); +}; diff --git a/Controllers/AsusAuraUSBController/AsusROGStrixLCController/RGBController_AsusROGStrixLC.cpp b/Controllers/AsusAuraUSBController/AsusROGStrixLCController/RGBController_AsusROGStrixLC.cpp new file mode 100644 index 00000000..2ae5bfe7 --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusROGStrixLCController/RGBController_AsusROGStrixLC.cpp @@ -0,0 +1,221 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusROGStrixLC.cpp | +| | +| RGBController for ASUS Aura liquid cooler | +| | +| Chris M (Dr_No) 17 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBControllerKeyNames.h" +#include "RGBController_AsusROGStrixLC.h" + +/**------------------------------------------------------------------*\ + @name Asus ROG Strix Liquid Cooler + @category Cooler + @type USB + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectAsusAuraUSBROGStrixLC + @comment +\*-------------------------------------------------------------------*/ + +RGBController_AsusROGStrixLC::RGBController_AsusROGStrixLC(AsusROGStrixLCController *controller_ptr) +{ + controller = controller_ptr; + uint8_t speed = ROGSTRIXLC_CONTROLLER_SPEED_NORMAL; + + name = controller->GetDeviceName(); + vendor = "ASUS"; + type = DEVICE_TYPE_COOLER; + description = "ASUS Liquid Cooler including 120mm, 140mm, 240mm, 280mm and 360mm radiators."; + version = KEY_EN_UNUSED; + serial = KEY_EN_UNUSED; + location = controller->GetLocation(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = ROGSTRIXLC_CONTROLLER_MODE_DIRECT; + 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 = ROGSTRIXLC_CONTROLLER_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.resize(Static.colors_max); + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = ROGSTRIXLC_CONTROLLER_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.colors.resize(Breathing.colors_max); + Breathing.brightness_min = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MIN; + Breathing.brightness_max = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; + Breathing.brightness = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; + Breathing.speed_min = ROGSTRIXLC_CONTROLLER_SPEED_SLOWEST; + Breathing.speed_max = ROGSTRIXLC_CONTROLLER_SPEED_FASTEST; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.speed = speed; + modes.push_back(Breathing); + + mode Flashing; + Flashing.name = "Flashing"; + Flashing.value = ROGSTRIXLC_CONTROLLER_MODE_FLASHING; + Flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Flashing.colors_min = 1; + Flashing.colors_max = 1; + Flashing.colors.resize(Flashing.colors_max); + Flashing.brightness_min = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MIN; + Flashing.brightness_max = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; + Flashing.brightness = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; + Flashing.speed_min = ROGSTRIXLC_CONTROLLER_SPEED_SLOWEST; + Flashing.speed_max = ROGSTRIXLC_CONTROLLER_SPEED_FASTEST; + Flashing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Flashing.speed = speed; + modes.push_back(Flashing); + + mode Spectrum; + Spectrum.name = "Spectrum"; + Spectrum.value = ROGSTRIXLC_CONTROLLER_MODE_SPECTRUM; + Spectrum.flags = MODE_FLAG_HAS_SPEED; + Spectrum.brightness_min = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MIN; + Spectrum.brightness_max = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; + Spectrum.brightness = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; + Spectrum.speed_min = ROGSTRIXLC_CONTROLLER_SPEED_SLOWEST; + Spectrum.speed_max = ROGSTRIXLC_CONTROLLER_SPEED_FASTEST; + Spectrum.color_mode = MODE_COLORS_NONE; + Spectrum.speed = speed; + modes.push_back(Spectrum); + + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = ROGSTRIXLC_CONTROLLER_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + Rainbow.brightness_min = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MIN; + Rainbow.brightness_max = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; + Rainbow.brightness = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; + Rainbow.speed_min = ROGSTRIXLC_CONTROLLER_SPEED_SLOWEST; + Rainbow.speed_max = ROGSTRIXLC_CONTROLLER_SPEED_FASTEST; + Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.speed = speed; + modes.push_back(Rainbow); + + mode FlashAndDash; + FlashAndDash.name = "Flash and Dash"; + FlashAndDash.value = ROGSTRIXLC_CONTROLLER_MODE_FLASHANDDASH; + FlashAndDash.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + FlashAndDash.brightness_min = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MIN; + FlashAndDash.brightness_max = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; + FlashAndDash.brightness = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; + FlashAndDash.speed_min = ROGSTRIXLC_CONTROLLER_SPEED_SLOWEST; + FlashAndDash.speed_max = ROGSTRIXLC_CONTROLLER_SPEED_FASTEST; + FlashAndDash.color_mode = MODE_COLORS_NONE; + FlashAndDash.speed = speed; + modes.push_back(FlashAndDash); + + SetupZones(); +} + +RGBController_AsusROGStrixLC::~RGBController_AsusROGStrixLC() +{ + delete controller; +} + +void RGBController_AsusROGStrixLC::SetupZones() +{ + /*-------------------------------------------------*\ + | Set up zones | + \*-------------------------------------------------*/ + LOG_DEBUG("[%s] - Get channel count: %i", name.c_str(), controller->GetChannelCount()); + + zones.resize(controller->GetChannelCount()); + + LOG_DEBUG("[%s] - Creating Zones and LEDs", name.c_str()); + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + AuraDeviceInfo device_info = controller->GetAuraDevices()[zone_idx]; + LOG_INFO("[%s] %s Zone %i - Header Count %i LED Count %i FX %02X Direct %02X", name.c_str(), + ((device_info.device_type == AuraDeviceType::FIXED) ? "Fixed" : "Addressable"), + zone_idx, device_info.num_headers, device_info.num_leds, device_info.effect_channel, device_info.direct_channel); + + zones[zone_idx].name = name + " Zone "; + zones[zone_idx].name.append(std::to_string(zone_idx)); + zones[zone_idx].type = ZONE_TYPE_LINEAR; + zones[zone_idx].leds_min = device_info.num_leds; + zones[zone_idx].leds_max = device_info.num_leds; + zones[zone_idx].leds_count = device_info.num_leds; + + for(unsigned int lp_idx = 0; lp_idx < zones[zone_idx].leds_count; lp_idx++) + { + led new_led; + + new_led.name = zones[zone_idx].name; + new_led.name.append(" LED " + std::to_string(lp_idx)); + new_led.value = lp_idx; + + leds.push_back(new_led); + } + } + + LOG_DEBUG("[%s] - Device zones and LEDs set", name.c_str()); + SetupColors(); +} + +void RGBController_AsusROGStrixLC::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_AsusROGStrixLC::DeviceUpdateLEDs() +{ + for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + UpdateZoneLEDs(zone_idx); + } +} + +void RGBController_AsusROGStrixLC::UpdateZoneLEDs(int zone) +{ + controller->SetLedsDirect( zones[zone].colors, zones[zone].leds_count ); +} + +void RGBController_AsusROGStrixLC::UpdateSingleLED(int led) +{ + UpdateZoneLEDs(GetLED_Zone(led)); +} + +void RGBController_AsusROGStrixLC::DeviceUpdateMode() +{ + RGBColor colour = (modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) ? modes[active_mode].colors[0] : 0; + + controller->SetMode( modes[active_mode].value, modes[active_mode].speed, modes[active_mode].direction, colour ); +} + +int RGBController_AsusROGStrixLC::GetLED_Zone(int led_idx) +{ + for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + int zone_start = zones[zone_idx].start_idx; + int zone_end = zone_start + zones[zone_idx].leds_count - 1; + + if(zone_start <= led_idx && zone_end >= led_idx) + { + return(zone_idx); + } + } + + return -1; +} diff --git a/Controllers/AsusAuraUSBController/AsusROGStrixLCController/RGBController_AsusROGStrixLC.h b/Controllers/AsusAuraUSBController/AsusROGStrixLCController/RGBController_AsusROGStrixLC.h new file mode 100644 index 00000000..2992fc9b --- /dev/null +++ b/Controllers/AsusAuraUSBController/AsusROGStrixLCController/RGBController_AsusROGStrixLC.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusROGStrixLC.h | +| | +| RGBController for ASUS Aura liquid cooler | +| | +| Chris M (Dr_No) 17 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "LogManager.h" +#include "RGBController.h" +#include "AsusROGStrixLCController.h" + +class RGBController_AsusROGStrixLC : public RGBController +{ +public: + RGBController_AsusROGStrixLC(AsusROGStrixLCController* controller_ptr); + ~RGBController_AsusROGStrixLC(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); +private: + int GetDeviceMode(); + int GetLED_Zone(int led_idx); + + AsusROGStrixLCController* controller; +}; diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraHeadsetStand.cpp b/Controllers/AsusAuraUSBController/RGBController_AsusAuraHeadsetStand.cpp deleted file mode 100644 index ba20cb8e..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraHeadsetStand.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraHeadsetStand.cpp | -| | -| Generic RGB Interface for Asus Aura | -| USB controller driver | -| | -| Mola19 06/04/2021 | -\*-----------------------------------------*/ - -#include "RGBController_AsusAuraHeadsetStand.h" - -/**------------------------------------------------------------------*\ - @name Asus Aura Headset Stand - @category HeadsetStand - @type USB - @save :white_check_mark: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectAsusAuraUSBHeadsetStand - @comment -\*-------------------------------------------------------------------*/ - -RGBController_AuraHeadsetStand::RGBController_AuraHeadsetStand(AuraHeadsetStandController* controller_ptr) -{ - controller = controller_ptr; - - name = "ASUS Aura Headset Stand"; - vendor = "ASUS"; - type = DEVICE_TYPE_HEADSET_STAND; - description = "ASUS Aura Headset Stand Device"; - version = controller->GetVersion(); - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = AURA_HEADSET_STAND_MODE_DIRECT; - 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 = AURA_HEADSET_STAND_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Static.brightness_min = AURA_HEADSETSTAND_BRIGHTNESS_MIN; - Static.brightness_max = AURA_HEADSETSTAND_BRIGHTNESS_MAX; - Static.brightness = AURA_HEADSETSTAND_BRIGHTNESS_DEFAULT; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; - Static.colors_min = 1; - Static.colors_max = 1; - Static.colors.resize(1); - modes.push_back(Static); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = AURA_HEADSET_STAND_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.speed_min = AURA_HEADSETSTAND_SPEED_MIN; - Breathing.speed_max = AURA_HEADSETSTAND_SPEED_MAX; - Breathing.speed = AURA_HEADSETSTAND_SPEED_DEFAULT; - Breathing.brightness_min = AURA_HEADSETSTAND_BRIGHTNESS_MIN; - Breathing.brightness_max = AURA_HEADSETSTAND_BRIGHTNESS_MAX; - Breathing.brightness = AURA_HEADSETSTAND_BRIGHTNESS_DEFAULT; - Breathing.colors_min = 1; - Breathing.colors_max = 1; - Breathing.colors.resize(1); - modes.push_back(Breathing); - - mode Strobing; - Strobing.name = "Flashing"; - Strobing.value = AURA_HEADSET_STAND_MODE_STROBING; - Strobing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Strobing.brightness_min = AURA_HEADSETSTAND_BRIGHTNESS_MIN; - Strobing.brightness_max = AURA_HEADSETSTAND_BRIGHTNESS_MAX; - Strobing.brightness = AURA_HEADSETSTAND_BRIGHTNESS_DEFAULT; - Strobing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Strobing.colors_min = 1; - Strobing.colors_max = 1; - Strobing.colors.resize(1); - modes.push_back(Strobing); - - mode SpectrumCycle; - SpectrumCycle.name = "Spectrum Cycle"; - SpectrumCycle.value = AURA_HEADSET_STAND_MODE_COLOR_CYCLE; - SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - SpectrumCycle.speed_min = AURA_HEADSETSTAND_SPEED_MIN; - SpectrumCycle.speed_max = AURA_HEADSETSTAND_SPEED_MAX; - SpectrumCycle.speed = AURA_HEADSETSTAND_SPEED_DEFAULT; - SpectrumCycle.brightness_min = AURA_HEADSETSTAND_BRIGHTNESS_MIN; - SpectrumCycle.brightness_max = AURA_HEADSETSTAND_BRIGHTNESS_MAX; - SpectrumCycle.brightness = AURA_HEADSETSTAND_BRIGHTNESS_DEFAULT; - SpectrumCycle.color_mode = MODE_COLORS_NONE; - modes.push_back(SpectrumCycle); - - mode Rainbow; - Rainbow.name = "Rainbow Wave"; - Rainbow.value = AURA_HEADSET_STAND_MODE_RAINBOW; - Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Rainbow.speed_min = AURA_HEADSETSTAND_SPEED_MIN; - Rainbow.speed_max = AURA_HEADSETSTAND_SPEED_MAX; - Rainbow.speed = AURA_HEADSETSTAND_SPEED_DEFAULT; - Rainbow.brightness_min = AURA_HEADSETSTAND_BRIGHTNESS_MIN; - Rainbow.brightness_max = AURA_HEADSETSTAND_BRIGHTNESS_MAX; - Rainbow.brightness = AURA_HEADSETSTAND_BRIGHTNESS_DEFAULT; - modes.push_back(Rainbow); - SetupZones(); -} - -RGBController_AuraHeadsetStand::~RGBController_AuraHeadsetStand() -{ - delete controller; -} - -void RGBController_AuraHeadsetStand::SetupZones() -{ - zone underglow_zone; - - underglow_zone.name = "Underglow"; - underglow_zone.type = ZONE_TYPE_LINEAR; - underglow_zone.leds_min = 17; - underglow_zone.leds_max = 17; - underglow_zone.leds_count = 17; - underglow_zone.matrix_map = NULL; - - zones.push_back(underglow_zone); - - for(unsigned int i = 0; i < 17; i++) - { - led underglow_led; - - underglow_led.name = "Underglow LED " + std::to_string(i); - - leds.push_back(underglow_led); - } - - zone logo_zone; - - logo_zone.name = "Logo"; - logo_zone.type = ZONE_TYPE_SINGLE; - logo_zone.leds_min = 1; - logo_zone.leds_max = 1; - logo_zone.leds_count = 1; - logo_zone.matrix_map = NULL; - - zones.push_back(logo_zone); - - led logo_led; - - logo_led.name = "Logo LED"; - - leds.push_back(logo_led); - - SetupColors(); -} - -void RGBController_AuraHeadsetStand::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_AuraHeadsetStand::DeviceUpdateLEDs() -{ - controller->UpdateLeds(std::vector(colors)); -} - -void RGBController_AuraHeadsetStand::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_AuraHeadsetStand::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_AuraHeadsetStand::DeviceUpdateMode() -{ - unsigned char red = 0; - unsigned char grn = 0; - unsigned char blu = 0; - switch(modes[active_mode].value) - { - case 0: - controller->UpdateLeds(std::vector(colors)); - break; - case 1: - case 2: - case 3: - red = RGBGetRValue(modes[active_mode].colors[0]); - grn = RGBGetGValue(modes[active_mode].colors[0]); - blu = RGBGetBValue(modes[active_mode].colors[0]); - controller->UpdateDevice(modes[active_mode].value, red, grn, blu, modes[active_mode].speed, modes[active_mode].brightness); - break; - case 4: - case 5: - controller->UpdateDevice(modes[active_mode].value, red, grn, blu, modes[active_mode].speed, modes[active_mode].brightness); - break; - } -} - -void RGBController_AuraHeadsetStand::DeviceSaveMode() -{ - DeviceUpdateMode(); - controller->SaveMode(); -} diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraHeadsetStand.h b/Controllers/AsusAuraUSBController/RGBController_AsusAuraHeadsetStand.h deleted file mode 100644 index 2be21a5c..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraHeadsetStand.h +++ /dev/null @@ -1,43 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraHeadsetStand.h | -| | -| Generic RGB Interface for Asus Aura | -| USB controller driver | -| | -| Mola19 06/04/2021 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "AsusAuraHeadsetStandController.h" - -enum -{ - AURA_HEADSETSTAND_BRIGHTNESS_MIN = 0, - AURA_HEADSETSTAND_BRIGHTNESS_MAX = 4, - AURA_HEADSETSTAND_BRIGHTNESS_DEFAULT = 4, - AURA_HEADSETSTAND_SPEED_MIN = 0, - AURA_HEADSETSTAND_SPEED_MAX = 255, - AURA_HEADSETSTAND_SPEED_DEFAULT = 127, -}; - -class RGBController_AuraHeadsetStand : public RGBController -{ -public: - RGBController_AuraHeadsetStand(AuraHeadsetStandController* controller_ptr); - ~RGBController_AuraHeadsetStand(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - AuraHeadsetStandController* controller; -}; diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraKeyboard.h b/Controllers/AsusAuraUSBController/RGBController_AsusAuraKeyboard.h deleted file mode 100644 index ded09cf6..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraKeyboard.h +++ /dev/null @@ -1,56 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraKeyboard.h | -| | -| Generic RGB Interface for Asus Aura | -| USB controller driver | -| | -| Adam Honse (CalcProgrammer1) 3/19/2021 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "AsusAuraKeyboardController.h" - -enum AuraKeyboardMappingLayoutType -{ - FLARE_LAYOUT, - SCOPE_LAYOUT, - SCOPE_RX_LAYOUT, - SCOPE_TKL_LAYOUT, - FALCHION_LAYOUT, -}; - -typedef struct -{ - const char* name; - unsigned char idx; -} led_type; - -typedef struct -{ - const char* name; - const zone_type type; - const unsigned int size; - matrix_map_type* matrix; -} led_zone; - -class RGBController_AuraKeyboard : public RGBController -{ -public: - RGBController_AuraKeyboard(AuraKeyboardController* controller_ptr, AuraKeyboardMappingLayoutType keyboard_layout); - ~RGBController_AuraKeyboard(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - AuraKeyboardController* controller; - AuraKeyboardMappingLayoutType layout; -}; diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraMonitor.cpp b/Controllers/AsusAuraUSBController/RGBController_AsusAuraMonitor.cpp deleted file mode 100644 index f4e1ef8d..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraMonitor.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraMonitor.cpp | -| | -| Generic RGB Interface for Asus Aura | -| USB controller driver | -| | -| Mola19 08/03/2022 | -\*-----------------------------------------*/ - -#include "RGBController_AsusAuraMonitor.h" - -/**------------------------------------------------------------------*\ - @name Asus Aura Monitor - @category LEDStrip - @type USB - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectAsusAuraUSBMonitor - @comment -\*-------------------------------------------------------------------*/ - -RGBController_AuraMonitor::RGBController_AuraMonitor(AuraMonitorController* controller_ptr) -{ - controller = controller_ptr; - - name = "ASUS Aura Monitor"; - vendor = "ASUS"; - type = DEVICE_TYPE_LEDSTRIP; - description = "ASUS Aura Monitor Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - 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(); -} - -RGBController_AuraMonitor::~RGBController_AuraMonitor() -{ - delete controller; -} - -void RGBController_AuraMonitor::SetupZones() -{ - zone underglow_zone; - - underglow_zone.name = "Backlight"; - underglow_zone.type = ZONE_TYPE_LINEAR; - underglow_zone.leds_min = 3; - underglow_zone.leds_max = 3; - underglow_zone.leds_count = 3; - underglow_zone.matrix_map = NULL; - - zones.push_back(underglow_zone); - - for(unsigned int i = 0; i < 3; i++) - { - led underglow_led; - - underglow_led.name = "Backlight LED " + std::to_string(i + 1); - - leds.push_back(underglow_led); - } - - SetupColors(); -} - -void RGBController_AuraMonitor::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_AuraMonitor::DeviceUpdateLEDs() -{ - controller->BeginUpdate(); - - for (int i = 0; i < 3; i++) - { - unsigned char red = RGBGetRValue(colors[i]); - unsigned char green = RGBGetGValue(colors[i]); - unsigned char blue = RGBGetBValue(colors[i]); - - controller->UpdateLed(i, red, green, blue); - } - - controller->ApplyChanges(); -} - -void RGBController_AuraMonitor::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_AuraMonitor::UpdateSingleLED(int led) -{ - controller->BeginUpdate(); - - unsigned char red = RGBGetRValue(colors[led]); - unsigned char green = RGBGetGValue(colors[led]); - unsigned char blue = RGBGetBValue(colors[led]); - - controller->UpdateLed(led, red, green, blue); - - controller->ApplyChanges(); -} - -void RGBController_AuraMonitor::DeviceUpdateMode() -{ - /*---------------------------------------------------------*\ - | This device does not support Mode changing | - \*---------------------------------------------------------*/ -} - -void RGBController_AuraMonitor::DeviceSaveMode() -{ - /*---------------------------------------------------------*\ - | This device does not support Mode saving | - \*---------------------------------------------------------*/ -} diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraMonitor.h b/Controllers/AsusAuraUSBController/RGBController_AsusAuraMonitor.h deleted file mode 100644 index 783d0a29..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraMonitor.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraMonitor.h | -| | -| Generic RGB Interface for Asus Aura | -| USB controller driver | -| | -| Mola19 08/03/2022 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "AsusAuraMonitorController.h" - -class RGBController_AuraMonitor : public RGBController -{ -public: - RGBController_AuraMonitor(AuraMonitorController* controller_ptr); - ~RGBController_AuraMonitor(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - AuraMonitorController* controller; -}; diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraMouse.cpp b/Controllers/AsusAuraUSBController/RGBController_AsusAuraMouse.cpp deleted file mode 100644 index 8763308f..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraMouse.cpp +++ /dev/null @@ -1,265 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraMouse.cpp | -| | -| Generic RGB Interface for Asus Aura | -| USB controller driver | -| | -| Adam Honse (CalcProgrammer1) 10/25/2020 | -\*-----------------------------------------*/ - -#include "RGBController_AsusAuraMouse.h" - -static std::string aura_mouse_zone_names[4] -{ - "Logo", - "Scroll Wheel", - "Underglow", - "Dock" -}; - -/**------------------------------------------------------------------*\ - @name Asus Aura Mouse - @category Mouse - @type USB - @save :white_check_mark: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectAsusAuraUSBMice - @comment -\*-------------------------------------------------------------------*/ - -RGBController_AuraMouse::RGBController_AuraMouse(AuraMouseController* controller_ptr) -{ - controller = controller_ptr; - - pid = controller->device_pid; - - name = "ASUS Aura Mouse"; - vendor = "ASUS"; - type = DEVICE_TYPE_MOUSE; - description = "ASUS Aura Mouse Device"; - version = controller->GetVersion(aura_mouse_devices[pid].wireless, aura_mouse_devices[pid].version_protocol); - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - std::vector mm = aura_mouse_devices[pid].mouse_modes; - - int mode_value = 0; - - for(std::vector::iterator it = mm.begin(); it != mm.end(); it++) - { - switch(*it) - { - case AURA_MOUSE_MODE_STATIC: - { - mode Direct; - Direct.name = "Direct"; - Direct.value = mode_value; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - Direct.brightness_min = aura_mouse_devices[pid].brightness_min; - Direct.brightness_max = aura_mouse_devices[pid].brightness_max; - Direct.brightness = aura_mouse_devices[pid].brightness_max; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - } - break; - - case AURA_MOUSE_MODE_BREATHING: - { - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = mode_value; - Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - Breathing.brightness_min = aura_mouse_devices[pid].brightness_min; - Breathing.brightness_max = aura_mouse_devices[pid].brightness_max; - Breathing.brightness = aura_mouse_devices[pid].brightness_max; - Breathing.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Breathing); - } - break; - - case AURA_MOUSE_MODE_SPECTRUM: - { - mode ColorCycle; - ColorCycle.name = "Spectrum Cycle"; - ColorCycle.value = mode_value; - ColorCycle.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE ; - ColorCycle.brightness_min = aura_mouse_devices[pid].brightness_min; - ColorCycle.brightness_max = aura_mouse_devices[pid].brightness_max; - ColorCycle.brightness = aura_mouse_devices[pid].brightness_max; - ColorCycle.color_mode = MODE_COLORS_NONE; - modes.push_back(ColorCycle); - } - break; - - case AURA_MOUSE_MODE_WAVE: - { - mode Wave; - Wave.name = "Rainbow Wave"; - Wave.value = mode_value; - Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - Wave.direction = 0; - Wave.speed_min = aura_mouse_devices[pid].speed_min; - Wave.speed_max = aura_mouse_devices[pid].speed_max; - Wave.speed = (aura_mouse_devices[pid].speed_min + aura_mouse_devices[pid].speed_max) / 2; - Wave.brightness_min = aura_mouse_devices[pid].brightness_min; - Wave.brightness_max = aura_mouse_devices[pid].brightness_max; - Wave.brightness = aura_mouse_devices[pid].brightness_max; - Wave.color_mode = MODE_COLORS_NONE; - modes.push_back(Wave); - } - break; - - case AURA_MOUSE_MODE_REACTIVE: - { - mode Reactive; - Reactive.name = "Reactive"; - Reactive.value = mode_value; - Reactive.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - Reactive.brightness_min = aura_mouse_devices[pid].brightness_min; - Reactive.brightness_max = aura_mouse_devices[pid].brightness_max; - Reactive.brightness = aura_mouse_devices[pid].brightness_max; - Reactive.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Reactive); - } - break; - - case AURA_MOUSE_MODE_COMET: - { - mode Comet; - Comet.name = "Comet"; - Comet.value = mode_value; - Comet.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - Comet.brightness_min = aura_mouse_devices[pid].brightness_min; - Comet.brightness_max = aura_mouse_devices[pid].brightness_max; - Comet.brightness = aura_mouse_devices[pid].brightness_max; - Comet.color_mode = MODE_COLORS_MODE_SPECIFIC; - Comet.direction = 0; - Comet.colors_min = 1; - Comet.colors_max = 1; - Comet.colors.resize(1); - modes.push_back(Comet); - } - break; - - case AURA_MOUSE_MODE_BATTERY: - { - mode BatteryMode; - BatteryMode.name = "Battery"; - BatteryMode.value = mode_value; - BatteryMode.flags = MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - BatteryMode.brightness_min = aura_mouse_devices[pid].brightness_min; - BatteryMode.brightness_max = aura_mouse_devices[pid].brightness_max; - BatteryMode.brightness = aura_mouse_devices[pid].brightness_max; - BatteryMode.color_mode = MODE_COLORS_NONE; - modes.push_back(BatteryMode); - } - break; - } - mode_value++; - } - - SetupZones(); -} - -RGBController_AuraMouse::~RGBController_AuraMouse() -{ - delete controller; -} - -void RGBController_AuraMouse::SetupZones() -{ - for(std::vector::iterator zone_it = aura_mouse_devices[pid].mouse_zones.begin(); zone_it != aura_mouse_devices[pid].mouse_zones.end(); zone_it++) - { - zone mouse_zone; - - mouse_zone.name = aura_mouse_zone_names[*zone_it]; - mouse_zone.type = ZONE_TYPE_SINGLE; - mouse_zone.leds_min = 1; - mouse_zone.leds_max = 1; - mouse_zone.leds_count = 1; - mouse_zone.matrix_map = NULL; - - zones.push_back(mouse_zone); - - led mouse_led; - - mouse_led.name = mouse_zone.name + " LED"; - mouse_led.value = *zone_it; - - leds.push_back(mouse_led); - } - - SetupColors(); -} - -void RGBController_AuraMouse::ResizeZone(int /*zone*/, int /*new_size*/) -{ - -} - -void RGBController_AuraMouse::DeviceUpdateLEDs() -{ - for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++) - { - UpdateSingleLED(zone_index); - } -} - -void RGBController_AuraMouse::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_AuraMouse::UpdateSingleLED(int led) -{ - uint8_t red = RGBGetRValue(colors[led]); - uint8_t grn = RGBGetGValue(colors[led]); - uint8_t blu = RGBGetBValue(colors[led]); - - controller->SendUpdate(leds[led].value, modes[active_mode].value, red, grn, blu, 0, false, 0, modes[active_mode].brightness); -} - -void RGBController_AuraMouse::DeviceUpdateMode() -{ - if(modes[active_mode].color_mode == MODE_COLORS_PER_LED) - { - DeviceUpdateLEDs(); - } - else - { - unsigned char red = 0; - unsigned char grn = 0; - unsigned char blu = 0; - - if (modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) - { - red = RGBGetRValue(modes[active_mode].colors[0]); - grn = RGBGetGValue(modes[active_mode].colors[0]); - blu = RGBGetBValue(modes[active_mode].colors[0]); - } - - - if(pid == AURA_ROG_SPATHA_X_DOCK_FAKE_PID) - { - controller->SendUpdate(AURA_MOUSE_ZONE_DOCK, modes[active_mode].value, red, grn, blu, modes[active_mode].direction, modes[active_mode].color_mode == MODE_COLORS_RANDOM, modes[active_mode].speed, modes[active_mode].brightness); - } - else if(pid == AURA_ROG_STRIX_IMPACT_PID) - { - /*-----------------------------------------------------------------*\ - | The ROG Impact doesn't accept AURA_MOUSE_ZONE_ALL | - \*-----------------------------------------------------------------*/ - controller->SendUpdate(AURA_MOUSE_ZONE_LOGO, modes[active_mode].value, red, grn, blu, modes[active_mode].direction, modes[active_mode].color_mode == MODE_COLORS_RANDOM, modes[active_mode].speed, modes[active_mode].brightness); - } - else - { - controller->SendUpdate(AURA_MOUSE_ZONE_ALL, modes[active_mode].value, red, grn, blu, modes[active_mode].direction, modes[active_mode].color_mode == MODE_COLORS_RANDOM, modes[active_mode].speed, modes[active_mode].brightness); - } - } -} - -void RGBController_AuraMouse::DeviceSaveMode() -{ - DeviceUpdateMode(); - controller->SaveMode(); -} diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraMouse.h b/Controllers/AsusAuraUSBController/RGBController_AsusAuraMouse.h deleted file mode 100644 index 0fed1509..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraMouse.h +++ /dev/null @@ -1,34 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraMouse.h | -| | -| Generic RGB Interface for Asus Aura | -| USB controller driver | -| | -| Adam Honse (CalcProgrammer1) 10/25/2020 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "AsusAuraMouseController.h" - -class RGBController_AuraMouse : public RGBController -{ -public: - RGBController_AuraMouse(AuraMouseController* controller_ptr); - ~RGBController_AuraMouse(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - AuraMouseController* controller; - uint16_t pid; -}; diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraMousemat.h b/Controllers/AsusAuraUSBController/RGBController_AsusAuraMousemat.h deleted file mode 100644 index 62242e5d..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraMousemat.h +++ /dev/null @@ -1,51 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraMousemat.h | -| | -| Generic RGB Interface for Asus Aura | -| USB controller driver | -| | -| Mola19 06/04/2021 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "AsusAuraMousematController.h" - -enum -{ - AURA_MOUSEMAT_BRIGHTNESS_MIN = 0, - AURA_MOUSEMAT_BRIGHTNESS_MAX = 4, - AURA_MOUSEMAT_BRIGHTNESS_DEFAULT = 4, - AURA_MOUSEMAT_SPEED_MIN = 127, - AURA_MOUSEMAT_SPEED_MAX = 0, - AURA_MOUSEMAT_SPEED_DEFAULT_STATIC = 0, - AURA_MOUSEMAT_SPEED_DEFAULT_BREATHING = 1, - AURA_MOUSEMAT_SPEED_DEFAULT_COLOR_CYCLE = 1, - AURA_MOUSEMAT_SPEED_DEFAULT_WAVE = 14, - AURA_MOUSEMAT_SPEED_DEFAULT_WAVE_PLANE = 2, - AURA_MOUSEMAT_SPEED_DEFAULT_COMET = 2, - AURA_MOUSEMAT_SPEED_DEFAULT_GLOWING_YOYO = 4, - AURA_MOUSEMAT_SPEED_DEFAULT_CROSS = 12, - AURA_MOUSEMAT_SPEED_DEFAULT_STARRY_NIGHT = 2, -}; - -class RGBController_AuraMousemat : public RGBController -{ -public: - RGBController_AuraMousemat(AuraMousematController* controller_ptr); - ~RGBController_AuraMousemat(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - AuraMousematController* controller; -}; diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraRyuoAIO.h b/Controllers/AsusAuraUSBController/RGBController_AsusAuraRyuoAIO.h deleted file mode 100644 index 91133967..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraRyuoAIO.h +++ /dev/null @@ -1,38 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_AsusAuraRyuoAIO.h | -| | -| Driver for the ASUS Aura Ryuo AIO | -| lighting controller | -| | -| Cooper Hall (geobot19 / Geo_bot) 08 Apr 2022 | -| using snipets from Chris M (Dr.No) | -\*-------------------------------------------------------------------*/ - -#pragma once -#include "LogManager.h" -#include "RGBController.h" -#include "AsusAuraRyuoAIOController.h" -#include - -class RGBController_AsusAuraRyuoAIO : public RGBController -{ -public: - RGBController_AsusAuraRyuoAIO(AsusAuraRyuoAIOController* controller_ptr); - ~RGBController_AsusAuraRyuoAIO(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - int GetDeviceMode(); - int GetLED_Zone(int led_idx); - - AsusAuraRyuoAIOController* controller; -}; - diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraStrixEvolve.cpp b/Controllers/AsusAuraUSBController/RGBController_AsusAuraStrixEvolve.cpp deleted file mode 100644 index 2b88eb02..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraStrixEvolve.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraStrixEvolve.cpp | -| | -| Generic RGB Interface for Asus Aura | -| USB controller driver | -| | -| Mola19 11/30/2021 | -\*-----------------------------------------*/ - -#include "RGBController_AsusAuraStrixEvolve.h" - -/**------------------------------------------------------------------*\ - @name Asus Aura Strix Evolve - @category Mouse - @type USB - @save :white_check_mark: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectAsusAuraUSBStrixEvolve - @comment -\*-------------------------------------------------------------------*/ - -RGBController_AuraStrixEvolve::RGBController_AuraStrixEvolve(AuraStrixEvolveController* controller_ptr) -{ - controller = controller_ptr; - - name = "ASUS ROG Strix Evolve"; - vendor = "ASUS"; - type = DEVICE_TYPE_MOUSE; - description = "ASUS Aura Mouse Device"; - version = controller->GetVersion(); - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = 1; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - Direct.brightness_min = AURA_STRIX_EVOLVE_BRIGHTNESS_MIN; - Direct.brightness_max = AURA_STRIX_EVOLVE_BRIGHTNESS_MAX; - Direct.brightness = AURA_STRIX_EVOLVE_BRIGHTNESS_DEFAULT; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = 2; - Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - Breathing.brightness_min = AURA_STRIX_EVOLVE_BRIGHTNESS_MIN; - Breathing.brightness_max = AURA_STRIX_EVOLVE_BRIGHTNESS_MAX; - Breathing.brightness = AURA_STRIX_EVOLVE_BRIGHTNESS_DEFAULT; - Breathing.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Breathing); - - mode ColorCycle; - ColorCycle.name = "Spectrum Cycle"; - ColorCycle.value = 3; - ColorCycle.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - ColorCycle.brightness_min = AURA_STRIX_EVOLVE_BRIGHTNESS_MIN; - ColorCycle.brightness_max = AURA_STRIX_EVOLVE_BRIGHTNESS_MAX; - ColorCycle.brightness = AURA_STRIX_EVOLVE_BRIGHTNESS_DEFAULT; - ColorCycle.color_mode = MODE_COLORS_NONE; - modes.push_back(ColorCycle); - - mode Reactive; - Reactive.name = "Reactive"; - Reactive.value = 4; - Reactive.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - Reactive.brightness_min = AURA_STRIX_EVOLVE_BRIGHTNESS_MIN; - Reactive.brightness_max = AURA_STRIX_EVOLVE_BRIGHTNESS_MAX; - Reactive.brightness = AURA_STRIX_EVOLVE_BRIGHTNESS_DEFAULT; - Reactive.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Reactive); - - SetupZones(); -} - -RGBController_AuraStrixEvolve::~RGBController_AuraStrixEvolve() -{ - delete controller; -} - -void RGBController_AuraStrixEvolve::SetupZones() -{ - zone mouse_zone; - - mouse_zone.name = "Underglow"; - mouse_zone.type = ZONE_TYPE_SINGLE; - mouse_zone.leds_min = 1; - mouse_zone.leds_max = 1; - mouse_zone.leds_count = 1; - mouse_zone.matrix_map = NULL; - - zones.push_back(mouse_zone); - - led mouse_led; - - mouse_led.name = "Underglow"; - mouse_led.value = 1; - - leds.push_back(mouse_led); - - SetupColors(); -} - -void RGBController_AuraStrixEvolve::ResizeZone(int /*zone*/, int /*new_size*/) -{ - -} - -void RGBController_AuraStrixEvolve::DeviceUpdateLEDs() -{ - unsigned char red = RGBGetRValue(colors[0]); - unsigned char grn = RGBGetGValue(colors[0]); - unsigned char blu = RGBGetBValue(colors[0]); - - controller->SendUpdate(0x1C, red); - controller->SendUpdate(0x1D, grn); - controller->SendUpdate(0x1E, blu); -} - -void RGBController_AuraStrixEvolve::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_AuraStrixEvolve::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_AuraStrixEvolve::DeviceUpdateMode() -{ - unsigned char red = RGBGetRValue(colors[0]); - unsigned char grn = RGBGetGValue(colors[0]); - unsigned char blu = RGBGetBValue(colors[0]); - - controller->SendUpdate(0x19, modes[active_mode].value); - controller->SendUpdate(0x1A, modes[active_mode].brightness); - controller->SendUpdate(0x1C, red); - controller->SendUpdate(0x1D, grn); - controller->SendUpdate(0x1E, blu); -} - -void RGBController_AuraStrixEvolve::DeviceSaveMode() -{ - unsigned char red = RGBGetRValue(colors[0]); - unsigned char grn = RGBGetGValue(colors[0]); - unsigned char blu = RGBGetBValue(colors[0]); - - unsigned int profile = controller->GetActiveProfile(); - - controller->UpdateProfile(0x19, profile, modes[active_mode].value); - controller->UpdateProfile(0x1A, profile, modes[active_mode].brightness); - controller->UpdateProfile(0x1C, profile, red); - controller->UpdateProfile(0x1D, profile, grn); - controller->UpdateProfile(0x1E, profile, blu); - - controller->SendSavePacket(); -} diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraStrixEvolve.h b/Controllers/AsusAuraUSBController/RGBController_AsusAuraStrixEvolve.h deleted file mode 100644 index 43a88df8..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraStrixEvolve.h +++ /dev/null @@ -1,40 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraStrixEvolve.h | -| | -| Generic RGB Interface for Asus Aura | -| USB controller driver | -| | -| Mola19 11/30/2021 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "AsusAuraStrixEvolveController.h" - -enum -{ - AURA_STRIX_EVOLVE_BRIGHTNESS_MIN = 0, - AURA_STRIX_EVOLVE_BRIGHTNESS_MAX = 255, - AURA_STRIX_EVOLVE_BRIGHTNESS_DEFAULT = 255 -}; - -class RGBController_AuraStrixEvolve : public RGBController -{ -public: - RGBController_AuraStrixEvolve(AuraStrixEvolveController* controller_ptr); - ~RGBController_AuraStrixEvolve(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - AuraStrixEvolveController* controller; -}; diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraTUFKeyboard.cpp b/Controllers/AsusAuraUSBController/RGBController_AsusAuraTUFKeyboard.cpp deleted file mode 100644 index aa116907..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraTUFKeyboard.cpp +++ /dev/null @@ -1,613 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraTUFKeyboard.cpp | -| | -| Generic RGB Interface for Asus Aura | -| USB controller driver | -| | -| Mola19 03/03/2020 | -\*-----------------------------------------*/ - -#include "RGBController_AsusAuraTUFKeyboard.h" -#include -#include - -/**------------------------------------------------------------------*\ - @name Asus Aura TUF Keyboard - @category Keyboard - @type USB - @save :white_check_mark: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectAsusAuraTUFUSBKeyboard - @comment -\*-------------------------------------------------------------------*/ - -RGBController_AuraTUFKeyboard::RGBController_AuraTUFKeyboard(AuraTUFKeyboardController* controller_ptr) -{ - controller = controller_ptr; - - pid = controller->device_pid; - - if(pid != AURA_ROG_CLAYMORE_PID) - { - name = "ASUS Aura Keyboard"; - vendor = "ASUS"; - type = DEVICE_TYPE_KEYBOARD; - description = "ASUS Aura Keyboard Device"; - version = controller->GetVersion(); - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - unsigned char AURA_KEYBOARD_SPEED_MIN = 0; - unsigned char AURA_KEYBOARD_SPEED_MAX = 0; - unsigned char AURA_KEYBOARD_SPEED_DEFAULT = 0; - - switch(pid) - { - case AURA_TUF_K1_GAMING_PID: - AURA_KEYBOARD_SPEED_MIN = 0; - AURA_KEYBOARD_SPEED_MAX = 2; - AURA_KEYBOARD_SPEED_DEFAULT = 1; - break; - case AURA_TUF_K3_GAMING_PID: - case AURA_TUF_K7_GAMING_PID: - AURA_KEYBOARD_SPEED_MIN = 15; - AURA_KEYBOARD_SPEED_MAX = 0; - AURA_KEYBOARD_SPEED_DEFAULT = 8; - break; - case AURA_TUF_K5_GAMING_PID: - AURA_KEYBOARD_SPEED_MIN = 63; - AURA_KEYBOARD_SPEED_MAX = 0; - AURA_KEYBOARD_SPEED_DEFAULT = 31; - break; - case AURA_ROG_FALCHION_WIRED_PID: - case AURA_ROG_FALCHION_WIRELESS_PID: - AURA_KEYBOARD_SPEED_MIN = 255; - AURA_KEYBOARD_SPEED_MAX = 0; - AURA_KEYBOARD_SPEED_DEFAULT = 8; - break; - default: - AURA_KEYBOARD_SPEED_MIN = 15; - AURA_KEYBOARD_SPEED_MAX = 0; - AURA_KEYBOARD_SPEED_DEFAULT = 8; - } - - mode Direct; - Direct.name = "Direct"; - Direct.value = AURA_KEYBOARD_MODE_DIRECT; - 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 = AURA_KEYBOARD_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - Static.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; - Static.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; - Static.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; - Static.colors_min = 1; - Static.colors_max = 1; - Static.colors.resize(1); - modes.push_back(Static); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = AURA_KEYBOARD_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - if(controller->is_per_led_keyboard) Breathing.flags |= MODE_FLAG_HAS_RANDOM_COLOR; - - Breathing.speed_min = AURA_KEYBOARD_SPEED_MIN; - Breathing.speed_max = AURA_KEYBOARD_SPEED_MAX; - Breathing.speed = AURA_KEYBOARD_SPEED_DEFAULT; - Breathing.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; - Breathing.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; - Breathing.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.colors_min = 1; - Breathing.colors_max = 2; - Breathing.colors.resize(1); - modes.push_back(Breathing); - - mode Color_Cycle; - Color_Cycle.name = "Spectrum Cycle"; - Color_Cycle.value = AURA_KEYBOARD_MODE_COLOR_CYCLE; - Color_Cycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - Color_Cycle.speed_min = AURA_KEYBOARD_SPEED_MIN; - Color_Cycle.speed_max = AURA_KEYBOARD_SPEED_MAX; - Color_Cycle.speed = AURA_KEYBOARD_SPEED_DEFAULT; - Color_Cycle.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; - Color_Cycle.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; - Color_Cycle.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; - Color_Cycle.color_mode = MODE_COLORS_NONE; - modes.push_back(Color_Cycle); - - mode Wave; - Wave.name = "Rainbow Wave"; - Wave.value = AURA_KEYBOARD_MODE_WAVE; - Wave.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_HV | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - if(controller->is_per_led_keyboard) Wave.flags |= MODE_FLAG_HAS_DIRECTION_UD; - - Wave.speed_min = AURA_KEYBOARD_SPEED_MIN; - Wave.speed_max = AURA_KEYBOARD_SPEED_MAX; - Wave.speed = AURA_KEYBOARD_SPEED_DEFAULT; - Wave.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; - Wave.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; - Wave.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; - Wave.direction = MODE_DIRECTION_LEFT; - Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; - - if(!controller->is_per_led_keyboard) - { - Wave.colors_min = 5; - Wave.colors_max = 5; - } - else - { - Wave.colors_min = 1; - Wave.colors_max = 7; - } - - Wave.colors.resize(Wave.colors_max); - modes.push_back(Wave); - - if(controller->is_per_led_keyboard) - { - mode Reactive; - Reactive.name = "Reactive"; - Reactive.value = AURA_KEYBOARD_MODE_REACTIVE; - Reactive.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - Reactive.speed_min = AURA_KEYBOARD_SPEED_MIN; - Reactive.speed_max = AURA_KEYBOARD_SPEED_MAX; - Reactive.speed = AURA_KEYBOARD_SPEED_DEFAULT; - Reactive.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; - Reactive.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; - Reactive.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; - Reactive.color_mode = MODE_COLORS_MODE_SPECIFIC; - Reactive.colors_min = 1; - Reactive.colors_max = 2; - Reactive.colors.resize(1); - modes.push_back(Reactive); - - mode Ripple; - Ripple.name = "Ripple"; - Ripple.value = AURA_KEYBOARD_MODE_RIPPLE; - Ripple.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - Ripple.speed_min = AURA_KEYBOARD_SPEED_MIN; - Ripple.speed_max = AURA_KEYBOARD_SPEED_MAX; - Ripple.speed = AURA_KEYBOARD_SPEED_DEFAULT; - Ripple.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; - Ripple.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; - Ripple.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; - Ripple.color_mode = MODE_COLORS_MODE_SPECIFIC; - Ripple.colors_min = 1; - Ripple.colors_max = 8; - Ripple.colors.resize(7); - modes.push_back(Ripple); - - mode Starry_Night; - Starry_Night.name = "Starry Night"; - Starry_Night.value = AURA_KEYBOARD_MODE_STARRY_NIGHT; - Starry_Night.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - Starry_Night.speed_min = AURA_KEYBOARD_SPEED_MIN; - Starry_Night.speed_max = AURA_KEYBOARD_SPEED_MAX; - Starry_Night.speed = AURA_KEYBOARD_SPEED_DEFAULT; - Starry_Night.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; - Starry_Night.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; - Starry_Night.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; - Starry_Night.color_mode = MODE_COLORS_MODE_SPECIFIC; - Starry_Night.colors_min = 1; - Starry_Night.colors_max = 3; - Starry_Night.colors.resize(1); - modes.push_back(Starry_Night); - - mode Quicksand; - Quicksand.name = "Quicksand"; - Quicksand.value = AURA_KEYBOARD_MODE_QUICKSAND; - Quicksand.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - Quicksand.direction = MODE_DIRECTION_DOWN; - Quicksand.speed_min = AURA_KEYBOARD_SPEED_MIN; - Quicksand.speed_max = AURA_KEYBOARD_SPEED_MAX; - Quicksand.speed = AURA_KEYBOARD_SPEED_DEFAULT; - Quicksand.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; - Quicksand.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; - Quicksand.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; - Quicksand.color_mode = MODE_COLORS_MODE_SPECIFIC; - Quicksand.colors_min = 6; - Quicksand.colors_max = 6; - Quicksand.colors.resize(6); - modes.push_back(Quicksand); - - mode Current; - Current.name = "Current"; - Current.value = AURA_KEYBOARD_MODE_CURRENT; - Current.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - Current.speed_min = AURA_KEYBOARD_SPEED_MIN; - Current.speed_max = AURA_KEYBOARD_SPEED_MAX; - Current.speed = AURA_KEYBOARD_SPEED_DEFAULT; - Current.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; - Current.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; - Current.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; - Current.color_mode = MODE_COLORS_MODE_SPECIFIC; - Current.colors_min = 1; - Current.colors_max = 3; - Current.colors.resize(1); - modes.push_back(Current); - - mode Rain_Drop; - Rain_Drop.name = "Rain Drop"; - Rain_Drop.value = AURA_KEYBOARD_MODE_RAIN_DROP; - Rain_Drop.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_BRIGHTNESS; - Rain_Drop.speed_min = AURA_KEYBOARD_SPEED_MIN; - Rain_Drop.speed_max = AURA_KEYBOARD_SPEED_MAX; - Rain_Drop.speed = AURA_KEYBOARD_SPEED_DEFAULT; - Rain_Drop.brightness_min = AURA_KEYBOARD_BRIGHTNESS_MIN; - Rain_Drop.brightness_max = AURA_KEYBOARD_BRIGHTNESS_MAX; - Rain_Drop.brightness = AURA_KEYBOARD_BRIGHTNESS_DEFAULT; - Rain_Drop.color_mode = MODE_COLORS_MODE_SPECIFIC; - Rain_Drop.colors_min = 1; - Rain_Drop.colors_max = 3; - Rain_Drop.colors.resize(1); - modes.push_back(Rain_Drop); - } - } - else - { - - name = "ASUS ROG Claymore"; - vendor = "ASUS"; - type = DEVICE_TYPE_KEYBOARD; - description = "ASUS Aura Keyboard Device"; - version = controller->GetVersion(); - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = AURA_KEYBOARD_MODE_DIRECT; - 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 = AURA_KEYBOARD_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; - Static.colors_min = 1; - Static.colors_max = 1; - Static.colors.resize(1); - modes.push_back(Static); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = AURA_KEYBOARD_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; - Breathing.speed_min = AURA_CLAYMORE_SPEED_MIN; - Breathing.speed_max = AURA_CLAYMORE_SPEED_MAX; - Breathing.speed = AURA_CLAYMORE_SPEED_DEFAULT_BREATHING; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.colors_min = 1; - Breathing.colors_max = 2; - Breathing.colors.resize(2); - modes.push_back(Breathing); - - mode Color_Cycle; - Color_Cycle.name = "Spectrum Cycle"; - Color_Cycle.value = AURA_KEYBOARD_MODE_COLOR_CYCLE; - Color_Cycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; - Color_Cycle.speed_min = AURA_CLAYMORE_SPEED_MIN; - Color_Cycle.speed_max = AURA_CLAYMORE_SPEED_MAX; - Color_Cycle.speed = AURA_CLAYMORE_SPEED_DEFAULT_COLOR_CYCLE; - Color_Cycle.color_mode = MODE_COLORS_NONE; - modes.push_back(Color_Cycle); - - mode Reactive; - Reactive.name = "Reactive"; - Reactive.value = AURA_KEYBOARD_MODE_REACTIVE; - Reactive.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; - Reactive.speed_min = AURA_CLAYMORE_SPEED_MIN; - Reactive.speed_max = AURA_CLAYMORE_SPEED_MAX; - Reactive.speed = AURA_CLAYMORE_SPEED_DEFAULT_REACTIVE; - Reactive.color_mode = MODE_COLORS_MODE_SPECIFIC; - Reactive.colors_min = 1; - Reactive.colors_max = 2; - Reactive.colors.resize(2); - modes.push_back(Reactive); - - mode Wave; - Wave.name = "Rainbow Wave"; - Wave.value = AURA_KEYBOARD_MODE_WAVE; - Wave.flags = MODE_COLORS_NONE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_AUTOMATIC_SAVE; - Wave.speed_min = AURA_CLAYMORE_SPEED_MIN; - Wave.speed_max = AURA_CLAYMORE_SPEED_MAX; - Wave.speed = AURA_CLAYMORE_SPEED_DEFAULT_WAVE; - Wave.direction = MODE_DIRECTION_LEFT; - Wave.color_mode = MODE_COLORS_NONE; - modes.push_back(Wave); - - mode Color_Wave; - Color_Wave.name = "Color Wave"; - Color_Wave.value = AURA_KEYBOARD_MODE_WAVE; - Color_Wave.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_AUTOMATIC_SAVE; - Color_Wave.speed_min = AURA_CLAYMORE_SPEED_MIN; - Color_Wave.speed_max = AURA_CLAYMORE_SPEED_MAX; - Color_Wave.speed = AURA_CLAYMORE_SPEED_DEFAULT_WAVE; - Color_Wave.direction = MODE_DIRECTION_LEFT; - Color_Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; - Color_Wave.colors_min = 1; - Color_Wave.colors_max = 2; - Color_Wave.colors.resize(2); - modes.push_back(Color_Wave); - - mode Ripple; - Ripple.name = "Ripple"; - Ripple.value = AURA_KEYBOARD_MODE_RIPPLE; - Ripple.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; - Ripple.speed_min = AURA_CLAYMORE_SPEED_MIN; - Ripple.speed_max = AURA_CLAYMORE_SPEED_MAX; - Ripple.speed = AURA_CLAYMORE_SPEED_DEFAULT_RIPPLE; - Ripple.color_mode = MODE_COLORS_MODE_SPECIFIC; - Ripple.colors_min = 1; - Ripple.colors_max = 2; - Ripple.colors.resize(2); - modes.push_back(Ripple); - - mode Starry_Night; - Starry_Night.name = "Starry Night"; - Starry_Night.value = AURA_KEYBOARD_MODE_STARRY_NIGHT; - Starry_Night.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; - Starry_Night.speed_min = AURA_CLAYMORE_SPEED_MIN; - Starry_Night.speed_max = AURA_CLAYMORE_SPEED_MAX; - Starry_Night.speed = AURA_CLAYMORE_SPEED_DEFAULT_STARRY_NIGHT; - Starry_Night.color_mode = MODE_COLORS_MODE_SPECIFIC; - Starry_Night.colors_min = 1; - Starry_Night.colors_max = 2; - Starry_Night.colors.resize(2); - modes.push_back(Starry_Night); - - mode Quicksand; - Quicksand.name = "Quicksand"; - Quicksand.value = AURA_KEYBOARD_MODE_QUICKSAND; - Quicksand.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; - Quicksand.direction = MODE_DIRECTION_DOWN; - Quicksand.speed_min = AURA_CLAYMORE_SPEED_MIN; - Quicksand.speed_max = AURA_CLAYMORE_SPEED_MAX; - Quicksand.speed = AURA_CLAYMORE_SPEED_DEFAULT_QUICKSAND; - Quicksand.color_mode = MODE_COLORS_MODE_SPECIFIC; - Quicksand.colors_min = 6; - Quicksand.colors_max = 6; - Quicksand.colors.resize(6); - modes.push_back(Quicksand); - } - - SetupZones(); -} - -RGBController_AuraTUFKeyboard::~RGBController_AuraTUFKeyboard() -{ - delete controller; -} - -void RGBController_AuraTUFKeyboard::SetupZones() -{ - std::map * keyboard_ptr; - - switch(pid) - { - case AURA_TUF_K3_GAMING_PID: - case AURA_TUF_K7_GAMING_PID: - keyboard_ptr = &AsusTUFK7Layouts; - break; - case AURA_ROG_FALCHION_WIRED_PID: - case AURA_ROG_FALCHION_WIRELESS_PID: - keyboard_ptr = &AsusFalchionLayouts; - break; - case AURA_ROG_CLAYMORE_PID: - unsigned char numpad; - numpad = controller->GetNumpadLocation(); - switch(numpad) - { - case 0: - keyboard_ptr = &AsusClaymoreNoNumpadLayouts; - break; - case 2: - keyboard_ptr = &AsusClaymoreNumpadRightLayouts; - break; - case 3: - keyboard_ptr = &AsusClaymoreNumpadLeftLayouts; - break; - default: - keyboard_ptr = &AsusClaymoreNoNumpadLayouts; - } - break; - case AURA_TUF_K1_GAMING_PID: - case AURA_TUF_K5_GAMING_PID: - keyboard_ptr = &AsusTufK1Layouts; - break; - default: - keyboard_ptr = &AsusTUFK7Layouts; - } - - std::map & keyboard = *keyboard_ptr; - - unsigned char layout = controller->GetLayout(); - - if(keyboard.find(layout % 100) == keyboard.end()) - { - /*---------------------------------------------------------*\ - | If Layout not found, take uk or us | - \*---------------------------------------------------------*/ - layout = std::floor(layout/100) == 2 ? ASUS_TUF_K7_LAYOUT_UK : ASUS_TUF_K7_LAYOUT_US; - } - else - { - layout = layout % 100; - } - - zone keyboard_zone; - keyboard_zone.name = "Keyboard"; - keyboard_zone.type = ZONE_TYPE_MATRIX; - keyboard_zone.leds_min = keyboard[layout].size; - keyboard_zone.leds_max = keyboard[layout].size; - keyboard_zone.leds_count = keyboard[layout].size; - keyboard_zone.matrix_map = new matrix_map_type; - keyboard_zone.matrix_map->height = keyboard[layout].rows; - keyboard_zone.matrix_map->width = keyboard[layout].cols; - keyboard_zone.matrix_map->map = keyboard[layout].matrix_map; - zones.push_back(keyboard_zone); - - for(int led_id = 0; led_id < keyboard[layout].size; led_id++) - { - led new_led; - new_led.name = keyboard[layout].led_names[led_id].name; - new_led.value = keyboard[layout].led_names[led_id].id; - leds.push_back(new_led); - } - - SetupColors(); - - /*---------------------------------------------------------*\ - | sends the init packet for the default mode (direct) | - \*---------------------------------------------------------*/ - DeviceUpdateMode(); -} - -void RGBController_AuraTUFKeyboard::ResizeZone(int /*zone*/, int /*new_size*/) -{ - -} - -void RGBController_AuraTUFKeyboard::DeviceUpdateLEDs() -{ - std::vector led_color_list = {}; - - for(size_t i = 0; i < colors.size(); i++) - { - led_color_list.push_back({ leds[i].value, colors[i] }); - } - - controller->UpdateLeds(led_color_list); -} - -void RGBController_AuraTUFKeyboard::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_AuraTUFKeyboard::UpdateSingleLED(int led) -{ - if(!controller->is_per_led_keyboard) - { - return DeviceUpdateLEDs(); - } - - unsigned char red = RGBGetRValue(colors[led]); - unsigned char green = RGBGetGValue(colors[led]); - unsigned char blue = RGBGetBValue(colors[led]); - - controller->UpdateSingleLed(leds[led].value, red, green, blue); -} - -static const uint8_t direction_map[2][6] = -{ - { 4, 0, 6, 2, 8, 1 }, // Default directions Left, Right, Up, Down, Horizontal, Vertical - { 0, 4, 6, 2, 0xFF, 0xFF }, // AURA_ROG_CLAYMORE directions Left, Right, Up, Down -}; - -void RGBController_AuraTUFKeyboard::DeviceUpdateMode() -{ - if(pid == AURA_ROG_CLAYMORE_PID) - { - controller->AllowRemoteControl(1); - } - - unsigned char color_mode = 0; - unsigned char direction = 0; - unsigned char brightness = 0; - - if(modes[active_mode].value == AURA_KEYBOARD_MODE_DIRECT) - { - if(pid == AURA_ROG_CLAYMORE_PID) controller->AllowRemoteControl(3); - return; - }; - - if(pid != AURA_ROG_CLAYMORE_PID) - { - brightness = modes[active_mode].brightness * 25; - - switch(modes[active_mode].value) - { - case AURA_KEYBOARD_MODE_BREATHING: - case AURA_KEYBOARD_MODE_REACTIVE: - case AURA_KEYBOARD_MODE_STARRY_NIGHT: - case AURA_KEYBOARD_MODE_CURRENT: - case AURA_KEYBOARD_MODE_RAIN_DROP: - if(!controller->is_per_led_keyboard && modes[active_mode].colors.size() > 1) - { - color_mode = 1; - break; - } - - bool color_is_black = (modes[active_mode].colors.size() > 1 && modes[active_mode].colors[1] == 000); - - if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC && !color_is_black) - { - color_mode = 16; - } - break; - } - - if(modes[active_mode].color_mode == MODE_COLORS_RANDOM) - { - color_mode = 1; - } - - if(modes[active_mode].value == AURA_KEYBOARD_MODE_WAVE) - { - /*----------------------------------------------------------*\ - | converting openrgb direction value to keyboard directions | - \*----------------------------------------------------------*/ - direction = direction_map[0][modes[active_mode].direction]; - } - } - else - { - if(modes[active_mode].color_mode == MODE_COLORS_RANDOM) - { - color_mode = 1; - } - - if(modes[active_mode].value == AURA_KEYBOARD_MODE_WAVE) { - if (modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) color_mode = 2; - - /*----------------------------------------------------------*\ - | converting openrgb direction value to keyboard directions | - \*----------------------------------------------------------*/ - direction = direction_map[1][modes[active_mode].direction]; - } - } - - - controller->UpdateDevice(modes[active_mode].value, std::vector(modes[active_mode].colors), direction, color_mode, modes[active_mode].speed, brightness); - - if(pid == AURA_ROG_CLAYMORE_PID) - { - controller->UpdateMode(modes[active_mode].value); - controller->SaveMode(); - controller->AllowRemoteControl(0); - } -} - -void RGBController_AuraTUFKeyboard::DeviceSaveMode() -{ - /*----------------------------------------------------------*\ - | not available for Claymore | - \*----------------------------------------------------------*/ - if(pid != AURA_ROG_CLAYMORE_PID) - { - DeviceUpdateMode(); - controller->SaveMode(); - } -} diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraTUFKeyboard.h b/Controllers/AsusAuraUSBController/RGBController_AsusAuraTUFKeyboard.h deleted file mode 100644 index dc811b26..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraTUFKeyboard.h +++ /dev/null @@ -1,55 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraTUFKeyboard.h | -| | -| Generic RGB Interface for Asus Aura | -| USB controller driver | -| | -| Mola19 03/03/2021 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "AsusAuraTUFKeyboardController.h" - -enum -{ - AURA_KEYBOARD_BRIGHTNESS_MIN = 0, - AURA_KEYBOARD_BRIGHTNESS_MAX = 4, - AURA_KEYBOARD_BRIGHTNESS_DEFAULT = 4, -}; - -enum -{ - AURA_CLAYMORE_SPEED_MIN = 254, - AURA_CLAYMORE_SPEED_MAX = 0, - AURA_CLAYMORE_SPEED_DEFAULT_STATIC = 0, - AURA_CLAYMORE_SPEED_DEFAULT_BREATHING = 107, - AURA_CLAYMORE_SPEED_DEFAULT_COLOR_CYCLE = 121, - AURA_CLAYMORE_SPEED_DEFAULT_REACTIVE = 56, - AURA_CLAYMORE_SPEED_DEFAULT_WAVE = 50, - AURA_CLAYMORE_SPEED_DEFAULT_RIPPLE = 108, - AURA_CLAYMORE_SPEED_DEFAULT_STARRY_NIGHT = 54, - AURA_CLAYMORE_SPEED_DEFAULT_QUICKSAND = 103 -}; - -class RGBController_AuraTUFKeyboard : public RGBController -{ -public: - RGBController_AuraTUFKeyboard(AuraTUFKeyboardController* controller_ptr); - ~RGBController_AuraTUFKeyboard(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - AuraTUFKeyboardController* controller; - uint16_t pid; -}; diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraUSB.cpp b/Controllers/AsusAuraUSBController/RGBController_AsusAuraUSB.cpp deleted file mode 100644 index a103323d..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraUSB.cpp +++ /dev/null @@ -1,273 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraUSB.cpp | -| | -| Generic RGB Interface for Asus Aura | -| USB controller driver | -| | -| Adam Honse (CalcProgrammer1) 1/18/2020 | -\*-----------------------------------------*/ - -#include "RGBController_AsusAuraUSB.h" - -/**------------------------------------------------------------------*\ - @name Asus Aura USB - @category Motherboard - @type USB - @save :x: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectAsusAuraUSBTerminal,DetectAsusAuraUSBAddressable,DetectAsusAuraUSBMotherboards - @comment The Asus Aura USB controller applies to most AMD and - Intel mainboards from the x470 and z390 chipsets onwards. -\*-------------------------------------------------------------------*/ - -RGBController_AuraUSB::RGBController_AuraUSB(AuraUSBController* controller_ptr) : - initializedMode(false) -{ - controller = controller_ptr; - - name = "ASUS Aura USB"; - vendor = "ASUS"; - version = controller->GetDeviceName(); - type = DEVICE_TYPE_MOTHERBOARD; - description = "ASUS Aura USB Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = AURA_MODE_DIRECT; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - - mode Off; - Off.name = "Off"; - Off.value = AURA_MODE_OFF; - Off.flags = 0; - Off.color_mode = MODE_COLORS_NONE; - modes.push_back(Off); - - mode Static; - Static.name = "Static"; - Static.value = AURA_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Static.colors_min = 1; - Static.colors_max = 1; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; - Static.colors.resize(1); - modes.push_back(Static); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = AURA_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Breathing.colors_min = 1; - Breathing.colors_max = 1; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.colors.resize(1); - modes.push_back(Breathing); - - mode Flashing; - Flashing.name = "Flashing"; - Flashing.value = AURA_MODE_FLASHING; - Flashing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Flashing.colors_min = 1; - Flashing.colors_max = 1; - Flashing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Flashing.colors.resize(1); - modes.push_back(Flashing); - - mode SpectrumCycle; - SpectrumCycle.name = "Spectrum Cycle"; - SpectrumCycle.value = AURA_MODE_SPECTRUM_CYCLE; - SpectrumCycle.flags = 0; - SpectrumCycle.color_mode = MODE_COLORS_NONE; - modes.push_back(SpectrumCycle); - - mode Rainbow; - Rainbow.name = "Rainbow"; - Rainbow.value = AURA_MODE_RAINBOW; - Rainbow.flags = 0; - Rainbow.color_mode = MODE_COLORS_NONE; - modes.push_back(Rainbow); - - mode ChaseFade; - ChaseFade.name = "Chase Fade"; - ChaseFade.value = AURA_MODE_CHASE_FADE; - ChaseFade.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - ChaseFade.colors_min = 1; - ChaseFade.colors_max = 1; - ChaseFade.color_mode = MODE_COLORS_MODE_SPECIFIC; - ChaseFade.colors.resize(1); - modes.push_back(ChaseFade); - - mode Chase; - Chase.name = "Chase"; - Chase.value = AURA_MODE_CHASE; - Chase.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Chase.colors_min = 1; - Chase.colors_max = 1; - Chase.color_mode = MODE_COLORS_MODE_SPECIFIC; - Chase.colors.resize(1); - modes.push_back(Chase); - - SetupZones(); -} - -RGBController_AuraUSB::~RGBController_AuraUSB() -{ - delete controller; -} - -void RGBController_AuraUSB::SetupZones() -{ - /*-------------------------------------------------*\ - | Only set LED count on the first run | - \*-------------------------------------------------*/ - bool first_run = false; - - if(zones.size() == 0) - { - first_run = true; - } - - /*-------------------------------------------------*\ - | Clear any existing color/LED configuration | - \*-------------------------------------------------*/ - leds.clear(); - colors.clear(); - zones.resize(controller->GetChannelCount()); - - /*-------------------------------------------------*\ - | Set zones and leds | - \*-------------------------------------------------*/ - int addressableCounter = 1; - for (unsigned int channel_idx = 0; channel_idx < zones.size(); channel_idx++) - { - AuraDeviceInfo device_info = controller->GetAuraDevices()[channel_idx]; - - zones[channel_idx].type = ZONE_TYPE_LINEAR; - - if(device_info.device_type == AuraDeviceType::FIXED) - { - zones[channel_idx].name = "Aura Mainboard"; - zones[channel_idx].leds_min = device_info.num_leds; - zones[channel_idx].leds_max = device_info.num_leds; - zones[channel_idx].leds_count = device_info.num_leds; - } - else - { - zones[channel_idx].name = "Aura Addressable "; - zones[channel_idx].name.append(std::to_string(addressableCounter)); - zones[channel_idx].leds_min = 0; - zones[channel_idx].leds_max = AURA_ADDRESSABLE_MAX_LEDS; - - addressableCounter++; - - if(first_run) - { - zones[channel_idx].leds_count = 0; - } - } - - unsigned int num_mainboard_leds = device_info.num_leds - device_info.num_headers; - for (unsigned int led_ch_idx = 0; led_ch_idx < zones[channel_idx].leds_count; led_ch_idx++) - { - unsigned led_idx = led_ch_idx + 1; - led new_led; - - new_led.name = zones[channel_idx].name; - if(device_info.device_type == AuraDeviceType::FIXED && led_ch_idx >= num_mainboard_leds) - { - new_led.name.append(", RGB Header "); - led_idx -= num_mainboard_leds; - } - else - { - new_led.name.append(", LED "); - } - new_led.name.append(std::to_string(led_idx)); - - new_led.value = channel_idx; - - leds.push_back(new_led); - } - - zones[channel_idx].matrix_map = NULL; - } - - SetupColors(); -} - -void RGBController_AuraUSB::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_AuraUSB::DeviceUpdateLEDs() -{ - if(!initializedMode) - { - DeviceUpdateMode(); - } - for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) - { - controller->SetChannelLEDs(zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); - } -} - -void RGBController_AuraUSB::UpdateZoneLEDs(int zone) -{ - if(!initializedMode) - { - DeviceUpdateMode(); - } - - controller->SetChannelLEDs(zone, zones[zone].colors, zones[zone].leds_count); -} - -void RGBController_AuraUSB::UpdateSingleLED(int led) -{ - if(!initializedMode) - { - DeviceUpdateMode(); - } - - unsigned int channel = leds[led].value; - - controller->SetChannelLEDs(channel, zones[channel].colors, zones[channel].leds_count); -} - -void RGBController_AuraUSB::DeviceUpdateMode() -{ - initializedMode = true; - unsigned char red = 0; - unsigned char grn = 0; - unsigned char blu = 0; - - if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) - { - red = RGBGetRValue(modes[active_mode].colors[0]); - grn = RGBGetGValue(modes[active_mode].colors[0]); - blu = RGBGetBValue(modes[active_mode].colors[0]); - } - - for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++) - { - if(zones[zone_idx].leds_count > 0) - { - controller->SetMode(zone_idx, modes[active_mode].value, red, grn, blu); - } - } -} diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusAuraUSB.h b/Controllers/AsusAuraUSBController/RGBController_AsusAuraUSB.h deleted file mode 100644 index d72320b9..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusAuraUSB.h +++ /dev/null @@ -1,37 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusAuraUSB.h | -| | -| Generic RGB Interface for Asus Aura | -| USB controller driver | -| | -| Adam Honse (CalcProgrammer1) 1/18/2020 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "AsusAuraUSBController.h" - -#define AURA_ADDRESSABLE_MAX_LEDS 120 - -class RGBController_AuraUSB : public RGBController -{ -public: - RGBController_AuraUSB(AuraUSBController* controller_ptr); - ~RGBController_AuraUSB(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - AuraUSBController* controller; - std::vector leds_channel; - std::vector zones_channel; - bool initializedMode; -}; diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusROGAlly.cpp b/Controllers/AsusAuraUSBController/RGBController_AsusROGAlly.cpp deleted file mode 100644 index 55561b17..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusROGAlly.cpp +++ /dev/null @@ -1,196 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusROGAlly.cpp | -| | -| Generic RGB Interface for Asus ROG Ally | -| controller driver | -| | -| Adam Honse (CalcProgrammer1) 6/12/2023 | -\*-----------------------------------------*/ - -#include "RGBController_AsusROGAlly.h" - -/**------------------------------------------------------------------*\ - @name Asus ROG Ally - @category Gamepad - @type USB - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectAsusROGAlly - @comment -\*-------------------------------------------------------------------*/ - -RGBController_AsusROGAlly::RGBController_AsusROGAlly(ROGAllyController* controller_ptr) -{ - controller = controller_ptr; - - name = "ASUS ROG Ally"; - vendor = "ASUS"; - type = DEVICE_TYPE_GAMEPAD; - description = "ASUS ROG Ally Device"; - version = controller->GetVersion(); - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = ROG_ALLY_MODE_DIRECT; - 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 = ROG_ALLY_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_MANUAL_SAVE; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; - Static.colors_min = 1; - Static.colors_max = 1; - Static.colors.resize(1); - modes.push_back(Static); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = ROG_ALLY_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_SPEED; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.speed_min = ROG_ALLY_SPEED_MIN; - Breathing.speed_max = ROG_ALLY_SPEED_MAX; - Breathing.speed = ROG_ALLY_SPEED_MED; - Breathing.colors_min = 2; - Breathing.colors_max = 2; - Breathing.colors.resize(2); - modes.push_back(Breathing); - - mode ColorCycle; - ColorCycle.name = "Spectrum Cycle"; - ColorCycle.value = ROG_ALLY_MODE_COLOR_CYCLE; - ColorCycle.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_SPEED; - ColorCycle.color_mode = MODE_COLORS_RANDOM; - ColorCycle.speed_min = ROG_ALLY_SPEED_MIN; - ColorCycle.speed_max = ROG_ALLY_SPEED_MAX; - ColorCycle.speed = ROG_ALLY_SPEED_MED; - modes.push_back(ColorCycle); - - mode Rainbow; - Rainbow.name = "Rainbow Wave"; - Rainbow.value = ROG_ALLY_MODE_RAINBOW; - Rainbow.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_MANUAL_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; - Rainbow.color_mode = MODE_COLORS_RANDOM; - Rainbow.speed_min = ROG_ALLY_SPEED_MIN; - Rainbow.speed_max = ROG_ALLY_SPEED_MAX; - Rainbow.speed = ROG_ALLY_SPEED_MED; - modes.push_back(Rainbow); - - mode Strobing; - Strobing.name = "Strobing"; - Strobing.value = ROG_ALLY_MODE_STROBING; - Strobing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_MANUAL_SAVE; - Strobing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Strobing.colors_min = 1; - Strobing.colors_max = 1; - Strobing.colors.resize(1); - modes.push_back(Strobing); - - SetupZones(); -} - -RGBController_AsusROGAlly::~RGBController_AsusROGAlly() -{ - delete controller; -} - -void RGBController_AsusROGAlly::SetupZones() -{ - zone left_stick_zone; - - left_stick_zone.name = "Left Stick"; - left_stick_zone.type = ZONE_TYPE_SINGLE; - left_stick_zone.leds_min = 2; - left_stick_zone.leds_max = 2; - left_stick_zone.leds_count = 2; - left_stick_zone.matrix_map = NULL; - - zones.push_back(left_stick_zone); - - for(unsigned int i = 0; i < 2; i++) - { - led left_stick_led; - - left_stick_led.name = "Left Stick LED " + std::to_string(i); - - leds.push_back(left_stick_led); - } - - zone right_stick_zone; - - right_stick_zone.name = "Right Stick"; - right_stick_zone.type = ZONE_TYPE_SINGLE; - right_stick_zone.leds_min = 2; - right_stick_zone.leds_max = 2; - right_stick_zone.leds_count = 2; - right_stick_zone.matrix_map = NULL; - - zones.push_back(right_stick_zone); - - for(unsigned int i = 0; i < 2; i++) - { - led right_stick_led; - - right_stick_led.name = "Right Stick LED " + std::to_string(i); - - leds.push_back(right_stick_led); - } - - SetupColors(); -} - -void RGBController_AsusROGAlly::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_AsusROGAlly::DeviceUpdateLEDs() -{ - if(modes[active_mode].value == ROG_ALLY_MODE_DIRECT) - { - controller->UpdateLeds(std::vector(colors)); - } -} - -void RGBController_AsusROGAlly::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_AsusROGAlly::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_AsusROGAlly::DeviceUpdateMode() -{ - if(modes[active_mode].value == ROG_ALLY_MODE_DIRECT) - { - DeviceUpdateLEDs(); - } - else - { - unsigned int rog_ally_direction = ROG_ALLY_DIRECTION_RIGHT; - - if((modes[active_mode].flags & MODE_FLAG_HAS_DIRECTION_LR) && (modes[active_mode].direction == MODE_DIRECTION_LEFT)) - { - rog_ally_direction = ROG_ALLY_DIRECTION_LEFT; - } - - controller->UpdateDevice(modes[active_mode].value, modes[active_mode].colors, modes[active_mode].speed, modes[active_mode].brightness, rog_ally_direction); - } -} - -void RGBController_AsusROGAlly::DeviceSaveMode() -{ - DeviceUpdateMode(); - controller->SaveMode(); -} diff --git a/Controllers/AsusAuraUSBController/RGBController_AsusROGAlly.h b/Controllers/AsusAuraUSBController/RGBController_AsusROGAlly.h deleted file mode 100644 index e3531ac7..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_AsusROGAlly.h +++ /dev/null @@ -1,34 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusROGAlly.cpp | -| | -| Generic RGB Interface for Asus ROG Ally | -| controller driver | -| | -| Adam Honse (CalcProgrammer1) 6/12/2023 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "AsusROGAllyController.h" - -class RGBController_AsusROGAlly : public RGBController -{ -public: - RGBController_AsusROGAlly(ROGAllyController* controller_ptr); - ~RGBController_AsusROGAlly(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - ROGAllyController* controller; -}; diff --git a/Controllers/AsusAuraUSBController/RGBController_ROGStrixLC_Controller.cpp b/Controllers/AsusAuraUSBController/RGBController_ROGStrixLC_Controller.cpp deleted file mode 100644 index 91f14c52..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_ROGStrixLC_Controller.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_ROGStrixLC_Controller.cpp | -| | -| Driver for the ASUS Aura Liquid Cooler (LC) series | -| of lighting controllers | -| | -| Chris M (Dr_No) 17 Jan 2022 | -| | -\*-------------------------------------------------------------------*/ - -#include "RGBControllerKeyNames.h" -#include "RGBController_ROGStrixLC_Controller.h" - -/**------------------------------------------------------------------*\ - @name Asus ROG Strix Liquid Cooler - @category Cooler - @type USB - @save :x: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectAsusAuraUSBROGStrixLC - @comment -\*-------------------------------------------------------------------*/ - -RGBController_ROGStrixLC_Controller::RGBController_ROGStrixLC_Controller(ROGStrixLC_Controller *controller_ptr) -{ - controller = controller_ptr; - uint8_t speed = ROGSTRIXLC_CONTROLLER_SPEED_NORMAL; - - name = "ROG Strix LC"; - vendor = "ASUS"; - type = DEVICE_TYPE_COOLER; - description = "ASUS Liquid Cooler including 120mm, 140mm, 240mm, 280mm and 360mm radiators."; - version = KEY_EN_UNUSED; - serial = KEY_EN_UNUSED; - location = controller->GetLocation(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = ROGSTRIXLC_CONTROLLER_MODE_DIRECT; - 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 = ROGSTRIXLC_CONTROLLER_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Static.colors_min = 1; - Static.colors_max = 1; - Static.colors.resize(Static.colors_max); - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; - modes.push_back(Static); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = ROGSTRIXLC_CONTROLLER_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Breathing.colors_min = 1; - Breathing.colors_max = 1; - Breathing.colors.resize(Breathing.colors_max); - Breathing.brightness_min = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MIN; - Breathing.brightness_max = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; - Breathing.brightness = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; - Breathing.speed_min = ROGSTRIXLC_CONTROLLER_SPEED_SLOWEST; - Breathing.speed_max = ROGSTRIXLC_CONTROLLER_SPEED_FASTEST; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.speed = speed; - modes.push_back(Breathing); - - mode Flashing; - Flashing.name = "Flashing"; - Flashing.value = ROGSTRIXLC_CONTROLLER_MODE_FLASHING; - Flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Flashing.colors_min = 1; - Flashing.colors_max = 1; - Flashing.colors.resize(Flashing.colors_max); - Flashing.brightness_min = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MIN; - Flashing.brightness_max = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; - Flashing.brightness = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; - Flashing.speed_min = ROGSTRIXLC_CONTROLLER_SPEED_SLOWEST; - Flashing.speed_max = ROGSTRIXLC_CONTROLLER_SPEED_FASTEST; - Flashing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Flashing.speed = speed; - modes.push_back(Flashing); - - mode Spectrum; - Spectrum.name = "Spectrum"; - Spectrum.value = ROGSTRIXLC_CONTROLLER_MODE_SPECTRUM; - Spectrum.flags = MODE_FLAG_HAS_SPEED; - Spectrum.brightness_min = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MIN; - Spectrum.brightness_max = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; - Spectrum.brightness = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; - Spectrum.speed_min = ROGSTRIXLC_CONTROLLER_SPEED_SLOWEST; - Spectrum.speed_max = ROGSTRIXLC_CONTROLLER_SPEED_FASTEST; - Spectrum.color_mode = MODE_COLORS_NONE; - Spectrum.speed = speed; - modes.push_back(Spectrum); - - mode Rainbow; - Rainbow.name = "Rainbow"; - Rainbow.value = ROGSTRIXLC_CONTROLLER_MODE_RAINBOW; - Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; - Rainbow.brightness_min = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MIN; - Rainbow.brightness_max = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; - Rainbow.brightness = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; - Rainbow.speed_min = ROGSTRIXLC_CONTROLLER_SPEED_SLOWEST; - Rainbow.speed_max = ROGSTRIXLC_CONTROLLER_SPEED_FASTEST; - Rainbow.color_mode = MODE_COLORS_NONE; - Rainbow.speed = speed; - modes.push_back(Rainbow); - - mode FlashAndDash; - FlashAndDash.name = "Flash and Dash"; - FlashAndDash.value = ROGSTRIXLC_CONTROLLER_MODE_FLASHANDDASH; - FlashAndDash.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; - FlashAndDash.brightness_min = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MIN; - FlashAndDash.brightness_max = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; - FlashAndDash.brightness = ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX; - FlashAndDash.speed_min = ROGSTRIXLC_CONTROLLER_SPEED_SLOWEST; - FlashAndDash.speed_max = ROGSTRIXLC_CONTROLLER_SPEED_FASTEST; - FlashAndDash.color_mode = MODE_COLORS_NONE; - FlashAndDash.speed = speed; - modes.push_back(FlashAndDash); - - SetupZones(); -} - -RGBController_ROGStrixLC_Controller::~RGBController_ROGStrixLC_Controller() -{ - delete controller; -} - -void RGBController_ROGStrixLC_Controller::SetupZones() -{ - /*-------------------------------------------------*\ - | Set up zones | - \*-------------------------------------------------*/ - LOG_DEBUG("[%s] - Get channel count: %i", name.c_str(), controller->GetChannelCount()); - - zones.resize(controller->GetChannelCount()); - - LOG_DEBUG("[%s] - Creating Zones and LEDs", name.c_str()); - for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) - { - AuraDeviceInfo device_info = controller->GetAuraDevices()[zone_idx]; - LOG_INFO("[%s] %s Zone %i - Header Count %i LED Count %i FX %02X Direct %02X", name.c_str(), - ((device_info.device_type == AuraDeviceType::FIXED) ? "Fixed" : "Addressable"), - zone_idx, device_info.num_headers, device_info.num_leds, device_info.effect_channel, device_info.direct_channel); - - zones[zone_idx].name = name + " Zone "; - zones[zone_idx].name.append(std::to_string(zone_idx)); - zones[zone_idx].type = ZONE_TYPE_LINEAR; - zones[zone_idx].leds_min = device_info.num_leds; - zones[zone_idx].leds_max = device_info.num_leds; - zones[zone_idx].leds_count = device_info.num_leds; - - for(unsigned int lp_idx = 0; lp_idx < zones[zone_idx].leds_count; lp_idx++) - { - led new_led; - - new_led.name = zones[zone_idx].name; - new_led.name.append(" LED " + std::to_string(lp_idx)); - new_led.value = lp_idx; - - leds.push_back(new_led); - } - } - - LOG_DEBUG("[%s] - Device zones and LEDs set", name.c_str()); - SetupColors(); -} - -void RGBController_ROGStrixLC_Controller::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_ROGStrixLC_Controller::DeviceUpdateLEDs() -{ - for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) - { - UpdateZoneLEDs(zone_idx); - } -} - -void RGBController_ROGStrixLC_Controller::UpdateZoneLEDs(int zone) -{ - controller->SetLedsDirect( zones[zone].colors, zones[zone].leds_count ); -} - -void RGBController_ROGStrixLC_Controller::UpdateSingleLED(int led) -{ - UpdateZoneLEDs(GetLED_Zone(led)); -} - -void RGBController_ROGStrixLC_Controller::DeviceUpdateMode() -{ - RGBColor colour = (modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) ? modes[active_mode].colors[0] : 0; - - controller->SetMode( modes[active_mode].value, modes[active_mode].speed, modes[active_mode].direction, colour ); -} - -int RGBController_ROGStrixLC_Controller::GetLED_Zone(int led_idx) -{ - for(size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) - { - int zone_start = zones[zone_idx].start_idx; - int zone_end = zone_start + zones[zone_idx].leds_count - 1; - - if( zone_start <= led_idx && zone_end >= led_idx) - { - return(zone_idx); - } - } - - return -1; -} diff --git a/Controllers/AsusAuraUSBController/RGBController_ROGStrixLC_Controller.h b/Controllers/AsusAuraUSBController/RGBController_ROGStrixLC_Controller.h deleted file mode 100644 index 5f5c27d2..00000000 --- a/Controllers/AsusAuraUSBController/RGBController_ROGStrixLC_Controller.h +++ /dev/null @@ -1,36 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_ROGStrixLC_Controller.h | -| | -| Driver for the ASUS Aura Liquid Cooler (LC) series | -| of lighting controllers | -| | -| Chris M (Dr_No) 17 Jan 2022 | -| | -\*-------------------------------------------------------------------*/ - -#pragma once -#include "LogManager.h" -#include "RGBController.h" -#include "ROGStrixLC_Controller.h" -#include - -class RGBController_ROGStrixLC_Controller : public RGBController -{ -public: - RGBController_ROGStrixLC_Controller(ROGStrixLC_Controller* controller_ptr); - ~RGBController_ROGStrixLC_Controller(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); -private: - int GetDeviceMode(); - int GetLED_Zone(int led_idx); - - ROGStrixLC_Controller* controller; -}; diff --git a/Controllers/AsusAuraUSBController/ROGStrixLC_Controller.cpp b/Controllers/AsusAuraUSBController/ROGStrixLC_Controller.cpp deleted file mode 100644 index e2dc06b2..00000000 --- a/Controllers/AsusAuraUSBController/ROGStrixLC_Controller.cpp +++ /dev/null @@ -1,127 +0,0 @@ -/*-------------------------------------------------------------------*\ -| ROGStrixLC_Controller.cpp | -| | -| Driver for the ASUS Aura Liquid Cooler (LC) series | -| of lighting controllers | -| | -| Chris M (Dr_No) 17 Jan 2022 | -| | -\*-------------------------------------------------------------------*/ - -#include "ROGStrixLC_Controller.h" - -ROGStrixLC_Controller::ROGStrixLC_Controller(hid_device* dev_handle, const char* path) : AuraUSBController(dev_handle, path) -{ - /*-----------------------------------------------------*\ - | Add addressable devices | - | Manually adding device info for now | - | TODO: Implement config table accurately | - | LC120 - 1F FF 05 05 04 00 00 00 | - \*-----------------------------------------------------*/ - device_info.push_back({0x00, 0x00, 4, 0, AuraDeviceType::FIXED}); -} - -ROGStrixLC_Controller::~ROGStrixLC_Controller() -{ - // Device will close at AuraUSBController destructor -} - -std::string ROGStrixLC_Controller::GetLocation() -{ - return("HID: " + location); -} - -void ROGStrixLC_Controller::SetMode(unsigned char /*channel*/, unsigned char /*mode*/, unsigned char /*red*/, unsigned char /*grn*/, unsigned char /*blu*/) -{ - /*---------------------------------------------------------*\ - | This interface is not used in this controller however is | - | required by the abstract class | - \*---------------------------------------------------------*/ -} - -void ROGStrixLC_Controller::SetMode(unsigned char mode, unsigned char speed, unsigned char direction, RGBColor colour) -{ - bool needs_update = !( (current_mode == mode) && (ToRGBColor(current_red, current_green, current_blue) == colour) && (current_speed == speed) && (current_direction == direction)); - - if (needs_update) - { - current_mode = mode; - current_speed = speed; - current_direction = direction; - current_red = RGBGetRValue(colour); - current_green = RGBGetGValue(colour); - current_blue = RGBGetBValue(colour); - SendUpdate(); - } -} - -void ROGStrixLC_Controller::SetChannelLEDs(unsigned char /*channel*/, RGBColor* /*colors*/, unsigned int /*num_colors*/) -{ - /*---------------------------------------------------------*\ - | This interface is not used in this controller however is | - | required by the abstract class | - \*---------------------------------------------------------*/ -} - -void ROGStrixLC_Controller::SetLedsDirect(RGBColor * led_colours, uint8_t led_count) -{ - uint8_t buffer[write_packet_size] = { 0xEC, 0x40, 0x00, 0xFF, led_count }; - - /*---------------------------------------------------------*\ - | Set the colour bytes in the packet | - \*---------------------------------------------------------*/ - for(uint8_t index = 0; index < led_count; index++) - { - uint8_t offset = (index * 3) + ROGSTRIXLC_GREEN_BYTE; - - buffer[offset + 0] = RGBGetRValue(led_colours[index]); - buffer[offset + 1] = RGBGetGValue(led_colours[index]); - buffer[offset + 2] = RGBGetBValue(led_colours[index]); - } - - /*---------------------------------------------------------*\ - | These 3 bytes might be timing bytes | - \*---------------------------------------------------------*/ - uint8_t offset = led_count * 3 + ROGSTRIXLC_GREEN_BYTE; - buffer[offset + 0] = 0x77; - buffer[offset + 1] = 0x10; - buffer[offset + 2] = 0xF3; - - hid_write(dev, buffer, write_packet_size); -} - -void ROGStrixLC_Controller::GetStatus() -{ - uint8_t buffer[write_packet_size] = { 0xEC, 0x01, 0x02 }; - - hid_write(dev, buffer, write_packet_size); - hid_read_timeout(dev, buffer, read_packet_size, ROGSTRIXLC_CONTROLLER_TIMEOUT); - - current_red = buffer[ROGSTRIXLC_RED_BYTE - 1]; - current_green = buffer[ROGSTRIXLC_GREEN_BYTE - 1]; - current_blue = buffer[ROGSTRIXLC_BLUE_BYTE - 1]; -} - -void ROGStrixLC_Controller::SendUpdate() -{ - uint8_t buffer[write_packet_size]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(buffer, 0x00, write_packet_size); - - buffer[ROGSTRIXLC_REPORTID_BYTE] = rogstrixlc_reportid; - buffer[ROGSTRIXLC_COMMAND_BYTE] = rogstrixlc_modefx; - buffer[ROGSTRIXLC_ZONE_BYTE] = 0; - buffer[ROGSTRIXLC_MODE_BYTE] = current_mode; - buffer[ROGSTRIXLC_RED_BYTE] = current_red; - buffer[ROGSTRIXLC_GREEN_BYTE] = current_green; - buffer[ROGSTRIXLC_BLUE_BYTE] = current_blue; - - buffer[ROGSTRIXLC_DIRECTION_BYTE] = current_direction; - buffer[ROGSTRIXLC_SPEED_BYTE] = current_speed; - - hid_write(dev, buffer, write_packet_size); -} - diff --git a/Controllers/AsusAuraUSBController/ROGStrixLC_Controller.h b/Controllers/AsusAuraUSBController/ROGStrixLC_Controller.h deleted file mode 100644 index ed44add8..00000000 --- a/Controllers/AsusAuraUSBController/ROGStrixLC_Controller.h +++ /dev/null @@ -1,92 +0,0 @@ -/*-------------------------------------------------------------------*\ -| ROGStrixLC_Controller.h | -| | -| Driver for the ASUS Aura Liquid Cooler (LC) series | -| of lighting controllers | -| | -| Chris M (Dr_No) 17 Jan 2022 | -| | -\*-------------------------------------------------------------------*/ - -#include -#include -#include "RGBController.h" -#include "AsusAuraUSBController.h" - -#pragma once - -#define ROGSTRIXLC_CONTROLLER_TIMEOUT 250 -#define HID_MAX_STR 255 - -#define ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MIN 0 -#define ROGSTRIXLC_CONTROLLER_BRIGHTNESS_MAX 255 - -enum -{ - ROGSTRIXLC_CONTROLLER_MODE_DIRECT = 0xFF, //Direct Led Control - Independently set LEDs in zone - ROGSTRIXLC_CONTROLLER_MODE_STATIC = 0x01, //Static Mode - Set entire zone to a single color. - ROGSTRIXLC_CONTROLLER_MODE_BREATHING = 0x02, //Breathing Mode - Fades between fully off and fully on. - ROGSTRIXLC_CONTROLLER_MODE_FLASHING = 0x03, //Flashing Mode - Abruptly changing between fully off and fully on. - ROGSTRIXLC_CONTROLLER_MODE_SPECTRUM = 0x04, //Spectrum Cycle Mode - Cycles through the color spectrum on all lights on the device - ROGSTRIXLC_CONTROLLER_MODE_RAINBOW = 0x05, //Rainbow Wave Mode - Cycle thru the color spectrum as a wave across all LEDs - ROGSTRIXLC_CONTROLLER_MODE_FLASHANDDASH = 0x0A, //Flash n Dash - Flash twice and then flash in direction -}; - -enum AsusAuraStrixLC_PacketMap -{ - ROGSTRIXLC_REPORTID_BYTE = 0, - ROGSTRIXLC_COMMAND_BYTE = 1, - ROGSTRIXLC_ZONE_BYTE = 2, - ROGSTRIXLC_MODE_BYTE = 3, - ROGSTRIXLC_RED_BYTE = 4, - ROGSTRIXLC_GREEN_BYTE = 5, - ROGSTRIXLC_BLUE_BYTE = 6, - ROGSTRIXLC_DIRECTION_BYTE = 7, - ROGSTRIXLC_SPEED_BYTE = 8, -}; - -enum -{ - ROGSTRIXLC_CONTROLLER_SPEED_SLOWEST = 0x04, // Slowest speed - ROGSTRIXLC_CONTROLLER_SPEED_SLOW = 0x03, // Slower speed - ROGSTRIXLC_CONTROLLER_SPEED_NORMAL = 0x02, // Normal speed - ROGSTRIXLC_CONTROLLER_SPEED_FAST = 0x01, // Fast speed - ROGSTRIXLC_CONTROLLER_SPEED_FASTEST = 0x00, // Fastest speed -}; - -class ROGStrixLC_Controller : public AuraUSBController -{ -public: - ROGStrixLC_Controller(hid_device* dev_handle, const char* path); - ~ROGStrixLC_Controller(); - - std::string GetLocation(); - - void SetChannelLEDs(unsigned char channel, RGBColor *colors, unsigned int num_colors); - void SetLedsDirect(RGBColor * led_colours, uint8_t led_count); - - void SetMode(unsigned char channel, unsigned char mode, unsigned char red, unsigned char grn, unsigned char blu); - void SetMode(unsigned char mode, unsigned char speed, unsigned char direction, RGBColor colour); -private: - static const uint8_t read_packet_size = 64; - static const uint8_t write_packet_size = read_packet_size + 1; - static const uint8_t rogstrixlc_modefx = 0x3B; - static const uint8_t rogstrixlc_direct = 0x40; - static const uint8_t rogstrixlc_reportid = 0xEC; - - std::string location; - - uint8_t zone_index; - uint8_t current_mode; - uint8_t current_speed; - - uint8_t current_red; - uint8_t current_green; - uint8_t current_blue; - uint8_t current_direction; - - void GetStatus(); - void SendUpdate(); - void SendEffect(unsigned char channel, unsigned char mode, unsigned char red, unsigned char grn, unsigned char blu); - void SendDirectApply(unsigned char channel); -}; diff --git a/Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController.h b/Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController.h deleted file mode 100644 index f475add4..00000000 --- a/Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController.h +++ /dev/null @@ -1,51 +0,0 @@ -/*-----------------------------------------*\ -| AsusCerberusKeyboardController.h | -| | -| Definitions and types for ASUS Cerberus | -| USB RGB lighting controller | -| | -| Mola19 03/03/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include -#include - -#pragma once - -enum -{ - CERBERUS_KEYBOARD_MODE_STATIC = 0, - CERBERUS_KEYBOARD_MODE_BREATHING = 1, - CERBERUS_KEYBOARD_MODE_REACTIVE = 2, - CERBERUS_KEYBOARD_MODE_EXPLOSION = 3, - CERBERUS_KEYBOARD_MODE_COLOR_CYCLE = 4, - CERBERUS_KEYBOARD_MODE_WAVE = 6, - CERBERUS_KEYBOARD_MODE_CUSTOM = 7, -}; - - -class AsusCerberusKeyboardController -{ -public: - AsusCerberusKeyboardController(hid_device* dev_handle, const char* path, unsigned short rev_version); - ~AsusCerberusKeyboardController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - std::string GetVersion(); - - void SetProfile(uint8_t profile); - void SetPerLEDColor(uint8_t key, uint8_t red, uint8_t green, uint8_t blue); - void SendPerLEDColorEnd(); - void SetPerLEDMode(uint8_t mode); - void SetMode(uint8_t mode, uint8_t red, uint8_t green, uint8_t blue, uint8_t direction, uint8_t brightness); - - -private: - hid_device* dev; - std::string location; - unsigned short version; -}; diff --git a/Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController.cpp b/Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController/AsusCerberusKeyboardController.cpp similarity index 86% rename from Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController.cpp rename to Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController/AsusCerberusKeyboardController.cpp index 6c383696..9a12e37b 100644 --- a/Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController.cpp +++ b/Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController/AsusCerberusKeyboardController.cpp @@ -1,28 +1,31 @@ -/*-----------------------------------------*\ -| AsusCerberusKeyboardController.cpp | -| | -| Driver for ASUS Cerberus USB lighting | -| controller | -| | -| Mola19 05/28/2022 | -\*-----------------------------------------*/ - -#include "AsusCerberusKeyboardController.h" +/*---------------------------------------------------------*\ +| AsusCerberusKeyboardController.cpp | +| | +| Driver for ASUS Cerberus keyboard | +| | +| Mola19 28 May 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include -#include -#include #include #include +#include #include -#include +#include +#include "AsusCerberusKeyboardController.h" +#include "StringUtils.h" #define ASUS_CERBERUS_KB_PACKET_SIZE 8 -AsusCerberusKeyboardController::AsusCerberusKeyboardController(hid_device* dev_handle, const char* path, unsigned short rev_version) +AsusCerberusKeyboardController::AsusCerberusKeyboardController(hid_device* dev_handle, const char* path, unsigned short rev_version, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; version = rev_version; } @@ -36,6 +39,11 @@ std::string AsusCerberusKeyboardController::GetDeviceLocation() return("HID: " + location); } +std::string AsusCerberusKeyboardController::GetDeviceName() +{ + return(name); +} + std::string AsusCerberusKeyboardController::GetSerialString() { wchar_t serial_string[128]; @@ -46,10 +54,7 @@ std::string AsusCerberusKeyboardController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } std::string AsusCerberusKeyboardController::GetVersion() diff --git a/Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController/AsusCerberusKeyboardController.h b/Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController/AsusCerberusKeyboardController.h new file mode 100644 index 00000000..9e4a94f3 --- /dev/null +++ b/Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController/AsusCerberusKeyboardController.h @@ -0,0 +1,53 @@ +/*---------------------------------------------------------*\ +| AsusCerberusKeyboardController.h | +| | +| Driver for ASUS Cerberus keyboard | +| | +| Mola19 03 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" + +enum +{ + CERBERUS_KEYBOARD_MODE_STATIC = 0, + CERBERUS_KEYBOARD_MODE_BREATHING = 1, + CERBERUS_KEYBOARD_MODE_REACTIVE = 2, + CERBERUS_KEYBOARD_MODE_EXPLOSION = 3, + CERBERUS_KEYBOARD_MODE_COLOR_CYCLE = 4, + CERBERUS_KEYBOARD_MODE_WAVE = 6, + CERBERUS_KEYBOARD_MODE_CUSTOM = 7, +}; + +class AsusCerberusKeyboardController +{ +public: + AsusCerberusKeyboardController(hid_device* dev_handle, const char* path, unsigned short rev_version, std::string dev_name); + ~AsusCerberusKeyboardController(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + std::string GetSerialString(); + std::string GetVersion(); + + void SetProfile(uint8_t profile); + void SetPerLEDColor(uint8_t key, uint8_t red, uint8_t green, uint8_t blue); + void SendPerLEDColorEnd(); + void SetPerLEDMode(uint8_t mode); + void SetMode(uint8_t mode, uint8_t red, uint8_t green, uint8_t blue, uint8_t direction, uint8_t brightness); + + +private: + hid_device* dev; + std::string location; + std::string name; + unsigned short version; +}; diff --git a/Controllers/AsusLegacyUSBController/RGBController_AsusCerberusKeyboard.cpp b/Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController/RGBController_AsusCerberusKeyboard.cpp similarity index 92% rename from Controllers/AsusLegacyUSBController/RGBController_AsusCerberusKeyboard.cpp rename to Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController/RGBController_AsusCerberusKeyboard.cpp index 3ec44d04..2d64337c 100644 --- a/Controllers/AsusLegacyUSBController/RGBController_AsusCerberusKeyboard.cpp +++ b/Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController/RGBController_AsusCerberusKeyboard.cpp @@ -1,16 +1,18 @@ -/*-----------------------------------------*\ -| RGBController_AsusCerberusKeyboard.cpp | -| | -| Generic RGB Interface for Asus Cerberus | -| USB controller driver | -| | -| Mola19 05/28/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AsusCerberusKeyboard.cpp | +| | +| RGBController for ASUS Cerberus keyboard | +| | +| Mola19 28 May 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_AsusCerberusKeyboard.h" -#include #include +#include #include "RGBControllerKeyNames.h" +#include "RGBController_AsusCerberusKeyboard.h" /**------------------------------------------------------------------*\ @name Asus Cerberus Mech Keyboard @@ -23,12 +25,11 @@ @comment \*-------------------------------------------------------------------*/ - //0xFFFFFFFF indicates an unused entry in matrix #define NA 0xFFFFFFFF - -static unsigned int matrix_map[6][24] = { +static unsigned int matrix_map[6][24] = +{ { 0, NA, 9, 15, 20, 25, NA, 35, 40, 45, 50, 56, 62, 67, 72, NA, 75, 79, 84, NA, NA, NA, NA, NA }, { 1, 6, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, NA, NA, 76, 80, 85, NA, 88, 93, 97, 102 }, { 2, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, 69, NA, NA, 77, 81, 86, NA, 89, 94, 98, 103 }, @@ -175,7 +176,7 @@ static const std::vector led_names = RGBController_AsusCerberusKeyboard::RGBController_AsusCerberusKeyboard(AsusCerberusKeyboardController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; /*------------------------------------------------------------------------------------------------------*\ | this device has 6 different profiles, but there is no way to fetch them from the device, | @@ -184,13 +185,13 @@ RGBController_AsusCerberusKeyboard::RGBController_AsusCerberusKeyboard(AsusCerbe controller->SetProfile(1); - name = "ASUS Cerberus Keyboard"; - vendor = "ASUS"; - type = DEVICE_TYPE_KEYBOARD; - description = "ASUS Cerberus Keyboard Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - version = controller->GetVersion(); + name = controller->GetDeviceName(); + vendor = "ASUS"; + type = DEVICE_TYPE_KEYBOARD; + description = "ASUS Cerberus Keyboard Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + version = controller->GetVersion(); mode Custom; Custom.name = "Custom"; diff --git a/Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController/RGBController_AsusCerberusKeyboard.h b/Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController/RGBController_AsusCerberusKeyboard.h new file mode 100644 index 00000000..27f14425 --- /dev/null +++ b/Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController/RGBController_AsusCerberusKeyboard.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusCerberusKeyboard.h | +| | +| RGBController for ASUS Cerberus keyboard | +| | +| Mola19 03 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AsusCerberusKeyboardController.h" + +enum +{ + CERBERUS_MECH_BRIGHTNESS_MIN = 0, + CERBERUS_MECH_BRIGHTNESS_MAX = 4, + CERBERUS_MECH_BRIGHTNESS_DEFAULT = 4 +}; + +class RGBController_AsusCerberusKeyboard : public RGBController +{ +public: + RGBController_AsusCerberusKeyboard(AsusCerberusKeyboardController* controller_ptr); + ~RGBController_AsusCerberusKeyboard(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + AsusCerberusKeyboardController* controller; +}; diff --git a/Controllers/AsusLegacyUSBController/AsusLegacyUSBControllerDetect.cpp b/Controllers/AsusLegacyUSBController/AsusLegacyUSBControllerDetect.cpp index 17a36489..b3bbc421 100644 --- a/Controllers/AsusLegacyUSBController/AsusLegacyUSBControllerDetect.cpp +++ b/Controllers/AsusLegacyUSBController/AsusLegacyUSBControllerDetect.cpp @@ -1,16 +1,26 @@ +/*---------------------------------------------------------*\ +| AsusLegacyUSBControllerDetect.cpp | +| | +| Detector for ASUS legacy USB devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "AsusCerberusKeyboardController.h" +#include "AsusSagarisKeyboardController.h" #include "AsusStrixClawController.h" -#include "RGBController.h" #include "RGBController_AsusCerberusKeyboard.h" +#include "RGBController_AsusSagarisKeyboard.h" #include "RGBController_AsusStrixClaw.h" -#include -#include -#include "dependencies/dmiinfo.h" #define ASUS_LEGACY_USB_VID 0x195D +#define ASUS_USB_VID 0x0B05 #define ASUS_CERBERUS_MECH_PID 0x2047 +#define ASUS_SAGARIS_GK1100_PID 0x1835 #define ASUS_ROG_STRIX_CLAW_PID 0x1016 void DetectAsusCerberusMech(hid_device_info* info, const std::string& name) @@ -19,9 +29,22 @@ void DetectAsusCerberusMech(hid_device_info* info, const std::string& name) if(dev) { - AsusCerberusKeyboardController* controller = new AsusCerberusKeyboardController(dev, info->path, info->release_number); + AsusCerberusKeyboardController* controller = new AsusCerberusKeyboardController(dev, info->path, info->release_number, name); RGBController_AsusCerberusKeyboard* rgb_controller = new RGBController_AsusCerberusKeyboard(controller); - rgb_controller->name = name; + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectAsusSagarisKeyboard(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + AsusSagarisKeyboardController* controller = new AsusSagarisKeyboardController(dev, info->path, info->release_number, name); + RGBController_AsusSagarisKeyboard* rgb_controller = new RGBController_AsusSagarisKeyboard(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -32,13 +55,13 @@ void DetectAsusStrixClaw(hid_device_info* info, const std::string& name) if(dev) { - StrixClawController* controller = new StrixClawController(dev, info->path); + StrixClawController* controller = new StrixClawController(dev, info->path, name); RGBController_StrixClaw* rgb_controller = new RGBController_StrixClaw(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } -REGISTER_HID_DETECTOR_IPU("ASUS Cerberus Mech", DetectAsusCerberusMech, ASUS_LEGACY_USB_VID, ASUS_CERBERUS_MECH_PID, 1, 0xFF01, 1); - -REGISTER_HID_DETECTOR_IPU("ASUS ROG Strix Claw", DetectAsusStrixClaw, ASUS_LEGACY_USB_VID, ASUS_ROG_STRIX_CLAW_PID, 0, 0xFF01, 1); \ No newline at end of file +REGISTER_HID_DETECTOR_IPU("ASUS Cerberus Mech", DetectAsusCerberusMech, ASUS_LEGACY_USB_VID, ASUS_CERBERUS_MECH_PID, 1, 0xFF01, 1); +REGISTER_HID_DETECTOR_IPU("ASUS Sagaris GK1100", DetectAsusSagarisKeyboard, ASUS_USB_VID, ASUS_SAGARIS_GK1100_PID, 1, 0xFF02, 2); +REGISTER_HID_DETECTOR_IPU("ASUS ROG Strix Claw", DetectAsusStrixClaw, ASUS_LEGACY_USB_VID, ASUS_ROG_STRIX_CLAW_PID, 0, 0xFF01, 1); diff --git a/Controllers/AsusLegacyUSBController/AsusSagarisKeyboardController/AsusSagarisKeyboardController.cpp b/Controllers/AsusLegacyUSBController/AsusSagarisKeyboardController/AsusSagarisKeyboardController.cpp new file mode 100644 index 00000000..dcdf7aa6 --- /dev/null +++ b/Controllers/AsusLegacyUSBController/AsusSagarisKeyboardController/AsusSagarisKeyboardController.cpp @@ -0,0 +1,201 @@ +/*---------------------------------------------------------*\ +| AsusSagarisKeyboardController.cpp | +| | +| Driver for ASUS Sagaris keyboard | +| | +| Mola19 20 Aug 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include "AsusSagarisKeyboardController.h" +#include "LogManager.h" +#include "StringUtils.h" + +#define ASUS_SAGARIS_KB_PACKET_SIZE 65 + +AsusSagarisKeyboardController::AsusSagarisKeyboardController(hid_device* dev_handle, const char* path, unsigned short rev_version, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + version = rev_version; +} + +AsusSagarisKeyboardController::~AsusSagarisKeyboardController() +{ + hid_close(dev); +} + +std::string AsusSagarisKeyboardController::GetVersion() +{ + return std::to_string((int) floor(version / 0x100)) + "." + std::to_string(version % 0x100); +} + +std::string AsusSagarisKeyboardController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string AsusSagarisKeyboardController::GetDeviceName() +{ + return(name); +} + +std::string AsusSagarisKeyboardController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +sagaris_mode AsusSagarisKeyboardController::GetMode() +{ + ClearResponses(); + + uint8_t usb_buf_out[ASUS_SAGARIS_KB_PACKET_SIZE]; + memset(usb_buf_out, 0x00, sizeof(usb_buf_out)); + + usb_buf_out[0x00] = 0x06; + usb_buf_out[0x01] = 0x0B; + usb_buf_out[0x02] = 0x03; + + hid_write(dev, usb_buf_out, ASUS_SAGARIS_KB_PACKET_SIZE); + + unsigned char usb_buf_in[ASUS_SAGARIS_KB_PACKET_SIZE]; + memset(usb_buf_in, 0x00, sizeof(usb_buf_in)); + int return_length = hid_read_timeout(dev, usb_buf_in, ASUS_SAGARIS_KB_PACKET_SIZE, 100); + + if(return_length == -1) + { + LOG_DEBUG("[Asus Sagaris GK1100]: Could not fetch mode"); + sagaris_mode default_mode; + default_mode.mode = SAGARIS_KEYBOARD_MODE_STATIC; + default_mode.brightness = SAGARIS_KEYBOARD_BRIGHTNESS_DEFAULT; + default_mode.speed = 0; + default_mode.colorIndex = 0; + + return default_mode; + } + + sagaris_mode current_mode; + current_mode.mode = usb_buf_in[3]; + current_mode.brightness = usb_buf_in[4]; + current_mode.speed = usb_buf_in[5]; + current_mode.colorIndex = usb_buf_in[6]; + + return current_mode; +} + +std::vector AsusSagarisKeyboardController::GetColors() +{ + ClearResponses(); + + uint8_t usb_buf_out[ASUS_SAGARIS_KB_PACKET_SIZE]; + memset(usb_buf_out, 0x00, sizeof(usb_buf_out)); + + usb_buf_out[0x00] = 0x06; + usb_buf_out[0x01] = 0x0B; + usb_buf_out[0x02] = 0x05; + + hid_write(dev, usb_buf_out, ASUS_SAGARIS_KB_PACKET_SIZE); + + std::vector colors; + colors.resize(7); + + for(int i = 0; i < 7; i++) + { + unsigned char usb_buf_in[ASUS_SAGARIS_KB_PACKET_SIZE]; + memset(usb_buf_in, 0x00, sizeof(usb_buf_in)); + int return_length = hid_read_timeout(dev, usb_buf_in, ASUS_SAGARIS_KB_PACKET_SIZE, 100); + + if(return_length == -1) + { + LOG_DEBUG("[Asus Sagaris GK1100]: Could not fetch color %i", i); + colors[i] = ToRGBColor(0, 0, 0); + continue; + } + + colors[i] = ToRGBColor(usb_buf_in[4] * 16, usb_buf_in[5] * 16, usb_buf_in[6] * 16); + } + + return colors; +} + +void AsusSagarisKeyboardController::SetColor + ( + uint8_t index, + uint8_t red, + uint8_t green, + uint8_t blue + ) +{ + uint8_t usb_buf[ASUS_SAGARIS_KB_PACKET_SIZE]; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x06; + usb_buf[0x01] = 0x0B; + usb_buf[0x02] = 0x04; + usb_buf[0x03] = 0x00; + usb_buf[0x04] = index; + usb_buf[0x05] = red; + usb_buf[0x06] = green; + usb_buf[0x07] = blue; + + hid_write(dev, usb_buf, ASUS_SAGARIS_KB_PACKET_SIZE); +} + +void AsusSagarisKeyboardController::SetMode + ( + uint8_t mode, + uint8_t brightness, + uint8_t speed, + uint8_t colorIndex + ) +{ + ClearResponses(); + + uint8_t usb_buf[ASUS_SAGARIS_KB_PACKET_SIZE]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x06; + usb_buf[0x01] = 0x0B; + usb_buf[0x02] = 0x01; + usb_buf[0x03] = mode; + usb_buf[0x04] = brightness; + usb_buf[0x05] = speed; + usb_buf[0x06] = colorIndex; + + hid_write(dev, usb_buf, ASUS_SAGARIS_KB_PACKET_SIZE); + + AwaitResponse(20); +} + +void AsusSagarisKeyboardController::AwaitResponse(int ms) +{ + unsigned char usb_buf[ASUS_SAGARIS_KB_PACKET_SIZE]; + hid_read_timeout(dev, usb_buf, ASUS_SAGARIS_KB_PACKET_SIZE, ms); +} + +void AsusSagarisKeyboardController::ClearResponses() +{ + int result = 1; + unsigned char usb_buf_flush[65]; + while(result > 0) + { + result = hid_read_timeout(dev, usb_buf_flush, 65, 0); + } +} diff --git a/Controllers/AsusLegacyUSBController/AsusSagarisKeyboardController/AsusSagarisKeyboardController.h b/Controllers/AsusLegacyUSBController/AsusSagarisKeyboardController/AsusSagarisKeyboardController.h new file mode 100644 index 00000000..2698bee3 --- /dev/null +++ b/Controllers/AsusLegacyUSBController/AsusSagarisKeyboardController/AsusSagarisKeyboardController.h @@ -0,0 +1,79 @@ +/*---------------------------------------------------------*\ +| AsusSagarisKeyboardController.h | +| | +| Driver for ASUS Sagaris keyboard | +| | +| Mola19 20 Aug 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" + +enum +{ + SAGARIS_KEYBOARD_MODE_OFF = 0, + SAGARIS_KEYBOARD_MODE_STATIC = 1, + SAGARIS_KEYBOARD_MODE_SPRIAL = 2, + SAGARIS_KEYBOARD_MODE_CUSTOM = 3, + SAGARIS_KEYBOARD_MODE_BREATHING = 4, + SAGARIS_KEYBOARD_MODE_REACTIVE = 5, + SAGARIS_KEYBOARD_MODE_STARRY_NIGHT = 6, + SAGARIS_KEYBOARD_MODE_LASER = 7, +}; + +enum +{ + SAGARIS_KEYBOARD_BRIGHTNESS_MIN = 0, + SAGARIS_KEYBOARD_BRIGHTNESS_MAX = 3, + SAGARIS_KEYBOARD_BRIGHTNESS_DEFAULT = 3 +}; + +enum +{ + SAGARIS_KEYBOARD_SPEED_MIN = 0, + SAGARIS_KEYBOARD_SPEED_MAX = 3, + SAGARIS_KEYBOARD_SPEED_DEFAULT = 2 +}; + +typedef struct +{ + uint8_t mode; + uint8_t brightness; + uint8_t speed; + uint8_t colorIndex; +} sagaris_mode; + + +class AsusSagarisKeyboardController +{ +public: + AsusSagarisKeyboardController(hid_device* dev_handle, const char* path, unsigned short rev_version, std::string dev_name); + ~AsusSagarisKeyboardController(); + + std::string GetVersion(); + std::string GetDeviceLocation(); + std::string GetDeviceName(); + std::string GetSerialString(); + + sagaris_mode GetMode(); + std::vector GetColors(); + + void SetMode(uint8_t mode, uint8_t brightness, uint8_t speed, uint8_t colorIndex); + void SetColor(uint8_t index, uint8_t red, uint8_t green, uint8_t blue); + + void AwaitResponse(int ms); + void ClearResponses(); + +private: + hid_device* dev; + std::string location; + std::string name; + unsigned short version; +}; diff --git a/Controllers/AsusLegacyUSBController/AsusSagarisKeyboardController/RGBController_AsusSagarisKeyboard.cpp b/Controllers/AsusLegacyUSBController/AsusSagarisKeyboardController/RGBController_AsusSagarisKeyboard.cpp new file mode 100644 index 00000000..ca0372d8 --- /dev/null +++ b/Controllers/AsusLegacyUSBController/AsusSagarisKeyboardController/RGBController_AsusSagarisKeyboard.cpp @@ -0,0 +1,250 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusSagarisKeyboard.cpp | +| | +| RGBController for ASUS Sagaris keyboard | +| | +| Mola19 20 Aug 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "RGBController_AsusSagarisKeyboard.h" + +/**------------------------------------------------------------------*\ + @name Asus Sagaris Keyboard + @category Keyboard + @type USB + @save :robot: + @direct :x: + @effects :white_check_mark: + @detectors DetectAsusSagarisKeyboard + @comment Missing controls for modifier keys, as they have independent lighting +\*-------------------------------------------------------------------*/ + +RGBController_AsusSagarisKeyboard::RGBController_AsusSagarisKeyboard(AsusSagarisKeyboardController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "ASUS"; + type = DEVICE_TYPE_KEYBOARD; + description = "ASUS Sagaris Keyboard Device"; + version = controller->GetVersion(); + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Off; + Off.name = "Off"; + Off.value = SAGARIS_KEYBOARD_MODE_OFF; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Static; + Static.name = "Static"; + Static.value = SAGARIS_KEYBOARD_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Static.brightness_min = SAGARIS_KEYBOARD_BRIGHTNESS_MIN; + Static.brightness_max = SAGARIS_KEYBOARD_BRIGHTNESS_MAX; + Static.brightness = SAGARIS_KEYBOARD_BRIGHTNESS_DEFAULT; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.resize(1); + modes.push_back(Static); + + mode Spiral; + Spiral.name = "Spiral"; + Spiral.value = SAGARIS_KEYBOARD_MODE_SPRIAL; + Spiral.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Spiral.brightness_min = SAGARIS_KEYBOARD_BRIGHTNESS_MIN; + Spiral.brightness_max = SAGARIS_KEYBOARD_BRIGHTNESS_MAX; + Spiral.brightness = SAGARIS_KEYBOARD_BRIGHTNESS_DEFAULT; + Spiral.speed_min = SAGARIS_KEYBOARD_SPEED_MIN; + Spiral.speed_max = SAGARIS_KEYBOARD_SPEED_MAX; + Spiral.speed = SAGARIS_KEYBOARD_SPEED_DEFAULT; + Spiral.color_mode = MODE_COLORS_MODE_SPECIFIC; + Spiral.colors_min = 7; + Spiral.colors_max = 7; + Spiral.colors.resize(7); + modes.push_back(Spiral); + + mode Custom; + Custom.name = "Custom"; + Custom.value = SAGARIS_KEYBOARD_MODE_CUSTOM; + Custom.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Custom.brightness_min = SAGARIS_KEYBOARD_BRIGHTNESS_MIN; + Custom.brightness_max = SAGARIS_KEYBOARD_BRIGHTNESS_MAX; + Custom.brightness = SAGARIS_KEYBOARD_BRIGHTNESS_DEFAULT; + Custom.color_mode = MODE_COLORS_MODE_SPECIFIC; + Custom.colors_min = 7; + Custom.colors_max = 7; + Custom.colors.resize(7); + modes.push_back(Custom); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = SAGARIS_KEYBOARD_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED; + Breathing.speed_min = SAGARIS_KEYBOARD_BRIGHTNESS_MIN; + Breathing.speed_max = SAGARIS_KEYBOARD_BRIGHTNESS_MAX; + Breathing.speed = SAGARIS_KEYBOARD_BRIGHTNESS_DEFAULT; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.colors_min = 7; + Breathing.colors_max = 7; + Breathing.colors.resize(7); + modes.push_back(Breathing); + + mode Reactive; + Reactive.name = "Reactive"; + Reactive.value = SAGARIS_KEYBOARD_MODE_REACTIVE; + Reactive.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Reactive.brightness_min = SAGARIS_KEYBOARD_BRIGHTNESS_MIN; + Reactive.brightness_max = SAGARIS_KEYBOARD_BRIGHTNESS_MAX; + Reactive.brightness = SAGARIS_KEYBOARD_BRIGHTNESS_DEFAULT; + Reactive.speed_min = SAGARIS_KEYBOARD_SPEED_MIN; + Reactive.speed_max = SAGARIS_KEYBOARD_SPEED_MAX; + Reactive.speed = SAGARIS_KEYBOARD_SPEED_DEFAULT; + Reactive.color_mode = MODE_COLORS_MODE_SPECIFIC; + Reactive.colors_min = 1; + Reactive.colors_max = 1; + Reactive.colors.resize(1); + modes.push_back(Reactive); + + mode Starry_Night; + Starry_Night.name = "Starry Night"; + Starry_Night.value = SAGARIS_KEYBOARD_MODE_STARRY_NIGHT; + Starry_Night.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Starry_Night.brightness_min = SAGARIS_KEYBOARD_SPEED_MIN; + Starry_Night.brightness_max = SAGARIS_KEYBOARD_SPEED_MAX; + Starry_Night.brightness = SAGARIS_KEYBOARD_SPEED_DEFAULT; + Starry_Night.speed_min = SAGARIS_KEYBOARD_BRIGHTNESS_MIN; + Starry_Night.speed_max = SAGARIS_KEYBOARD_BRIGHTNESS_MAX; + Starry_Night.speed = SAGARIS_KEYBOARD_BRIGHTNESS_DEFAULT; + Starry_Night.color_mode = MODE_COLORS_MODE_SPECIFIC; + Starry_Night.colors_min = 7; + Starry_Night.colors_max = 7; + Starry_Night.colors.resize(7); + modes.push_back(Starry_Night); + + mode Laser; + Laser.name = "Laser"; + Laser.value = SAGARIS_KEYBOARD_MODE_LASER; + Laser.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Laser.brightness_min = SAGARIS_KEYBOARD_SPEED_MIN; + Laser.brightness_max = SAGARIS_KEYBOARD_SPEED_MAX; + Laser.brightness = SAGARIS_KEYBOARD_SPEED_DEFAULT; + Laser.speed_min = SAGARIS_KEYBOARD_BRIGHTNESS_MIN; + Laser.speed_max = SAGARIS_KEYBOARD_BRIGHTNESS_MAX; + Laser.speed = SAGARIS_KEYBOARD_BRIGHTNESS_DEFAULT; + Laser.color_mode = MODE_COLORS_MODE_SPECIFIC; + Laser.colors_min = 7; + Laser.colors_max = 7; + Laser.colors.resize(7); + modes.push_back(Laser); + + SetupZones(); + + sagaris_mode current_mode = controller->GetMode(); + + active_mode = current_mode.mode; + last_mode = current_mode.mode; + modes[active_mode].brightness = current_mode.brightness; + modes[active_mode].speed = current_mode.speed; + + current_colors = controller->GetColors(); + + for(unsigned int i = 0; i < modes[active_mode].colors.size(); i++) + { + modes[active_mode].colors[i] = current_colors[i]; + } +} + +RGBController_AsusSagarisKeyboard::~RGBController_AsusSagarisKeyboard() +{ + delete controller; +} + +void RGBController_AsusSagarisKeyboard::SetupZones() +{ + zone keyboard; + keyboard.name = "Keyboard"; + keyboard.type = ZONE_TYPE_SINGLE; + keyboard.leds_min = 1; + keyboard.leds_max = 1; + keyboard.leds_count = 1; + keyboard.matrix_map = nullptr; + + SetupColors(); +} + +void RGBController_AsusSagarisKeyboard::ResizeZone(int /*zone*/, int /*new_size*/) +{ + +} + +void RGBController_AsusSagarisKeyboard::DeviceUpdateLEDs() +{ + +} + +void RGBController_AsusSagarisKeyboard::UpdateZoneLEDs(int /*zone*/) +{ + +} + +void RGBController_AsusSagarisKeyboard::UpdateSingleLED(int /*led*/) +{ + +} + +void RGBController_AsusSagarisKeyboard::DeviceUpdateMode() +{ + if(last_mode != active_mode) + { + last_mode = active_mode; + for(unsigned int i = 0; i < modes[active_mode].colors.size(); i++) + { + modes[active_mode].colors[i] = current_colors[i]; + } + } + else + { + for(unsigned int i = 0; i < modes[active_mode].colors.size(); i++) + { + current_colors[i] = modes[active_mode].colors[i]; + } + + for(unsigned int i = 0; i < modes[active_mode].colors.size(); i++) + { + /*-----------------------------------------*\ + | This device uses 4bit colorValues (0-16) | + \*-----------------------------------------*/ + uint8_t red = RGBGetRValue(modes[active_mode].colors[i]) / 16; + uint8_t green = RGBGetGValue(modes[active_mode].colors[i]) / 16; + uint8_t blue = RGBGetBValue(modes[active_mode].colors[i]) / 16; + + controller->SetColor(i, red, green, blue); + } + } + + /*------------------------------------------------------------------------------------------------------*\ + | This device uses a global color storage for 7 colors, | + | each time a mode is selected, it is specified which color is chosen (some use all). | + | As OpenRGB doesn't support selecting the color index, color 1 is used for single color modes. | + \*------------------------------------------------------------------------------------------------------*/ + + uint8_t colorIndex = 0; + + uint8_t mode = modes[active_mode].value; + + if(mode == SAGARIS_KEYBOARD_MODE_STARRY_NIGHT) + { + colorIndex = 7; + } + + controller->SetMode(mode, modes[active_mode].brightness, modes[active_mode].speed, colorIndex); +} diff --git a/Controllers/AsusLegacyUSBController/AsusSagarisKeyboardController/RGBController_AsusSagarisKeyboard.h b/Controllers/AsusLegacyUSBController/AsusSagarisKeyboardController/RGBController_AsusSagarisKeyboard.h new file mode 100644 index 00000000..905d1d34 --- /dev/null +++ b/Controllers/AsusLegacyUSBController/AsusSagarisKeyboardController/RGBController_AsusSagarisKeyboard.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusSagarisKeyboard.h | +| | +| RGBController for ASUS Sagaris keyboard | +| | +| Mola19 20 Aug 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AsusSagarisKeyboardController.h" + +class RGBController_AsusSagarisKeyboard : public RGBController +{ +public: + RGBController_AsusSagarisKeyboard(AsusSagarisKeyboardController* controller_ptr); + ~RGBController_AsusSagarisKeyboard(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + AsusSagarisKeyboardController* controller; + std::vector current_colors; + uint8_t last_mode; +}; diff --git a/Controllers/AsusLegacyUSBController/AsusStrixClawController.cpp b/Controllers/AsusLegacyUSBController/AsusStrixClawController.cpp deleted file mode 100644 index 830c8876..00000000 --- a/Controllers/AsusLegacyUSBController/AsusStrixClawController.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/*-----------------------------------------*\ -| AsusStrixClawController.cpp | -| | -| Driver for ASUS Strix USB | -| lighting controller | -| | -| Mola19 08/06/2022 | -\*-----------------------------------------*/ - -#include "AsusStrixClawController.h" - -#include -#include - -StrixClawController::StrixClawController(hid_device* dev_handle, const char* path) -{ - dev = dev_handle; - location = path; -} - -StrixClawController::~StrixClawController() -{ - hid_close(dev); -} - -std::string StrixClawController::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string StrixClawController::GetSerialString() -{ - wchar_t serial_string[HID_MAX_STR]; - int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); - - if(ret != 0) - { - return(""); - } - - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); -} - -std::string StrixClawController::GetVersion() -{ - - // asking the device to prepare version information - unsigned char usb_buf_out[9]; - - memset(usb_buf_out, 0x00, 9); - - usb_buf_out[0x00] = 0x07; - usb_buf_out[0x01] = 0x80; - - hid_send_feature_report(dev, usb_buf_out, 9); - - // retrieving the version information - unsigned char usb_buf_in[9]; - - memset(usb_buf_in, 0x00, 9); - - usb_buf_in[0x00] = 0x07; - - hid_get_feature_report(dev, usb_buf_in, 9); - - return (std::to_string(usb_buf_in[1]) + std::to_string(usb_buf_in[2])); -} - -void StrixClawController::SetScrollWheelLED(bool OnOff) -{ - unsigned char usb_buf[9]; - - memset(usb_buf, 0x00, 9); - - usb_buf[0x00] = 0x07; - usb_buf[0x01] = 0x07; - usb_buf[0x02] = 0x01; - usb_buf[0x03] = OnOff; - hid_send_feature_report(dev, usb_buf, 9); -} - -void StrixClawController::SetLogoLED(uint8_t brightness) -{ - unsigned char usb_buf[9]; - - memset(usb_buf, 0x00, 9); - - usb_buf[0x00] = 0x07; - usb_buf[0x01] = 0x0a; - usb_buf[0x02] = 0x01; - usb_buf[0x03] = 0x00; - usb_buf[0x04] = brightness; - hid_send_feature_report(dev, usb_buf, 9); -} diff --git a/Controllers/AsusLegacyUSBController/AsusStrixClawController.h b/Controllers/AsusLegacyUSBController/AsusStrixClawController.h deleted file mode 100644 index e56f55db..00000000 --- a/Controllers/AsusLegacyUSBController/AsusStrixClawController.h +++ /dev/null @@ -1,35 +0,0 @@ -/*-----------------------------------------*\ -| AsusStrixClawController.h | -| | -| Definitions and types for ASUS | -| Legacy USB RGB lighting controller | -| | -| Mola19 08/06/2022 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include - -#pragma once - -#define HID_MAX_STR 255 - -class StrixClawController -{ -public: - StrixClawController(hid_device* dev_handle, const char* path); - virtual ~StrixClawController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - std::string GetVersion(); - - void SetScrollWheelLED(bool OnOff); - void SetLogoLED(uint8_t brightness); - -private: - hid_device* dev; - std::string location; -}; diff --git a/Controllers/AsusLegacyUSBController/AsusStrixClawController/AsusStrixClawController.cpp b/Controllers/AsusLegacyUSBController/AsusStrixClawController/AsusStrixClawController.cpp new file mode 100644 index 00000000..026242ff --- /dev/null +++ b/Controllers/AsusLegacyUSBController/AsusStrixClawController/AsusStrixClawController.cpp @@ -0,0 +1,102 @@ +/*---------------------------------------------------------*\ +| AsusStrixClawController.cpp | +| | +| Driver for ASUS Strix Claw mouse | +| | +| Mola19 06 Aug 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "AsusStrixClawController.h" +#include "StringUtils.h" + +StrixClawController::StrixClawController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; +} + +StrixClawController::~StrixClawController() +{ + hid_close(dev); +} + +std::string StrixClawController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string StrixClawController::GetDeviceName() +{ + return(name); +} + +std::string StrixClawController::GetSerialString() +{ + wchar_t serial_string[HID_MAX_STR]; + int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string StrixClawController::GetVersion() +{ + + // asking the device to prepare version information + unsigned char usb_buf_out[9]; + + memset(usb_buf_out, 0x00, 9); + + usb_buf_out[0x00] = 0x07; + usb_buf_out[0x01] = 0x80; + + hid_send_feature_report(dev, usb_buf_out, 9); + + // retrieving the version information + unsigned char usb_buf_in[9]; + + memset(usb_buf_in, 0x00, 9); + + usb_buf_in[0x00] = 0x07; + + hid_get_feature_report(dev, usb_buf_in, 9); + + return (std::to_string(usb_buf_in[1]) + std::to_string(usb_buf_in[2])); +} + +void StrixClawController::SetScrollWheelLED(bool OnOff) +{ + unsigned char usb_buf[9]; + + memset(usb_buf, 0x00, 9); + + usb_buf[0x00] = 0x07; + usb_buf[0x01] = 0x07; + usb_buf[0x02] = 0x01; + usb_buf[0x03] = OnOff; + hid_send_feature_report(dev, usb_buf, 9); +} + +void StrixClawController::SetLogoLED(uint8_t brightness) +{ + unsigned char usb_buf[9]; + + memset(usb_buf, 0x00, 9); + + usb_buf[0x00] = 0x07; + usb_buf[0x01] = 0x0a; + usb_buf[0x02] = 0x01; + usb_buf[0x03] = 0x00; + usb_buf[0x04] = brightness; + hid_send_feature_report(dev, usb_buf, 9); +} diff --git a/Controllers/AsusLegacyUSBController/AsusStrixClawController/AsusStrixClawController.h b/Controllers/AsusLegacyUSBController/AsusStrixClawController/AsusStrixClawController.h new file mode 100644 index 00000000..c1373da2 --- /dev/null +++ b/Controllers/AsusLegacyUSBController/AsusStrixClawController/AsusStrixClawController.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------*\ +| AsusStrixClawController.h | +| | +| Driver for ASUS Strix Claw mouse | +| | +| Mola19 06 Aug 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define HID_MAX_STR 255 + +class StrixClawController +{ +public: + StrixClawController(hid_device* dev_handle, const char* path, std::string dev_name); + virtual ~StrixClawController(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + std::string GetSerialString(); + std::string GetVersion(); + + void SetScrollWheelLED(bool OnOff); + void SetLogoLED(uint8_t brightness); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/AsusLegacyUSBController/RGBController_AsusStrixClaw.cpp b/Controllers/AsusLegacyUSBController/AsusStrixClawController/RGBController_AsusStrixClaw.cpp similarity index 80% rename from Controllers/AsusLegacyUSBController/RGBController_AsusStrixClaw.cpp rename to Controllers/AsusLegacyUSBController/AsusStrixClawController/RGBController_AsusStrixClaw.cpp index 54b31a87..30e505c6 100644 --- a/Controllers/AsusLegacyUSBController/RGBController_AsusStrixClaw.cpp +++ b/Controllers/AsusLegacyUSBController/AsusStrixClawController/RGBController_AsusStrixClaw.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_AsusStrixClaw.cpp | -| | -| Generic RGB Interface for Asus | -| Legacy USB controller driver | -| | -| Mola19 08/06/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AsusStrixClaw.cpp | +| | +| RGBController for ASUS Strix Claw mouse | +| | +| Mola19 06 Aug 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_AsusStrixClaw.h" @@ -24,7 +26,7 @@ RGBController_StrixClaw::RGBController_StrixClaw(StrixClawController* controller { controller = controller_ptr; - name = "ASUS ROG Strix Claw"; + name = controller->GetDeviceName(); vendor = "ASUS"; type = DEVICE_TYPE_MOUSE; description = "ASUS Legacy Mouse Device"; @@ -102,17 +104,17 @@ void RGBController_StrixClaw::ResizeZone(int /*zone*/, int /*new_size*/) void RGBController_StrixClaw::DeviceUpdateLEDs() { - + } void RGBController_StrixClaw::UpdateZoneLEDs(int /*zone*/) { - + } void RGBController_StrixClaw::UpdateSingleLED(int /*led*/) { - + } void RGBController_StrixClaw::DeviceUpdateMode() diff --git a/Controllers/AsusLegacyUSBController/AsusStrixClawController/RGBController_AsusStrixClaw.h b/Controllers/AsusLegacyUSBController/AsusStrixClawController/RGBController_AsusStrixClaw.h new file mode 100644 index 00000000..9dd939c7 --- /dev/null +++ b/Controllers/AsusLegacyUSBController/AsusStrixClawController/RGBController_AsusStrixClaw.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusStrixClaw.h | +| | +| RGBController for ASUS Strix Claw mouse | +| | +| Mola19 06 Aug 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AsusStrixClawController.h" + +class RGBController_StrixClaw : public RGBController +{ +public: + RGBController_StrixClaw(StrixClawController* controller_ptr); + ~RGBController_StrixClaw(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + StrixClawController* controller; +}; diff --git a/Controllers/AsusLegacyUSBController/RGBController_AsusCerberusKeyboard.h b/Controllers/AsusLegacyUSBController/RGBController_AsusCerberusKeyboard.h deleted file mode 100644 index a633348f..00000000 --- a/Controllers/AsusLegacyUSBController/RGBController_AsusCerberusKeyboard.h +++ /dev/null @@ -1,39 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusCerberusKeyboard.h | -| | -| Generic RGB Interface for Asus Cerberus | -| USB controller driver | -| | -| Mola19 03/03/2021 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "AsusCerberusKeyboardController.h" - -enum -{ - CERBERUS_MECH_BRIGHTNESS_MIN = 0, - CERBERUS_MECH_BRIGHTNESS_MAX = 4, - CERBERUS_MECH_BRIGHTNESS_DEFAULT = 4 -}; - -class RGBController_AsusCerberusKeyboard : public RGBController -{ -public: - RGBController_AsusCerberusKeyboard(AsusCerberusKeyboardController* controller_ptr); - ~RGBController_AsusCerberusKeyboard(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - AsusCerberusKeyboardController* controller; -}; diff --git a/Controllers/AsusLegacyUSBController/RGBController_AsusStrixClaw.h b/Controllers/AsusLegacyUSBController/RGBController_AsusStrixClaw.h deleted file mode 100644 index 1da0f858..00000000 --- a/Controllers/AsusLegacyUSBController/RGBController_AsusStrixClaw.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_AsusStrixClaw.h | -| | -| Generic RGB Interface for Asus | -| Legacy USB controller driver | -| | -| Mola19 08/06/2022 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "AsusStrixClawController.h" - - -class RGBController_StrixClaw : public RGBController -{ -public: - RGBController_StrixClaw(StrixClawController* controller_ptr); - ~RGBController_StrixClaw(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - StrixClawController* controller; -}; diff --git a/Controllers/AsusTUFLaptopController/AsusTUFLaptopController.cpp b/Controllers/AsusTUFLaptopController/AsusTUFLaptopController.cpp deleted file mode 100644 index b248913d..00000000 --- a/Controllers/AsusTUFLaptopController/AsusTUFLaptopController.cpp +++ /dev/null @@ -1,330 +0,0 @@ -#ifdef _WIN32 - -#include "AsusTUFLaptopController.h" - -#include -#include -#include -#include - -#include -#include -#include - -static bool coInitialized = 0; - -static GUID CLSID_GUID_DEVCLASS_SYSTEM = { 0x4D36E97D, 0xE325, 0x11CE, {0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } }; - -int AsusTUFLaptopController::checkWMIType() -{ - int n; - int v6; - int result = 0; - struct _SP_DEVINFO_DATA DeviceInfoData; - const int bufsize = 260; - wchar_t PropertyBuffer[bufsize]; - - HDEVINFO devinfo = SetupDiGetClassDevsW(&CLSID_GUID_DEVCLASS_SYSTEM, 0, 0, 2u); - if ( devinfo == HDEVINFO(-1) ) - { - return 0; - } - n = 0; - DeviceInfoData.cbSize = sizeof(DeviceInfoData); - - while ( SetupDiEnumDeviceInfo(devinfo, n, &DeviceInfoData) ) // Invalid buffer - { - if ( SetupDiGetDeviceRegistryPropertyW(devinfo, - &DeviceInfoData, - SPDRP_ENUMERATOR_NAME, - NULL, - PBYTE(PropertyBuffer), - sizeof(PropertyBuffer), - 0) ) - { - // If we found property "ACPI" - if(!wcscmp(PropertyBuffer, L"ACPI")) - { - memset(PropertyBuffer, 0, sizeof(PropertyBuffer)); - if ( SetupDiGetDeviceInstanceIdW(devinfo, &DeviceInfoData, PropertyBuffer, bufsize, 0) ) - { - _wcsupr_s(PropertyBuffer, bufsize); - if(wcsstr(PropertyBuffer, L"ACPI\\ATK0100")) - { - result = 1; - break; - } - if(!wcscmp(PropertyBuffer, L"ACPI\\PNP0C14\\ATK")) - { - result = 2; - break; - } - } - } - } - ++n; - } - SetupDiDestroyDeviceInfoList(devinfo); - return result; -} - -AsusTUFLaptopController::AsusTUFLaptopController() -{ - hDevice = CreateFileW(L"\\\\.\\ATKACPI", 0xC0000000, 3u, 0, 3u, 0, 0); -} - -AsusTUFLaptopController* AsusTUFLaptopController::checkAndCreate() -{ - // This might cause issues when coInitialize() is used in multiple places - HRESULT init = CoInitializeEx(0, COINIT_APARTMENTTHREADED); - if ( init < 0 && init != 0x80010106 ) - return 0; - coInitialized = 1; - - int type = checkWMIType(); - if ( type == 2 ) - { - AsusTUFLaptopController* controller = new AsusTUFLaptopController(); - if(controller->hDevice != HANDLE(-1)) - { - return controller; - } - delete controller; - } - return nullptr; -} - -AsusTUFLaptopController::~AsusTUFLaptopController() -{ - if ( hDevice && hDevice != HANDLE(-1) ) - { - CloseHandle(hDevice); - hDevice = 0; - } - // This might cause issues when coInitialize() is used in multiple places - if ( coInitialized ) - { - CoUninitialize(); - coInitialized = 0; - } - -} - -bool AsusTUFLaptopController::deviceIoControlWrapper(const void *dataIn, int commandIndex, int dataSizeIn, void *dataOut, int *dataSizeOut) -{ - size_t BytesReturned; - const int bufsize = 1024; - char outBuffer[bufsize]; - - LPDWORD inBuffer = LPDWORD(malloc(dataSizeIn + 8)); - inBuffer[0] = commandIndex; - inBuffer[1] = dataSizeIn; - memmove(inBuffer + 2, dataIn, dataSizeIn); - memset(outBuffer, 0, bufsize); - BytesReturned = 0; - bool result = DeviceIoControl( - hDevice, - 0x22240Cu, - inBuffer, - dataSizeIn + 8, - outBuffer, - bufsize, - LPDWORD(&BytesReturned), - 0); - if ( result ) - { - if ( *dataSizeOut < BytesReturned ) - { - BytesReturned = *dataSizeOut; - } - memmove(dataOut, outBuffer, BytesReturned); - } - free(inBuffer); - return result; -} - -bool AsusTUFLaptopController::deviceControl(int a1, int a2) -{ - if ( hDevice && hDevice != HANDLE(-1) ) - { - int data[2]; - data[0] = a1; - data[1] = a2; - int result; - int outBufSize = 4; - if ( deviceIoControlWrapper(&data, 1398162756, 8, &result, &outBufSize) ) - { - if(outBufSize < 4) - { - result = 0; - } - if ( result == 1 ) - { - return 1; - } - } - } - return 0; -} - -bool AsusTUFLaptopController::deviceControl(int a1, int a2, int a3) -{ - unsigned int data[3]; - data[0] = a1; - data[1] = a2; - data[2] = a3; - int outBuf; - int outBufSize = 4; - - if ( hDevice && hDevice != HANDLE(-1) ) - { - if ( deviceIoControlWrapper(data, 0x53564544, 12, &outBuf, &outBufSize) ) - { - if(outBufSize < 4) - { - outBuf = 0; - } - if ( outBuf == 1 ) - { - return 1; - } - } - } - return 0; -} - -bool AsusTUFLaptopController::getStatus(int a1, int *out) -{ - int status; - int statusSize = 4; - - if ( !hDevice || hDevice == HANDLE(-1) || (!deviceIoControlWrapper(&a1, 1398035268, 4, &status, &statusSize)) ) - { - return 0; - } - if(statusSize < 4) - { - status = 0; - } - *out = status; - return 1; -} - -bool AsusTUFLaptopController::getStatusExtended(int a1, int a2, int *status1, int *status2, int* status3) -{ - int commandData[2]; - commandData[0] = a1; - commandData[1] = a2; - int statusBuffer[3]; - int statusSize = 12; - - if ( hDevice && hDevice != HANDLE(-1) - && deviceIoControlWrapper(commandData, 1398035268, 8, statusBuffer, &statusSize) ) - { - *status1 = statusBuffer[0]; - *status2 = statusBuffer[1]; - *status3 = statusBuffer[2]; - return 1; - } - else - { - return 0; - } -} - -void AsusTUFLaptopController::setMode(unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char mode, - unsigned char speed, - bool save) -{ - - /*--------------------------------------------------------*\ - | Use switch case since our speed values are magic numbers | - | Default to Medium/Normal speed | - \*--------------------------------------------------------*/ - unsigned char speed_val; - - switch(speed) - { - case(1): - speed_val = ASUS_WMI_KEYBOARD_SPEED_SLOW; - break; - default: - case(2): - speed_val = ASUS_WMI_KEYBOARD_SPEED_NORMAL; - break; - case(3): - speed_val = ASUS_WMI_KEYBOARD_SPEED_FAST; - break; - } - - - /*----------------------------------------------------------*\ - | We need to use a magic value to save to firmware in order | - | To persist reboots. Save is normal op with different magic | - \*---------------------------------------------------------*/ - unsigned char save_val = ASUS_WMI_KEYBOARD_MAGIC_USE; - - if (save) - { - save_val = ASUS_WMI_KEYBOARD_MAGIC_SAVE; - } - - // B3 is store value - unsigned int high = save_val | (mode<<8) | (red<<16) | (green<<24); - unsigned int low = blue | (speed_val<<8); - - deviceControl(ASUS_WMI_DEVID_TUF_RGB_MODE, high, low); - -} - -unsigned char AsusTUFLaptopController::getBrightness() -{ - int backlight_state = 0; - getStatus(ASUS_WMI_DEVID_KBD_BACKLIGHT, &backlight_state); - - /*----------------------------------------------*\ - | Only lowest two bits indicate brightness level | - \*----------------------------------------------*/ - return backlight_state & 0x7F; -} - -void AsusTUFLaptopController::setBrightness(unsigned char brightness) -{ - /*-----------------------------------------------------*\ - | Only calls in this format persistently set brightness | - \*-----------------------------------------------------*/ - int ctrl_param = 0x80 | (brightness & 0x7F); - deviceControl(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param); -} - -/*-----------------------------------------------------------*\ -| These settings will not persist a reboot unless save is set | -\*-----------------------------------------------------------*/ -void AsusTUFLaptopController::setPowerState(bool boot, - bool awake, - bool sleep, - bool shutdown, - bool save) -{ - unsigned int state = 0xBD; - - if (boot) state = state | ASUS_WMI_KEYBOARD_POWER_BOOT; - if (awake) state = state | ASUS_WMI_KEYBOARD_POWER_AWAKE; - if (sleep) state = state | ASUS_WMI_KEYBOARD_POWER_SLEEP; - if (shutdown) state = state | ASUS_WMI_KEYBOARD_POWER_SHUTDOWN; - - if (save) state = state | ASUS_WMI_KEYBOARD_POWER_SAVE; - - deviceControl(ASUS_WMI_DEVID_TUF_RGB_STATE, state); -} - -void AsusTUFLaptopController::setFanMode(int mode) -{ - deviceControl(ASUS_WMI_DEVID_FAN_BOOST_MODE, mode); -} - - -#endif diff --git a/Controllers/AsusTUFLaptopController/AsusTUFLaptopController.h b/Controllers/AsusTUFLaptopController/AsusTUFLaptopController.h deleted file mode 100644 index 1bafa02a..00000000 --- a/Controllers/AsusTUFLaptopController/AsusTUFLaptopController.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef ASUSTUFLAPTOPCONTROLLER_H -#define ASUSTUFLAPTOPCONTROLLER_H - -#ifdef _WIN32 - -#include - -#define ASUS_WMI_DEVID_KBD_BACKLIGHT 0x00050021 -#define ASUS_WMI_DEVID_TUF_RGB_MODE 0x00100056 -#define ASUS_WMI_DEVID_TUF_RGB_STATE 0x00100057 - -#define ASUS_WMI_DEVID_FAN_BOOST_MODE 0x00110018 -#define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075 - -#define ASUS_WMI_KEYBOARD_SPEED_SLOW 0xE1 -#define ASUS_WMI_KEYBOARD_SPEED_NORMAL 0xEB -#define ASUS_WMI_KEYBOARD_SPEED_FAST 0xF5 - -#define ASUS_WMI_KEYBOARD_SPEED_MIN 1 -#define ASUS_WMI_KEYBOARD_SPEED_MAX 3 - -#define ASUS_WMI_KEYBOARD_MODE_STATIC 0x00 -#define ASUS_WMI_KEYBOARD_MODE_BREATHING 0x01 -#define ASUS_WMI_KEYBOARD_MODE_COLORCYCLE 0x02 -#define ASUS_WMI_KEYBOARD_MODE_STROBING 0x0A - -#define ASUS_WMI_KEYBOARD_BRIGHTNESS_MIN 0 -#define ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX 3 - -#define ASUS_WMI_KEYBOARD_MAGIC_USE 0xB3 -#define ASUS_WMI_KEYBOARD_MAGIC_SAVE 0xB4 - -#define ASUS_WMI_KEYBOARD_POWER_BOOT 0x03<<16 -#define ASUS_WMI_KEYBOARD_POWER_AWAKE 0x0C<<16 -#define ASUS_WMI_KEYBOARD_POWER_SLEEP 0x30<<16 -#define ASUS_WMI_KEYBOARD_POWER_SHUTDOWN 0xC0<<16 - -#define ASUS_WMI_KEYBOARD_POWER_SAVE 0x01<<8 - -#define ASUS_WMI_FAN_SPEED_NORMAL 0 -#define ASUS_WMI_FAN_SPEED_TURBO 1 -#define ASUS_WMI_FAN_SPEED_SILENT 2 - -class AsusTUFLaptopController -{ -private: - HANDLE hDevice; - static int checkWMIType(); - AsusTUFLaptopController(); - - bool deviceIoControlWrapper(const void *dataIn, int commandIndex, int dataSizeIn, void *dataOut, int *dataSizeOut); - bool deviceControl(int a1, int a2); - bool deviceControl(int a1, int a2, int a3); - bool getStatus(int a1, int *out); - bool getStatusExtended(int a1, int a2, int *status1, int *status2, int* status3); - -public: - static AsusTUFLaptopController * checkAndCreate(); - ~AsusTUFLaptopController(); - - void setMode(unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char mode, - unsigned char speed, - bool save); - - unsigned char getBrightness(); - void setBrightness(unsigned char brightness); - - void setPowerState(bool boot, - bool awake, - bool sleep, - bool shutdown, - bool save); - - void setFanMode(int mode); -}; - -#endif - -#endif // ASUSTUFLAPTOPCONTROLLER_H diff --git a/Controllers/AsusTUFLaptopController/AsusTUFLaptopController_Linux.cpp b/Controllers/AsusTUFLaptopController/AsusTUFLaptopController_Linux.cpp new file mode 100644 index 00000000..880d1e3c --- /dev/null +++ b/Controllers/AsusTUFLaptopController/AsusTUFLaptopController_Linux.cpp @@ -0,0 +1,59 @@ +/*---------------------------------------------------------*\ +| AsusTUFLaptopController_Linux.cpp | +| | +| Driver for ASUS TUF laptop | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "AsusTUFLaptopController_Linux.h" + +void AsusTUFLaptopLinuxController::SendUpdate + ( + unsigned char mode, + unsigned char speed, + unsigned char save, + unsigned char red, + unsigned char green, + unsigned char blue + ) +{ + std::string s = ""; + s.append(ASUS_KBD_BACKLIGHT_BASE_PATH); + s.append(ASUS_KBD_BACKLIGHT_MODE_PATH); + FILE *controller = fopen(s.c_str(), "w"); + + s = ""; + s.append(std::to_string(save)); + s.append(" "); + s.append(std::to_string(mode)); + s.append(" "); + s.append(std::to_string(red)); + s.append(" "); + s.append(std::to_string(green)); + s.append(" "); + s.append(std::to_string(blue)); + s.append(" "); + s.append(std::to_string(speed)); + + fputs(s.c_str(), controller); + + fclose(controller); +} + +void AsusTUFLaptopLinuxController::SendBrightness + ( + unsigned char brightness + ) +{ + std::string s = ""; + s.append(ASUS_KBD_BACKLIGHT_BASE_PATH); + s.append(ASUS_KBD_BACKLIGHT_BRIGHTNESS_PATH); + FILE *controller = fopen(s.c_str(), "w"); + + fputs(std::to_string(brightness).c_str(), controller); + + fclose(controller); +} diff --git a/Controllers/AsusTUFLaptopController/AsusTUFLaptopController_Linux.h b/Controllers/AsusTUFLaptopController/AsusTUFLaptopController_Linux.h new file mode 100644 index 00000000..b9e07e64 --- /dev/null +++ b/Controllers/AsusTUFLaptopController/AsusTUFLaptopController_Linux.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------*\ +| AsusTUFLaptopController_Linux.h | +| | +| Driver for ASUS TUF laptop | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" + +#define ASUS_KBD_BACKLIGHT_BRIGHTNESS_MIN 0 +#define ASUS_KBD_BACKLIGHT_BRIGHTNESS_MAX 3 +#define ASUS_KBD_BACKLIGHT_BRIGHTNESS 3 + +#define ASUS_KBD_BACKLIGHT_SPEED_MIN 0 +#define ASUS_KBD_BACKLIGHT_SPEED_MAX 2 +#define ASUS_KBD_BACKLIGHT_SPEED 1 + +#define ASUS_KBD_BACKLIGHT_BASE_PATH "/sys/devices/platform/asus-nb-wmi/leds/asus::kbd_backlight" +#define ASUS_KBD_BACKLIGHT_MODE_PATH "/kbd_rgb_mode" +#define ASUS_KBD_BACKLIGHT_BRIGHTNESS_PATH "/brightness" + +class AsusTUFLaptopLinuxController +{ +public: + void SendBrightness + ( + unsigned char brightness + ); + + void SendUpdate + ( + unsigned char mode, + unsigned char speed, + unsigned char save, + unsigned char red, + unsigned char green, + unsigned char blue + ); +}; diff --git a/Controllers/AsusTUFLaptopController/AsusTUFLaptopController_Windows.cpp b/Controllers/AsusTUFLaptopController/AsusTUFLaptopController_Windows.cpp new file mode 100644 index 00000000..bceadba5 --- /dev/null +++ b/Controllers/AsusTUFLaptopController/AsusTUFLaptopController_Windows.cpp @@ -0,0 +1,343 @@ +/*---------------------------------------------------------*\ +| AsusTUFLaptopController_Windows.cpp | +| | +| Driver for ASUS TUF laptop | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include "AsusTUFLaptopController_Windows.h" + +static bool coInitialized = 0; + +static GUID CLSID_GUID_DEVCLASS_SYSTEM = { 0x4D36E97D, 0xE325, 0x11CE, {0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } }; + +int AsusTUFLaptopController::checkWMIType() +{ + int n; + int result = 0; + struct _SP_DEVINFO_DATA DeviceInfoData; + const int bufsize = 260; + wchar_t PropertyBuffer[bufsize]; + + HDEVINFO devinfo = SetupDiGetClassDevsW(&CLSID_GUID_DEVCLASS_SYSTEM, 0, 0, 2u); + + if(devinfo == HDEVINFO(-1)) + { + return 0; + } + + n = 0; + DeviceInfoData.cbSize = sizeof(DeviceInfoData); + + while(SetupDiEnumDeviceInfo(devinfo, n, &DeviceInfoData)) // Invalid buffer + { + if(SetupDiGetDeviceRegistryPropertyW(devinfo, + &DeviceInfoData, + SPDRP_ENUMERATOR_NAME, + NULL, + PBYTE(PropertyBuffer), + sizeof(PropertyBuffer), + 0)) + { + // If we found property "ACPI" + if(!wcscmp(PropertyBuffer, L"ACPI")) + { + memset(PropertyBuffer, 0, sizeof(PropertyBuffer)); + if(SetupDiGetDeviceInstanceIdW(devinfo, &DeviceInfoData, PropertyBuffer, bufsize, 0)) + { + _wcsupr_s(PropertyBuffer, bufsize); + if(wcsstr(PropertyBuffer, L"ACPI\\ATK0100")) + { + result = 1; + break; + } + if(!wcscmp(PropertyBuffer, L"ACPI\\PNP0C14\\ATK")) + { + result = 2; + break; + } + } + } + } + + n++; + } + SetupDiDestroyDeviceInfoList(devinfo); + + return(result); +} + +AsusTUFLaptopController::AsusTUFLaptopController() +{ + hDevice = CreateFileW(L"\\\\.\\ATKACPI", 0xC0000000, 3u, 0, 3u, 0, 0); +} + +AsusTUFLaptopController* AsusTUFLaptopController::checkAndCreate() +{ + // This might cause issues when coInitialize() is used in multiple places + HRESULT init = CoInitializeEx(0, COINIT_APARTMENTTHREADED); + + if(init < 0 && init != 0x80010106) + { + return(0); + } + + coInitialized = 1; + + int type = checkWMIType(); + if(type == 2) + { + AsusTUFLaptopController* controller = new AsusTUFLaptopController(); + if(controller->hDevice != HANDLE(-1)) + { + return(controller); + } + delete controller; + } + + return(nullptr); +} + +AsusTUFLaptopController::~AsusTUFLaptopController() +{ + if(hDevice && hDevice != HANDLE(-1)) + { + CloseHandle(hDevice); + hDevice = 0; + } + + /*-----------------------------------------------------*\ + | This might cause issues when coInitialize() is used | + | in multiple places | + \*-----------------------------------------------------*/ + if(coInitialized) + { + CoUninitialize(); + coInitialized = 0; + } +} + +bool AsusTUFLaptopController::deviceIoControlWrapper(const void *dataIn, int commandIndex, int dataSizeIn, void *dataOut, int *dataSizeOut) +{ + size_t BytesReturned; + const int bufsize = 1024; + char outBuffer[bufsize]; + + LPDWORD inBuffer = LPDWORD(malloc(dataSizeIn + 8)); + inBuffer[0] = commandIndex; + inBuffer[1] = dataSizeIn; + memmove(inBuffer + 2, dataIn, dataSizeIn); + memset(outBuffer, 0, bufsize); + BytesReturned = 0; + bool result = DeviceIoControl( + hDevice, + 0x22240Cu, + inBuffer, + dataSizeIn + 8, + outBuffer, + bufsize, + LPDWORD(&BytesReturned), + 0); + if(result) + { + if((size_t)*dataSizeOut < BytesReturned) + { + BytesReturned = (size_t)*dataSizeOut; + } + memmove(dataOut, outBuffer, BytesReturned); + } + free(inBuffer); + + return(result); +} + +bool AsusTUFLaptopController::deviceControl(int a1, int a2) +{ + if(hDevice && hDevice != HANDLE(-1)) + { + int data[2]; + data[0] = a1; + data[1] = a2; + int result; + int outBufSize = 4; + + if(deviceIoControlWrapper(&data, 1398162756, 8, &result, &outBufSize)) + { + if(outBufSize < 4) + { + result = 0; + } + if(result == 1) + { + return(1); + } + } + } + return(0); +} + +bool AsusTUFLaptopController::deviceControl(int a1, int a2, int a3) +{ + unsigned int data[3]; + data[0] = a1; + data[1] = a2; + data[2] = a3; + int outBuf; + int outBufSize = 4; + + if(hDevice && hDevice != HANDLE(-1)) + { + if(deviceIoControlWrapper(data, 0x53564544, 12, &outBuf, &outBufSize)) + { + if(outBufSize < 4) + { + outBuf = 0; + } + if(outBuf == 1) + { + return(1); + } + } + } + return(0); +} + +bool AsusTUFLaptopController::getStatus(int a1, int *out) +{ + int status; + int statusSize = 4; + + if(!hDevice || hDevice == HANDLE(-1) || (!deviceIoControlWrapper(&a1, 1398035268, 4, &status, &statusSize))) + { + return(0); + } + if(statusSize < 4) + { + status = 0; + } + + *out = status; + + return(1); +} + +bool AsusTUFLaptopController::getStatusExtended(int a1, int a2, int *status1, int *status2, int* status3) +{ + int commandData[2]; + commandData[0] = a1; + commandData[1] = a2; + int statusBuffer[3]; + int statusSize = 12; + + if(hDevice && hDevice != HANDLE(-1) && deviceIoControlWrapper(commandData, 1398035268, 8, statusBuffer, &statusSize)) + { + *status1 = statusBuffer[0]; + *status2 = statusBuffer[1]; + *status3 = statusBuffer[2]; + + return(1); + } + else + { + return(0); + } +} + +void AsusTUFLaptopController::setMode(unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char mode, + unsigned char speed, + bool save) +{ + /*--------------------------------------------------------*\ + | Use switch case since our speed values are magic numbers | + | Default to Medium/Normal speed | + \*--------------------------------------------------------*/ + unsigned char speed_val; + + switch(speed) + { + case(1): + speed_val = ASUS_WMI_KEYBOARD_SPEED_SLOW; + break; + default: + case(2): + speed_val = ASUS_WMI_KEYBOARD_SPEED_NORMAL; + break; + case(3): + speed_val = ASUS_WMI_KEYBOARD_SPEED_FAST; + break; + } + + /*----------------------------------------------------------*\ + | We need to use a magic value to save to firmware in order | + | To persist reboots. Save is normal op with different magic | + \*----------------------------------------------------------*/ + unsigned char save_val = ASUS_WMI_KEYBOARD_MAGIC_USE; + + if(save) + { + save_val = ASUS_WMI_KEYBOARD_MAGIC_SAVE; + } + + // B3 is store value + unsigned int high = save_val | (mode<<8) | (red<<16) | (green<<24); + unsigned int low = blue | (speed_val<<8); + + deviceControl(ASUS_WMI_DEVID_TUF_RGB_MODE, high, low); +} + +unsigned char AsusTUFLaptopController::getBrightness() +{ + int backlight_state = 0; + getStatus(ASUS_WMI_DEVID_KBD_BACKLIGHT, &backlight_state); + + /*-----------------------------------------------------*\ + | Only lowest two bits indicate brightness level | + \*-----------------------------------------------------*/ + return backlight_state & 0x7F; +} + +void AsusTUFLaptopController::setBrightness(unsigned char brightness) +{ + /*-----------------------------------------------------*\ + | Only calls in this format persistently set brightness | + \*-----------------------------------------------------*/ + int ctrl_param = 0x80 | (brightness & 0x7F); + deviceControl(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param); +} + +/*-----------------------------------------------------------*\ +| These settings will not persist a reboot unless save is set | +\*-----------------------------------------------------------*/ +void AsusTUFLaptopController::setPowerState(bool boot, + bool awake, + bool sleep, + bool shutdown, + bool save) +{ + unsigned int state = 0xBD; + + if(boot) state = state | ASUS_WMI_KEYBOARD_POWER_BOOT; + if(awake) state = state | ASUS_WMI_KEYBOARD_POWER_AWAKE; + if(sleep) state = state | ASUS_WMI_KEYBOARD_POWER_SLEEP; + if(shutdown) state = state | ASUS_WMI_KEYBOARD_POWER_SHUTDOWN; + if(save) state = state | ASUS_WMI_KEYBOARD_POWER_SAVE; + + deviceControl(ASUS_WMI_DEVID_TUF_RGB_STATE, state); +} + +void AsusTUFLaptopController::setFanMode(int mode) +{ + deviceControl(ASUS_WMI_DEVID_FAN_BOOST_MODE, mode); +} diff --git a/Controllers/AsusTUFLaptopController/AsusTUFLaptopController_Windows.h b/Controllers/AsusTUFLaptopController/AsusTUFLaptopController_Windows.h new file mode 100644 index 00000000..b8b84709 --- /dev/null +++ b/Controllers/AsusTUFLaptopController/AsusTUFLaptopController_Windows.h @@ -0,0 +1,84 @@ +/*---------------------------------------------------------*\ +| AsusTUFLaptopController_Windows.h | +| | +| Driver for ASUS TUF laptop | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include + +#define ASUS_WMI_DEVID_KBD_BACKLIGHT 0x00050021 +#define ASUS_WMI_DEVID_TUF_RGB_MODE 0x00100056 +#define ASUS_WMI_DEVID_TUF_RGB_STATE 0x00100057 + +#define ASUS_WMI_DEVID_FAN_BOOST_MODE 0x00110018 +#define ASUS_WMI_DEVID_THROTTLE_THERMAL_POLICY 0x00120075 + +#define ASUS_WMI_KEYBOARD_SPEED_SLOW 0xE1 +#define ASUS_WMI_KEYBOARD_SPEED_NORMAL 0xEB +#define ASUS_WMI_KEYBOARD_SPEED_FAST 0xF5 + +#define ASUS_WMI_KEYBOARD_SPEED_MIN 1 +#define ASUS_WMI_KEYBOARD_SPEED_MAX 3 + +#define ASUS_WMI_KEYBOARD_MODE_STATIC 0x00 +#define ASUS_WMI_KEYBOARD_MODE_BREATHING 0x01 +#define ASUS_WMI_KEYBOARD_MODE_COLORCYCLE 0x02 +#define ASUS_WMI_KEYBOARD_MODE_STROBING 0x0A + +#define ASUS_WMI_KEYBOARD_BRIGHTNESS_MIN 0 +#define ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX 3 + +#define ASUS_WMI_KEYBOARD_MAGIC_USE 0xB3 +#define ASUS_WMI_KEYBOARD_MAGIC_SAVE 0xB4 + +#define ASUS_WMI_KEYBOARD_POWER_BOOT 0x03<<16 +#define ASUS_WMI_KEYBOARD_POWER_AWAKE 0x0C<<16 +#define ASUS_WMI_KEYBOARD_POWER_SLEEP 0x30<<16 +#define ASUS_WMI_KEYBOARD_POWER_SHUTDOWN 0xC0<<16 + +#define ASUS_WMI_KEYBOARD_POWER_SAVE 0x01<<8 + +#define ASUS_WMI_FAN_SPEED_NORMAL 0 +#define ASUS_WMI_FAN_SPEED_TURBO 1 +#define ASUS_WMI_FAN_SPEED_SILENT 2 + +class AsusTUFLaptopController +{ +private: + HANDLE hDevice; + static int checkWMIType(); + AsusTUFLaptopController(); + + bool deviceIoControlWrapper(const void *dataIn, int commandIndex, int dataSizeIn, void *dataOut, int *dataSizeOut); + bool deviceControl(int a1, int a2); + bool deviceControl(int a1, int a2, int a3); + bool getStatus(int a1, int *out); + bool getStatusExtended(int a1, int a2, int *status1, int *status2, int* status3); + +public: + static AsusTUFLaptopController * checkAndCreate(); + ~AsusTUFLaptopController(); + + void setMode(unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char mode, + unsigned char speed, + bool save); + + unsigned char getBrightness(); + void setBrightness(unsigned char brightness); + + void setPowerState(bool boot, + bool awake, + bool sleep, + bool shutdown, + bool save); + + void setFanMode(int mode); +}; diff --git a/Controllers/AsusTUFLaptopController/AsusTUFLaptopDetect_Linux.cpp b/Controllers/AsusTUFLaptopController/AsusTUFLaptopDetect_Linux.cpp new file mode 100644 index 00000000..d8a106af --- /dev/null +++ b/Controllers/AsusTUFLaptopController/AsusTUFLaptopDetect_Linux.cpp @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| AsusTUFLaptopDetect_Linux.cpp | +| | +| Detector for ASUS TUF laptop | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "Detector.h" +#include "RGBController_AsusTUFLaptop_Linux.h" + +static void DetectAsusTUFLaptopLinuxControllers() +{ + /*-------------------------------------------------------------------------------------*\ + | If /sys/devices/platform/asus-nb-wmi/leds/asus::kbd_backlight/kbd_rgb_mode exists, | + | the kernel support TUF Laptop keyboard LED controlling. | + \*-------------------------------------------------------------------------------------*/ + + std::string s = ""; + s.append(ASUS_KBD_BACKLIGHT_BASE_PATH); + s.append(ASUS_KBD_BACKLIGHT_MODE_PATH); + + if(!access(s.c_str(), F_OK)) + { + AsusTUFLaptopLinuxController* controller = new AsusTUFLaptopLinuxController(); + RGBController_AsusTUFLaptopLinux* rgb_controller = new RGBController_AsusTUFLaptopLinux(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + return; +} + +REGISTER_DETECTOR("ASUS TUF Laptop", DetectAsusTUFLaptopLinuxControllers); diff --git a/Controllers/AsusTUFLaptopController/AsusTUFLaptopDetect_Windows.cpp b/Controllers/AsusTUFLaptopController/AsusTUFLaptopDetect_Windows.cpp new file mode 100644 index 00000000..012d30e3 --- /dev/null +++ b/Controllers/AsusTUFLaptopController/AsusTUFLaptopDetect_Windows.cpp @@ -0,0 +1,52 @@ +/*---------------------------------------------------------*\ +| AsusTUFLaptopDetect_Windows.cpp | +| | +| Detector for ASUS TUF laptop | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "RGBController_AsusTUFLaptop_Windows.h" +#include "wmi.h" + +static void DetectAsusTUFLaptopWMIControllers() +{ + // Try to retrieve ProductID / Device name from WMI; Possibly can be rewritten to use wmi.cpp + // IF you encounter false detection ( e.g. if your laptop keyboard backlight uses USB interface + // instead of ACPI WMI) please add a WHITELIST by checking the + // `name` variable for model substrings like "FX505DU" + // For now, checking for "TUF Gaming" should suffice + + Wmi wmi; + + std::vector systemProduct; + if (wmi.query("SELECT * FROM Win32_ComputerSystemProduct", systemProduct)) + { + return; + } + + // There should only be one, a cycle is a precaution + if(systemProduct.size() != 1) + { + return; + } + std::string& name = systemProduct[0]["Name"]; + + if(name.find("TUF Gaming") == name.npos) + { + return; + } + + AsusTUFLaptopController* controller = AsusTUFLaptopController::checkAndCreate(); + if(controller) + { + RGBController* new_controller = new RGBController_AsusTUFLaptopWMI(controller); + + ResourceManager::get()->RegisterRGBController(new_controller); + } +} /* DetectAsusTUFLaptopWMIControllers() */ + +REGISTER_DETECTOR("ASUS TUF Laptop", DetectAsusTUFLaptopWMIControllers); diff --git a/Controllers/AsusTUFLaptopController/AsusTUFLaptopLinuxController.cpp b/Controllers/AsusTUFLaptopController/AsusTUFLaptopLinuxController.cpp deleted file mode 100644 index f112dbea..00000000 --- a/Controllers/AsusTUFLaptopController/AsusTUFLaptopLinuxController.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "AsusTUFLaptopLinuxController.h" - -#include - -void AsusTUFLaptopLinuxController::SendUpdate -( - unsigned char mode, - unsigned char speed, - unsigned char save, - unsigned char red, - unsigned char green, - unsigned char blue -) -{ - std::string s = ""; - s.append(ASUS_KBD_BACKLIGHT_BASE_PATH); - s.append(ASUS_KBD_BACKLIGHT_MODE_PATH); - FILE *controller = fopen(s.c_str(), "w"); - - s = ""; - s.append(std::to_string(save)); - s.append(" "); - s.append(std::to_string(mode)); - s.append(" "); - s.append(std::to_string(red)); - s.append(" "); - s.append(std::to_string(green)); - s.append(" "); - s.append(std::to_string(blue)); - s.append(" "); - s.append(std::to_string(speed)); - - fputs(s.c_str(), controller); - - fclose(controller); -} - -void AsusTUFLaptopLinuxController::SendBrightness -( - unsigned char brightness -) -{ - std::string s = ""; - s.append(ASUS_KBD_BACKLIGHT_BASE_PATH); - s.append(ASUS_KBD_BACKLIGHT_BRIGHTNESS_PATH); - FILE *controller = fopen(s.c_str(), "w"); - - fputs(std::to_string(brightness).c_str(), controller); - - fclose(controller); -} diff --git a/Controllers/AsusTUFLaptopController/AsusTUFLaptopLinuxController.h b/Controllers/AsusTUFLaptopController/AsusTUFLaptopLinuxController.h deleted file mode 100644 index 70f0054b..00000000 --- a/Controllers/AsusTUFLaptopController/AsusTUFLaptopLinuxController.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef ASUSTUFLAPTOPLINUXCONTROLLER_H -#define ASUSTUFLAPTOPLINUXCONTROLLER_H - -#include "RGBController.h" - -#define ASUS_KBD_BACKLIGHT_BRIGHTNESS_MIN 0 -#define ASUS_KBD_BACKLIGHT_BRIGHTNESS_MAX 3 -#define ASUS_KBD_BACKLIGHT_BRIGHTNESS 3 - -#define ASUS_KBD_BACKLIGHT_SPEED_MIN 0 -#define ASUS_KBD_BACKLIGHT_SPEED_MAX 2 -#define ASUS_KBD_BACKLIGHT_SPEED 1 - -#define ASUS_KBD_BACKLIGHT_BASE_PATH "/sys/devices/platform/asus-nb-wmi/leds/asus::kbd_backlight" -#define ASUS_KBD_BACKLIGHT_MODE_PATH "/kbd_rgb_mode" -#define ASUS_KBD_BACKLIGHT_BRIGHTNESS_PATH "/brightness" - -class AsusTUFLaptopLinuxController -{ -public: - void SendBrightness - ( - unsigned char brightness - ); - - void SendUpdate - ( - unsigned char mode, - unsigned char speed, - unsigned char save, - unsigned char red, - unsigned char green, - unsigned char blue - ); -}; - -#endif // ASUSTUFLAPTOPLINUXCONTROLLER_H diff --git a/Controllers/AsusTUFLaptopController/AsusTUFLaptopLinuxDetect.cpp b/Controllers/AsusTUFLaptopController/AsusTUFLaptopLinuxDetect.cpp deleted file mode 100644 index b05e728f..00000000 --- a/Controllers/AsusTUFLaptopController/AsusTUFLaptopLinuxDetect.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "RGBController_AsusTUFLaptopLinux.h" -#include "AsusTUFLaptopLinuxController.h" - -#include -#include "Detector.h" -#include - -static void DetectAsusTUFLaptopLinuxControllers() -{ - /*-------------------------------------------------------------------------------------*\ - | If /sys/devices/platform/asus-nb-wmi/leds/asus::kbd_backlight/kbd_rgb_mode exists, | - | the kernel support TUF Laptop keyboard LED controlling. | - \*-------------------------------------------------------------------------------------*/ - - std::string s = ""; - s.append(ASUS_KBD_BACKLIGHT_BASE_PATH); - s.append(ASUS_KBD_BACKLIGHT_MODE_PATH); - - if(!access(s.c_str(), F_OK)) - { - AsusTUFLaptopLinuxController* controller = new AsusTUFLaptopLinuxController(); - RGBController_AsusTUFLaptopLinux* rgb_controller = new RGBController_AsusTUFLaptopLinux(controller); - ResourceManager::get()->RegisterRGBController(rgb_controller); - } - return; -} - -REGISTER_DETECTOR("ASUS TUF Laptop", DetectAsusTUFLaptopLinuxControllers); diff --git a/Controllers/AsusTUFLaptopController/AsusTUFLaptopWMIDetect.cpp b/Controllers/AsusTUFLaptopController/AsusTUFLaptopWMIDetect.cpp deleted file mode 100644 index 86fb36e0..00000000 --- a/Controllers/AsusTUFLaptopController/AsusTUFLaptopWMIDetect.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#ifdef _WIN32 - -#include "AsusTUFLaptopController.h" -#include "RGBController_AsusTUFLaptopWMI.h" - -#include "Detector.h" -#include "wmi.h" -#include - -static void DetectAsusTUFLaptopWMIControllers() -{ - // Try to retrieve ProductID / Device name from WMI; Possibly can be rewritten to use wmi.cpp - // IF you encounter false detection ( e.g. if your laptop keyboard backlight uses USB interface - // instead of ACPI WMI) please add a WHITELIST by checking the - // `name` variable for model substrings like "FX505DU" - // For now, checking for "TUF Gaming" should suffice - - Wmi wmi; - - std::vector systemProduct; - if (wmi.query("SELECT * FROM Win32_ComputerSystemProduct", systemProduct)) - { - return; - } - - // There should only be one, a cycle is a precaution - if(systemProduct.size() != 1) - { - return; - } - std::string& name = systemProduct[0]["Name"]; - - if(name.find("TUF Gaming") == name.npos) - { - return; - } - - AsusTUFLaptopController* controller = AsusTUFLaptopController::checkAndCreate(); - if(controller) - { - RGBController* new_controller = new RGBController_AsusTUFLaptopWMI(controller); - - ResourceManager::get()->RegisterRGBController(new_controller); - } -} /* DetectAsusTUFLaptopWMIControllers() */ - -REGISTER_DETECTOR("ASUS TUF Laptop", DetectAsusTUFLaptopWMIControllers); - -#endif diff --git a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopLinux.cpp b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopLinux.cpp deleted file mode 100644 index da9a01b1..00000000 --- a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopLinux.cpp +++ /dev/null @@ -1,150 +0,0 @@ -#include "RGBController_AsusTUFLaptopLinux.h" - -/**------------------------------------------------------------------*\ - @name Asus TUF Laptop Linux WMI - @category Keyboard - @type File Stream - @save :x: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectAsusTUFLaptopLinuxControllers - @comment Tested on ASUS TUF Gaming A15 2022 - PLEASE UPDATE YOUR KERNEL TO A VERSION NEWER THAN 6.1.0 - - Every devices supported by asus-wmi would work technically. -\*-------------------------------------------------------------------*/ - -RGBController_AsusTUFLaptopLinux::RGBController_AsusTUFLaptopLinux(AsusTUFLaptopLinuxController* controller_ptr) -{ - controller = controller_ptr; - - name = "ASUS TUF Keyboard"; - vendor = "ASUS"; - type = DEVICE_TYPE_KEYBOARD; - description = "Asus TUF Device"; - location = ASUS_KBD_BACKLIGHT_BASE_PATH; - - mode Direct; - Direct.name = "Direct"; - Direct.value = 4; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Direct.brightness_min = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MIN; - Direct.brightness_max = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MAX; - Direct.brightness = ASUS_KBD_BACKLIGHT_BRIGHTNESS; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - - mode Static; - Static.name = "Static"; - Static.value = 0; - Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Static.brightness_min = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MIN; - Static.brightness_max = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MAX; - Static.brightness = ASUS_KBD_BACKLIGHT_BRIGHTNESS; - Static.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Static); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = 1; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Breathing.speed_min = ASUS_KBD_BACKLIGHT_SPEED_MIN; - Breathing.speed_max = ASUS_KBD_BACKLIGHT_SPEED_MAX; - Breathing.brightness_min = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MIN; - Breathing.brightness_max = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MAX; - Breathing.brightness = ASUS_KBD_BACKLIGHT_BRIGHTNESS; - Breathing.color_mode = MODE_COLORS_PER_LED; - Breathing.speed = ASUS_KBD_BACKLIGHT_SPEED; - modes.push_back(Breathing); - - mode Cycle; - Cycle.name = "Spectrum Cycle"; - Cycle.value = 2; - Cycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; - Cycle.speed_min = ASUS_KBD_BACKLIGHT_SPEED_MIN; - Cycle.speed_max = ASUS_KBD_BACKLIGHT_SPEED_MAX; - Cycle.brightness_min = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MIN; - Cycle.brightness_max = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MAX; - Cycle.brightness = ASUS_KBD_BACKLIGHT_BRIGHTNESS; - Cycle.color_mode = MODE_COLORS_NONE; - Cycle.speed = ASUS_KBD_BACKLIGHT_SPEED; - modes.push_back(Cycle); - - mode Flashing; - Flashing.name = "Flashing"; - Flashing.value = 0x0A; - Flashing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Flashing.brightness_min = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MIN; - Flashing.brightness_max = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MAX; - Flashing.brightness = ASUS_KBD_BACKLIGHT_BRIGHTNESS; - Flashing.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Flashing); - - SetupZones(); -} - -void RGBController_AsusTUFLaptopLinux::SetupZones() -{ - /*---------------------------------------------------------*\ - | Set up zone | - \*---------------------------------------------------------*/ - zones.resize(1); - zones[0].type = ZONE_TYPE_SINGLE; - zones[0].name = "Keyboard Backlight zone"; - zones[0].leds_min = 1; - zones[0].leds_max = 1; - zones[0].leds_count = 1; - zones[0].matrix_map = NULL; - - /*---------------------------------------------------------*\ - | Set up LED | - \*---------------------------------------------------------*/ - leds.resize(1); - leds[0].name = "Keyboard Backlight LED"; - - SetupColors(); -} - -void RGBController_AsusTUFLaptopLinux::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_AsusTUFLaptopLinux::DeviceUpdateLEDs() -{ - uint8_t red = RGBGetRValue(colors[0]); - uint8_t green = RGBGetGValue(colors[0]); - uint8_t blue = RGBGetBValue(colors[0]); - uint8_t speed = 0; - uint8_t mode = modes[active_mode].value; - uint8_t save = 1; - if(mode == 4) - { - mode = 0; - save = 0; - } - if(mode == 1 || mode == 2) - { - speed = modes[active_mode].speed; - } - - controller->SendUpdate(mode, speed, save, red, green, blue); - controller->SendBrightness(modes[active_mode].brightness); -} - -void RGBController_AsusTUFLaptopLinux::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_AsusTUFLaptopLinux::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_AsusTUFLaptopLinux::DeviceUpdateMode() -{ - DeviceUpdateLEDs(); -} diff --git a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopLinux.h b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopLinux.h deleted file mode 100644 index a7e76bca..00000000 --- a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopLinux.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef RGBCONTROLLER_ASUSTUFLAPTOPLINUX_H -#define RGBCONTROLLER_ASUSTUFLAPTOPLINUX_H - -#include "RGBController.h" -#include "AsusTUFLaptopLinuxController.h" - - -class RGBController_AsusTUFLaptopLinux : public RGBController -{ -public: - RGBController_AsusTUFLaptopLinux(AsusTUFLaptopLinuxController* controller_ptr); - - void SetupZones() override; - - void ResizeZone(int zone, int new_size) override; - - void DeviceUpdateLEDs() override; - void UpdateZoneLEDs(int zone) override; - void UpdateSingleLED(int led) override; - - void DeviceUpdateMode() override; - -private: - AsusTUFLaptopLinuxController* controller; -}; - -#endif // RGBCONTROLLER_ASUSTUFLAPTOPLINUX_H diff --git a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.cpp b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.cpp deleted file mode 100644 index c8e2fdee..00000000 --- a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.cpp +++ /dev/null @@ -1,176 +0,0 @@ -#ifdef _WIN32 - -#include "RGBController_AsusTUFLaptopWMI.h" - -using namespace std::chrono_literals; - -/**------------------------------------------------------------------*\ - @name Asus TUF Laptop - @category Keyboard - @type WMI - @save :x: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectAsusTUFLaptopWMIControllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_AsusTUFLaptopWMI::RGBController_AsusTUFLaptopWMI(AsusTUFLaptopController* controller_ptr) -{ - name = "ASUS TUF Keyboard"; - vendor = "ASUS"; - type = DEVICE_TYPE_KEYBOARD; - description = "WMI Device"; - location = "\\\\.\\ATKACPI"; - - mode Static; - Static.name = "Static"; - Static.value = ASUS_WMI_KEYBOARD_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Static.color_mode = MODE_COLORS_PER_LED; - Static.brightness_max = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; - Static.brightness_min = ASUS_WMI_KEYBOARD_BRIGHTNESS_MIN; - Static.brightness = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; - modes.push_back(Static); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = ASUS_WMI_KEYBOARD_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Breathing.color_mode = MODE_COLORS_PER_LED; - Breathing.speed_min = ASUS_WMI_KEYBOARD_SPEED_MIN; - Breathing.speed_max = ASUS_WMI_KEYBOARD_SPEED_MAX; - Breathing.speed = 2; - Breathing.brightness_max = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; - Breathing.brightness_min = ASUS_WMI_KEYBOARD_BRIGHTNESS_MIN; - Breathing.brightness = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; - modes.push_back(Breathing); - - mode ColorCycle; - ColorCycle.name = "Color Cycle"; - ColorCycle.value = ASUS_WMI_KEYBOARD_MODE_COLORCYCLE; - ColorCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - ColorCycle.color_mode = MODE_COLORS_NONE; - ColorCycle.speed_min = ASUS_WMI_KEYBOARD_SPEED_MIN; - ColorCycle.speed_max = ASUS_WMI_KEYBOARD_SPEED_MAX; - ColorCycle.speed = 2; - ColorCycle.brightness_max = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; - ColorCycle.brightness_min = ASUS_WMI_KEYBOARD_BRIGHTNESS_MIN; - ColorCycle.brightness = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; - modes.push_back(ColorCycle); - - mode Strobing; - Strobing.name = "Strobing"; - Strobing.value = ASUS_WMI_KEYBOARD_MODE_STROBING; - Strobing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Strobing.color_mode = MODE_COLORS_PER_LED; - Strobing.brightness_max = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; - Strobing.brightness_min = ASUS_WMI_KEYBOARD_BRIGHTNESS_MIN; - Strobing.brightness = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; - modes.push_back(Strobing); - - SetupZones(); - - controller = controller_ptr; - - ReadConfiguration(); -} - -RGBController_AsusTUFLaptopWMI::~RGBController_AsusTUFLaptopWMI() -{ - delete controller; -} - -void RGBController_AsusTUFLaptopWMI::SetupZones() -{ - /*---------------------------------------------------------*\ - | Device only has one zone and one led | - \*---------------------------------------------------------*/ - zone* new_zone = new zone(); - led* new_led = new led(); - - new_zone->type = ZONE_TYPE_SINGLE; - new_zone->name = "Keyboard Backlight zone"; - new_zone->leds_min = 1; - new_zone->leds_max = 1; - new_zone->leds_count = 1; - new_zone->matrix_map = NULL; - - new_led->name = "Keyboard Backlight LED"; - - zones.push_back(*new_zone); - leds.push_back(*new_led); - - SetupColors(); -} - -void RGBController_AsusTUFLaptopWMI::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -/*---------------------------------------------------------*\ -| Break this function off since we have to call save in the | - same operation as doing everything else. | -\*---------------------------------------------------------*/ -void RGBController_AsusTUFLaptopWMI::ControllerSetMode(bool save) -{ - unsigned char red = RGBGetRValue(colors[0]); - unsigned char green = RGBGetGValue(colors[0]); - unsigned char blue = RGBGetBValue(colors[0]); - - unsigned char mode = (unsigned char)modes[(unsigned int)active_mode].value; - - /*------------------------------------------------------------*\ - | Use speed only if the mode supports it. Otherwise set normal | - \*------------------------------------------------------------*/ - unsigned char speed = ASUS_WMI_KEYBOARD_SPEED_NORMAL; - - if (modes[(unsigned int)active_mode].flags & MODE_FLAG_HAS_SPEED) - { - speed = (unsigned char)modes[(unsigned int)active_mode].speed; - } - - controller->setMode(red, green, blue, mode, speed, save); -} - -void RGBController_AsusTUFLaptopWMI::DeviceUpdateLEDs() -{ - ControllerSetMode(false); -} - -void RGBController_AsusTUFLaptopWMI::UpdateZoneLEDs(int /*zone*/) -{ - ControllerSetMode(false); -} - -void RGBController_AsusTUFLaptopWMI::UpdateSingleLED(int /*led*/) -{ - ControllerSetMode(false); -} - -void RGBController_AsusTUFLaptopWMI::DeviceUpdateMode() -{ - if (modes[(unsigned int)active_mode].flags & MODE_FLAG_HAS_BRIGHTNESS) - { - controller->setBrightness((unsigned char)modes[(unsigned int)active_mode].brightness); - } - ControllerSetMode(false); -} - -void RGBController_AsusTUFLaptopWMI::ReadConfiguration() -{ - if (modes[(unsigned int)active_mode].flags & MODE_FLAG_HAS_BRIGHTNESS) - { - modes[(unsigned int)active_mode].brightness = controller->getBrightness(); - } -} - -void RGBController_AsusTUFLaptopWMI::DeviceSaveMode() -{ - ControllerSetMode(true); -} - -#endif diff --git a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.h b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.h deleted file mode 100644 index a6387c10..00000000 --- a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifdef _WIN32 - -#ifndef RGBCONTROLLER_ASUSTUFLAPTOPWMI_H -#define RGBCONTROLLER_ASUSTUFLAPTOPWMI_H - -#include "AsusTUFLaptopController.h" -#include "RGBController.h" - -class RGBController_AsusTUFLaptopWMI : public RGBController -{ -public: - RGBController_AsusTUFLaptopWMI(AsusTUFLaptopController* controller_ptr); - virtual ~RGBController_AsusTUFLaptopWMI(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - AsusTUFLaptopController* controller; - - void ReadConfiguration(); - void ControllerSetMode(bool save); -}; - -#endif // RGBCONTROLLER_ASUSTUFLAPTOPWMI_H - -#endif // _WIN32 diff --git a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptop_Linux.cpp b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptop_Linux.cpp new file mode 100644 index 00000000..d0d5c804 --- /dev/null +++ b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptop_Linux.cpp @@ -0,0 +1,159 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusTUFLaptop_Linux.cpp | +| | +| RGBController for ASUS TUF laptop | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_AsusTUFLaptop_Linux.h" + +/**------------------------------------------------------------------*\ + @name Asus TUF Laptop Linux WMI + @category Keyboard + @type File Stream + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectAsusTUFLaptopLinuxControllers + @comment Tested on ASUS TUF Gaming A15 2022 + PLEASE UPDATE YOUR KERNEL TO A VERSION NEWER THAN 6.1.0 + + Every devices supported by asus-wmi would work technically. +\*-------------------------------------------------------------------*/ + +RGBController_AsusTUFLaptopLinux::RGBController_AsusTUFLaptopLinux(AsusTUFLaptopLinuxController* controller_ptr) +{ + controller = controller_ptr; + + name = "ASUS TUF Laptop Keyboard"; + vendor = "ASUS"; + type = DEVICE_TYPE_LAPTOP; + description = "Asus TUF Device"; + location = ASUS_KBD_BACKLIGHT_BASE_PATH; + + mode Direct; + Direct.name = "Direct"; + Direct.value = 4; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.brightness_min = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MIN; + Direct.brightness_max = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MAX; + Direct.brightness = ASUS_KBD_BACKLIGHT_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Static; + Static.name = "Static"; + Static.value = 0; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Static.brightness_min = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MIN; + Static.brightness_max = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MAX; + Static.brightness = ASUS_KBD_BACKLIGHT_BRIGHTNESS; + Static.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = 1; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Breathing.speed_min = ASUS_KBD_BACKLIGHT_SPEED_MIN; + Breathing.speed_max = ASUS_KBD_BACKLIGHT_SPEED_MAX; + Breathing.brightness_min = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MIN; + Breathing.brightness_max = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MAX; + Breathing.brightness = ASUS_KBD_BACKLIGHT_BRIGHTNESS; + Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.speed = ASUS_KBD_BACKLIGHT_SPEED; + modes.push_back(Breathing); + + mode Cycle; + Cycle.name = "Spectrum Cycle"; + Cycle.value = 2; + Cycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Cycle.speed_min = ASUS_KBD_BACKLIGHT_SPEED_MIN; + Cycle.speed_max = ASUS_KBD_BACKLIGHT_SPEED_MAX; + Cycle.brightness_min = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MIN; + Cycle.brightness_max = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MAX; + Cycle.brightness = ASUS_KBD_BACKLIGHT_BRIGHTNESS; + Cycle.color_mode = MODE_COLORS_NONE; + Cycle.speed = ASUS_KBD_BACKLIGHT_SPEED; + modes.push_back(Cycle); + + mode Flashing; + Flashing.name = "Flashing"; + Flashing.value = 0x0A; + Flashing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Flashing.brightness_min = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MIN; + Flashing.brightness_max = ASUS_KBD_BACKLIGHT_BRIGHTNESS_MAX; + Flashing.brightness = ASUS_KBD_BACKLIGHT_BRIGHTNESS; + Flashing.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Flashing); + + SetupZones(); +} + +void RGBController_AsusTUFLaptopLinux::SetupZones() +{ + /*---------------------------------------------------------*\ + | Set up zone | + \*---------------------------------------------------------*/ + zones.resize(1); + zones[0].type = ZONE_TYPE_SINGLE; + zones[0].name = "Keyboard Backlight zone"; + zones[0].leds_min = 1; + zones[0].leds_max = 1; + zones[0].leds_count = 1; + zones[0].matrix_map = NULL; + + /*---------------------------------------------------------*\ + | Set up LED | + \*---------------------------------------------------------*/ + leds.resize(1); + leds[0].name = "Keyboard Backlight LED"; + + SetupColors(); +} + +void RGBController_AsusTUFLaptopLinux::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_AsusTUFLaptopLinux::DeviceUpdateLEDs() +{ + uint8_t red = RGBGetRValue(colors[0]); + uint8_t green = RGBGetGValue(colors[0]); + uint8_t blue = RGBGetBValue(colors[0]); + uint8_t speed = 0; + uint8_t mode = modes[active_mode].value; + uint8_t save = 1; + if(mode == 4) + { + mode = 0; + save = 0; + } + if(mode == 1 || mode == 2) + { + speed = modes[active_mode].speed; + } + + controller->SendUpdate(mode, speed, save, red, green, blue); + controller->SendBrightness(modes[active_mode].brightness); +} + +void RGBController_AsusTUFLaptopLinux::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_AsusTUFLaptopLinux::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_AsusTUFLaptopLinux::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} diff --git a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptop_Linux.h b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptop_Linux.h new file mode 100644 index 00000000..01256b3e --- /dev/null +++ b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptop_Linux.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusTUFLaptop_Linux.h | +| | +| RGBController for ASUS TUF laptop | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "AsusTUFLaptopController_Linux.h" + +class RGBController_AsusTUFLaptopLinux : public RGBController +{ +public: + RGBController_AsusTUFLaptopLinux(AsusTUFLaptopLinuxController* controller_ptr); + + void SetupZones() override; + + void ResizeZone(int zone, int new_size) override; + + void DeviceUpdateLEDs() override; + void UpdateZoneLEDs(int zone) override; + void UpdateSingleLED(int led) override; + + void DeviceUpdateMode() override; + +private: + AsusTUFLaptopLinuxController* controller; +}; diff --git a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptop_Windows.cpp b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptop_Windows.cpp new file mode 100644 index 00000000..562dfa03 --- /dev/null +++ b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptop_Windows.cpp @@ -0,0 +1,181 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusTUFLaptop_Windows.cpp | +| | +| RGBController for ASUS TUF laptop | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_AsusTUFLaptop_Windows.h" + +using namespace std::chrono_literals; + +/**------------------------------------------------------------------*\ + @name Asus TUF Laptop + @category Keyboard + @type WMI + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectAsusTUFLaptopWMIControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_AsusTUFLaptopWMI::RGBController_AsusTUFLaptopWMI(AsusTUFLaptopController* controller_ptr) +{ + name = "ASUS TUF Laptop Keyboard"; + vendor = "ASUS"; + type = DEVICE_TYPE_LAPTOP; + description = "WMI Device"; + location = "\\\\.\\ATKACPI"; + + mode Static; + Static.name = "Static"; + Static.value = ASUS_WMI_KEYBOARD_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Static.color_mode = MODE_COLORS_PER_LED; + Static.brightness_max = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; + Static.brightness_min = ASUS_WMI_KEYBOARD_BRIGHTNESS_MIN; + Static.brightness = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = ASUS_WMI_KEYBOARD_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.speed_min = ASUS_WMI_KEYBOARD_SPEED_MIN; + Breathing.speed_max = ASUS_WMI_KEYBOARD_SPEED_MAX; + Breathing.speed = 2; + Breathing.brightness_max = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; + Breathing.brightness_min = ASUS_WMI_KEYBOARD_BRIGHTNESS_MIN; + Breathing.brightness = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; + modes.push_back(Breathing); + + mode ColorCycle; + ColorCycle.name = "Color Cycle"; + ColorCycle.value = ASUS_WMI_KEYBOARD_MODE_COLORCYCLE; + ColorCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + ColorCycle.color_mode = MODE_COLORS_NONE; + ColorCycle.speed_min = ASUS_WMI_KEYBOARD_SPEED_MIN; + ColorCycle.speed_max = ASUS_WMI_KEYBOARD_SPEED_MAX; + ColorCycle.speed = 2; + ColorCycle.brightness_max = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; + ColorCycle.brightness_min = ASUS_WMI_KEYBOARD_BRIGHTNESS_MIN; + ColorCycle.brightness = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; + modes.push_back(ColorCycle); + + mode Strobing; + Strobing.name = "Strobing"; + Strobing.value = ASUS_WMI_KEYBOARD_MODE_STROBING; + Strobing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Strobing.color_mode = MODE_COLORS_PER_LED; + Strobing.brightness_max = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; + Strobing.brightness_min = ASUS_WMI_KEYBOARD_BRIGHTNESS_MIN; + Strobing.brightness = ASUS_WMI_KEYBOARD_BRIGHTNESS_MAX; + modes.push_back(Strobing); + + SetupZones(); + + controller = controller_ptr; + + ReadConfiguration(); +} + +RGBController_AsusTUFLaptopWMI::~RGBController_AsusTUFLaptopWMI() +{ + delete controller; +} + +void RGBController_AsusTUFLaptopWMI::SetupZones() +{ + /*---------------------------------------------------------*\ + | Device only has one zone and one led | + \*---------------------------------------------------------*/ + zone* new_zone = new zone(); + led* new_led = new led(); + + new_zone->type = ZONE_TYPE_SINGLE; + new_zone->name = "Keyboard Backlight zone"; + new_zone->leds_min = 1; + new_zone->leds_max = 1; + new_zone->leds_count = 1; + new_zone->matrix_map = NULL; + + new_led->name = "Keyboard Backlight LED"; + + zones.push_back(*new_zone); + leds.push_back(*new_led); + + SetupColors(); +} + +void RGBController_AsusTUFLaptopWMI::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +/*---------------------------------------------------------*\ +| Break this function off since we have to call save in the | + same operation as doing everything else. | +\*---------------------------------------------------------*/ +void RGBController_AsusTUFLaptopWMI::ControllerSetMode(bool save) +{ + unsigned char red = RGBGetRValue(colors[0]); + unsigned char green = RGBGetGValue(colors[0]); + unsigned char blue = RGBGetBValue(colors[0]); + + unsigned char mode = (unsigned char)modes[(unsigned int)active_mode].value; + + /*------------------------------------------------------------*\ + | Use speed only if the mode supports it. Otherwise set normal | + \*------------------------------------------------------------*/ + unsigned char speed = ASUS_WMI_KEYBOARD_SPEED_NORMAL; + + if (modes[(unsigned int)active_mode].flags & MODE_FLAG_HAS_SPEED) + { + speed = (unsigned char)modes[(unsigned int)active_mode].speed; + } + + controller->setMode(red, green, blue, mode, speed, save); +} + +void RGBController_AsusTUFLaptopWMI::DeviceUpdateLEDs() +{ + ControllerSetMode(false); +} + +void RGBController_AsusTUFLaptopWMI::UpdateZoneLEDs(int /*zone*/) +{ + ControllerSetMode(false); +} + +void RGBController_AsusTUFLaptopWMI::UpdateSingleLED(int /*led*/) +{ + ControllerSetMode(false); +} + +void RGBController_AsusTUFLaptopWMI::DeviceUpdateMode() +{ + if (modes[(unsigned int)active_mode].flags & MODE_FLAG_HAS_BRIGHTNESS) + { + controller->setBrightness((unsigned char)modes[(unsigned int)active_mode].brightness); + } + ControllerSetMode(false); +} + +void RGBController_AsusTUFLaptopWMI::ReadConfiguration() +{ + if (modes[(unsigned int)active_mode].flags & MODE_FLAG_HAS_BRIGHTNESS) + { + modes[(unsigned int)active_mode].brightness = controller->getBrightness(); + } +} + +void RGBController_AsusTUFLaptopWMI::DeviceSaveMode() +{ + ControllerSetMode(true); +} diff --git a/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptop_Windows.h b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptop_Windows.h new file mode 100644 index 00000000..248f0413 --- /dev/null +++ b/Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptop_Windows.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------*\ +| RGBController_AsusTUFLaptop_Windows.h | +| | +| RGBController for ASUS TUF laptop | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "AsusTUFLaptopController_Windows.h" +#include "RGBController.h" + +class RGBController_AsusTUFLaptopWMI : public RGBController +{ +public: + RGBController_AsusTUFLaptopWMI(AsusTUFLaptopController* controller_ptr); + virtual ~RGBController_AsusTUFLaptopWMI(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + AsusTUFLaptopController* controller; + + void ReadConfiguration(); + void ControllerSetMode(bool save); +}; diff --git a/Controllers/BlinkyTapeController/BlinkyTapeController.cpp b/Controllers/BlinkyTapeController/BlinkyTapeController.cpp index 6f6c91b1..ccbfc13c 100644 --- a/Controllers/BlinkyTapeController/BlinkyTapeController.cpp +++ b/Controllers/BlinkyTapeController/BlinkyTapeController.cpp @@ -1,17 +1,19 @@ /*---------------------------------------------------------*\ -| BlinkyTapeController.cpp | +| BlinkyTapeController.cpp | | | -| BlinkyTape controller interface | +| Driver for BlinkyTape | | | -| Matt Mets (matt@blinkinlabs.com), 07/01/2021 | +| Matt Mets (matt@blinkinlabs.com) 01 Jul 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "BlinkyTapeController.h" - #include #include #include #include +#include "BlinkyTapeController.h" #ifndef WIN32 #define LPSTR char * @@ -74,7 +76,7 @@ void BlinkyTapeController::SetLEDs(std::vector colors) | 0-n: Data Byte (0-254) | | n+1: Packet End Byte (0xFF) | \*-------------------------------------------------------------*/ - const unsigned int payload_size = (colors.size() * 3); + const unsigned int payload_size = ((unsigned int)colors.size() * 3); const unsigned int packet_size = payload_size + 1; std::vector serial_buf(packet_size); @@ -91,9 +93,9 @@ void BlinkyTapeController::SetLEDs(std::vector colors) { const unsigned int color_offset = color_idx * 3; - serial_buf[0x00 + color_offset] = std::min((unsigned int)254, RGBGetRValue(colors[color_idx])); - serial_buf[0x01 + color_offset] = std::min((unsigned int)254, RGBGetGValue(colors[color_idx])); - serial_buf[0x02 + color_offset] = std::min((unsigned int)254, RGBGetBValue(colors[color_idx])); + serial_buf[0x00 + color_offset] = (unsigned char)std::min((unsigned int)254, RGBGetRValue(colors[color_idx])); + serial_buf[0x01 + color_offset] = (unsigned char)std::min((unsigned int)254, RGBGetGValue(colors[color_idx])); + serial_buf[0x02 + color_offset] = (unsigned char)std::min((unsigned int)254, RGBGetBValue(colors[color_idx])); } /*-------------------------------------------------------------*\ @@ -101,4 +103,3 @@ void BlinkyTapeController::SetLEDs(std::vector colors) \*-------------------------------------------------------------*/ serialport->serial_write((char *)serial_buf.data(), packet_size); } - diff --git a/Controllers/BlinkyTapeController/BlinkyTapeController.h b/Controllers/BlinkyTapeController/BlinkyTapeController.h index 0b4c7774..c6e3632c 100644 --- a/Controllers/BlinkyTapeController/BlinkyTapeController.h +++ b/Controllers/BlinkyTapeController/BlinkyTapeController.h @@ -1,11 +1,15 @@ /*---------------------------------------------------------*\ -| Definitions for BlinkyTape Interface | +| BlinkyTapeController.h | | | -| Matt Mets (matt@blinkinlabs.com), 07/01/2021 | +| Driver for BlinkyTape | +| | +| Matt Mets (matt@blinkinlabs.com) 01 Jul 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#ifndef BLINKYTAPE_H -#define BLINKYTAPE_H +#pragma once #include "RGBController.h" #include "serial_port.h" @@ -34,5 +38,3 @@ private: std::string port_name; serial_port *serialport = nullptr; }; - -#endif diff --git a/Controllers/BlinkyTapeController/BlinkyTapeControllerDetect.cpp b/Controllers/BlinkyTapeController/BlinkyTapeControllerDetect.cpp index 1415dedf..93d23d78 100644 --- a/Controllers/BlinkyTapeController/BlinkyTapeControllerDetect.cpp +++ b/Controllers/BlinkyTapeController/BlinkyTapeControllerDetect.cpp @@ -1,15 +1,25 @@ +/*---------------------------------------------------------*\ +| BlinkyTapeControllerDetect.cpp | +| | +| Detector for BlinkyTape | +| | +| Matt Mets (matt@blinkinlabs.com) 01 Jul 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "BlinkyTapeController.h" -#include "RGBController.h" #include "RGBController_BlinkyTape.h" -#include "SettingsManager.h" #include "find_usb_serial_port.h" -#include -#include -#include -#define BLINKINLABS_VID 0x1D50 -#define BLINKYTAPE_PID 0x605E +/*-----------------------------------------------------*\ +| BlinkyTape VID and PID | +\*-----------------------------------------------------*/ +#define BLINKINLABS_VID 0x1D50 +#define BLINKYTAPE_PID 0x605E /******************************************************************************************\ * * diff --git a/Controllers/BlinkyTapeController/RGBController_BlinkyTape.cpp b/Controllers/BlinkyTapeController/RGBController_BlinkyTape.cpp index 16f22629..84baf8db 100644 --- a/Controllers/BlinkyTapeController/RGBController_BlinkyTape.cpp +++ b/Controllers/BlinkyTapeController/RGBController_BlinkyTape.cpp @@ -1,9 +1,12 @@ /*---------------------------------------------------------*\ -| RGBController_BlinkyTape.cpp | +| RGBController_BlinkyTape.cpp | | | -| Generic RGB Interface for BlinkyTape Led controller | +| RGBController for BlinkyTape | | | -| Matt Mets (matt@blinkinlabs.com), 07/01/2021 | +| Matt Mets (matt@blinkinlabs.com) 01 Jul 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ #include "RGBController_BlinkyTape.h" @@ -21,19 +24,19 @@ RGBController_BlinkyTape::RGBController_BlinkyTape(BlinkyTapeController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "BlinkyTape"; - vendor = "Blinkinlabs"; - type = DEVICE_TYPE_LEDSTRIP; - description = "BlinkyTape Controller Device"; - location = controller->GetLocation(); + name = "BlinkyTape"; + vendor = "Blinkinlabs"; + type = DEVICE_TYPE_LEDSTRIP; + description = "BlinkyTape Controller Device"; + location = controller->GetLocation(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + 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(); diff --git a/Controllers/BlinkyTapeController/RGBController_BlinkyTape.h b/Controllers/BlinkyTapeController/RGBController_BlinkyTape.h index 06f3da69..ca1fdbd7 100644 --- a/Controllers/BlinkyTapeController/RGBController_BlinkyTape.h +++ b/Controllers/BlinkyTapeController/RGBController_BlinkyTape.h @@ -1,12 +1,16 @@ /*---------------------------------------------------------*\ -| RGBController_BlinkyTape.h | +| RGBController_BlinkyTape.h | | | -| Generic RGB Interface for BlinkyTape Led controller | +| RGBController for BlinkyTape | | | -| Matt Mets (matt@blinkinlabs.com), 07/01/2021 | +| Matt Mets (matt@blinkinlabs.com) 01 Jul 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "serial_port.h" #include "BlinkyTapeController.h" diff --git a/Controllers/CherryKeyboardController/CherryKeyboardController.cpp b/Controllers/CherryKeyboardController/CherryKeyboardController.cpp index d9f36b74..1ffd3ba7 100644 --- a/Controllers/CherryKeyboardController/CherryKeyboardController.cpp +++ b/Controllers/CherryKeyboardController/CherryKeyboardController.cpp @@ -1,20 +1,23 @@ -/*-----------------------------------------*\ -| CherryKeyboardController.cpp | -| | -| Driver for Cherry RGB keyboard lighting | -| controller | -| | -| Sebastian Kraus 12/25/2021 | -\*-----------------------------------------*/ - -#include "CherryKeyboardController.h" +/*---------------------------------------------------------*\ +| CherryKeyboardController.cpp | +| | +| Driver for Cherry keyboard | +| | +| Sebastian Kraus 25 Dec 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "CherryKeyboardController.h" +#include "StringUtils.h" -CherryKeyboardController::CherryKeyboardController(hid_device* dev_handle, const char* path) +CherryKeyboardController::CherryKeyboardController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } CherryKeyboardController::~CherryKeyboardController() @@ -27,6 +30,11 @@ std::string CherryKeyboardController::GetDeviceLocation() return("HID: " + location); } +std::string CherryKeyboardController::GetDeviceName() +{ + return(name); +} + std::string CherryKeyboardController::GetSerialString() { wchar_t serial_string[128]; @@ -37,10 +45,7 @@ std::string CherryKeyboardController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void CherryKeyboardController::SetKeyboardColors @@ -62,7 +67,7 @@ void CherryKeyboardController::SetKeyboardColors { packet_size = size; } - + SendKeyboardData ( &color_data[packet_offset], @@ -95,18 +100,19 @@ void CherryKeyboardController::SendKeyboardModeEx unsigned char blue ) { - unsigned char parameter_data[8]; + unsigned char parameter_data[9]; - parameter_data[0] = mode; - parameter_data[1] = brightness; - parameter_data[2] = speed; - parameter_data[3] = direction; - parameter_data[4] = random_flag; - parameter_data[5] = red; - parameter_data[6] = green; - parameter_data[7] = blue; + parameter_data[0] = 0x0; + parameter_data[1] = mode; + parameter_data[2] = brightness; + parameter_data[3] = speed; + parameter_data[4] = direction; + parameter_data[5] = random_flag; + parameter_data[6] = red; + parameter_data[7] = green; + parameter_data[8] = blue; - SendKeyboardParameter(0, 8, parameter_data); + SendKeyboardParameter(0, 9, parameter_data); } /*-------------------------------------------------------------------------------------------------*\ @@ -147,7 +153,7 @@ void CherryKeyboardController::SendKeyboardBegin() usb_buf[0x01] = CHERRY_KB_COMMAND_BEGIN; usb_buf[0x02] = 0x00; usb_buf[0x03] = CHERRY_KB_COMMAND_BEGIN; - + /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ @@ -173,7 +179,7 @@ void CherryKeyboardController::SendKeyboardEnd() usb_buf[0x01] = CHERRY_KB_COMMAND_END; usb_buf[0x02] = 0x00; usb_buf[0x03] = CHERRY_KB_COMMAND_END; - + /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ @@ -209,7 +215,7 @@ void CherryKeyboardController::SendKeyboardData | Copy in data bytes | \*-----------------------------------------------------*/ memcpy(&usb_buf[0x08], data, data_size); - + /*-----------------------------------------------------*\ | Compute Checksum | \*-----------------------------------------------------*/ @@ -237,17 +243,18 @@ void CherryKeyboardController::SendKeyboardParameter memset(usb_buf, 0x00, sizeof(usb_buf)); /*-----------------------------------------------------*\ - | Set up Keyboard Parameter (0x06) packet | + | Set up Keyboard Parameter (0x08) packet | \*-----------------------------------------------------*/ usb_buf[0x00] = 0x04; usb_buf[0x03] = CHERRY_KB_COMMAND_SET_PARAMETER; usb_buf[0x04] = parameter_size; usb_buf[0x05] = parameter; + usb_buf[0x07] = 0x55; /*-----------------------------------------------------*\ | Copy in data bytes | \*-----------------------------------------------------*/ - memcpy(&usb_buf[0x09], parameter_data, parameter_size); + memcpy(&usb_buf[0x08], parameter_data, parameter_size); /*-----------------------------------------------------*\ | Compute Checksum | diff --git a/Controllers/CherryKeyboardController/CherryKeyboardController.h b/Controllers/CherryKeyboardController/CherryKeyboardController.h index b1212abb..fe948ed8 100644 --- a/Controllers/CherryKeyboardController/CherryKeyboardController.h +++ b/Controllers/CherryKeyboardController/CherryKeyboardController.h @@ -1,22 +1,54 @@ -/*-----------------------------------------*\ -| CherryKeyboardController.h | -| | -| Definitions and types for Cherry RGB | -| keyboard lighting controller | -| | -| Sebastian Kraus 12/25/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| CherryKeyboardController.h | +| | +| Driver for Cherry keyboard | +| | +| Sebastian Kraus 25 Dec 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + #define CHERRY_KB_PACKET_SIZE 64 #define CHERRY_KB_MAX_PACKET_SIZE ( 0x36 )/* max packet size for color*/ /* update packets */ + +/*-----------------------------------------------------*\ +| Cherry keyboard product IDs | +\*-----------------------------------------------------*/ +#define MX_BOARD_3_0S_FL_NBL_PID 0x0077 +#define MX_BOARD_3_0S_FL_RGB_PID 0x0079 +#define MX_BOARD_3_0S_FL_RGB_KOR_PID 0x0083 +#define MX_1_0_FL_BL_PID 0x00AB +#define MX_BOARD_1_0_TKL_RGB_PID 0x00AC +#define MX_BOARD_8_0_TKL_RGB_PID 0x00B7 +#define MX_BOARD_10_0_FL_RGB_PID 0x00BB +#define G80_3000_TKL_NBL_PID 0x00C3 +#define MX_BOARD_2_0S_FL_RGB_EU_PID 0x01A6 +#define MX_BOARD_2_0S_FL_RGB_US_PID 0x00C4 +#define MX_BOARD_2_0S_FL_NBL_PID 0x00CE +#define G80_3000_TKL_RGB_PID 0x00C5 +#define MV_BOARD_3_0FL_RGB_PID 0x00C7 +#define CCF_MX_8_0_TKL_BL_PID 0x00C9 +#define CCF_MX_1_0_TKL_BL_PID 0x00CA +#define CCF_MX_1_0_TKL_NBL_PID 0x00CB +#define G80_3000_TKL_NBL_KOR_PID 0x00CD +#define MX_1_0_FL_NBL_PID 0x00D2 +#define MX_1_0_FL_RGB_PID 0x00D3 +#define G80_3000N_TKL_RGB_EU_PID 0x00DD +#define G80_3000N_TKL_RGB_US_PID 0x00E0 +#define G80_3000N_FL_RGB_EU_PID 0x00DE +#define G80_3000N_FL_RGB_US_PID 0x00E1 +#define MX_BOARD_10_0N_FL_RGB_EU_PID 0x00DF +#define MX_BOARD_10_0N_FL_RGB_US_PID 0x00E2 + + enum { CHERRY_KB_COMMAND_BEGIN = 0x01, /* Begin packet command */ @@ -57,7 +89,7 @@ enum CHERRY_KB_MODE_RADIATION = 0x12, CHERRY_KB_MODE_RIPPLES = 0x13, CHERRY_KB_MODE_SINGLE_KEY = 0x15, - + }; enum @@ -92,10 +124,11 @@ enum class CherryKeyboardController { public: - CherryKeyboardController(hid_device* dev_handle, const char* path); + CherryKeyboardController(hid_device* dev_handle, const char* path, std::string dev_name); ~CherryKeyboardController(); std::string GetDeviceLocation(); + std::string GetDeviceName(); std::string GetSerialString(); void SetKeyboardColors @@ -135,6 +168,7 @@ public: private: hid_device* dev; std::string location; + std::string name; void ComputeChecksum ( diff --git a/Controllers/CherryKeyboardController/CherryKeyboardControllerDetect.cpp b/Controllers/CherryKeyboardController/CherryKeyboardControllerDetect.cpp index ca632601..69167040 100644 --- a/Controllers/CherryKeyboardController/CherryKeyboardControllerDetect.cpp +++ b/Controllers/CherryKeyboardController/CherryKeyboardControllerDetect.cpp @@ -1,37 +1,24 @@ +/*---------------------------------------------------------*\ +| CherryKeyboardControllerDetect.cpp | +| | +| Detector for Cherry keyboard | +| | +| Sebastian Kraus 25 Dec 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "CherryKeyboardController.h" -#include "RGBController.h" #include "RGBController_CherryKeyboard.h" -#include -#include /*-----------------------------------------------------*\ -| Keyboard product IDs | +| Cherry keyboard VID and usage page | \*-----------------------------------------------------*/ -#define CHERRY_KEYBOARD_VID 0x046A -#define CHERRY_KEYBOARD_USAGE_PAGE 0xFF1C -#define MX_BOARD_3_0S_FL_NBL_PID 0x0077 -#define MX_BOARD_3_0S_FL_RGB_PID 0x0079 -#define MX_BOARD_3_0S_FL_RGB_KOR_PID 0x0083 -#define MX_1_0_FL_BL_PID 0x00AB -#define MX_BOARD_1_0_TKL_RGB_PID 0x00AC -#define MX_BOARD_8_0_TKL_RGB_PID 0x00B7 -#define MX_BOARD_10_0_FL_RGB_PID 0x00BB -#define G80_3000_TKL_NBL_PID 0x00C3 -#define MX_BOARD_2_0S_FL_RGB_PID 0x00C4 -#define G80_3000_TKL_RGB_PID 0x00C5 -#define MV_BOARD_3_0FL_RGB_PID 0x00C7 -#define CCF_MX_8_0_TKL_BL_PID 0x00C9 -#define CCF_MX_1_0_TKL_BL_PID 0x00CA -#define CCF_MX_1_0_TKL_NBL_PID 0x00CB -#define G30_3000_TKL_NBL_KOR_PID 0x00CD -#define MX_BOARD_2_0S_FL_NBL_PID 0x00CE -#define MX_1_0_FL_NBL_PID 0x00D2 -#define MX_1_0_FL_RGB_PID 0x00D3 -#define G80_3000N_TKL_RGB_PID 0x00DD -#define G30_3000N_FL_RGB_PID 0x00DE -#define MX_BOARD_10_0N_FL_RGB_PID 0x00DF -#define MX_BOARD_2_0S_FL_RGB_DE_PID 0x01A6 +#define CHERRY_KEYBOARD_VID 0x046A +#define CHERRY_KEYBOARD_USAGE_PAGE 0xFF1C /******************************************************************************************\ * * @@ -46,9 +33,9 @@ void DetectCherryKeyboards(hid_device_info* info, const std::string& name) hid_device* dev = hid_open_path(info->path); if( dev ) { - CherryKeyboardController* controller = new CherryKeyboardController(dev, info->path); - RGBController_CherryKeyboard* rgb_controller = new RGBController_CherryKeyboard(controller); - rgb_controller->name = name; + CherryKeyboardController* controller = new CherryKeyboardController(dev, info->path, name); + RGBController_CherryKeyboard* rgb_controller = new RGBController_CherryKeyboard(controller, info->product_id); + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -64,17 +51,20 @@ REGISTER_HID_DETECTOR_IP("Cherry Keyboard MX BOARD 1.0 TKL RGB", DetectCh REGISTER_HID_DETECTOR_IP("Cherry Keyboard MX BOARD 8.0 TKL RGB", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, MX_BOARD_8_0_TKL_RGB_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); REGISTER_HID_DETECTOR_IP("Cherry Keyboard MX BOARD 10.0 FL RGB", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, MX_BOARD_10_0_FL_RGB_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); REGISTER_HID_DETECTOR_IP("Cherry Keyboard G80-3000 TKL NBL", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, G80_3000_TKL_NBL_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); -REGISTER_HID_DETECTOR_IP("Cherry Keyboard MX BOARD 2.0S FL RGB", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, MX_BOARD_2_0S_FL_RGB_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("Cherry Keyboard MX BOARD 2.0S FL RGB (EU)", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, MX_BOARD_2_0S_FL_RGB_EU_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("Cherry Keyboard MX BOARD 2.0S FL RGB (US)", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, MX_BOARD_2_0S_FL_RGB_US_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("Cherry Keyboard MX BOARD 2.0S FL NBL", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, MX_BOARD_2_0S_FL_NBL_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); REGISTER_HID_DETECTOR_IP("Cherry Keyboard G80-3000 TKL RGB", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, G80_3000_TKL_RGB_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); REGISTER_HID_DETECTOR_IP("Cherry Keyboard MV BOARD 3.0 FL RGB", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, MV_BOARD_3_0FL_RGB_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); REGISTER_HID_DETECTOR_IP("Cherry Keyboard CCF MX 8.0 TKL BL", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, CCF_MX_8_0_TKL_BL_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); REGISTER_HID_DETECTOR_IP("Cherry Keyboard CCF MX 1.0 TKL BL", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, CCF_MX_1_0_TKL_BL_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); REGISTER_HID_DETECTOR_IP("Cherry Keyboard CCF MX 1.0 TKL NBL", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, CCF_MX_1_0_TKL_NBL_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); -REGISTER_HID_DETECTOR_IP("Cherry Keyboard G80-3000 TKL NBL KOREAN", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, G30_3000_TKL_NBL_KOR_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); -REGISTER_HID_DETECTOR_IP("Cherry Keyboard MX BOARD 2.0S FL NBL", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, MX_BOARD_2_0S_FL_NBL_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("Cherry Keyboard G80-3000 TKL NBL KOREAN", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, G80_3000_TKL_NBL_KOR_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); REGISTER_HID_DETECTOR_IP("Cherry Keyboard MX 1.0 FL NBL", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, MX_1_0_FL_NBL_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); REGISTER_HID_DETECTOR_IP("Cherry Keyboard MX 1.0 FL RGB", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, MX_1_0_FL_RGB_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); -REGISTER_HID_DETECTOR_IP("Cherry Keyboard G80-3000N TKL RGB", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, G80_3000N_TKL_RGB_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); -REGISTER_HID_DETECTOR_IP("Cherry Keyboard G80-3000N FL RGB", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, G30_3000N_FL_RGB_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); -REGISTER_HID_DETECTOR_IP("Cherry Keyboard MX BOARD 10.0N FL RGB", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, MX_BOARD_10_0N_FL_RGB_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); -REGISTER_HID_DETECTOR_IP("Cherry Keyboard MX BOARD 2.0S FL RGB DE", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, MX_BOARD_2_0S_FL_RGB_DE_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("Cherry Keyboard G80-3000N TKL RGB (EU)", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, G80_3000N_TKL_RGB_EU_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("Cherry Keyboard G80-3000N TKL RGB (US)", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, G80_3000N_TKL_RGB_US_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("Cherry Keyboard G80-3000N FL RGB (EU)", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, G80_3000N_FL_RGB_EU_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("Cherry Keyboard G80-3000N FL RGB (US)", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, G80_3000N_FL_RGB_US_PID , 1, CHERRY_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("Cherry Keyboard MX BOARD 10.0N FL RGB (EU)", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, MX_BOARD_10_0N_FL_RGB_EU_PID, 1, CHERRY_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("Cherry Keyboard MX BOARD 10.0N FL RGB (US)", DetectCherryKeyboards, CHERRY_KEYBOARD_VID, MX_BOARD_10_0N_FL_RGB_US_PID, 1, CHERRY_KEYBOARD_USAGE_PAGE); diff --git a/Controllers/CherryKeyboardController/RGBController_CherryKeyboard.cpp b/Controllers/CherryKeyboardController/RGBController_CherryKeyboard.cpp index 61eb9d7b..d55d5ba9 100644 --- a/Controllers/CherryKeyboardController/RGBController_CherryKeyboard.cpp +++ b/Controllers/CherryKeyboardController/RGBController_CherryKeyboard.cpp @@ -1,24 +1,32 @@ -/*-----------------------------------------*\ -| RGBController_CherryKeyboard.cpp | -| | -| Generic RGB Interface for Cherry RGB | -| Keyboard | -| | -| Sebastian Kraus 12/25/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CherryKeyboard.cpp | +| | +| RGBController for Cherry keyboard | +| | +| Sebastian Kraus 25 Dec 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CherryKeyboard.h" //0xFFFFFFFF indicates an unused entry in matrix #define NA 0xFFFFFFFF +#define CHERRY_MATRIX_MAP_HEIGHT 6 +#define CHERRY_MATRIX_MAP_WIDTH 21 +#define CHERRY_MATRIX_CELL_COUNT ( CHERRY_MATRIX_MAP_HEIGHT * CHERRY_MATRIX_MAP_WIDTH ) -static unsigned int matrix_map[6][23] = - { { 0, NA, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96, NA, NA, NA, NA, NA, NA }, - { 1, 7, 13, 19, 25, 31, 37, 43, 49, 55, 61, 67, 73, 79, 85, 91, 97, NA, NA, NA, NA, NA, NA }, - { 2, 8, 14, 20, 26, 32, 38, 44, 50, 56, 62, 68, 74, NA, 86, 92, 98, NA, NA, NA, NA, NA, NA }, - { 3, 9, 15, 21, 27, 33, 39, 45, 51, 57, 63, 69, 75, 81, NA, NA, NA, NA, NA, NA, NA, NA, NA }, - { 4, 10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, NA, 82, NA, 94, NA, NA, NA, NA, NA, NA, NA }, - { 5, 11, 17, NA, NA, NA, 41, NA, NA, NA, 65, 71, 77, 83, 89, 95, 101, NA, NA, NA, NA, NA, NA } }; +/* The total byte count for all colors is 'number of matrix cells' times '3 color components' */ +#define CUSTOM_COLOR_ARRAY_BYTE_COUNT ( CHERRY_MATRIX_CELL_COUNT * 3 ) + +static unsigned int matrix_map[CHERRY_MATRIX_MAP_HEIGHT][CHERRY_MATRIX_MAP_WIDTH] = + { { 0, NA, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96, 102, 108, 114, 120 }, + { 1, 7, 13, 19, 25, 31, 37, 43, 49, 55, 61, 67, 73, 79, 85, 91, 97, 103, 109, 115, 121 }, + { 2, 8, 14, 20, 26, 32, 38, 44, 50, 56, 62, 68, 74, NA, 86, 92, 98, 104, 110, 116, NA }, + { 3, 9, 15, 21, 27, 33, 39, 45, 51, 57, 63, 69, 75, 81, NA, NA, NA, 105, 111, 117, 122 }, + { 4, 10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, NA, 82, NA, 94, NA, 106, 112, 118, NA }, + { 5, 11, 17, NA, NA, NA, 41, NA, NA, NA, 65, 71, 77, 83, 89, 95, 101, 113, NA, 119, 124 } }; /**------------------------------------------------------------------*\ @name Cherry Keyboard @@ -31,11 +39,11 @@ static unsigned int matrix_map[6][23] = @comment \*-------------------------------------------------------------------*/ -RGBController_CherryKeyboard::RGBController_CherryKeyboard(CherryKeyboardController* controller_ptr) +RGBController_CherryKeyboard::RGBController_CherryKeyboard(CherryKeyboardController* controller_ptr, uint16_t product_id) { controller = controller_ptr; - name = "Cherry Keyboard Device"; + name = controller->GetDeviceName(); vendor = "Cherry"; type = DEVICE_TYPE_KEYBOARD; description = "Cherry Keyboard Device"; @@ -43,202 +51,259 @@ RGBController_CherryKeyboard::RGBController_CherryKeyboard(CherryKeyboardControl serial = controller->GetSerialString(); mode Custom; - Custom.name = "Custom"; - Custom.value = CHERRY_KB_MODE_CUSTOM; - Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Custom.color_mode = MODE_COLORS_PER_LED; + Custom.name = "Custom"; + Custom.value = CHERRY_KB_MODE_CUSTOM; + Custom.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Custom.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + Custom.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + Custom.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + Custom.color_mode = MODE_COLORS_PER_LED; modes.push_back(Custom); mode Wave; - Wave.name = "Wave"; - Wave.value = CHERRY_KB_MODE_WAVE; - Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Wave.speed_min = CHERRY_KB_SPEED_SLOWEST; - Wave.speed_max = CHERRY_KB_SPEED_FASTEST; - Wave.speed = CHERRY_KB_SPEED_NORMAL; - Wave.colors_min = 1; - Wave.colors_max = 1; - Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; + Wave.name = "Wave"; + Wave.value = CHERRY_KB_MODE_WAVE; + Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Wave.speed_min = CHERRY_KB_SPEED_SLOWEST; + Wave.speed_max = CHERRY_KB_SPEED_FASTEST; + Wave.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + Wave.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + Wave.colors_min = 1; + Wave.colors_max = 1; + Wave.speed = CHERRY_KB_SPEED_NORMAL; + Wave.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; Wave.colors.resize(1); modes.push_back(Wave); mode Spectrum; - Spectrum.name = "Spectrum"; - Spectrum.value = CHERRY_KB_MODE_SPECTRUM; - Spectrum.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; - Spectrum.speed_min = CHERRY_KB_SPEED_SLOWEST; - Spectrum.speed_max = CHERRY_KB_SPEED_FASTEST; - Spectrum.speed = CHERRY_KB_SPEED_NORMAL; - Spectrum.color_mode = MODE_COLORS_NONE; + Spectrum.name = "Spectrum"; + Spectrum.value = CHERRY_KB_MODE_SPECTRUM; + Spectrum.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Spectrum.speed_min = CHERRY_KB_SPEED_SLOWEST; + Spectrum.speed_max = CHERRY_KB_SPEED_FASTEST; + Spectrum.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + Spectrum.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + Spectrum.speed = CHERRY_KB_SPEED_NORMAL; + Spectrum.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + Spectrum.color_mode = MODE_COLORS_NONE; Spectrum.colors.resize(1); modes.push_back(Spectrum); mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = CHERRY_KB_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Breathing.speed_min = CHERRY_KB_SPEED_SLOWEST; - Breathing.speed_max = CHERRY_KB_SPEED_FASTEST; - Breathing.speed = CHERRY_KB_SPEED_NORMAL; - Breathing.colors_min = 1; - Breathing.colors_max = 1; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.name = "Breathing"; + Breathing.value = CHERRY_KB_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.speed_min = CHERRY_KB_SPEED_SLOWEST; + Breathing.speed_max = CHERRY_KB_SPEED_FASTEST; + Breathing.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + Breathing.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.speed = CHERRY_KB_SPEED_NORMAL; + Breathing.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; Breathing.colors.resize(1); modes.push_back(Breathing); mode Static; - Static.name = "Static"; - Static.value = CHERRY_KB_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Static.colors_min = 1; - Static.colors_max = 1; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.name = "Static"; + Static.value = CHERRY_KB_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Static.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + Static.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + Static.colors_min = 1; + Static.colors_max = 1; + Static.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; Static.colors.resize(1); modes.push_back(Static); mode Radar; - Radar.name = "Radar"; - Radar.value = CHERRY_KB_MODE_RADAR; - Radar.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Radar.speed_min = CHERRY_KB_SPEED_SLOWEST; - Radar.speed_max = CHERRY_KB_SPEED_FASTEST; - Radar.speed = CHERRY_KB_SPEED_NORMAL; - Radar.colors_min = 1; - Radar.colors_max = 1; - Radar.color_mode = MODE_COLORS_MODE_SPECIFIC; + Radar.name = "Radar"; + Radar.value = CHERRY_KB_MODE_RADAR; + Radar.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Radar.speed_min = CHERRY_KB_SPEED_SLOWEST; + Radar.speed_max = CHERRY_KB_SPEED_FASTEST; + Radar.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + Radar.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + Radar.colors_min = 1; + Radar.colors_max = 1; + Radar.speed = CHERRY_KB_SPEED_NORMAL; + Radar.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + Radar.color_mode = MODE_COLORS_MODE_SPECIFIC; Radar.colors.resize(1); - modes.push_back(Radar); + if(hasUnofficialModeSupport(product_id)) + modes.push_back(Radar); mode Vortex; - Vortex.name = "Vortex"; - Vortex.value = CHERRY_KB_MODE_VORTEX; - Vortex.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Vortex.speed_min = CHERRY_KB_SPEED_SLOWEST; - Vortex.speed_max = CHERRY_KB_SPEED_FASTEST; - Vortex.speed = CHERRY_KB_SPEED_NORMAL; - Vortex.colors_min = 1; - Vortex.colors_max = 1; - Vortex.color_mode = MODE_COLORS_MODE_SPECIFIC; + Vortex.name = "Vortex"; + Vortex.value = CHERRY_KB_MODE_VORTEX; + Vortex.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Vortex.speed_min = CHERRY_KB_SPEED_SLOWEST; + Vortex.speed_max = CHERRY_KB_SPEED_FASTEST; + Vortex.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + Vortex.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + Vortex.colors_min = 1; + Vortex.colors_max = 1; + Vortex.speed = CHERRY_KB_SPEED_NORMAL; + Vortex.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + Vortex.color_mode = MODE_COLORS_MODE_SPECIFIC; Vortex.colors.resize(1); - modes.push_back(Vortex); + if(hasUnofficialModeSupport(product_id)) + modes.push_back(Vortex); mode Fire; - Fire.name = "Fire"; - Fire.value = CHERRY_KB_MODE_FIRE; - Fire.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Fire.speed_min = CHERRY_KB_SPEED_SLOWEST; - Fire.speed_max = CHERRY_KB_SPEED_FASTEST; - Fire.speed = CHERRY_KB_SPEED_NORMAL; - Fire.colors_min = 1; - Fire.colors_max = 1; - Fire.color_mode = MODE_COLORS_MODE_SPECIFIC; + Fire.name = "Fire"; + Fire.value = CHERRY_KB_MODE_FIRE; + Fire.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Fire.speed_min = CHERRY_KB_SPEED_SLOWEST; + Fire.speed_max = CHERRY_KB_SPEED_FASTEST; + Fire.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + Fire.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + Fire.colors_min = 1; + Fire.colors_max = 1; + Fire.speed = CHERRY_KB_SPEED_NORMAL; + Fire.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + Fire.color_mode = MODE_COLORS_MODE_SPECIFIC; Fire.colors.resize(1); - modes.push_back(Fire); + if(hasUnofficialModeSupport(product_id)) + modes.push_back(Fire); mode Stars; - Stars.name = "Stars"; - Stars.value = CHERRY_KB_MODE_STARS; - Stars.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Stars.speed_min = CHERRY_KB_SPEED_SLOWEST; - Stars.speed_max = CHERRY_KB_SPEED_FASTEST; - Stars.speed = CHERRY_KB_SPEED_NORMAL; - Stars.color_mode = MODE_COLORS_MODE_SPECIFIC; + Stars.name = "Stars"; + Stars.value = CHERRY_KB_MODE_STARS; + Stars.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Stars.speed_min = CHERRY_KB_SPEED_SLOWEST; + Stars.speed_max = CHERRY_KB_SPEED_FASTEST; + Stars.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + Stars.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + Stars.speed = CHERRY_KB_SPEED_NORMAL; + Stars.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + Stars.color_mode = MODE_COLORS_MODE_SPECIFIC; Stars.colors.resize(1); - modes.push_back(Stars); + if(hasUnofficialModeSupport(product_id)) + modes.push_back(Stars); mode Rain; - Rain.name = "Rain"; - Rain.value = CHERRY_KB_MODE_RAIN; - Rain.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Rain.speed_min = CHERRY_KB_SPEED_SLOWEST; - Rain.speed_max = CHERRY_KB_SPEED_FASTEST; - Rain.speed = CHERRY_KB_SPEED_NORMAL; - Rain.colors_min = 1; - Rain.colors_max = 1; - Rain.color_mode = MODE_COLORS_MODE_SPECIFIC; + Rain.name = "Rain"; + Rain.value = CHERRY_KB_MODE_RAIN; + Rain.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Rain.speed_min = CHERRY_KB_SPEED_SLOWEST; + Rain.speed_max = CHERRY_KB_SPEED_FASTEST; + Rain.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + Rain.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + Rain.colors_min = 1; + Rain.colors_max = 1; + Rain.speed = CHERRY_KB_SPEED_NORMAL; + Rain.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + Rain.color_mode = MODE_COLORS_MODE_SPECIFIC; Rain.colors.resize(1); - modes.push_back(Rain); + if(hasUnofficialModeSupport(product_id)) + modes.push_back(Rain); mode Rolling; - Rolling.name = "Rolling"; - Rolling.value = CHERRY_KB_MODE_ROLLING; - Rolling.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; - Rolling.speed_min = CHERRY_KB_SPEED_SLOWEST; - Rolling.speed_max = CHERRY_KB_SPEED_FASTEST; - Rolling.speed = CHERRY_KB_SPEED_NORMAL; - Rolling.color_mode = MODE_COLORS_NONE; + Rolling.name = "Rolling"; + Rolling.value = CHERRY_KB_MODE_ROLLING; + Rolling.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Rolling.speed_min = CHERRY_KB_SPEED_SLOWEST; + Rolling.speed_max = CHERRY_KB_SPEED_FASTEST; + Rolling.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + Rolling.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + Rolling.speed = CHERRY_KB_SPEED_NORMAL; + Rolling.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + Rolling.color_mode = MODE_COLORS_NONE; modes.push_back(Rolling); - + mode Curve; - Curve.name = "Curve"; - Curve.value = CHERRY_KB_MODE_CURVE; - Curve.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Curve.speed_min = CHERRY_KB_SPEED_SLOWEST; - Curve.speed_max = CHERRY_KB_SPEED_FASTEST; - Curve.speed = CHERRY_KB_SPEED_NORMAL; - Curve.colors_min = 1; - Curve.colors_max = 1; - Curve.color_mode = MODE_COLORS_MODE_SPECIFIC; + Curve.name = "Curve"; + Curve.value = CHERRY_KB_MODE_CURVE; + Curve.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Curve.speed_min = CHERRY_KB_SPEED_SLOWEST; + Curve.speed_max = CHERRY_KB_SPEED_FASTEST; + Curve.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + Curve.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + Curve.colors_min = 1; + Curve.colors_max = 1; + Curve.speed = CHERRY_KB_SPEED_NORMAL; + Curve.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + Curve.color_mode = MODE_COLORS_MODE_SPECIFIC; Curve.colors.resize(1); modes.push_back(Curve); mode WaveMid; - WaveMid.name = "Wave Mid"; - WaveMid.value = CHERRY_KB_MODE_WAVE_MID; - WaveMid.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - WaveMid.speed_min = CHERRY_KB_SPEED_SLOWEST; - WaveMid.speed_max = CHERRY_KB_SPEED_FASTEST; - WaveMid.speed = CHERRY_KB_SPEED_NORMAL; - WaveMid.color_mode = MODE_COLORS_NONE; + WaveMid.name = "Wave Mid"; + WaveMid.value = CHERRY_KB_MODE_WAVE_MID; + WaveMid.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + WaveMid.speed_min = CHERRY_KB_SPEED_SLOWEST; + WaveMid.speed_max = CHERRY_KB_SPEED_FASTEST; + WaveMid.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + WaveMid.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + WaveMid.speed = CHERRY_KB_SPEED_NORMAL; + WaveMid.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + WaveMid.color_mode = MODE_COLORS_NONE; WaveMid.colors.resize(1); - modes.push_back(WaveMid); + if(hasUnofficialModeSupport(product_id)) + modes.push_back(WaveMid); mode Scan; - Scan.name = "Scan"; - Scan.value = CHERRY_KB_MODE_SCAN; - Scan.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Scan.colors_min = 1; - Scan.colors_max = 1; - Scan.color_mode = MODE_COLORS_MODE_SPECIFIC; + Scan.name = "Scan"; + Scan.value = CHERRY_KB_MODE_SCAN; + Scan.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Scan.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + Scan.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + Scan.colors_min = 1; + Scan.colors_max = 1; + Scan.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + Scan.color_mode = MODE_COLORS_MODE_SPECIFIC; Scan.colors.resize(1); modes.push_back(Scan); mode Radiation; - Radiation.name = "Radiation"; - Radiation.value = CHERRY_KB_MODE_RADIATION; - Radiation.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Radiation.speed_min = CHERRY_KB_SPEED_SLOWEST; - Radiation.speed_max = CHERRY_KB_SPEED_FASTEST; - Radiation.speed = CHERRY_KB_SPEED_NORMAL; - Radiation.colors_min = 1; - Radiation.colors_max = 1; - Radiation.color_mode = MODE_COLORS_MODE_SPECIFIC; + Radiation.name = "Radiation"; + Radiation.value = CHERRY_KB_MODE_RADIATION; + Radiation.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Radiation.speed_min = CHERRY_KB_SPEED_SLOWEST; + Radiation.speed_max = CHERRY_KB_SPEED_FASTEST; + Radiation.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + Radiation.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + Radiation.colors_min = 1; + Radiation.colors_max = 1; + Radiation.speed = CHERRY_KB_SPEED_NORMAL; + Radiation.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + Radiation.color_mode = MODE_COLORS_MODE_SPECIFIC; Radiation.colors.resize(1); modes.push_back(Radiation); mode Ripples; - Ripples.name = "Ripples"; - Ripples.value = CHERRY_KB_MODE_RIPPLES; - Ripples.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Ripples.speed_min = CHERRY_KB_SPEED_SLOWEST; - Ripples.speed_max = CHERRY_KB_SPEED_FASTEST; - Ripples.speed = CHERRY_KB_SPEED_NORMAL; - Ripples.colors_min = 1; - Ripples.colors_max = 1; - Ripples.color_mode = MODE_COLORS_MODE_SPECIFIC; + Ripples.name = "Ripples"; + Ripples.value = CHERRY_KB_MODE_RIPPLES; + Ripples.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Ripples.speed_min = CHERRY_KB_SPEED_SLOWEST; + Ripples.speed_max = CHERRY_KB_SPEED_FASTEST; + Ripples.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + Ripples.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + Ripples.colors_min = 1; + Ripples.colors_max = 1; + Ripples.speed = CHERRY_KB_SPEED_NORMAL; + Ripples.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + Ripples.color_mode = MODE_COLORS_MODE_SPECIFIC; Ripples.colors.resize(1); modes.push_back(Ripples); mode SingleKey; - SingleKey.name = "Single Key"; - SingleKey.value = CHERRY_KB_MODE_SINGLE_KEY; - SingleKey.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - SingleKey.speed_min = CHERRY_KB_SPEED_SLOWEST; - SingleKey.speed_max = CHERRY_KB_SPEED_FASTEST; - SingleKey.speed = CHERRY_KB_SPEED_NORMAL; - SingleKey.colors_min = 1; - SingleKey.colors_max = 1; - SingleKey.color_mode = MODE_COLORS_MODE_SPECIFIC; + SingleKey.name = "Single Key"; + SingleKey.value = CHERRY_KB_MODE_SINGLE_KEY; + SingleKey.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + SingleKey.speed_min = CHERRY_KB_SPEED_SLOWEST; + SingleKey.speed_max = CHERRY_KB_SPEED_FASTEST; + SingleKey.brightness_min = CHERRY_KB_BRIGHTNESS_LOWEST; + SingleKey.brightness_max = CHERRY_KB_BRIGHTNESS_HIGHEST; + SingleKey.colors_min = 1; + SingleKey.colors_max = 1; + SingleKey.speed = CHERRY_KB_SPEED_NORMAL; + SingleKey.brightness = CHERRY_KB_BRIGHTNESS_HIGHEST; + SingleKey.color_mode = MODE_COLORS_MODE_SPECIFIC; SingleKey.colors.resize(1); modes.push_back(SingleKey); @@ -267,17 +332,17 @@ void RGBController_CherryKeyboard::SetupZones() new_zone.name = "Keyboard"; new_zone.type = ZONE_TYPE_MATRIX; - new_zone.leds_min = 126; - new_zone.leds_max = 126; - new_zone.leds_count = 126; + new_zone.leds_min = CHERRY_MATRIX_CELL_COUNT; + new_zone.leds_max = CHERRY_MATRIX_CELL_COUNT; + new_zone.leds_count = CHERRY_MATRIX_CELL_COUNT; new_zone.matrix_map = new matrix_map_type; - new_zone.matrix_map->height = 6; - new_zone.matrix_map->width = 23; + new_zone.matrix_map->height = CHERRY_MATRIX_MAP_HEIGHT; + new_zone.matrix_map->width = CHERRY_MATRIX_MAP_WIDTH; new_zone.matrix_map->map = (unsigned int *)&matrix_map; - + zones.push_back(new_zone); - for(int led_idx = 0; led_idx < 126; led_idx++) + for(int led_idx = 0; led_idx < CHERRY_MATRIX_CELL_COUNT; led_idx++) { led new_led; @@ -299,9 +364,9 @@ void RGBController_CherryKeyboard::ResizeZone(int /*zone*/, int /*new_size*/) void RGBController_CherryKeyboard::DeviceUpdateLEDs() { - unsigned char color_data[7*CHERRY_KB_MAX_PACKET_SIZE]; + unsigned char color_data[CUSTOM_COLOR_ARRAY_BYTE_COUNT]; - for(int led_idx = 0; led_idx < 126; led_idx++) + for(int led_idx = 0; led_idx < CHERRY_MATRIX_CELL_COUNT; led_idx++) { color_data[(3 * led_idx) + 0] = RGBGetRValue(colors[led_idx]); color_data[(3 * led_idx) + 1] = RGBGetGValue(colors[led_idx]); @@ -311,7 +376,7 @@ void RGBController_CherryKeyboard::DeviceUpdateLEDs() controller->SetKeyboardColors ( color_data, - CHERRY_KB_MAX_PACKET_SIZE * 7 + CUSTOM_COLOR_ARRAY_BYTE_COUNT ); } @@ -325,11 +390,6 @@ void RGBController_CherryKeyboard::UpdateSingleLED(int /*led*/) DeviceUpdateLEDs(); } -void RGBController_CherryKeyboard::SetCustomMode() -{ - -} - void RGBController_CherryKeyboard::DeviceUpdateMode() { unsigned char red = 0x00; @@ -347,7 +407,7 @@ void RGBController_CherryKeyboard::DeviceUpdateMode() controller->SendKeyboardModeEx ( modes[active_mode].value, - CHERRY_KB_BRIGHTNESS_HIGHEST, + modes[active_mode].brightness, modes[active_mode].speed, 0, random, @@ -356,3 +416,43 @@ void RGBController_CherryKeyboard::DeviceUpdateMode() blu ); } + +bool RGBController_CherryKeyboard::hasUnofficialModeSupport(const uint16_t product_id) +{ + switch(product_id) + { + // no backlight: Why are they even listed here? (no lights, no macros) + case MX_BOARD_3_0S_FL_NBL_PID: + case G80_3000_TKL_NBL_PID: + case MX_1_0_FL_NBL_PID: + case G80_3000_TKL_NBL_KOR_PID: + case CCF_MX_1_0_TKL_NBL_PID: + // white backlight keyboards: very doubtful if any of those RGB modes match + case CCF_MX_8_0_TKL_BL_PID: + case CCF_MX_1_0_TKL_BL_PID: + case MX_1_0_FL_BL_PID: + return false; + // RGB keyboards known for not supporting unofficial modes + case MX_BOARD_3_0S_FL_RGB_PID: + case MX_BOARD_3_0S_FL_RGB_KOR_PID: + case MX_BOARD_2_0S_FL_RGB_US_PID: + case MX_BOARD_2_0S_FL_NBL_PID: + case MX_BOARD_2_0S_FL_RGB_EU_PID: + case MV_BOARD_3_0FL_RGB_PID: + return false; + // RGB keyboards which (probably) support unofficial modes + case MX_BOARD_1_0_TKL_RGB_PID: // unknown + case MX_BOARD_8_0_TKL_RGB_PID: // unknown + case MX_BOARD_10_0_FL_RGB_PID: // unknown (probably yes, related to 10.0N) + case G80_3000_TKL_RGB_PID: // unknown + case MX_1_0_FL_RGB_PID: // unkown + case G80_3000N_TKL_RGB_EU_PID: // yes + case G80_3000N_TKL_RGB_US_PID: // yes + case G80_3000N_FL_RGB_EU_PID: // firmware v0102: YES, firmware v0103: NO + case G80_3000N_FL_RGB_US_PID: // firmware v0102: YES, firmware v0103: NO + case MX_BOARD_10_0N_FL_RGB_EU_PID: // yes + case MX_BOARD_10_0N_FL_RGB_US_PID: // yes + default: + return true; + } +} diff --git a/Controllers/CherryKeyboardController/RGBController_CherryKeyboard.h b/Controllers/CherryKeyboardController/RGBController_CherryKeyboard.h index 79f1b4f8..245af656 100644 --- a/Controllers/CherryKeyboardController/RGBController_CherryKeyboard.h +++ b/Controllers/CherryKeyboardController/RGBController_CherryKeyboard.h @@ -1,33 +1,37 @@ -/*-----------------------------------------*\ -| RGBController_CherryKeyboard.h | -| | -| Generic RGB Interface for Cherry RGB | -| Keyboard | -| | -| Sebastian Kraus 12/25/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CherryKeyboard.h | +| | +| RGBController for Cherry keyboard | +| | +| Sebastian Kraus 25 Dec 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "CherryKeyboardController.h" class RGBController_CherryKeyboard : public RGBController { public: - RGBController_CherryKeyboard(CherryKeyboardController* controller_ptr); + RGBController_CherryKeyboard(CherryKeyboardController* controller_ptr, uint16_t product_id); ~RGBController_CherryKeyboard(); void SetupZones(); void ResizeZone(int zone, int new_size); - + void DeviceUpdateLEDs(); void UpdateZoneLEDs(int zone); void UpdateSingleLED(int led); - void SetCustomMode(); void DeviceUpdateMode(); private: CherryKeyboardController* controller; + + static bool hasUnofficialModeSupport(uint16_t product_id); }; diff --git a/Controllers/ColorfulGPUController/ColorfulGPUController.cpp b/Controllers/ColorfulGPUController/ColorfulGPUController.cpp index f7e3a3fa..d1b15da5 100644 --- a/Controllers/ColorfulGPUController/ColorfulGPUController.cpp +++ b/Controllers/ColorfulGPUController/ColorfulGPUController.cpp @@ -1,10 +1,22 @@ -#include "ColorfulGPUController.h" -#include +/*---------------------------------------------------------*\ +| ColorfulGPUController.cpp | +| | +| Driver for Colorful GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -ColorfulGPUController::ColorfulGPUController(i2c_smbus_interface* bus, colorful_gpu_dev_id dev) +#include +#include "ColorfulGPUController.h" +#include "pci_ids.h" +#include "LogManager.h" + +ColorfulGPUController::ColorfulGPUController(i2c_smbus_interface* bus, colorful_gpu_dev_id dev, std::string dev_name) { - this->bus = bus; - this->dev = dev; + this->bus = bus; + this->dev = dev; + this->name = dev_name; } ColorfulGPUController::~ColorfulGPUController() @@ -22,23 +34,51 @@ std::string ColorfulGPUController::GetDeviceLocation() return("I2C: " + return_string); } +std::string ColorfulGPUController::GetDeviceName() +{ + return(name); +} + void ColorfulGPUController::SetDirect(RGBColor color) { uint8_t r = RGBGetRValue(color); uint8_t g = RGBGetGValue(color); uint8_t b = RGBGetBValue(color); - uint8_t data_pkt[COLORFUL_PACKET_LENGTH] = { 0xAA, 0xEF, 0x12, 0x03, 0x01, 0xFF, r, g, b}; - - int crc = 0; - - for (int i = 0; i < COLORFUL_PACKET_LENGTH - 2; ++i) + if(this->bus->pci_subsystem_device == COLORFUL_IGAME_RTX_4070_VULCAN_OCV) { - crc += data_pkt[i]; + uint8_t data_pkt[COLORFUL_PACKET_LENGTH_V2] = { 0xAA, 0xEF, 0x01, 0x04, 0x88, 0x26 }; + for(int i=6; i < COLORFUL_PACKET_LENGTH_V2 -2; i = i + 3) + { + data_pkt[i] = r; + data_pkt[i+1] = g; + data_pkt[i+2] = b; + } + + int crc = 0; + for(int i = 0; i < COLORFUL_PACKET_LENGTH_V2 - 2; ++i) + { + crc += data_pkt[i]; + } + + data_pkt[COLORFUL_PACKET_LENGTH_V2 - 2] = crc & 0xFF; + data_pkt[COLORFUL_PACKET_LENGTH_V2 - 1] = crc >> 8; + + bus->i2c_write_block(dev, COLORFUL_PACKET_LENGTH_V2, data_pkt); } + else + { + uint8_t data_pkt[COLORFUL_PACKET_LENGTH_V1] = { 0xAA, 0xEF, 0x12, 0x03, 0x01, 0xFF, r, g, b}; - data_pkt[COLORFUL_PACKET_LENGTH - 2] = crc & 0xFF; - data_pkt[COLORFUL_PACKET_LENGTH - 1] = crc >> 8; + int crc = 0; + for(int i = 0; i < COLORFUL_PACKET_LENGTH_V1 - 2; ++i) + { + crc += data_pkt[i]; + } - bus->i2c_write_block(dev, COLORFUL_PACKET_LENGTH, data_pkt); + data_pkt[COLORFUL_PACKET_LENGTH_V1 - 2] = crc & 0xFF; + data_pkt[COLORFUL_PACKET_LENGTH_V1 - 1] = crc >> 8; + + bus->i2c_write_block(dev, COLORFUL_PACKET_LENGTH_V1, data_pkt); + } } diff --git a/Controllers/ColorfulGPUController/ColorfulGPUController.h b/Controllers/ColorfulGPUController/ColorfulGPUController.h index ed5c9948..279c0b05 100644 --- a/Controllers/ColorfulGPUController/ColorfulGPUController.h +++ b/Controllers/ColorfulGPUController/ColorfulGPUController.h @@ -1,24 +1,36 @@ +/*---------------------------------------------------------*\ +| ColorfulGPUController.h | +| | +| Driver for Colorful GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + #include #include "i2c_smbus.h" #include "RGBController.h" -#pragma once - typedef unsigned char colorful_gpu_dev_id; -#define COLORFUL_PACKET_LENGTH 11 +#define COLORFUL_PACKET_LENGTH_V1 11 +#define COLORFUL_PACKET_LENGTH_V2 122 class ColorfulGPUController { public: - ColorfulGPUController(i2c_smbus_interface* bus, colorful_gpu_dev_id dev); + ColorfulGPUController(i2c_smbus_interface* bus, colorful_gpu_dev_id dev, std::string dev_name); ~ColorfulGPUController(); std::string GetDeviceLocation(); - void SetDirect(RGBColor color); + std::string GetDeviceName(); + void SetDirect(RGBColor color); private: i2c_smbus_interface * bus; colorful_gpu_dev_id dev; + std::string name; }; diff --git a/Controllers/ColorfulGPUController/ColorfulGPUControllerDetect.cpp b/Controllers/ColorfulGPUController/ColorfulGPUControllerDetect.cpp index 1d83ab82..e9757497 100644 --- a/Controllers/ColorfulGPUController/ColorfulGPUControllerDetect.cpp +++ b/Controllers/ColorfulGPUController/ColorfulGPUControllerDetect.cpp @@ -1,12 +1,18 @@ -#include "Detector.h" +/*---------------------------------------------------------*\ +| ColorfulGPUControllerDetect.cpp | +| | +| Detector for Colorful GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "LogManager.h" #include "ColorfulGPUController.h" -#include "RGBController.h" #include "RGBController_ColorfulGPU.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include bool TestForColorfulGPU(i2c_smbus_interface* bus, uint8_t i2c_addr) { @@ -22,31 +28,47 @@ bool TestForColorfulGPU(i2c_smbus_interface* bus, uint8_t i2c_addr) int res = bus->i2c_read_block(i2c_addr, &pktsz, read_pkt); - return res == 0 && (read_pkt[0] == 0xAA && read_pkt[1] == 0xEF && read_pkt[2] == 0x81); + LOG_DEBUG("[ColorfulGPUController] Handshake: res: %d. Expected 0xAA, 0xEF, 0x81. Received: 0x%02X, 0x%02X, 0x%02X.", res, read_pkt[0], read_pkt[1], read_pkt[2]); + + return res >= 0 && (read_pkt[0] == 0xAA && read_pkt[1] == 0xEF && read_pkt[2] == 0x81); } void DetectColorfulGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name) { if(TestForColorfulGPU(bus, i2c_addr)) { - ColorfulGPUController* controller = new ColorfulGPUController(bus, i2c_addr); + ColorfulGPUController* controller = new ColorfulGPUController(bus, i2c_addr, name); RGBController_ColorfulGPU* rgb_controller = new RGBController_ColorfulGPU(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } -REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Advanced OC 12G L-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ADVANCED_OC_12G_LV, 0x61); -REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ultra W OC 12G L-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G, 0x61); -REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ultra W OC 12G L-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G_2, 0x61); -REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Ultra W OC LHR-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G_2, 0x61); -REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3070_ADVANCED_OCV, 0x61); -REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3070 Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3070_ADVANCED_OCV, 0x61); -REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3070 Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3070_ADVANCED_OCV2, 0x61); -REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3070 Ultra W OC LHR", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3070_ULTRAW_OC, 0x61); -REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3070 Ti Ultra W OC LHR", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3070_TI_ULTRAW_OC, 0x61); -REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3070 Ti Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3070_TI_ADVANCED_OCV2, 0x61); -REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3080 Ti Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3080_TI_ADVANCED_OCV2, 0x61); -REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4070 Ti Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4070_TI_ADVANCED_OCV, 0x61); -REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4080 Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4080_ULTRAW_OCV2, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Advanced OC 12G L-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ADVANCED_OC_12G_LV, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ultra W OC 12G L-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ultra W OC 12G L-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA106_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ultra W OC 12G L-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G_2, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Ultra W OC LHR-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Ultra W OC LHR-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060_ULTRAW_OC_12G_2, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3070_ADVANCED_OCV, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3060 Ti Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3060TI_ADVANCED_OC, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3070 Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3070_ADVANCED_OCV, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3070 Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3070_ADVANCED_OCV2, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3070 Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3070_ULTRAW_OC, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3070 Ultra W OC LHR", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3070_ULTRAW_OC, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3070 Ti Ultra W OC LHR", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3070TI_ULTRAW_OC, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3070 Ti Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3070TI_ADVANCED_OCV2, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3080 Advanced OC 10G-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3080_ADVANCED_OC_10G, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3080 Ti Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3080TI_ADVANCED_OCV2, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3080 Ultra W OC 10G LHR-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3080_ULTRAW_OC_10G, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 3080 Ultra W OC 10G LHR-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_3080_ULTRAW_OC_10G_2, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4070 Ti Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4070TI_ADVANCED_OCV, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4070 Ti SUPER Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_AD102_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4070TI_SUPER_ADVANCED_OCV2, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4070 Ti SUPER Ultra W", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4070TI_SUPER_ULTRA_W, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4070 SUPER Ultra W OC", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4070_SUPER_ULTRA_W_OC, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4070 Vulcan OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4070_VULCAN_OCV, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4070 SUPER Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4070S_ULTRAW_OCV, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4080 Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4080_ULTRAW_OCV, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4080 Ultra W OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4080_ULTRAW_OCV2, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4090 Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4090_ADVANCED_OCV, 0x61); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 4090 Advanced OC-V", DetectColorfulGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_4090_ADVANCED_OCV2, 0x61); diff --git a/Controllers/ColorfulGPUController/RGBController_ColorfulGPU.cpp b/Controllers/ColorfulGPUController/RGBController_ColorfulGPU.cpp index 56593ba4..2e2e3a96 100644 --- a/Controllers/ColorfulGPUController/RGBController_ColorfulGPU.cpp +++ b/Controllers/ColorfulGPUController/RGBController_ColorfulGPU.cpp @@ -1,5 +1,14 @@ -#include "RGBController_ColorfulGPU.h" +/*---------------------------------------------------------*\ +| RGBController_ColorfulGPU.cpp | +| | +| RGBController for Colorful GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include +#include "RGBController_ColorfulGPU.h" /**------------------------------------------------------------------*\ @name Colorful GPU @@ -15,7 +24,8 @@ RGBController_ColorfulGPU::RGBController_ColorfulGPU(ColorfulGPUController * colorful_gpu_ptr) { controller = colorful_gpu_ptr; - name = "Colorful GPU Device"; + + name = controller->GetDeviceName(); vendor = "Colorful"; type = DEVICE_TYPE_GPU; description = name; diff --git a/Controllers/ColorfulGPUController/RGBController_ColorfulGPU.h b/Controllers/ColorfulGPUController/RGBController_ColorfulGPU.h index 01d335c7..36b535ec 100644 --- a/Controllers/ColorfulGPUController/RGBController_ColorfulGPU.h +++ b/Controllers/ColorfulGPUController/RGBController_ColorfulGPU.h @@ -1,3 +1,12 @@ +/*---------------------------------------------------------*\ +| RGBController_ColorfulGPU.h | +| | +| RGBController for Colorful GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include "RGBController.h" @@ -20,7 +29,4 @@ public: private: ColorfulGPUController* controller; - }; - - diff --git a/Controllers/ColorfulTuringGPUController/ColorfulTuringGPUController.cpp b/Controllers/ColorfulTuringGPUController/ColorfulTuringGPUController.cpp index 8d7e71e4..e80a4dcc 100644 --- a/Controllers/ColorfulTuringGPUController/ColorfulTuringGPUController.cpp +++ b/Controllers/ColorfulTuringGPUController/ColorfulTuringGPUController.cpp @@ -1,10 +1,20 @@ -#include "ColorfulTuringGPUController.h" -#include +/*---------------------------------------------------------*\ +| ColorfulTuringGPUController.cpp | +| | +| Driver for Colorful Turing GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -ColorfulTuringGPUController::ColorfulTuringGPUController(i2c_smbus_interface* bus, colorful_gpu_dev_id dev) +#include +#include "ColorfulTuringGPUController.h" + +ColorfulTuringGPUController::ColorfulTuringGPUController(i2c_smbus_interface* bus, colorful_gpu_dev_id dev, std::string dev_name) { - this->bus = bus; - this->dev = dev; + this->bus = bus; + this->dev = dev; + this->name = dev_name; } ColorfulTuringGPUController::~ColorfulTuringGPUController() @@ -22,6 +32,11 @@ std::string ColorfulTuringGPUController::GetDeviceLocation() return("I2C: " + return_string); } +std::string ColorfulTuringGPUController::GetDeviceName() +{ + return(name); +} + int ColorfulTuringGPUController::GetMode() { uint8_t data_pkt[COLORFUL_MODE_PACKET_LENGTH]; @@ -65,12 +80,19 @@ void ColorfulTuringGPUController::SetStateDisplay(RGBColor color) bus->i2c_write_block(dev, COLORFUL_COLOR_PACKET_LENGTH, data_pkt); } -void ColorfulTuringGPUController::SetDirect(RGBColor color) +void ColorfulTuringGPUController::SetDirect(RGBColor color, bool save) { uint8_t r = RGBGetRValue(color); uint8_t g = RGBGetGValue(color); uint8_t b = RGBGetBValue(color); - uint8_t data_pkt[COLORFUL_COLOR_PACKET_LENGTH] = { 0x88, 0x02, 0x32, 0x02, r, g, b}; + uint8_t data_pkt[COLORFUL_COLOR_PACKET_LENGTH] = { 0x08, 0x0, 0x20, 0x10, r, g, b}; + if(save) + { + data_pkt[0] = 0x88; + data_pkt[1] = 0x02; + data_pkt[2] = 0x32; + data_pkt[3] = 0x02; + } int crc = 1; diff --git a/Controllers/ColorfulTuringGPUController/ColorfulTuringGPUController.h b/Controllers/ColorfulTuringGPUController/ColorfulTuringGPUController.h index e8cdd41c..f7d66d79 100644 --- a/Controllers/ColorfulTuringGPUController/ColorfulTuringGPUController.h +++ b/Controllers/ColorfulTuringGPUController/ColorfulTuringGPUController.h @@ -1,9 +1,18 @@ +/*---------------------------------------------------------*\ +| ColorfulTuringGPUController.h | +| | +| Driver for Colorful Turing GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + #include #include "i2c_smbus.h" #include "RGBController.h" -#pragma once - typedef unsigned char colorful_gpu_dev_id; #define COLORFUL_COLOR_PACKET_LENGTH 8 @@ -22,13 +31,15 @@ enum class ColorfulTuringGPUController { public: - ColorfulTuringGPUController(i2c_smbus_interface* bus, colorful_gpu_dev_id dev); + ColorfulTuringGPUController(i2c_smbus_interface* bus, colorful_gpu_dev_id dev, std::string dev_name); ~ColorfulTuringGPUController(); std::string GetDeviceLocation(); + std::string GetDeviceName(); + int GetMode(); RGBColor GetColor(); - void SetDirect(RGBColor color); + void SetDirect(RGBColor color, bool save); void SetStateDisplay(RGBColor color); void SetBreathing(RGBColor color); void SetOff(); @@ -38,4 +49,5 @@ public: private: i2c_smbus_interface * bus; colorful_gpu_dev_id dev; + std::string name; }; diff --git a/Controllers/ColorfulTuringGPUController/ColorfulTuringGPUControllerDetect.cpp b/Controllers/ColorfulTuringGPUController/ColorfulTuringGPUControllerDetect.cpp index 3cd50f07..b550f21b 100644 --- a/Controllers/ColorfulTuringGPUController/ColorfulTuringGPUControllerDetect.cpp +++ b/Controllers/ColorfulTuringGPUController/ColorfulTuringGPUControllerDetect.cpp @@ -1,23 +1,28 @@ -#include "Detector.h" +/*---------------------------------------------------------*\ +| ColorfulTuringGPUControllerDetect.cpp | +| | +| Driver for Colorful Turing GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" #include "ColorfulTuringGPUController.h" -#include "RGBController.h" #include "RGBController_ColorfulTuringGPU.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include void DetectColorfulTuringGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name) { if(bus->port_id == 1) { - ColorfulTuringGPUController* controller = new ColorfulTuringGPUController(bus, i2c_addr); + ColorfulTuringGPUController* controller = new ColorfulTuringGPUController(bus, i2c_addr, name); RGBController_ColorfulTuringGPU* rgb_controller = new RGBController_ColorfulTuringGPU(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } -REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 2070 SUPER Advanced OC-V", DetectColorfulTuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_2070_SUPER_ADVANCED_OCV, 0x50); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 2070 SUPER Advanced OC-V", DetectColorfulTuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_2070_SUPER_ADVANCED_OCV, 0x50); +REGISTER_I2C_PCI_DETECTOR("iGame GeForce RTX 2070 SUPER Advanced OC-V", DetectColorfulTuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, COLORFUL_SUB_VEN, COLORFUL_IGAME_RTX_2070_SUPER_ADVANCED_OCV2, 0x50); diff --git a/Controllers/ColorfulTuringGPUController/RGBController_ColorfulTuringGPU.cpp b/Controllers/ColorfulTuringGPUController/RGBController_ColorfulTuringGPU.cpp index 1d28cbbe..abb29a26 100644 --- a/Controllers/ColorfulTuringGPUController/RGBController_ColorfulTuringGPU.cpp +++ b/Controllers/ColorfulTuringGPUController/RGBController_ColorfulTuringGPU.cpp @@ -1,5 +1,14 @@ -#include "RGBController_ColorfulTuringGPU.h" +/*---------------------------------------------------------*\ +| RGBController_ColorfulTuringGPU.cpp | +| | +| RGBController for Colorful Turing GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include +#include "RGBController_ColorfulTuringGPU.h" /**------------------------------------------------------------------*\ @name Colorful GPU @@ -15,7 +24,8 @@ RGBController_ColorfulTuringGPU::RGBController_ColorfulTuringGPU(ColorfulTuringGPUController * colorful_gpu_ptr) { controller = colorful_gpu_ptr; - name = "Colorful GPU Device"; + + name = controller->GetDeviceName(); vendor = "Colorful"; type = DEVICE_TYPE_GPU; description = name; @@ -31,7 +41,7 @@ RGBController_ColorfulTuringGPU::RGBController_ColorfulTuringGPU(ColorfulTuringG mode Direct; Direct.name = "Direct"; Direct.value = COLORFUL_TURING_GPU_RGB_MODE_STATIC; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); @@ -70,15 +80,15 @@ RGBController_ColorfulTuringGPU::~RGBController_ColorfulTuringGPU() int RGBController_ColorfulTuringGPU::getModeIndex(int mode_value) { - for(std::size_t mode_index = 0; mode_index < modes.size(); mode_index++) + for(unsigned int mode_index = 0; mode_index < modes.size(); mode_index++) { - if (modes[mode_index].value == mode_value) + if(modes[mode_index].value == mode_value) { - return mode_index; + return(mode_index); } } - return 0; + return(0); } void RGBController_ColorfulTuringGPU::SetupZones() @@ -86,7 +96,7 @@ void RGBController_ColorfulTuringGPU::SetupZones() zone new_zone; new_zone.name = "GPU"; - new_zone.type = ZONE_TYPE_LINEAR; + new_zone.type = ZONE_TYPE_SINGLE; new_zone.leds_min = 1; new_zone.leds_max = 1; new_zone.leds_count = 1; @@ -122,10 +132,10 @@ void RGBController_ColorfulTuringGPU::DeviceUpdateLEDs() controller->SetStateDisplay(colors[0]); break; case COLORFUL_TURING_GPU_RGB_MODE_STATIC: - controller->SetDirect(colors[0]); + controller->SetDirect(colors[0], false); break; default: - controller->SetDirect(colors[0]); + controller->SetDirect(colors[0], false); } } @@ -143,3 +153,15 @@ void RGBController_ColorfulTuringGPU::DeviceUpdateMode() { DeviceUpdateLEDs(); } + +void RGBController_ColorfulTuringGPU::DeviceSaveMode() +{ + switch(modes[active_mode].value) + { + case COLORFUL_TURING_GPU_RGB_MODE_STATIC: + controller->SetDirect(colors[0], true); + break; + default: + DeviceUpdateLEDs(); + } +} diff --git a/Controllers/ColorfulTuringGPUController/RGBController_ColorfulTuringGPU.h b/Controllers/ColorfulTuringGPUController/RGBController_ColorfulTuringGPU.h index b41856ce..4b0c7a72 100644 --- a/Controllers/ColorfulTuringGPUController/RGBController_ColorfulTuringGPU.h +++ b/Controllers/ColorfulTuringGPUController/RGBController_ColorfulTuringGPU.h @@ -1,3 +1,12 @@ +/*---------------------------------------------------------*\ +| RGBController_ColorfulTuringGPU.h | +| | +| RGBController for Colorful Turing GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include "RGBController.h" @@ -15,11 +24,11 @@ public: void UpdateZoneLEDs(int zone); void UpdateSingleLED(int led); void DeviceUpdateMode(); + void DeviceSaveMode(); private: ColorfulTuringGPUController* controller; int getModeIndex(int mode_value); - }; diff --git a/Controllers/CoolerMasterController/CMARGBController/CMARGBController.cpp b/Controllers/CoolerMasterController/CMARGBController/CMARGBController.cpp new file mode 100644 index 00000000..01b2b580 --- /dev/null +++ b/Controllers/CoolerMasterController/CMARGBController/CMARGBController.cpp @@ -0,0 +1,298 @@ +/*---------------------------------------------------------*\ +| CMARGBController.cpp | +| | +| Driver for Cooler Master ARGB controller | +| | +| Chris M (Dr_No) 10 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "CMARGBController.h" +#include "StringUtils.h" + +CMARGBController::CMARGBController(hid_device* dev_handle, char *_path, unsigned char _zone_idx, std::shared_ptr cm_mutex) +{ + dev = dev_handle; + location = _path; + zone_index = _zone_idx; + mutex_ptr = cm_mutex; + + /*---------------------------------------------------------*\ + | Get device name from HID manufacturer and product strings | + \*---------------------------------------------------------*/ + wchar_t name_string[HID_MAX_STR]; + + hid_get_manufacturer_string(dev, name_string, HID_MAX_STR); + device_name = StringUtils::wstring_to_string(name_string); + + hid_get_product_string(dev, name_string, HID_MAX_STR); + device_name.append(" ").append(StringUtils::wstring_to_string(name_string)); + + GetStatus(); +} + +CMARGBController::~CMARGBController() +{ + if(mutex_ptr.use_count() <= 1) + { + hid_close(dev); + } +} + +void CMARGBController::GetStatus() +{ + unsigned char buffer[CM_ARGB_PACKET_SIZE] = { 0x00, 0x80, 0x0B, 0x01 }; + int buffer_size = (sizeof(buffer) / sizeof(buffer[0])); + int rgb_offset = 0; + int zone; + + if (argb_header_data[zone_index].digital) + { + zone = argb_header_data[zone_index].header; + buffer[CM_ARGB_COMMAND_BYTE] = 0x0B; + } + else + { + zone = 0x00; + buffer[CM_ARGB_COMMAND_BYTE] = 0x0A; + rgb_offset = 1; + } + + /*---------------------------------------------*\ + | Guard the writes to the controller until the | + | for loop has completed to avoid collisons | + \*---------------------------------------------*/ + std::lock_guard guard(*mutex_ptr); + + /*---------------------------------------------------------*\ + | If this is the group then just return the first status | + \*---------------------------------------------------------*/ + buffer[CM_ARGB_ZONE_BYTE] = ( zone > 0x08 ) ? 0x01 : zone; + hid_write(dev, buffer, buffer_size); + hid_read_timeout(dev, buffer, buffer_size, CM_ARGB_INTERRUPT_TIMEOUT); + + current_mode = buffer[4 - rgb_offset]; + bool_random = ( buffer[5 - rgb_offset] == 0x00 ); + current_speed = buffer[6 - rgb_offset]; + current_brightness = buffer[7 - rgb_offset]; + current_red = buffer[8 - rgb_offset]; + current_green = buffer[9 - rgb_offset]; + current_blue = buffer[10 - rgb_offset]; +} + +std::string CMARGBController::GetDeviceName() +{ + return(device_name); +} + +std::string CMARGBController::GetSerial() +{ + wchar_t serial_string[HID_MAX_STR]; + int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string CMARGBController::GetLocation() +{ + return("HID: " + location); +} + +unsigned char CMARGBController::GetZoneIndex() +{ + return(zone_index); +} + +unsigned char CMARGBController::GetMode() +{ + return(current_mode); +} + +unsigned char CMARGBController::GetLedRed() +{ + return(current_red); +} + +unsigned char CMARGBController::GetLedGreen() +{ + return(current_green); +} + +unsigned char CMARGBController::GetLedBlue() +{ + return(current_blue); +} + +unsigned char CMARGBController::GetLedSpeed() +{ + return(current_speed); +} + +bool CMARGBController::GetRandomColours() +{ + return(bool_random); +} + +void CMARGBController::SetLedCount(int zone, int led_count) +{ + unsigned char buffer[CM_ARGB_PACKET_SIZE] = { 0x00, 0x80, 0x0D, 0x02 }; + int buffer_size = (sizeof(buffer) / sizeof(buffer[0])); + + buffer[CM_ARGB_ZONE_BYTE] = zone; + buffer[CM_ARGB_MODE_BYTE] = led_count; + buffer[CM_ARGB_COLOUR_INDEX_BYTE] = (0x0F - led_count > 0) ? 0x0F - led_count : 0x01; + + /*---------------------------------------------*\ + | Guard the writes to the controller until the | + | for loop has completed to avoid collisons | + \*---------------------------------------------*/ + std::lock_guard guard(*mutex_ptr); + + hid_write(dev, buffer, buffer_size); +} + +void CMARGBController::SetMode(uint8_t mode, uint8_t speed, uint8_t brightness, RGBColor colour, bool random_colours) +{ + bool needs_update = !( (current_mode == mode) && (current_speed == speed) && (current_brightness == brightness) && (ToRGBColor(current_red, current_green, current_blue) == colour)); + + if (needs_update) + { + current_mode = mode; + current_speed = speed; + current_brightness = brightness; + current_red = RGBGetRValue(colour); + current_green = RGBGetGValue(colour); + current_blue = RGBGetBValue(colour); + bool_random = random_colours; + + SendUpdate(); + } +} + +void CMARGBController::SetLedsDirect(RGBColor *led_colours, unsigned int led_count) +{ + const unsigned char buffer_size = CM_ARGB_PACKET_SIZE; + unsigned char buffer[buffer_size] = { 0x00, 0x00, 0x07, 0x02 }; + unsigned char packet_count = 0; + std::vector colours; + + /*---------------------------------------------*\ + | Set up the RGB triplets to send | + \*---------------------------------------------*/ + for(unsigned int i = 0; i < led_count; i++) + { + RGBColor colour = led_colours[i]; + + colours.push_back( RGBGetRValue(colour) ); + colours.push_back( RGBGetGValue(colour) ); + colours.push_back( RGBGetBValue(colour) ); + } + + buffer[CM_ARGB_FUNCTION_BYTE] = zone_index - 1; + buffer[CM_ARGB_ZONE_BYTE] = led_count; + unsigned char buffer_idx = CM_ARGB_MODE_BYTE; + + /*---------------------------------------------*\ + | Guard the writes to the controller until the | + | for loop has completed to avoid collisons | + \*---------------------------------------------*/ + std::lock_guard guard(*mutex_ptr); + + for(std::vector::iterator it = colours.begin(); it != colours.end(); buffer_idx = CM_ARGB_COMMAND_BYTE) + { + /*-----------------------------------------------------------------*\ + | Fill the write buffer till its full or the colour buffer is empty | + \*-----------------------------------------------------------------*/ + buffer[CM_ARGB_REPORT_BYTE] = packet_count; + while (( buffer_idx < buffer_size) && ( it != colours.end() )) + { + buffer[buffer_idx] = *it; + buffer_idx++; + it++; + } + + if(it == colours.end()) + { + buffer[CM_ARGB_REPORT_BYTE] += 0x80; + } + + hid_write(dev, buffer, buffer_size); + + /*-----------------------------------------------------------------*\ + | Reset the write buffer | + \*-----------------------------------------------------------------*/ + memset(buffer, 0x00, buffer_size ); + packet_count++; + } +} + +void CMARGBController::SendUpdate() +{ + /*---------------------------------------------*\ + | Guard the writes to the controller | + \*---------------------------------------------*/ + std::lock_guard guard(*mutex_ptr); + + unsigned char buffer[CM_ARGB_PACKET_SIZE] = { 0x00 }; + int buffer_size = (sizeof(buffer) / sizeof(buffer[0])); + bool boolARGB_header = argb_header_data[zone_index].digital; + bool boolPassthru = ( current_mode == CM_ARGB_MODE_PASSTHRU ) || ( current_mode == CM_RGB_MODE_PASSTHRU ); + bool boolDirect = ( current_mode == CM_ARGB_MODE_DIRECT ); + unsigned char function = boolPassthru ? (boolARGB_header ? 0x02 : 0x04) : (boolARGB_header ? 0x01 : 0x03); + buffer[CM_ARGB_REPORT_BYTE] = 0x80; + buffer[CM_ARGB_COMMAND_BYTE] = 0x01; + + if(boolDirect) + { + buffer[CM_ARGB_FUNCTION_BYTE] = 0x01; + buffer[CM_ARGB_ZONE_BYTE] = 0x02; + + hid_write(dev, buffer, buffer_size); + hid_read_timeout(dev, buffer, buffer_size, CM_ARGB_INTERRUPT_TIMEOUT); + + /*-----------------------------------------------------------------*\ + | Direct mode is now set up and no other mode packet is required | + \*-----------------------------------------------------------------*/ + return; + } + + buffer[CM_ARGB_FUNCTION_BYTE] = function; + + hid_write(dev, buffer, buffer_size); + hid_read_timeout(dev, buffer, buffer_size, CM_ARGB_INTERRUPT_TIMEOUT); + + if(boolARGB_header) + { + buffer[CM_ARGB_COMMAND_BYTE] = 0x0B; //ARGB sends 0x0B (1011) RGB sends 0x04 (0100) + buffer[CM_ARGB_FUNCTION_BYTE] = (false) ? 0x01 : 0x02; //This controls direct mode TODO + buffer[CM_ARGB_ZONE_BYTE] = argb_header_data[zone_index].header; + buffer[CM_ARGB_MODE_BYTE] = current_mode; + buffer[CM_ARGB_COLOUR_INDEX_BYTE] = bool_random ? 0x00 : 0x10; + buffer[CM_ARGB_SPEED_BYTE] = current_speed; + buffer[CM_ARGB_BRIGHTNESS_BYTE] = current_brightness; + buffer[CM_ARGB_RED_BYTE] = current_red; + buffer[CM_ARGB_GREEN_BYTE] = current_green; + buffer[CM_ARGB_BLUE_BYTE] = current_blue; + } + else + { + buffer[CM_ARGB_COMMAND_BYTE] = boolPassthru ? 0x01 : 0x04; //ARGB sends 0x0b (1011) RGB sends 0x04 (0100) + buffer[CM_ARGB_MODE_BYTE + CM_RGB_OFFSET] = current_mode; + buffer[CM_ARGB_COLOUR_INDEX_BYTE + CM_RGB_OFFSET] = bool_random ? 0x00 : 0x10; + buffer[CM_ARGB_SPEED_BYTE + CM_RGB_OFFSET] = current_speed; + buffer[CM_ARGB_BRIGHTNESS_BYTE + CM_RGB_OFFSET] = current_brightness; + buffer[CM_ARGB_RED_BYTE + CM_RGB_OFFSET] = current_red; + buffer[CM_ARGB_GREEN_BYTE + CM_RGB_OFFSET] = current_green; + buffer[CM_ARGB_BLUE_BYTE + CM_RGB_OFFSET] = current_blue; + } + + hid_write(dev, buffer, buffer_size); + hid_read_timeout(dev, buffer, buffer_size, CM_ARGB_INTERRUPT_TIMEOUT); +} diff --git a/Controllers/CoolerMasterController/CMARGBController/CMARGBController.h b/Controllers/CoolerMasterController/CMARGBController/CMARGBController.h new file mode 100644 index 00000000..54e7d088 --- /dev/null +++ b/Controllers/CoolerMasterController/CMARGBController/CMARGBController.h @@ -0,0 +1,140 @@ +/*---------------------------------------------------------*\ +| CMARGBController.h | +| | +| Driver for Cooler Master ARGB controller | +| | +| Chris M (Dr_No) 10 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include +#include +#include "RGBController.h" //Needed to set the direct mode + +#define CM_ARGB_COLOUR_MODE_DATA_SIZE (sizeof(colour_mode_data[0]) / sizeof(colour_mode_data[0][0])) +#define CM_ARGB_HEADER_DATA_SIZE (sizeof(argb_header_data) / sizeof(argb_headers) ) +#define CM_ARGB_INTERRUPT_TIMEOUT 250 +#define CM_ARGB_PACKET_SIZE 65 +#define CM_ARGB_DEVICE_NAME_SIZE (sizeof(device_name) / sizeof(device_name[ 0 ])) +#define CM_RGB_OFFSET -2 +#define HID_MAX_STR 255 + +#define CM_ARGB_BRIGHTNESS_MAX 255 +#define CM_ARGB_FW0023 std::string("A202011171238") +#define CM_ARGB_FW0028 std::string("A202105291658") + +enum +{ + CM_ARGB_REPORT_BYTE = 1, + CM_ARGB_COMMAND_BYTE = 2, + CM_ARGB_FUNCTION_BYTE = 3, + CM_ARGB_ZONE_BYTE = 4, + CM_ARGB_MODE_BYTE = 5, + CM_ARGB_COLOUR_INDEX_BYTE = 6, + CM_ARGB_SPEED_BYTE = 7, + CM_ARGB_BRIGHTNESS_BYTE = 8, + CM_ARGB_RED_BYTE = 9, + CM_ARGB_GREEN_BYTE = 10, + CM_ARGB_BLUE_BYTE = 11 +}; + +struct argb_headers +{ + const char* name; + unsigned char header; + bool digital; + unsigned int count; +}; + +static argb_headers argb_header_data[] = +{ + { "RGB Header", 0xFE, false, 1 }, + { "Digital ARGB1", 0x01, true, 12 }, + { "Digital ARGB2", 0x02, true, 12 }, + { "Digital ARGB3", 0x04, true, 12 }, + { "Digital ARGB4", 0x08, true, 12 }, + //{ "All Digital ARGB", 0xFF, true, 12 } +}; + +enum +{ + CM_RGB_MODE_MIRAGE = 0x01, //Mirage + CM_RGB_MODE_FLASH = 0x02, //Flash + CM_RGB_MODE_BREATHING = 0x03, //Breathing + CM_RGB_MODE_STATIC = 0x05, //Static + CM_RGB_MODE_OFF = 0x06, //Turn off + CM_RGB_MODE_PASSTHRU = 0xFF //Motherboard Pass Thru Mode +}; + +enum +{ + CM_ARGB_MODE_OFF = 0x0B, //Turn off + CM_ARGB_MODE_SPECTRUM = 0x01, //Spectrum Mode + CM_ARGB_MODE_RELOAD = 0x02, //Reload Mode + CM_ARGB_MODE_RECOIL = 0x03, //Recoil Mode + CM_ARGB_MODE_BREATHING = 0x04, //Breathing Mode + CM_ARGB_MODE_REFILL = 0x05, //Refill Mode + CM_ARGB_MODE_DEMO = 0x06, //Demo Mode + CM_ARGB_MODE_FILLFLOW = 0x08, //Fill Flow Mode + CM_ARGB_MODE_RAINBOW = 0x09, //Rainbow Mode + CM_ARGB_MODE_STATIC = 0x0A, //Static Mode + CM_ARGB_MODE_DIRECT = 0xFE, //Direct Led Control + CM_ARGB_MODE_PASSTHRU = 0xFF //Motherboard Pass Thru Mode +}; + +enum +{ + CM_ARGB_SPEED_SLOWEST = 0x00, // Slowest speed + CM_ARGB_SPEED_SLOW = 0x01, // Slower speed + CM_ARGB_SPEED_NORMAL = 0x02, // Normal speed + CM_ARGB_SPEED_FAST = 0x03, // Fast speed + CM_ARGB_SPEED_FASTEST = 0x04, // Fastest speed +}; + +class CMARGBController +{ +public: + CMARGBController(hid_device* dev_handle, char *_path, unsigned char _zone_idx, std::shared_ptr cm_mutex); + ~CMARGBController(); + + std::string GetDeviceName(); + std::string GetSerial(); + std::string GetLocation(); + + unsigned char GetZoneIndex(); + unsigned char GetMode(); + unsigned char GetLedRed(); + unsigned char GetLedGreen(); + unsigned char GetLedBlue(); + unsigned char GetLedSpeed(); + bool GetRandomColours(); + void SetLedCount(int zone, int led_count); + void SetMode(uint8_t mode, uint8_t speed, uint8_t brightness, RGBColor colour, bool random_colours); + void SetLedsDirect(RGBColor * led_colours, unsigned int led_count); + +private: + std::string device_name; + std::string location; + hid_device* dev; + std::shared_ptr mutex_ptr; + + unsigned char zone_index; + unsigned char current_mode; + unsigned char current_speed; + + unsigned char current_red; + unsigned char current_green; + unsigned char current_blue; + unsigned char current_brightness; + bool bool_random; + + void GetStatus(); + void SendUpdate(); +}; diff --git a/Controllers/CoolerMasterController/RGBController_CMARGBController.cpp b/Controllers/CoolerMasterController/CMARGBController/RGBController_CMARGBController.cpp similarity index 93% rename from Controllers/CoolerMasterController/RGBController_CMARGBController.cpp rename to Controllers/CoolerMasterController/CMARGBController/RGBController_CMARGBController.cpp index 84e6850b..88b04380 100644 --- a/Controllers/CoolerMasterController/RGBController_CMARGBController.cpp +++ b/Controllers/CoolerMasterController/CMARGBController/RGBController_CMARGBController.cpp @@ -1,11 +1,13 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMARGBController.cpp | -| | -| Driver for Coolermaster ARGB Controller | -| | -| Chris M (Dr_No) 14th Oct 2020 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CMARGBController.cpp | +| | +| RGBController for Cooler Master ARGB controller | +| | +| Chris M (Dr_No) 14 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CMARGBController.h" @@ -270,7 +272,7 @@ RGBController_CMARGBController::RGBController_CMARGBController(CMARGBController* SetupZones(); int temp_mode = controller->GetMode(); - for(std::size_t mode_idx = 0; mode_idx < modes.size() ; mode_idx++) + for(int mode_idx = 0; mode_idx < (int)modes.size() ; mode_idx++) { if (temp_mode == modes[mode_idx].value) { @@ -382,7 +384,7 @@ void RGBController_CMARGBController::DeviceUpdateLEDs() { uint8_t end_zone = last_zone(cmargb->GetZoneIndex()); - for(std::size_t zone_idx = first_zone(cmargb->GetZoneIndex()); zone_idx < end_zone; zone_idx++) + for(int zone_idx = first_zone(cmargb->GetZoneIndex()); zone_idx < end_zone; zone_idx++) { UpdateZoneLEDs(zone_idx); } @@ -398,18 +400,6 @@ void RGBController_CMARGBController::UpdateSingleLED(int led) UpdateZoneLEDs(GetLED_Zone(led)); } -void RGBController_CMARGBController::SetCustomMode() -{ - for(std::size_t mode_idx = 0; mode_idx < modes.size() ; mode_idx++) - { - if (modes[mode_idx].value == CM_ARGB_MODE_DIRECT) - { - active_mode = mode_idx; - break; - } - } -} - void RGBController_CMARGBController::DeviceUpdateMode() { bool random_colours = (modes[active_mode].color_mode == MODE_COLORS_RANDOM); @@ -423,12 +413,12 @@ int RGBController_CMARGBController::GetLED_Zone(int led_idx) /*---------------------------------------------------------*\ | This may be more useful in the abstract RGBController.cpp | \*---------------------------------------------------------*/ - for(size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + for(int zone_idx = 0; zone_idx < (int)zones.size(); zone_idx++) { int zone_start = zones[zone_idx].start_idx; int zone_end = zone_start + zones[zone_idx].leds_count - 1; - if( zone_start <= led_idx && zone_end >= led_idx) + if(zone_start <= led_idx && zone_end >= led_idx) { return(zone_idx); } diff --git a/Controllers/CoolerMasterController/CMARGBController/RGBController_CMARGBController.h b/Controllers/CoolerMasterController/CMARGBController/RGBController_CMARGBController.h new file mode 100644 index 00000000..b42bdedf --- /dev/null +++ b/Controllers/CoolerMasterController/CMARGBController/RGBController_CMARGBController.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------*\ +| RGBController_CMARGBController.h | +| | +| RGBController for Cooler Master ARGB controller | +| | +| Chris M (Dr_No) 14 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "CMARGBController.h" + +#define first_zone(zn) ((zones.size() > 1) ? 1 : 0) +#define last_zone(zn) ((zones.size() > 1) ? 4 : 1) + +class RGBController_CMARGBController : public RGBController +{ +public: + RGBController_CMARGBController(CMARGBController* controller_ptr); + ~RGBController_CMARGBController(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + void Init_Controller(); + int GetDeviceMode(); + int GetLED_Zone(int led_idx); + + CMARGBController* controller; +}; diff --git a/Controllers/CoolerMasterController/CMARGBGen2A1Controller/CMARGBGen2A1Controller.cpp b/Controllers/CoolerMasterController/CMARGBGen2A1Controller/CMARGBGen2A1Controller.cpp new file mode 100644 index 00000000..5e7683eb --- /dev/null +++ b/Controllers/CoolerMasterController/CMARGBGen2A1Controller/CMARGBGen2A1Controller.cpp @@ -0,0 +1,384 @@ +/*---------------------------------------------------------*\ +| CMARGBGen2A1Controller.cpp | +| | +| Driver for Cooler Master ARGB Gen 2 A1 controller | +| | +| Morgan Guimard (morg) 26 Jun 2022 | +| Fabian R (kderazorback) 11 Aug 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "CMARGBGen2A1Controller.h" +#include "StringUtils.h" + +CMARGBGen2A1controller::CMARGBGen2A1controller(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) +{ + dev = dev_handle; + location = info.path; + name = dev_name; + + /*---------------------------------------------*\ + | Setup direct mode on start | + \*---------------------------------------------*/ + SetupDirectMode(); +} + +CMARGBGen2A1controller::~CMARGBGen2A1controller() +{ + hid_close(dev); +} + +std::string CMARGBGen2A1controller::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string CMARGBGen2A1controller::GetNameString() +{ + return(name); +} + +std::string CMARGBGen2A1controller::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void CMARGBGen2A1controller::SaveToFlash() +{ + unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; + + memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; + usb_buf[2] = CM_ARGB_GEN2_A1_FLASH; + usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; + + hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_LONG)); +} + +void CMARGBGen2A1controller::SetupDirectMode() +{ + ResetDevice(); + + unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; + + /*---------------------------------------------*\ + | Swith to direct mode | + \*---------------------------------------------*/ + usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; + usb_buf[2] = CM_ARGB_GEN2_A1_HW_MODE_SETUP; + usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; + usb_buf[4] = CM_ARGB_GEN2_A1_CHANNEL_ALL; // CHANNEL + usb_buf[5] = CM_ARGB_GEN2_A1_SUBCHANNEL_ALL; // SUBCHANNEL + usb_buf[6] = CM_ARGB_GEN2_A1_CUSTOM_MODE; + usb_buf[7] = CM_ARGB_GEN2_A1_SPEED_HALF; + usb_buf[8] = CM_ARGB_GEN2_A1_BRIGHTNESS_MAX; + usb_buf[9] = 0xFF; // R + usb_buf[10] = 0xFF; // G + usb_buf[11] = 0xFF; // B + + hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_SHORT)); + + std::vector colorOffChain; + colorOffChain.push_back(0); + for(unsigned int channel = 0; channel < CM_ARGB_GEN2_A1_CHANNEL_COUNT; channel++) + { + SendChannelColors(channel, CM_ARGB_GEN2_A1_SUBCHANNEL_ALL, colorOffChain); + } + + for(unsigned int channel = 0; channel < CM_ARGB_GEN2_A1_CHANNEL_COUNT; channel++) + { + SetCustomSequence(channel); + } + + software_mode_activated = true; +} + +void CMARGBGen2A1controller::SetupZoneSize(unsigned int zone_id, unsigned int size) +{ + /*---------------------------------------------*\ + | Set the mode sequence to full static | + | (01 for static) | + | | + | This device stores 2 distinct values | + | - effect speed | + | - approximated zone size | + | | + | It's probably based on standard ARGB sizes | + | Still, the 06 value has some mystery. | + | | + | ES= effect speed | + | LC= LEDs count | + | | + | ES LC | + | ----- | + | 0a 06 | + | 09 06 | + | 08 07 | + | 07 08 | + | 06 0a | + | 05 0c | + | 04 0f | + | 03 14 | + | 02 1e | + | 01 3c | + \*---------------------------------------------*/ + + const unsigned char gaps[10] = + { + 0x05, 0x06, 0x07, 0x08, 0x0A, 0x0C, 0x0F, 0x14, 0x1E, 0x3C + }; + + unsigned char speed = 0x0A; + + for(unsigned int g = 0; g < 10; g++) + { + if(size <= gaps[g]) + { + break; + } + + speed--; + } + + unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; + + memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; + usb_buf[2] = CM_ARGB_GEN2_A1_SIZES; + usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; + usb_buf[4] = 1 << zone_id; + + usb_buf[5] = speed; + usb_buf[6] = size; + + hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_LONG)); + + /*---------------------------------------------*\ + | Refresh direct mode to cycle the strips | + | with the new length | + \*---------------------------------------------*/ + if(software_mode_activated) + { + SetupDirectMode(); + } +} + +void CMARGBGen2A1controller::SendChannelColors(unsigned int zone_id, unsigned int subchannel_id, std::vector colors) +{ + /*---------------------------------------------*\ + | Create the color data array | + \*---------------------------------------------*/ + std::vector color_data = CreateColorData(colors); + + std::vector::iterator it = color_data.begin(); + + unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; + + unsigned int offset; + + /*----------------------------------------------------*\ + | Break-up color data in packet/s | + | Intentionally clearing first packet only | + | Leaving garbage on subsequent packets | + | Original software appears to not clear them anyways. | + \*----------------------------------------------------*/ + memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); + for(unsigned int p = 0; p < CM_ARGB_GEN2_A1_PACKETS_PER_CHANNEL && it != color_data.end(); p++) + { + offset = 1; + + usb_buf[offset++] = p; + usb_buf[offset++] = CM_ARGB_GEN2_A1_SET_RGB_VALUES; + usb_buf[offset++] = CM_ARGB_GEN2_A1_WRITE; + usb_buf[offset++] = 1 << zone_id; + usb_buf[offset++] = 1 << subchannel_id; + + while(it != color_data.end() && offset < CM_ARGB_GEN2_A1_PACKET_LENGTH) + { + usb_buf[offset++] = *it; + it++; + } + + if(p >= CM_ARGB_GEN2_A1_PACKETS_PER_CHANNEL - 1 || it == color_data.end()) + { + /*--------------------------*\ + | Rewrite as end packet | + \*--------------------------*/ + usb_buf[1] = p + 0x80; + } + + hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + /*-----------------------------------------------*\ + | This device needs some delay before we send | + | any other packet :( | + | This time is critical since the device is | + | still latching its input buffer. | + | Reducing this may start to introduce artifacts | + \*-----------------------------------------------*/ + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_MEDIUM)); + } + + /*---------------------------------------------*\ + | Next channel needs some delay as well | + \*---------------------------------------------*/ + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_SHORT)); +} + +void CMARGBGen2A1controller::SetMode(unsigned int mode_value, unsigned char speed, unsigned char brightness, RGBColor color, bool random) +{ + unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; + + /*---------------------------------------------*\ + | Switch to hardware mode if needed | + \*---------------------------------------------*/ + if(software_mode_activated) + { + memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; + usb_buf[2] = CM_ARGB_GEN2_A1_LIGHTNING_CONTROL; + usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; + + hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + software_mode_activated = false; + + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_LONG)); + } + + /*---------------------------------------------*\ + | Set the mode values and write to the device | + \*---------------------------------------------*/ + memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; + usb_buf[2] = CM_ARGB_GEN2_A1_HW_MODE_SETUP; + usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; + + usb_buf[4] = CM_ARGB_GEN2_A1_CHANNEL_ALL; + usb_buf[5] = CM_ARGB_GEN2_A1_SUBCHANNEL_ALL; + + usb_buf[6] = mode_value; + + bool is_custom_mode = (mode_value == CM_ARGB_GEN2_A1_CUSTOM_MODE); + + if(is_custom_mode) + { + usb_buf[7] = CM_ARGB_GEN2_A1_SPEED_MAX; + usb_buf[8] = CM_ARGB_GEN2_A1_BRIGHTNESS_MAX; + usb_buf[9] = 0xFF; // R + usb_buf[10] = 0xFF; // G + usb_buf[11] = 0xFF; // B + } + else + { + usb_buf[7] = speed; + usb_buf[8] = brightness; + usb_buf[9] = RGBGetRValue(color); + usb_buf[10] = RGBGetGValue(color); + usb_buf[11] = RGBGetBValue(color); + usb_buf[12] = random; + } + + hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_LONG)); + + if(is_custom_mode) + { + for(unsigned int channel = 0; channel < CM_ARGB_GEN2_A1_CHANNEL_COUNT; channel++) + { + SetCustomSequence(channel); + } + } +} + +std::vector CMARGBGen2A1controller::CreateColorData(std::vector colors) +{ + std::vector color_data; + + for(unsigned int c = 0; c < colors.size(); c++) + { + color_data.push_back(RGBGetRValue(colors[c])); + color_data.push_back(RGBGetGValue(colors[c])); + color_data.push_back(RGBGetBValue(colors[c])); + } + + return(color_data); +} + +void CMARGBGen2A1controller::SetCustomSequence(unsigned int zone_id) +{ + unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; + + /*---------------------------------------------*\ + | Set custom speed for sequence mode | + \*---------------------------------------------*/ + memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; + usb_buf[2] = CM_ARGB_GEN2_A1_CUSTOM_SPEED; + usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; + usb_buf[4] = 1 << zone_id; // CHANNEL + usb_buf[5] = 0x32; + + hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_SHORT)); + + SetPipelineStaticSequence(zone_id); +} + +void CMARGBGen2A1controller::SetPipelineStaticSequence(unsigned int zone_id) +{ + /*------------------------------------------------*\ + | Set the mode sequence to full static | + | All steps on the effect pipeline to 0x01 STATIC | + \*------------------------------------------------*/ + unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; + memset(usb_buf, CM_ARGB_GEN2_A1_STATIC_MODE, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + usb_buf[0] = 0x00; + usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; + usb_buf[2] = CM_ARGB_GEN2_A1_CUSTOM_SEQUENCES; + usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; + usb_buf[4] = 1 << zone_id; + + hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_LONG)); +} + +void CMARGBGen2A1controller::ResetDevice() +{ + unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; + + memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); + usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; + usb_buf[2] = CM_ARGB_GEN2_A1_RESET; + usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; + + hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); + + std::this_thread::sleep_for(std::chrono::milliseconds(CM_ARGB_GEN2_A1_SLEEP_LONG)); +} diff --git a/Controllers/CoolerMasterController/CMARGBGen2A1Controller/CMARGBGen2A1Controller.h b/Controllers/CoolerMasterController/CMARGBGen2A1Controller/CMARGBGen2A1Controller.h new file mode 100644 index 00000000..7b30ee32 --- /dev/null +++ b/Controllers/CoolerMasterController/CMARGBGen2A1Controller/CMARGBGen2A1Controller.h @@ -0,0 +1,113 @@ +/*---------------------------------------------------------*\ +| CMARGBGen2A1Controller.h | +| | +| Driver for Cooler Master ARGB Gen 2 A1 controller | +| | +| Morgan Guimard (morg) 26 Jun 2022 | +| Fabian R (kderazorback) 11 Aug 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define CM_ARGB_GEN2_A1_PACKET_LENGTH 65 +#define CM_ARGB_GEN2_A1_CHANNEL_MAX_SIZE 72 +#define CM_ARGB_GEN2_A1_CHANNEL_COUNT 3 +#define CM_ARGB_GEN2_A1_PACKETS_PER_CHANNEL 2 + +#define CM_ARGB_GEN2_A1_SLEEP_SHORT 5 +#define CM_ARGB_GEN2_A1_SLEEP_MEDIUM 45 +#define CM_ARGB_GEN2_A1_SLEEP_LONG 70 + +enum +{ + CM_ARGB_GEN2_A1_DIRECT_MODE = 0xFF, + CM_ARGB_GEN2_A1_SPECTRUM_MODE = 0x00, + CM_ARGB_GEN2_A1_STATIC_MODE = 0x01, + CM_ARGB_GEN2_A1_RELOAD_MODE = 0x02, + CM_ARGB_GEN2_A1_RECOIL_MODE = 0x03, + CM_ARGB_GEN2_A1_BREATHING_MODE = 0x04, + CM_ARGB_GEN2_A1_REFILL_MODE = 0x05, + CM_ARGB_GEN2_A1_DEMO_MODE = 0x06, + CM_ARGB_GEN2_A1_FILL_FLOW_MODE = 0x07, + CM_ARGB_GEN2_A1_RAINBOW_MODE = 0x08, + CM_ARGB_GEN2_A1_CUSTOM_MODE = 0xC0, + CM_ARGB_GEN2_A1_OFF_MODE = 0x09 +}; + +enum +{ + CM_ARGB_GEN2_A1_BRIGHTNESS_MAX = 0xFF, + CM_ARGB_GEN2_A1_BRIGHTNESS_MIN = 0x00, + CM_ARGB_GEN2_A1_SPEED_MAX = 0x04, + CM_ARGB_GEN2_A1_SPEED_HALF = 0x02, + CM_ARGB_GEN2_A1_SPEED_MIN = 0x00, +}; + +enum +{ + CM_ARGB_GEN2_A1_COMMAND = 0x80, + CM_ARGB_GEN2_A1_COMMAND_EXTRA_1 = 0x81, + CM_ARGB_GEN2_A1_COMMAND_EXTRA_2 = 0x82, + CM_ARGB_GEN2_A1_READ = 0x01, + CM_ARGB_GEN2_A1_WRITE = 0x02, + CM_ARGB_GEN2_A1_RESPONSE = 0x03 +}; + +enum +{ + CM_ARGB_GEN2_A1_SIZES = 0x06, + CM_ARGB_GEN2_A1_SET_RGB_VALUES = 0x08, + CM_ARGB_GEN2_A1_FLASH = 0x0B, + CM_ARGB_GEN2_A1_IDENTIFY = 0x0A, + CM_ARGB_GEN2_A1_LIGHTNING_CONTROL = 0x01, + CM_ARGB_GEN2_A1_HW_MODE_SETUP = 0x03, + CM_ARGB_GEN2_A1_CUSTOM_SEQUENCES = 0x10, + CM_ARGB_GEN2_A1_CUSTOM_SPEED = 0x11, + CM_ARGB_GEN2_A1_RESET = 0xC0, + CM_ARGB_GEN2_A1_APPLY_CHANGES = 0xB0 +}; + +enum +{ + CM_ARGB_GEN2_A1_CHANNEL_A = 0x01, + CM_ARGB_GEN2_A1_CHANNEL_B = 0x02, + CM_ARGB_GEN2_A1_CHANNEL_C = 0x04, + CM_ARGB_GEN2_A1_CHANNEL_ALL = 0xFF, + CM_ARGB_GEN2_A1_SUBCHANNEL_ALL = 0xFF +}; + +class CMARGBGen2A1controller +{ +public: + CMARGBGen2A1controller(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~CMARGBGen2A1controller(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SendChannelColors(unsigned int zone_id, unsigned int subchannel_id, std::vector colors); + void SetupZoneSize(unsigned int zone_id, unsigned int size); + void SetupDirectMode(); + void SetMode(unsigned int mode_value, unsigned char speed, unsigned char brightness, RGBColor color, bool random); + void SetCustomColors(unsigned int zone_id, std::vector colors); + void SaveToFlash(); + +private: + std::string location; + std::string name; + bool software_mode_activated = false; + hid_device* dev; + + void SetCustomSequence(unsigned int zone_id); + void SetPipelineStaticSequence(unsigned int zone_id); + std::vector CreateColorData(std::vector colors); + void ResetDevice(); +}; diff --git a/Controllers/CoolerMasterController/RGBController_CMARGBGen2A1Controller.cpp b/Controllers/CoolerMasterController/CMARGBGen2A1Controller/RGBController_CMARGBGen2A1Controller.cpp similarity index 75% rename from Controllers/CoolerMasterController/RGBController_CMARGBGen2A1Controller.cpp rename to Controllers/CoolerMasterController/CMARGBGen2A1Controller/RGBController_CMARGBGen2A1Controller.cpp index fe62f7c3..704b97cb 100644 --- a/Controllers/CoolerMasterController/RGBController_CMARGBGen2A1Controller.cpp +++ b/Controllers/CoolerMasterController/CMARGBGen2A1Controller/RGBController_CMARGBGen2A1Controller.cpp @@ -1,16 +1,18 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMARGBGen2A1Controller.cpp | -| | -| Driver for Coolermaster ARGB Gen 2 A1 USB Controller | -| | -| morg (Morgan Guimard) 6/26/2022 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CMARGBGen2A1Controller.cpp | +| | +| Driver for Cooler Master ARGB Gen 2 A1 controller | +| | +| Morgan Guimard (morg) 26 Jun 2022 | +| Fabian R (kderazorback) 11 Aug 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_CMARGBGen2A1Controller.h" - -#include #include +#include +#include "RGBController_CMARGBGen2A1Controller.h" /**------------------------------------------------------------------*\ @name Coolermaster ARGB A1 @@ -20,21 +22,26 @@ @direct :white_check_mark: @effects :white_check_mark: @detectors DetectCoolerMasterARGBGen2A1 - @comment This device does not have Gen 2 support in OpenRGB yet. + @comment OpenRGB partially supports Gen 2 protocol for this device. - Gen2 has auto-resize feature and parallel to serial magical stuff.< + Gen2 has auto-resize feature and parallel to serial magical stuff, + Strip size is auto detected by the controller but not reported + back to OpenRGB. Configure zones and segments for each channel + to allow individual addressing. + Take note that this controller is extremely slow, using fast + update rates may introduce color artifacts.< \*-------------------------------------------------------------------*/ RGBController_CMARGBGen2A1Controller::RGBController_CMARGBGen2A1Controller(CMARGBGen2A1controller* controller_ptr) { controller = controller_ptr; - name = "CoolerMaster LED Controller A1"; + + name = controller->GetNameString(); vendor = "CoolerMaster"; type = DEVICE_TYPE_LEDSTRIP; - description = name; + description = "CoolerMaster LED Controller A1 Device"; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); - version = ""; mode Direct; Direct.name = "Direct"; @@ -148,16 +155,16 @@ RGBController_CMARGBGen2A1Controller::RGBController_CMARGBGen2A1Controller(CMARG modes.push_back(FillFlow); mode Rainbow; - Rainbow.name = "Rainbow"; - Rainbow.value = CM_ARGB_GEN2_A1_RAINBOW_MODE; - Rainbow.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE;; - Rainbow.color_mode = MODE_COLORS_NONE; - Rainbow.brightness = CM_ARGB_GEN2_A1_BRIGHTNESS_MAX; - Rainbow.brightness_min = CM_ARGB_GEN2_A1_BRIGHTNESS_MIN; - Rainbow.brightness_max = CM_ARGB_GEN2_A1_BRIGHTNESS_MAX; - Rainbow.speed = CM_ARGB_GEN2_A1_SPEED_MAX/2; - Rainbow.speed_min = CM_ARGB_GEN2_A1_SPEED_MIN; - Rainbow.speed_max = CM_ARGB_GEN2_A1_SPEED_MAX; + Rainbow.name = "Rainbow"; + Rainbow.value = CM_ARGB_GEN2_A1_RAINBOW_MODE; + Rainbow.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE;; + Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.brightness = CM_ARGB_GEN2_A1_BRIGHTNESS_MAX; + Rainbow.brightness_min = CM_ARGB_GEN2_A1_BRIGHTNESS_MIN; + Rainbow.brightness_max = CM_ARGB_GEN2_A1_BRIGHTNESS_MAX; + Rainbow.speed = CM_ARGB_GEN2_A1_SPEED_MAX/2; + Rainbow.speed_min = CM_ARGB_GEN2_A1_SPEED_MIN; + Rainbow.speed_max = CM_ARGB_GEN2_A1_SPEED_MAX; modes.push_back(Rainbow); mode Custom; @@ -216,7 +223,6 @@ void RGBController_CMARGBGen2A1Controller::ResizeZone(int zone, int new_size) { zones[zone].leds_count = new_size; - // todo: refactor with above code unsigned int total_leds = 0; for(unsigned int channel = 0; channel < CM_ARGB_GEN2_A1_CHANNEL_COUNT; channel++) @@ -240,12 +246,23 @@ void RGBController_CMARGBGen2A1Controller::DeviceUpdateLEDs() { for(unsigned int channel = 0; channel < CM_ARGB_GEN2_A1_CHANNEL_COUNT; channel ++) { - UpdateZoneLEDs(channel); + if (zones[channel].segments.size() > 0) + { + unsigned int i = 0; + for(std::vector::iterator it = zones[channel].segments.begin(); it != zones[channel].segments.end(); it++) + { + UpdateSegmentLEDs(channel, i++); + } + } + else + { + UpdateSegmentLEDs(channel, CM_ARGB_GEN2_A1_SUBCHANNEL_ALL); + } } } void RGBController_CMARGBGen2A1Controller::UpdateZoneLEDs(int zone) -{ +{ if(zones[zone].leds_count > 0) { unsigned int start = zones[zone].start_idx; @@ -253,25 +270,43 @@ void RGBController_CMARGBGen2A1Controller::UpdateZoneLEDs(int zone) std::vector zone_colors(colors.begin() + start , colors.begin() + end); - if(modes[active_mode].value == CM_ARGB_GEN2_A1_DIRECT_MODE) - { - controller->SendDirectChannel(zone, zone_colors); - } - else - { - controller->SetCustomColors(zone, zone_colors); - } + controller->SendChannelColors(zone, CM_ARGB_GEN2_A1_SUBCHANNEL_ALL, zone_colors); } } -void RGBController_CMARGBGen2A1Controller::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); +void RGBController_CMARGBGen2A1Controller::UpdateSegmentLEDs(int zone, int subchannel) +{ + if(zones[zone].leds_count <= 0) + { + return; + } + + unsigned int start = zones[zone].start_idx; + unsigned int end = start + zones[zone].leds_count; + bool use_direct_mode = modes[active_mode].value == CM_ARGB_GEN2_A1_DIRECT_MODE || modes[active_mode].value == CM_ARGB_GEN2_A1_CUSTOM_MODE; + + std::vector color_vector(colors.begin() + start, colors.begin() + start + end); + + if(use_direct_mode) + { + if(zones[zone].segments.size() > 0) + { + start += zones[zone].segments[subchannel].start_idx; + end += zones[zone].segments[subchannel].start_idx + zones[zone].segments[subchannel].leds_count; + + color_vector = std::vector(colors.begin() + start , colors.begin() + end); + } + + controller->SendChannelColors(zone, subchannel, color_vector); + return; + } + + controller->SendChannelColors(zone, CM_ARGB_GEN2_A1_SUBCHANNEL_ALL, color_vector); } -void RGBController_CMARGBGen2A1Controller::SetCustomMode() +void RGBController_CMARGBGen2A1Controller::UpdateSingleLED(int /*led*/) { - active_mode = 0; + DeviceUpdateLEDs(); } void RGBController_CMARGBGen2A1Controller::DeviceUpdateMode() diff --git a/Controllers/CoolerMasterController/CMARGBGen2A1Controller/RGBController_CMARGBGen2A1Controller.h b/Controllers/CoolerMasterController/CMARGBGen2A1Controller/RGBController_CMARGBGen2A1Controller.h new file mode 100644 index 00000000..49fb613c --- /dev/null +++ b/Controllers/CoolerMasterController/CMARGBGen2A1Controller/RGBController_CMARGBGen2A1Controller.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_CMARGBGen2A1Controller.h | +| | +| Driver for Cooler Master ARGB Gen 2 A1 controller | +| | +| Morgan Guimard (morg) 26 Jun 2022 | +| Fabian R (kderazorback) 11 Aug 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "CMARGBGen2A1Controller.h" + +class RGBController_CMARGBGen2A1Controller : public RGBController +{ +public: + RGBController_CMARGBGen2A1Controller(CMARGBGen2A1controller* controller_ptr); + ~RGBController_CMARGBGen2A1Controller(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSegmentLEDs(int zone, int subchannel); + void UpdateSingleLED(int led); + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + CMARGBGen2A1controller* controller; +}; diff --git a/Controllers/CoolerMasterController/CMARGBGen2A1controller.cpp b/Controllers/CoolerMasterController/CMARGBGen2A1controller.cpp deleted file mode 100644 index a845a98c..00000000 --- a/Controllers/CoolerMasterController/CMARGBGen2A1controller.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/*-------------------------------------------------------------------*\ -| CMARGBGen2A1controller.cpp | -| | -| Driver for Coolermaster ARGB Gen 2 A1 USB Controller | -| | -| morg (Morgan Guimard) 6/26/2022 | -| | -\*-------------------------------------------------------------------*/ - -#include "CMARGBGen2A1controller.h" -#include - -CMARGBGen2A1controller::CMARGBGen2A1controller(hid_device* dev_handle, const hid_device_info& info) -{ - dev = dev_handle; - location = info.path; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } - - /*---------------------------------------------*\ - | Setup direct mode on start | - \*---------------------------------------------*/ - SetupDirectMode(); -} - -CMARGBGen2A1controller::~CMARGBGen2A1controller() -{ - hid_close(dev); -} - -std::string CMARGBGen2A1controller::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string CMARGBGen2A1controller::GetSerialString() -{ - return(serial_number); -} - -void CMARGBGen2A1controller::SaveToFlash() -{ - unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; - - memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; - usb_buf[2] = CM_ARGB_GEN2_A1_FLASH; - usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; - - hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - std::this_thread::sleep_for(std::chrono::milliseconds(10)); -} - -void CMARGBGen2A1controller::SetupDirectMode() -{ - unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; - - /*---------------------------------------------*\ - | Swith to direct mode | - \*---------------------------------------------*/ - memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; - usb_buf[2] = CM_ARGB_GEN2_A1_LIGHTNING_CONTROL; - usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; - usb_buf[4] = 0x01; // channel??? - - hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - - software_mode_activated = true; -} - -void CMARGBGen2A1controller::SetupZoneSize(unsigned int zone_id, unsigned int size) -{ - /*---------------------------------------------*\ - | Set the mode sequence to full static | - | (01 for static) | - | | - | This device stores 2 distinct values | - | - effect speed | - | - approximated zone size | - | | - | It's probably based on standard ARGB sizes | - | Still, the 06 value has some mystery. | - | | - | ES= effect speed | - | LC= LEDs count | - | | - | ES LC | - | ----- | - | 0a 06 | - | 09 06 | - | 08 07 | - | 07 08 | - | 06 0a | - | 05 0c | - | 04 0f | - | 03 14 | - | 02 1e | - | 01 3c | - \*---------------------------------------------*/ - - const unsigned char gaps[10] = - { - 0x05, 0x06, 0x07, 0x08, 0x0A, 0x0C, 0x0F, 0x14, 0x1E, 0x3C - }; - - unsigned char speed = 0x0A; - - for(unsigned int g = 0; g < 10; g++) - { - if(size <= gaps[g]) - { - break; - } - - speed--; - } - - unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; - - memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; - usb_buf[2] = CM_ARGB_GEN2_A1_SIZES; - usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; - usb_buf[4] = 1 << zone_id; - - usb_buf[5] = speed; - usb_buf[6] = size; - - hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - std::this_thread::sleep_for(std::chrono::milliseconds(10)); -} - -void CMARGBGen2A1controller::SendDirectChannel(unsigned int zone_id, std::vector colors) -{ - /*---------------------------------------------*\ - | Create the color data array | - \*---------------------------------------------*/ - std::vector color_data = CreateColorData(colors); - - std::vector::iterator it = color_data.begin(); - - unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; - - unsigned int offset; - - unsigned char packet_start[CM_ARGB_GEN2_A1_PACKETS_PER_CHANNEL] = - { - 0x00, 0x01, 0x82 - }; - - /*---------------------------------------------*\ - | Send 3 packets for the zone | - \*---------------------------------------------*/ - for(unsigned int p = 0; p < CM_ARGB_GEN2_A1_PACKETS_PER_CHANNEL; p++) - { - memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - usb_buf[1] = packet_start[p]; - usb_buf[2] = 0x09; - - if(p == 0) - { - usb_buf[3] = 1 << zone_id; - usb_buf[5] = 0x3C; - - offset = 6; - } - else - { - offset = 3; - } - - while(offset < CM_ARGB_GEN2_A1_PACKET_LENGTH && it != color_data.end()) - { - usb_buf[offset] = *it; - offset++; - it++; - } - - hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - /*---------------------------------------------*\ - | This device needs some delay before we send | - | any other packet | - \*---------------------------------------------*/ - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - } - - /*---------------------------------------------*\ - | Next channel needs some delay as well | - \*---------------------------------------------*/ - std::this_thread::sleep_for(std::chrono::milliseconds(2)); -} - -void CMARGBGen2A1controller::SetMode(unsigned int mode_value, unsigned char speed, unsigned char brightness, RGBColor color, bool random) -{ - unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; - - /*---------------------------------------------*\ - | Switch to hardware mode if needed | - \*---------------------------------------------*/ - if(software_mode_activated) - { - memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; - usb_buf[2] = CM_ARGB_GEN2_A1_LIGHTNING_CONTROL; - usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; - - hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - software_mode_activated = false; - - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - - /*---------------------------------------------*\ - | Set the mode values and write to the device | - \*---------------------------------------------*/ - memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; - usb_buf[2] = CM_ARGB_GEN2_A1_HW_MODE_SETUP; - usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; - - usb_buf[4] = 0xFF; - usb_buf[5] = 0xFF; - - usb_buf[6] = mode_value; - - bool is_custom_mode = mode_value == CM_ARGB_GEN2_A1_CUSTOM_MODE; - - if(is_custom_mode) - { - usb_buf[8] = 0xFF; - } - else - { - usb_buf[7] = speed; - usb_buf[8] = brightness; - usb_buf[9] = RGBGetRValue(color); - usb_buf[10] = RGBGetGValue(color); - usb_buf[11] = RGBGetBValue(color); - usb_buf[12] = random; - } - - - hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - - if(is_custom_mode) - { - for(unsigned int channel = 0; channel < CM_ARGB_GEN2_A1_CHANNEL_COUNT; channel++) - { - SetCustomSequence(channel); - } - } -} - -std::vector CMARGBGen2A1controller::CreateColorData(std::vector colors) -{ - std::vector color_data; - - for(unsigned int c = 0; c < colors.size(); c++) - { - color_data.push_back(RGBGetRValue(colors[c])); - color_data.push_back(RGBGetGValue(colors[c])); - color_data.push_back(RGBGetBValue(colors[c])); - } - - return color_data; -} - - -void CMARGBGen2A1controller::SetCustomColors(unsigned int zone_id, std::vector colors) -{ - unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; - - /*---------------------------------------------*\ - | Create the color data array | - \*---------------------------------------------*/ - std::vector color_data = CreateColorData(colors); - - std::vector::iterator it = color_data.begin(); - - unsigned char packet_start[5] = - { - CM_ARGB_GEN2_A1_COMMAND, 0x00, 0x01, 0x02, 0x83 - }; - - /*---------------------------------------------*\ - | Send the 5 packets of colors | - \*---------------------------------------------*/ - for(unsigned int p = 0; p < 5; p++) - { - memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - usb_buf[1] = packet_start[p]; - - /*----------------------------------------------*\ - | This part isnt well understood | - | 1st packet starts with CM_ARGB_GEN2_A1_COMMAND | - | Looks like it is a read command | - \*----------------------------------------------*/ - usb_buf[2] = p == 0 ? 0x06 : 0x08; // 0x08 custom data, 0x06 sizes? - usb_buf[3] = p == 0 ? 0x01 : 0x02; // read/write has no meaning here - - usb_buf[4] = 1 << zone_id; - - unsigned int offset = 6; - - while(p > 0 && offset < CM_ARGB_GEN2_A1_PACKET_LENGTH && it != color_data.end()) - { - usb_buf[offset] = *it; - offset++; - it++; - } - - hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - std::this_thread::sleep_for(std::chrono::milliseconds(20)); - } - -} - -void CMARGBGen2A1controller::SetCustomSequence(unsigned int zone_id) -{ - unsigned char usb_buf[CM_ARGB_GEN2_A1_PACKET_LENGTH]; - - const unsigned char static_seq = 0x01; - - /*---------------------------------------------*\ - | Set the mode sequence to full static | - | (01 for static) | - \*---------------------------------------------*/ - memset(usb_buf, 0x00, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - usb_buf[1] = CM_ARGB_GEN2_A1_COMMAND; - usb_buf[2] = CM_ARGB_GEN2_A1_CUSTOM_SEQUENCES; - usb_buf[3] = CM_ARGB_GEN2_A1_WRITE; - usb_buf[4] = 1 << zone_id; - - usb_buf[5] = static_seq; - usb_buf[6] = static_seq; - usb_buf[7] = static_seq; - usb_buf[8] = static_seq; - usb_buf[9] = static_seq; - usb_buf[10] = static_seq; - - hid_write(dev, usb_buf, CM_ARGB_GEN2_A1_PACKET_LENGTH); - - std::this_thread::sleep_for(std::chrono::milliseconds(10)); -} diff --git a/Controllers/CoolerMasterController/CMARGBGen2A1controller.h b/Controllers/CoolerMasterController/CMARGBGen2A1controller.h deleted file mode 100644 index 5da345b8..00000000 --- a/Controllers/CoolerMasterController/CMARGBGen2A1controller.h +++ /dev/null @@ -1,89 +0,0 @@ -/*-------------------------------------------------------------------*\ -| CMARGBGen2A1controller.h | -| | -| Driver for Coolermaster ARGB Gen 2 A1 USB Controller | -| | -| morg (Morgan Guimard) 6/26/2022 | -| | -\*-------------------------------------------------------------------*/ - -#include "RGBController.h" -#include -#include - -#pragma once - -#define CM_ARGB_GEN2_A1_PACKET_LENGTH 65 -#define CM_ARGB_GEN2_A1_CHANNEL_MAX_SIZE 48 -#define CM_ARGB_GEN2_A1_CHANNEL_COUNT 3 -#define CM_ARGB_GEN2_A1_PACKETS_PER_CHANNEL 3 - -enum -{ - CM_ARGB_GEN2_A1_DIRECT_MODE = 0xFF, - CM_ARGB_GEN2_A1_SPECTRUM_MODE = 0x00, - CM_ARGB_GEN2_A1_STATIC_MODE = 0x01, - CM_ARGB_GEN2_A1_RELOAD_MODE = 0x02, - CM_ARGB_GEN2_A1_RECOIL_MODE = 0x03, - CM_ARGB_GEN2_A1_BREATHING_MODE = 0x04, - CM_ARGB_GEN2_A1_REFILL_MODE = 0x05, - CM_ARGB_GEN2_A1_DEMO_MODE = 0x06, - CM_ARGB_GEN2_A1_FILL_FLOW_MODE = 0x07, - CM_ARGB_GEN2_A1_RAINBOW_MODE = 0x08, - CM_ARGB_GEN2_A1_CUSTOM_MODE = 0xC0, - CM_ARGB_GEN2_A1_OFF_MODE = 0x09 -}; - -enum -{ - CM_ARGB_GEN2_A1_BRIGHTNESS_MAX = 0xFF, - CM_ARGB_GEN2_A1_BRIGHTNESS_MIN = 0x00, - CM_ARGB_GEN2_A1_SPEED_MAX = 0x04, - CM_ARGB_GEN2_A1_SPEED_MIN = 0x00, -}; - -enum -{ - CM_ARGB_GEN2_A1_COMMAND = 0x80, - CM_ARGB_GEN2_A1_READ = 0x01, - CM_ARGB_GEN2_A1_WRITE = 0x02, - CM_ARGB_GEN2_A1_RESPONSE = 0x03 -}; - -enum -{ - CM_ARGB_GEN2_A1_SIZES = 0x06, - CM_ARGB_GEN2_A1_FLASH = 0x0B, - CM_ARGB_GEN2_A1_IDENTIFY = 0x0A, - CM_ARGB_GEN2_A1_LIGHTNING_CONTROL = 0x01, - CM_ARGB_GEN2_A1_HW_MODE_SETUP = 0x03, - CM_ARGB_GEN2_A1_CUSTOM_SEQUENCES = 0x10, - CM_ARGB_GEN2_A1_CUSTOM_SPEED = 0x11 - -}; - -class CMARGBGen2A1controller -{ -public: - CMARGBGen2A1controller(hid_device* dev_handle, const hid_device_info& info); - ~CMARGBGen2A1controller(); - - std::string GetSerialString(); - std::string GetDeviceLocation(); - - void SendDirectChannel(unsigned int zone_id, std::vector colors); - void SetupZoneSize(unsigned int zone_id, unsigned int size); - void SetupDirectMode(); - void SetMode(unsigned int mode_value, unsigned char speed, unsigned char brightness, RGBColor color, bool random); - void SetCustomColors(unsigned int zone_id, std::vector colors); - void SaveToFlash(); - -private: - std::string serial_number; - std::string location; - bool software_mode_activated = false; - hid_device* dev; - - void SetCustomSequence(unsigned int zone_id); - std::vector CreateColorData(std::vector colors); -}; diff --git a/Controllers/CoolerMasterController/CMARGBcontroller.cpp b/Controllers/CoolerMasterController/CMARGBcontroller.cpp deleted file mode 100644 index 44a489fe..00000000 --- a/Controllers/CoolerMasterController/CMARGBcontroller.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/*-------------------------------------------------------------------*\ -| CMARGBController.cpp | -| | -| Driver for Coolermaster ARGB USB Controller | -| | -| Chris M (Dr_No) 10th Oct 2020 | -| | -\*-------------------------------------------------------------------*/ - -#include "CMARGBcontroller.h" - -CMARGBController::CMARGBController(hid_device* dev_handle, char *_path, unsigned char _zone_idx, std::shared_ptr cm_mutex) -{ - const int szTemp = 256; - wchar_t tmpName[szTemp]; - - dev = dev_handle; - location = _path; - zone_index = _zone_idx; - mutex_ptr = cm_mutex; - - hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - device_name = std::string(wName.begin(), wName.end()); - - hid_get_product_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); - - hid_get_serial_number_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - serial = std::string(wName.begin(), wName.end()); - - GetStatus(); -} - -CMARGBController::~CMARGBController() -{ - hid_close(dev); -} - -void CMARGBController::GetStatus() -{ - unsigned char buffer[CM_ARGB_PACKET_SIZE] = { 0x00, 0x80, 0x0B, 0x01 }; - int buffer_size = (sizeof(buffer) / sizeof(buffer[0])); - int rgb_offset = 0; - int zone; - - if (argb_header_data[zone_index].digital) - { - zone = argb_header_data[zone_index].header; - buffer[CM_ARGB_COMMAND_BYTE] = 0x0B; - } - else - { - zone = 0x00; - buffer[CM_ARGB_COMMAND_BYTE] = 0x0A; - rgb_offset = 1; - } - - /*---------------------------------------------*\ - | Guard the writes to the controller until the | - | for loop has completed to avoid collisons | - \*---------------------------------------------*/ - std::lock_guard guard(*mutex_ptr); - - /*---------------------------------------------------------*\ - | If this is the group then just return the first status | - \*---------------------------------------------------------*/ - buffer[CM_ARGB_ZONE_BYTE] = ( zone > 0x08 ) ? 0x01 : zone; - hid_write(dev, buffer, buffer_size); - hid_read_timeout(dev, buffer, buffer_size, CM_ARGB_INTERRUPT_TIMEOUT); - - current_mode = buffer[4 - rgb_offset]; - bool_random = ( buffer[5 - rgb_offset] == 0x00 ); - current_speed = buffer[6 - rgb_offset]; - current_brightness = buffer[7 - rgb_offset]; - current_red = buffer[8 - rgb_offset]; - current_green = buffer[9 - rgb_offset]; - current_blue = buffer[10 - rgb_offset]; -} - -std::string CMARGBController::GetDeviceName() -{ - return device_name; -} - -std::string CMARGBController::GetSerial() -{ - return serial; -} - -std::string CMARGBController::GetLocation() -{ - return("HID: " + location); -} - -unsigned char CMARGBController::GetZoneIndex() -{ - return zone_index; -} - -unsigned char CMARGBController::GetMode() -{ - return current_mode; -} - -unsigned char CMARGBController::GetLedRed() -{ - return current_red; -} - -unsigned char CMARGBController::GetLedGreen() -{ - return current_green; -} - -unsigned char CMARGBController::GetLedBlue() -{ - return current_blue; -} - -unsigned char CMARGBController::GetLedSpeed() -{ - return current_speed; -} - -bool CMARGBController::GetRandomColours() -{ - return bool_random; -} - -void CMARGBController::SetLedCount(int zone, int led_count) -{ - unsigned char buffer[CM_ARGB_PACKET_SIZE] = { 0x00, 0x80, 0x0D, 0x02 }; - int buffer_size = (sizeof(buffer) / sizeof(buffer[0])); - - buffer[CM_ARGB_ZONE_BYTE] = zone; - buffer[CM_ARGB_MODE_BYTE] = led_count; - buffer[CM_ARGB_COLOUR_INDEX_BYTE] = (0x0F - led_count > 0) ? 0x0F - led_count : 0x01; - - /*---------------------------------------------*\ - | Guard the writes to the controller until the | - | for loop has completed to avoid collisons | - \*---------------------------------------------*/ - std::lock_guard guard(*mutex_ptr); - - hid_write(dev, buffer, buffer_size); -} - -void CMARGBController::SetMode(uint8_t mode, uint8_t speed, uint8_t brightness, RGBColor colour, bool random_colours) -{ - bool needs_update = !( (current_mode == mode) && (current_speed == speed) && (current_brightness == brightness) && (ToRGBColor(current_red, current_green, current_blue) == colour)); - - if (needs_update) - { - current_mode = mode; - current_speed = speed; - current_brightness = brightness; - current_red = RGBGetRValue(colour); - current_green = RGBGetGValue(colour); - current_blue = RGBGetBValue(colour); - bool_random = random_colours; - - SendUpdate(); - } -} - -void CMARGBController::SetLedsDirect(RGBColor *led_colours, unsigned int led_count) -{ - const unsigned char buffer_size = CM_ARGB_PACKET_SIZE; - unsigned char buffer[buffer_size] = { 0x00, 0x00, 0x07, 0x02 }; - unsigned char packet_count = 0; - std::vector colours; - - /*---------------------------------------------*\ - | Set up the RGB triplets to send | - \*---------------------------------------------*/ - for(unsigned int i = 0; i < led_count; i++) - { - RGBColor colour = led_colours[i]; - - colours.push_back( RGBGetRValue(colour) ); - colours.push_back( RGBGetGValue(colour) ); - colours.push_back( RGBGetBValue(colour) ); - } - - buffer[CM_ARGB_FUNCTION_BYTE] = zone_index - 1; - buffer[CM_ARGB_ZONE_BYTE] = led_count; - unsigned char buffer_idx = CM_ARGB_MODE_BYTE; - - /*---------------------------------------------*\ - | Guard the writes to the controller until the | - | for loop has completed to avoid collisons | - \*---------------------------------------------*/ - std::lock_guard guard(*mutex_ptr); - - for(std::vector::iterator it = colours.begin(); it != colours.end(); buffer_idx = CM_ARGB_COMMAND_BYTE) - { - /*-----------------------------------------------------------------*\ - | Fill the write buffer till its full or the colour buffer is empty | - \*-----------------------------------------------------------------*/ - buffer[CM_ARGB_REPORT_BYTE] = packet_count; - while (( buffer_idx < buffer_size) && ( it != colours.end() )) - { - buffer[buffer_idx] = *it; - buffer_idx++; - it++; - } - - if(it == colours.end()) - { - buffer[CM_ARGB_REPORT_BYTE] += 0x80; - } - - hid_write(dev, buffer, buffer_size); - - /*-----------------------------------------------------------------*\ - | Reset the write buffer | - \*-----------------------------------------------------------------*/ - memset(buffer, 0x00, buffer_size ); - packet_count++; - } -} - -void CMARGBController::SendUpdate() -{ - /*---------------------------------------------*\ - | Guard the writes to the controller | - \*---------------------------------------------*/ - std::lock_guard guard(*mutex_ptr); - - unsigned char buffer[CM_ARGB_PACKET_SIZE] = { 0x00 }; - int buffer_size = (sizeof(buffer) / sizeof(buffer[0])); - bool boolARGB_header = argb_header_data[zone_index].digital; - bool boolPassthru = ( current_mode == CM_ARGB_MODE_PASSTHRU ) || ( current_mode == CM_RGB_MODE_PASSTHRU ); - bool boolDirect = ( current_mode == CM_ARGB_MODE_DIRECT ); - unsigned char function = boolPassthru ? (boolARGB_header ? 0x02 : 0x04) : (boolARGB_header ? 0x01 : 0x03); - buffer[CM_ARGB_REPORT_BYTE] = 0x80; - buffer[CM_ARGB_COMMAND_BYTE] = 0x01; - - if(boolDirect) - { - buffer[CM_ARGB_FUNCTION_BYTE] = 0x01; - buffer[CM_ARGB_ZONE_BYTE] = 0x02; - - hid_write(dev, buffer, buffer_size); - hid_read_timeout(dev, buffer, buffer_size, CM_ARGB_INTERRUPT_TIMEOUT); - - /*-----------------------------------------------------------------*\ - | Direct mode is now set up and no other mode packet is required | - \*-----------------------------------------------------------------*/ - return; - } - - buffer[CM_ARGB_FUNCTION_BYTE] = function; - - hid_write(dev, buffer, buffer_size); - hid_read_timeout(dev, buffer, buffer_size, CM_ARGB_INTERRUPT_TIMEOUT); - - if(boolARGB_header) - { - buffer[CM_ARGB_COMMAND_BYTE] = 0x0B; //ARGB sends 0x0B (1011) RGB sends 0x04 (0100) - buffer[CM_ARGB_FUNCTION_BYTE] = (false) ? 0x01 : 0x02; //This controls direct mode TODO - buffer[CM_ARGB_ZONE_BYTE] = argb_header_data[zone_index].header; - buffer[CM_ARGB_MODE_BYTE] = current_mode; - buffer[CM_ARGB_COLOUR_INDEX_BYTE] = bool_random ? 0x00 : 0x10; - buffer[CM_ARGB_SPEED_BYTE] = current_speed; - buffer[CM_ARGB_BRIGHTNESS_BYTE] = current_brightness; - buffer[CM_ARGB_RED_BYTE] = current_red; - buffer[CM_ARGB_GREEN_BYTE] = current_green; - buffer[CM_ARGB_BLUE_BYTE] = current_blue; - } - else - { - buffer[CM_ARGB_COMMAND_BYTE] = boolPassthru ? 0x01 : 0x04; //ARGB sends 0x0b (1011) RGB sends 0x04 (0100) - buffer[CM_ARGB_MODE_BYTE + CM_RGB_OFFSET] = current_mode; - buffer[CM_ARGB_COLOUR_INDEX_BYTE + CM_RGB_OFFSET] = bool_random ? 0x00 : 0x10; - buffer[CM_ARGB_SPEED_BYTE + CM_RGB_OFFSET] = current_speed; - buffer[CM_ARGB_BRIGHTNESS_BYTE + CM_RGB_OFFSET] = current_brightness; - buffer[CM_ARGB_RED_BYTE + CM_RGB_OFFSET] = current_red; - buffer[CM_ARGB_GREEN_BYTE + CM_RGB_OFFSET] = current_green; - buffer[CM_ARGB_BLUE_BYTE + CM_RGB_OFFSET] = current_blue; - } - - hid_write(dev, buffer, buffer_size); - hid_read_timeout(dev, buffer, buffer_size, CM_ARGB_INTERRUPT_TIMEOUT); -} diff --git a/Controllers/CoolerMasterController/CMARGBcontroller.h b/Controllers/CoolerMasterController/CMARGBcontroller.h deleted file mode 100644 index 4dedb7fc..00000000 --- a/Controllers/CoolerMasterController/CMARGBcontroller.h +++ /dev/null @@ -1,141 +0,0 @@ -/*-------------------------------------------------------------------*\ -| CMARGBController.h | -| | -| Driver for Coolermaster ARGB USB Controller | -| | -| Chris M (Dr_No) 10th Oct 2020 | -| | -| Simple RGB device with 5 modes | -| | -\*-------------------------------------------------------------------*/ - -#include -#include -#include -#include -#include -#include "RGBController.h" //Needed to set the direct mode - -#pragma once - -#define CM_ARGB_COLOUR_MODE_DATA_SIZE (sizeof(colour_mode_data[0]) / sizeof(colour_mode_data[0][0])) -#define CM_ARGB_HEADER_DATA_SIZE (sizeof(argb_header_data) / sizeof(argb_headers) ) -#define CM_ARGB_INTERRUPT_TIMEOUT 250 -#define CM_ARGB_PACKET_SIZE 65 -#define CM_ARGB_DEVICE_NAME_SIZE (sizeof(device_name) / sizeof(device_name[ 0 ])) -#define CM_RGB_OFFSET -2 -#define HID_MAX_STR 255 - -#define CM_ARGB_BRIGHTNESS_MAX 255 -#define CM_ARGB_FW0023 std::string("A202011171238") -#define CM_ARGB_FW0028 std::string("A202105291658") - -enum -{ - CM_ARGB_REPORT_BYTE = 1, - CM_ARGB_COMMAND_BYTE = 2, - CM_ARGB_FUNCTION_BYTE = 3, - CM_ARGB_ZONE_BYTE = 4, - CM_ARGB_MODE_BYTE = 5, - CM_ARGB_COLOUR_INDEX_BYTE = 6, - CM_ARGB_SPEED_BYTE = 7, - CM_ARGB_BRIGHTNESS_BYTE = 8, - CM_ARGB_RED_BYTE = 9, - CM_ARGB_GREEN_BYTE = 10, - CM_ARGB_BLUE_BYTE = 11 -}; - -struct argb_headers -{ - const char* name; - unsigned char header; - bool digital; - unsigned int count; -}; - -static argb_headers argb_header_data[] = -{ - { "RGB Header", 0xFE, false, 1 }, - { "Digital ARGB1", 0x01, true, 12 }, - { "Digital ARGB2", 0x02, true, 12 }, - { "Digital ARGB3", 0x04, true, 12 }, - { "Digital ARGB4", 0x08, true, 12 }, - //{ "All Digital ARGB", 0xFF, true, 12 } -}; - -enum -{ - CM_RGB_MODE_MIRAGE = 0x01, //Mirage - CM_RGB_MODE_FLASH = 0x02, //Flash - CM_RGB_MODE_BREATHING = 0x03, //Breathing - CM_RGB_MODE_STATIC = 0x05, //Static - CM_RGB_MODE_OFF = 0x06, //Turn off - CM_RGB_MODE_PASSTHRU = 0xFF //Motherboard Pass Thru Mode -}; - -enum -{ - CM_ARGB_MODE_OFF = 0x0B, //Turn off - CM_ARGB_MODE_SPECTRUM = 0x01, //Spectrum Mode - CM_ARGB_MODE_RELOAD = 0x02, //Reload Mode - CM_ARGB_MODE_RECOIL = 0x03, //Recoil Mode - CM_ARGB_MODE_BREATHING = 0x04, //Breathing Mode - CM_ARGB_MODE_REFILL = 0x05, //Refill Mode - CM_ARGB_MODE_DEMO = 0x06, //Demo Mode - CM_ARGB_MODE_FILLFLOW = 0x08, //Fill Flow Mode - CM_ARGB_MODE_RAINBOW = 0x09, //Rainbow Mode - CM_ARGB_MODE_STATIC = 0x0A, //Static Mode - CM_ARGB_MODE_DIRECT = 0xFE, //Direct Led Control - CM_ARGB_MODE_PASSTHRU = 0xFF //Motherboard Pass Thru Mode -}; - -enum -{ - CM_ARGB_SPEED_SLOWEST = 0x00, // Slowest speed - CM_ARGB_SPEED_SLOW = 0x01, // Slower speed - CM_ARGB_SPEED_NORMAL = 0x02, // Normal speed - CM_ARGB_SPEED_FAST = 0x03, // Fast speed - CM_ARGB_SPEED_FASTEST = 0x04, // Fastest speed -}; - -class CMARGBController -{ -public: - CMARGBController(hid_device* dev_handle, char *_path, unsigned char _zone_idx, std::shared_ptr cm_mutex); - ~CMARGBController(); - - std::string GetDeviceName(); - std::string GetSerial(); - std::string GetLocation(); - - unsigned char GetZoneIndex(); - unsigned char GetMode(); - unsigned char GetLedRed(); - unsigned char GetLedGreen(); - unsigned char GetLedBlue(); - unsigned char GetLedSpeed(); - bool GetRandomColours(); - void SetLedCount(int zone, int led_count); - void SetMode(uint8_t mode, uint8_t speed, uint8_t brightness, RGBColor colour, bool random_colours); - void SetLedsDirect(RGBColor * led_colours, unsigned int led_count); - -private: - std::string device_name; - std::string serial; - std::string location; - hid_device* dev; - std::shared_ptr mutex_ptr; - - unsigned char zone_index; - unsigned char current_mode; - unsigned char current_speed; - - unsigned char current_red; - unsigned char current_green; - unsigned char current_blue; - unsigned char current_brightness; - bool bool_random; - - void GetStatus(); - void SendUpdate(); -}; diff --git a/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardAbstractController.cpp b/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardAbstractController.cpp new file mode 100644 index 00000000..655c0f73 --- /dev/null +++ b/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardAbstractController.cpp @@ -0,0 +1,197 @@ +/*---------------------------------------------------------*\ +| CMKeyboardAbstractController.cpp | +| | +| Driver for Cooler Master keyboards | +| | +| Tam D (too.manyhobbies) 30 Nov 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "CMKeyboardAbstractController.h" +#include "StringUtils.h" + +CMKeyboardAbstractController::CMKeyboardAbstractController(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name) +{ + wchar_t tmp[HID_MAX_STR]; + + m_pDev = dev_handle; + m_productId = dev_info->product_id; + m_sLocation = dev_info->path; + m_deviceName = dev_name; + + hid_get_manufacturer_string(m_pDev, tmp, HID_MAX_STR); + m_vendorName = StringUtils::wstring_to_string(tmp); + + hid_get_product_string(m_pDev, tmp, HID_MAX_STR); + m_serialNumber = StringUtils::wstring_to_string(tmp); + + bool bNotFound = true; + + for(uint16_t i = 0; i < COOLERMASTER_KEYBOARD_DEVICE_COUNT; i++) + { + if(cm_kb_device_list[i]->product_id == m_productId) + { + bNotFound = false; + m_deviceIndex = i; + break; + } + } + + if(bNotFound) + { + LOG_ERROR("[%s] device capabilities not found. Please creata a new device request.", m_deviceName.c_str()); + } +}; + +CMKeyboardAbstractController::~CMKeyboardAbstractController() +{ + hid_close(m_pDev); +}; + +std::string CMKeyboardAbstractController::GetDeviceName() +{ + return(m_deviceName); +} + +std::string CMKeyboardAbstractController::GetDeviceVendor() +{ + return(m_vendorName); +} + +std::string CMKeyboardAbstractController::GetDeviceSerial() +{ + return(m_serialNumber); +} + +const cm_kb_device* CMKeyboardAbstractController::GetDeviceData() +{ + return(cm_kb_device_list[m_deviceIndex]); +} + +std::string CMKeyboardAbstractController::GetLocation() +{ + return(m_sLocation); +} + +std::string CMKeyboardAbstractController::GetFirmwareVersion() +{ + return(m_sFirmwareVersion); +} + +int CMKeyboardAbstractController::GetProductID() +{ + return(m_productId); +} + +std::vector CMKeyboardAbstractController::SendCommand(std::vector buf, uint8_t fill) +{ + int status; + std::vector read; + + uint8_t data[CM_KEYBOARD_WRITE_SIZE]; + memset(data, fill, CM_KEYBOARD_WRITE_SIZE); + + size_t i = 1; + for(uint8_t b : buf) + { + data[i++] = b; + } + + std::lock_guard guard(m_mutexSendCommand); + status = hid_write(m_pDev, data, CM_KEYBOARD_WRITE_SIZE); + + if(status < 0) + { + LOG_ERROR("[%s] SendCommand() failed code %d.", m_deviceName.c_str(), status); + return(read); + } + + memset(data, 0, CM_KEYBOARD_WRITE_SIZE); + status = hid_read(m_pDev, data, CM_KEYBOARD_WRITE_SIZE); + + if(status < 0) + { + LOG_ERROR("[%s] SendCommand() failed code %d.", m_deviceName.c_str(), status); + return(read); + } + + for(i = 0; i < (size_t)status; i++) + { + read.push_back(data[i]); + } + + return(read); +} + +/*---------------------------------------------------------*\ +| Enter/leave direct control mode | +\*---------------------------------------------------------*/ +void CMKeyboardAbstractController::SetControlMode(uint8_t modeId) +{ + SendCommand({0x41, (uint8_t)modeId}); +}; + +/*---------------------------------------------------------*\ +| Sets the currently active profile. | +| byte[0] = 0x51 0x00 0x00 0x00 | +| byte[4] = profileId | +| - corresponds to saved keyboard profile i.e. [1-4] | +| - 0x05 - Used on MK and CK style keyboards? | +\*---------------------------------------------------------*/ +void CMKeyboardAbstractController::SetActiveProfile(uint8_t profileId) +{ + SendCommand({0x51, 0x00, 0x00, 0x00, profileId}); +}; + +uint8_t CMKeyboardAbstractController::GetActiveProfile() +{ + std::vector data = SendCommand({0x52, 0x00}); + + if(data.size() > 4) + { + return((int)data[4]); + } + + return(0xFF); // error +} + +/*---------------------------------------------------------*\ +| Saves changes in currently used profile. | +| byte[1] = 0x52 | +\*---------------------------------------------------------*/ +void CMKeyboardAbstractController::SaveActiveProfile() +{ + SendCommand({0x50, 0x55}); +} + +void CMKeyboardAbstractController::SetActiveEffect(uint8_t effectId) +{ + SendCommand({0x51, 0x28, 0x00, 0x00, effectId}); +}; + +void CMKeyboardAbstractController::SaveProfile() +{ + SendCommand({0x50, 0x55}); +} + + +uint8_t CMKeyboardAbstractController::GetModeStatus() +{ + std::vector data = SendCommand({0x52, 0x28}); + + return(data[4]); +}; + +std::string CMKeyboardAbstractController::GetHexString(std::vector buf) +{ + std::stringstream hexss; + + for(uint8_t b : buf) + { + hexss << std::hex << b << " "; + } + + return(hexss.str()); +} diff --git a/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardAbstractController.h b/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardAbstractController.h new file mode 100644 index 00000000..23c865e7 --- /dev/null +++ b/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardAbstractController.h @@ -0,0 +1,120 @@ +/*---------------------------------------------------------*\ +| CMKeyboardAbstractController.h | +| | +| Driver for Cooler Master keyboards | +| | +| Tam D (too.manyhobbies) 30 Nov 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "CMKeyboardDevices.h" +#include "KeyboardLayoutManager.h" +#include "RGBController.h" +#include "LogManager.h" + +#define HID_MAX_STR 255 +#define CM_KEYBOARD_WRITE_SIZE 65 +#define CM_MAX_LEDS 255 +#define CM_KEYBOARD_TIMEOUT 50 +#define CM_KEYBOARD_TIMEOUT_SHORT 3 + +struct cm_keyboard_effect +{ + uint8_t effectId; + uint8_t p1; + uint8_t p2; + uint8_t p3; + RGBColor color1; + RGBColor color2; +}; + +/*---------------------------------------------------------*\ +| byte[0] = 0x41 | +| byte[1] = modeId | +\*---------------------------------------------------------*/ +enum cm_keyboard_control_mode +{ + MODE_FIRMWARE = 0x00, + MODE_EFFECT = 0x01, + MODE_MANUAL_V2 = 0x02, + MODE_CUSTOM_PROFILE = 0x03, + MODE_CUSTOM_PROFILE_V2 = 0x05, + MODE_DIRECT = 0x80 +}; + +class CMKeyboardAbstractController +{ +public: + CMKeyboardAbstractController(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name); + virtual ~CMKeyboardAbstractController(); + + /*---------------------------------------------------------*\ + | Common USB controller fuctions | + \*---------------------------------------------------------*/ + int GetProductID(); + std::string GetDeviceName(); + std::string GetDeviceVendor(); + std::string GetDeviceSerial(); + std::string GetLocation(); + std::string GetFirmwareVersion(); + const cm_kb_device* GetDeviceData(); + + /*---------------------------------------------------------*\ + | Keyboard Layout Manager support funtions | + \*---------------------------------------------------------*/ + + /*---------------------------------------------------------*\ + | Common keyboard driver functions | + \*---------------------------------------------------------*/ + virtual void SetControlMode(uint8_t modeId); + virtual void SetActiveProfile(uint8_t profileId); + virtual uint8_t GetActiveProfile(); + virtual void SaveActiveProfile(); + virtual void SaveProfile(); + virtual void SetActiveEffect(uint8_t effectId); + virtual uint8_t GetModeStatus(); + virtual void InitializeModes(std::vector &modes) = 0; + virtual KEYBOARD_LAYOUT GetKeyboardLayout() = 0; + + /*---------------------------------------------------------*\ + | Protocol specific funtions to be implmented | + \*---------------------------------------------------------*/ + virtual void SetLeds(std::vector leds, std::vector colors) = 0; + virtual void SetSingleLED(uint8_t in_led, RGBColor in_color) = 0; + virtual void Initialize() = 0; + virtual void Shutdown() = 0; + virtual void SetLEDControl(bool bManual) = 0; // FW or SW control + virtual void SetCustomMode() = 0; + virtual void SetMode(mode selectedMode) = 0; + +protected: + /*---------------------------------------------------------*\ + | Utility functions. | + \*---------------------------------------------------------*/ + std::vector SendCommand(std::vector buf, uint8_t fill=0x00); + std::string GetHexString(std::vector buf); + std::string m_sFirmwareVersion; + std::string m_deviceName; + hid_device* m_pDev; + uint16_t m_productId; + uint16_t m_deviceIndex; + std::string m_vendorName; + std::string m_sLocation; + std::string m_serialNumber; + KEYBOARD_LAYOUT m_keyboardLayout; + std::map mapModeValueEffect; + std::mutex m_mutex; + std::mutex m_mutexSendCommand; +}; + diff --git a/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardDevices.cpp b/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardDevices.cpp new file mode 100644 index 00000000..538f1825 --- /dev/null +++ b/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardDevices.cpp @@ -0,0 +1,902 @@ +/*---------------------------------------------------------*\ +| CMKeyboardDevices.cpp | +| | +| Device list for Cooler Master keyboards | +| | +| Tam D (too.manyhobbies) 30 Nov 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "CMKeyboardDevices.h" + +/*-------------------------------------------------------------------------*\ +| Coolermaster Key Values | +\*-------------------------------------------------------------------------*/ + +const std::vector mk_pro_s_keymap = +{ +/* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK */ + 96, 97, 98, 99, 104, 105, 106, 112, 113, 114, 67, 68, 69, 102, 103, 107, +/* BKTK 1 2 3 4 5 6 7 8 9 0 - = BPSC INS HOME PGUP */ + 0, 1, 8, 9, 16, 17, 24, 25, 32, 33, 40, 41, 48, 49, 56, 57, 64, +/* TAB Q W E R T Y U I O P [ ] \ DEL END PGDN */ + 2, 3, 10, 11, 18, 19, 26, 27, 34, 35, 42, 43, 50, 51, 58, 59, 66, +/* CPLK A S D F G H J K L ; " # ENTR */ + 4, 5, 12, 13, 20, 21, 28, 29, 36, 37, 44, 45, 89, 52, +/* LSFT ISO\ Z X C V B N M , . / RSFT ARWU */ + 6, 100, 7, 14, 15, 22, 23, 30, 31, 38, 39, 46, 47, 61, +/* LCTL LWIN LALT SPC RALT RFNC RMNU RCTL ARWL ARWD ARWR */ + 91, 90, 92, 93, 94, 60, 95, 54, 63, 62, 70, +}; + +const std::vector mk_pro_l_keymap = +{ +/* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK P1 P2 P3 P4 */ + 11, 22, 30, 25, 27, 7, 51, 57, 62, 86, 87, 83, 85, 79, 72, 0, +/* BKTK 1 2 3 4 5 6 7 8 9 0 - = BPSC INS HOME PGUP NMLK NMDV NMTM NMMI */ + 14, 15, 23, 31, 39, 38, 46, 47, 55, 63, 71, 70, 54, 81, 3, 1, 2, 100, 108, 116, 118, +/* TAB Q W E R T Y U I O P [ ] \ DEL END PGDN NM7 NM8 NM9 NMPL */ + 9, 8, 16, 24, 32, 33, 41, 40, 48, 56, 64, 65, 49, 82, 94, 92, 88, 96, 104, 112, 110, +/* CPLK A S D F G H J K L ; ' \ ENTR NM4 NM5 NM6 */ + 17, 10, 18, 26, 34, 35, 43, 42, 50, 58, 66, 67, 68, 84, 97, 105, 113, +/* LSFT ISO\ Z X C V B N M , . / RSFT ARWU NM1 NM2 NM3 NMER */ + 73, 19, 12, 20, 28, 36, 37, 45, 44, 52, 60, 69, 74, 80, 98, 106, 114, 111, +/* LCTL LWIN LALT SPACE RALT RWFNC RMNU RCTRL ARWL ARDN ARWR NM0 NMPD */ + 6, 90, 75, 91, 77, 78, 61, 4, 95, 93, 5, 107, 115, +}; + +const std::vector mk850_keymap = +{ +/* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK AIM AIMU AIMD */ + 6, 27, 34, 41, 48, 62, 69, 76, 83, 90, 97, 104, 111, 118, 125, 132, +/* M1 BKTK 1 2 3 4 5 6 7 8 9 0 - = BPSC INS HOME PGUP NMLK NMDV NMTM NMMI */ + 7, 21, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91, 98, 112, 119, 126, 133, 254, 147, 154, 161, +/* M2 TAB Q W E R T Y U I O P [ ] \ DEL END PGDN NM7 NM8 NM9 NMPL */ + 8, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99, 113, 120, 127, 134, 141, 148, 155, 162, +/* M3 CPLK A S D F G H J K L ; ' # ENTR NM4 NM5 NM6 */ + 9, 23, 30, 37, 44, 51, 58, 65, 72, 79, 86, 93, 0, 114, 142, 149, 156, +/* M4 LSFT ISO\ Z X C V B N M , . / RSFT ARWU NM1 NM2 NM3 NMER */ + 10, 0, 24, 31, 38, 45, 52, 59, 66, 73, 80, 87, 115, 129, 143, 150, 157, 164, +/* M5 LCTL LWIN LALT SPACE RALT RWFNC RMNU RCTRL ARWL ARDN ARWR NM0 NMPD */ + 11, 18, 25, 53, 81, 88, 95, 116, 123, 130, 137, 144, 158, +}; + +/*-------------------------------------------------------------*\ +| CoolerMaster SK (60%) | +\*-------------------------------------------------------------*/ +const std::vector sk620_keymap = +{ +/* T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 */ +/* L1 ESC 1 2 3 4 5 6 7 8 9 0 - = BPSC R1 */ + 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 106, +/* L2 TAB Q W E R T Y U I O P [ ] R2 */ + 9, 23, 30, 37, 44, 51, 58, 65, 72, 79, 86, 93, 100, +/* L3 CPLK A S D F G H J K L ; " \ ENTR R3 */ + 10, 24, 31, 38, 45, 52, 59, 66, 73, 80, 87, 94, 101, 108, +/* L4 LSFT ISO\ Z X C V B N M , . # RSFT ARWU DEL R$ */ + 11, 18, 25, 32, 39, 46, 53, 60, 67, 74, 81, 88, 95, 102, 109, +/* L5 LCTL LWIN LALT SPACE RALT RWFNC ARWL ARDN ARWR R5 */ + 12, 19, 26, 54, 82, 89, 96, 103, 110, +/* B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 B13 B14 B15 B15 */ +}; + +/*-------------------------------------------------------------*\ +| CoolerMaster SK (60%) | +\*-------------------------------------------------------------*/ +const std::vector sk622_keymap = +{ +/* T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 */ +/* L1 ESC 1 2 3 4 5 6 7 8 9 0 - = BPSC R1 */ + 8, 15, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 106, +/* L2 TAB Q W E R T Y U I O P [ ] R2 */ + 9, 23, 30, 37, 44, 51, 58, 65, 72, 79, 86, 93, 100, +/* L3 CPLK A S D F G H J K L ; " \ ENTR R3 */ + 10, 24, 31, 38, 45, 52, 59, 66, 73, 80, 87, 94, 101, 108, +/* L4 LSFT ISO\ Z X C V B N M , . # RSFT ARWU DEL R$ */ + 11, 18, 25, 32, 39, 46, 53, 60, 67, 74, 81, 88, 95, 102, 109, +/* L5 LCTL LWIN LALT SPACE RALT RWFNC ARWL ARDN ARWR R5 */ + 12, 19, 26, 54, 82, 89, 96, 103, 110, +/* B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 B13 B14 B15 B15 */ +}; + +const std::vector sk630_keymap = +{ +/* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK */ + 9, 33, 41, 49, 57, 73, 81, 89, 97, 105, 113, 121, 129, 137, 145, 153, +/* BKTK 1 2 3 4 5 6 7 8 9 0 - = BPSC INS HOME PGUP */ + 10, 26, 34, 42, 50, 58, 66, 74, 82, 90, 98, 106, 114, 130, 138, 146, 154, +/* TAB Q W E R T Y U I O P [ ] \ DEL END PGDN */ + 11, 27, 35, 43, 51, 59, 67, 75, 83, 91, 99, 107, 115, 131, 139, 147, 155, +/* CPLK A S D F G H J K L ; " # ENTR */ + 12, 28, 36, 44, 52, 60, 68, 76, 84, 92, 100, 108, 116, 132, +/* LSFT ISO\ Z X C V B N M , . / RSFT ARWU */ + 13, 21, 29, 37, 45, 53, 61, 69, 77, 85, 93, 101, 133, 149, +/* LCTL LWIN LALT SPC RALT RFNC RMNU RCTL ARWL ARWD ARWR */ + 14, 22, 30, 62, 94, 102, 110, 134, 142, 150, 158, +}; + +const std::vector sk650_keymap = +{ +/* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK */ + 0, 24, 32, 40, 48, 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144, +/* BKTK 1 2 3 4 5 6 7 8 9 0 - = BPSC INS HOME PGUP NMLK NMDV NMTM NMMI */ + 1, 17, 25, 33, 41, 49, 57, 65, 73, 81, 89, 97, 105, 121, 129, 137, 145, 153, 161, 169, 177, +/* TAB Q W E R T Y U I O P [ ] \ DEL END PGDN NM7 NM8 NM9 NMPL */ + 2, 18, 26, 34, 42, 50, 58, 66, 74, 82, 90, 98, 106, 122, 130, 138, 146, 154, 162, 170, 178, +/* CPLK A S D F G H J K L ; ' # ENTR NM4 NM5 NM6 */ + 3, 19, 27, 35, 43, 51, 59, 67, 75, 83, 91, 99, 107, 123, 155, 163, 171, +/* LSFT ISO\ Z X C V B N M , . / RSFT ARWU NM1 NM2 NM3 NMER */ + 4, 20, 28, 36, 44, 52, 60, 68, 76, 84, 92, 100, 124, 140, 156, 164, 172, 180, +/* LCTL LWIN LALT SPACE RALT RWFNC RMNU RCTRL ARWL ARDN ARWR NM0 NMPD */ + 5, 13, 21, 53, 85, 93, 101, 125, 133, 141, 149, 165, 173, +}; + +const std::vector sk652_keymap = +{ + +/* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK */ + 9, 33, 41, 49, 57, 73, 81, 89, 97, 105, 113, 121, 129, 137, 145, 153, +/* BKTK 1 2 3 4 5 6 7 8 9 0 - = BPSC INS HOME PGUP NMLK NMDV NMTM NMMI */ + 10, 26, 34, 42, 50, 58, 66, 74, 82, 90, 98, 106, 114, 130, 138, 146, 154, 162, 170, 178, 186, +/* TAB Q W E R T Y U I O P [ ] \ DEL END PGDN NM7 NM8 NM9 NMPL */ + 11, 27, 35, 43, 51, 59, 67, 75, 83, 91, 99, 107, 115, 131, 139, 147, 155, 163, 171, 179, 187, +/* CPLK A S D F G H J K L ; ' # ENTR NM4 NM5 NM6 */ + 12, 28, 36, 44, 52, 60, 68, 76, 84, 92, 100, 108, 116, 132, 164, 172, 180, +/* LSFT ISO\ Z X C V B N M , . / RSFT ARWU NM1 NM2 NM3 NMER */ + 13, 21, 29, 37, 45, 53, 61, 69, 77, 85, 93, 101, 133, 149, 165, 173, 181, 189, +/* LCTL LWIN LALT SPACE RALT RWFNC RMNU RCTRL ARWL ARDN ARWR NM0 NMPD */ + 14, 22, 30, 62, 94, 102, 110, 134, 142, 150, 158, 174, 182, +}; + +const std::vector sk653_keymap = +{ +/* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK */ + 0, 24, 32, 40, 48, 64, 72, 80, 88, 96, 104, 112, 120, 128, 136, 144, +/* BKTK 1 2 3 4 5 6 7 8 9 0 - = BPSC INS HOME PGUP NMLK NMDV NMTM NMMI */ + 1, 17, 25, 33, 41, 49, 57, 65, 73, 81, 89, 97, 105, 121, 129, 137, 145, 153, 161, 169, 177, +/* TAB Q W E R T Y U I O P [ ] \ DEL END PGDN NM7 NM8 NM9 NMPL */ + 2, 18, 26, 34, 42, 50, 58, 66, 74, 82, 90, 98, 106, 122, 130, 138, 146, 154, 162, 170, 178, +/* CPLK A S D F G H J K L ; ' # ENTR NM4 NM5 NM6 */ + 3, 19, 27, 35, 43, 51, 59, 67, 75, 83, 91, 99, 107, 123, 155, 163, 171, +/* LSFT ISO\ Z X C V B N M , . / RSFT ARWU NM1 NM2 NM3 NMER */ + 4, 20, 28, 36, 44, 52, 60, 68, 76, 84, 92, 100, 124, 140, 156, 164, 172, 180, +/* LCTL LWIN LALT SPACE RALT RWFNC RMNU RCTRL ARWL ARDN ARWR NM0 NMPD */ + 5, 13, 21, 53, 85, 93, 101, 125, 133, 141, 149, 165, 173, +}; + +const std::vector mk730_keymap = +{ +/* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK */ + 7, 28, 35, 42, 49, 63, 70, 77, 84, 91, 98, 105, 112, 119, 126, 133, +/* L1 BKTK 1 2 3 4 5 6 7 8 9 0 - = BPSC INS HOME PGUP R1 */ + 8, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99, 113, 120, 127, 134, +/* L2 TAB Q W E R T Y U I O P [ ] \ DEL END PGDN R2 */ + 9, 23, 30, 37, 44, 51, 58, 65, 72, 79, 86, 93, 100, 114, 121, 128, 135, +/* L3 CPLK A S D F G H J K L ; ' # ENTR R3 */ + 10, 24, 31, 38, 45, 52, 59, 66, 73, 80, 87, 94, 108, 115, +/* L4 LSFT ISO\ Z X C V B N M , . / RSFT ARWU R4 */ + 11, 18, 25, 32, 39, 46, 53, 60, 67, 74, 81, 88, 116, 130, +/* LCTL LWIN LALT SPACE RALT RWFNC RMNU RCTRL ARWL ARDN ARWR */ + 12, 19, 26, 54, 82, 89, 96, 117, 124, 131, 138, +/* B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 B12 */ +}; + +const std::vector mk750_keymap = +{ +/* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK MUT PLA REW FFWD */ + 7, 28, 35, 42, 49, 63, 70, 77, 84, 91, 98, 105, 112, 119, 136, 133, +/* L1 BKTK 1 2 3 4 5 6 7 8 9 0 - = BPSC INS HOME PGUP NMLK NMDV NMTM NMMI R1 */ + 8, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99, 113, 120, 127, 134, 0, 148, 155, 162, +/* L2 TAB Q W E R T Y U I O P [ ] \ DEL END PGDN NM7 NM8 NM9 NMPL R2 */ + 9, 23, 30, 37, 44, 51, 58, 65, 72, 79, 86, 93, 100, 114, 121, 128, 135, 142, 149, 156, 163, +/* L3 CPLK A S D F G H J K L ; ' # ENTR NM4 NM5 NM6 R3 */ + 10, 24, 31, 38, 45, 52, 59, 66, 73, 80, 87, 94, 108, 115, 143, 150, 157, +/* L4 LSFT ISO\ Z X C V B N M , . / RSFT ARWU NM1 NM2 NM3 NMER R4 */ + 11, 18, 25, 32, 39, 46, 53, 60, 67, 74, 81, 88, 116, 130, 144, 151, 158, 165, +/* LCTL LWIN LALT SPACE RALT RWFNC RMNU RCTRL ARWL ARDN ARWR NM0 NMPD */ + 12, 19, 26, 54, 82, 89, 96, 117, 124, 131, 138, 152, 159, +/* B1 B2 B3 B4 B5 B6 B7 B8 B9 B10 B11 B12 B12 B13 B14 B15 B16 B17 B18 */ +}; + + +const std::vector ck530_keymap = +{ +/* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK */ + 6, 21, 27, 34, 41, 55, 62, 69, 76, 83, 90, 97, 104, 111, 118, 125, +/* BKTK 1 2 3 4 5 6 7 8 9 0 - = BPSC INS HOME PGUP */ + 7, 15, 22, 28, 35, 42, 49, 56, 63, 70, 77, 84, 91, 105, 112, 119, 126, +/* TAB Q W E R T Y U I O P [ ] \ DEL END PGDN */ + 8, 16, 23, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 106, 113, 120, 127, +/* CPLK A S D F G H J K L ; " # ENTR */ + 9, 17, 24, 30, 37, 44, 51, 58, 65, 72, 79, 86, 93, 107, +/* LSFT ISO\ Z X C V B N M , . / RSFT ARWU */ + 10, 18, 25, 31, 38, 45, 52, 59, 66, 73, 80, 87, 108, 122, +/* LCTL LWIN LALT SPC RALT RFNC RMNU RCTL ARWL ARWD ARWR */ + 11, 12, 19, 46, 74, 81, 88, 109, 116, 123, 130, +}; + +const std::vector ck530_v2_keymap = +{ +/* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK */ + 7, 28, 35, 42, 49, 63, 70, 77, 84, 91, 98, 105, 112, 119, 126, 133, +/* BKTK 1 2 3 4 5 6 7 8 9 0 - = BPSC INS HOME PGUP */ + 8, 22, 29, 36, 43, 50, 57, 64, 71, 78, 85, 92, 99, 113, 120, 127, 134, +/* TAB Q W E R T Y U I O P [ ] \ DEL END PGDN */ + 9, 23, 30, 37, 44, 51, 58, 65, 72, 79, 86, 93, 100, 114, 121, 128, 135, +/* CPLK A S D F G H J K L ; " # ENTR */ + 10, 24, 31, 38, 45, 52, 59, 66, 73, 80, 87, 94, 108, 115, +/* LSFT ISO\ Z X C V B N M , . / RSFT ARWU */ + 11, 18, 25, 32, 39, 46, 53, 60, 67, 74, 88, 81, 116, 130, +/* LCTL LWIN LALT SPC RALT RFNC RMNU RCTL ARWL ARWD ARWR */ + 12, 19, 26, 54, 82, 89, 96, 117, 124, 131, 138, +}; + +const std::vector ck550_v2_keymap = +{ +/* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK */ + 0, 18, 24, 30, 36, 48, 54, 60, 66, 72, 78, 84, 90, 96, 102, 108, +/* BKTK 1 2 3 4 5 6 7 8 9 0 - = BPSC INS HOME PGUP NMLK NMDV NMTM NMMI */ + 1, 13, 19, 25, 31, 37, 43, 49, 55, 61, 67, 73, 79, 91, 97, 103, 109, 115, 121, 127, 133, +/* TAB Q W E R T Y U I O P [ ] \ DEL END PGDN NM7 NM8 NM9 NMPL */ + 2, 14, 20, 26, 32, 38, 44, 50, 56, 62, 68, 74, 80, 92, 98, 104, 110, 116, 122, 128, 134, +/* CPLK A S D F G H J K L ; ' # ENTR NM4 NM5 NM6 */ + 3, 15, 21, 27, 33, 39, 45, 51, 57, 63, 69, 75, 87, 93, 117, 123, 129, +/* LSFT ISO\ Z X C V B N M , . / RSFT ARWU NM1 NM2 NM3 NMER */ + 4, 10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70,/*76,*/ 94, 106, 118, 124, 130, 136, +/* LCTL LWIN LALT SPACE RALT RWFNC RMNU RCTRL ARWL ARDN ARWR NM0 NMPD */ + 5, 11, 17, 41, 65, 71, 77, 95, 101, 107, 113, 125, 131, +}; + +const std::vector ck552_keymap = +{ +/* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK */ + 0, 18, 24, 30, 36, 48, 54, 60, 66, 72, 78, 84, 90, 96, 102, 108, +/* BKTK 1 2 3 4 5 6 7 8 9 0 - = BPSC INS HOME PGUP NMLK NMDV NMTM NMMI */ + 1, 13, 19, 25, 31, 37, 43, 49, 55, 61, 67, 73, 79, 91, 97, 103, 109, 115, 121, 127, 133, +/* TAB Q W E R T Y U I O P [ ] \ DEL END PGDN NM7 NM8 NM9 NMPL */ + 2, 14, 20, 26, 32, 38, 44, 50, 56, 62, 68, 74, 80, 92, 98, 104, 110, 116, 122, 128, 134, +/* CPLK A S D F G H J K L ; ' # ENTR NM4 NM5 NM6 */ + 3, 15, 21, 27, 33, 39, 45, 51, 57, 63, 69, 75, 81, 93, 117, 123, 129, +/* LSFT ISO\ Z X C V B N M , . / RSFT ARWU NM1 NM2 NM3 NMER */ + 4, 10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70,/*76,*/ 94, 106, 118, 124, 130, 136, +/* LCTL LWIN LALT SPACE RALT RWFNC RMNU RCTRL ARWL ARDN ARWR NM0 NMPD */ + 5, 11, 17, 41, 65, 71, 77, 95, 101, 107, 113, 125, 131, +}; + +/*-------------------------------------------------------------------------*\ +| KEYMAPS | +\*-------------------------------------------------------------------------*/ +keyboard_keymap_overlay_values mk_pro_s_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_TKL, + { + mk_pro_s_keymap, + { + /* Add more regional layout fixes here */ + } + }, + { + /*---------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, Alternate Name, OpCode, | + \*---------------------------------------------------------------------------------------------------------*/ + }, +}; + +keyboard_keymap_overlay_values mk_pro_l_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_FULL, + { + mk_pro_l_keymap, + { + /* Add more regional layout fixes here */ + } + }, + { + /*---------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode, | + \*---------------------------------------------------------------------------------------------------------*/ + { 0, 0, 17, 101, "Key: P1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 18, 109, "Key: P2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 19, 117, "Key: P3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 20, 119, "Key: P4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + }, +}; + +/*-------------------------------------------------------------*\ +| CoolerMaster MK85O Keyboard | +| Unknown Keys: ISO\, ISO# set to 0 | +\*-------------------------------------------------------------*/ +keyboard_keymap_overlay_values mk850_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_FULL, + { + mk850_keymap, + { + /* Add more regional layout fixes here */ + } + }, + { + /*---------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode, | + \*---------------------------------------------------------------------------------------------------------*/ + { 0, 0, 17, 146, "Key: Aim <|>", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // aimpad <|> + { 0, 0, 18, 153, "Key: Aim -", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // aimpad + + { 0, 0, 19, 160, "Key: Aim +", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // aimpad - + { 0, 1, 0, 0, "Key: M5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 0, 1, "Key: M4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 0, 2, "Key: M3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 0, 3, "Key: M2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 0, 4, "Key: M1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + }, +}; + +keyboard_keymap_overlay_values sk620_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_SIXTY, + { + sk620_keymap, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-----------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, Alternate Name, OpCode, | + \*-----------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 7, "Light: Top 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, + { 0, 0, 1, 14, "Light: Top 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 2, 21, "Light: Top 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 3, 28, "Light: Top 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 4, 35, "Light: Top 5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 5, 42, "Light: Top 6", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 6, 49, "Light: Top 7", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 7, 56, "Light: Top 8", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 8, 63, "Light: Top 9", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 9, 70, "Light: Top 10", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 10, 77, "Light: Top 11", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 11, 84, "Light: Top 12", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 12, 91, "Light: Top 13", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 13, 98, "Light: Top 14", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 14, 105, "Light: Top 14", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 0, 0, "Light: Left 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 0, 1, "Light: Left 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 0, 2, "Light: Left 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 0, 3, "Light: Left 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 0, 4, "Light: Left 5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 16, 112, "Light: Right 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 16, 113, "Light: Right 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 16, 114, "Light: Right 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 16, 115, "Light: Right 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 16, 116, "Light: Right 5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 0, 6, "Light: Bottom 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, + { 0, 6, 1, 20, "Light: Bottom 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 2, 27, "Light: Bottom 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 3, 34, "Light: Bottom 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 4, 41, "Light: Bottom 5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 5, 48, "Light: Bottom 6", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 6, 55, "Light: Bottom 7", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 7, 62, "Light: Bottom 8", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 8, 69, "Light: Bottom 9", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 9, 76, "Light: Bottom 10", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 10, 83, "Light: Bottom 11", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 11, 90, "Light: Bottom 12", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 12, 97, "Light: Bottom 13", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 13, 104, "Light: Bottom 14", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 14, 111, "Light: Bottom 15", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 14, 118, "Light: Bottom 16", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + }, +}; + +keyboard_keymap_overlay_values sk622_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_SIXTY, + { + sk622_keymap, + { + /* Add more regional layout fixes here */ + } + }, + { + /*---------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode, | + \*---------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 7, "Light: Top 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, + { 0, 0, 1, 14, "Light: Top 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 2, 21, "Light: Top 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 3, 28, "Light: Top 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 4, 35, "Light: Top 5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 5, 42, "Light: Top 6", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 6, 49, "Light: Top 7", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 7, 56, "Light: Top 8", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 8, 63, "Light: Top 9", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 9, 70, "Light: Top 10", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 10, 77, "Light: Top 11", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 11, 84, "Light: Top 12", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 12, 91, "Light: Top 13", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 13, 98, "Light: Top 14", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 14, 105, "Light: Top 14", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 0, 0, "Light: Left 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 0, 1, "Light: Left 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 0, 2, "Light: Left 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 0, 3, "Light: Left 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 0, 4, "Light: Left 5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 16, 112, "Light: Right 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 16, 113, "Light: Right 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 16, 114, "Light: Right 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 16, 115, "Light: Right 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 16, 116, "Light: Right 5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 0, 6, "Light: Bottom 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, + { 0, 6, 1, 20, "Light: Bottom 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 2, 27, "Light: Bottom 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 3, 34, "Light: Bottom 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 4, 41, "Light: Bottom 5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 5, 48, "Light: Bottom 6", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 6, 55, "Light: Bottom 7", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 7, 62, "Light: Bottom 8", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 8, 69, "Light: Bottom 9", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 9, 76, "Light: Bottom 10", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 10, 83, "Light: Bottom 11", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 11, 90, "Light: Bottom 12", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 12, 97, "Light: Bottom 13", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 13, 104, "Light: Bottom 14", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 14, 111, "Light: Bottom 15", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 14, 118, "Light: Bottom 16", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + }, +}; + +keyboard_keymap_overlay_values sk630_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_TKL, + { + sk630_keymap, + { + /* Add more regional layout fixes here */ + } + }, + { + /*---------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, OpCode, | + \*---------------------------------------------------------------------------------------------------------*/ + } +}; + +keyboard_keymap_overlay_values sk650_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_FULL, + { + sk650_keymap, + { + /* Add more regional layout fixes here */ + } + }, + { + /*---------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, OpCode, | + \*---------------------------------------------------------------------------------------------------------*/ + } +}; + +keyboard_keymap_overlay_values sk652_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_FULL, + { + sk652_keymap, + { + /* Add more regional layout fixes here */ + } + }, + { + /*---------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, OpCode, | + \*---------------------------------------------------------------------------------------------------------*/ + } +}; + +keyboard_keymap_overlay_values sk653_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_FULL, + { + sk653_keymap, + { + /* Add more regional layout fixes here */ + } + }, + { + /*---------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, OpCode, | + \*---------------------------------------------------------------------------------------------------------*/ + } +}; + +/*-------------------------------------------------------------*\ +| CoolerMaster MK730 Keyboard | +\*-------------------------------------------------------------*/ +keyboard_keymap_overlay_values mk730_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_TKL, + { + mk730_keymap, + { + /* Add more regional layout fixes here */ + } + }, + { + /*---------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode, | + \*---------------------------------------------------------------------------------------------------------*/ + { 0, 1, 0, 1, "Light: Left 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 0, 2, "Light: Left 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 0, 3, "Light: Left 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 0, 4, "Light: Left 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 18, 141, "Light: Right 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 18, 142, "Light: Right 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 18, 143, "Light: Right 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 18, 144, "Light: Right 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 1, 13, "Light: Bottom 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, + { 0, 6, 2, 20, "Light: Bottom 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 3, 27, "Light: Bottom 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 4, 34, "Light: Bottom 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 5, 41, "Light: Bottom 5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 6, 55, "Light: Bottom 6", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 7, 62, "Light: Bottom 7", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 8, 69, "Light: Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 10, 76, "Light: Bottom 8", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 11, 90, "Light: Bottom 9", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 12, 104, "Light: Bottom 10", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 13, 111, "Light: Bottom 11", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 14, 118, "Light: Bottom 12", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 15, 125, "Light: Bottom 13", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + } +}; + +/*-------------------------------------------------------------*\ +| CoolerMaster MK750 Keyboard | +| based on keymap defined in Signal. | +| The keymap needs the following adjustments | +| NMLK - Unknown set to 0 | +| SCLK - Unknown set to 0 | +| CAPS - Unknown set to 0 | +| Guesses on ISO\ and # | +\*-------------------------------------------------------------*/ +keyboard_keymap_overlay_values mk750_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_FULL, + { + mk750_keymap, + { + /* Add more regional layout fixes here */ + } + }, + { + /*---------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode, | + \*---------------------------------------------------------------------------------------------------------*/ + { 0, 0, 17, 140, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 18, 147, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 19, 154, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 20, 161, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 0, 1, "Light: Left 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 0, 2, "Light: Left 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 0, 3, "Light: Left 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 0, 4, "Light: Left 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 22, 170, "Light: Right 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 22, 171, "Light: Right 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 22, 172, "Light: Right 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 22, 173, "Light: Right 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 1, 20, "Light: Bottom 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, + { 0, 6, 2, 27, "Light: Bottom 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 3, 34, "Light: Bottom 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 4, 41, "Light: Bottom 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 5, 55, "Light: Bottom 5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 6, 62, "Light: Bottom 6", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 7, 69, "Light: Bottom 7", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 8, 76, "Light: Bottom 8", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 9, 83, "Light: Bottom 9", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 10, 90, "Light: Bottom 10", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 11, 104, "Light: Bottom 11", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 12, 111, "Light: Bottom 12", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 13, 118, "Light: Bottom 13", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 14, 125, "Light: Bottom 14", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 15, 132, "Light: Bottom 15", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 16, 146, "Light: Bottom 16", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 17, 153, "Light: Bottom 17", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 18, 160, "Light: Bottom 18", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + } +}; + +keyboard_keymap_overlay_values ck530_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_TKL, + { + ck530_keymap, + { + /* Add more regional layout fixes here */ + } + }, + { + /*---------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, OpCode, | + \*---------------------------------------------------------------------------------------------------------*/ + } +}; + +keyboard_keymap_overlay_values ck530_v2_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_TKL, + { + ck530_v2_keymap, + { + /* Add more regional layout fixes here */ + } + }, + { + /*---------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, OpCode, | + \*---------------------------------------------------------------------------------------------------------*/ + } +}; + + +keyboard_keymap_overlay_values ck550v2_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_FULL, + { + ck550_v2_keymap, + { + { + /* Add more regional layout fixes here */ + /*---------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, OpCode, | + \*---------------------------------------------------------------------------------------------------------*/ + }, + }, + }, + { + /*---------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode, | + \*---------------------------------------------------------------------------------------------------------*/ + { 0, 0, 17, 120, "Indicator: N", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 18, 126, "Indicator: C", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 19, 132, "Indicator: S", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + }, +}; + +keyboard_keymap_overlay_values ck552_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_FULL, + { + ck552_keymap, + { + { + /* Add more regional layout fixes here */ + /*---------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, OpCode, | + \*---------------------------------------------------------------------------------------------------------*/ + }, + }, + }, + { + /*---------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, OpCode, | + \*---------------------------------------------------------------------------------------------------------*/ + }, +}; + +static const cm_kb_zone cm_generic_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, +}; + +cm_kb_device mk_pro_s_device +{ + COOLERMASTER_KEYBOARD_PRO_S_PID, + { + &cm_generic_zone, + }, + &mk_pro_s_layout, +}; + +cm_kb_device mk_pro_l_device +{ + COOLERMASTER_KEYBOARD_PRO_L_PID, + { + &cm_generic_zone, + }, + &mk_pro_l_layout, +}; + +cm_kb_device mk850_device +{ + COOLERMASTER_KEYBOARD_MK850_PID, + { + &cm_generic_zone, + }, + &mk850_layout, +}; + +cm_kb_device sk620w_device +{ + COOLERMASTER_KEYBOARD_SK620W_PID, + { + &cm_generic_zone, + }, + &sk620_layout, +}; + +cm_kb_device sk620b_device +{ + COOLERMASTER_KEYBOARD_SK620B_PID, + { + &cm_generic_zone, + }, + &sk620_layout, +}; + +cm_kb_device sk622w_device +{ + COOLERMASTER_KEYBOARD_SK622W_PID, + { + &cm_generic_zone, + }, + &sk622_layout, +}; + +cm_kb_device sk622b_device +{ + COOLERMASTER_KEYBOARD_SK622B_PID, + { + &cm_generic_zone, + }, + &sk622_layout, +}; + +cm_kb_device sk630_device +{ + COOLERMASTER_KEYBOARD_SK630_PID, + { + &cm_generic_zone, + }, + &sk630_layout, +}; + +cm_kb_device sk650_device +{ + COOLERMASTER_KEYBOARD_SK650_PID, + { + &cm_generic_zone, + }, + &sk650_layout, +}; + +cm_kb_device sk652_device +{ + COOLERMASTER_KEYBOARD_SK652_PID, + { + &cm_generic_zone, + }, + &sk652_layout, +}; + +cm_kb_device sk653_device +{ + COOLERMASTER_KEYBOARD_SK653_PID, + { + &cm_generic_zone, + }, + &sk652_layout, +}; + +/*---------------------------------------------------------*\ +| TODO: Keymap is incomplete. Extra keys mode enabled to | +| aid in key discovery. | +\*---------------------------------------------------------*/ +cm_kb_device mk730_device +{ + COOLERMASTER_KEYBOARD_MK730_PID, + { + &cm_generic_zone, + }, + &mk730_layout, +}; + +cm_kb_device mk750_device +{ + COOLERMASTER_KEYBOARD_MK750_PID, + { + &cm_generic_zone, + }, + &mk750_layout, +}; + +cm_kb_device ck530_device +{ + COOLERMASTER_KEYBOARD_CK530_PID, + { + &cm_generic_zone, + }, + &ck530_layout, +}; + +cm_kb_device ck530_v2_device +{ + COOLERMASTER_KEYBOARD_CK530_V2_PID, + { + &cm_generic_zone, + }, + &ck530_v2_layout, +}; + +cm_kb_device ck550_v2_device +{ + COOLERMASTER_KEYBOARD_CK550_V2_PID, + { + &cm_generic_zone, + }, + &ck550v2_layout, +}; + +cm_kb_device ck552_v2_device +{ + COOLERMASTER_KEYBOARD_CK552_V2_PID, + { + &cm_generic_zone, + }, + &ck552_layout, +}; + +cm_kb_device mk_pro_l_white_device +{ + COOLERMASTER_KEYBOARD_PRO_L_WHITE_PID, + { + &cm_generic_zone, + }, + &mk_pro_s_layout, +}; + +/*-----------------------------------------------------------------*\ +| KEYBOARDS | +\*-----------------------------------------------------------------*/ +const cm_kb_device* cm_kb_devices[] = +{ + &mk_pro_s_device, + &mk_pro_l_device, + &mk850_device, + &sk620w_device, + &sk620b_device, + &sk622w_device, + &sk622b_device, + &sk630_device, + &sk650_device, + &sk652_device, + &sk653_device, + &mk730_device, + &mk750_device, + &ck530_device, + &ck530_v2_device, + &ck550_v2_device, + &ck552_v2_device, + &mk_pro_l_white_device, +}; + +const unsigned int COOLERMASTER_KEYBOARD_DEVICE_COUNT = (sizeof(cm_kb_devices) / sizeof(cm_kb_devices[ 0 ])); +const cm_kb_device** cm_kb_device_list = cm_kb_devices; diff --git a/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardDevices.h b/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardDevices.h new file mode 100644 index 00000000..3f445d90 --- /dev/null +++ b/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardDevices.h @@ -0,0 +1,123 @@ +/*---------------------------------------------------------*\ +| CMKeyboardDevices.h | +| | +| Device list for Cooler Master keyboards | +| | +| Tam D (too.manyhobbies) 30 Nov 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "KeyboardLayoutManager.h" + +/*-----------------------------------------------------*\ +| List of all supported effects by this controller. | +| All of these effects are firmware controlled, and | +| they types of effects supported will depend on the | +| Keyboard. | +| | +| To enable a command, the SetEffect(effectId) needs | +| to be called. The specific effectId->Effect mapping | +| depends on the keyboard. | +\*-----------------------------------------------------*/ +enum cm_keyboard_effect_type +{ + NONE = 0, + DIRECT, + SINGLE, + FULLY_LIT, + STATIC, + BREATHE, + CYCLE, + WAVE, + RIPPLE, + CROSS, + RAINDROPS, + STARS, + SNAKE, + CUSTOMIZED, + INDICATOR, + MULTILAYER, + REACTIVE_FADE, + REACTIVE_PUNCH, + REACTIVE_TORNADO, + HEARTBEAT, + FIREBALL, + SNOW, + CIRCLE_SPECTRUM, + WATER_RIPPLE, + OFF +}; + +#define CM_KB_ZONES_MAX 1 + +typedef struct +{ + std::string name; + zone_type type; +} cm_kb_zone; + +typedef struct +{ + uint16_t product_id; + const cm_kb_zone * zones[CM_KB_ZONES_MAX]; + keyboard_keymap_overlay_values* layout_new; +} cm_kb_device; + +#define COOLERMASTER_VID 0x2516 + +#define CMKB_MAXKEYS 256 + +/*-----------------------------------------------------------------*\ +| keyboard support status is indicated to the right of | +| the PID definition. Attribution to products is also | +| indicated. | +| | +| libcmmk | +| signal https://gitlab.com/signalrgb/signal-plugins | +| openrgb | +| ck550-macos https://github.com/vookimedlo/ck550-macos/tree/master | +| reversed | +| | +| issue tickets, open merge requests etc are provided | +| for developer references. | +| # denotes issue ticket | +| ! denotes merge/pull request | +\*-----------------------------------------------------------------*/ +#define COOLERMASTER_KEYBOARD_CK351_PID 0x014F // unsupported +#define COOLERMASTER_KEYBOARD_CK530_PID 0x009F // [ck550-macos] +#define COOLERMASTER_KEYBOARD_CK530_V2_PID 0x0147 // [signal] +#define COOLERMASTER_KEYBOARD_CK550_V2_PID 0x0145 // [openrgb #800, #2863, signal] +#define COOLERMASTER_KEYBOARD_CK552_V2_PID 0x007F // [ck550-macos, signal] +#define COOLERMASTER_KEYBOARD_CK570_V2_PID 0x01E8 // unsupported +#define COOLERMASTER_KEYBOARD_CK720_PID 0x016B // unsupported +#define COOLERMASTER_KEYBOARD_CK721_PID 0x016D // unsupported +#define COOLERMASTER_KEYBOARD_CK721LINE_PID 0x01EE // unsupported +#define COOLERMASTER_KEYBOARD_PRO_L_PID 0x003B // [libcmmk !16] +#define COOLERMASTER_KEYBOARD_PRO_L_WHITE_PID 0x0047 // [libcmmk] +#define COOLERMASTER_KEYBOARD_PRO_S_PID 0x003C // [libcmmk #30 !31 !36, !37, !7, #5(closed), #3(closed)] +// MASTERKEYS PRO M [libcmmk #17] +#define COOLERMASTER_KEYBOARD_MK721_PID 0x016F // unsupported +#define COOLERMASTER_KEYBOARD_MK730_PID 0x008F // [openrgb #1630, libcmmk] +#define COOLERMASTER_KEYBOARD_MK750_PID 0x0067 // fw1.2 [libcmmk #25 !9, !14, signal] +#define COOLERMASTER_KEYBOARD_MK770_PID 0x01D5 // unsupported +#define COOLERMASTER_KEYBOARD_MK850_PID 0x0069 // [signal] +#define COOLERMASTER_KEYBOARD_SK620B_PID 0x0157 // [openrgb #4292] +#define COOLERMASTER_KEYBOARD_SK620W_PID 0x0159 // [openrgb #4292, signal] +#define COOLERMASTER_KEYBOARD_SK622B_PID 0x0149 // [openrgb #3110, signal #217(closed)] +#define COOLERMASTER_KEYBOARD_SK622W_PID 0x014B // [signal] +#define COOLERMASTER_KEYBOARD_SK630_PID 0x0089 // [openrgb #967, libcmmk !21] +#define COOLERMASTER_KEYBOARD_SK631B_PID 0x008B // unsupported +#define COOLERMASTER_KEYBOARD_SK631W_PID 0x0125 // [libcmmk] +#define COOLERMASTER_KEYBOARD_SK650_PID 0x008D // [openrgb #613, libcmmk #23 !37 !27 !28, signal] +#define COOLERMASTER_KEYBOARD_SK651B_PID 0x0091 // unsupported +#define COOLERMASTER_KEYBOARD_SK651W_PID 0x0127 // [signal] +#define COOLERMASTER_KEYBOARD_SK652_PID 0x015D // [signal] +#define COOLERMASTER_KEYBOARD_SK653_PID 0x01AB // [openrgb #3571, signal] + +extern const unsigned int COOLERMASTER_KEYBOARD_DEVICE_COUNT; +extern const cm_kb_device** cm_kb_device_list; diff --git a/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardV1Controller.cpp b/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardV1Controller.cpp new file mode 100644 index 00000000..c00ccf0f --- /dev/null +++ b/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardV1Controller.cpp @@ -0,0 +1,500 @@ +/*---------------------------------------------------------*\ +| CMKeyboardV1Controller.cpp | +| | +| Driver for Cooler Master MasterKeys (V1) keyboards | +| | +| Tam D (too.manyhobbies) 30 Nov 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "CMKeyboardV1Controller.h" +#include "LogManager.h" + +CMKeyboardV1Controller::CMKeyboardV1Controller(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name) : CMKeyboardAbstractController(dev_handle, dev_info, dev_name) +{ + m_sFirmwareVersion = _GetFirmwareVersion(); +} + +CMKeyboardV1Controller::~CMKeyboardV1Controller() +{ +} + +void CMKeyboardV1Controller::Initialize() +{ + SetLEDControl(true); +} + +void CMKeyboardV1Controller::SetActiveEffect(uint8_t effectId) +{ + SendCommand({0x51, 0x28, 0x00, 0x00, effectId}); +} + +uint8_t CMKeyboardV1Controller::GetActiveEffect() +{ + std::vector data = SendCommand({0x52, 0x28}); + + return data[4]; +} + +void CMKeyboardV1Controller::SetEffect(uint8_t effectId, uint8_t p1, uint8_t p2, uint8_t p3, RGBColor color1, RGBColor color2) +{ + std::vector data; + + data.push_back(0x51); + data.push_back(0x2C); + data.push_back(0x00); // multilayer_mode - NOT SUPPORTED + data.push_back(0x00); + data.push_back(effectId); + data.push_back(p1); + data.push_back(p2); + data.push_back(p3); + data.push_back(0xFF); + data.push_back(0xFF); + data.push_back(RGBGetRValue(color1)); + data.push_back(RGBGetGValue(color1)); + data.push_back(RGBGetBValue(color1)); + data.push_back(RGBGetRValue(color2)); + data.push_back(RGBGetGValue(color2)); + data.push_back(RGBGetBValue(color2)); + + /*-------------------------------------------*\ + | Likely a bit mask for each LEDs. | + | 3 bits per LED x 127 possible LEDs ~48 bytes| + \*-------------------------------------------*/ + for(size_t i = 0; i < 48; i++) + { + data.push_back(0xFF); + } + + SetCustomMode(); + SetActiveEffect(effectId); + SendCommand(data); +} + +void CMKeyboardV1Controller::SetCustomMode() +{ + SetControlMode(0x01); +} + +void CMKeyboardV1Controller::SetMode(mode selectedMode) +{ + RGBColor color1 = 0; + RGBColor color2 = 0; + uint8_t cSpeed = 0; + uint8_t cDirection = 0; + uint8_t effectId = selectedMode.value; + bool bModeRandom = false; + + if(selectedMode.colors.size() >= 1) + { + color1 = selectedMode.colors[0]; + } + + if(selectedMode.colors.size() >= 2) + { + color2 = selectedMode.colors[1]; + } + + if(selectedMode.color_mode == MODE_COLORS_RANDOM) + { + bModeRandom = true; + } + + int selectedEffect = mapModeValueEffect[effectId]; + cSpeed = selectedMode.speed; + + switch(selectedMode.direction) + { + case MODE_DIRECTION_LEFT: + case MODE_DIRECTION_HORIZONTAL: + cDirection = 0x00; + break; + + case MODE_DIRECTION_RIGHT: + cDirection = 0x04; + break; + + case MODE_DIRECTION_UP: + case MODE_DIRECTION_VERTICAL: + cDirection = 0x06; + break; + + case MODE_DIRECTION_DOWN: + cDirection = 0x02; + break; + + default: + break; + } + + switch(selectedEffect) + { + case DIRECT: + case STATIC: + { + SetEffect(effectId, 0, 0, 0, color1, color2); + } + break; + + case CROSS: + case BREATHE: + case REACTIVE_PUNCH: + case CIRCLE_SPECTRUM: + case SNAKE: + { + SetEffect(effectId, cSpeed, 0, 0xFF, color1, color2); + } + break; + + case WAVE: + { + SetEffect(effectId, cSpeed, cDirection, 0xFF, color1, color2); + } + break; + + case RIPPLE: + { + SetEffect(effectId, cSpeed, bModeRandom ? 0x80 : 0x00, 0xFF, color1, color2); + } + break; + + case RAINDROPS: + { + SetEffect(effectId, 0x6a, 0x00, cSpeed, color1, color2); + } + break; + + case STARS: + { + SetEffect(effectId, cSpeed, 0x00, 0x10, color1, color2); + } + break; + + default: + break; + } +} + +void CMKeyboardV1Controller::InitializeModes(std::vector &modes) +{ + mode Direct; + Direct.name = "Direct"; + Direct.value = 0x02; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + + modes.push_back(Direct); + + mapModeValueEffect[0x02] = DIRECT; + + mode Static; + Static.name = "Static"; + Static.value = 0x00; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.resize(1); + modes.push_back(Static); + mapModeValueEffect[0x00] = STATIC; + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = 0x01; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.speed_min = 0x46; + Breathing.speed_max = 0x27; + Breathing.speed = 0x36; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.colors.resize(1); + modes.push_back(Breathing); + mapModeValueEffect[0x01] = BREATHE; + + mode Cycle; + Cycle.name = "Spectrum Cycle"; + Cycle.value = 0x02; + Cycle.flags = MODE_FLAG_HAS_SPEED; + Cycle.color_mode = MODE_COLORS_NONE; + Cycle.speed_min = 0x96; + Cycle.speed_max = 0x68; + Cycle.speed = 0x7F; + modes.push_back(Cycle); + mapModeValueEffect[0x02] = CIRCLE_SPECTRUM; + + mode Reactive; + Reactive.name = "Reactive"; + Reactive.value = 0x03; + Reactive.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED; + Reactive.color_mode = MODE_COLORS_MODE_SPECIFIC; + Reactive.speed_min = 0x3C; + Reactive.speed_max = 0x2F; + Reactive.speed = 0x35; + Reactive.colors_min = 2; + Reactive.colors_max = 2; + Reactive.colors.resize(2); + modes.push_back(Reactive); + mapModeValueEffect[0x03] = REACTIVE_PUNCH; + + mode Wave; + Wave.name = "Rainbow Wave"; + Wave.value = 0x04; + Wave.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD; + Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; + Wave.speed_min = 0x48; + Wave.speed_max = 0x2A; + Wave.speed = 0x29; + Wave.direction = MODE_DIRECTION_LEFT; + Wave.colors_min = 1; + Wave.colors_max = 1; + Wave.colors.resize(1); + modes.push_back(Wave); + mapModeValueEffect[0x04] = WAVE; + + mode Ripple; + Ripple.name = "Ripple Effect"; + Ripple.value = 0x05; + Ripple.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED; + Ripple.color_mode = MODE_COLORS_MODE_SPECIFIC; + Ripple.speed_min = 0x96; + Ripple.speed_max = 0x62; + Ripple.speed = 0x7C; + Ripple.colors_min = 2; + Ripple.colors_max = 2; + Ripple.colors.resize(2); + modes.push_back(Ripple); + mapModeValueEffect[0x05] = RIPPLE; + + mode Cross; + Cross.name = "Cross"; + Cross.value = 0x06; + Cross.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED; + Cross.color_mode = MODE_COLORS_MODE_SPECIFIC; + Cross.speed_min = 0x2A; + Cross.speed_max = 0x48; + Cross.speed = 0x39; + Cross.colors_min = 2; + Cross.colors_max = 2; + Cross.colors.resize(2); + modes.push_back(Cross); + mapModeValueEffect[0x06] = CROSS; + + mode Raindrops; + Raindrops.name = "Raindrops"; + Raindrops.value = 0x07; + Raindrops.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED; + Raindrops.color_mode = MODE_COLORS_MODE_SPECIFIC; + Raindrops.speed_min = 0x40; + Raindrops.speed_max = 0x08; + Raindrops.speed = 0x24; + Raindrops.colors_min = 2; + Raindrops.colors_max = 2; + Raindrops.colors.resize(2); + modes.push_back(Raindrops); + mapModeValueEffect[0x07] = RAINDROPS; + + mode Stars; + Stars.name = "Starfield"; + Stars.value = 0x08; + Stars.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED; + Stars.color_mode = MODE_COLORS_MODE_SPECIFIC; + Stars.speed_min = 0x46; + Stars.speed_max = 0x32; + Stars.speed = 0x3C; + Stars.colors_min = 2; + Stars.colors_max = 2; + Stars.colors.resize(2); + modes.push_back(Stars); + mapModeValueEffect[0x08] = STARS; + + mode Snake; + Snake.name = "Snake"; + Snake.value = 0x09; + Snake.flags = MODE_FLAG_HAS_SPEED; + Snake.color_mode = MODE_COLORS_NONE; + Snake.speed_min = 0x48; + Snake.speed_max = 0x2A; + Snake.speed = 0x39; + modes.push_back(Snake); + mapModeValueEffect[0x09] = SNAKE; +} + +struct cm_keyboard_effect CMKeyboardV1Controller::GetEffect(uint8_t effectId) +{ + std::vector data; + data.push_back(0x52); + data.push_back(0x2C); + data.push_back(0x00); + data.push_back(0x00); + data.push_back(effectId); + + data = SendCommand(data); + struct cm_keyboard_effect response; + + response.effectId = effectId; + response.p1 = data[5]; + response.p2 = data[6]; + response.p3 = data[7]; + response.color1 = ToRGBColor(data[10], data[11], data[12]); + response.color2 = ToRGBColor(data[13], data[14], data[15]); + + return response; +} + +std::vector CMKeyboardV1Controller::GetEnabledEffects() +{ + std::vector data; + + data = SendCommand({0x52, 0x29}); + + std::vector effects; + + for(size_t i = 4; data[i] != 0xFF; i++) + { + effects.push_back(data[i]); + } + + return effects; +} + + +void CMKeyboardV1Controller::SetLEDControl(bool bManual) +{ + uint8_t modeId = 0; // firmware + + if(bManual) + { + modeId = 0x02; // manual + } + + SetControlMode(modeId); +}; + +void CMKeyboardV1Controller::SetLeds(std::vector leds, std::vector colors) +{ + SetLEDControl(true); + + RGBColor rgbColorMap[CM_MAX_LEDS]; + memset(rgbColorMap, 0, sizeof(RGBColor)*CM_MAX_LEDS); + + for(size_t i = 0; i < leds.size(); i++) + { + rgbColorMap[leds[i].value] = colors[i]; + } + + RGBColor * pRGBColor = rgbColorMap; + + std::lock_guard guard(m_mutex); + + for(size_t i = 0; i < 8; i++) + { + std::vector data; + data.push_back(0xC0); + data.push_back(0x02); + data.push_back((uint8_t)(i * 2)); + data.push_back(0x00); + + for(size_t j = 0; j < 16; j++) + { + data.push_back(RGBGetRValue(*pRGBColor)); + data.push_back(RGBGetGValue(*pRGBColor)); + data.push_back(RGBGetBValue(*pRGBColor)); + + ++pRGBColor; + } + + SendCommand(data); + } +} + +void CMKeyboardV1Controller::SetSingleLED(uint8_t in_led, RGBColor in_color) +{ + std::vector data; + data.push_back(0xC0); + data.push_back(0x01); + data.push_back(0x01); + data.push_back(0x00); + data.push_back(in_led); + data.push_back(RGBGetRValue(in_color)); + data.push_back(RGBGetGValue(in_color)); + data.push_back(RGBGetBValue(in_color)); + + SendCommand(data); +} + +/*-------------------------------------------------------------------*\ +| Detect the Firmware Version | +| | +| Firmware version string is in the format: | +| .. | +| Where is: | +| UNK = 0, ANSI/US = 1, ISO/EU = 2, JP = 3 | +| Examples: | +| 1.2.1 = ANSI/US Keyboard (PRO S) | +| 2.2.1 = ISO/EU Keyboard (PRO L) | +\*-------------------------------------------------------------------*/ +std::string CMKeyboardV1Controller::_GetFirmwareVersion() +{ + std::vector read; + + SetControlMode(MODE_FIRMWARE); + read = SendCommand({0x01, 0x02}); + + char cVersionStr[CM_KEYBOARD_WRITE_SIZE]; + + for(size_t i = 0; i < read.size(); i++) + { + cVersionStr[i] = read[i]; + } + + cVersionStr[CM_KEYBOARD_WRITE_SIZE - 1] = 0; + + std::string sFirmwareVersion; + + sFirmwareVersion = std::string(cVersionStr+4); + + LOG_VERBOSE("[%s] GetFirmwareVersion(): [%s]", m_deviceName.c_str(), sFirmwareVersion.c_str()); + + return sFirmwareVersion; +} + +void CMKeyboardV1Controller::Shutdown() +{ + +} + +KEYBOARD_LAYOUT CMKeyboardV1Controller::GetKeyboardLayout() +{ + KEYBOARD_LAYOUT layout = KEYBOARD_LAYOUT_DEFAULT; + + if(m_sFirmwareVersion.empty()) + { + LOG_WARNING("[%s] GetKeyboardLayout() empty firmware string detected. Unable to detect firmware layout. Assuming defaults.", m_deviceName.c_str()); + + layout = KEYBOARD_LAYOUT_ANSI_QWERTY; + return layout; + } + + switch(m_sFirmwareVersion.c_str()[0]) + { + case '0': + default: + case '1': + layout = KEYBOARD_LAYOUT_ANSI_QWERTY; + break; + + case '2': + layout = KEYBOARD_LAYOUT_ISO_QWERTY; + break; + + case '3': + layout = KEYBOARD_LAYOUT_JIS; + break; + } + + return layout; +} diff --git a/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardV1Controller.h b/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardV1Controller.h new file mode 100644 index 00000000..987c40a1 --- /dev/null +++ b/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardV1Controller.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------*\ +| CMKeyboardV1Controller.h | +| | +| Driver for Cooler Master MasterKeys (V1) keyboards | +| | +| Tam D (too.manyhobbies) 30 Nov 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "CMKeyboardAbstractController.h" + +class CMKeyboardV1Controller : public CMKeyboardAbstractController +{ +public: + CMKeyboardV1Controller(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name); + ~CMKeyboardV1Controller(); + + /*---------------------------------------------------------*\ + | Protocol specific funtions to be implmented | + \*---------------------------------------------------------*/ + void SetLeds(std::vector leds, std::vector colors); + void SetSingleLED(uint8_t in_led, RGBColor in_color); + void Initialize(); + void Shutdown(); + void SetLEDControl(bool bManual); + + void SetActiveEffect(uint8_t effectId); + uint8_t GetActiveEffect(); + void SetEffect(uint8_t effectId, uint8_t p1, uint8_t p2, uint8_t p3, RGBColor color1, RGBColor color2); + struct cm_keyboard_effect GetEffect(uint8_t effectId); + void SetCustomMode(); + void SetMode(mode selectedMode); + std::vector GetEnabledEffects(); + void InitializeModes(std::vector &modes); + KEYBOARD_LAYOUT GetKeyboardLayout(); + +private: + std::string _GetFirmwareVersion(); +}; diff --git a/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardV2Controller.cpp b/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardV2Controller.cpp new file mode 100644 index 00000000..303f1cd5 --- /dev/null +++ b/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardV2Controller.cpp @@ -0,0 +1,1055 @@ +/*---------------------------------------------------------*\ +| CMKeyboardV2Controller.cpp | +| | +| Driver for Cooler Master V2 keyboards | +| | +| Tam D (too.manyhobbies) 30 Nov 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include "CMKeyboardV2Controller.h" +#include "LogManager.h" +#include "StringUtils.h" + +CMKeyboardV2Controller::CMKeyboardV2Controller(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name) : CMKeyboardAbstractController(dev_handle, dev_info, dev_name) +{ + m_sFirmwareVersion = _GetFirmwareVersion(); + m_bMoreFFs = false; +} + +CMKeyboardV2Controller::~CMKeyboardV2Controller() +{ +} + +/*-----------------------------------------------------------------*\ +| Firmware version string is in the format: | +| V.. | +| Where is: | +| UNK = 0, ANSI/US = 1, ISO/EU = 2, JP = 3 | +\*-----------------------------------------------------------------*/ +KEYBOARD_LAYOUT CMKeyboardV2Controller::GetKeyboardLayout() +{ + KEYBOARD_LAYOUT layout = KEYBOARD_LAYOUT_DEFAULT; + + if(m_sFirmwareVersion.empty()) + { + LOG_WARNING("[%s] _GetKeyboardLayout() empty firmware string detected. Assuming ANSI layout as default..", m_deviceName.c_str()); + + layout = KEYBOARD_LAYOUT_ANSI_QWERTY; + } + else + { + switch(m_sFirmwareVersion.c_str()[1]) + { + case '3': + layout = KEYBOARD_LAYOUT_JIS; + break; + + case '2': + layout = KEYBOARD_LAYOUT_ISO_QWERTY; + break; + + default: + case '1': + layout = KEYBOARD_LAYOUT_ANSI_QWERTY; + break; + } + } + + /*------------------------------------------------------------*\ + | Double check keyboard type per #3592, EU keyboard reported | + | with version ID in serial number. | + \*------------------------------------------------------------*/ + if(m_serialNumber.find("JP") != std::string::npos) + { + layout = KEYBOARD_LAYOUT_JIS; + } + + if(m_serialNumber.find("EU") != std::string::npos) + { + layout = KEYBOARD_LAYOUT_ISO_QWERTY; + } + + return(layout); +} + +/*-----------------------------------------------------------------*\ +| Gets the firmware version. | +| Strings are stored as UTF-16 so need to be converted to string | +| Firmware format is VX.YY.ZZ . | +\*-----------------------------------------------------------------*/ +std::string CMKeyboardV2Controller::_GetFirmwareVersion() +{ + std::vector read; + + SetControlMode(MODE_FIRMWARE); + read = SendCommand({0x12, 0x20}); + + uint8_t cVersionStr[CM_KEYBOARD_WRITE_SIZE]; + + size_t i = 0; + for(uint8_t it : read) + { + cVersionStr[i++] = it; + } + + std::u16string usFirmwareVersion(reinterpret_cast(cVersionStr+8)); + std::string sFirmwareVersion(StringUtils::u16string_to_string(usFirmwareVersion)); + + LOG_VERBOSE("[%s] GetFirmwareVersion(): [%s]", m_deviceName.c_str(), sFirmwareVersion.c_str()); + + return sFirmwareVersion; +} + +void CMKeyboardV2Controller::Initialize() +{ + switch(m_productId) + { + case COOLERMASTER_KEYBOARD_SK620B_PID: + case COOLERMASTER_KEYBOARD_SK620W_PID: + MagicCommand(0x09); + break; + + case COOLERMASTER_KEYBOARD_SK622B_PID: + case COOLERMASTER_KEYBOARD_SK622W_PID: + MagicStartupPacket(); + MagicCommand(0x09); + break; + + case COOLERMASTER_KEYBOARD_SK630_PID: + case COOLERMASTER_KEYBOARD_SK650_PID: + SetActiveProfile(0x0C); + m_bMoreFFs = true; + break; + + case COOLERMASTER_KEYBOARD_SK652_PID: + case COOLERMASTER_KEYBOARD_SK653_PID: + MagicStartupPacket(); + MagicCommand(0x0C); + m_bMoreFFs = true; + break; + + case COOLERMASTER_KEYBOARD_CK530_PID: + case COOLERMASTER_KEYBOARD_CK530_V2_PID: + SetActiveProfile(0x05); + MagicCommand(0x0A); + break; + + case COOLERMASTER_KEYBOARD_CK550_V2_PID: + SetActiveProfile(0x05); + MagicCommand(0x09); + break; + + case COOLERMASTER_KEYBOARD_MK730_PID: + SetActiveProfile(0x05); + MagicCommand(0x0A); + m_bMoreFFs = true; + break; + + case COOLERMASTER_KEYBOARD_CK552_V2_PID: + SetControlMode(0x80); + MagicCommand(0x01); + break; + + default: + SendCommand({0x56, 0x81, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB}); + break; + } +} + +void CMKeyboardV2Controller::Shutdown() +{ + +} + +/*---------------------------------------------------------*\ +| Required for some keyboards. No idea what it does. | +\*---------------------------------------------------------*/ +void CMKeyboardV2Controller::MagicStartupPacket() +{ + std::lock_guard guard(m_mutex); + + SendCommand({0x12}); + SendCommand({0x12, 0x20}); + SendCommand({0x12, 0x01}); + SendCommand({0x12, 0x22}); + SendCommand({0x42, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01}); + SendCommand({0x43, 0x00, 0x00, 0x00, 0x01}); +}; + +void CMKeyboardV2Controller::SetLEDControl(bool bManual) +{ + uint8_t modeId = 0; + + if(bManual) + { + modeId = 0x05; + } + + SetControlMode(modeId); +} + +void CMKeyboardV2Controller::SetLeds(std::vector leds, std::vector colors) +{ + SetLEDControl(true); + Initialize(); + + RGBColor rgbColorMap[CM_MAX_LEDS]; + memset(rgbColorMap, 0, sizeof(RGBColor)*CM_MAX_LEDS); + + for(size_t i = 0; i < leds.size(); i++) + { + rgbColorMap[leds[i].value] = colors[i]; + } + + /*---------------------------------------------------------*\ + | Convert color array to linear map of RGB positions. | + | Map is sequential layout of RGB for each LED. i indicates | + | the position in the map (i*3), | + \*---------------------------------------------------------*/ + uint8_t linearColorMap[CM_MAX_LEDS*3] = {0,}; + + for(size_t i = 0; i < CM_MAX_LEDS; i++) + { + linearColorMap[i*3] = RGBGetRValue(rgbColorMap[i]); + linearColorMap[i*3+1] = RGBGetGValue(rgbColorMap[i]); + linearColorMap[i*3+2] = RGBGetBValue(rgbColorMap[i]); + } + + /*---------------------------------------------------------*\ + | For future reference, some keyboares may designate a | + | different number of max LEDs. | + \*---------------------------------------------------------*/ + const uint8_t nLEDs = 0xC1; + + /*---------------------------------------------------------*\ + | Build initial packet. | + | This specifies some of the initial parameters such as the | + | number of LEDs, and the first grouping of LEDs. | + | The packet structure seems to be fixed for these first 24 | + | bytes. | + \*---------------------------------------------------------*/ + std::vector data = + { + 0x56, 0x83, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x80, 0x01, 0x00, nLEDs, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 + }; + + size_t pktIdx; + for(pktIdx = 0; pktIdx < 40; pktIdx++) + { + data.push_back(linearColorMap[pktIdx]); + } + + std::lock_guard guard(m_mutex); + + SendCommand(data); + + /*---------------------------------------------------------*\ + | Build subsequent packets. | + | Aproximately 9 packets of 60 bytes each. Total may change | + | if we get a keyboard with an insane number of LEDs. | + \*---------------------------------------------------------*/ + for(size_t i = 1; i < 10; ++i) + { + data.clear(); + data.push_back(0x56); + data.push_back(0x83); + data.push_back((uint8_t)i); + data.push_back(0x00); + + for(size_t j = 0; j < 60; j++) + { + data.push_back(linearColorMap[pktIdx++]); + } + + SendCommand(data); + } + + SendApplyPacket(0xFF); +} + +void CMKeyboardV2Controller::SetSingleLED(uint8_t /*in_led*/, RGBColor /*in_color*/) +{ +} + +void CMKeyboardV2Controller::MagicCommand(uint8_t profileId) +{ + SendCommand( + { + 0x56, 0x81, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + profileId, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB} + ); +}; + +void CMKeyboardV2Controller::_SetEffectMode(uint8_t effectId) +{ + std::vector data; + + switch(effectId) + { + case STATIC: + case DIRECT: + case CYCLE: + case BREATHE: + case CIRCLE_SPECTRUM: + case REACTIVE_TORNADO: + data = std::vector + { + 0x56, 0x81, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, + }; + break; + + case WAVE: + data = std::vector + { + 0x56, 0x81, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x99, 0x99, 0x99, 0x99 + }; + break; + + case STARS: + case RAINDROPS: + case SNOW: + case CROSS: + case RIPPLE: + case REACTIVE_PUNCH: + case REACTIVE_FADE: + case HEARTBEAT: + case FIREBALL: + case WATER_RIPPLE: + data = std::vector + { + 0x56, 0x81, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x88, + }; + break; + + case CUSTOMIZED: + data = std::vector{ + 0x56, 0x81, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0xBB, 0xBB, 0xBB, 0xBB, + }; + break; + + default: + break; + } + + SendCommand(data); +} + +void CMKeyboardV2Controller::SendApplyPacket(uint8_t mode) +{ + SendCommand({0x51, 0x28, 0x00, 0x00, mode}); +} + + +/*---------------------------------------------------------*\ +| Sets the speed for each mode. Seems like almost every mode| +| has a different set of speed settings. | +\*---------------------------------------------------------*/ +void CMKeyboardV2Controller::_UpdateSpeed(mode selectedMode, uint8_t &cSpeed1, uint8_t &cSpeed2) +{ + std::vectorvSpeed1{0x00, 0x00, 0x00, 0x00, 0x00}; + std::vectorvSpeed2{0x00, 0x00, 0x00, 0x00, 0x00}; + + switch(selectedMode.value) + { + case CROSS: + case REACTIVE_FADE: + vSpeed1 = std::vector{0x17, 0x0E, 0x0B, 0x0A, 0x04}; + vSpeed2 = std::vector{0x01, 0x01, 0x02, 0x05, 0x04}; + break; + + case WAVE: + vSpeed1 = std::vector{0x17, 0x0D, 0x07, 0x09, 0x08}; + vSpeed2 = std::vector{0x01, 0x04, 0x06, 0x0C, 0x11}; + break; + + case REACTIVE_PUNCH: + vSpeed1 = std::vector{0x0E, 0x0A, 0x04, 0x07, 0x01}; + break; + + case BREATHE: + vSpeed1 = std::vector{0x08, 0x0A, 0x0C, 0x07, 0x09}; + vSpeed2 = std::vector{0x01, 0x02, 0x04, 0x04, 0x09}; + break; + + case CIRCLE_SPECTRUM: + case REACTIVE_TORNADO: + switch (selectedMode.direction) + { + case MODE_DIRECTION_LEFT: + vSpeed1 = std::vector{0xFF, 0xFE, 0xFD, 0xFC, 0xFC}; + vSpeed2 = std::vector{0x04, 0x08, 0x08, 0x0C, 0x00}; + break; + + default: + case MODE_DIRECTION_RIGHT: + vSpeed1 = std::vector{0x00, 0x01, 0x02, 0x03, 0x04}; + vSpeed2 = std::vector{0x0C, 0x08, 0x08, 0x04, 0x00}; + break; + } + break; + + case CYCLE: + vSpeed1 = std::vector{0x10, 0x0C, 0x08, 0x04, 0x00}; + break; + + case RIPPLE: + case WATER_RIPPLE: + vSpeed1 = std::vector{0x36, 0x18, 0x0C, 0x06, 0x02}; + break; + + case FIREBALL: + case HEARTBEAT: + vSpeed1 = std::vector{0x01, 0x02, 0x03, 0x05, 0x09}; + break; + + case RAINDROPS: + case SNOW: + vSpeed1 = std::vector{0x0B, 0x08, 0x05, 0x02, 0x00}; + vSpeed2 = std::vector{0x08, 0x18, 0x30, 0x38, 0x40}; + break; + + case STARS: + vSpeed1 = std::vector{0x17, 0x0E, 0x08, 0x0A, 0x0A}; + vSpeed2 = std::vector{0x01, 0x01, 0x01, 0x02, 0x04}; + break; + + case OFF: + default: + break; + } + + if(selectedMode.speed >= 1 && selectedMode.speed <= 5) + { + cSpeed1 = vSpeed1[selectedMode.speed-1]; + cSpeed2 = vSpeed2[selectedMode.speed-1]; + } +} + +void CMKeyboardV2Controller::SetCustomMode() +{ + std::lock_guard guard(m_mutex); + + SendCommand({0x41, 0x80}); + SendCommand({0x52}); +} + +void CMKeyboardV2Controller::SetMode(mode selectedMode) +{ + std::vector data(64, 0); + std::vector data1(64, 0); + std::vector data2(64, 0); + + uint8_t cColor1_R = 0; + uint8_t cColor1_G = 0; + uint8_t cColor1_B = 0; + uint8_t cColor2_R = 0; + uint8_t cColor2_G = 0; + uint8_t cColor2_B = 0; + + RGBColor color1 = 0; + RGBColor color2 = 0; + uint8_t cSpeed1 = 0; + uint8_t cSpeed2 = 0; + + _UpdateSpeed(selectedMode, cSpeed1, cSpeed2); + + uint8_t cBright = (uint8_t)selectedMode.brightness; + uint8_t cDirection = 0; + uint8_t effectId = selectedMode.value; + + if(selectedMode.colors.size() >= 1) + { + color1 = selectedMode.colors[0]; + cColor1_R = (uint8_t)RGBGetRValue(color1); + cColor1_G = (uint8_t)RGBGetGValue(color1); + cColor1_B = (uint8_t)RGBGetBValue(color1); + } + + if(selectedMode.colors.size() >= 2) + { + color2 = selectedMode.colors[1]; + cColor2_R = (uint8_t)RGBGetRValue(color2); + cColor2_G = (uint8_t)RGBGetGValue(color2); + cColor2_B = (uint8_t)RGBGetBValue(color2); + } + + switch(selectedMode.direction) + { + case MODE_DIRECTION_LEFT: + case MODE_DIRECTION_HORIZONTAL: + cDirection = 0x04; + break; + + case MODE_DIRECTION_RIGHT: + cDirection = 0x00; + break; + + case MODE_DIRECTION_UP: + case MODE_DIRECTION_VERTICAL: + cDirection = 0x06; + break; + + case MODE_DIRECTION_DOWN: + cDirection = 0x02; + break; + + default: + break; + } + + SetCustomMode(); + + std::lock_guard guard(m_mutex); + _SetEffectMode(effectId); + + switch(effectId) + { + case OFF: + break; + + case DIRECT: + break; + + case STATIC: + { + data = std::vector + { + 0x56, 0x83, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x00, + cColor1_R, cColor1_G, cColor1_B, cBright, 0x00, 0x00, 0x00, 0x00, + }; + SendCommand(data); + } + break; + + case WAVE: + { + data = std::vector + { + 0x56, 0x83, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x32, 0x00, 0xC1, cSpeed1, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, cBright, 0x00, cDirection, cSpeed2, 0x00, + 0x00, 0x04, 0x08 + }; + SendCommand(data); + } + break; + + case STARS: + { + data = std::vector + { + 0x56, 0x83, 0x00, 0x00, 0x0D, 0x00, 0x0D, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x00, + cColor2_R, cColor2_G, cColor2_B, cBright, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x80, cSpeed1, 0x10, 0x00, 0x00, + cColor1_R, cColor1_G, cColor1_B, cBright, 0x00, 0x00, cSpeed2, 0x01, + 0x01, 0x10, 0x08, 0x01, 0x10, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + SendCommand(data); + + data1 = std::vector + { + 0x56, 0x83, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF + }; + + data2 = std::vector + { + 0x56, 0x83, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF + }; + + data = m_bMoreFFs ? data2 : data1; + + SendCommand(data); + } + break; + + case RAINDROPS: + { + data = std::vector + { + 0x56, 0x83, 0x00, 0x00, 0x0D, 0x00, 0x0D, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x00, + cColor2_R, cColor2_G, cColor2_B, cBright, 0x00, 0x00, 0x00, 0x00, + 0x81, 0x40, 0x00, 0x80, cSpeed1, 0x10, 0x00, 0x00, + cColor1_R, cColor1_G, cColor1_B, cBright, 0x00, 0x00, 0x03, 0x00, + cSpeed2, 0x18, 0x04, 0x10, 0x01, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + SendCommand(data); + + data1 = std::vector + { + 0x56, 0x83, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF + }; + + data2 = std::vector + { + 0x56, 0x83, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF + }; + + data = m_bMoreFFs ? data2 : data1; + + SendCommand(data); + } + break; + + case SNOW: + { + data = std::vector + { + 0x56, 0x83, 0x00, 0x00, 0x0D, 0x00, 0x0D, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x00, + cColor2_R, cColor2_G, cColor2_B, cBright, 0x00, 0x00, 0x00, 0x00, + 0x81, 0x40, 0x00, 0x80, cSpeed1, 0x10, 0x00, 0x00, + cColor1_R, cColor1_G, cColor1_B, cBright, 0x00, 0x00, 0x03, 0x00, + cSpeed2, 0xFF, 0x10, 0x10, 0x01, 0x40, 0x00, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + SendCommand(data); + + data = std::vector + { + 0x56, 0x83, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF + }; + SendCommand(data); + } + break; + + case CYCLE: + { + data = std::vector + { + 0x56, 0x83, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x31, 0x00, 0xC1, cSpeed1, 0x00, 0x00, 0x00, + 0x40, 0x00, 0xFF, cBright, 0x00, 0x00, 0x03, 0x00, + }; + + SendCommand(data); + } + break; + + case BREATHE: + { + data = std::vector + { + 0x56, 0x83, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0xC1, cSpeed1, 0x00, 0x00, 0x00, + cColor1_R, cColor1_G, cColor1_B, cBright, 0x01, 0x00, cSpeed2, 0x00, + }; + SendCommand(data); + } + break; + + case CIRCLE_SPECTRUM: + { + /*---------------------------------------------------*\ + | Speed and directions are interlinked. Probably has | + | to do how speed is computed within the firmware. | + | The speed values for this mode take into account | + | the direction. | + \*---------------------------------------------------*/ + data = std::vector + { + 0x56, 0x83, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x34, 0x00, 0xC1, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, cBright, 0x00, 0x00, cSpeed1, 0x00, + 0x00, cSpeed2, 0x00, 0x04, 0xA0, 0x00, 0x30, 0x00, + }; + SendCommand(data); + } + break; + + case CROSS: + { + data = std::vector + { + 0x56, 0x83, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x00, + cColor2_R, cColor2_G, cColor2_B, cBright, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x80, cSpeed1, 0x10, 0x00, 0x00, + cColor1_R, cColor1_G, cColor1_B, cBright, 0x00, 0x00, cSpeed2, 0x01, + 0x03, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + SendCommand(data); + + data1 = std::vector + { + 0x56, 0x83, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }; + + data2 = std::vector + { + 0x56, 0x83, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }; + + data = m_bMoreFFs ? data2 : data1; + SendCommand(data); + } + break; + + case SINGLE: + break; + + case RIPPLE: + { + data = std::vector + { + 0x56, 0x83, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x00, + cColor2_R, cColor2_G, cColor2_B, cBright, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x82, 0x00, 0x80, cSpeed1, 0x10, 0x00, 0x00, + cColor1_R, cColor1_G, cColor1_B, cBright, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + SendCommand(data); + + data = std::vector + { + 0x56, 0x83, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + SendCommand(data); + } + break; + + case REACTIVE_PUNCH: + { + data = std::vector + { + 0x56, 0x83, 0x00, 0x00, 0x0B, 0x00, 0x0B, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x00, + cColor2_R, cColor2_G, cColor2_B, cBright, 0x00, 0x00, 0x00, 0x00, + 0x28, 0x80, 0x00, 0x80, cSpeed1, 0x10, 0x00, 0x00, + cColor1_R, cColor1_G, cColor1_B, cBright, 0x00, 0x00, 0x01, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + + SendCommand(data); + + data1 = std::vector + { + 0x56, 0x83, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF + }; + + data2 = std::vector + { + 0x56, 0x83, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF + }; + + data = m_bMoreFFs ? data2 : data1; + + SendCommand(data); + } + break; + + case REACTIVE_FADE: + { + data = std::vector + { + 0x56, 0x83, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x00, + cColor2_R, cColor2_G, cColor2_B, cBright, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x80, cSpeed1, 0x10, 0x00, 0x00, + cColor1_R, cColor1_G, cColor1_B, cBright, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + SendCommand(data); + + data1 = std::vector + { + 0x56, 0x83, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }; + + data2 = std::vector + { + 0x56, 0x83, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }; + + data = m_bMoreFFs ? data2 : data1; + + SendCommand(data); + } + break; + + case REACTIVE_TORNADO: + { + /*---------------------------------------------------*\ + | Speed and directions are interlinked. Probably has | + | to do how speed is computed within the firmware. | + | The speed values for this mode take into account | + | the direction. | + \*---------------------------------------------------*/ + data = std::vector + { + 0x56, 0x83, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x83, 0x00, 0xC1, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xFF, cBright, 0x00, 0x00, cSpeed1, 0x00, + 0x00, cSpeed2, 0x00, 0x00, 0x30, 0x00, 0x10, 0x00, + }; + SendCommand(data); + } + break; + + case HEARTBEAT: + { + data = std::vector + { + 0x56, 0x83, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x00, + cColor2_R, cColor2_G, cColor2_B, cBright, 0x00, 0x00, 0x00, 0x00, + 0x20, 0xA0, 0x00, 0x80, 0x20, 0x10, 0x00, 0x00, + cColor1_R, cColor1_G, cColor1_B, cBright, 0x00, 0x00, cSpeed1, 0x00, + 0x02, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + SendCommand(data); + + data = std::vector + { + 0x56, 0x83, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }; + SendCommand(data); + } + break; + + case FIREBALL: + { + data = std::vector + { + 0x56, 0x83, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x00, + cColor2_R, cColor2_G, cColor2_B, cBright, 0x00, 0x00, 0x00, 0x00, + 0x20, 0xA0, 0x00, 0x80, 0x10, 0x10, 0x00, 0x00, + cColor1_R, cColor1_G, cColor1_B, cBright, 0x00, 0x00, cSpeed1, 0x00, + 0x01, 0x08, 0x09, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + SendCommand(data); + + data = std::vector + { + 0x56, 0x83, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }; + SendCommand(data); + } + break; + + case WATER_RIPPLE: + { + data = std::vector + { + 0x56, 0x83, 0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, + 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0xC1, 0x00, 0x00, 0x00, 0x00, + cColor2_R, cColor2_G, cColor2_B, cBright, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x82, 0x00, 0x80, cSpeed1, 0x10, 0x00, 0x00, + cColor1_R, cColor1_G, cColor1_B, cBright, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x90, 0x14, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF + }; + SendCommand(data); + + data = std::vector + { + 0x56, 0x83, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + }; + SendCommand(data); + } + break; + + case SNAKE: + default: + break; + } + + switch(effectId) + { + case OFF: + SendCommand({0x51, 0x28, 0x00, 0x00, 0x10}); + SendCommand({0x41, 0x80}); + break; + + default: + SendCommand({0x41, 0x80}); + SendCommand({0x51, 0x28, 0x00, 0x00, 0xFF}); + break; + } +} + +struct stCMKeyboardV2_mode CMKeyboardV2_modes[] = +{ +/*----------------------------------------------------------------------------------------------------------------------------------------*\ +| Speed Brightness | +| NAME VALUE MIN MAX SET MAX DIR Number of Colors COLOR_MODE FLAGS | +\*----------------------------------------------------------------------------------------------------------------------------------------*/ + {"Direct", DIRECT, 1, 5, 3, 0xFF, 0, 0, MODE_COLORS_PER_LED, MODE_FLAG_HAS_PER_LED_COLOR}, + {"Static", STATIC, 1, 5, 3, 0xFF, 0, 1, MODE_COLORS_MODE_SPECIFIC, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_BRIGHTNESS }, + {"Wave", WAVE, 1, 5, 3, 0xFF, MODE_DIRECTION_LEFT,1, MODE_COLORS_NONE, MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_HAS_SPEED | + MODE_FLAG_HAS_DIRECTION_LR | + MODE_FLAG_HAS_DIRECTION_UD}, + {"Crosshair", CROSS, 1, 5, 3, 0xFF, 0, 2, MODE_COLORS_MODE_SPECIFIC, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_HAS_SPEED }, + {"Reactive Fade",REACTIVE_FADE,1,5, 3, 0xFF, 0, 2, MODE_COLORS_MODE_SPECIFIC, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_HAS_SPEED }, + {"Stars", STARS, 1, 5, 3, 0xFF, 0, 2, MODE_COLORS_MODE_SPECIFIC, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_HAS_SPEED }, + {"Raindrops", RAINDROPS, 1, 5, 3, 0xFF, 0, 2, MODE_COLORS_MODE_SPECIFIC, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_HAS_SPEED }, + {"Color Cycle", CYCLE, 1, 5, 3, 0xFF, 0, 0, MODE_COLORS_NONE, MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_HAS_SPEED }, + {"Breathing", BREATHE, 1, 5, 3, 0xFF, 0, 1, MODE_COLORS_MODE_SPECIFIC, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_HAS_SPEED }, + {"Ripple", RIPPLE, 1, 5, 3, 0xFF, 0, 2, MODE_COLORS_MODE_SPECIFIC, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_HAS_SPEED }, + {"Fireball", FIREBALL, 1, 5, 3, 0xFF, 0, 2, MODE_COLORS_MODE_SPECIFIC, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_HAS_SPEED }, + {"Water Ripple",WATER_RIPPLE,1,5, 3, 0xFF, 0, 2, MODE_COLORS_MODE_SPECIFIC, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_HAS_SPEED }, + {"Reactive Punch",REACTIVE_PUNCH,1,5,3, 0xFF, 0, 2, MODE_COLORS_MODE_SPECIFIC, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_HAS_SPEED }, + {"Snowing", SNOW, 1, 5, 3, 0xFF, 0, 2, MODE_COLORS_MODE_SPECIFIC, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_HAS_SPEED }, + {"Heartbeat", HEARTBEAT, 1, 5, 3, 0xFF, 0, 2, MODE_COLORS_MODE_SPECIFIC, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_HAS_SPEED }, + {"Circle Spectrum",CIRCLE_SPECTRUM,1,5,3,0xFF, MODE_DIRECTION_LEFT,0, MODE_COLORS_NONE, MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_HAS_SPEED | + MODE_FLAG_HAS_DIRECTION_LR}, + {"Reactive Tornado",REACTIVE_TORNADO,1,5,3,0xFF,MODE_DIRECTION_LEFT,0, MODE_COLORS_NONE, MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_HAS_SPEED | + MODE_FLAG_HAS_DIRECTION_LR}, + {"Off", OFF, 0, 0, 0, 0xFF, MODE_DIRECTION_LEFT, 0, MODE_COLORS_NONE, 0}, + { 0, NONE, 0, 0, 0, 0, 0, 0, 0, 0}, +}; + +void CMKeyboardV2Controller::InitializeModes(std::vector &modes) +{ + stCMKeyboardV2_mode * pCurrentMode = CMKeyboardV2_modes; + + while(pCurrentMode->value != NONE) + { + mode m; + + m.name = std::string(pCurrentMode->name); + m.value = pCurrentMode->value; + m.flags = pCurrentMode->flags; + m.color_mode = pCurrentMode->color_mode; + m.speed_min = pCurrentMode->speed_min; + m.speed_max = pCurrentMode->speed_max; + m.speed = pCurrentMode->speed; + m.brightness_min = 0x00; + m.brightness_max = 0xFF; + m.brightness = 0xFF; + m.colors_min = pCurrentMode->nColors; + m.colors_max = pCurrentMode->nColors; + m.colors.resize(pCurrentMode->nColors); + m.direction = pCurrentMode->direction; + + modes.push_back(m); + + pCurrentMode++; + } +} diff --git a/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardV2Controller.h b/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardV2Controller.h new file mode 100644 index 00000000..99d9a8ca --- /dev/null +++ b/Controllers/CoolerMasterController/CMKeyboardController/CMKeyboardV2Controller.h @@ -0,0 +1,59 @@ +/*---------------------------------------------------------*\ +| CMKeyboardV2Controller.h | +| | +| Driver for Cooler Master V2 keyboards | +| | +| Tam D (too.manyhobbies) 30 Nov 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "CMKeyboardAbstractController.h" + +struct stCMKeyboardV2_mode +{ + const char *name; + unsigned int value; + unsigned int speed_min; + unsigned int speed_max; + unsigned int speed; + unsigned int brightness; + unsigned int direction; + unsigned int nColors; + unsigned int color_mode; + unsigned int flags; +}; + +class CMKeyboardV2Controller : public CMKeyboardAbstractController +{ +public: + CMKeyboardV2Controller(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name); + ~CMKeyboardV2Controller(); + + /*---------------------------------------------------------*\ + | Protocol specific funtions to be implmented | + \*---------------------------------------------------------*/ + void SetLeds(std::vector leds, std::vector colors); + void SetSingleLED(uint8_t in_led, RGBColor in_color); + void Initialize(); + void Shutdown(); + void SetLEDControl(bool bManual); + void SendApplyPacket(uint8_t mode); + void MagicStartupPacket(); + void MagicCommand(uint8_t profileId); + void SetCustomMode(); + void SetMode(mode selectedMode); + void SetEffect(uint8_t effectId, uint8_t p1, uint8_t p2, uint8_t p3, RGBColor color1, RGBColor color2); + void InitializeModes(std::vector &modes); + KEYBOARD_LAYOUT GetKeyboardLayout(); + +private: + void _SetEffectMode(uint8_t effectId); + void _UpdateSpeed(mode selectedMode, uint8_t &cSpeed1, uint8_t &cSpeed2); + std::string _GetFirmwareVersion(); + + bool m_bMoreFFs; +}; diff --git a/Controllers/CoolerMasterController/CMKeyboardController/RGBController_CMKeyboardController.cpp b/Controllers/CoolerMasterController/CMKeyboardController/RGBController_CMKeyboardController.cpp new file mode 100644 index 00000000..1612d5df --- /dev/null +++ b/Controllers/CoolerMasterController/CMKeyboardController/RGBController_CMKeyboardController.cpp @@ -0,0 +1,197 @@ +/*---------------------------------------------------------*\ +| RGBController_CMKeyboardController.cpp | +| | +| RGBController for Cooler Master keyboards | +| | +| Tam D (too.manyhobbies) 30 Nov 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_CMKeyboardController.h" +#include "CMKeyboardDevices.h" + +/**------------------------------------------------------------------*\ + @name Coolermaster Masterkeys Keyboards + @category Keyboard + @type USB + @save :robot: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectCoolerMasterV1Keyboards,DetectCoolerMasterV2Keyboards + @comment + In CMKeyboardV1Controller brightness control not supported. + Supported effects differ between CMKeyboardV1Controller and + CMKeyboardV2Controller. +\*-------------------------------------------------------------------*/ +RGBController_CMKeyboardController::RGBController_CMKeyboardController(CMKeyboardAbstractController* pController) +{ + m_pController = pController; + vendor = m_pController->GetDeviceVendor(); + type = DEVICE_TYPE_KEYBOARD; + description = "Cooler Master Keyboard Device"; + version = m_pController->GetFirmwareVersion(); + + /*----------------------------------------------------------------*\ + | Coolermaster uses the name field to store the serial number in | + | many of their keyboards. | + \*----------------------------------------------------------------*/ + serial = m_pController->GetDeviceSerial(); + location = m_pController->GetLocation(); + m_keyboardLayout = m_pController->GetKeyboardLayout(); + name = m_pController->GetDeviceName(); + + m_pController->InitializeModes(modes); + + SetupZones(); +} + +RGBController_CMKeyboardController::~RGBController_CMKeyboardController() +{ + /*---------------------------------------------------------*\ + | Delete the matrix map | + \*---------------------------------------------------------*/ + for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++) + { + if(zones[zone_index].matrix_map != NULL) + { + if(zones[zone_index].matrix_map->map != NULL) + { + delete zones[zone_index].matrix_map->map; + } + + delete zones[zone_index].matrix_map; + } + } + + if(m_pController) + { + delete m_pController; + } +} + +#define COOLERMASTER_ZONES_MAX 1 +void RGBController_CMKeyboardController::SetupZones() +{ + std::string physical_size; + unsigned int max_led_value = 0; + const cm_kb_device* coolermaster = m_pController->GetDeviceData(); + + /*---------------------------------------------------------*\ + | Fill in zones from the device data | + \*---------------------------------------------------------*/ + for(size_t i = 0; i < COOLERMASTER_ZONES_MAX; i++) + { + if(coolermaster->zones[i] == NULL) + { + break; + } + else + { + zone new_zone; + + new_zone.name = coolermaster->zones[i]->name; + new_zone.type = coolermaster->zones[i]->type; + + if(new_zone.type == ZONE_TYPE_MATRIX) + { + KeyboardLayoutManager new_kb(m_keyboardLayout, coolermaster->layout_new->base_size, coolermaster->layout_new->key_values); + + matrix_map_type * new_map = new matrix_map_type; + new_zone.matrix_map = new_map; + + if(coolermaster->layout_new->base_size != KEYBOARD_SIZE_EMPTY) + { + /*---------------------------------------------------------*\ + | Minor adjustments to keyboard layout | + \*---------------------------------------------------------*/ + keyboard_keymap_overlay_values* temp = coolermaster->layout_new; + new_kb.ChangeKeys(*temp); + + new_map->height = new_kb.GetRowCount(); + new_map->width = new_kb.GetColumnCount(); + new_map->map = new unsigned int[new_map->height * new_map->width]; + + /*---------------------------------------------------------*\ + | Matrix map still uses declared zone rows and columns | + | as the packet structure depends on the matrix map | + \*---------------------------------------------------------*/ + new_kb.GetKeyMap(new_map->map, KEYBOARD_MAP_FILL_TYPE_COUNT, new_map->height, new_map->width); + + /*---------------------------------------------------------*\ + | Create LEDs for the Matrix zone | + | Place keys in the layout to populate the matrix | + \*---------------------------------------------------------*/ + new_zone.leds_count = new_kb.GetKeyCount(); + LOG_DEBUG("[%s] Created KB matrix with %d rows and %d columns containing %d keys", + m_pController->GetDeviceName().c_str(), new_kb.GetRowCount(), new_kb.GetColumnCount(), new_zone.leds_count); + + for(unsigned int led_idx = 0; led_idx < new_zone.leds_count; led_idx++) + { + led new_led; + + new_led.name = new_kb.GetKeyNameAt(led_idx); + new_led.value = new_kb.GetKeyValueAt(led_idx); + max_led_value = std::max(max_led_value, new_led.value); + leds.push_back(new_led); + } + } + + /*---------------------------------------------------------*\ + | Add 1 the max_led_value to account for the 0th index | + \*---------------------------------------------------------*/ + max_led_value++; + } + + /*---------------------------------------------------------*\ + | name is not set yet so description is used instead | + \*---------------------------------------------------------*/ + LOG_DEBUG("[%s] Creating a %s zone: %s with %d LEDs", description.c_str(), + ((new_zone.type == ZONE_TYPE_MATRIX) ? "matrix": "linear"), + new_zone.name.c_str(), new_zone.leds_count); + new_zone.leds_min = new_zone.leds_count; + new_zone.leds_max = new_zone.leds_count; + zones.push_back(new_zone); + + } + } + + + SetupColors(); +} + +void RGBController_CMKeyboardController::ResizeZone(int /*zone*/, int /*new_size*/) +{ +} + +void RGBController_CMKeyboardController::DeviceUpdateLEDs() +{ + m_pController->SetLeds(leds, colors); +} + +void RGBController_CMKeyboardController::UpdateSingleLED(int led, RGBColor color) +{ + uint8_t key_value = m_pLayoutManager->GetKeyValueAt(led); + m_pController->SetSingleLED(key_value, color); +} + +void RGBController_CMKeyboardController::UpdateSingleLED(int led) +{ + m_pController->SetSingleLED(led, colors[led]); +} + +void RGBController_CMKeyboardController::UpdateZoneLEDs(int /*zone_idx*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_CMKeyboardController::DeviceUpdateMode() +{ + m_pController->SetMode(modes[active_mode]); +} + +void RGBController_CMKeyboardController::SetCustomMode() +{ + +} diff --git a/Controllers/CoolerMasterController/CMKeyboardController/RGBController_CMKeyboardController.h b/Controllers/CoolerMasterController/CMKeyboardController/RGBController_CMKeyboardController.h new file mode 100644 index 00000000..db333229 --- /dev/null +++ b/Controllers/CoolerMasterController/CMKeyboardController/RGBController_CMKeyboardController.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------*\ +| RGBController_CMKeyboardController.h | +| | +| RGBController for Cooler Master keyboards | +| | +| Tam D (too.manyhobbies) 30 Nov 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "CMKeyboardAbstractController.h" +#include "CMKeyboardV1Controller.h" +#include "CMKeyboardV2Controller.h" +#include "CMKeyboardDevices.h" + +class RGBController_CMKeyboardController : public RGBController +{ +public: + RGBController_CMKeyboardController(CMKeyboardAbstractController* pController); + ~RGBController_CMKeyboardController(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateSingleLED(int led, RGBColor color); + void UpdateSingleLED(int led); + void UpdateZoneLEDs(int zone_idx); + + void SetCustomMode(); + void DeviceUpdateMode(); + +private: + CMKeyboardAbstractController* m_pController;; + KeyboardLayoutManager* m_pLayoutManager; + KEYBOARD_LAYOUT m_keyboardLayout; + layout_values m_layoutValues; +}; diff --git a/Controllers/CoolerMasterController/CMMKController.cpp b/Controllers/CoolerMasterController/CMMKController.cpp deleted file mode 100644 index e50d2308..00000000 --- a/Controllers/CoolerMasterController/CMMKController.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/*-------------------------------------------------------------------*\ -| CMMKController.cpp | -| | -| Driver for Coolermaster MasterKeys Keyboards | -| | -| Lukas N (chmod222) 28th Jun 2020 | -| Tam D (too.manyhobbies) 25th Apr 2021 | -| | -\*-------------------------------------------------------------------*/ - -#include "CMMKController.h" - -CMMKController::CMMKController(hid_device* dev, hid_device_info* dev_info) -{ - location = dev_info->path; - - const int szTemp = 256; - wchar_t tmpName[szTemp]; - - hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - vendor_name = std::string(wName.begin(), wName.end()); - - hid_get_product_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - device_name = std::string(wName.begin(), wName.end()); - - cmmk_attach_path(&cmmk_handle, dev_info->path, dev_info->product_id, -1); - - char buf[32] = {0}; - cmmk_get_firmware_version(&cmmk_handle, buf, 32); - - /*--------------------------------------------------------------*\ - | Adjust the row count for keyboards without the front light bar | - | Adjust the column count for TKL keyboards (i.e. x30 vs x50) | - \*--------------------------------------------------------------*/ - enum cmmk_product_type kb_type = cmmk_get_device_model(&cmmk_handle); - row_count = (kb_type == CMMK_PRODUCT_MASTERKEYS_MK750) ? CMMK_ROWS_MAX : CMMK_ROWS_MAX - 1; - switch(kb_type) - { - case CMMK_PRODUCT_MASTERKEYS_PRO_S: - case CMMK_PRODUCT_MASTERKEYS_SK630: - column_count = CMMK_COLS_MAX - 4; - break; - - case CMMK_PRODUCT_MASTERKEYS_PRO_L: - case CMMK_PRODUCT_MASTERKEYS_MK750: - case CMMK_PRODUCT_MASTERKEYS_SK650: - default: - column_count = CMMK_COLS_MAX; - } - - firmware_version = buf; -} - -CMMKController::~CMMKController() -{ - cmmk_detach(&cmmk_handle); -} - -std::string CMMKController::GetDeviceName() -{ - return device_name; -} - -std::string CMMKController::GetDeviceVendor() -{ - return vendor_name; -} - -std::string CMMKController::GetLocation() -{ - return location; -} - -std::string CMMKController::GetFirmwareVersion() -{ - return firmware_version; -} - -uint8_t CMMKController::GetRowCount() -{ - return row_count; -} - -uint8_t CMMKController::GetColumnCount() -{ - return column_count; -} - -void CMMKController::SetFirmwareControl() -{ - ActivateMode(CMMK_FIRMWARE); -} - -void CMMKController::SetManualControl() -{ - ActivateMode(CMMK_MANUAL); -} - -void CMMKController::SetSingle(int row, int col, struct rgb color) -{ - cmmk_set_single_key(&cmmk_handle, row, col, &color); -} - -void CMMKController::SetAll(struct cmmk_color_matrix const& colors) -{ - cmmk_set_leds(&cmmk_handle, &colors); -} - -void CMMKController::SetAllSingle(struct rgb color) -{ - cmmk_set_all_single(&cmmk_handle, &color); -} - -void CMMKController::SetMode(cmmk_effect_fully_lit eff) -{ - ActivateEffect(CMMK_EFFECT_FULLY_LIT); - cmmk_set_effect_fully_lit(&cmmk_handle, &eff); -} - -void CMMKController::SetMode(cmmk_effect_breathe eff) -{ - ActivateEffect(CMMK_EFFECT_BREATHE); - cmmk_set_effect_breathe(&cmmk_handle, &eff); -} - -void CMMKController::SetMode(cmmk_effect_cycle eff) -{ - ActivateEffect(CMMK_EFFECT_CYCLE); - cmmk_set_effect_cycle(&cmmk_handle, &eff); -} - -void CMMKController::SetMode(cmmk_effect_single eff) -{ - ActivateEffect(CMMK_EFFECT_SINGLE); - cmmk_set_effect_single(&cmmk_handle, &eff); -} - -void CMMKController::SetMode(cmmk_effect_wave eff) -{ - ActivateEffect(CMMK_EFFECT_WAVE); - cmmk_set_effect_wave(&cmmk_handle, &eff); -} - -void CMMKController::SetMode(cmmk_effect_ripple eff) -{ - ActivateEffect(CMMK_EFFECT_RIPPLE); - cmmk_set_effect_ripple(&cmmk_handle, &eff); -} - -void CMMKController::SetMode(cmmk_effect_cross eff) -{ - ActivateEffect(CMMK_EFFECT_CROSS); - cmmk_set_effect_cross(&cmmk_handle, &eff); -} - -void CMMKController::SetMode(cmmk_effect_raindrops eff) -{ - ActivateEffect(CMMK_EFFECT_RAINDROPS); - cmmk_set_effect_raindrops(&cmmk_handle, &eff); -} - -void CMMKController::SetMode(cmmk_effect_stars eff) -{ - ActivateEffect(CMMK_EFFECT_STARS); - cmmk_set_effect_stars(&cmmk_handle, &eff); -} - -void CMMKController::SetMode(cmmk_effect_snake eff) -{ - ActivateEffect(CMMK_EFFECT_SNAKE); - cmmk_set_effect_snake(&cmmk_handle, &eff); -} - -bool CMMKController::PositionValid(int y, int x) -{ - return(cmmk_lookup_key_id(&cmmk_handle, y, x) >= 0); -} - -void CMMKController::ActivateMode(int mode) -{ - if (current_mode != mode) - { - cmmk_set_control_mode(&cmmk_handle, mode); - - current_mode = mode; - current_effect = -1; - } -} - -void CMMKController::ActivateEffect(int effect) -{ - ActivateMode(CMMK_EFFECT); - - if (current_effect != effect) - { - cmmk_set_active_effect(&cmmk_handle, (enum cmmk_effect_id)effect); - - current_effect = effect; - } -} diff --git a/Controllers/CoolerMasterController/CMMKController.h b/Controllers/CoolerMasterController/CMMKController.h deleted file mode 100644 index 641a0de1..00000000 --- a/Controllers/CoolerMasterController/CMMKController.h +++ /dev/null @@ -1,64 +0,0 @@ -/*-------------------------------------------------------------------*\ -| CMMKController.h | -| | -| Driver for Coolermaster MasterKeys keyboards | -| | -| Lukas N (chmod222) 28th Jun 2020 | -| | -\*-------------------------------------------------------------------*/ - -#include -#include -#include - -#pragma once - -class CMMKController -{ -public: - CMMKController(hid_device* dev_handle, hid_device_info* dev_info); - ~CMMKController(); - - std::string GetDeviceName(); - std::string GetDeviceVendor(); - std::string GetLocation(); - std::string GetFirmwareVersion(); - uint8_t GetRowCount(); - uint8_t GetColumnCount(); - - void SetFirmwareControl(); - void SetManualControl(); - - void SetSingle(int row, int col, struct rgb color); - void SetAll(struct cmmk_color_matrix const& colors); - void SetAllSingle(struct rgb color); - - void SetMode(cmmk_effect_fully_lit eff); - void SetMode(cmmk_effect_breathe eff); - void SetMode(cmmk_effect_cycle eff); - void SetMode(cmmk_effect_single eff); - void SetMode(cmmk_effect_wave eff); - void SetMode(cmmk_effect_ripple eff); - void SetMode(cmmk_effect_cross eff); - void SetMode(cmmk_effect_raindrops eff); - void SetMode(cmmk_effect_stars eff); - void SetMode(cmmk_effect_snake eff); - - bool PositionValid(int y, int x); - -private: - void ActivateMode(int mode); - void ActivateEffect(int effect); - - int current_mode = -1; - int current_effect = -1; - - std::string device_name; - std::string vendor_name; - std::string location; - std::string firmware_version; - uint8_t row_count; - uint8_t column_count; - - mutable struct cmmk cmmk_handle; -}; diff --git a/Controllers/CoolerMasterController/CMMM711Controller.cpp b/Controllers/CoolerMasterController/CMMM711Controller/CMMM711Controller.cpp similarity index 76% rename from Controllers/CoolerMasterController/CMMM711Controller.cpp rename to Controllers/CoolerMasterController/CMMM711Controller/CMMM711Controller.cpp index 4b2e0146..e6cc5007 100644 --- a/Controllers/CoolerMasterController/CMMM711Controller.cpp +++ b/Controllers/CoolerMasterController/CMMM711Controller/CMMM711Controller.cpp @@ -1,35 +1,34 @@ -/*-------------------------------------------------------------------*\ -| CMMM711Controller.cpp | -| | -| Driver for Coolermaster Master Mouse 711 | -| | -| Chris M (Dr_No) 14th Feb 2021 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| CMMM711Controller.cpp | +| | +| Driver for Cooler Master M711 mouse | +| | +| Chris M (Dr_No) 14 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "CMMM711Controller.h" #include +#include "CMMM711Controller.h" +#include "StringUtils.h" CMMM711Controller::CMMM711Controller(hid_device* dev_handle, char *_path) { - const int szTemp = HID_MAX_STR; - wchar_t tmpName[szTemp]; - dev = dev_handle; location = _path; current_speed = CM_MM711_SPEED_NORMAL; - hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - device_name = std::string(wName.begin(), wName.end()); + /*---------------------------------------------------------*\ + | Get device name from HID manufacturer and product strings | + \*---------------------------------------------------------*/ + wchar_t name_string[HID_MAX_STR]; - hid_get_product_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); + hid_get_manufacturer_string(dev, name_string, HID_MAX_STR); + device_name = StringUtils::wstring_to_string(name_string); - hid_get_indexed_string(dev, 2, tmpName, szTemp); - wName = std::wstring(tmpName); - serial = std::string(wName.begin(), wName.end()); + hid_get_product_string(dev, name_string, HID_MAX_STR); + device_name.append(" ").append(StringUtils::wstring_to_string(name_string)); SendInitPacket(); GetColourStatus(); @@ -87,12 +86,20 @@ void CMMM711Controller::GetModeStatus() std::string CMMM711Controller::GetDeviceName() { - return device_name; + return(device_name); } std::string CMMM711Controller::GetSerial() { - return serial; + wchar_t serial_string[HID_MAX_STR]; + int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } std::string CMMM711Controller::GetLocation() @@ -102,37 +109,37 @@ std::string CMMM711Controller::GetLocation() unsigned char CMMM711Controller::GetMode() { - return current_mode; + return(current_mode); } unsigned char CMMM711Controller::GetLedRed() { - return current_red; + return(current_red); } unsigned char CMMM711Controller::GetLedGreen() { - return current_green; + return(current_green); } unsigned char CMMM711Controller::GetLedBlue() { - return current_blue; + return(current_blue); } unsigned char CMMM711Controller::GetLedSpeed() { - return current_speed; + return(current_speed); } RGBColor CMMM711Controller::GetWheelColour() { - return wheel_colour; + return(wheel_colour); } RGBColor CMMM711Controller::GetLogoColour() { - return logo_colour; + return(logo_colour); } void CMMM711Controller::SetLedsDirect(RGBColor wheel_colour, RGBColor logo_colour) diff --git a/Controllers/CoolerMasterController/CMMM711Controller.h b/Controllers/CoolerMasterController/CMMM711Controller/CMMM711Controller.h similarity index 81% rename from Controllers/CoolerMasterController/CMMM711Controller.h rename to Controllers/CoolerMasterController/CMMM711Controller/CMMM711Controller.h index 141721b1..b95ebd2a 100644 --- a/Controllers/CoolerMasterController/CMMM711Controller.h +++ b/Controllers/CoolerMasterController/CMMM711Controller/CMMM711Controller.h @@ -1,19 +1,21 @@ -/*-------------------------------------------------------------------*\ -| CMMM711Controller.h | -| | -| Driver for Coolermaster Master Mouse 711 | -| | -| Chris M (Dr_No) 14th Feb 2021 | -| | -\*-------------------------------------------------------------------*/ - -#include -#include -#include -#include "RGBController.h" +/*---------------------------------------------------------*\ +| CMMM711Controller.h | +| | +| Driver for Cooler Master M711 mouse | +| | +| Chris M (Dr_No) 14 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include +#include "RGBController.h" + #define CM_MM711_PACKET_SIZE 65 #define CM_MM711_COLOUR_MODE_DATA_SIZE (sizeof(colour_mode_data[0]) / sizeof(colour_mode_data[0][0])) #define CM_MM711_HEADER_DATA_SIZE (sizeof(argb_header_data) / sizeof(argb_headers) ) diff --git a/Controllers/CoolerMasterController/RGBController_CMMM711Controller.cpp b/Controllers/CoolerMasterController/CMMM711Controller/RGBController_CMMM711Controller.cpp similarity index 85% rename from Controllers/CoolerMasterController/RGBController_CMMM711Controller.cpp rename to Controllers/CoolerMasterController/CMMM711Controller/RGBController_CMMM711Controller.cpp index 283f1490..cda06f4e 100644 --- a/Controllers/CoolerMasterController/RGBController_CMMM711Controller.cpp +++ b/Controllers/CoolerMasterController/CMMM711Controller/RGBController_CMMM711Controller.cpp @@ -1,16 +1,18 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMMM711Controller.cpp | -| | -| Driver for Coolermaster MM711 Controller | -| | -| Chris M (Dr_No) 14th Feb 2021 | -| | -\*-------------------------------------------------------------------*/ - -#define applyBrightness(c, bright) ((RGBColor) ((RGBGetBValue(c) * bright / CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT) << 16 | (RGBGetGValue(c) * bright / CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT) << 8 | (RGBGetRValue(c) * bright / CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT))) +/*---------------------------------------------------------*\ +| RGBController_CMMM711Controller.cpp | +| | +| RGBController for Cooler Master M711 mouse | +| | +| Chris M (Dr_No) 14 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CMMM711Controller.h" +#define applyBrightness(c, bright) ((RGBColor) ((RGBGetBValue(c) * bright / CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT) << 16 | (RGBGetGValue(c) * bright / CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT) << 8 | (RGBGetRValue(c) * bright / CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT))) + /**------------------------------------------------------------------*\ @name Coolermaster Master Mouse @category Mouse @@ -107,16 +109,16 @@ RGBController_CMMM711Controller::RGBController_CMMM711Controller(CMMM711Controll uint8_t temp_mode = controller->GetMode(); - for(std::size_t mode_index = 0; mode_index < modes.size(); mode_index++) + for(int mode_index = 0; mode_index < (int)modes.size(); mode_index++) { - if (modes[mode_index].value == temp_mode) + if(modes[mode_index].value == temp_mode) { active_mode = mode_index; break; } } - if (modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) { modes[active_mode].colors[0] = ToRGBColor(controller->GetLedRed(),controller->GetLedGreen(),controller->GetLedBlue()); } @@ -182,25 +184,13 @@ void RGBController_CMMM711Controller::UpdateSingleLED(int /*led*/) DeviceUpdateLEDs(); } -void RGBController_CMMM711Controller::SetCustomMode() -{ - for(std::size_t mode_index = 0; mode_index < modes.size(); mode_index++) - { - if (modes[mode_index].value == CM_MM711_MODE_CUSTOM) - { - active_mode = mode_index; - break; - } - } -} - void RGBController_CMMM711Controller::DeviceUpdateMode() { RGBColor colour = 0; - if (modes[active_mode].value != CM_MM711_MODE_CUSTOM) + if(modes[active_mode].value != CM_MM711_MODE_CUSTOM) { - if( modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC ) + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC ) { colour = modes[active_mode].colors[0]; } diff --git a/Controllers/CoolerMasterController/CMMM711Controller/RGBController_CMMM711Controller.h b/Controllers/CoolerMasterController/CMMM711Controller/RGBController_CMMM711Controller.h new file mode 100644 index 00000000..b993e444 --- /dev/null +++ b/Controllers/CoolerMasterController/CMMM711Controller/RGBController_CMMM711Controller.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------*\ +| RGBController_CMMM711Controller.h | +| | +| RGBController for Cooler Master M711 mouse | +| | +| Chris M (Dr_No) 14 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "CMMM711Controller.h" + +#define CM_MM_ARGB_BRIGHTNESS_MIN 0x00 +#define CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT 0xFF +#define CM_MM_ARGB_BRIGHTNESS_MAX_SPECTRUM 0x7F + +class RGBController_CMMM711Controller : public RGBController +{ +public: + RGBController_CMMM711Controller(CMMM711Controller* controller_ptr); + ~RGBController_CMMM711Controller(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); +private: + void Init_Controller(); + int GetDeviceMode(); + + CMMM711Controller* controller; +}; diff --git a/Controllers/CoolerMasterController/CMMM712Controller/CMMM712Controller.cpp b/Controllers/CoolerMasterController/CMMM712Controller/CMMM712Controller.cpp new file mode 100644 index 00000000..95a37fbe --- /dev/null +++ b/Controllers/CoolerMasterController/CMMM712Controller/CMMM712Controller.cpp @@ -0,0 +1,192 @@ +/*---------------------------------------------------------*\ +| CMMM712Controller.cpp | +| | +| Driver for Cooler Master MM712 mouse | +| Derived from CMMM711Controller.cpp | +| | +| Chris M (Dr_No) 14 Feb 2021 | +| Frans Meulenbroeks 08 Dec 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "CMMM712Controller.h" +#include "StringUtils.h" + +#define CM_MM712_PACKET_SIZE 65 +#define CM_MM712_INTERRUPT_TIMEOUT 250 +#define HID_MAX_STR 255 + +enum +{ + CM_MM712_MODE_BYTE = 4, + CM_MM712_BRIGHTNESS_BYTE = 6, + CM_MM712_SPEED_BYTE = 7, + CM_MM712_RED_BYTE = 8, + CM_MM712_GREEN_BYTE = 9, + CM_MM712_BLUE_BYTE = 10, +}; + +CMMM712Controller::CMMM712Controller(hid_device* dev_handle, char *_path) +{ + dev = dev_handle; + location = _path; + + /*---------------------------------------------------------*\ + | Get device name from HID manufacturer and product strings | + \*---------------------------------------------------------*/ + wchar_t name_string[HID_MAX_STR]; + + hid_get_manufacturer_string(dev, name_string, HID_MAX_STR); + device_name = StringUtils::wstring_to_string(name_string); + + hid_get_product_string(dev, name_string, HID_MAX_STR); + device_name.append(" ").append(StringUtils::wstring_to_string(name_string)); + + SendInitPacket(); + GetModeStatus(); + GetColorStatus(current_mode); +} + +CMMM712Controller::~CMMM712Controller() +{ + hid_close(dev); +} + +void CMMM712Controller::SendBuffer(uint8_t *buffer, uint8_t buffer_size) +{ + hid_write(dev, buffer, buffer_size); + hid_read_timeout(dev, buffer, buffer_size, CM_MM712_INTERRUPT_TIMEOUT); +} + +void CMMM712Controller::GetColorStatus(uint8_t mode) +{ + uint8_t buffer[CM_MM712_PACKET_SIZE] = { 0x00, 0x4C, 0x81, 0x03, mode }; + + SendBuffer(buffer, CM_MM712_PACKET_SIZE); + initial_color = ToRGBColor(buffer[CM_MM712_RED_BYTE - 2], buffer[CM_MM712_GREEN_BYTE - 2], buffer[CM_MM712_BLUE_BYTE - 2]); +} + +void CMMM712Controller::GetModeStatus() +{ + uint8_t buffer[CM_MM712_PACKET_SIZE] = { 0x00, 0x4C, 0x81, 0x07 }; + + SendBuffer(buffer, CM_MM712_PACKET_SIZE); + current_mode = buffer[CM_MM712_MODE_BYTE - 1]; + SetMode(current_mode); +} + +std::string CMMM712Controller::GetDeviceName() +{ + return(device_name); +} + +std::string CMMM712Controller::GetSerial() +{ + wchar_t serial_string[HID_MAX_STR]; + int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string CMMM712Controller::GetLocation() +{ + return("HID: " + location); +} + +unsigned char CMMM712Controller::GetMode() +{ + return(current_mode); +} + +RGBColor CMMM712Controller::GetInitialLedColor() +{ + return initial_color; +} + +void CMMM712Controller::SetLedsDirect(RGBColor color) +{ + unsigned char buffer[CM_MM712_PACKET_SIZE] = + { + 0x00, 0x5A, 0x81, 0x03, + (unsigned char)RGBGetRValue(color), + (unsigned char)RGBGetGValue(color), + (unsigned char)RGBGetBValue(color) + }; + + if(current_mode!=CM_MM712_MODE_DIRECT) + { + SetDirectMode(true); + } + hid_write(dev, buffer, CM_MM712_PACKET_SIZE); +// SendBuffer(buffer, CM_MM712_PACKET_SIZE); +} + +void CMMM712Controller::SendUpdate(uint8_t mode, uint8_t speed, RGBColor color, uint8_t brightness) +{ + unsigned char buffer[CM_MM712_PACKET_SIZE] = + { + 0x00, 0x4C, 0x81, 0x04, mode, 0xFF, brightness, speed, + (unsigned char)RGBGetRValue(color), + (unsigned char)RGBGetGValue(color), + (unsigned char)RGBGetBValue(color), + 0xFF + }; + + if(current_mode==CM_MM712_MODE_DIRECT) + { + SetDirectMode(false); + SendInitPacket(); + } + + SendBuffer(buffer, CM_MM712_PACKET_SIZE); + SetMode(mode); +} + +void CMMM712Controller::SendInitPacket() +{ + unsigned char buffer[CM_MM712_PACKET_SIZE] = { 0x00, 0x44, 0x81, 0x02 }; + + SendBuffer(buffer, CM_MM712_PACKET_SIZE); +} + +void CMMM712Controller::SetDirectMode(bool onoff) +{ + unsigned char buffer[CM_MM712_PACKET_SIZE] = { 0x00, 0x5a, 0x81, (unsigned char)(0x01+onoff) }; + + hid_write(dev, buffer, CM_MM712_PACKET_SIZE); +} + +void CMMM712Controller::SetMode(uint8_t mode) +{ + unsigned char buffer[CM_MM712_PACKET_SIZE] = { 0x00, 0x4C, 0x81, 0x08, mode}; + + if(current_mode==CM_MM712_MODE_DIRECT) + { + SendInitPacket(); + } + + SendBuffer(buffer, CM_MM712_PACKET_SIZE); + current_mode = mode; +} + +void CMMM712Controller::SetProfile(uint8_t profile) +{ + unsigned char buffer[CM_MM712_PACKET_SIZE] = { 0x00, 0x44, 0x81, 0x01, profile}; + + SendBuffer(buffer, CM_MM712_PACKET_SIZE); +} + +void CMMM712Controller::SaveStatus() +{ + unsigned char buffer[CM_MM712_PACKET_SIZE] = { 0x54, 0x81, 1}; + + SendBuffer(buffer, CM_MM712_PACKET_SIZE); +} diff --git a/Controllers/CoolerMasterController/CMMM712Controller/CMMM712Controller.h b/Controllers/CoolerMasterController/CMMM712Controller/CMMM712Controller.h new file mode 100644 index 00000000..cf05f97c --- /dev/null +++ b/Controllers/CoolerMasterController/CMMM712Controller/CMMM712Controller.h @@ -0,0 +1,69 @@ +/*---------------------------------------------------------*\ +| CMMM712Controller.h | +| | +| Driver for Cooler Master MM712 mouse | +| Derived from CMMM711Controller.h | +| | +| Chris M (Dr_No) 14 Feb 2021 | +| Frans Meulenbroeks 08 Dec 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +enum +{ + CM_MM712_MODE_STATIC = 0, //Static Mode + CM_MM712_MODE_BREATHING = 1, //Breathing Mode + CM_MM712_MODE_SPECTRUM_CYCLE = 2, //Spectrum Cycle Mode + CM_MM712_MODE_OFF = 3, //Turn Off + CM_MM712_MODE_DIRECT = 4, //Direct LED Control +}; + +enum +{ + CM_MM712_SPEED_SLOWEST = 0x0, //Slowest speed + CM_MM712_SPEED_NORMAL = 0x2, //Normal speed + CM_MM712_SPEED_FASTEST = 0x4, //Fastest speed +}; + +class CMMM712Controller +{ +public: + CMMM712Controller(hid_device* dev_handle, char *_path); + ~CMMM712Controller(); + + std::string GetDeviceName(); + std::string GetSerial(); + std::string GetLocation(); + + uint8_t GetMode(); + RGBColor GetInitialLedColor(); + + void SendUpdate(uint8_t mode, uint8_t speed, RGBColor color, uint8_t brightness); + void SetMode(uint8_t mode); + void SetDirectMode(bool onoff); + void SetLedsDirect(RGBColor color); + void SaveStatus(); +private: + std::string device_name; + std::string serial; + std::string location; + hid_device* dev; + + uint8_t current_mode; + RGBColor initial_color; + + void GetColorStatus(uint8_t mode); + void GetModeStatus(); + void SendInitPacket(); + void SetProfile(uint8_t profile); + void SendBuffer(uint8_t *buffer, uint8_t buffer_size); + +}; diff --git a/Controllers/CoolerMasterController/CMMM712Controller/MM712protocol.txt b/Controllers/CoolerMasterController/CMMM712Controller/MM712protocol.txt new file mode 100644 index 00000000..deebfd32 --- /dev/null +++ b/Controllers/CoolerMasterController/CMMM712Controller/MM712protocol.txt @@ -0,0 +1,108 @@ +Analysis of the MM712 protocol +By Frans Meulenbroeks +PID 0x2516, VID 0x0169 +We must use interface 3 +C = Command, R = Response + +Init: +===== +C: 0x00 0x44 0x81 0x02 +R: 0x45 0x81 0x02 0x02 0x01 +First byte is second byte of command+1, 2nd and 3rd byte are the 3rd and 4th byte of the command +No idea what the last two bytes are. +This init command inits to normal state. +After that one can submit all normal commands. These give a response. + +C: 0x00 0x5a 0x81 0x02 +R: 0x5b 0x81 0x02 +This init command inits to direct state. +After that one can submit all direct state commands. These give no response + +Note that you can always change between the two states by giving the appropriate init command. + +I have also seen +C: 0x00, 0x46, 0x81 +0x46 is command code +R: 47 81 50 03 00 00 f2 9b 1e 00 64 02 00 00 00 ff 03 06 00 ... +No idea what the response data is +This also brought the device to type-4 state. + +NORMAL COMMANDS +=============== + +Query stored colors: +==================== +C: 0x00 0x4c 0x81 0x03 0 +R: 0x4d 0x81 0x03 0x06 0xff 0x00 0xff 0xff 0x00 + Brig Spee Red Gree Blue Speed is not really relevant +These are the settings for the static mode + +C: 0x00 0x4c 0x81 0x03 1 +R: 0x4d 0x81 0x03 0xff 0xff 0x04 0xff 0x00 0x00 0xff + Brig Spee Red Gree Blue +These are the settings for the breathing mode + +C: 0x00 0x4c 0x81 0x03 2 +R: 0x81 0x03 0x06 0x7f 0x02 + Brig Spee +These are the settings for the cycling mode + +C: 0x00 0x4c 0x81 0x03 3 +R: 0x4d 0x81 0x03 0x06 0x00 +This is the response for the off mode +Other/higher numbers also return this value + +Detecting the mode: +=================== +C: 0x00 0x4c 0x81 0x07 +R: 0x4d 0x81 0x07 0x01 + ^ actual mode + +Setting the mode: +================= +C: 0x00 0x4c 0x81 0x08 0x01 + ^ new mode 0=static,1=breathing,2=cycling,3 or higher=off +R: 0x4d 0x81 0x07 0x01 + can't explain the 0x07; later calls returned 0x08 in this field + +C: 0x00 0x4c 0x81 0x08 0x02 +R: 0x4d 0x81 0x08 0x02 + +Setting the color: +================== +C: 0x00 0x4c 0x81 0x04 0x00 0xff 0xff 0x02 0x00 0xff 0x00 + cmd mode ???? brig spee red gree blue Speed is only relevant for breathing and cyclic, color is not relevant for cyclic + This sets the color, speed and brightness for the specific mode. + Note that this does not imply a mode switch + The first 0xff byte does not seem to do anything. I've changed to a different number but saw no result +R: 0x47 0x81 0x50 0x03 0x00 0x00 0xf2 0x9b 0x1e 0x00 0x64 0x02 0x00 0x00 0x00 0xff 0x01 0xff 0x00 0x00 +No idea what this means, Reply seems independent of color set + +Saving values: +============== +C: 0x00 0x54 0x81 0x01 +This saves the actual color for all modes and the mode itself to internal flash +R: 0x55 0x81 0x01 0x00 + +Change Profile +============== +C: 0x00 0x44 0x81 0x01 0x02 + ^ new profile must be in [0..4] otherwise this is a no-op +R: 0x45 0x81 0x01 0x02 0x01 + ^ it is unclear what this value is, values 0, 1 and 2 are observed + + +DIRECT COMMANDS +============== +C: 0x00 0x5a 0x81 0x01 +Leave direct state (return to normal, note that a new init for normal is needed) + +C: 0x00 0x5a 0x81 0x03 0xff 0x00 0x25 + red gree blue This changes the color right away. No response is generated. + CoolerMaster MasterPlus software uses this to dynamically generate animations + +Final notes: +It is possible to change the mode on the mouse (see mouse doc). +This also changes the value in flash +It is also possible to change the colors in mode 0 and 1 using the mouse. +8 different colors can be selected. I did not find a way to define these colors from software so I suspect these are hardcoded diff --git a/Controllers/CoolerMasterController/CMMM712Controller/RGBController_CMMM712Controller.cpp b/Controllers/CoolerMasterController/CMMM712Controller/RGBController_CMMM712Controller.cpp new file mode 100644 index 00000000..cb830353 --- /dev/null +++ b/Controllers/CoolerMasterController/CMMM712Controller/RGBController_CMMM712Controller.cpp @@ -0,0 +1,199 @@ +/*---------------------------------------------------------*\ +| RGBController_CMMM712Controller.cpp | +| | +| RGBController for Cooler Master MM712 mouse | +| Derived from RGBController_CMMM712Controller.cpp | +| | +| Chris M (Dr_No) 14 Feb 2021 | +| Frans Meulenbroeks 08 Dec 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_CMMM712Controller.h" + +#define applyBrightness(c, bright) ((RGBColor) ((RGBGetBValue(c) * bright / CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT) << 16 | (RGBGetGValue(c) * bright / CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT) << 8 | (RGBGetRValue(c) * bright / CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT))) + +/**------------------------------------------------------------------*\ + @name Coolermaster Master Mouse + @category Mouse + @type USB + @save :robot: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectCoolerMasterMouse + @comment +\*-------------------------------------------------------------------*/ + +RGBController_CMMM712Controller::RGBController_CMMM712Controller(CMMM712Controller* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "Cooler Master"; + type = DEVICE_TYPE_MOUSE; + description = controller->GetDeviceName(); + serial = controller->GetSerial(); + location = controller->GetLocation(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = CM_MM712_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.brightness_min = CM_MM_ARGB_BRIGHTNESS_MIN; + Direct.brightness_max = CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT; + Direct.brightness = CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Static; + Static.name = "Static"; + Static.value = CM_MM712_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Static.brightness_min = CM_MM_ARGB_BRIGHTNESS_MIN; + Static.brightness_max = CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT; + Static.brightness = CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.resize(Static.colors_max); + Static.speed_min = CM_MM712_SPEED_SLOWEST; + Static.speed_max = CM_MM712_SPEED_FASTEST; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.speed = CM_MM712_SPEED_NORMAL; + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = CM_MM712_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Breathing.brightness_min = CM_MM_ARGB_BRIGHTNESS_MIN; + Breathing.brightness_max = CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT; + Breathing.brightness = CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.colors.resize(Breathing.colors_max); + Breathing.speed_min = CM_MM712_SPEED_SLOWEST; + Breathing.speed_max = CM_MM712_SPEED_FASTEST; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.speed = CM_MM712_SPEED_NORMAL; + modes.push_back(Breathing); + + mode Spectrum_Cycle; + Spectrum_Cycle.name = "Spectrum Cycle"; + Spectrum_Cycle.value = CM_MM712_MODE_SPECTRUM_CYCLE; + Spectrum_Cycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Spectrum_Cycle.brightness_min = CM_MM_ARGB_BRIGHTNESS_MIN; + Spectrum_Cycle.brightness_max = CM_MM_ARGB_BRIGHTNESS_MAX_SPECTRUM; + Spectrum_Cycle.brightness = CM_MM_ARGB_BRIGHTNESS_MAX_SPECTRUM; + Spectrum_Cycle.speed_min = CM_MM712_SPEED_SLOWEST; + Spectrum_Cycle.speed_max = CM_MM712_SPEED_FASTEST; + Spectrum_Cycle.color_mode = MODE_COLORS_NONE; + Spectrum_Cycle.speed = CM_MM712_SPEED_NORMAL; + modes.push_back(Spectrum_Cycle); + + mode Off; + Off.name = "Off"; + Off.value = CM_MM712_MODE_OFF; + Off.flags = MODE_FLAG_MANUAL_SAVE; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + Init_Controller(); //Only processed on first run + SetupZones(); + + uint8_t temp_mode = controller->GetMode(); + + for(int mode_index = 0; mode_index < (int)modes.size(); mode_index++) + { + if(modes[mode_index].value == temp_mode) + { + active_mode = mode_index; + break; + } + } + + colors[0] = controller->GetInitialLedColor(); + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + modes[active_mode].colors[0] = colors[0]; + } +} + +RGBController_CMMM712Controller::~RGBController_CMMM712Controller() +{ + delete controller; +} + +void RGBController_CMMM712Controller::Init_Controller() +{ + zone mouse_zone; + mouse_zone.name = name; + mouse_zone.type = ZONE_TYPE_SINGLE; + mouse_zone.leds_min = 1; + mouse_zone.leds_max = 1; + mouse_zone.leds_count = 1; + mouse_zone.matrix_map = NULL; + zones.push_back(mouse_zone); + + led logo_led; + logo_led.name = "Logo LED"; + logo_led.value = 0; + leds.push_back(logo_led); +} + +void RGBController_CMMM712Controller::SetupZones() +{ + SetupColors(); +} + +void RGBController_CMMM712Controller::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_CMMM712Controller::DeviceUpdateLEDs() +{ + modes[active_mode].brightness=255; + RGBColor logo = applyBrightness(colors[0], modes[active_mode].brightness); + + controller->SetLedsDirect(logo); +} + +void RGBController_CMMM712Controller::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_CMMM712Controller::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_CMMM712Controller::DeviceUpdateMode() +{ + if(modes[active_mode].value==CM_MM712_MODE_DIRECT) + { + controller->SetDirectMode(true); + } + else + { + controller->SetDirectMode(false); + RGBColor colour = 0; + + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC ) + { + colour = modes[active_mode].colors[0]; + } + + controller->SendUpdate(modes[active_mode].value, modes[active_mode].speed, colour, modes[active_mode].brightness); + } +} + +void RGBController_CMMM712Controller::DeviceSaveMode() +{ + DeviceUpdateMode(); + controller->SaveStatus(); +} diff --git a/Controllers/CoolerMasterController/CMMM712Controller/RGBController_CMMM712Controller.h b/Controllers/CoolerMasterController/CMMM712Controller/RGBController_CMMM712Controller.h new file mode 100644 index 00000000..52ed4cf1 --- /dev/null +++ b/Controllers/CoolerMasterController/CMMM712Controller/RGBController_CMMM712Controller.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------*\ +| RGBController_CMMM712Controller.h | +| | +| RGBController for Cooler Master M712 mouse | +| Derived from RGBController_CMMM712Controller.h | +| | +| Chris M (Dr_No) 14 Feb 2021 | +| Frans Meulenbroeks 08 Dec 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "CMMM712Controller.h" + +#define CM_MM_ARGB_BRIGHTNESS_MIN 0x00 +#define CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT 0xFF +#define CM_MM_ARGB_BRIGHTNESS_MAX_SPECTRUM 0x7F + +class RGBController_CMMM712Controller : public RGBController +{ +public: + RGBController_CMMM712Controller(CMMM712Controller* controller_ptr); + ~RGBController_CMMM712Controller(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); +private: + void Init_Controller(); + + CMMM712Controller* controller; +}; diff --git a/Controllers/CoolerMasterController/CMMMController.cpp b/Controllers/CoolerMasterController/CMMMController/CMMMController.cpp similarity index 88% rename from Controllers/CoolerMasterController/CMMMController.cpp rename to Controllers/CoolerMasterController/CMMMController/CMMMController.cpp index 1cb1e27a..ecf989d7 100644 --- a/Controllers/CoolerMasterController/CMMMController.cpp +++ b/Controllers/CoolerMasterController/CMMMController/CMMMController.cpp @@ -1,32 +1,26 @@ -/*-------------------------------------------------------------------*\ -| CMMMController.cpp | -| | -| Driver for Coolermaster MasterMouse | -| | -| Chris M (Dr_No) 14th Feb 2021 - MM711 Base | -| Dracrius 12th Mar 2022 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| CMMMController.cpp | +| | +| Driver for Cooler Master mouse | +| | +| Chris M (Dr_No) 14 Feb 2021 | +| Dracrius 12 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "CMMMController.h" #include +#include "CMMMController.h" +#include "StringUtils.h" -CMMMController::CMMMController(hid_device* dev_handle, char *_path, uint16_t pid) : product_id(pid) +CMMMController::CMMMController(hid_device* dev_handle, char *_path, uint16_t pid, std::string dev_name) { - const int szTemp = HID_MAX_STR; - wchar_t tmpName[szTemp]; - dev = dev_handle; location = _path; + name = dev_name; current_speed = CM_MM_SPEED_3; - - hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - vendor = std::string(wName.begin(), wName.end()); - - hid_get_indexed_string(dev, 2, tmpName, szTemp); - wName = std::wstring(tmpName); - serial = std::string(wName.begin(), wName.end()); + product_id = pid; if(product_id == CM_MM530_PID || product_id == CM_MM531_PID) { @@ -60,8 +54,8 @@ CMMMController::CMMMController(hid_device* dev_handle, char *_path, uint16_t pid wheel_bytes[0] = CM_MM_MODE_BYTE; wheel_bytes[1] = CM_MM_SPEED_BYTE; wheel_bytes[2] = CM_MM_NFI_1; - } - + } + logo_bytes[0] = CM_MM_NFI_2; logo_bytes[1] = CM_MM_NFI_3; logo_bytes[2] = CM_MM_BRIGHTNESS_BYTE; @@ -123,12 +117,28 @@ void CMMMController::GetModeStatus() std::string CMMMController::GetDeviceVendor() { - return vendor; + wchar_t vendor_string[HID_MAX_STR]; + int ret = hid_get_manufacturer_string(dev, vendor_string, HID_MAX_STR); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(vendor_string)); } std::string CMMMController::GetSerial() { - return serial; + wchar_t serial_string[HID_MAX_STR]; + int ret = hid_get_indexed_string(dev, 2, serial_string, HID_MAX_STR); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } std::string CMMMController::GetLocation() @@ -136,6 +146,11 @@ std::string CMMMController::GetLocation() return("HID: " + location); } +std::string CMMMController::GetName() +{ + return(name); +} + uint16_t CMMMController::GetProductID() { return product_id; diff --git a/Controllers/CoolerMasterController/CMMMController.h b/Controllers/CoolerMasterController/CMMMController/CMMMController.h similarity index 84% rename from Controllers/CoolerMasterController/CMMMController.h rename to Controllers/CoolerMasterController/CMMMController/CMMMController.h index f4153ac2..aa45d46e 100644 --- a/Controllers/CoolerMasterController/CMMMController.h +++ b/Controllers/CoolerMasterController/CMMMController/CMMMController.h @@ -1,20 +1,22 @@ -/*-------------------------------------------------------------------*\ -| CMMMController.h | -| | -| Driver for Coolermaster MasterMouse | -| | -| Chris M (Dr_No) 14th Feb 2021 - MM711 Base | -| Dracrius 12th Mar 2022 | -| | -\*-------------------------------------------------------------------*/ - -#include -#include -#include -#include "RGBController.h" +/*---------------------------------------------------------*\ +| CMMMController.h | +| | +| Driver for Cooler Master mouse | +| | +| Chris M (Dr_No) 14 Feb 2021 | +| Dracrius 12 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include +#include "RGBController.h" + #define CM_MM_PACKET_SIZE 65 #define CM_MM_COLOUR_MODE_DATA_SIZE (sizeof(colour_mode_data[0]) / sizeof(colour_mode_data[0][0])) #define CM_MM_HEADER_DATA_SIZE (sizeof(argb_header_data) / sizeof(argb_headers) ) @@ -87,12 +89,13 @@ enum class CMMMController { public: - CMMMController(hid_device* dev_handle, char *_path, uint16_t pid); + CMMMController(hid_device* dev_handle, char *_path, uint16_t pid, std::string dev_name); ~CMMMController(); std::string GetDeviceVendor(); std::string GetSerial(); std::string GetLocation(); + std::string GetName(); uint16_t GetProductID(); @@ -112,8 +115,6 @@ public: void SendSavePacket(); private: std::string name; - std::string vendor; - std::string serial; std::string location; hid_device* dev; diff --git a/Controllers/CoolerMasterController/RGBController_CMMMController.cpp b/Controllers/CoolerMasterController/CMMMController/RGBController_CMMMController.cpp similarity index 89% rename from Controllers/CoolerMasterController/RGBController_CMMMController.cpp rename to Controllers/CoolerMasterController/CMMMController/RGBController_CMMMController.cpp index 7d03b52f..d2a9d6e6 100644 --- a/Controllers/CoolerMasterController/RGBController_CMMMController.cpp +++ b/Controllers/CoolerMasterController/CMMMController/RGBController_CMMMController.cpp @@ -1,17 +1,19 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMMMController.cpp | -| | -| Driver for Cooler Master MasterMouse Controller | -| | -| Chris M (Dr_No) 14th Feb 2021 - MM711 Base | -| Dracrius 12th Mar 2022 | -| | -\*-------------------------------------------------------------------*/ - -#define applyBrightness(c, bright) ((RGBColor) ((RGBGetBValue(c) * bright / CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT) << 16 | (RGBGetGValue(c) * bright / CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT) << 8 | (RGBGetRValue(c) * bright / CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT))) +/*---------------------------------------------------------*\ +| RGBController_CMMMController.cpp | +| | +| RGBController for Cooler Master mouse | +| | +| Chris M (Dr_No) 14 Feb 2021 | +| Dracrius 12 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CMMMController.h" +#define applyBrightness(c, bright) ((RGBColor) ((RGBGetBValue(c) * bright / CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT) << 16 | (RGBGetGValue(c) * bright / CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT) << 8 | (RGBGetRValue(c) * bright / CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT))) + /**------------------------------------------------------------------*\ @name Coolermaster Master Mouse @category Mouse @@ -27,10 +29,10 @@ RGBController_CMMMController::RGBController_CMMMController(CMMMController* contr { controller = controller_ptr; - name = "Cooler Master MasterMouse"; + name = controller->GetName(); vendor = controller->GetDeviceVendor(); type = DEVICE_TYPE_MOUSE; - description = "Cooler Master MasterMouse"; + description = "Cooler Master MasterMouse Device"; serial = controller->GetSerial(); location = controller->GetLocation(); @@ -135,7 +137,7 @@ RGBController_CMMMController::RGBController_CMMMController(CMMMController* contr uint8_t temp_mode = controller->GetMode(); - for(std::size_t mode_index = 0; mode_index < modes.size(); mode_index++) + for(int mode_index = 0; mode_index < (int)modes.size(); mode_index++) { if(modes[mode_index].value == temp_mode) { @@ -247,18 +249,6 @@ void RGBController_CMMMController::UpdateSingleLED(int /*led*/) DeviceUpdateLEDs(); } -void RGBController_CMMMController::SetCustomMode() -{ - for(std::size_t mode_index = 0; mode_index < modes.size(); mode_index++) - { - if(modes[mode_index].value == CM_MM_MODE_CUSTOM) - { - active_mode = mode_index; - break; - } - } -} - void RGBController_CMMMController::DeviceUpdateMode() { RGBColor mode_one = 0; diff --git a/Controllers/CoolerMasterController/CMMMController/RGBController_CMMMController.h b/Controllers/CoolerMasterController/CMMMController/RGBController_CMMMController.h new file mode 100644 index 00000000..5c07a06a --- /dev/null +++ b/Controllers/CoolerMasterController/CMMMController/RGBController_CMMMController.h @@ -0,0 +1,46 @@ +/*---------------------------------------------------------*\ +| RGBController_CMMMController.h | +| | +| RGBController for Cooler Master mouse | +| | +| Chris M (Dr_No) 14 Feb 2021 | +| Dracrius 12 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "CMMMController.h" + +#define CM_MM_ARGB_BRIGHTNESS_MIN 0x00 +#define CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT 0xFF +#define CM_MM_ARGB_BRIGHTNESS_MAX_SPECTRUM 0x7F + +class RGBController_CMMMController : public RGBController +{ +public: + RGBController_CMMMController(CMMMController* controller_ptr); + ~RGBController_CMMMController(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + void Init_Controller(); + int GetDeviceMode(); + + int leds_count; + + CMMMController* controller; +}; diff --git a/Controllers/CoolerMasterController/CMMP750Controller.cpp b/Controllers/CoolerMasterController/CMMP750Controller.cpp deleted file mode 100644 index 42e677da..00000000 --- a/Controllers/CoolerMasterController/CMMP750Controller.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/*-------------------------------------------------------------------*\ -| CMMP750Controller.cpp | -| | -| Driver for Coolermaster MP750 mousepad | -| | -| Chris M (Dr_No) 16th Apr 2020 | -| | -\*-------------------------------------------------------------------*/ - -#include "CMMP750Controller.h" - -static unsigned char colour_mode_data[][6] = -{ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Off */ - { 0x01, 0x04, 0xFF, 0x00, 0xFF, 0x00 }, /* Static */ - { 0x02, 0x04, 0xFF, 0x00, 0xFF, 0x80 }, /* Blinking */ - { 0x03, 0x04, 0xFF, 0x00, 0xFF, 0x80 }, /* Breathing */ - { 0x04, 0x04, 0x80, 0x00, 0x00, 0x00 }, /* Colour Cycle */ - { 0x05, 0x04, 0x80, 0x00, 0x00, 0x00 } /* Colour Breath */ -}; - -static unsigned char speed_mode_data[9] = -{ - 0xFF, 0xE0, 0xC0, 0xA0, 0x80, 0x60, 0x40, 0x20, 0x00 /* Speed Definition */ -}; - -CMMP750Controller::CMMP750Controller(hid_device* dev_handle, char *_path) -{ - dev = dev_handle; - location = _path; - - const int szTemp = 256; - wchar_t tmpName[szTemp]; - - hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - device_name = std::string(wName.begin(), wName.end()); - - hid_get_product_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); - - hid_get_serial_number_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - serial = std::string(wName.begin(), wName.end()); - - GetStatus(); //When setting up device get current status -} - -CMMP750Controller::~CMMP750Controller() -{ - hid_close(dev); -} - -void CMMP750Controller::GetStatus() -{ - unsigned char buffer[0x41] = { 0x00 }; - int buffer_size = (sizeof(buffer) / sizeof(buffer[0])); - buffer[1] = 0x07; - - hid_write(dev, buffer, buffer_size); - hid_read(dev, buffer, buffer_size); - - if((buffer[0] == 0x80) && (buffer[1] == 0x05)) - { - current_mode = buffer[2]; - current_red = buffer[3]; - current_green = buffer[4]; - current_blue = buffer[5]; - - for(int i = 0; (speed_mode_data[i] >= buffer[6] && i <= MP750_SPEED_FASTEST); i++) - { - current_speed = i; - } - } - else - { - //Code should never reach here however just in case there is a failure set something - current_mode = CM_MP750_MODE_COLOR_CYCLE; //Unicorn Spew - current_red = 0xFF; - current_green = 0xFF; - current_blue = 0xFF; - current_speed = MP750_SPEED_NORMAL; - } -} - -std::string CMMP750Controller::GetDeviceName() -{ - return device_name; -} - -std::string CMMP750Controller::GetSerial() -{ - return serial; -} - -std::string CMMP750Controller::GetLocation() -{ - return("HID: " + location); -} - -unsigned char CMMP750Controller::GetMode() -{ - return current_mode; -} - -unsigned char CMMP750Controller::GetLedRed() -{ - return current_red; -} - -unsigned char CMMP750Controller::GetLedGreen() -{ - return current_green; -} - -unsigned char CMMP750Controller::GetLedBlue() -{ - return current_blue; -} - -unsigned char CMMP750Controller::GetLedSpeed() -{ - return current_speed; -} - -void CMMP750Controller::SetMode(unsigned char mode, unsigned char speed) -{ - current_mode = mode; - current_speed = speed; - - SendUpdate(); -} - -void CMMP750Controller::SetColor(unsigned char red, unsigned char green, unsigned char blue) -{ - current_red = red; - current_green = green; - current_blue = blue; - - SendUpdate(); -} - -void CMMP750Controller::SendUpdate() -{ - unsigned char buffer[0x41] = { 0x00 }; - int buffer_size = (sizeof(buffer) / sizeof(buffer[0])); - - for(std::size_t i = 0; i < CM_COLOUR_MODE_DATA_SIZE; i++) - { - buffer[i+1] = colour_mode_data[current_mode][i]; - } - - if(current_mode > CM_MP750_MODE_BREATHING) - { - //If the mode is random colours set SPEED at BYTE2 - buffer[CM_RED_BYTE] = speed_mode_data[current_speed]; - } - else - { - //Otherwise SPEED is BYTE5 - buffer[CM_RED_BYTE] = current_red; - buffer[CM_GREEN_BYTE] = current_green; - buffer[CM_BLUE_BYTE] = current_blue; - buffer[CM_SPEED_BYTE] = speed_mode_data[current_speed]; - } - - hid_write(dev, buffer, buffer_size); -} diff --git a/Controllers/CoolerMasterController/CMMP750Controller/CMMP750Controller.cpp b/Controllers/CoolerMasterController/CMMP750Controller/CMMP750Controller.cpp new file mode 100644 index 00000000..10342f22 --- /dev/null +++ b/Controllers/CoolerMasterController/CMMP750Controller/CMMP750Controller.cpp @@ -0,0 +1,176 @@ +/*---------------------------------------------------------*\ +| CMMP750Controller.cpp | +| | +| Driver for Cooler Master MP750 mousemat | +| | +| Chris M (Dr_No) 16 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "CMMP750Controller.h" +#include "StringUtils.h" + +static unsigned char colour_mode_data[][6] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* Off */ + { 0x01, 0x04, 0xFF, 0x00, 0xFF, 0x00 }, /* Static */ + { 0x02, 0x04, 0xFF, 0x00, 0xFF, 0x80 }, /* Blinking */ + { 0x03, 0x04, 0xFF, 0x00, 0xFF, 0x80 }, /* Breathing */ + { 0x04, 0x04, 0x80, 0x00, 0x00, 0x00 }, /* Colour Cycle */ + { 0x05, 0x04, 0x80, 0x00, 0x00, 0x00 } /* Colour Breath */ +}; + +static unsigned char speed_mode_data[9] = +{ + 0xFF, 0xE0, 0xC0, 0xA0, 0x80, 0x60, 0x40, 0x20, 0x00 /* Speed Definition */ +}; + +CMMP750Controller::CMMP750Controller(hid_device* dev_handle, char *_path) +{ + dev = dev_handle; + location = _path; + + /*---------------------------------------------------------*\ + | Get device name from HID manufacturer and product strings | + \*---------------------------------------------------------*/ + wchar_t name_string[HID_MAX_STR]; + + hid_get_manufacturer_string(dev, name_string, HID_MAX_STR); + device_name = StringUtils::wstring_to_string(name_string); + + hid_get_product_string(dev, name_string, HID_MAX_STR); + device_name.append(" ").append(StringUtils::wstring_to_string(name_string)); + + GetStatus(); //When setting up device get current status +} + +CMMP750Controller::~CMMP750Controller() +{ + hid_close(dev); +} + +void CMMP750Controller::GetStatus() +{ + unsigned char buffer[0x41] = { 0x00 }; + int buffer_size = (sizeof(buffer) / sizeof(buffer[0])); + buffer[1] = 0x07; + + hid_write(dev, buffer, buffer_size); + hid_read(dev, buffer, buffer_size); + + if((buffer[0] == 0x80) && (buffer[1] == 0x05)) + { + current_mode = buffer[2]; + current_red = buffer[3]; + current_green = buffer[4]; + current_blue = buffer[5]; + + for(int i = 0; (speed_mode_data[i] >= buffer[6] && i <= MP750_SPEED_FASTEST); i++) + { + current_speed = i; + } + } + else + { + //Code should never reach here however just in case there is a failure set something + current_mode = CM_MP750_MODE_COLOR_CYCLE; //Unicorn Spew + current_red = 0xFF; + current_green = 0xFF; + current_blue = 0xFF; + current_speed = MP750_SPEED_NORMAL; + } +} + +std::string CMMP750Controller::GetDeviceName() +{ + return(device_name); +} + +std::string CMMP750Controller::GetSerial() +{ + wchar_t serial_string[HID_MAX_STR]; + int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string CMMP750Controller::GetLocation() +{ + return("HID: " + location); +} + +unsigned char CMMP750Controller::GetMode() +{ + return(current_mode); +} + +unsigned char CMMP750Controller::GetLedRed() +{ + return(current_red); +} + +unsigned char CMMP750Controller::GetLedGreen() +{ + return(current_green); +} + +unsigned char CMMP750Controller::GetLedBlue() +{ + return(current_blue); +} + +unsigned char CMMP750Controller::GetLedSpeed() +{ + return(current_speed); +} + +void CMMP750Controller::SetMode(unsigned char mode, unsigned char speed) +{ + current_mode = mode; + current_speed = speed; + + SendUpdate(); +} + +void CMMP750Controller::SetColor(unsigned char red, unsigned char green, unsigned char blue) +{ + current_red = red; + current_green = green; + current_blue = blue; + + SendUpdate(); +} + +void CMMP750Controller::SendUpdate() +{ + unsigned char buffer[0x41] = { 0x00 }; + int buffer_size = (sizeof(buffer) / sizeof(buffer[0])); + + for(std::size_t i = 0; i < CM_COLOUR_MODE_DATA_SIZE; i++) + { + buffer[i+1] = colour_mode_data[current_mode][i]; + } + + if(current_mode > CM_MP750_MODE_BREATHING) + { + //If the mode is random colours set SPEED at BYTE2 + buffer[CM_RED_BYTE] = speed_mode_data[current_speed]; + } + else + { + //Otherwise SPEED is BYTE5 + buffer[CM_RED_BYTE] = current_red; + buffer[CM_GREEN_BYTE] = current_green; + buffer[CM_BLUE_BYTE] = current_blue; + buffer[CM_SPEED_BYTE] = speed_mode_data[current_speed]; + } + + hid_write(dev, buffer, buffer_size); +} diff --git a/Controllers/CoolerMasterController/CMMP750Controller.h b/Controllers/CoolerMasterController/CMMP750Controller/CMMP750Controller.h similarity index 82% rename from Controllers/CoolerMasterController/CMMP750Controller.h rename to Controllers/CoolerMasterController/CMMP750Controller/CMMP750Controller.h index a6c9e3ca..c68e6c4d 100644 --- a/Controllers/CoolerMasterController/CMMP750Controller.h +++ b/Controllers/CoolerMasterController/CMMP750Controller/CMMP750Controller.h @@ -1,10 +1,27 @@ +/*---------------------------------------------------------*\ +| CMMP750Controller.h | +| | +| Driver for Cooler Master MP750 mousemat | +| | +| Chris M (Dr_No) 16 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include + +#define CM_COLOUR_MODE_DATA_SIZE (sizeof(colour_mode_data[0]) / sizeof(colour_mode_data[0][0])) +#define CM_INTERRUPT_TIMEOUT 250 +#define CM_DEVICE_NAME_SIZE (sizeof(device_name) / sizeof(device_name[ 0 ])) +#define CM_SERIAL_SIZE (sizeof(serial) / sizeof(serial[ 0 ])) +#define HID_MAX_STR 255 + /*-------------------------------------------------------------------*\ -| CMMP750Controller.h | -| | -| Driver for Coolermaster MP750 mousepad | -| | -| Chris M (Dr_No) 16th Apr 2020 | -| | | Simple RGB device with 5 modes | | BYTE0 = Mode (0x01 thru 0x05 | | BYTE1 = ?? Must be set to 0x04 for colour modes otherwise ignored | @@ -14,18 +31,6 @@ | BYTE5 = Colour Modes: SPEED else ignored | \*-------------------------------------------------------------------*/ -#include -#include -#include - -#pragma once - -#define CM_COLOUR_MODE_DATA_SIZE (sizeof(colour_mode_data[0]) / sizeof(colour_mode_data[0][0])) -#define CM_INTERRUPT_TIMEOUT 250 -#define CM_DEVICE_NAME_SIZE (sizeof(device_name) / sizeof(device_name[ 0 ])) -#define CM_SERIAL_SIZE (sizeof(serial) / sizeof(serial[ 0 ])) -#define HID_MAX_STR 255 - enum { CM_MODE_BYTE = 1, @@ -79,7 +84,6 @@ public: private: std::string device_name; - std::string serial; std::string location; hid_device* dev; diff --git a/Controllers/CoolerMasterController/RGBController_CMMP750Controller.cpp b/Controllers/CoolerMasterController/CMMP750Controller/RGBController_CMMP750Controller.cpp similarity index 86% rename from Controllers/CoolerMasterController/RGBController_CMMP750Controller.cpp rename to Controllers/CoolerMasterController/CMMP750Controller/RGBController_CMMP750Controller.cpp index d9187412..eceac678 100644 --- a/Controllers/CoolerMasterController/RGBController_CMMP750Controller.cpp +++ b/Controllers/CoolerMasterController/CMMP750Controller/RGBController_CMMP750Controller.cpp @@ -1,11 +1,13 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMMP750Controller.cpp | -| | -| Driver for Coolermaster MP750 mousepad | -| | -| Chris M (Dr_No) 18th Apr 2020 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CMMP750Controller.cpp | +| | +| RGBController for Cooler Master MP750 mousemat | +| | +| Chris M (Dr_No) 18 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CMMP750Controller.h" @@ -173,11 +175,6 @@ void RGBController_CMMP750Controller::UpdateSingleLED(int led) UpdateZoneLEDs(led); } -void RGBController_CMMP750Controller::SetCustomMode() -{ - active_mode = 0; -} - void RGBController_CMMP750Controller::DeviceUpdateMode() { controller->SetMode(modes[active_mode].value, modes[active_mode].speed); diff --git a/Controllers/CoolerMasterController/CMMP750Controller/RGBController_CMMP750Controller.h b/Controllers/CoolerMasterController/CMMP750Controller/RGBController_CMMP750Controller.h new file mode 100644 index 00000000..aaab9e81 --- /dev/null +++ b/Controllers/CoolerMasterController/CMMP750Controller/RGBController_CMMP750Controller.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_CMMP750Controller.h | +| | +| RGBController for Cooler Master MP750 mousemat | +| | +| Chris M (Dr_No) 18 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "CMMP750Controller.h" + +class RGBController_CMMP750Controller : public RGBController +{ +public: + RGBController_CMMP750Controller(CMMP750Controller* controller_ptr); + ~RGBController_CMMP750Controller(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + CMMP750Controller* controller; + + int GetDeviceMode(); +}; diff --git a/Controllers/CoolerMasterController/CMMonitorController/CMMonitorController.cpp b/Controllers/CoolerMasterController/CMMonitorController/CMMonitorController.cpp new file mode 100644 index 00000000..3b810a50 --- /dev/null +++ b/Controllers/CoolerMasterController/CMMonitorController/CMMonitorController.cpp @@ -0,0 +1,208 @@ +/*---------------------------------------------------------*\ +| CMMonitorController.cpp | +| | +| Driver for Cooler Master monitor | +| | +| Morgan Guimard (morg) 18 Sep 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "CMMonitorController.h" +#include "StringUtils.h" + +using namespace std::chrono_literals; + +CMMonitorController::CMMonitorController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) +{ + dev = dev_handle; + location = info.path; + name = dev_name; +} + +CMMonitorController::~CMMonitorController() +{ + hid_close(dev); +} + +std::string CMMonitorController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string CMMonitorController::GetNameString() +{ + return(name); +} + +std::string CMMonitorController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void CMMonitorController::SetMode(uint8_t mode_value, const RGBColor& color, uint8_t speed, uint8_t brightness) +{ + if(software_mode_enabled) + { + SetSoftwareModeEnabled(false); + } + + uint8_t usb_buf[CM_MONITOR_PACKET_LENGTH]; + memset(usb_buf, 0x00, CM_MONITOR_PACKET_LENGTH); + + usb_buf[1] = 0x80; + usb_buf[2] = (mode_value == CM_MONITOR_OFF_MODE) ? 0x0F : 0x0B; + usb_buf[3] = 0x02; + usb_buf[4] = 0x02; + usb_buf[5] = mode_value; + usb_buf[6] = (mode_value == CM_MONITOR_OFF_MODE) ? 0x00 : 0x08; + usb_buf[7] = speed; + usb_buf[8] = brightness; + usb_buf[9] = RGBGetRValue(color); + usb_buf[10] = RGBGetGValue(color); + usb_buf[11] = RGBGetBValue(color); + + hid_write(dev, usb_buf, CM_MONITOR_PACKET_LENGTH); +} + +void CMMonitorController::SetCustomMode(const std::vector& colors, uint8_t brightnesss) +{ + if(software_mode_enabled) + { + SetSoftwareModeEnabled(false); + } + + /*---------------------------------------------------------*\ + | Creates the color buffer | + \*---------------------------------------------------------*/ + uint8_t color_data[CM_MONITOR_COLOR_DATA_LENGTH]; + memset(color_data, 0x00, CM_MONITOR_COLOR_DATA_LENGTH); + + uint8_t offset = 0; + + for(const RGBColor& color: colors) + { + color_data[offset++] = RGBGetRValue(color); + color_data[offset++] = RGBGetGValue(color); + color_data[offset++] = RGBGetBValue(color); + } + + /*---------------------------------------------------------*\ + | Sends the 7 sequence packets | + \*---------------------------------------------------------*/ + uint8_t usb_buf[CM_MONITOR_PACKET_LENGTH]; + + offset = 0; + + for(unsigned int i = 0; i < 7; i++) + { + memset(usb_buf, 0x00, CM_MONITOR_PACKET_LENGTH); + + usb_buf[1] = i < 6 ? i : 0x86; + + /*---------------------------------------------------------*\ + | First packet contains static data | + \*---------------------------------------------------------*/ + if(i == 0) + { + usb_buf[2] = 0x10; + usb_buf[3] = 0x02; + usb_buf[4] = 0x02; + usb_buf[5] = 0x80; + usb_buf[6] = brightnesss; + + memcpy(&usb_buf[7], &color_data[offset], CM_MONITOR_PACKET_LENGTH - 7); + offset += CM_MONITOR_PACKET_LENGTH - 7; + } + else + { + memcpy(&usb_buf[2], &color_data[offset], CM_MONITOR_PACKET_LENGTH - 2); + offset += (CM_MONITOR_PACKET_LENGTH - 2); + } + + hid_write(dev, usb_buf, CM_MONITOR_PACKET_LENGTH); + } +} + +void CMMonitorController::SendDirect(const std::vector& colors) +{ + if(!software_mode_enabled) + { + SetSoftwareModeEnabled(true); + } + + /*---------------------------------------------------------*\ + | Creates the color buffer | + \*---------------------------------------------------------*/ + uint8_t color_data[CM_MONITOR_COLOR_DATA_LENGTH]; + memset(color_data, 0x00, CM_MONITOR_COLOR_DATA_LENGTH); + + unsigned int offset = 0; + + for(const RGBColor& color: colors) + { + color_data[offset++] = RGBGetRValue(color); + color_data[offset++] = RGBGetGValue(color); + color_data[offset++] = RGBGetBValue(color); + } + + /*---------------------------------------------------------*\ + | Sends the 7 sequence packets | + \*---------------------------------------------------------*/ + uint8_t usb_buf[CM_MONITOR_PACKET_LENGTH]; + + offset = 0; + + for(unsigned int i = 0; i < 7; i++) + { + memset(usb_buf, 0x00, CM_MONITOR_PACKET_LENGTH); + + usb_buf[1] = i < 6 ? i : 0x86; + + if(i == 0) + { + usb_buf[2] = 0x07; + usb_buf[3] = 0x02; + usb_buf[4] = 0x02; + usb_buf[5] = 0x01; + usb_buf[6] = 0x80; + + memcpy(&usb_buf[7], &color_data[offset], CM_MONITOR_PACKET_LENGTH - 7); + offset += CM_MONITOR_PACKET_LENGTH - 7; + } + else + { + memcpy(&usb_buf[2], &color_data[offset], CM_MONITOR_PACKET_LENGTH - 2); + offset += (CM_MONITOR_PACKET_LENGTH - 2); + } + + hid_write(dev, usb_buf, CM_MONITOR_PACKET_LENGTH); + } + +} + +void CMMonitorController::SetSoftwareModeEnabled(bool value) +{ + uint8_t usb_buf[CM_MONITOR_PACKET_LENGTH]; + memset(usb_buf, 0x00, CM_MONITOR_PACKET_LENGTH); + + usb_buf[1] = 0x80; + usb_buf[2] = 0x07; + usb_buf[3] = 0x02; + usb_buf[4] = 0x02; + usb_buf[6] = value; + + hid_write(dev, usb_buf, CM_MONITOR_PACKET_LENGTH); + + software_mode_enabled = value; +} diff --git a/Controllers/CoolerMasterController/CMMonitorController/CMMonitorController.h b/Controllers/CoolerMasterController/CMMonitorController/CMMonitorController.h new file mode 100644 index 00000000..140c1f20 --- /dev/null +++ b/Controllers/CoolerMasterController/CMMonitorController/CMMonitorController.h @@ -0,0 +1,61 @@ +/*---------------------------------------------------------*\ +| CMMonitorController.h | +| | +| Driver for Cooler Master monitor | +| | +| Morgan Guimard (morg) 18 Sep 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define CM_MONITOR_PACKET_LENGTH 65 +#define CM_MONITOR_COLOR_DATA_LENGTH 436 + +enum +{ + CM_MONITOR_DIRECT_MODE = 0xFF, + CM_MONITOR_CUSTOM_MODE = 0xFE, + CM_MONITOR_SPECTRUM_MODE = 0x00, + CM_MONITOR_RELOAD_MODE = 0x01, + CM_MONITOR_RECOIL_MODE = 0x02, + CM_MONITOR_BREATHING_MODE = 0x03, + CM_MONITOR_REFILL_MODE = 0x04, + CM_MONITOR_OFF_MODE = 0x06 +}; + +enum +{ + CM_MONITOR_BRIGHTNESS_MAX = 0xFF, + CM_MONITOR_BRIGHTNESS_MIN = 0x00, + CM_MONITOR_SPEED_MAX = 0x04, + CM_MONITOR_SPEED_MIN = 0x00, +}; + +class CMMonitorController +{ +public: + CMMonitorController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~CMMonitorController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SendDirect(const std::vector& colors); + void SetMode(uint8_t mode_value, const RGBColor& color, uint8_t speed, uint8_t brightness); + void SetCustomMode(const std::vector& colors, uint8_t brightnesss); + +private: + std::string location; + std::string name; + hid_device* dev; + bool software_mode_enabled = false; + void SetSoftwareModeEnabled(bool value); +}; diff --git a/Controllers/CoolerMasterController/CMMonitorController/RGBController_CMMonitorController.cpp b/Controllers/CoolerMasterController/CMMonitorController/RGBController_CMMonitorController.cpp new file mode 100644 index 00000000..b9d1c969 --- /dev/null +++ b/Controllers/CoolerMasterController/CMMonitorController/RGBController_CMMonitorController.cpp @@ -0,0 +1,221 @@ +/*---------------------------------------------------------*\ +| RGBController_CMMonitorController.cpp | +| | +| RGBController for Cooler Master monitor | +| | +| Morgan Guimard (morg) 18 Sep 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "RGBController_CMMonitorController.h" + +/**------------------------------------------------------------------*\ + @name Coolermaster Gaming Monitor + @category Accessory + @type USB + @save :robot: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectCoolerMasterMonitor + @comment +\*-------------------------------------------------------------------*/ + +RGBController_CMMonitorController::RGBController_CMMonitorController(CMMonitorController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "CoolerMaster"; + type = DEVICE_TYPE_MONITOR; + description = "CoolerMaster Monitor Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = CM_MONITOR_DIRECT_MODE; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Spectrum; + Spectrum.name = "Spectrum cycle"; + Spectrum.value = CM_MONITOR_SPECTRUM_MODE; + Spectrum.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Spectrum.color_mode = MODE_COLORS_NONE; + Spectrum.speed_min = CM_MONITOR_SPEED_MIN; + Spectrum.speed_max = CM_MONITOR_SPEED_MAX; + Spectrum.speed = CM_MONITOR_SPEED_MAX/2; + Spectrum.brightness_min = CM_MONITOR_BRIGHTNESS_MIN; + Spectrum.brightness_max = CM_MONITOR_BRIGHTNESS_MAX; + Spectrum.brightness = CM_MONITOR_BRIGHTNESS_MAX; + modes.push_back(Spectrum); + + mode Reload; + Reload.name = "Reload"; + Reload.value = CM_MONITOR_RELOAD_MODE; + Reload.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Reload.color_mode = MODE_COLORS_MODE_SPECIFIC; + Reload.colors_min = 1; + Reload.colors_max = 1; + Reload.colors.resize(1); + Reload.speed_min = CM_MONITOR_SPEED_MIN; + Reload.speed_max = CM_MONITOR_SPEED_MAX; + Reload.speed = CM_MONITOR_SPEED_MAX/2; + Reload.brightness_min = CM_MONITOR_BRIGHTNESS_MIN; + Reload.brightness_max = CM_MONITOR_BRIGHTNESS_MAX; + Reload.brightness = CM_MONITOR_BRIGHTNESS_MAX; + modes.push_back(Reload); + + mode Recoil; + Recoil.name = "Recoil"; + Recoil.value = CM_MONITOR_RECOIL_MODE; + Recoil.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Recoil.color_mode = MODE_COLORS_MODE_SPECIFIC; + Recoil.colors_min = 1; + Recoil.colors_max = 1; + Recoil.colors.resize(1); + Recoil.speed_min = CM_MONITOR_SPEED_MIN; + Recoil.speed_max = CM_MONITOR_SPEED_MAX; + Recoil.speed = CM_MONITOR_SPEED_MAX/2; + Recoil.brightness_min = CM_MONITOR_BRIGHTNESS_MIN; + Recoil.brightness_max = CM_MONITOR_BRIGHTNESS_MAX; + Recoil.brightness = CM_MONITOR_BRIGHTNESS_MAX; + modes.push_back(Recoil); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = CM_MONITOR_BREATHING_MODE; + Breathing.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.colors.resize(1); + Breathing.speed_min = CM_MONITOR_SPEED_MIN; + Breathing.speed_max = CM_MONITOR_SPEED_MAX; + Breathing.speed = CM_MONITOR_SPEED_MAX/2; + Breathing.brightness_min = CM_MONITOR_BRIGHTNESS_MIN; + Breathing.brightness_max = CM_MONITOR_BRIGHTNESS_MAX; + Breathing.brightness = CM_MONITOR_BRIGHTNESS_MAX; + modes.push_back(Breathing); + + mode Refill; + Refill.name = "Refill"; + Refill.value = CM_MONITOR_REFILL_MODE; + Refill.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Refill.color_mode = MODE_COLORS_MODE_SPECIFIC; + Refill.colors_min = 1; + Refill.colors_max = 1; + Refill.colors.resize(1); + Refill.speed_min = CM_MONITOR_SPEED_MIN; + Refill.speed_max = CM_MONITOR_SPEED_MAX; + Refill.speed = CM_MONITOR_SPEED_MAX/2; + Refill.brightness_min = CM_MONITOR_BRIGHTNESS_MIN; + Refill.brightness_max = CM_MONITOR_BRIGHTNESS_MAX; + Refill.brightness = CM_MONITOR_BRIGHTNESS_MAX; + modes.push_back(Refill); + + mode Custom; + Custom.name = "Custom"; + Custom.value = CM_MONITOR_CUSTOM_MODE; + Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Custom.color_mode = MODE_COLORS_PER_LED; + Custom.brightness_min = CM_MONITOR_BRIGHTNESS_MIN; + Custom.brightness_max = CM_MONITOR_BRIGHTNESS_MAX; + Custom.brightness = CM_MONITOR_BRIGHTNESS_MAX; + modes.push_back(Custom); + + mode Off; + Off.name = "Off"; + Off.value = CM_MONITOR_SPECTRUM_MODE; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + SetupZones(); +} + +RGBController_CMMonitorController::~RGBController_CMMonitorController() +{ + delete controller; +} + +void RGBController_CMMonitorController::SetupZones() +{ + zone z; + + z.name = "Monitor"; + z.type = ZONE_TYPE_LINEAR; + z.leds_min = 47; + z.leds_max = 47; + z.leds_count = 47; + z.matrix_map = NULL; + + zones.push_back(z); + + for(unsigned int i = 0; i < 47; i++) + { + led l; + l.name = std::to_string(i + 1); + l.value = i; + leds.push_back(l); + } + + SetupColors(); +} + +void RGBController_CMMonitorController::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_CMMonitorController::DeviceUpdateLEDs() +{ + if(modes[active_mode].value == CM_MONITOR_DIRECT_MODE) + { + controller->SendDirect(colors); + } + else if(modes[active_mode].value == CM_MONITOR_CUSTOM_MODE) + { + controller->SetCustomMode(colors, modes[active_mode].brightness); + } +} + +void RGBController_CMMonitorController::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_CMMonitorController::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_CMMonitorController::DeviceUpdateMode() +{ + switch(modes[active_mode].value) + { + case CM_MONITOR_OFF_MODE: + case CM_MONITOR_SPECTRUM_MODE: + controller->SetMode(modes[active_mode].value, 0, modes[active_mode].speed, modes[active_mode].brightness); + break; + + case CM_MONITOR_RELOAD_MODE: + case CM_MONITOR_RECOIL_MODE: + case CM_MONITOR_BREATHING_MODE: + case CM_MONITOR_REFILL_MODE: + controller->SetMode(modes[active_mode].value, modes[active_mode].colors[0], modes[active_mode].speed, modes[active_mode].brightness); + break; + + case CM_MONITOR_CUSTOM_MODE: + DeviceUpdateLEDs(); + break; + default: break; + } +} diff --git a/Controllers/CoolerMasterController/CMMonitorController/RGBController_CMMonitorController.h b/Controllers/CoolerMasterController/CMMonitorController/RGBController_CMMonitorController.h new file mode 100644 index 00000000..9b8bd767 --- /dev/null +++ b/Controllers/CoolerMasterController/CMMonitorController/RGBController_CMMonitorController.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_CMMonitorController.h | +| | +| RGBController for Cooler Master monitor | +| | +| Morgan Guimard (morg) 18 Sep 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "CMMonitorController.h" + +class RGBController_CMMonitorController : public RGBController +{ +public: + RGBController_CMMonitorController(CMMonitorController* controller_ptr); + ~RGBController_CMMonitorController(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + CMMonitorController* controller; +}; diff --git a/Controllers/CoolerMasterController/CMR6000Controller.cpp b/Controllers/CoolerMasterController/CMR6000Controller/CMR6000Controller.cpp similarity index 76% rename from Controllers/CoolerMasterController/CMR6000Controller.cpp rename to Controllers/CoolerMasterController/CMR6000Controller/CMR6000Controller.cpp index 77ebb1cf..05babe7b 100644 --- a/Controllers/CoolerMasterController/CMR6000Controller.cpp +++ b/Controllers/CoolerMasterController/CMR6000Controller/CMR6000Controller.cpp @@ -1,13 +1,17 @@ -/*-------------------------------------------------------------------*\ -| CMR6000Controller.cpp | -| | -| Driver for Coolermaster based AMD Radeon GPU (6000 series) | -| | -| Eric S (edbgon) 2nd Feb 2021 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| CMR6000Controller.cpp | +| | +| Driver for Cooler Master AMD Radeon 6000 series GPU | +| | +| Eric S (edbgon) 02 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "CMR6000Controller.h" #include +#include "CMR6000Controller.h" +#include "StringUtils.h" CMR6000Controller::CMR6000Controller(hid_device* dev_handle, char *_path, uint16_t _pid) { @@ -15,21 +19,16 @@ CMR6000Controller::CMR6000Controller(hid_device* dev_handle, char *_path, uint16 location = _path; pid = _pid; - const int szTemp = 256; - wchar_t tmpName[szTemp]; + /*---------------------------------------------------------*\ + | Get device name from HID manufacturer and product strings | + \*---------------------------------------------------------*/ + wchar_t name_string[HID_MAX_STR]; - hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - device_name = std::string(wName.begin(), wName.end()); - - hid_get_product_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); - - hid_get_serial_number_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - serial = std::string(wName.begin(), wName.end()); + hid_get_manufacturer_string(dev, name_string, HID_MAX_STR); + device_name = StringUtils::wstring_to_string(name_string); + hid_get_product_string(dev, name_string, HID_MAX_STR); + device_name.append(" ").append(StringUtils::wstring_to_string(name_string)); } CMR6000Controller::~CMR6000Controller() @@ -42,12 +41,20 @@ CMR6000Controller::~CMR6000Controller() std::string CMR6000Controller::GetDeviceName() { - return device_name; + return(device_name); } std::string CMR6000Controller::GetSerial() { - return serial; + wchar_t serial_string[HID_MAX_STR]; + int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } std::string CMR6000Controller::GetLocation() @@ -57,27 +64,27 @@ std::string CMR6000Controller::GetLocation() unsigned char CMR6000Controller::GetMode() { - return current_mode; + return(current_mode); } unsigned char CMR6000Controller::GetLedSpeed() { - return current_speed; + return(current_speed); } unsigned char CMR6000Controller::GetBrightness() { - return current_brightness; + return(current_brightness); } bool CMR6000Controller::GetRandomColours() { - return current_random; + return(current_random); } uint16_t CMR6000Controller::GetPID() { - return pid; + return(pid); } void CMR6000Controller::SetMode(unsigned char mode, unsigned char speed, RGBColor color1, RGBColor color2, unsigned char random, unsigned char brightness) diff --git a/Controllers/CoolerMasterController/CMR6000Controller.h b/Controllers/CoolerMasterController/CMR6000Controller/CMR6000Controller.h similarity index 83% rename from Controllers/CoolerMasterController/CMR6000Controller.h rename to Controllers/CoolerMasterController/CMR6000Controller/CMR6000Controller.h index d8b82ea3..19f3bf81 100644 --- a/Controllers/CoolerMasterController/CMR6000Controller.h +++ b/Controllers/CoolerMasterController/CMR6000Controller/CMR6000Controller.h @@ -1,18 +1,21 @@ -/*-------------------------------------------------------------------*\ -| CMR6000Controller.h | -| | -| Driver for Coolermaster based AMD Radeon GPU (6000 series) | -| | -| Eric S (edbgon) 2nd Feb 2021 | -\*-------------------------------------------------------------------*/ - -#include -#include -#include -#include "RGBController.h" +/*---------------------------------------------------------*\ +| CMR6000Controller.h | +| | +| Driver for Cooler Master AMD Radeon 6000 series GPU | +| | +| Eric S (edbgon) 02 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include +#include "RGBController.h" + #define COOLERMASTER_RADEON_6000_PID 0x014D #define COOLERMASTER_RADEON_6900_PID 0x015B @@ -75,7 +78,6 @@ public: private: std::string device_name; - std::string serial; std::string location; hid_device* dev; uint16_t pid; diff --git a/Controllers/CoolerMasterController/RGBController_CMR6000Controller.cpp b/Controllers/CoolerMasterController/CMR6000Controller/RGBController_CMR6000Controller.cpp similarity index 91% rename from Controllers/CoolerMasterController/RGBController_CMR6000Controller.cpp rename to Controllers/CoolerMasterController/CMR6000Controller/RGBController_CMR6000Controller.cpp index 1fbbb718..92f4e49d 100644 --- a/Controllers/CoolerMasterController/RGBController_CMR6000Controller.cpp +++ b/Controllers/CoolerMasterController/CMR6000Controller/RGBController_CMR6000Controller.cpp @@ -1,10 +1,14 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMR6000Controller.cpp | -| | -| Driver for Coolermaster based AMD Radeon GPU (6000 series) | -| | -| Eric S (edbgon) 2nd Feb 2021 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CMR6000Controller.cpp | +| | +| RGBController for Cooler Master AMD Radeon 6000 series | +| GPU | +| | +| Eric S (edbgon) 02 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CMR6000Controller.h" @@ -87,7 +91,7 @@ RGBController_CMR6000Controller::RGBController_CMR6000Controller(CMR6000Controll Rainbow.speed = MR6000_RAINBOW_SPEED_NORMAL; Rainbow.speed_max = MR6000_RAINBOW_SPEED_FASTEST; Rainbow.color_mode = MODE_COLORS_NONE; - Rainbow.speed = MR6000_CYCLE_SPEED_NORMAL; + Rainbow.speed = MR6000_RAINBOW_SPEED_NORMAL; Rainbow.brightness_min = 0x00; Rainbow.brightness_max = 0xFF; Rainbow.brightness = 0xFF; @@ -218,11 +222,6 @@ void RGBController_CMR6000Controller::UpdateSingleLED(int /*led*/) DeviceUpdateLEDs(); } -void RGBController_CMR6000Controller::SetCustomMode() -{ - active_mode = 1; -} - void RGBController_CMR6000Controller::DeviceUpdateMode() { DeviceUpdateLEDs(); diff --git a/Controllers/CoolerMasterController/CMR6000Controller/RGBController_CMR6000Controller.h b/Controllers/CoolerMasterController/CMR6000Controller/RGBController_CMR6000Controller.h new file mode 100644 index 00000000..09e66b7c --- /dev/null +++ b/Controllers/CoolerMasterController/CMR6000Controller/RGBController_CMR6000Controller.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_CMR6000Controller.h | +| | +| RGBController for Cooler Master AMD Radeon 6000 series | +| GPU | +| | +| Eric S (edbgon) 02 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "CMR6000Controller.h" + +class RGBController_CMR6000Controller : public RGBController +{ +public: + RGBController_CMR6000Controller(CMR6000Controller* controller_ptr); + ~RGBController_CMR6000Controller(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); +private: + CMR6000Controller* controller; + + int GetDeviceMode(); +}; diff --git a/Controllers/CoolerMasterController/CMRGBController.cpp b/Controllers/CoolerMasterController/CMRGBController/CMRGBController.cpp similarity index 87% rename from Controllers/CoolerMasterController/CMRGBController.cpp rename to Controllers/CoolerMasterController/CMRGBController/CMRGBController.cpp index b18c38f3..4daa97e7 100644 --- a/Controllers/CoolerMasterController/CMRGBController.cpp +++ b/Controllers/CoolerMasterController/CMRGBController/CMRGBController.cpp @@ -1,35 +1,34 @@ -/*-------------------------------------------------------------------*\ -| CMRGBController.cpp | -| | -| Driver for Coolermaster RGB USB Controller | -| | -| Nic W (midgetspy) 13th Apr 2021 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| CMRGBController.cpp | +| | +| Driver for Cooler Master RGB controller | +| | +| Nic W (midgetspy) 13 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include "RGBController_CMRGBController.h" #include "CMRGBController.h" -#include +#include "StringUtils.h" CMRGBController::CMRGBController(hid_device* dev_handle, char* path) { - const int szTemp = 256; - wchar_t tmpName[szTemp]; - dev = dev_handle; location = path; - hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - device_name = std::string(wName.begin(), wName.end()); + /*---------------------------------------------------------*\ + | Get device name from HID manufacturer and product strings | + \*---------------------------------------------------------*/ + wchar_t name_string[HID_MAX_STR]; - hid_get_product_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); + hid_get_manufacturer_string(dev, name_string, HID_MAX_STR); + device_name = StringUtils::wstring_to_string(name_string); - hid_get_serial_number_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - serial = std::string(wName.begin(), wName.end()); + hid_get_product_string(dev, name_string, HID_MAX_STR); + device_name.append(" ").append(StringUtils::wstring_to_string(name_string)); ReadCurrentMode(); } @@ -299,7 +298,15 @@ std::string CMRGBController::GetDeviceName() std::string CMRGBController::GetSerial() { - return(serial); + wchar_t serial_string[HID_MAX_STR]; + int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } std::string CMRGBController::GetLocation() @@ -328,10 +335,10 @@ RGBColor CMRGBController::GetModeColor(int color_number) { case 0: return(current_mode_color_1); - + case 1: return(current_mode_color_2); - + default: return(ToRGBColor(0, 0, 0)); } @@ -343,16 +350,16 @@ RGBColor CMRGBController::GetPortColor(int port_number) { case 0: return(current_port1_color); - + case 1: return(current_port2_color); - + case 2: return(current_port3_color); - + case 3: return(current_port4_color); - + default: return(ToRGBColor(0, 0, 0)); } diff --git a/Controllers/CoolerMasterController/CMRGBController.h b/Controllers/CoolerMasterController/CMRGBController/CMRGBController.h similarity index 86% rename from Controllers/CoolerMasterController/CMRGBController.h rename to Controllers/CoolerMasterController/CMRGBController/CMRGBController.h index 4ea1a2ae..0351cd7e 100644 --- a/Controllers/CoolerMasterController/CMRGBController.h +++ b/Controllers/CoolerMasterController/CMRGBController/CMRGBController.h @@ -1,17 +1,20 @@ -/*-------------------------------------------------------------------*\ -| CMRGBController.h | -| | -| Driver for Coolermaster RGB USB Controller | -| | -| Nic W (midgetspy) 13th Apr 2021 | -| | -\*-------------------------------------------------------------------*/ - -#include -#include -#include "RGBController.h" +/*---------------------------------------------------------*\ +| CMRGBController.h | +| | +| Driver for Cooler Master RGB controller | +| | +| Nic W (midgetspy) 13 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + +#include +#include +#include "RGBController.h" + #define CM_RGBC_NUM_LEDS 4 #define REPORT_ID_OFFSET 1 @@ -34,6 +37,7 @@ #define CM_RGBC_SPEED_NONE 0x05 #define CM_RGBC_BRIGHTNESS_OFF 0x03 +#define HID_MAX_STR 255 /*-------------------------------------------------*\ | OP OPCODES | @@ -120,7 +124,6 @@ public: private: std::string device_name; - std::string serial; std::string location; hid_device* dev; diff --git a/Controllers/CoolerMasterController/RGBController_CMRGBController.cpp b/Controllers/CoolerMasterController/CMRGBController/RGBController_CMRGBController.cpp similarity index 89% rename from Controllers/CoolerMasterController/RGBController_CMRGBController.cpp rename to Controllers/CoolerMasterController/CMRGBController/RGBController_CMRGBController.cpp index c7a64081..fccbfc63 100644 --- a/Controllers/CoolerMasterController/RGBController_CMRGBController.cpp +++ b/Controllers/CoolerMasterController/CMRGBController/RGBController_CMRGBController.cpp @@ -1,11 +1,13 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMRGBController.cpp | -| | -| Driver for Coolermaster RGB USB Controller | -| | -| Nic W (midgetspy) 13th Apr 2021 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CMRGBController.cpp | +| | +| RGBController for Cooler Master RGB controller | +| | +| Nic W (midgetspy) 13 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CMRGBController.h" @@ -158,7 +160,7 @@ void RGBController_CMRGBController::ReadAllModeConfigsFromDevice() { int device_mode = controller->GetMode(); - for(std::size_t mode_idx = 0; mode_idx < modes.size(); mode_idx++) + for(int mode_idx = 0; mode_idx < (int)modes.size(); mode_idx++) { if(device_mode == modes[mode_idx].value) { @@ -188,14 +190,14 @@ void RGBController_CMRGBController::ReadAllModeConfigsFromDevice() void RGBController_CMRGBController::LoadConfigFromDeviceController(int mode_idx) { - for(std::size_t color_idx = 0; color_idx < modes[mode_idx].colors.size(); color_idx++) + for(int color_idx = 0; color_idx < (int)modes[mode_idx].colors.size(); color_idx++) { modes[mode_idx].colors[0] = controller->GetModeColor(color_idx); } if(modes[mode_idx].flags & MODE_FLAG_HAS_PER_LED_COLOR) { - for (std::size_t led_idx = 0; led_idx < leds.size(); led_idx++) + for(int led_idx = 0; led_idx < (int)leds.size(); led_idx++) { SetLED(led_idx, controller->GetPortColor(led_idx)); } @@ -248,7 +250,7 @@ void RGBController_CMRGBController::ResizeZone(int /*zone*/, int /*new_size*/) void RGBController_CMRGBController::DeviceUpdateLEDs() { - for(size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + for(int zone_idx = 0; zone_idx < (int)zones.size(); zone_idx++) { UpdateZoneLEDs(zone_idx); } @@ -263,18 +265,6 @@ void RGBController_CMRGBController::UpdateSingleLED(int /*led*/) { } -void RGBController_CMRGBController::SetCustomMode() -{ - for(std::size_t mode_idx = 0; mode_idx < modes.size() ; mode_idx++) - { - if (modes[mode_idx].value == CM_RGBC_MODE_MULTIPLE) - { - active_mode = mode_idx; - break; - } - } -} - void RGBController_CMRGBController::DeviceUpdateMode() { RGBColor color_1 = (modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) ? modes[active_mode].colors[0] : 0; diff --git a/Controllers/CoolerMasterController/CMRGBController/RGBController_CMRGBController.h b/Controllers/CoolerMasterController/CMRGBController/RGBController_CMRGBController.h new file mode 100644 index 00000000..5b5d0f20 --- /dev/null +++ b/Controllers/CoolerMasterController/CMRGBController/RGBController_CMRGBController.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------*\ +| RGBController_CMRGBController.h | +| | +| RGBController for Cooler Master RGB controller | +| | +| Nic W (midgetspy) 13 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "CMRGBController.h" + +class RGBController_CMRGBController : public RGBController +{ +public: + RGBController_CMRGBController(CMRGBController* controller_ptr); + ~RGBController_CMRGBController(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + CMRGBController* controller; + void LoadConfigFromDeviceController(int device_mode); + void ReadAllModeConfigsFromDevice(); +}; diff --git a/Controllers/CoolerMasterController/CMSmallARGBController.cpp b/Controllers/CoolerMasterController/CMSmallARGBController/CMSmallARGBController.cpp similarity index 82% rename from Controllers/CoolerMasterController/CMSmallARGBController.cpp rename to Controllers/CoolerMasterController/CMSmallARGBController/CMSmallARGBController.cpp index 96ca8f1c..397d8405 100644 --- a/Controllers/CoolerMasterController/CMSmallARGBController.cpp +++ b/Controllers/CoolerMasterController/CMSmallARGBController/CMSmallARGBController.cpp @@ -1,16 +1,17 @@ -/*-------------------------------------------------------------------*\ -| CMSmallARGBController.cpp | -| | -| Driver for Coolermaster Small ARGB USB Controller | -| | -| Chris M (Dr_No) 31st Jan 2021 | -| | -| Simple RGB device with 5 modes | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| CMSmallARGBController.cpp | +| | +| Driver for Cooler Master Small ARGB controller | +| | +| Chris M (Dr_No) 31 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "CMSmallARGBController.h" #include +#include "CMSmallARGBController.h" +#include "StringUtils.h" cm_small_argb_headers cm_small_argb_header_data[1] = { @@ -19,25 +20,21 @@ cm_small_argb_headers cm_small_argb_header_data[1] = CMSmallARGBController::CMSmallARGBController(hid_device* dev_handle, char *_path, unsigned char _zone_idx) { - const int szTemp = 256; - wchar_t tmpName[szTemp]; - dev = dev_handle; location = _path; zone_index = _zone_idx; current_speed = CM_SMALL_ARGB_SPEED_NORMAL; - hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - device_name = std::string(wName.begin(), wName.end()); + /*---------------------------------------------------------*\ + | Get device name from HID manufacturer and product strings | + \*---------------------------------------------------------*/ + wchar_t name_string[HID_MAX_STR]; - hid_get_product_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); + hid_get_manufacturer_string(dev, name_string, HID_MAX_STR); + device_name = StringUtils::wstring_to_string(name_string); - hid_get_serial_number_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - serial = std::string(wName.begin(), wName.end()); + hid_get_product_string(dev, name_string, HID_MAX_STR); + device_name.append(" ").append(StringUtils::wstring_to_string(name_string)); GetStatus(); } @@ -80,12 +77,20 @@ void CMSmallARGBController::GetStatus() std::string CMSmallARGBController::GetDeviceName() { - return device_name; + return(device_name); } std::string CMSmallARGBController::GetSerial() { - return serial; + wchar_t serial_string[HID_MAX_STR]; + int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } std::string CMSmallARGBController::GetLocation() @@ -95,37 +100,37 @@ std::string CMSmallARGBController::GetLocation() unsigned char CMSmallARGBController::GetZoneIndex() { - return zone_index; + return(zone_index); } unsigned char CMSmallARGBController::GetMode() { - return current_mode; + return(current_mode); } unsigned char CMSmallARGBController::GetLedRed() { - return current_red; + return(current_red); } unsigned char CMSmallARGBController::GetLedGreen() { - return current_green; + return(current_green); } unsigned char CMSmallARGBController::GetLedBlue() { - return current_blue; + return(current_blue); } unsigned char CMSmallARGBController::GetLedSpeed() { - return current_speed; + return(current_speed); } bool CMSmallARGBController::GetRandomColours() { - return bool_random; + return(bool_random); } void CMSmallARGBController::SetLedCount(int zone, int led_count) diff --git a/Controllers/CoolerMasterController/CMSmallARGBController.h b/Controllers/CoolerMasterController/CMSmallARGBController/CMSmallARGBController.h similarity index 79% rename from Controllers/CoolerMasterController/CMSmallARGBController.h rename to Controllers/CoolerMasterController/CMSmallARGBController/CMSmallARGBController.h index 59976cc1..e66df77f 100644 --- a/Controllers/CoolerMasterController/CMSmallARGBController.h +++ b/Controllers/CoolerMasterController/CMSmallARGBController/CMSmallARGBController.h @@ -1,23 +1,28 @@ -/*-------------------------------------------------------------------*\ -| CMSmallARGBController.h | -| | -| Driver for Coolermaster Small ARGB USB Controller | -| | -| Chris M (Dr_No) 31st Jan 2021 | -| | -| Simple RGB device with 5 modes | -| | -\*-------------------------------------------------------------------*/ - -#include -#include -#include -#include "RGBController.h" //Needed to set the direct mode +/*---------------------------------------------------------*\ +| CMSmallARGBController.h | +| | +| Driver for Cooler Master Small ARGB controller | +| | +| Chris M (Dr_No) 31 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include +#include "RGBController.h" //Needed to set the direct mode + +/*---------------------------------------------------------*\ +| Simple RGB device with 5 modes | +\*---------------------------------------------------------*/ + #define CM_SMALL_ARGB_PACKET_SIZE 65 #define CM_SMALL_ARGB_INTERRUPT_TIMEOUT 250 +#define HID_MAX_STR 255 enum { @@ -89,7 +94,6 @@ public: void SetLedsDirect(RGBColor * led_colours, unsigned int led_count); private: std::string device_name; - std::string serial; std::string location; hid_device* dev; diff --git a/Controllers/CoolerMasterController/RGBController_CMSmallARGBController.cpp b/Controllers/CoolerMasterController/CMSmallARGBController/RGBController_CMSmallARGBController.cpp similarity index 93% rename from Controllers/CoolerMasterController/RGBController_CMSmallARGBController.cpp rename to Controllers/CoolerMasterController/CMSmallARGBController/RGBController_CMSmallARGBController.cpp index e48e23cb..c7daca44 100644 --- a/Controllers/CoolerMasterController/RGBController_CMSmallARGBController.cpp +++ b/Controllers/CoolerMasterController/CMSmallARGBController/RGBController_CMSmallARGBController.cpp @@ -1,11 +1,13 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMSmallARGBController.cpp | -| | -| Driver for Coolermaster Small ARGB USB Controller | -| | -| Chris M (Dr_No) 31st Jan 2021 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CMSmallARGBController.cpp | +| | +| RGBController for Cooler Master Small ARGB controller | +| | +| Chris M (Dr_No) 31 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CMSmallARGBController.h" @@ -155,9 +157,9 @@ RGBController_CMSmallARGBController::RGBController_CMSmallARGBController(CMSmall int temp_mode = controller->GetMode(); - for(std::size_t mode_idx = 0; mode_idx < modes.size() ; mode_idx++) + for(int mode_idx = 0; mode_idx < (int)modes.size() ; mode_idx++) { - if (temp_mode == modes[mode_idx].value) + if(temp_mode == modes[mode_idx].value) { active_mode = mode_idx; break; @@ -259,7 +261,7 @@ void RGBController_CMSmallARGBController::ResizeZone(int zone, int new_size) void RGBController_CMSmallARGBController::DeviceUpdateLEDs() { - for(size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + for(int zone_idx = 0; zone_idx < (int)zones.size(); zone_idx++) { UpdateZoneLEDs(zone_idx); } diff --git a/Controllers/CoolerMasterController/CMSmallARGBController/RGBController_CMSmallARGBController.h b/Controllers/CoolerMasterController/CMSmallARGBController/RGBController_CMSmallARGBController.h new file mode 100644 index 00000000..72b2272a --- /dev/null +++ b/Controllers/CoolerMasterController/CMSmallARGBController/RGBController_CMSmallARGBController.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------*\ +| RGBController_CMSmallARGBController.h | +| | +| RGBController for Cooler Master Small ARGB controller | +| | +| Chris M (Dr_No) 31 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "CMSmallARGBController.h" + +#define CM_SMALL_ARGB_MIN_LEDS 4 +#define CM_SMALL_ARGB_MAX_LEDS 48 +#define CM_SMALL_ARGB_BRIGHTNESS_MAX 0xFF +#define CM_SMALL_ARGB_FW0012 "A202104052336" + +class RGBController_CMSmallARGBController : public RGBController +{ +public: + RGBController_CMSmallARGBController(CMSmallARGBController* controller_ptr); + ~RGBController_CMSmallARGBController(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void SetCustomMode(); + void DeviceUpdateMode(); +private: + void Init_Controller(); + int GetDeviceMode(); + + CMSmallARGBController* controller; +}; diff --git a/Controllers/CoolerMasterController/CoolerMasterControllerDetect.cpp b/Controllers/CoolerMasterController/CoolerMasterControllerDetect.cpp index 08d4980e..1e5b80b7 100644 --- a/Controllers/CoolerMasterController/CoolerMasterControllerDetect.cpp +++ b/Controllers/CoolerMasterController/CoolerMasterControllerDetect.cpp @@ -1,23 +1,33 @@ +/*---------------------------------------------------------*\ +| CoolerMasterControllerDetect.cpp | +| | +| Detector for Cooler Master devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + /*-----------------------------------------------------*\ | OpenRGB includes | \*-----------------------------------------------------*/ -#include +#include #include "Detector.h" #include "LogManager.h" -#include "RGBController.h" /*-----------------------------------------------------*\ | Coolermaster specific includes | \*-----------------------------------------------------*/ #include "RGBController_CMMMController.h" #include "RGBController_CMMM711Controller.h" +#include "RGBController_CMMM712Controller.h" #include "RGBController_CMMP750Controller.h" #include "RGBController_CMARGBController.h" #include "RGBController_CMSmallARGBController.h" #include "RGBController_CMARGBGen2A1Controller.h" #include "RGBController_CMRGBController.h" #include "RGBController_CMR6000Controller.h" -#include "RGBController_CMMKController.h" +#include "RGBController_CMMonitorController.h" +#include "RGBController_CMKeyboardController.h" /*-----------------------------------------------------*\ | Coolermaster USB vendor ID | @@ -26,13 +36,8 @@ /*-----------------------------------------------------*\ | Coolermaster Keyboards | +| PIDs defined in `CMMKControllerV2.h` | \*-----------------------------------------------------*/ -#define COOLERMASTER_MASTERKEYS_PRO_L_PID 0x003B -#define COOLERMASTER_MASTERKEYS_PRO_L_WHITE_PID 0x0047 -#define COOLERMASTER_MASTERKEYS_PRO_S_PID 0x003C -#define COOLERMASTER_MASTERKEYS_MK750_PID 0x0067 -#define COOLERMASTER_MASTERKEYS_SK630_PID 0x0089 -#define COOLERMASTER_MASTERKEYS_SK650_PID 0x008D /*-----------------------------------------------------*\ | Coolermaster GPUs | @@ -45,6 +50,7 @@ #define COOLERMASTER_ARGB_PID 0x1011 #define COOLERMASTER_ARGB_GEN2_A1_PID 0x0173 #define COOLERMASTER_ARGB_GEN2_A1_V2_PID 0x01C9 +#define COOLERMASTER_ARGB_GEN2_A1_MINI_PID 0x01CB #define COOLERMASTER_SMALL_ARGB_PID 0x1000 #define COOLERMASTER_RGB_PID 0x004F @@ -54,6 +60,7 @@ #define COOLERMASTER_MM530_PID 0x0065 #define COOLERMASTER_MM531_PID 0x0097 #define COOLERMASTER_MM711_PID 0x0101 +#define COOLERMASTER_MM712_PID 0x0169 #define COOLERMASTER_MM720_PID 0x0141 #define COOLERMASTER_MM730_PID 0x0165 @@ -64,6 +71,11 @@ #define COOLERMASTER_MP750_L_PID 0x0107 #define COOLERMASTER_MP750_MEDIUM_PID 0x0105 +/*-----------------------------------------------------*\ +| Coolermaster Monitors | +\*-----------------------------------------------------*/ +#define COOLERMASTER_GM27_FQS_PID 0x01BB + /******************************************************************************************\ * * * DetectCoolerMasterControllers * @@ -84,11 +96,11 @@ void DetectCoolerMasterARGB(hid_device_info* info, const std::string&) \*-------------------------------------------------*/ std::shared_ptr cm_mutex = std::make_shared(); - for(std::size_t i = 0; i < CM_ARGB_HEADER_DATA_SIZE; i++) + for(unsigned char i = 0; i < CM_ARGB_HEADER_DATA_SIZE; i++) { CMARGBController* controller = new CMARGBController(dev, info->path, i, cm_mutex); RGBController_CMARGBController* rgb_controller = new RGBController_CMARGBController(controller); - // Constructor sets the name + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -100,9 +112,9 @@ void DetectCoolerMasterARGBGen2A1(hid_device_info* info, const std::string& name if(dev) { - CMARGBGen2A1controller* controller = new CMARGBGen2A1controller(dev, *info); + CMARGBGen2A1controller* controller = new CMARGBGen2A1controller(dev, *info, name); RGBController_CMARGBGen2A1Controller* rgb_controller = new RGBController_CMARGBGen2A1Controller(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -115,21 +127,80 @@ void DetectCoolerMasterGPU(hid_device_info* info, const std::string&) { CMR6000Controller* controller = new CMR6000Controller(dev, info->path, info->product_id); RGBController_CMR6000Controller* rgb_controller = new RGBController_CMR6000Controller(controller); - // Constructor sets the name + ResourceManager::get()->RegisterRGBController(rgb_controller); } } -void DetectCoolerMasterKeyboards(hid_device_info* info, const std::string&) +void DetectCoolerMasterV1Keyboards(hid_device_info* info, const std::string& name) { hid_device* dev = hid_open_path(info->path); if(dev) { - CMMKController* controller = new CMMKController(dev, info); - RGBController_CMMKController* rgb_controller = new RGBController_CMMKController(controller); - // Constructor sets the name - ResourceManager::get()->RegisterRGBController(rgb_controller); + switch(info->product_id) + { + case COOLERMASTER_KEYBOARD_PRO_L_PID: + case COOLERMASTER_KEYBOARD_PRO_L_WHITE_PID: + case COOLERMASTER_KEYBOARD_PRO_S_PID: + { + CMKeyboardV1Controller* controller = new CMKeyboardV1Controller(dev, info, name); + RGBController_CMKeyboardController* rgb_controller = new RGBController_CMKeyboardController(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + break; + + default: + LOG_DEBUG("[%s] Controller not created as the product ID %04X is missing from detector switch", name.c_str(), info->product_id); + break; + } + } +} + +void DetectCoolerMasterV2Keyboards(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + switch(info->product_id) + { + case COOLERMASTER_KEYBOARD_PRO_L_PID: + case COOLERMASTER_KEYBOARD_PRO_L_WHITE_PID: + case COOLERMASTER_KEYBOARD_PRO_S_PID: + { + CMKeyboardV1Controller* controller = new CMKeyboardV1Controller(dev, info, name); + RGBController_CMKeyboardController* rgb_controller = new RGBController_CMKeyboardController(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + break; + + case COOLERMASTER_KEYBOARD_SK622B_PID: + case COOLERMASTER_KEYBOARD_SK622W_PID: + case COOLERMASTER_KEYBOARD_SK630_PID: + case COOLERMASTER_KEYBOARD_SK650_PID: + case COOLERMASTER_KEYBOARD_SK652_PID: + case COOLERMASTER_KEYBOARD_SK653_PID: + case COOLERMASTER_KEYBOARD_CK530_PID: + case COOLERMASTER_KEYBOARD_CK530_V2_PID: + case COOLERMASTER_KEYBOARD_CK550_V2_PID: + case COOLERMASTER_KEYBOARD_CK552_V2_PID: + case COOLERMASTER_KEYBOARD_MK730_PID: + case COOLERMASTER_KEYBOARD_MK750_PID: + { + CMKeyboardV2Controller* controller = new CMKeyboardV2Controller(dev, info, name); + RGBController_CMKeyboardController* rgb_controller = new RGBController_CMKeyboardController(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + break; + + default: + LOG_DEBUG("[%s] Controller not created as the product ID %04X is missing from detector switch", name.c_str(), info->product_id); + break; + } } } @@ -139,36 +210,40 @@ void DetectCoolerMasterMouse(hid_device_info* info, const std::string& name) if(dev) { - switch(info->product_id) - { - case COOLERMASTER_MM530_PID: - case COOLERMASTER_MM531_PID: - case COOLERMASTER_MM720_PID: - case COOLERMASTER_MM730_PID: - { - CMMMController* controller = new CMMMController(dev, info->path, info->product_id); - RGBController_CMMMController* rgb_controller = new RGBController_CMMMController(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } - break; + CMMMController* controller = new CMMMController(dev, info->path, info->product_id, name); + RGBController_CMMMController* rgb_controller = new RGBController_CMMMController(controller); - case COOLERMASTER_MM711_PID: - { - CMMM711Controller* controller = new CMMM711Controller(dev, info->path); - RGBController_CMMM711Controller* rgb_controller = new RGBController_CMMM711Controller(controller); - // Constructor sets the name - ResourceManager::get()->RegisterRGBController(rgb_controller); - } - break; - - default: - LOG_DEBUG("[%s] Controller not created as the product ID %04X is missing from detector switch", name.c_str(), info->product_id); - } + ResourceManager::get()->RegisterRGBController(rgb_controller); } } -void DetectCoolerMasterMousemats(hid_device_info* info, const std::string&) +void DetectCoolerMasterMouse711(hid_device_info* info, const std::string& /*name*/) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + CMMM711Controller* controller = new CMMM711Controller(dev, info->path); + RGBController_CMMM711Controller* rgb_controller = new RGBController_CMMM711Controller(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectCoolerMasterMouse712(hid_device_info* info, const std::string& /*name*/) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + CMMM712Controller* controller = new CMMM712Controller(dev, info->path); + RGBController_CMMM712Controller* rgb_controller = new RGBController_CMMM712Controller(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectCoolerMasterMousemats(hid_device_info* info, const std::string& /*name*/) { hid_device* dev = hid_open_path(info->path); @@ -176,12 +251,12 @@ void DetectCoolerMasterMousemats(hid_device_info* info, const std::string&) { CMMP750Controller* controller = new CMMP750Controller(dev, info->path); RGBController_CMMP750Controller* rgb_controller = new RGBController_CMMP750Controller(controller); - // Constructor sets the name + ResourceManager::get()->RegisterRGBController(rgb_controller); } } -void DetectCoolerMasterRGB(hid_device_info* info, const std::string&) +void DetectCoolerMasterRGB(hid_device_info* info, const std::string& /*name*/) { hid_device* dev = hid_open_path(info->path); @@ -189,12 +264,12 @@ void DetectCoolerMasterRGB(hid_device_info* info, const std::string&) { CMRGBController* controller = new CMRGBController(dev, info->path); RGBController_CMRGBController* rgb_controller = new RGBController_CMRGBController(controller); - // Constructor sets the name + ResourceManager::get()->RegisterRGBController(rgb_controller); } } -void DetectCoolerMasterSmallARGB(hid_device_info* info, const std::string&) +void DetectCoolerMasterSmallARGB(hid_device_info* info, const std::string& /*name*/) { hid_device* dev = hid_open_path(info->path); @@ -202,20 +277,46 @@ void DetectCoolerMasterSmallARGB(hid_device_info* info, const std::string&) { CMSmallARGBController* controller = new CMSmallARGBController(dev, info->path, 0); RGBController_CMSmallARGBController* rgb_controller = new RGBController_CMSmallARGBController(controller); - // Constructor sets the name + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectCoolerMasterMonitor(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + CMMonitorController* controller = new CMMonitorController(dev, *info, name); + RGBController_CMMonitorController* rgb_controller = new RGBController_CMMonitorController(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); } } /*-----------------------------------------------------*\ | Coolermaster Keyboards | +| PIDs defined in `CMKeyboardDevices.h` | \*-----------------------------------------------------*/ -REGISTER_HID_DETECTOR_IPU("Cooler Master MasterKeys Pro L", DetectCoolerMasterKeyboards, COOLERMASTER_VID, COOLERMASTER_MASTERKEYS_PRO_L_PID, 1, 0xFF00, 1); -REGISTER_HID_DETECTOR_IPU("Cooler Master MasterKeys Pro L White", DetectCoolerMasterKeyboards, COOLERMASTER_VID, COOLERMASTER_MASTERKEYS_PRO_L_WHITE_PID, 1, 0xFF00, 1); -REGISTER_HID_DETECTOR_IPU("Cooler Master MasterKeys Pro S", DetectCoolerMasterKeyboards, COOLERMASTER_VID, COOLERMASTER_MASTERKEYS_PRO_S_PID, 1, 0xFF00, 1); -REGISTER_HID_DETECTOR_IPU("Cooler Master MK750", DetectCoolerMasterKeyboards, COOLERMASTER_VID, COOLERMASTER_MASTERKEYS_MK750_PID, 1, 0xFF00, 1); -REGISTER_HID_DETECTOR_IPU("Cooler Master SK630", DetectCoolerMasterKeyboards, COOLERMASTER_VID, COOLERMASTER_MASTERKEYS_SK630_PID, 1, 0xFF00, 1); -REGISTER_HID_DETECTOR_IPU("Cooler Master SK650", DetectCoolerMasterKeyboards, COOLERMASTER_VID, COOLERMASTER_MASTERKEYS_SK650_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master MasterKeys Pro S", DetectCoolerMasterV1Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_PRO_S_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master MasterKeys Pro L", DetectCoolerMasterV1Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_PRO_L_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master MasterKeys Pro L White", DetectCoolerMasterV1Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_PRO_L_WHITE_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master MK850", DetectCoolerMasterV2Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_MK850_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master SK620 White", DetectCoolerMasterV2Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_SK620W_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master SK620 Black", DetectCoolerMasterV2Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_SK620B_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master SK622 White", DetectCoolerMasterV2Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_SK622W_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master SK622 Black", DetectCoolerMasterV2Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_SK622B_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master SK630", DetectCoolerMasterV2Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_SK630_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master SK650", DetectCoolerMasterV2Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_SK650_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master SK652", DetectCoolerMasterV2Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_SK652_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master SK653", DetectCoolerMasterV2Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_SK653_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master MK730", DetectCoolerMasterV2Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_MK730_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master MK750", DetectCoolerMasterV2Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_MK750_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master CK530", DetectCoolerMasterV2Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_CK530_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master CK530 V2", DetectCoolerMasterV2Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_CK530_V2_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master CK550 V2", DetectCoolerMasterV2Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_CK550_V2_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master CK550 V1 / CK552", DetectCoolerMasterV2Keyboards, COOLERMASTER_VID, COOLERMASTER_KEYBOARD_CK552_V2_PID, 1, 0xFF00, 1); /*-----------------------------------------------------*\ | Coolermaster LEDstrip controllers | @@ -223,6 +324,7 @@ REGISTER_HID_DETECTOR_IPU("Cooler Master SK650", DetectCooler REGISTER_HID_DETECTOR_IPU("Cooler Master ARGB", DetectCoolerMasterARGB, COOLERMASTER_VID, COOLERMASTER_ARGB_PID, 0, 0xFF00, 1); REGISTER_HID_DETECTOR_IPU("Cooler Master ARGB Gen 2 A1", DetectCoolerMasterARGBGen2A1, COOLERMASTER_VID, COOLERMASTER_ARGB_GEN2_A1_PID, 1, 0xFF01, 1); REGISTER_HID_DETECTOR_IPU("Cooler Master ARGB Gen 2 A1 V2", DetectCoolerMasterARGBGen2A1, COOLERMASTER_VID, COOLERMASTER_ARGB_GEN2_A1_V2_PID, 1, 0xFF01, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master ARGB Gen 2 A1 Mini", DetectCoolerMasterARGBGen2A1, COOLERMASTER_VID, COOLERMASTER_ARGB_GEN2_A1_MINI_PID, 1, 0xFF01, 1); REGISTER_HID_DETECTOR_IPU("Cooler Master RGB", DetectCoolerMasterRGB, COOLERMASTER_VID, COOLERMASTER_RGB_PID, 1, 0xFF00, 1); REGISTER_HID_DETECTOR_IPU("Cooler Master Small ARGB", DetectCoolerMasterSmallARGB, COOLERMASTER_VID, COOLERMASTER_SMALL_ARGB_PID, 0, 0xFF00, 1); @@ -231,7 +333,8 @@ REGISTER_HID_DETECTOR_IPU("Cooler Master Small ARGB", DetectCooler \*-----------------------------------------------------*/ REGISTER_HID_DETECTOR_IPU("Cooler Master MM530", DetectCoolerMasterMouse, COOLERMASTER_VID, COOLERMASTER_MM530_PID, 1, 0xFF00, 1); //REGISTER_HID_DETECTOR_IPU("Cooler Master MM531", DetectCoolerMasterMouse, COOLERMASTER_VID, COOLERMASTER_MM531_PID, 1, 0xFF00, 1); -REGISTER_HID_DETECTOR_IPU("Cooler Master MM711", DetectCoolerMasterMouse, COOLERMASTER_VID, COOLERMASTER_MM711_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master MM711", DetectCoolerMasterMouse711, COOLERMASTER_VID, COOLERMASTER_MM711_PID, 1, 0xFF00, 1); +REGISTER_HID_DETECTOR_IPU("Cooler Master MM712", DetectCoolerMasterMouse712, COOLERMASTER_VID, COOLERMASTER_MM712_PID, 3, 0xFF0A, 2); REGISTER_HID_DETECTOR_IPU("Cooler Master MM720", DetectCoolerMasterMouse, COOLERMASTER_VID, COOLERMASTER_MM720_PID, 1, 0xFF00, 1); REGISTER_HID_DETECTOR_IPU("Cooler Master MM730", DetectCoolerMasterMouse, COOLERMASTER_VID, COOLERMASTER_MM730_PID, 1, 0xFF00, 1); @@ -246,5 +349,10 @@ REGISTER_HID_DETECTOR_PU ("Cooler Master MP750 Medium", DetectCooler | Coolermaster GPUs | | PIDs defined in `CMR6000Controller.h` | \*-----------------------------------------------------*/ -REGISTER_HID_DETECTOR_I ("Cooler Master Radeon 6000 GPU", DetectCoolerMasterGPU, COOLERMASTER_VID, COOLERMASTER_RADEON_6000_PID, 1 ); -REGISTER_HID_DETECTOR_I ("Cooler Master Radeon 6900 GPU", DetectCoolerMasterGPU, COOLERMASTER_VID, COOLERMASTER_RADEON_6900_PID, 1 ); +REGISTER_HID_DETECTOR_I ("Cooler Master Radeon RX 6000 GPU", DetectCoolerMasterGPU, COOLERMASTER_VID, COOLERMASTER_RADEON_6000_PID, 1 ); +REGISTER_HID_DETECTOR_I ("Cooler Master Radeon RX 6900 GPU", DetectCoolerMasterGPU, COOLERMASTER_VID, COOLERMASTER_RADEON_6900_PID, 1 ); + +/*-----------------------------------------------------*\ +| Coolermaster Monitors | +\*-----------------------------------------------------*/ +REGISTER_HID_DETECTOR_IPU("Cooler Master GM27-FQS ARGB Monitor", DetectCoolerMasterMonitor, COOLERMASTER_VID, COOLERMASTER_GM27_FQS_PID, 0, 0xFF00, 1); diff --git a/Controllers/CoolerMasterController/RGBController_CMARGBController.h b/Controllers/CoolerMasterController/RGBController_CMARGBController.h deleted file mode 100644 index bd5ff079..00000000 --- a/Controllers/CoolerMasterController/RGBController_CMARGBController.h +++ /dev/null @@ -1,40 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMARGBController.h | -| | -| Driver for Coolermaster ARGB Controller | -| | -| Chris M (Dr_No) 14th Oct 2020 | -| | -\*-------------------------------------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "CMARGBcontroller.h" -#include - -#define first_zone(zn) ((zones.size() > 1) ? 1 : 0) -#define last_zone(zn) ((zones.size() > 1) ? 4 : 1) - -class RGBController_CMARGBController : public RGBController -{ -public: - RGBController_CMARGBController(CMARGBController* controller_ptr); - ~RGBController_CMARGBController(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void SetCustomMode(); - void DeviceUpdateMode(); - -private: - void Init_Controller(); - int GetDeviceMode(); - int GetLED_Zone(int led_idx); - - CMARGBController* controller; -}; diff --git a/Controllers/CoolerMasterController/RGBController_CMARGBGen2A1Controller.h b/Controllers/CoolerMasterController/RGBController_CMARGBGen2A1Controller.h deleted file mode 100644 index 577f2f0f..00000000 --- a/Controllers/CoolerMasterController/RGBController_CMARGBGen2A1Controller.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMARGBGen2A1Controller.h | -| | -| Driver for Coolermaster ARGB Controller | -| | -| morg (Morgan Guimard) 6/26/2022 | -| | -\*-------------------------------------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "CMARGBGen2A1controller.h" -#include - -class RGBController_CMARGBGen2A1Controller : public RGBController -{ -public: - RGBController_CMARGBGen2A1Controller(CMARGBGen2A1controller* controller_ptr); - ~RGBController_CMARGBGen2A1Controller(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - void SetCustomMode(); - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - CMARGBGen2A1controller* controller; -}; diff --git a/Controllers/CoolerMasterController/RGBController_CMMKController.cpp b/Controllers/CoolerMasterController/RGBController_CMMKController.cpp deleted file mode 100644 index dce60a1f..00000000 --- a/Controllers/CoolerMasterController/RGBController_CMMKController.cpp +++ /dev/null @@ -1,498 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMMKController.cpp | -| | -| Driver for Coolermaster MasterKeys keyboards | -| | -| Lukas N (chmod222) 28th Jun 2020 | -| Tam D (too.manyhobbies) 25th Apr 2021 | -| | -\*-------------------------------------------------------------------*/ - -#include "RGBController_CMMKController.h" - -#include - -using namespace std::chrono_literals; - -#define CMMK_SPEED_MIN CMMK_SPEED0 -#define CMMK_SPEED_MID CMMK_SPEED2 -#define CMMK_SPEED_MAX CMMK_SPEED4 -#define CMMK_MODE_FIRMWARE 0xFF -#define CMMK_MODE_MANUAL 0x7F - -/**------------------------------------------------------------------*\ - @name Coolermaster Masterkeys Keyboards - @category Keyboard - @type USB - @save :robot: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectCoolerMasterKeyboards - @comment -\*-------------------------------------------------------------------*/ - -RGBController_CMMKController::RGBController_CMMKController(CMMKController* controller_ptr) -{ - controller = controller_ptr; - - name = controller->GetDeviceName(); - vendor = controller->GetDeviceVendor(); - type = DEVICE_TYPE_KEYBOARD; - description = "Cooler Master MasterKeys Device"; - version = controller->GetFirmwareVersion(); - serial = ""; - location = controller->GetLocation(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = CMMK_MODE_MANUAL; - 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 = CMMK_EFFECT_FULLY_LIT; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; - Static.colors_min = 1; - Static.colors_max = 1; - Static.colors.resize(1); - modes.push_back(Static); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = CMMK_EFFECT_BREATHE; - Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.speed_min = CMMK_SPEED_MIN; - Breathing.speed_max = CMMK_SPEED_MAX; - Breathing.speed = CMMK_SPEED_MID; - Breathing.colors_min = 1; - Breathing.colors_max = 1; - Breathing.colors.resize(1); - modes.push_back(Breathing); - - mode Cycle; - Cycle.name = "Spectrum Cycle"; - Cycle.value = CMMK_EFFECT_CYCLE; - Cycle.flags = MODE_FLAG_HAS_SPEED; - Cycle.color_mode = MODE_COLORS_NONE; - Cycle.speed_min = 2 * CMMK_SPEED_MIN; //Spectrum Cycle uses a unique speed range - Cycle.speed_max = 2 * CMMK_SPEED_MAX; - Cycle.speed = 2 * CMMK_SPEED_MID; - modes.push_back(Cycle); - - mode Reactive; - Reactive.name = "Reactive"; - Reactive.value = CMMK_EFFECT_SINGLE; - Reactive.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED; - Reactive.color_mode = MODE_COLORS_MODE_SPECIFIC; - Reactive.speed_min = CMMK_SPEED_MIN; - Reactive.speed_max = CMMK_SPEED_MAX; - Reactive.speed = CMMK_SPEED_MID; - Reactive.colors_min = 2; - Reactive.colors_max = 2; - Reactive.colors.resize(2); - modes.push_back(Reactive); - - mode Wave; - Wave.name = "Rainbow Wave"; - Wave.value = CMMK_EFFECT_WAVE; - Wave.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD; - Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; - Wave.speed_min = CMMK_SPEED_MIN; - Wave.speed_max = CMMK_SPEED_MAX; - Wave.speed = CMMK_SPEED_MID; - Wave.direction = MODE_DIRECTION_LEFT; - Wave.colors_min = 1; - Wave.colors_max = 1; - Wave.colors.resize(1); - modes.push_back(Wave); - - mode Ripple; - Ripple.name = "Ripple Effect"; - Ripple.value = CMMK_EFFECT_RIPPLE; - Ripple.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED; - Ripple.color_mode = MODE_COLORS_MODE_SPECIFIC; - Ripple.speed_min = CMMK_SPEED_MIN; - Ripple.speed_max = CMMK_SPEED_MAX; - Ripple.speed = CMMK_SPEED_MID; - Ripple.colors_min = 2; - Ripple.colors_max = 2; - Ripple.colors.resize(2); - modes.push_back(Ripple); - - mode Cross; - Cross.name = "Cross"; - Cross.value = CMMK_EFFECT_CROSS; - Cross.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED; - Cross.color_mode = MODE_COLORS_MODE_SPECIFIC; - Cross.speed_min = CMMK_SPEED_MIN; - Cross.speed_max = CMMK_SPEED_MAX; - Cross.speed = CMMK_SPEED_MID; - Cross.colors_min = 2; - Cross.colors_max = 2; - Cross.colors.resize(2); - modes.push_back(Cross); - - mode Raindrops; - Raindrops.name = "Raindrops"; - Raindrops.value = CMMK_EFFECT_RAINDROPS; - Raindrops.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED; - Raindrops.color_mode = MODE_COLORS_MODE_SPECIFIC; - Raindrops.speed_min = CMMK_SPEED_MIN; - Raindrops.speed_max = CMMK_SPEED_MAX; - Raindrops.speed = CMMK_SPEED_MID; - Raindrops.colors_min = 2; - Raindrops.colors_max = 2; - Raindrops.colors.resize(2); - modes.push_back(Raindrops); - - mode Stars; - Stars.name = "Starfield"; - Stars.value = CMMK_EFFECT_STARS; - Stars.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED; - Stars.color_mode = MODE_COLORS_MODE_SPECIFIC; - Stars.speed_min = CMMK_SPEED_MIN; - Stars.speed_max = CMMK_SPEED_MAX; - Stars.speed = CMMK_SPEED_MID; - Stars.colors_min = 2; - Stars.colors_max = 2; - Stars.colors.resize(2); - modes.push_back(Stars); - - mode Snake; - Snake.name = "Snake"; - Snake.value = CMMK_EFFECT_SNAKE; - Snake.flags = MODE_FLAG_HAS_SPEED; - Snake.color_mode = MODE_COLORS_NONE; - Snake.speed_min = CMMK_SPEED_MIN; - Snake.speed_max = CMMK_SPEED_MAX; - Snake.speed = CMMK_SPEED_MID; - modes.push_back(Snake); - - mode FirmwareControl; - FirmwareControl.name = "Firmware Controlled"; - FirmwareControl.value = 0xFF; - FirmwareControl.flags = 0; - FirmwareControl.color_mode = MODE_COLORS_NONE; - modes.push_back(FirmwareControl); - - SetupZones(); -} - -RGBController_CMMKController::~RGBController_CMMKController() -{ - delete controller; -} - -void RGBController_CMMKController::SetupMatrixMap() -{ - for(int y = 0; y < CMMK_ROWS_MAX; y++) - { - for(int x = 0; x < CMMK_COLS_MAX; x++) - { - matrix_map[y][x] = 0xFFFFFFFF; - } - } - - for(size_t i = 0; i < leds.size(); i++) - { - led& l = leds[i]; - - int y = (l.value & 0xFF00) >> 8; - int x = (l.value & 0xFF); - - matrix_map[y][x] = i; - } -} - -void RGBController_CMMKController::SetupZones() -{ - uint8_t row_count = controller->GetRowCount(); - uint8_t column_count = controller->GetColumnCount(); - - for(int y = 0; y < row_count; y++) - { - for(int x = 0; x < column_count; x++) - { - if(!controller->PositionValid(y, x)) - { - continue; - } - - std::stringstream namestrm; - - led key; - - namestrm << "Key @ Row " << (y + 1) << ", Column" << (x + 1); - - key.name = namestrm.str(); - key.value = (y & 0xFF) << 8 | (x & 0xFF); - - leds.push_back(key); - } - } - - zone KeyboardZone; - KeyboardZone.name = "Keyboard"; - KeyboardZone.type = ZONE_TYPE_MATRIX; - KeyboardZone.leds_min = leds.size(); - KeyboardZone.leds_max = leds.size(); - KeyboardZone.leds_count = leds.size(); - KeyboardZone.matrix_map = new matrix_map_type; - KeyboardZone.matrix_map->height = row_count; - KeyboardZone.matrix_map->width = column_count; - KeyboardZone.matrix_map->map = (unsigned int *)&matrix_map; - - zones.push_back(KeyboardZone); - - SetupMatrixMap(); - SetupColors(); -} - -void RGBController_CMMKController::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -struct rgb map_to_cmmk_rgb(RGBColor input) -{ - return rgb - { - (uint8_t)RGBGetRValue(input), - (uint8_t)RGBGetGValue(input), - (uint8_t)RGBGetBValue(input) - }; -} - -enum cmmk_wave_direction map_to_cmmk_dir(int input) -{ - switch(input) - { - case MODE_DIRECTION_LEFT: - return CMMK_RIGHT_TO_LEFT; - - case MODE_DIRECTION_RIGHT: - return CMMK_LEFT_TO_RIGHT; - - case MODE_DIRECTION_UP: - return CMMK_FRONT_TO_BACK; - - case MODE_DIRECTION_DOWN: - return CMMK_BACK_TO_FRONT; - - default: - return CMMK_RIGHT_TO_LEFT; - } -} - -void copy_buffers(led* buf, RGBColor* colbuf, size_t n, struct cmmk_color_matrix& mat, std::atomic& dirty) -{ - dirty.store(false); - - for(size_t i = 0; i < n; i++) - { - led const& selected_led = buf[i]; - - int y = (selected_led.value & 0xFF00) >> 8; - int x = selected_led.value & 0xFF; - - struct rgb col = map_to_cmmk_rgb(colbuf[i]); - struct rgb ecol = mat.data[y][x]; - - if(ecol.R != col.R || ecol.G != col.G || ecol.B != col.B) - { - dirty.store(true); - - mat.data[y][x] = col; - } - } -} - -void RGBController_CMMKController::DeviceUpdateLEDs() -{ - copy_buffers(leds.data(), colors.data(), leds.size(), current_matrix, dirty); - - if(force_update.load() || dirty.load()) - { - controller->SetAll(current_matrix); - - force_update.store(false); - } -} - -void RGBController_CMMKController::UpdateZoneLEDs(int zone_idx) -{ - zone& z = zones[zone_idx]; - - copy_buffers(z.leds, z.colors, z.leds_count, current_matrix, dirty); - - if(force_update.load() || dirty.load()) - { - controller->SetAll(current_matrix); - - force_update.store(false); - } -} - -void RGBController_CMMKController::UpdateSingleLED(int led_idx) -{ - led& selected_led = leds[led_idx]; - - int y = (selected_led.value & 0xFF00) >> 8; - int x = selected_led.value & 0xFF; - - current_matrix.data[y][x] = map_to_cmmk_rgb(colors[led_idx]); - - controller->SetSingle(y, x, map_to_cmmk_rgb(colors[led_idx])); - dirty.store(false); -} - -void RGBController_CMMKController::SetCustomMode() -{ - active_mode = 1; -} - -void RGBController_CMMKController::DeviceUpdateMode() -{ - force_update.store(true); - - switch(modes[active_mode].value) - { - case CMMK_MODE_FIRMWARE: - controller->SetFirmwareControl(); - break; - - case CMMK_MODE_MANUAL: - controller->SetManualControl(); - break; - - case CMMK_EFFECT_FULLY_LIT: - { - cmmk_effect_fully_lit fully_lit_effect; - - fully_lit_effect.color = map_to_cmmk_rgb(modes[active_mode].colors[0]); - - controller->SetMode(fully_lit_effect); - } - break; - - case CMMK_EFFECT_BREATHE: - { - cmmk_effect_breathe breathe_effect; - - breathe_effect.speed = (uint8_t)modes[active_mode].speed; - breathe_effect.color = map_to_cmmk_rgb(modes[active_mode].colors[0]); - - controller->SetMode(breathe_effect); - } - break; - - case CMMK_EFFECT_CYCLE: - { - cmmk_effect_cycle cycle_effect; - - cycle_effect.speed = (uint8_t)modes[active_mode].speed; - - controller->SetMode(cycle_effect); - } - break; - - case CMMK_EFFECT_SINGLE: - { - cmmk_effect_single single_effect; - - single_effect.speed = (uint8_t)modes[active_mode].speed; - single_effect.active = map_to_cmmk_rgb(modes[active_mode].colors[0]); - single_effect.rest = map_to_cmmk_rgb(modes[active_mode].colors[1]); - - controller->SetMode(single_effect); - } - break; - - case CMMK_EFFECT_WAVE: - { - cmmk_effect_wave wave_effect; - - wave_effect.speed = (uint8_t)modes[active_mode].speed; - wave_effect.direction = map_to_cmmk_dir(modes[active_mode].direction); - wave_effect.start = map_to_cmmk_rgb(modes[active_mode].colors[0]); - - controller->SetMode(wave_effect); - } - break; - - case CMMK_EFFECT_RIPPLE: - { - cmmk_effect_ripple ripple_effect; - - ripple_effect.speed = (uint8_t)modes[active_mode].speed; - ripple_effect.active = map_to_cmmk_rgb(modes[active_mode].colors[0]); - ripple_effect.rest = map_to_cmmk_rgb(modes[active_mode].colors[1]); - - if(modes[active_mode].color_mode == MODE_COLORS_RANDOM) - { - ripple_effect.ripple_type = CMMK_RIPPLE_RANDOM_COLOR; - } - else - { - ripple_effect.ripple_type = CMMK_RIPPLE_GIVEN_COLOR; - } - - controller->SetMode(ripple_effect); - } - break; - - case CMMK_EFFECT_CROSS: - { - cmmk_effect_cross cross_effect; - - cross_effect.speed = (uint8_t)modes[active_mode].speed; - cross_effect.active = map_to_cmmk_rgb(modes[active_mode].colors[0]); - cross_effect.rest = map_to_cmmk_rgb(modes[active_mode].colors[1]); - - controller->SetMode(cross_effect); - } - break; - - case CMMK_EFFECT_RAINDROPS: - { - cmmk_effect_raindrops raindrops_effect; - - raindrops_effect.speed = (uint8_t)modes[active_mode].speed; - raindrops_effect.interval = CMMK_SPEED_MID; - raindrops_effect.active = map_to_cmmk_rgb(modes[active_mode].colors[0]); - raindrops_effect.rest = map_to_cmmk_rgb(modes[active_mode].colors[1]); - - controller->SetMode(raindrops_effect); - } - break; - - case CMMK_EFFECT_STARS: - { - cmmk_effect_stars stars_effect; - - stars_effect.speed = (uint8_t)modes[active_mode].speed; - stars_effect.interval = CMMK_SPEED_MID; - stars_effect.active = map_to_cmmk_rgb(modes[active_mode].colors[0]); - stars_effect.rest = map_to_cmmk_rgb(modes[active_mode].colors[1]); - - controller->SetMode(stars_effect); - } - break; - - case CMMK_EFFECT_SNAKE: - { - cmmk_effect_snake snake_effect; - - snake_effect.speed = (uint8_t)modes[active_mode].speed; - - controller->SetMode(snake_effect); - } - break; - } -} diff --git a/Controllers/CoolerMasterController/RGBController_CMMKController.h b/Controllers/CoolerMasterController/RGBController_CMMKController.h deleted file mode 100644 index 39c87ab3..00000000 --- a/Controllers/CoolerMasterController/RGBController_CMMKController.h +++ /dev/null @@ -1,42 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMMKController.h | -| | -| Driver for Coolermaster MasterKeys keyboards | -| | -| Lukas N (chmod222) 28th Jun 2020 | -| Tam D (too.manyhobbies) 25th Apr 2021 | -| | -\*-------------------------------------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "CMMKController.h" - -class RGBController_CMMKController : public RGBController -{ -public: - RGBController_CMMKController(CMMKController* controller_ptr); - ~RGBController_CMMKController(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void SetCustomMode(); - void DeviceUpdateMode(); - -private: - void SetupMatrixMap(); - - CMMKController* controller; - - int matrix_map[CMMK_ROWS_MAX][CMMK_COLS_MAX]; - struct cmmk_color_matrix current_matrix; - - std::atomic dirty; - std::atomic force_update; -}; diff --git a/Controllers/CoolerMasterController/RGBController_CMMM711Controller.h b/Controllers/CoolerMasterController/RGBController_CMMM711Controller.h deleted file mode 100644 index a6c67c2d..00000000 --- a/Controllers/CoolerMasterController/RGBController_CMMM711Controller.h +++ /dev/null @@ -1,40 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMMM711Controller.h | -| | -| Driver for Coolermaster MM711 Controller | -| | -| Chris M (Dr_No) 14th Feb 2021 | -| | -\*-------------------------------------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "CMMM711Controller.h" -#include - -#define CM_MM_ARGB_BRIGHTNESS_MIN 0x00 -#define CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT 0xFF -#define CM_MM_ARGB_BRIGHTNESS_MAX_SPECTRUM 0x7F - -class RGBController_CMMM711Controller : public RGBController -{ -public: - RGBController_CMMM711Controller(CMMM711Controller* controller_ptr); - ~RGBController_CMMM711Controller(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void SetCustomMode(); - void DeviceUpdateMode(); - void DeviceSaveMode(); -private: - void Init_Controller(); - int GetDeviceMode(); - - CMMM711Controller* controller; -}; diff --git a/Controllers/CoolerMasterController/RGBController_CMMMController.h b/Controllers/CoolerMasterController/RGBController_CMMMController.h deleted file mode 100644 index 79d23691..00000000 --- a/Controllers/CoolerMasterController/RGBController_CMMMController.h +++ /dev/null @@ -1,43 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMMMController.h | -| | -| Driver for Coolermaster MaterMouse Controller | -| | -| Chris M (Dr_No) 14th Feb 2021 - MM711 Base | -| Dracrius 12th Mar 2022 | -| | -\*-------------------------------------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "CMMMController.h" -#include - -#define CM_MM_ARGB_BRIGHTNESS_MIN 0x00 -#define CM_MM_ARGB_BRIGHTNESS_MAX_DEFAULT 0xFF -#define CM_MM_ARGB_BRIGHTNESS_MAX_SPECTRUM 0x7F - -class RGBController_CMMMController : public RGBController -{ -public: - RGBController_CMMMController(CMMMController* controller_ptr); - ~RGBController_CMMMController(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void SetCustomMode(); - void DeviceUpdateMode(); - void DeviceSaveMode(); -private: - void Init_Controller(); - int GetDeviceMode(); - - int leds_count; - - CMMMController* controller; -}; diff --git a/Controllers/CoolerMasterController/RGBController_CMMP750Controller.h b/Controllers/CoolerMasterController/RGBController_CMMP750Controller.h deleted file mode 100644 index 69e3f56d..00000000 --- a/Controllers/CoolerMasterController/RGBController_CMMP750Controller.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMMP750Controller.h | -| | -| Driver for Coolermaster MP750 mousepad | -| | -| Chris M (Dr_No) 18th Apr 2020 | -| | -\*-------------------------------------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "CMMP750Controller.h" - -class RGBController_CMMP750Controller : public RGBController -{ -public: - RGBController_CMMP750Controller(CMMP750Controller* controller_ptr); - ~RGBController_CMMP750Controller(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void SetCustomMode(); - void DeviceUpdateMode(); -private: - CMMP750Controller* controller; - - int GetDeviceMode(); -}; diff --git a/Controllers/CoolerMasterController/RGBController_CMR6000Controller.h b/Controllers/CoolerMasterController/RGBController_CMR6000Controller.h deleted file mode 100644 index 0bf823dc..00000000 --- a/Controllers/CoolerMasterController/RGBController_CMR6000Controller.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMR6000Controller.h | -| | -| Driver for Coolermaster based AMD Radeon GPU (6000 series) | -| | -| Eric S (edbgon) 2nd Feb 2021 | -\*-------------------------------------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "CMR6000Controller.h" - -class RGBController_CMR6000Controller : public RGBController -{ -public: - RGBController_CMR6000Controller(CMR6000Controller* controller_ptr); - ~RGBController_CMR6000Controller(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void SetCustomMode(); - void DeviceUpdateMode(); -private: - CMR6000Controller* controller; - - int GetDeviceMode(); -}; diff --git a/Controllers/CoolerMasterController/RGBController_CMRGBController.h b/Controllers/CoolerMasterController/RGBController_CMRGBController.h deleted file mode 100644 index 9b9cc7cf..00000000 --- a/Controllers/CoolerMasterController/RGBController_CMRGBController.h +++ /dev/null @@ -1,35 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMRGBController.h | -| | -| Driver for Coolermaster RGB USB Controller | -| | -| Nic W (midgetspy) 13th Apr 2021 | -| | -\*-------------------------------------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "CMRGBController.h" -#include - -class RGBController_CMRGBController : public RGBController -{ -public: - RGBController_CMRGBController(CMRGBController* controller_ptr); - ~RGBController_CMRGBController(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void SetCustomMode(); - void DeviceUpdateMode(); - -private: - CMRGBController* controller; - void LoadConfigFromDeviceController(int device_mode); - void ReadAllModeConfigsFromDevice(); -}; diff --git a/Controllers/CoolerMasterController/RGBController_CMSmallARGBController.h b/Controllers/CoolerMasterController/RGBController_CMSmallARGBController.h deleted file mode 100644 index 961ca7c4..00000000 --- a/Controllers/CoolerMasterController/RGBController_CMSmallARGBController.h +++ /dev/null @@ -1,40 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CMSmallARGBController.h | -| | -| Driver for Coolermaster Small ARGB USB Controller | -| | -| Chris M (Dr_No) 31st Jan 2021 | -| | -\*-------------------------------------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "CMSmallARGBController.h" -#include - -#define CM_SMALL_ARGB_MIN_LEDS 4 -#define CM_SMALL_ARGB_MAX_LEDS 48 -#define CM_SMALL_ARGB_BRIGHTNESS_MAX 0xFF -#define CM_SMALL_ARGB_FW0012 "A202104052336" - -class RGBController_CMSmallARGBController : public RGBController -{ -public: - RGBController_CMSmallARGBController(CMSmallARGBController* controller_ptr); - ~RGBController_CMSmallARGBController(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void SetCustomMode(); - void DeviceUpdateMode(); -private: - void Init_Controller(); - int GetDeviceMode(); - - CMSmallARGBController* controller; -}; diff --git a/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.cpp b/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.cpp index fd44221b..9c869ec3 100644 --- a/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.cpp +++ b/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.cpp @@ -1,28 +1,48 @@ /*---------------------------------------------------------*\ -| CorsairCommanderCoreController.cpp | +| CorsairCommanderCoreController.cpp | | | -| Processing Code for Corsair Commander Core | +| Driver for Corsair Commander Core | | | -| Jeff P. | +| Jeff P. | +| Nikola Jurkovic (jurkovic.nikola) 14 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "CorsairCommanderCoreController.h" - #include #include #include +#include "CorsairCommanderCoreController.h" +#include "CorsairDeviceGuard.h" using namespace std::chrono_literals; -CorsairCommanderCoreController::CorsairCommanderCoreController(hid_device* dev_handle, const char* path, int pid) +CorsairCommanderCoreController::CorsairCommanderCoreController(hid_device* dev_handle, const char* path, int pid, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; keepalive_thread_run = 1; controller_ready = 0; packet_size = CORSAIR_COMMANDER_CORE_PACKET_SIZE_V2; command_res_size = packet_size - 4; this->pid = pid; + guard_manager_ptr = new DeviceGuardManager(new CorsairDeviceGuard()); + + if(pid == CORSAIR_COMMANDER_CORE2_PID) + { + packet_size = CORSAIR_COMMANDER_CORE_PACKET_SIZE_V3; + command_res_size = packet_size - 4; + } + else if(pid == CORSAIR_COMMANDER_CORE_XT_PID) + { + /*-----------------------------------------------------*\ + | Commander Core XT | + \*-----------------------------------------------------*/ + packet_size = CORSAIR_COMMANDER_CORE_XT_PACKET_SIZE; + command_res_size = packet_size - 4; + } /*-----------------------------------------------------*\ | Initialize controller | @@ -37,6 +57,13 @@ CorsairCommanderCoreController::CorsairCommanderCoreController(hid_device* dev_h CorsairCommanderCoreController::~CorsairCommanderCoreController() { + /*-----------------------------------------------------*\ + | Hardware mode | + \*-----------------------------------------------------*/ + unsigned char command[2] = {0x01, 0x03}; + unsigned char cmd_data[2] = {0x00, 0x01}; + SendCommand(command, cmd_data, 2, NULL); + /*-----------------------------------------------------*\ | Close keepalive thread | \*-----------------------------------------------------*/ @@ -48,6 +75,7 @@ CorsairCommanderCoreController::~CorsairCommanderCoreController() | Close HID device | \*-----------------------------------------------------*/ hid_close(dev); + delete guard_manager_ptr; } void CorsairCommanderCoreController::InitController() @@ -57,31 +85,20 @@ void CorsairCommanderCoreController::InitController() \*-----------------------------------------------------*/ unsigned char command[2] = {0x02, 0x13}; unsigned char* res = new unsigned char[command_res_size]; + SendCommand(command, NULL, 0, res); version[0] = res[0]; version[1] = res[1]; version[2] = res[2]; delete[] res; - if (pid == 0x0C1C && version[0] == 1) + if(pid == CORSAIR_COMMANDER_CORE_PID && version[0] == 1) { packet_size = CORSAIR_COMMANDER_CORE_PACKET_SIZE_V1; command_res_size = packet_size - 4; } - else if (pid == 0x0C32) - { - packet_size = CORSAIR_COMMANDER_CORE_PACKET_SIZE_V3; - } - /*-----------------------------------------------------*\ - | Wake up device | - \*-----------------------------------------------------*/ - command[0] = 0x01; - command[1] = 0x03; - unsigned char cmd_data[2] = {0x00, 0x02}; - SendCommand(command, cmd_data, 2, NULL); - - SetFanMode(); + SetFanMode(false); } std::string CorsairCommanderCoreController::GetFirmwareString() @@ -94,11 +111,39 @@ std::string CorsairCommanderCoreController::GetLocationString() return("HID: " + location); } +std::string CorsairCommanderCoreController::GetNameString() +{ + return(name); +} + +int CorsairCommanderCoreController::GetPidInt() +{ + return(this->pid); +} + +std::vector CorsairCommanderCoreController::GetLedCounts() +{ + /*-----------------------------------------------------*\ + | Get the LED count per device | + \*-----------------------------------------------------*/ + std::vector led_counts; + unsigned char endpoint[2] = {0x20, 0x00}; + unsigned char* res = new unsigned char[command_res_size]; + ReadData(endpoint, res); + for(int i = 0; i < res[2]; i++) + { + led_counts.push_back(res[i*4+6] << 8 | res[i*4+5]); + } + delete[] res; + + return led_counts; +} + void CorsairCommanderCoreController::KeepaliveThread() { while(keepalive_thread_run.load()) { - if (controller_ready) + if(controller_ready) { if((std::chrono::steady_clock::now() - last_commit_time) > std::chrono::seconds(10)) { @@ -126,16 +171,15 @@ void CorsairCommanderCoreController::SendCommit() last_commit_time = std::chrono::steady_clock::now(); /*-----------------------------------------------------*\ - | Send packet | + | Keepalive | \*-----------------------------------------------------*/ - unsigned char command[2] = {0x01, 0x03}; - unsigned char cmd_data[2] = {0x00, 0x02}; - SendCommand(command, cmd_data, 2, NULL); + unsigned char command[2] = {0x02, 0x13}; + SendCommand(command, NULL, 2, NULL, false); } } -void CorsairCommanderCoreController::SendCommand(unsigned char command[2], unsigned char data[], unsigned short int data_len, unsigned char res[]) +void CorsairCommanderCoreController::SendCommand(unsigned char command[2], unsigned char data[], unsigned short int data_len, unsigned char res[], bool dev_read) { /*---------------------------------------------------------*\ | Private function to send a command | @@ -153,12 +197,26 @@ void CorsairCommanderCoreController::SendCommand(unsigned char command[2], unsig memcpy(&buf[4], data, data_len); } - hid_write(dev, buf, packet_size); - do + /*---------------------------------------------------------*\ + | HID I/O start | + \*---------------------------------------------------------*/ { - hid_read(dev, buf, packet_size); + DeviceGuardLock _ = guard_manager_ptr->AwaitExclusiveAccess(); + + hid_write(dev, buf, packet_size); + if(dev_read) + { + do + { + hid_read(dev, buf, packet_size); + } + while(buf[0] != 0x00); + } } - while (buf[0] != 0x00); + + /*---------------------------------------------------------*\ + | HID I/O end (lock released) | + \*---------------------------------------------------------*/ if(res != NULL) { @@ -177,10 +235,9 @@ void CorsairCommanderCoreController::WriteData(unsigned char endpoint[2], unsign /*---------------------------------------------------------*\ | Open endpoint | \*---------------------------------------------------------*/ - unsigned char command[2] = {0x0d, 0x00}; + unsigned char command[2] = {0x0D, 0x00}; SendCommand(command, endpoint, 2, NULL); - /*---------------------------------------------------------*\ | Write data | \*---------------------------------------------------------*/ @@ -242,6 +299,35 @@ void CorsairCommanderCoreController::WriteData(unsigned char endpoint[2], unsign SendCommand(command, NULL, 0, NULL); } +void CorsairCommanderCoreController::ReadData(unsigned char endpoint[2], unsigned char data[]) +{ + /*---------------------------------------------------------*\ + | Private function to read data from an endpoint | + | Note: Right now we only know how to read the first packet.| + | It is not currently know how to read more. | + \*---------------------------------------------------------*/ + + /*---------------------------------------------------------*\ + | Open endpoint | + \*---------------------------------------------------------*/ + unsigned char command[2] = {0x0D, 0x00}; + SendCommand(command, endpoint, 2, NULL); + + /*---------------------------------------------------------*\ + | Read data | + \*---------------------------------------------------------*/ + command[0] = 0x08; + command[1] = 0x00; + SendCommand(command, NULL, 0, data); + + /*---------------------------------------------------------*\ + | Close endpoint | + \*---------------------------------------------------------*/ + command[0] = 0x05; + command[1] = 0x01; + SendCommand(command, NULL, 0, NULL); +} + void CorsairCommanderCoreController::SetDirectColor ( std::vector colors, @@ -255,9 +341,14 @@ void CorsairCommanderCoreController::SetDirectColor int packet_offset = 0; int led_idx = 0; int channel_idx = 0; - unsigned char* usb_buf = new unsigned char[CORSAIR_COMMANDER_CORE_RGB_DATA_LENGTH]; + int packet_len = CORSAIR_COMMANDER_CORE_RGB_DATA_LENGTH; - memset(usb_buf, 0, CORSAIR_COMMANDER_CORE_RGB_DATA_LENGTH); + if(pid == CORSAIR_COMMANDER_CORE_XT_PID) + { + packet_len = CORSAIR_COMMANDER_CORE_XT_RGB_DATA_LENGTH; + } + + unsigned char* usb_buf = new unsigned char[packet_len]; for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++) { @@ -269,24 +360,13 @@ void CorsairCommanderCoreController::SetDirectColor 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 += 3; } led_idx = led_idx + zones[zone_idx].leds_count; - /*-------------------------------------------------*\ - | Move offset for pump zone with less than 29 LEDs | - \*-------------------------------------------------*/ - if(zone_idx == 0) + if(zone_idx != 0) { - packet_offset += 3 * (29 - zones[zone_idx].leds_count); - } - else - { - /*-------------------------------------------------*\ - | Move offset for fans with less than 34 LEDs | - \*-------------------------------------------------*/ packet_offset += 3 * (34 - zones[zone_idx].leds_count); } @@ -306,33 +386,100 @@ void CorsairCommanderCoreController::SetDirectColor } } -void CorsairCommanderCoreController::SetFanMode() +void CorsairCommanderCoreController::SetFanMode(bool external_rgb_port) { - /*--------------------------------------------------------------------------------------------------*\ - | Force controller to 6 QL fan mode to expose maximum number of LEDs per rgb port (34 LEDs per port) | - \*--------------------------------------------------------------------------------------------------*/ + controller_ready = 0; + DeviceGuardLock _ = guard_manager_ptr->AwaitExclusiveAccess(); + + /*-----------------------------------------------------*\ + | Force controller to 6 QL fan mode to expose maximum | + | number of LEDs per rgb port (34 LEDs per port) | + \*-----------------------------------------------------*/ + unsigned int index = 3; + unsigned int max_index = 15; + unsigned char endpoint[2] = {0x1E, 0x00}; + unsigned char data_type[2] = {0x0D, 0x00}; - unsigned char endpoint[2] = {0x1E, 0x00}; - unsigned char data_type[2] = {0x0D, 0x00}; unsigned char buf[15]; /*-----------------------------------------------------*\ - | Set AIO mode | + | Zero out buffer | \*-----------------------------------------------------*/ - buf[0] = 0x07; - buf[1] = 0x01; - buf[2] = 0x08; + memset(buf, 0x00, 15); + + buf[0] = 0x07; + if(pid == CORSAIR_COMMANDER_CORE_XT_PID) + { + /*-------------------------------------------------*\ + | Commander Core XT external RGB port | + \*-------------------------------------------------*/ + if(external_rgb_port) + { + /*---------------------------------------------*\ + | Enable external port | + \*---------------------------------------------*/ + buf[1] = 0x01; + buf[2] = 0x01; + } + else + { + /*---------------------------------------------*\ + | Shift packet start position and maximum index | + \*---------------------------------------------*/ + buf[1] = 0x00; + buf[2] = 0x00; + index = 2; + max_index = 14; + } + } + else + { + /*-------------------------------------------------*\ + | Commander Core, Set AIO mode | + \*-------------------------------------------------*/ + buf[1] = 0x01; + buf[2] = 0x08; + } /*-----------------------------------------------------*\ | SET fan modes | \*-----------------------------------------------------*/ - for(unsigned int i = 3; i < 15; i = i + 2) + for(unsigned int i = index; i < max_index; i = i + 2) { - buf[i] = 0x01; - buf[i + 1] = 0x06; + buf[i] = 0x01; + buf[i + 1] = 0x06; } WriteData(endpoint, data_type, buf, 15); - + controller_ready = 1; + + /*-----------------------------------------------------*\ + | Wake up device, needs to be done after setting fan | + | mode to reinitialize device if fan mode has changed | + \*-----------------------------------------------------*/ + unsigned char command[2] = {0x01, 0x03}; + unsigned char cmd_data[2] = {0x00, 0x02}; + SendCommand(command, cmd_data, 2, NULL); +} + +void CorsairCommanderCoreController::SetLedAmount(int led_amount) +{ + controller_ready = 0; + DeviceGuardLock _ = guard_manager_ptr->AwaitExclusiveAccess(); + + unsigned char buf[15]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(buf, 0x00, 15); + + unsigned char endpoint[2] = {0x1D, 0x00}; + unsigned char data_type[2] = {0x0C, 0x00}; + + buf[0] = 0x07; + buf[1] = led_amount; + + WriteData(endpoint, data_type, buf, 15); controller_ready = 1; } diff --git a/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.h b/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.h index fe489193..f8ad889a 100644 --- a/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.h +++ b/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.h @@ -1,27 +1,44 @@ /*---------------------------------------------------------*\ -| CorsairCommanderCoreController.h | +| CorsairCommanderCoreController.h | | | -| Definitions for Corsair Commander Core | -| Based on code by: | -| Adam Honse (calcprogrammer1@gmail.com), 8/17/2020 | +| Driver for Corsair Commander Core | | | -| Jeff P. | +| Jeff P. | +| Nikola Jurkovic (jurkovic.nikola) 14 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "RGBController.h" -#include -#include -#include - #pragma once -#define CORSAIR_COMMANDER_CORE_PACKET_SIZE_V1 1025 // First bit is the report bit -#define CORSAIR_COMMANDER_CORE_PACKET_SIZE_V2 97 // First bit is the report bit -#define CORSAIR_COMMANDER_CORE_PACKET_SIZE_V3 65 // First bit is the report bit +#include +#include +#include +#include "RGBController.h" +#include "DeviceGuardManager.h" -#define CORSAIR_COMMANDER_CORE_RGB_DATA_LENGTH 699 -#define CORSAIR_QL_FAN_ZONE_OFFSET 102 -#define CORSAIR_COMMANDER_CORE_NUM_CHANNELS 6 +/*-----------------------------------------------------*\ +| Packet size per device | +\*-----------------------------------------------------*/ +#define CORSAIR_COMMANDER_CORE_PACKET_SIZE_V1 1025 +#define CORSAIR_COMMANDER_CORE_PACKET_SIZE_V2 97 +#define CORSAIR_COMMANDER_CORE_PACKET_SIZE_V3 65 +#define CORSAIR_COMMANDER_CORE_XT_PACKET_SIZE 385 + +#define CORSAIR_COMMANDER_CORE_RGB_DATA_LENGTH 699 +#define CORSAIR_COMMANDER_CORE_XT_RGB_DATA_LENGTH 1224 + +#define CORSAIR_QL_FAN_ZONE_OFFSET 102 +#define CORSAIR_COMMANDER_CORE_NUM_CHANNELS 6 + +#define CORSAIR_COMMANDER_CORE_PID 0x0C1C +#define CORSAIR_COMMANDER_CORE2_PID 0x0C32 +#define CORSAIR_COMMANDER_CORE3_PID 0x0C1D +#define CORSAIR_COMMANDER_CORE4_PID 0x0C3C +#define CORSAIR_COMMANDER_CORE5_PID 0x0C3D +#define CORSAIR_COMMANDER_CORE6_PID 0x0C3E +#define CORSAIR_COMMANDER_CORE_XT_PID 0x0C2A enum { @@ -31,11 +48,14 @@ enum class CorsairCommanderCoreController { public: - CorsairCommanderCoreController(hid_device* dev_handle, const char* path, int pid); + CorsairCommanderCoreController(hid_device* dev_handle, const char* path, int pid, std::string dev_name); ~CorsairCommanderCoreController(); std::string GetFirmwareString(); + std::vector GetLedCounts(); std::string GetLocationString(); + std::string GetNameString(); + int GetPidInt(); void SetDirectColor ( @@ -44,24 +64,28 @@ public: ); void KeepaliveThread(); - void SetFanMode(); + void SetFanMode(bool external_rgb_port); + void SetLedAmount(int led_amount); private: - hid_device* dev; - std::thread* keepalive_thread; - std::atomic keepalive_thread_run; - std::atomic controller_ready; - std::string location; - std::vector lastcolors; - std::vector lastzones; - unsigned short int version[3] = {0, 0, 0}; - int packet_size; - int command_res_size; - int pid; - std::chrono::time_point last_commit_time; + hid_device* dev; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::atomic controller_ready; + std::string location; + std::vector lastcolors; + std::vector lastzones; + std::string name; + unsigned short int version[3] = {0, 0, 0}; + int packet_size; + int command_res_size; + int pid; + std::chrono::time_point last_commit_time; + DeviceGuardManager* guard_manager_ptr; - void SendCommand(unsigned char command[2], unsigned char data[], unsigned short int data_len, unsigned char res[]); + void SendCommand(unsigned char command[2], unsigned char data[], unsigned short int data_len, unsigned char res[], bool dev_read = true); void WriteData(unsigned char endpoint[2], unsigned char data_type[2], unsigned char data[], unsigned short int data_len); + void ReadData(unsigned char endpoint[2], unsigned char data[]); void SendCommit(); void InitController(); diff --git a/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreControllerDetect.cpp b/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreControllerDetect.cpp index f4e08956..6d4330a6 100644 --- a/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreControllerDetect.cpp +++ b/Controllers/CorsairCommanderCoreController/CorsairCommanderCoreControllerDetect.cpp @@ -1,43 +1,49 @@ +/*---------------------------------------------------------*\ +| CorsairCommanderCoreControllerDetect.cpp | +| | +| Detector for Corsair Commander Core | +| | +| Jeff P. | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "CorsairCommanderCoreController.h" -#include "RGBController.h" #include "RGBController_CorsairCommanderCore.h" -#include -#include /*-----------------------------------------------------*\ | Corsair vendor ID | \*-----------------------------------------------------*/ #define CORSAIR_VID 0x1B1C -/*-----------------------------------------------------*\ -| Commander Core product IDs | -\*-----------------------------------------------------*/ -#define CORSAIR_COMMANDER_CORE_PID 0x0C1C -#define CORSAIR_COMMANDER_CORE2_PID 0x0C32 - /******************************************************************************************\ * * -* DetectCorsairCapellixControllers * +* DetectCorsairCommanderCoreControllers * * * * Tests the USB address to see if a Corsair RGB Cooler controller exists there. * * * \******************************************************************************************/ -void DetectCorsairCapellixHIDControllers(hid_device_info* info, const std::string& name) +void DetectCorsairCommanderCoreControllers(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, info->product_id); + CorsairCommanderCoreController* controller = new CorsairCommanderCoreController(dev, info->path, info->product_id, name); RGBController_CorsairCommanderCore* rgb_controller = new RGBController_CorsairCommanderCore(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); } } -REGISTER_HID_DETECTOR_IPU("Corsair Commander Core", DetectCorsairCapellixHIDControllers, CORSAIR_VID, CORSAIR_COMMANDER_CORE_PID, 0x00, 0xFF42, 0x01); -REGISTER_HID_DETECTOR_IPU("Corsair Commander Core", DetectCorsairCapellixHIDControllers, CORSAIR_VID, CORSAIR_COMMANDER_CORE2_PID, 0x00, 0xFF42, 0x01); +REGISTER_HID_DETECTOR_IPU("Corsair Commander Core", DetectCorsairCommanderCoreControllers, CORSAIR_VID, CORSAIR_COMMANDER_CORE_PID, 0x00, 0xFF42, 0x01); +REGISTER_HID_DETECTOR_IPU("Corsair Commander Core", DetectCorsairCommanderCoreControllers, CORSAIR_VID, CORSAIR_COMMANDER_CORE2_PID, 0x00, 0xFF42, 0x01); +REGISTER_HID_DETECTOR_IPU("Corsair Commander Core", DetectCorsairCommanderCoreControllers, CORSAIR_VID, CORSAIR_COMMANDER_CORE3_PID, 0x00, 0xFF42, 0x01); +REGISTER_HID_DETECTOR_IPU("Corsair Commander Core", DetectCorsairCommanderCoreControllers, CORSAIR_VID, CORSAIR_COMMANDER_CORE4_PID, 0x00, 0xFF42, 0x01); +REGISTER_HID_DETECTOR_IPU("Corsair Commander Core", DetectCorsairCommanderCoreControllers, CORSAIR_VID, CORSAIR_COMMANDER_CORE5_PID, 0x00, 0xFF42, 0x01); +REGISTER_HID_DETECTOR_IPU("Corsair Commander Core", DetectCorsairCommanderCoreControllers, CORSAIR_VID, CORSAIR_COMMANDER_CORE6_PID, 0x00, 0xFF42, 0x01); +REGISTER_HID_DETECTOR_IPU("Corsair Commander Core XT", DetectCorsairCommanderCoreControllers, CORSAIR_VID, CORSAIR_COMMANDER_CORE_XT_PID, 0x00, 0xFF42, 0x01); diff --git a/Controllers/CorsairCommanderCoreController/RGBController_CorsairCommanderCore.cpp b/Controllers/CorsairCommanderCoreController/RGBController_CorsairCommanderCore.cpp index 4de29c0e..2f9c6a13 100644 --- a/Controllers/CorsairCommanderCoreController/RGBController_CorsairCommanderCore.cpp +++ b/Controllers/CorsairCommanderCoreController/RGBController_CorsairCommanderCore.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_CorsairCapellix.cpp | -| | -| Generic RGB Interface for Corsair | -| Commander Core | -| | -| Jeff P. | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairCCommanderCore.cpp | +| | +| RGBController for Corsair Commander Core | +| | +| Jeff P. | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CorsairCommanderCore.h" @@ -21,7 +23,7 @@ \*-------------------------------------------------------------------*/ #define NA 0xFFFFFFFF -static unsigned int matrix_map[7][7] = +static unsigned int matrix_map29[7][7] = { { 28, NA, 27, NA, 26, NA, 25 }, { NA, 16, NA, 15, NA, 14, NA }, @@ -32,16 +34,31 @@ static unsigned int matrix_map[7][7] = { 19, NA, 20, NA, 21, NA, 22 }, }; +static unsigned int matrix_map24[11][11] = +{ + { NA, NA, NA, NA, NA, 6, NA, NA, NA, NA, NA }, + { NA, NA, NA, 4, 5, NA, 7, 8, NA, NA, NA }, + { NA, NA, 3, NA, NA, NA, NA, NA, 9, NA, NA }, + { NA, 2, NA, NA, NA, NA, NA, NA, NA, 10, NA }, + { NA, 1, NA, NA, NA, NA, NA, NA, NA, 11, NA }, + { 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, 12 }, + { NA, 23, NA, NA, NA, NA, NA, NA, NA, 13, NA }, + { NA, 22, NA, NA, NA, NA, NA, NA, NA, 14, NA }, + { NA, NA, 21, NA, NA, NA, NA, NA, 15, NA, NA }, + { NA, NA, NA, 20, 19, NA, 17, 16, NA, NA, NA }, + { NA, NA, NA, NA, NA, 18, NA, NA, NA, NA, NA } +}; + RGBController_CorsairCommanderCore::RGBController_CorsairCommanderCore(CorsairCommanderCoreController* controller_ptr) { controller = controller_ptr; + name = controller->GetNameString(); vendor = "Corsair"; - description = "Corsair Commander Core"; + description = "Corsair Commander Core Device"; version = controller->GetFirmwareString(); type = DEVICE_TYPE_COOLER; location = controller->GetLocationString(); - SetupZones(); mode Direct; @@ -67,16 +84,37 @@ void RGBController_CorsairCommanderCore::SetupZones() first_run = 1; } + std::vector led_count = controller->GetLedCounts(); zones.resize(7); - zones[0].name = "Pump"; - zones[0].type = ZONE_TYPE_MATRIX; - zones[0].leds_min = 29; - zones[0].leds_max = 29; - zones[0].leds_count = 29; - zones[0].matrix_map = new matrix_map_type; - zones[0].matrix_map->height = 7; - zones[0].matrix_map->width = 7; - zones[0].matrix_map->map = (unsigned int *)&matrix_map; + if(controller->GetPidInt() == CORSAIR_COMMANDER_CORE_XT_PID) + { + zones[0].name = "External RGB Port"; + zones[0].type = ZONE_TYPE_LINEAR; + zones[0].leds_min = zones[0].leds_min; + zones[0].leds_max = 204; + zones[0].leds_count = zones[0].leds_count; + } + else + { + zones[0].name = "Pump"; + zones[0].type = ZONE_TYPE_MATRIX; + zones[0].leds_min = led_count.at(0); + zones[0].leds_max = led_count.at(0); + zones[0].leds_count = led_count.at(0); + zones[0].matrix_map = new matrix_map_type; + if(led_count.at(0) == 24) + { + zones[0].matrix_map->height = 11; + zones[0].matrix_map->width = 11; + zones[0].matrix_map->map = (unsigned int *)&matrix_map24; + } + else + { + zones[0].matrix_map->height = 7; + zones[0].matrix_map->width = 7; + zones[0].matrix_map->map = (unsigned int *)&matrix_map29; + } + } for(unsigned int i = 1; i < (CORSAIR_COMMANDER_CORE_NUM_CHANNELS + 1); i++) { @@ -87,7 +125,7 @@ void RGBController_CorsairCommanderCore::SetupZones() if(first_run) { - zones[i].leds_count = 0; + zones[i].leds_count = (led_count.size() > i) ? led_count.at(i) : 0; } } @@ -96,7 +134,7 @@ void RGBController_CorsairCommanderCore::SetupZones() 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++) + 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); @@ -118,7 +156,18 @@ void RGBController_CorsairCommanderCore::ResizeZone(int zone, int new_size) if(((unsigned int)new_size >= zones[zone].leds_min) && ((unsigned int)new_size <= zones[zone].leds_max)) { zones[zone].leds_count = new_size; - + if(zone == 0 && controller->GetPidInt() == CORSAIR_COMMANDER_CORE_XT_PID) + { + if(new_size > 0) + { + controller->SetFanMode(true); + controller->SetLedAmount(new_size); + } + else + { + controller->SetFanMode(false); + } + } SetupZones(); } } diff --git a/Controllers/CorsairCommanderCoreController/RGBController_CorsairCommanderCore.h b/Controllers/CorsairCommanderCoreController/RGBController_CorsairCommanderCore.h index ef5c924d..43f434a1 100644 --- a/Controllers/CorsairCommanderCoreController/RGBController_CorsairCommanderCore.h +++ b/Controllers/CorsairCommanderCoreController/RGBController_CorsairCommanderCore.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_CorsairCapellix.h | -| | -| Generic RGB Interface for Corsair | -| Commander Core | -| | -| Jeff P. | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairCCommanderCore.h | +| | +| RGBController for Corsair Commander Core | +| | +| Jeff P. | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "CorsairCommanderCoreController.h" diff --git a/Controllers/CorsairController/CorsairDeviceGuard.cpp b/Controllers/CorsairController/CorsairDeviceGuard.cpp new file mode 100644 index 00000000..aacf36f8 --- /dev/null +++ b/Controllers/CorsairController/CorsairDeviceGuard.cpp @@ -0,0 +1,64 @@ +/*---------------------------------------------------------*\ +| CorsairDeviceGuard.cpp | +| | +| DeviceGuard for Corsair devices | +| | +| Evan Mulawski 04 Sep 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "CorsairDeviceGuard.h" + +CorsairDeviceGuard::CorsairDeviceGuard() : DeviceGuard() +{ +#ifdef _WIN32 + mutex_handle = CreateWindowsMutex(); +#endif +} + +void CorsairDeviceGuard::Acquire() +{ +#ifdef _WIN32 + while(true) + { + DWORD result = WaitForSingleObject(mutex_handle, INFINITE); + + if(result == WAIT_OBJECT_0) + { + break; + } + + if(result == WAIT_ABANDONED) + { + ReleaseMutex(mutex_handle); + } + } +#endif +} + +void CorsairDeviceGuard::Release() +{ +#ifdef _WIN32 + ReleaseMutex(mutex_handle); +#endif +} + +#ifdef _WIN32 + +HANDLE CorsairDeviceGuard::CreateWindowsMutex() +{ + SECURITY_DESCRIPTOR sd; + InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); + SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); + + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = &sd; + sa.bInheritHandle = FALSE; + + return CreateMutex(&sa, FALSE, "Global\\CorsairLinkReadWriteGuardMutex"); +} + +#endif diff --git a/Controllers/CorsairController/CorsairDeviceGuard.h b/Controllers/CorsairController/CorsairDeviceGuard.h new file mode 100644 index 00000000..9ae428d5 --- /dev/null +++ b/Controllers/CorsairController/CorsairDeviceGuard.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------*\ +| CorsairDeviceGuard.cpp | +| | +| DeviceGuard for Corsair devices | +| | +| Evan Mulawski 04 Sep 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "DeviceGuard.h" + +#ifdef _WIN32 +/*---------------------------------------------------------*\ +| Windows interferes with std::max unless NOMINMAX defined | +\*---------------------------------------------------------*/ +#define NOMINMAX +#include +#endif + +class CorsairDeviceGuard : public DeviceGuard +{ +public: + CorsairDeviceGuard(); + + void Acquire() override; + void Release() override; + +private: +#ifdef _WIN32 + HANDLE mutex_handle; + + HANDLE CreateWindowsMutex(); +#endif +}; diff --git a/Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumController.cpp b/Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumController.cpp index 223b2115..ff8a28a4 100644 --- a/Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumController.cpp +++ b/Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumController.cpp @@ -1,23 +1,26 @@ -/*------------------------------------------*\ -| CorsairDominatorPlatinumController.cpp | -| | -| Drover for Corsair Domintator Platinum | -| RGB RAM lighting controller | -| | -| Erik Gilling (konkers) 9/25/2020 | -\*------------------------------------------*/ - -#include "CorsairDominatorPlatinumController.h" +/*---------------------------------------------------------*\ +| CorsairDominatorPlatinumController.cpp | +| | +| Driver for Corsair Dominator Platinum RAM | +| | +| Erik Gilling (konkers) 25 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include +#include "CorsairDominatorPlatinumController.h" using namespace std::chrono_literals; -CorsairDominatorPlatinumController::CorsairDominatorPlatinumController(i2c_smbus_interface *bus, corsair_dev_id dev, unsigned int leds_count) +CorsairDominatorPlatinumController::CorsairDominatorPlatinumController(i2c_smbus_interface *bus, corsair_dev_id dev, unsigned int leds_count, std::string dev_name) { this->bus = bus; this->dev = dev; this->leds_count = leds_count; + this->name = dev_name; led_data[0] = 0xc; } @@ -41,6 +44,11 @@ std::string CorsairDominatorPlatinumController::GetDeviceLocation() return("I2C: " + return_string); } +std::string CorsairDominatorPlatinumController::GetDeviceName() +{ + return(name); +} + void CorsairDominatorPlatinumController::SetAllColors ( unsigned char red, diff --git a/Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumController.h b/Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumController.h index 82ee1a5c..c4d56bc7 100644 --- a/Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumController.h +++ b/Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumController.h @@ -1,28 +1,31 @@ -/*-----------------------------------------*\ -| CorsairDominatorPlatinumController.h | -| | -| Definitions and types for Corsair | -| Domintator Platinum RGB RAM lighting | -| controller | -| | -| Erik Gilling (konkers) 9/25/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairDominatorPlatinumController.h | +| | +| Driver for Corsair Dominator Platinum RAM | +| | +| Erik Gilling (konkers) 25 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" -#define CORSAIR_DOMINATOR_PLATINUM_DATA_SIZE 38 -#pragma once +#define CORSAIR_DOMINATOR_PLATINUM_DATA_SIZE 38 typedef unsigned char corsair_dev_id; class CorsairDominatorPlatinumController { public: - CorsairDominatorPlatinumController(i2c_smbus_interface *bus, corsair_dev_id dev, unsigned int leds_count); + CorsairDominatorPlatinumController(i2c_smbus_interface *bus, corsair_dev_id dev, unsigned int leds_count, std::string dev_name); ~CorsairDominatorPlatinumController(); std::string GetDeviceLocation(); + std::string GetDeviceName(); unsigned int GetLEDCount(); void SetAllColors(unsigned char red, unsigned char green, unsigned char blue); @@ -35,6 +38,7 @@ private: i2c_smbus_interface* bus; corsair_dev_id dev; unsigned int leds_count; + std::string name; static unsigned char crc8(unsigned char init, unsigned char poly, unsigned char *data, unsigned char len); }; diff --git a/Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumControllerDetect.cpp b/Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumControllerDetect.cpp index 57bf8cb2..3cc2ce30 100644 --- a/Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumControllerDetect.cpp +++ b/Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumControllerDetect.cpp @@ -1,13 +1,22 @@ +/*---------------------------------------------------------*\ +| CorsairDominatorPlatinumControllerDetect.cpp | +| | +| Detector for Corsair Dominator Platinum RAM | +| | +| Erik Gilling (konkers) 25 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "CorsairDominatorPlatinumController.h" -#include "RGBController.h" #include "RGBController_CorsairDominatorPlatinum.h" +#include "SettingsManager.h" +#include "LogManager.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include "LogManager.h" -#include -#include -#include using namespace std::chrono_literals; @@ -40,6 +49,13 @@ json corsair_dominator_models = {"name", "Corsair Vengeance RGB RS"}, {"leds", 6} } + }, + { + "CMP", + { + {"name", "Corsair Dominator Titanium"}, + {"leds", 11} + } } }; @@ -59,9 +75,9 @@ bool TestForCorsairDominatorPlatinumController(i2c_smbus_interface *bus, unsigne res = bus->i2c_smbus_read_byte_data(address, 0x43); - if(res != 0x1b) + if(!(res == 0x1A || res == 0x1B)) { - LOG_DEBUG("[%s] Failed: expected 0x1b, got %04X", CORSAIR_DOMINATOR_PLATINUM_NAME, res); + LOG_DEBUG("[%s] Failed: expected 0x1a or 0x1b, got %04X", CORSAIR_DOMINATOR_PLATINUM_NAME, res); return false; } @@ -141,9 +157,8 @@ void DetectCorsairDominatorPlatinumControllers(std::vectorname = name; ResourceManager::get()->RegisterRGBController(rgbcontroller); } diff --git a/Controllers/CorsairDominatorPlatinumController/RGBController_CorsairDominatorPlatinum.cpp b/Controllers/CorsairDominatorPlatinumController/RGBController_CorsairDominatorPlatinum.cpp index 3248465e..db79be9c 100644 --- a/Controllers/CorsairDominatorPlatinumController/RGBController_CorsairDominatorPlatinum.cpp +++ b/Controllers/CorsairDominatorPlatinumController/RGBController_CorsairDominatorPlatinum.cpp @@ -1,10 +1,13 @@ -/*-------------------------------------------------*\ -| RGBController_CorsairDominatorPlatinum.cpp | -| | -| Corsair Vengeance Pro RGB driver | -| | -| Erik Gilling (konkers) 9/25/2020 | -\*-------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairDominatorPlatinum.cpp | +| | +| RGBController for Corsair Dominator Platinum RAM | +| | +| Erik Gilling (konkers) 25 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CorsairDominatorPlatinum.h" @@ -17,12 +20,23 @@ @effects :x: @detectors DetectCorsairDominatorPlatinumControllers @comment + The Corsair Dominator controller chip can be found on several + Corsair memory sticks which have different LED counts. This can be controlled + by editing the Part Number in OpenRGB.json with values in the below table. + + | Part Number | LED Count | + | :---------: | --------: | + | CMG | 6 | + | CMH | 10 | + | CMN | 10 | + | CMT | 12 | \*-------------------------------------------------------------------*/ RGBController_CorsairDominatorPlatinum::RGBController_CorsairDominatorPlatinum(CorsairDominatorPlatinumController* controller_ptr) { controller = controller_ptr; + name = controller->GetDeviceName(); vendor = "Corsair"; type = DEVICE_TYPE_DRAM; description = "Corsair RAM RGB Device"; @@ -85,7 +99,7 @@ void RGBController_CorsairDominatorPlatinum::ResizeZone(int /*zone*/, int /*new_ void RGBController_CorsairDominatorPlatinum::DeviceUpdateLEDs() { - for(std::size_t led = 0; led < colors.size(); led++) + for(unsigned int led = 0; led < (unsigned int)colors.size(); led++) { RGBColor color = colors[led]; unsigned char red = RGBGetRValue(color); diff --git a/Controllers/CorsairDominatorPlatinumController/RGBController_CorsairDominatorPlatinum.h b/Controllers/CorsairDominatorPlatinumController/RGBController_CorsairDominatorPlatinum.h index 2d388598..5e2e7170 100644 --- a/Controllers/CorsairDominatorPlatinumController/RGBController_CorsairDominatorPlatinum.h +++ b/Controllers/CorsairDominatorPlatinumController/RGBController_CorsairDominatorPlatinum.h @@ -1,10 +1,13 @@ -/*--------------------------------------------*\ -| RGBController_CorsairDominatorPlatinum.h | -| | -| Corsair Dominator Platinum RGB driver | -| | -| Erik Gilling (konkers) 9/25/2020 | -\*--------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairDominatorPlatinum.h | +| | +| RGBController for Corsair Dominator Platinum RAM | +| | +| Erik Gilling (konkers) 25 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/CorsairHydro2Controller/CorsairHydro2Controller.cpp b/Controllers/CorsairHydro2Controller/CorsairHydro2Controller.cpp index f1d7b1fe..fe9310d1 100644 --- a/Controllers/CorsairHydro2Controller/CorsairHydro2Controller.cpp +++ b/Controllers/CorsairHydro2Controller/CorsairHydro2Controller.cpp @@ -1,15 +1,18 @@ -/*-----------------------------------------*\ -| CorsairHydro2Controller.cpp | -| | -| Controller for Corsair H100i v2 | -| | -| Tim Demand (tim.dmd) 1/10/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairHydro2Controller.cpp | +| | +| Driver for Corsair H100i v2 | +| | +| Tim Demand (tim.dmd) 10 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "CorsairHydro2Controller.h" #include #include #include +#include "CorsairHydro2Controller.h" CorsairHydro2Controller::CorsairHydro2Controller(libusb_device_handle* dev_handle) { diff --git a/Controllers/CorsairHydro2Controller/CorsairHydro2Controller.h b/Controllers/CorsairHydro2Controller/CorsairHydro2Controller.h index 7542a546..7b126298 100644 --- a/Controllers/CorsairHydro2Controller/CorsairHydro2Controller.h +++ b/Controllers/CorsairHydro2Controller/CorsairHydro2Controller.h @@ -1,21 +1,20 @@ -/*-----------------------------------------*\ -| CorsairHydro2Controller.h | -| | -| Controller for Corsair H100i v2 | -| | -| Tim Demand (tim.dmd) 1/10/2023 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#ifdef __FreeBSD__ -#include -#else -#include -#endif +/*---------------------------------------------------------*\ +| CorsairHydro2Controller.h | +| | +| Driver for Corsair H100i v2 | +| | +| Tim Demand (tim.dmd) 10 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + class CorsairHydro2Controller { public: diff --git a/Controllers/CorsairHydro2Controller/CorsairHydro2ControllerDetect.cpp b/Controllers/CorsairHydro2Controller/CorsairHydro2ControllerDetect.cpp index 62018d67..ed970b67 100644 --- a/Controllers/CorsairHydro2Controller/CorsairHydro2ControllerDetect.cpp +++ b/Controllers/CorsairHydro2Controller/CorsairHydro2ControllerDetect.cpp @@ -1,21 +1,18 @@ -/*-----------------------------------------*\ -| CorsairHydro2ControllerDetect.cpp | -| | -| Detector for Corsair H100i v2 | -| | -| Tim Demand (tim.dmd) 1/10/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairHydro2ControllerDetect.cpp | +| | +| Detector for Corsair H100i v2 | +| | +| Tim Demand (tim.dmd) 10 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include "Detector.h" #include "CorsairHydro2Controller.h" -#include "RGBController.h" #include "RGBController_CorsairHydro2.h" -#include -#ifdef __FreeBSD__ -#include -#else -#include -#endif #define CORSAIR_VID 0x1B1C #define H100I_V2_PID 0x0C09 @@ -37,7 +34,6 @@ void DetectCorsairHydro2Controllers() CorsairHydro2Controller* controller = new CorsairHydro2Controller(dev); RGBController_CorsairHydro2* rgb_controller = new RGBController_CorsairHydro2(controller); - rgb_controller->name = "Corsair H100i v2"; ResourceManager::get()->RegisterRGBController(rgb_controller); } diff --git a/Controllers/CorsairHydro2Controller/RGBController_CorsairHydro2.cpp b/Controllers/CorsairHydro2Controller/RGBController_CorsairHydro2.cpp index 86240afb..36bdd317 100644 --- a/Controllers/CorsairHydro2Controller/RGBController_CorsairHydro2.cpp +++ b/Controllers/CorsairHydro2Controller/RGBController_CorsairHydro2.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_CorsairHydro2.cpp | -| | -| RGB Controller for Corsair H100i v2 | -| | -| Tim Demand (tim.dmd) 1/10/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairHydro2.cpp | +| | +| RGBController for Corsair H100i v2 | +| | +| Tim Demand (tim.dmd) 10 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CorsairHydro2.h" @@ -21,8 +24,9 @@ RGBController_CorsairHydro2::RGBController_CorsairHydro2(CorsairHydro2Controller* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; + name = "Corsair H100i v2"; vendor = "Corsair"; description = "Corsair H100i v2"; type = DEVICE_TYPE_COOLER; diff --git a/Controllers/CorsairHydro2Controller/RGBController_CorsairHydro2.h b/Controllers/CorsairHydro2Controller/RGBController_CorsairHydro2.h index 5ac8a322..80351b63 100644 --- a/Controllers/CorsairHydro2Controller/RGBController_CorsairHydro2.h +++ b/Controllers/CorsairHydro2Controller/RGBController_CorsairHydro2.h @@ -1,12 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_CorsairHydro2.h | -| | -| RGB Controller for Corsair H100i v2 | -| | -| Tim Demand (tim.dmd) 1/10/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairHydro2.h | +| | +| RGBController for Corsair H100i v2 | +| | +| Tim Demand (tim.dmd) 10 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "CorsairHydro2Controller.h" diff --git a/Controllers/CorsairHydroController/CorsairHydroController.cpp b/Controllers/CorsairHydroController/CorsairHydroController.cpp index 638edd1f..0bac0521 100644 --- a/Controllers/CorsairHydroController/CorsairHydroController.cpp +++ b/Controllers/CorsairHydroController/CorsairHydroController.cpp @@ -1,18 +1,23 @@ /*---------------------------------------------------------*\ -| Processing Code for Corsair Hydro Series | +| CorsairHydroController.cpp | | | -| Adam Honse (calcprogrammer1@gmail.com), 8/17/2020 | +| Driver for Corsair Hydro Series coolers | +| | +| Adam Honse (calcprogrammer1@gmail.com) 17 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "CorsairHydroController.h" - #include #include #include +#include "CorsairHydroController.h" -CorsairHydroController::CorsairHydroController(libusb_device_handle* dev_handle) +CorsairHydroController::CorsairHydroController(libusb_device_handle* dev_handle, std::string dev_name) { dev = dev_handle; + name = dev_name; /*-----------------------------------------------------*\ | Fill in location string with USB ID | @@ -47,6 +52,11 @@ std::string CorsairHydroController::GetLocation() return("USB: " + location); } +std::string CorsairHydroController::GetNameString() +{ + return(name); +} + void CorsairHydroController::SetBlink ( std::vector & colors, @@ -68,7 +78,7 @@ void CorsairHydroController::SetFixed /*-----------------------------------------------------*\ | Fixed mode seems to just be shift mode with the same | | value for both colors | - \*-----------------------------------------------------*/ + \*-----------------------------------------------------*/ SendApplyShift(); } @@ -208,7 +218,7 @@ void CorsairHydroController::SendColors | Set up Send Colors packet | \*-----------------------------------------------------*/ usb_buf[0] = 0x56; - usb_buf[1] = colors.size(); + usb_buf[1] = (unsigned char)colors.size(); /*---------------------------------------------------------*\ | Fill in colors from vector | @@ -226,7 +236,7 @@ void CorsairHydroController::SendColors \*---------------------------------------------------------*/ if((color_idx == 0) && colors.size() == 1) { - usb_buf[1] = colors.size() + 1; + usb_buf[1] = (unsigned char)colors.size() + 1; usb_buf[(color_idx * 3) + 5] = RGBGetRValue(colors[color_idx]); usb_buf[(color_idx * 3) + 6] = RGBGetGValue(colors[color_idx]); usb_buf[(color_idx * 3) + 7] = RGBGetBValue(colors[color_idx]); diff --git a/Controllers/CorsairHydroController/CorsairHydroController.h b/Controllers/CorsairHydroController/CorsairHydroController.h index a6e9a98b..e9ac61aa 100644 --- a/Controllers/CorsairHydroController/CorsairHydroController.h +++ b/Controllers/CorsairHydroController/CorsairHydroController.h @@ -1,19 +1,20 @@ /*---------------------------------------------------------*\ -| Definitions for Corsair Hydro Series | +| CorsairHydroController.h | | | -| Adam Honse (calcprogrammer1@gmail.com), 8/17/2020 | +| Driver for Corsair Hydro Series coolers | +| | +| Adam Honse (calcprogrammer1@gmail.com) 17 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "RGBController.h" -#include -#ifdef __FreeBSD__ -#include -#else -#include -#endif - #pragma once +#include +#include +#include "RGBController.h" + enum { CORSAIR_HYDRO_CMD_READ_PUMP_SPEED = 0x31, @@ -34,7 +35,7 @@ enum class CorsairHydroController { public: - CorsairHydroController(libusb_device_handle* dev_handle); + CorsairHydroController(libusb_device_handle* dev_handle, std::string dev_name); ~CorsairHydroController(); unsigned char GetFanPercent(unsigned char fan_channel); @@ -42,8 +43,8 @@ public: unsigned short GetFanRPM(unsigned char fan_channel); std::string GetFirmwareString(); - std::string GetLocation(); + std::string GetNameString(); void SetBlink ( @@ -66,12 +67,13 @@ public: ( std::vector & colors, unsigned char speed - ); + ); private: libusb_device_handle* dev; std::string firmware_version; std::string location; + std::string name; void SendApplyBlink(); void SendApplyPulse(); diff --git a/Controllers/CorsairHydroController/CorsairHydroControllerDetect.cpp b/Controllers/CorsairHydroController/CorsairHydroControllerDetect.cpp index 9b8dd62d..3f19c329 100644 --- a/Controllers/CorsairHydroController/CorsairHydroControllerDetect.cpp +++ b/Controllers/CorsairHydroController/CorsairHydroControllerDetect.cpp @@ -1,13 +1,18 @@ +/*---------------------------------------------------------*\ +| CorsairHydroControllerDetect.cpp | +| | +| Detector for Corsair Hydro Series coolers | +| | +| Adam Honse (calcprogrammer1@gmail.com) 17 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "CorsairHydroController.h" -#include "RGBController.h" #include "RGBController_CorsairHydro.h" -#include -#ifdef __FreeBSD__ -#include -#else -#include -#endif /*-----------------------------------------------------*\ | Corsair vendor ID | @@ -67,9 +72,8 @@ void DetectCorsairHydroControllers() libusb_detach_kernel_driver(dev, 0); libusb_claim_interface(dev, 0); - CorsairHydroController* controller = new CorsairHydroController(dev); + CorsairHydroController* controller = new CorsairHydroController(dev, device_list[device_idx].name); RGBController_CorsairHydro* rgb_controller = new RGBController_CorsairHydro(controller); - rgb_controller->name = device_list[device_idx].name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -80,7 +84,7 @@ REGISTER_DETECTOR("Corsair Hydro Series", DetectCorsairHydroControllers); /*---------------------------------------------------------------------------------------------------------*\ | Entries for dynamic UDEV rules | | | -| DUMMY_DEVICE_DETECTOR("Corsair Hydro Series", DetectCorsairHydroControllers, 0x1B1C, x0C12 ) | -| DUMMY_DEVICE_DETECTOR("Corsair Hydro Series", DetectCorsairHydroControllers, 0x1B1C, x0C13 ) | -| DUMMY_DEVICE_DETECTOR("Corsair Hydro Series", DetectCorsairHydroControllers, 0x1B1C, x0C15 ) | +| DUMMY_DEVICE_DETECTOR("Corsair Hydro Series", DetectCorsairHydroControllers, 0x1B1C, 0x0C12 ) | +| DUMMY_DEVICE_DETECTOR("Corsair Hydro Series", DetectCorsairHydroControllers, 0x1B1C, 0x0C13 ) | +| DUMMY_DEVICE_DETECTOR("Corsair Hydro Series", DetectCorsairHydroControllers, 0x1B1C, 0x0C15 ) | \*---------------------------------------------------------------------------------------------------------*/ diff --git a/Controllers/CorsairHydroController/RGBController_CorsairHydro.cpp b/Controllers/CorsairHydroController/RGBController_CorsairHydro.cpp index b68d0b75..9dbadf2f 100644 --- a/Controllers/CorsairHydroController/RGBController_CorsairHydro.cpp +++ b/Controllers/CorsairHydroController/RGBController_CorsairHydro.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_CorsairHydro.cpp | -| | -| Generic RGB Interface for Corsair | -| Hydro Series | -| | -| Adam Honse (CalcProgrammer1) 8/18/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairHydro.cpp | +| | +| RGBController for Corsair Hydro Series coolers | +| | +| Adam Honse (calcprogrammer1@gmail.com) 18 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CorsairHydro.h" @@ -24,6 +26,7 @@ RGBController_CorsairHydro::RGBController_CorsairHydro(CorsairHydroController* c { controller = controller_ptr; + name = controller->GetNameString(); vendor = "Corsair"; description = "Corsair Hydro Series Device"; version = controller->GetFirmwareString(); diff --git a/Controllers/CorsairHydroController/RGBController_CorsairHydro.h b/Controllers/CorsairHydroController/RGBController_CorsairHydro.h index 3551f30b..4b405c26 100644 --- a/Controllers/CorsairHydroController/RGBController_CorsairHydro.h +++ b/Controllers/CorsairHydroController/RGBController_CorsairHydro.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_CorsairHydro.h | -| | -| Generic RGB Interface for Corsair | -| Hydro Series | -| | -| Adam Honse (CalcProgrammer1) 8/17/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairHydro.h | +| | +| RGBController for Corsair Hydro Series coolers | +| | +| Adam Honse (calcprogrammer1@gmail.com) 17 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "CorsairHydroController.h" diff --git a/Controllers/CorsairHydroPlatinumController/CorsairHydroPlatinumController.cpp b/Controllers/CorsairHydroPlatinumController/CorsairHydroPlatinumController.cpp index 3d2af818..8f11aee2 100644 --- a/Controllers/CorsairHydroPlatinumController/CorsairHydroPlatinumController.cpp +++ b/Controllers/CorsairHydroPlatinumController/CorsairHydroPlatinumController.cpp @@ -1,14 +1,18 @@ -/*-------------------------------------------------------------------*\ -| CorsairHydroPlatinumController.cpp | -| | -| Driver for Corsair Hydro Platinum AIO Coolers | -| | -| Kasper 28th March 2021 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairHydroPlatinumController.cpp | +| | +| Driver for Corsair Hydro Platinum coolers | +| | +| Kasper 28 Mar 2021 | +| Nikola Jurkovic (jurkovic.nikola) 13 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "CorsairHydroPlatinumController.h" #include +#include "CorsairHydroPlatinumController.h" +#include "CorsairDeviceGuard.h" static const uint8_t CRC_TABLE[256] = { @@ -48,44 +52,95 @@ static const uint8_t CRC_TABLE[256] = static const uint8_t MAGIC_1[61] = { - 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, - 0x7f, 0x7f, 0x7f, 0xff, 0x00, 0xff, 0xff, 0xff, - 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, - 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, - 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff + 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, + 0x7F, 0x7F, 0x7F, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, + 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static const uint8_t MAGIC_2[61] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; static const uint8_t MAGIC_3[61] = { - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, + 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, + 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff + 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -CorsairHydroPlatinumController::CorsairHydroPlatinumController(hid_device* dev_handle, const char* path) +static const uint8_t HARDWARE_MAGIC_1[61] = { - dev = dev_handle; - location = path; + 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, + 0x7F, 0x7F, 0x7F, 0x7F, 0x09, 0x20, 0x07, 0x00, + 0x0B, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, + 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static const uint8_t HARDWARE_MAGIC_2[61] = +{ + 0x0A, 0x01, 0x04, 0x07, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0A, 0x0B, 0x00, 0x01, 0x02, 0x03, 0x04, + 0x01, 0x0A, 0x07, 0x04, 0x0B, 0x0A, 0x09, 0x08, + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x01, 0x0A, 0x07, 0x04, 0x01, 0x0A, 0x09, 0x08, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static const uint8_t HARDWARE_MAGIC_3[61] = +{ + 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +static const uint8_t HARDWARE_MAGIC_4[61] = +{ + 0x00, 0x00, 0xFF, 0x00, 0x4A, 0xFF, 0x00, 0x94, + 0xFF, 0x00, 0xDF, 0xFF, 0x00, 0xFF, 0xAA, 0x00, + 0xFF, 0x15, 0x7F, 0x7F, 0x00, 0xFA, 0x00, 0x06, + 0xDB, 0x00, 0x32, 0xD7, 0x00, 0x58, 0xF6, 0x00, + 0x76, 0x94, 0x00, 0xB4, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +CorsairHydroPlatinumController::CorsairHydroPlatinumController(hid_device* dev_handle, const char* path, bool dev_rgb_fan, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + have_rgb_fan = dev_rgb_fan; + guard_manager_ptr = new DeviceGuardManager(new CorsairDeviceGuard()); SendMagic(MAGIC_1, CORSAIR_HYDRO_PLATINUM_MAGIC_1); SendMagic(MAGIC_2, CORSAIR_HYDRO_PLATINUM_MAGIC_2); @@ -94,36 +149,55 @@ CorsairHydroPlatinumController::CorsairHydroPlatinumController(hid_device* dev_h CorsairHydroPlatinumController::~CorsairHydroPlatinumController() { + /*-----------------------------------------------------*\ + | Hardware lights, 2,3,4,1 | + \*-----------------------------------------------------*/ + SendMagic(HARDWARE_MAGIC_2, CORSAIR_HYDRO_PLATINUM_MAGIC_2); + SendMagic(HARDWARE_MAGIC_3, CORSAIR_HYDRO_PLATINUM_MAGIC_3); + SendMagic(HARDWARE_MAGIC_4, CORSAIR_HYDRO_PLATINUM_SET_LIGHTING_1); + SendMagic(HARDWARE_MAGIC_1, CORSAIR_HYDRO_PLATINUM_MAGIC_1); + hid_close(dev); + delete guard_manager_ptr; } std::string CorsairHydroPlatinumController::GetLocation() { - return location; + return("HID: " + location); } std::string CorsairHydroPlatinumController::GetFirmwareString() { - return firmware_version; + return(firmware_version); +} + +std::string CorsairHydroPlatinumController::GetName() +{ + return(name); } void CorsairHydroPlatinumController::SetupColors(std::vector colors) { - unsigned int end_led = colors.size() >= 20 ? 20 : colors.size(); + unsigned int end_led = (colors.size() >= 20) ? 20 : (unsigned int)colors.size(); SendColors(colors, 0, end_led, CORSAIR_HYDRO_PLATINUM_SET_LIGHTING_1); if(colors.size() > 20) { - end_led = colors.size() >= 40 ? 40 : colors.size(); + end_led = (colors.size() >= 40) ? 40 : (unsigned int)colors.size(); SendColors(colors, 20, end_led, CORSAIR_HYDRO_PLATINUM_SET_LIGHTING_2); } if(colors.size() > 40) { - end_led = colors.size() >= 48 ? 48 : colors.size(); + end_led = (colors.size() >= 48) ? 48 : (unsigned int)colors.size(); SendColors(colors, 40, end_led, CORSAIR_HYDRO_PLATINUM_SET_LIGHTING_3); } } +bool CorsairHydroPlatinumController::HaveRgbFan() +{ + return(have_rgb_fan); +} + void CorsairHydroPlatinumController::SendMagic(const uint8_t* magic, unsigned int command) { unsigned char usb_buf[CORSAIR_HYDRO_PLATINUM_PACKET_SIZE]; @@ -152,8 +226,18 @@ void CorsairHydroPlatinumController::SendMagic(const uint8_t* magic, unsigned in /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, CORSAIR_HYDRO_PLATINUM_PACKET_SIZE); - hid_read(dev, usb_buf, CORSAIR_HYDRO_PLATINUM_PACKET_SIZE); + /*---------------------------------------------------------*\ + | HID I/O start | + \*---------------------------------------------------------*/ + { + DeviceGuardLock _ = guard_manager_ptr->AwaitExclusiveAccess(); + + hid_write(dev, usb_buf, CORSAIR_HYDRO_PLATINUM_PACKET_SIZE); + hid_read(dev, usb_buf, CORSAIR_HYDRO_PLATINUM_PACKET_SIZE); + } + /*---------------------------------------------------------*\ + | HID I/O end (lock released) | + \*---------------------------------------------------------*/ if(firmware_version.empty()) { @@ -204,8 +288,17 @@ void CorsairHydroPlatinumController::SendColors(std::vector colors, un checksum_array.insert(checksum_array.begin(), std::begin(usb_buf) + 2, std::end(usb_buf) - 1); usb_buf[64] = ComputePEC(static_cast(checksum_array.data()), 62); - hid_write(dev, usb_buf, CORSAIR_HYDRO_PLATINUM_PACKET_SIZE); - hid_read(dev, usb_buf, CORSAIR_HYDRO_PLATINUM_PACKET_SIZE); + /*---------------------------------------------------------*\ + | HID I/O start | + \*---------------------------------------------------------*/ + { + DeviceGuardLock _ = guard_manager_ptr->AwaitExclusiveAccess(); + + hid_write(dev, usb_buf, CORSAIR_HYDRO_PLATINUM_PACKET_SIZE); + } + /*---------------------------------------------------------*\ + | HID I/O end (lock released) | + \*---------------------------------------------------------*/ /*-----------------------------------------------------*\ | This delay prevents the AIO from soft-locking when | @@ -235,11 +328,11 @@ uint8_t CorsairHydroPlatinumController::ComputePEC(const void * data, size_t siz uint8_t * pos = (uint8_t *) data; uint8_t * end = pos + size; - while (pos < end) + while(pos < end) { val = CRC_TABLE[val ^ *pos]; pos++; } return val; -} \ No newline at end of file +} diff --git a/Controllers/CorsairHydroPlatinumController/CorsairHydroPlatinumController.h b/Controllers/CorsairHydroPlatinumController/CorsairHydroPlatinumController.h index 094003fc..e730ac75 100644 --- a/Controllers/CorsairHydroPlatinumController/CorsairHydroPlatinumController.h +++ b/Controllers/CorsairHydroPlatinumController/CorsairHydroPlatinumController.h @@ -1,18 +1,22 @@ -/*-------------------------------------------------------------------*\ -| CorsairHydroPlatinumController.h | -| | -| Driver for Corsair Hydro Platinum AIO Coolers | -| | -| Kasper 28th March 2021 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairHydroPlatinumController.h | +| | +| Driver for Corsair Hydro Platinum coolers | +| | +| Kasper 28 Mar 2021 | +| Nikola Jurkovic (jurkovic.nikola) 13 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include "RGBController.h" -#include #include -#include +#include +#include +#include "RGBController.h" +#include "DeviceGuardManager.h" #define CORSAIR_HYDRO_PLATINUM_PACKET_SIZE 65 #define CORSAIR_HYDRO_PLATINUM_PACKET_DELAY 5 @@ -31,19 +35,23 @@ enum class CorsairHydroPlatinumController { public: - CorsairHydroPlatinumController(hid_device* dev_handle, const char* path); + CorsairHydroPlatinumController(hid_device* dev_handle, const char* path, bool dev_rgb_fan, std::string dev_name); ~CorsairHydroPlatinumController(); std::string GetLocation(); std::string GetFirmwareString(); + std::string GetName(); void SetupColors(std::vector colors); + bool HaveRgbFan(); private: - hid_device* dev; - std::string location; - std::string firmware_version; - - std::atomic sequence_number; + hid_device* dev; + std::string location; + std::string firmware_version; + std::string name; + std::atomic sequence_number; + DeviceGuardManager* guard_manager_ptr; + bool have_rgb_fan = true; void SendMagic(const uint8_t* magic, unsigned int command); void SendColors(std::vector colors, unsigned int start, unsigned int end, unsigned int command); diff --git a/Controllers/CorsairHydroPlatinumController/CorsairHydroPlatinumControllerDetect.cpp b/Controllers/CorsairHydroPlatinumController/CorsairHydroPlatinumControllerDetect.cpp index 58a62212..926a4ef2 100644 --- a/Controllers/CorsairHydroPlatinumController/CorsairHydroPlatinumControllerDetect.cpp +++ b/Controllers/CorsairHydroPlatinumController/CorsairHydroPlatinumControllerDetect.cpp @@ -1,53 +1,84 @@ -/*-------------------------------------------------------------------*\ -| CorsairHydroPlatinumControllerDetect.cpp | -| | -| Driver for Corsair Hydro Platinum AIO Coolers | -| | -| Kasper 28th March 2021 | -| | -\*-------------------------------------------------------------------*/ - -#include "Detector.h" -#include "CorsairHydroPlatinumController.h" -#include "RGBController.h" -#include "RGBController_CorsairHydroPlatinum.h" -#include - -/*-----------------------------------------------------*\ -| Corsair vendor ID | -\*-----------------------------------------------------*/ -#define CORSAIR_VID 0x1B1C - -/*-----------------------------------------------------*\ -| Product IDs | -\*-----------------------------------------------------*/ -#define CORSAIR_HYDRO_H100I_PLATINUM_PID 0x0C18 -#define CORSAIR_HYDRO_H100I_PLATINUM_SE_PID 0x0C19 -#define CORSAIR_HYDRO_H115I_PLATINUM_PID 0x0C17 -#define CORSAIR_HYDRO_H60I_PRO_XT_PID 0x0C29 -#define CORSAIR_HYDRO_H100I_PRO_XT_PID 0x0C20 -#define CORSAIR_HYDRO_H100I_PRO_XT_V2_PID 0x0C2D -#define CORSAIR_HYDRO_H115I_PRO_XT_PID 0x0C21 -#define CORSAIR_HYDRO_H150I_PRO_XT_PID 0x0C22 - -void DetectCorsairHydroPlatinumControllers(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - - if(dev) - { - CorsairHydroPlatinumController* controller = new CorsairHydroPlatinumController(dev, info->path); - RGBController_CorsairHydroPlatinum* rgb_controller = new RGBController_CorsairHydroPlatinum(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -REGISTER_HID_DETECTOR("Corsair Hydro H100i Platinum", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H100I_PLATINUM_PID ); -REGISTER_HID_DETECTOR("Corsair Hydro H100i Platinum SE", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H100I_PLATINUM_SE_PID ); -REGISTER_HID_DETECTOR("Corsair Hydro H115i Platinum", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H115I_PLATINUM_PID ); -REGISTER_HID_DETECTOR("Corsair Hydro H60i Pro XT", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H60I_PRO_XT_PID ); -REGISTER_HID_DETECTOR("Corsair Hydro H100i Pro XT", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H100I_PRO_XT_PID ); -REGISTER_HID_DETECTOR("Corsair Hydro H100i Pro XT v2", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H100I_PRO_XT_V2_PID ); -REGISTER_HID_DETECTOR("Corsair Hydro H115i Pro XT", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H115I_PRO_XT_PID ); -REGISTER_HID_DETECTOR("Corsair Hydro H150i Pro XT", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H150I_PRO_XT_PID ); +/*---------------------------------------------------------*\ +| CorsairHydroPlatinumControllerDetect.cpp | +| | +| Detector for Corsair Hydro Platinum coolers | +| | +| Kasper 28 Mar 2021 | +| Nikola Jurkovic (jurkovic.nikola) 13 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "CorsairHydroPlatinumController.h" +#include "RGBController_CorsairHydroPlatinum.h" + +/*-----------------------------------------------------*\ +| Corsair vendor ID | +\*-----------------------------------------------------*/ +#define CORSAIR_VID 0x1B1C + +/*-----------------------------------------------------*\ +| Product IDs | +\*-----------------------------------------------------*/ +#define CORSAIR_HYDRO_H100I_PLATINUM_PID 0x0C18 +#define CORSAIR_HYDRO_H100I_PLATINUM_SE_PID 0x0C19 +#define CORSAIR_HYDRO_H115I_PLATINUM_PID 0x0C17 +#define CORSAIR_HYDRO_H60I_PRO_XT_PID 0x0C29 +#define CORSAIR_HYDRO_H100I_PRO_XT_PID 0x0C20 +#define CORSAIR_HYDRO_H100I_PRO_XT_V2_PID 0x0C2D +#define CORSAIR_HYDRO_H115I_PRO_XT_PID 0x0C21 +#define CORSAIR_HYDRO_H150I_PRO_XT_PID 0x0C22 +#define CORSAIR_HYDRO_H100I_ELITE_RGB_PID 0x0C35 +#define CORSAIR_HYDRO_H115I_ELITE_RGB_PID 0x0C36 +#define CORSAIR_HYDRO_H150I_ELITE_RGB_PID 0x0C37 +#define CORSAIR_HYDRO_H100I_ELITE_RGB_PID_WHITE 0x0C40 +#define CORSAIR_HYDRO_H150I_ELITE_RGB_PID_WHITE 0x0C41 + +void DetectCorsairHydroPlatinumControllers(hid_device_info* info, const std::string& name) +{ + uint16_t no_rgb_fan_models[] = + { + CORSAIR_HYDRO_H100I_ELITE_RGB_PID, + CORSAIR_HYDRO_H115I_ELITE_RGB_PID, + CORSAIR_HYDRO_H150I_ELITE_RGB_PID, + CORSAIR_HYDRO_H100I_ELITE_RGB_PID_WHITE, + CORSAIR_HYDRO_H150I_ELITE_RGB_PID_WHITE + }; + + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + bool dev_rgb_fan = true; + for(uint16_t pid : no_rgb_fan_models) + { + if(info->product_id == pid) + { + dev_rgb_fan = false; + break; + } + } + + CorsairHydroPlatinumController* controller = new CorsairHydroPlatinumController(dev, info->path, dev_rgb_fan, name); + RGBController_CorsairHydroPlatinum* rgb_controller = new RGBController_CorsairHydroPlatinum(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR("Corsair Hydro H100i Platinum", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H100I_PLATINUM_PID ); +REGISTER_HID_DETECTOR("Corsair Hydro H100i Platinum SE", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H100I_PLATINUM_SE_PID ); +REGISTER_HID_DETECTOR("Corsair Hydro H115i Platinum", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H115I_PLATINUM_PID ); +REGISTER_HID_DETECTOR("Corsair Hydro H60i Pro XT", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H60I_PRO_XT_PID ); +REGISTER_HID_DETECTOR("Corsair Hydro H100i Pro XT", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H100I_PRO_XT_PID ); +REGISTER_HID_DETECTOR("Corsair Hydro H100i Pro XT v2", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H100I_PRO_XT_V2_PID ); +REGISTER_HID_DETECTOR("Corsair Hydro H115i Pro XT", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H115I_PRO_XT_PID ); +REGISTER_HID_DETECTOR("Corsair Hydro H150i Pro XT", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H150I_PRO_XT_PID ); +REGISTER_HID_DETECTOR("Corsair Hydro H100i Elite", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H100I_ELITE_RGB_PID ); +REGISTER_HID_DETECTOR("Corsair Hydro H115i Elite", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H115I_ELITE_RGB_PID ); +REGISTER_HID_DETECTOR("Corsair Hydro H150i Elite", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H150I_ELITE_RGB_PID ); +REGISTER_HID_DETECTOR("Corsair Hydro H100i Elite White", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H100I_ELITE_RGB_PID_WHITE ); +REGISTER_HID_DETECTOR("Corsair Hydro H150i Elite White", DetectCorsairHydroPlatinumControllers, CORSAIR_VID, CORSAIR_HYDRO_H150I_ELITE_RGB_PID_WHITE ); diff --git a/Controllers/CorsairHydroPlatinumController/RGBController_CorsairHydroPlatinum.cpp b/Controllers/CorsairHydroPlatinumController/RGBController_CorsairHydroPlatinum.cpp index ac9ba815..295b77f7 100644 --- a/Controllers/CorsairHydroPlatinumController/RGBController_CorsairHydroPlatinum.cpp +++ b/Controllers/CorsairHydroPlatinumController/RGBController_CorsairHydroPlatinum.cpp @@ -1,133 +1,147 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CorsairHydroPlatinum.cpp | -| | -| Driver for Corsair Hydro Platinum AIO Coolers | -| | -| Kasper 28th March 2021 | -| | -\*-------------------------------------------------------------------*/ - -#include "RGBController_CorsairHydroPlatinum.h" - -#define NA 0xFFFFFFFF -static unsigned int matrix_map[5][5] = -{ - { NA, 11, 12, 13, NA }, - { 10, NA, 1, NA, 14 }, - { 9, 0, NA, 2, 15 }, - { 8, NA, 3, NA, 4 }, - { NA, 7, 6, 5, NA } -}; - -/**------------------------------------------------------------------*\ - @name Corsair Hydro Platinum - @category Cooler - @type USB - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectCorsairHydroPlatinumControllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_CorsairHydroPlatinum::RGBController_CorsairHydroPlatinum(CorsairHydroPlatinumController* controller_ptr) -{ - controller = controller_ptr; - - name = "Corsair Hydro Platinum Series Device"; - vendor = "Corsair"; - description = "Corsair Hydro Platinum Series Device"; - type = DEVICE_TYPE_COOLER; - location = controller->GetLocation(); - version = controller->GetFirmwareString(); - - 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); - - Init_Controller(); - SetupZones(); -} - -void RGBController_CorsairHydroPlatinum::Init_Controller() -{ - zone cpu_block_zone; - cpu_block_zone.name = "CPU Block"; - cpu_block_zone.type = ZONE_TYPE_MATRIX; - cpu_block_zone.leds_min = 16; - cpu_block_zone.leds_max = 16; - cpu_block_zone.leds_count = 16; - cpu_block_zone.matrix_map = new matrix_map_type; - cpu_block_zone.matrix_map->height = 5; - cpu_block_zone.matrix_map->width = 5; - cpu_block_zone.matrix_map->map = (unsigned int *)&matrix_map; - zones.push_back(cpu_block_zone); - - zone fans_zone; - fans_zone.name = "Fans"; - fans_zone.type = ZONE_TYPE_LINEAR; - fans_zone.leds_min = 0; - fans_zone.leds_max = 32; - fans_zone.leds_count = 0; - fans_zone.matrix_map = NULL; - zones.push_back(fans_zone); -} - -void RGBController_CorsairHydroPlatinum::SetupZones() -{ - /*-------------------------------------------------*\ - | Clear any existing color/LED configuration | - \*-------------------------------------------------*/ - 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 + " " + std::to_string(led_idx);; - leds.push_back(new_led); - } - } - - SetupColors(); -} - -void RGBController_CorsairHydroPlatinum::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_CorsairHydroPlatinum::DeviceUpdateLEDs() -{ - controller->SetupColors(colors); -} - -void RGBController_CorsairHydroPlatinum::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_CorsairHydroPlatinum::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_CorsairHydroPlatinum::DeviceUpdateMode() -{ - -} +/*---------------------------------------------------------*\ +| RGBController_CorsairHydroPlatinum.cpp | +| | +| RGBController for Corsair Hydro Platinum coolers | +| | +| Kasper 28 Mar 2021 | +| Nikola Jurkovic (jurkovic.nikola) 13 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_CorsairHydroPlatinum.h" + +#define NA 0xFFFFFFFF +static unsigned int matrix_map[5][5] = +{ + { NA, 11, 12, 13, NA }, + { 10, NA, 1, NA, 14 }, + { 9, 0, NA, 2, 15 }, + { 8, NA, 3, NA, 4 }, + { NA, 7, 6, 5, NA } +}; + +/**------------------------------------------------------------------*\ + @name Corsair Hydro Platinum + @category Cooler + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectCorsairHydroPlatinumControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_CorsairHydroPlatinum::RGBController_CorsairHydroPlatinum(CorsairHydroPlatinumController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = "Corsair"; + description = "Corsair Hydro Platinum Series Device"; + type = DEVICE_TYPE_COOLER; + location = controller->GetLocation(); + version = controller->GetFirmwareString(); + + 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); + + Init_Controller(); + SetupZones(); +} + +RGBController_CorsairHydroPlatinum::~RGBController_CorsairHydroPlatinum() +{ + delete controller; +} + +void RGBController_CorsairHydroPlatinum::Init_Controller() +{ + zone cpu_block_zone; + cpu_block_zone.name = "CPU Block"; + cpu_block_zone.type = ZONE_TYPE_MATRIX; + cpu_block_zone.leds_min = 16; + cpu_block_zone.leds_max = 16; + cpu_block_zone.leds_count = 16; + cpu_block_zone.matrix_map = new matrix_map_type; + cpu_block_zone.matrix_map->height = 5; + cpu_block_zone.matrix_map->width = 5; + cpu_block_zone.matrix_map->map = (unsigned int *)&matrix_map; + zones.push_back(cpu_block_zone); + + /*-----------------------------------------------------*\ + | If the device is RGB fan-capable, set up fan zones. | + \*-----------------------------------------------------*/ + if(controller->HaveRgbFan()) + { + zone fans_zone; + fans_zone.name = "Fans"; + fans_zone.type = ZONE_TYPE_LINEAR; + fans_zone.leds_min = 0; + fans_zone.leds_max = 32; + fans_zone.leds_count = 0; + fans_zone.matrix_map = NULL; + zones.push_back(fans_zone); + } +} + +void RGBController_CorsairHydroPlatinum::SetupZones() +{ + /*-------------------------------------------------*\ + | Clear any existing color/LED configuration | + \*-------------------------------------------------*/ + 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 + " " + std::to_string(led_idx);; + leds.push_back(new_led); + } + } + + SetupColors(); +} + +void RGBController_CorsairHydroPlatinum::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_CorsairHydroPlatinum::DeviceUpdateLEDs() +{ + controller->SetupColors(colors); +} + +void RGBController_CorsairHydroPlatinum::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_CorsairHydroPlatinum::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_CorsairHydroPlatinum::DeviceUpdateMode() +{ + +} diff --git a/Controllers/CorsairHydroPlatinumController/RGBController_CorsairHydroPlatinum.h b/Controllers/CorsairHydroPlatinumController/RGBController_CorsairHydroPlatinum.h index 664d906f..7ae2ea53 100644 --- a/Controllers/CorsairHydroPlatinumController/RGBController_CorsairHydroPlatinum.h +++ b/Controllers/CorsairHydroPlatinumController/RGBController_CorsairHydroPlatinum.h @@ -1,33 +1,38 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CorsairHydroPlatinum.h | -| | -| Driver for Corsair Hydro Platinum AIO Coolers | -| | -| Kasper 28th March 2021 | -| | -\*-------------------------------------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "CorsairHydroPlatinumController.h" - -class RGBController_CorsairHydroPlatinum : public RGBController -{ -public: - RGBController_CorsairHydroPlatinum(CorsairHydroPlatinumController* controller_ptr); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - CorsairHydroPlatinumController* controller; - - void Init_Controller(); -}; +/*---------------------------------------------------------*\ +| RGBController_CorsairHydroPlatinum.h | +| | +| RGBController for Corsair Hydro Platinum coolers | +| | +| Kasper 28 Mar 2021 | +| Nikola Jurkovic (jurkovic.nikola) 13 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "CorsairHydroPlatinumController.h" + +class RGBController_CorsairHydroPlatinum : public RGBController +{ +public: + RGBController_CorsairHydroPlatinum(CorsairHydroPlatinumController* controller_ptr); + ~RGBController_CorsairHydroPlatinum(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + CorsairHydroPlatinumController* controller; + + void Init_Controller(); +}; diff --git a/Controllers/CorsairICueLinkController/CorsairICueLinkController.cpp b/Controllers/CorsairICueLinkController/CorsairICueLinkController.cpp new file mode 100644 index 00000000..5ea434ec --- /dev/null +++ b/Controllers/CorsairICueLinkController/CorsairICueLinkController.cpp @@ -0,0 +1,315 @@ +/*---------------------------------------------------------*\ +| CorsairICueLinkController.cpp | +| | +| Driver for Corsair iCue Link System Hub | +| | +| Aiden Vigue (acvigue) 02 Mar 2025 | +| Adam Honse 01 Aug 2025 | +| Nikola Jurkovic (jurkovic.nikola) 11 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include + +#include "CorsairDeviceGuard.h" +#include "CorsairICueLinkController.h" +#include "CorsairICueLinkProtocol.h" + +using namespace std::chrono_literals; + +CorsairICueLinkController::CorsairICueLinkController(hid_device* dev_handle, const char* path, std::string name) +{ + dev = dev_handle; + location = path; + this->name = name; + + guard_manager_ptr = new DeviceGuardManager(new CorsairDeviceGuard()); + + GetControllerFirmware(); // Firmware + SetControllerSoftwareMode(); // Software mode + GetControllerDevices(); // Get connected devices +} + +CorsairICueLinkController::~CorsairICueLinkController() +{ + SetControllerHardwareMode(); // Release device back to hardware mode + hid_close(dev); + delete guard_manager_ptr; +} + +void CorsairICueLinkController::SetControllerSoftwareMode() +{ + SendCommand(CORSAIR_ICUE_LINK_CMD_SOFTWARE_MODE, { }, { }); +} + +void CorsairICueLinkController::SetControllerHardwareMode() +{ + SendCommand(CORSAIR_ICUE_LINK_CMD_HARDWARE_MODE, { }, { }); +} + +void CorsairICueLinkController::GetControllerFirmware() +{ + /*-----------------------------------------------------*\ + | Get the firmware version | + \*-----------------------------------------------------*/ + std::vector firmware_data = SendCommand(CORSAIR_ICUE_LINK_CMD_GET_FIRMWARE, { }, { }); + version = + { + firmware_data[4], + firmware_data[5], + static_cast(firmware_data[6] | (firmware_data[7] << 8)) + }; +} + +void CorsairICueLinkController::GetControllerDevices() +{ + /*-----------------------------------------------------*\ + | Get the endpoints data | + \*-----------------------------------------------------*/ + std::vector endpoint_data = Read(CORSAIR_ICUE_LINK_MODE_GET_DEVICES, CORSAIR_ICUE_LINK_DATA_TYPE_GET_DEVICES); + unsigned char channel = endpoint_data[6]; + std::vector index = std::vector(endpoint_data.begin() + 7, endpoint_data.end()); + std::size_t pos = 0; + + /*-----------------------------------------------------*\ + | Process each channel | + \*-----------------------------------------------------*/ + for(std::size_t channel_idx = 1; channel_idx < (std::size_t)(channel + 1); channel_idx++) + { + std::size_t device_id_length = index[pos + 7]; + + if(device_id_length == 0) + { + pos += 8; + continue; + } + + /*-------------------------------------------------*\ + | Extract endpoint metadata and ID from data | + \*-------------------------------------------------*/ + std::vector endpoint_metadata = std::vector(index.begin() + pos, index.begin() + pos + 8); + std::vector endpoint_id = std::vector(index.begin() + pos + 8, index.begin() + pos + 8 + device_id_length); + + /*-------------------------------------------------*\ + | Get device information for this endpoint | + \*-------------------------------------------------*/ + unsigned char type = endpoint_metadata[2]; + unsigned char model = endpoint_metadata[3]; + const CorsairICueLinkDevice * device = FindCorsairICueLinkDevice(type, model); + + if(device == nullptr) + { + pos += 8 + device_id_length; + LOG_WARNING("[CorsairICueLinkController] Unknown device type: 0x%02x, model: 0x%02x", type, model); + continue; + } + + /*-------------------------------------------------*\ + | Dont process internal device due to duplication | + \*-------------------------------------------------*/ + if(device->internal == true) + { + pos += 8 + device_id_length; + continue; + } + + if(device->led_channels == 0) + { + LOG_WARNING("[CorsairICueLinkController] Device type %s has 0 LEDs, please open issue", device->display_name.c_str()); + pos += 8 + device_id_length; + continue; + } + + /*-------------------------------------------------*\ + | Append this endpoint's serial number to the | + | device's serial number string | + \*-------------------------------------------------*/ + std::string endpoint_id_str(endpoint_id.begin(), endpoint_id.end()); + serial += "\r\n" + endpoint_id_str; // Why do we need endpoint IDs when colors are managed via endpoint channel IDs ? + + /*-------------------------------------------------*\ + | Add endpoint device to list | + \*-------------------------------------------------*/ + endpoints.push_back(device); + + pos += 8 + device_id_length; + } +} + +std::string CorsairICueLinkController::GetFirmwareString() +{ + char buffer[20]; + std::snprintf(buffer, sizeof(buffer), "v%d.%d.%d", version[0], version[1], version[2]); + return std::string(buffer); +} + +std::string CorsairICueLinkController::GetNameString() +{ + return(name); +} + +std::string CorsairICueLinkController::GetLocationString() +{ + return("HID: " + location); +} + +std::string CorsairICueLinkController::GetSerialString() +{ + return(serial); +} + +std::vector CorsairICueLinkController::GetEndpoints() +{ + return(endpoints); +} + +void CorsairICueLinkController::UpdateLights(RGBColor* colors, std::size_t num_colors) +{ + /*-------------------------------------------------*\ + | Send color buffer, packed RGBRGBRGB | + \*-------------------------------------------------*/ + std::vector color_data; + for(std::size_t i = 0; i < num_colors; i++) + { + color_data.push_back(RGBGetRValue(colors[i])); + color_data.push_back(RGBGetGValue(colors[i])); + color_data.push_back(RGBGetBValue(colors[i])); + } + + Write(CORSAIR_ICUE_LINK_MODE_SET_COLOR, CORSAIR_ICUE_LINK_DATA_TYPE_SET_COLOR, color_data, CORSAIR_ICUE_ENDPOINT_TYPE_COLOR); +} + +std::vector> CorsairICueLinkController::ProcessMultiChunkPacket(const std::vector& data, size_t max_chunk_size) +{ + std::vector> result; + size_t offset = 0; + + while(offset < data.size()) + { + size_t end = std::min(max_chunk_size, data.size() - offset); + std::vector chunk(data.begin() + offset, data.begin() + offset + end); + result.push_back(chunk); + offset += end; + } + + return result; +} + +std::vector CorsairICueLinkController::SendCommand(std::vector command, std::vector data, std::vector waitForDataType) +{ + DeviceGuardLock lock = guard_manager_ptr->AwaitExclusiveAccess(); + + std::vector write_buf(CORSAIR_ICUE_LINK_BUFFER_WRITE_LENGTH); + write_buf[2] = 0x01; + + size_t command_size = command.size(); + size_t data_size = data.size(); + + for(size_t i = 0; i < command_size; i++) + { + write_buf[3 + i] = command[i]; + } + + for(size_t i = 0; i < data_size; i++) + { + write_buf[3 + command_size + i] = data[i]; + } + + std::vector read_buf(CORSAIR_ICUE_LINK_BUFFER_READ_LENGTH); + + hid_write(dev, write_buf.data(), CORSAIR_ICUE_LINK_BUFFER_WRITE_LENGTH); + hid_read_timeout(dev, read_buf.data(), CORSAIR_ICUE_LINK_BUFFER_READ_LENGTH, 1000); + + if(waitForDataType.size() != 2) + { + return read_buf; + } + + int tries = 0; + while((read_buf[4] != waitForDataType[0]) && tries < 5) + { + std::fill(read_buf.begin(), read_buf.end(), 0); // Clear the buffer before reading again + hid_read_timeout(dev, read_buf.data(), CORSAIR_ICUE_LINK_BUFFER_READ_LENGTH, 1000); + tries++; + } + + return read_buf; +} + +std::vector CorsairICueLinkController::Read(std::vector endpoint, std::vector data_type) +{ + /*-----------------------------------------------------*\ + | Private function to read data from an endpoint | + \*-----------------------------------------------------*/ + DeviceGuardLock lock = guard_manager_ptr->AwaitExclusiveAccess(); + + SendCommand(CORSAIR_ICUE_LINK_CMD_CLOSE_ENDPOINT, endpoint, { }); + SendCommand(CORSAIR_ICUE_LINK_CMD_OPEN_ENDPOINT, endpoint, { }); + std::vector res = SendCommand(CORSAIR_ICUE_LINK_CMD_READ, { }, data_type); + SendCommand(CORSAIR_ICUE_LINK_CMD_CLOSE_ENDPOINT, endpoint, { }); + + return res; +} + +void CorsairICueLinkController::Write(std::vector endpoint, std::vector data_type, std::vector data, CORSAIR_ICUE_ENDPOINT_TYPE endpoint_type) +{ + DeviceGuardLock lock = guard_manager_ptr->AwaitExclusiveAccess(); + + std::vector buf(data_type.size() + data.size() + CORSAIR_ICUE_LINK_WRITE_HEADER_SIZE); + + unsigned short data_len = (unsigned short)(data.size() + 2); + buf[0] = (unsigned char)(data_len & 0xFF); + buf[1] = (unsigned char)((data_len >> 8) & 0xFF); + + /*-----------------------------------------------------*\ + | Pack data into next bytes | + \*-----------------------------------------------------*/ + for(size_t i = 0; i < data_type.size(); i++) + { + buf[CORSAIR_ICUE_LINK_WRITE_HEADER_SIZE + i] = data_type[i]; + } + + /*-----------------------------------------------------*\ + | Pack data into next bytes | + \*-----------------------------------------------------*/ + for(size_t i = 0; i < data.size(); i++) + { + buf[CORSAIR_ICUE_LINK_WRITE_HEADER_SIZE + data_type.size() + i] = data[i]; + } + + SendCommand(CORSAIR_ICUE_LINK_CMD_CLOSE_ENDPOINT, endpoint, { }); + + if(endpoint_type == CORSAIR_ICUE_ENDPOINT_TYPE_DEFAULT) + { + SendCommand(CORSAIR_ICUE_LINK_CMD_OPEN_ENDPOINT, endpoint, { }); + SendCommand(CORSAIR_ICUE_LINK_CMD_WRITE, buf, { }); + SendCommand(CORSAIR_ICUE_LINK_CMD_CLOSE_ENDPOINT, endpoint, { }); + return; + } + + SendCommand(CORSAIR_ICUE_LINK_CMD_OPEN_COLOR_ENDPOINT, endpoint, { }); + std::vector> chunks = ProcessMultiChunkPacket(buf, CORSAIR_ICUE_LINK_MAXIMUM_BUFFER_PER_REQUEST); + + for(size_t i = 0; i < chunks.size(); i++) + { + if(i == 0) + { + /*-----------------------------------------------------*\ + | Initial color packet | + \*-----------------------------------------------------*/ + SendCommand(CORSAIR_ICUE_LINK_CMD_WRITE_COLOR, chunks[i], {}); + } + else + { + /*-----------------------------------------------------*\ + | Everything else follows 0x07, 0x00 | + \*-----------------------------------------------------*/ + SendCommand(CORSAIR_ICUE_LINK_CMD_WRITE_COLOR_NEXT, chunks[i], {}); + } + } + + SendCommand(CORSAIR_ICUE_LINK_CMD_CLOSE_ENDPOINT, endpoint, { }); +} diff --git a/Controllers/CorsairICueLinkController/CorsairICueLinkController.h b/Controllers/CorsairICueLinkController/CorsairICueLinkController.h new file mode 100644 index 00000000..5593a894 --- /dev/null +++ b/Controllers/CorsairICueLinkController/CorsairICueLinkController.h @@ -0,0 +1,60 @@ +/*---------------------------------------------------------*\ +| CorsairICueLinkController.h | +| | +| Driver for Corsair iCue Link System Hub | +| | +| Aiden Vigue (acvigue) 02 Mar 2025 | +| Adam Honse 01 Aug 2025 | +| Nikola Jurkovic 11 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include + +#include "CorsairICueLinkProtocol.h" +#include "DeviceGuardManager.h" +#include "RGBController.h" + +class CorsairICueLinkController +{ +public: + CorsairICueLinkController(hid_device* dev_handle, const char* path, std::string name); + ~CorsairICueLinkController(); + + std::string GetFirmwareString(); + std::string GetNameString(); + std::string GetLocationString(); + std::string GetSerialString(); + + std::vector GetEndpoints(); + + void UpdateLights(RGBColor* colors, std::size_t num_colors); + +private: + hid_device* dev; + std::string name; + std::string location; + std::string serial; + std::vector version; + + DeviceGuardManager* guard_manager_ptr; + + std::vector endpoints; + + void GetControllerFirmware(); + void GetControllerDevices(); + void SetControllerSoftwareMode(); + void SetControllerHardwareMode(); + + std::vector> ProcessMultiChunkPacket(const std::vector& data, size_t max_chunk_size); + std::vector SendCommand(std::vector command, std::vector data, std::vector waitForDataType); + + std::vector Read(std::vector endpoint, std::vector data_type); + void Write(std::vector endpoint, std::vector data_type, std::vector data, CORSAIR_ICUE_ENDPOINT_TYPE endpoint_type); +}; diff --git a/Controllers/CorsairICueLinkController/CorsairICueLinkControllerDetect.cpp b/Controllers/CorsairICueLinkController/CorsairICueLinkControllerDetect.cpp new file mode 100644 index 00000000..91e1f396 --- /dev/null +++ b/Controllers/CorsairICueLinkController/CorsairICueLinkControllerDetect.cpp @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| CorsairICueLinkControllerDetect.cpp | +| | +| Detector for Corsair iCue Link System Hub | +| | +| Aiden Vigue (acvigue) 02 Mar 2025 | +| Adam Honse 01 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "LogManager.h" +#include "CorsairICueLinkController.h" +#include "RGBController_CorsairICueLink.h" + +#define CORSAIR_VID 0x1B1C +#define CORSAIR_ICUE_LINK_SYSTEM_HUB_PID 0x0C3F + +void DetectCorsairICueLinkControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + CorsairICueLinkController* controller = new CorsairICueLinkController(dev, info->path, name); + RGBController_CorsairICueLink* rgb_controller = new RGBController_CorsairICueLink(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR_IPU("Corsair iCUE Link System Hub", DetectCorsairICueLinkControllers, CORSAIR_VID, CORSAIR_ICUE_LINK_SYSTEM_HUB_PID, 0x00, 0xFF42, 0x01); diff --git a/Controllers/CorsairICueLinkController/CorsairICueLinkProtocol.cpp b/Controllers/CorsairICueLinkController/CorsairICueLinkProtocol.cpp new file mode 100644 index 00000000..f3244cca --- /dev/null +++ b/Controllers/CorsairICueLinkController/CorsairICueLinkProtocol.cpp @@ -0,0 +1,25 @@ +/*---------------------------------------------------------*\ +| CorsairICueLinkProtocol.cpp | +| | +| Driver for Corsair iCue Link System Hub | +| | +| Aiden Vigue (acvigue) 2 Mar 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "CorsairICueLinkProtocol.h" + +const CorsairICueLinkDevice* FindCorsairICueLinkDevice(unsigned char type, unsigned char model) +{ + for(size_t i = 0; i < sizeof(known_devices) / sizeof(known_devices[0]); i++) + { + if(known_devices[i].type == type && known_devices[i].model == model) + { + return(&known_devices[i]); + } + } + + return nullptr; +} diff --git a/Controllers/CorsairICueLinkController/CorsairICueLinkProtocol.h b/Controllers/CorsairICueLinkController/CorsairICueLinkProtocol.h new file mode 100644 index 00000000..e014ef43 --- /dev/null +++ b/Controllers/CorsairICueLinkController/CorsairICueLinkProtocol.h @@ -0,0 +1,100 @@ +/*---------------------------------------------------------*\ +| CorsairICueLinkProtocol.h | +| | +| Driver for Corsair iCue Link System Hub | +| | +| Aiden Vigue (acvigue) 02 Mar 2025 | +| Nikola Jurkovic (jurkovic.nikola) 11 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include + +typedef struct CorsairICueLinkDevice +{ + unsigned char type = 0x00; + unsigned char model = 0x00; + std::string display_name = "Unknown"; + unsigned char led_channels = 0; + bool internal = false; +} CorsairICueLinkDevice; + +static const CorsairICueLinkDevice known_devices[] = +{ + { 0x05, 0x02, "iCUE LINK 5000T RGB", 160 }, + { 0x05, 0x01, "iCUE LINK 9000D RGB AIRFLOW", 22 }, + { 0x05, 0x00, "iCUE LINK ADAPTER", 0 }, + { 0x06, 0x00, "iCUE LINK COOLER PUMP LCD", 24 }, + { 0x11, 0x00, "iCUE LINK TITAN 240", 20 }, + { 0x11, 0x04, "iCUE LINK TITAN 240", 20 }, + { 0x07, 0x00, "iCUE LINK H100i RGB", 20 }, + { 0x07, 0x04, "iCUE LINK H100i RGB", 20 }, + { 0x11, 0x01, "iCUE LINK TITAN 280", 20 }, + { 0x07, 0x01, "iCUE LINK H115i RGB", 20 }, + { 0x11, 0x02, "iCUE LINK TITAN 360", 20 }, + { 0x11, 0x05, "iCUE LINK TITAN 360", 20 }, + { 0x07, 0x02, "iCUE LINK H150i RGB", 20 }, + { 0x07, 0x05, "iCUE LINK H150i RGB", 20 }, + { 0x11, 0x03, "iCUE LINK TITAN 420", 20 }, + { 0x07, 0x03, "iCUE LINK H170i RGB", 20 }, + { 0x10, 0x00, "VRM COOLER MODULE", 0 }, + { 0x02, 0x00, "iCUE LINK LX RGB", 18 }, + { 0x14, 0x00, "ORIGIN OA", 0 }, + { 0x01, 0x00, "iCUE LINK QX RGB", 34 }, + { 0x13, 0x00, "iCUE LINK RX", 0 }, + { 0x04, 0x00, "iCUE LINK RX MAX", 0 }, + { 0x0F, 0x00, "iCUE LINK RX RGB", 8 }, + { 0x03, 0x00, "iCUE LINK RX RGB MAX", 8 }, + { 0x09, 0x00, "iCUE LINK XC7 ELITE", 24 }, + { 0x0C, 0x00, "iCUE LINK XD5 ELITE", 22 }, + { 0x0E, 0x00, "iCUE LINK XD5 ELITE LCD", 22, true }, + { 0x19, 0x00, "iCUE LINK XD6 ELITE", 22 }, + { 0x0A, 0x00, "iCUE LINK XG3 HYBRID", 0 }, + { 0x0D, 0x00, "iCUE LINK XG7 RGB", 16 } +}; + +//Lengths +#define CORSAIR_ICUE_LINK_BUFFER_WRITE_LENGTH 513 +#define CORSAIR_ICUE_LINK_BUFFER_READ_LENGTH 512 +#define CORSAIR_ICUE_LINK_READ_HEADER_SIZE 3 +#define CORSAIR_ICUE_LINK_WRITE_HEADER_SIZE 4 +#define CORSAIR_ICUE_LINK_MAXIMUM_BUFFER_PER_REQUEST 508 + +//Commands +#define CORSAIR_ICUE_LINK_CMD_OPEN_ENDPOINT {0x0d, 0x01} +#define CORSAIR_ICUE_LINK_CMD_OPEN_COLOR_ENDPOINT {0x0d, 0x00} +#define CORSAIR_ICUE_LINK_CMD_CLOSE_ENDPOINT {0x05, 0x01, 0x01} +#define CORSAIR_ICUE_LINK_CMD_GET_FIRMWARE {0x02, 0x13} +#define CORSAIR_ICUE_LINK_CMD_SOFTWARE_MODE {0x01, 0x03, 0x00, 0x02} +#define CORSAIR_ICUE_LINK_CMD_HARDWARE_MODE {0x01, 0x03, 0x00, 0x01} +#define CORSAIR_ICUE_LINK_CMD_WRITE {0x06, 0x01} +#define CORSAIR_ICUE_LINK_CMD_WRITE_COLOR {0x06, 0x00} +#define CORSAIR_ICUE_LINK_CMD_WRITE_COLOR_NEXT {0x07, 0x00} +#define CORSAIR_ICUE_LINK_CMD_READ {0x08, 0x01} +#define CORSAIR_ICUE_LINK_CMD_GET_DEVICE_MODE {0x01, 0x08, 0x01} + +//Command modes +#define CORSAIR_ICUE_LINK_MODE_GET_DEVICES {0x36,} +#define CORSAIR_ICUE_LINK_MODE_GET_TEMPERATURES {0x21,} +#define CORSAIR_ICUE_LINK_MODE_GET_SPEEDS {0x17,} +#define CORSAIR_ICUE_LINK_MODE_SET_SPEED {0x18,} +#define CORSAIR_ICUE_LINK_MODE_SET_COLOR {0x22,} + +//Command data types +#define CORSAIR_ICUE_LINK_DATA_TYPE_GET_DEVICES {0x21, 0x00} +#define CORSAIR_ICUE_LINK_DATA_TYPE_GET_TEMPERATURES {0x10, 0x00} +#define CORSAIR_ICUE_LINK_DATA_TYPE_GET_SPEEDS {0x25, 0x00} +#define CORSAIR_ICUE_LINK_DATA_TYPE_SET_SPEED {0x07, 0x00} +#define CORSAIR_ICUE_LINK_DATA_TYPE_SET_COLOR {0x12, 0x00} + +typedef enum CORSAIR_ICUE_ENDPOINT_TYPE +{ + CORSAIR_ICUE_ENDPOINT_TYPE_DEFAULT, + CORSAIR_ICUE_ENDPOINT_TYPE_COLOR +} CORSAIR_ICUE_ENDPOINT_TYPE; + +const CorsairICueLinkDevice* FindCorsairICueLinkDevice(unsigned char type, unsigned char model); diff --git a/Controllers/CorsairICueLinkController/RGBController_CorsairICueLink.cpp b/Controllers/CorsairICueLinkController/RGBController_CorsairICueLink.cpp new file mode 100644 index 00000000..9e528970 --- /dev/null +++ b/Controllers/CorsairICueLinkController/RGBController_CorsairICueLink.cpp @@ -0,0 +1,153 @@ +/*---------------------------------------------------------*\ +| RGBController_CorsairICueLink.cpp | +| | +| Driver for Corsair iCue Link Devices | +| | +| Aiden Vigue (acvigue) 02 Mar 2025 | +| Adam Honse 01 Aug 2025 | +| Nikola Jurkovic (jurkovic.nikola) 11 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "CorsairICueLinkProtocol.h" +#include "RGBController_CorsairICueLink.h" + +using namespace std::chrono_literals; + +/**------------------------------------------------------------------*\ + @name Corsair iCUE Link Device Controller + @category Cooler + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectCorsairICueLinkController + @comment +\*-------------------------------------------------------------------*/ + +RGBController_CorsairICueLink::RGBController_CorsairICueLink(CorsairICueLinkController* controller) +{ + this->controller = controller; + + name = controller->GetNameString(); + vendor = "Corsair"; + description = "iCUE Link Device"; + version = controller->GetFirmwareString(); + location = controller->GetLocationString(); + serial = controller->GetSerialString(); + type = DEVICE_TYPE_COOLER; + + 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(); + + keepalive_thread_run = 1; + keepalive_thread = new std::thread(&RGBController_CorsairICueLink::KeepaliveThread, this); +} + +RGBController_CorsairICueLink::~RGBController_CorsairICueLink() +{ + keepalive_thread_run = 0; + keepalive_thread->join(); + delete keepalive_thread; + + delete controller; +} + +void RGBController_CorsairICueLink::SetupZones() +{ + for(std::size_t zone_idx = 0; zone_idx < controller->GetEndpoints().size(); zone_idx++) + { + if(controller->GetEndpoints()[zone_idx]->type == 0x06) + { + /*-----------------------------------------------------*\ + | We skip LCD processing here | + \*-----------------------------------------------------*/ + continue; + } + + zone new_zone; + new_zone.name = controller->GetEndpoints()[zone_idx]->display_name; + new_zone.type = ZONE_TYPE_LINEAR; + new_zone.leds_min = controller->GetEndpoints()[zone_idx]->led_channels; + new_zone.leds_max = new_zone.leds_min; + new_zone.leds_count = new_zone.leds_min; + zones.push_back(new_zone); + + if(controller->GetEndpoints()[zone_idx]->type == 0x07 || controller->GetEndpoints()[zone_idx]->type == 0x11) + { + /*---------------------------------------------------------*\ + | iCUE LINK AIO 'H' Series || iCUE LINK AIO 'TITAN' Series | + \*---------------------------------------------------------*/ + for(std::size_t lcd_idx = 0; lcd_idx < controller->GetEndpoints().size(); lcd_idx++) + { + if(controller->GetEndpoints()[lcd_idx]->type == 0x06) + { + zone lcd_zone; + lcd_zone.name = controller->GetEndpoints()[lcd_idx]->display_name; + lcd_zone.type = ZONE_TYPE_LINEAR; + lcd_zone.leds_min = controller->GetEndpoints()[lcd_idx]->led_channels; + lcd_zone.leds_max = lcd_zone.leds_min; + lcd_zone.leds_count = lcd_zone.leds_min; + zones.push_back(lcd_zone); + } + } + } + + for(unsigned int led_idx = 0; led_idx < new_zone.leds_count; led_idx++) + { + led new_led; + new_led.name = "LED " + std::to_string(led_idx + 1); + + leds.push_back(new_led); + } + } + + SetupColors(); +} + +void RGBController_CorsairICueLink::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*-----------------------------------------------------*\ + | Device does not support resizing zones | + \*-----------------------------------------------------*/ +} + +void RGBController_CorsairICueLink::DeviceUpdateLEDs() +{ + controller->UpdateLights(&colors[0], colors.size()); +} + +void RGBController_CorsairICueLink::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_CorsairICueLink::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_CorsairICueLink::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} + +void RGBController_CorsairICueLink::KeepaliveThread() +{ + while(keepalive_thread_run.load()) + { + if((std::chrono::steady_clock::now() - last_commit_time) > std::chrono::seconds(5)) + { + DeviceUpdateLEDs(); + } + std::this_thread::sleep_for(1s); + } +} \ No newline at end of file diff --git a/Controllers/CorsairICueLinkController/RGBController_CorsairICueLink.h b/Controllers/CorsairICueLinkController/RGBController_CorsairICueLink.h new file mode 100644 index 00000000..a8839e4f --- /dev/null +++ b/Controllers/CorsairICueLinkController/RGBController_CorsairICueLink.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------*\ +| RGBController_CorsairICueLink.h | +| | +| RGBController for Corsair iCue Link Devices | +| | +| Aiden Vigue (acvigue) 02 Mar 2025 | +| Adam Honse 01 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "CorsairICueLinkController.h" +#include "RGBController.h" + +class RGBController_CorsairICueLink : public RGBController +{ +public: + RGBController_CorsairICueLink(CorsairICueLinkController* controller); + ~RGBController_CorsairICueLink(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + CorsairICueLinkController* controller; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::chrono::time_point last_commit_time; + + void KeepaliveThread(); +}; diff --git a/Controllers/CorsairLightingNodeController/CorsairLightingNodeController.cpp b/Controllers/CorsairLightingNodeController/CorsairLightingNodeController.cpp index de6fe3b3..2f02e2e5 100644 --- a/Controllers/CorsairLightingNodeController/CorsairLightingNodeController.cpp +++ b/Controllers/CorsairLightingNodeController/CorsairLightingNodeController.cpp @@ -1,22 +1,30 @@ /*---------------------------------------------------------*\ -| Processing Code for Corsair Lighting Node Pro | +| CorsairLightingNodeController.cpp | | | -| Adam Honse (calcprogrammer1@gmail.com), 1/12/2020 | +| Driver for Corsair Lighting Node devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "CorsairLightingNodeController.h" - +#include #include #include #include -#include +#include "CorsairLightingNodeController.h" +#include "CorsairDeviceGuard.h" +#include "StringUtils.h" using namespace std::chrono_literals; -CorsairLightingNodeController::CorsairLightingNodeController(hid_device* dev_handle, const char* path) +CorsairLightingNodeController::CorsairLightingNodeController(hid_device* dev_handle, const char* path, std::string dev_name) { - dev = dev_handle; - location = path; + dev = dev_handle; + location = path; + name = dev_name; + guard_manager_ptr = new DeviceGuardManager(new CorsairDeviceGuard()); SendFirmwareRequest(); @@ -37,6 +45,7 @@ CorsairLightingNodeController::~CorsairLightingNodeController() delete keepalive_thread; hid_close(dev); + delete guard_manager_ptr; } void CorsairLightingNodeController::KeepaliveThread() @@ -61,6 +70,11 @@ std::string CorsairLightingNodeController::GetLocationString() return("HID: " + location); } +std::string CorsairLightingNodeController::GetNameString() +{ + return(name); +} + std::string CorsairLightingNodeController::GetSerialString() { wchar_t serial_string[128]; @@ -71,10 +85,7 @@ std::string CorsairLightingNodeController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void CorsairLightingNodeController::SetBrightness(unsigned char brightness) @@ -176,7 +187,7 @@ void CorsairLightingNodeController::SetChannelLEDs(unsigned char channel, RGBCol { pkt_size = 50; } - + for(int color_idx = 0; color_idx < pkt_size; color_idx++) { red_color_data[color_idx] = RGBGetRValue(colors[pkt_offset + color_idx]); @@ -205,7 +216,7 @@ void CorsairLightingNodeController::SetChannelLEDs(unsigned char channel, RGBCol void CorsairLightingNodeController::SendFirmwareRequest() { int actual; - unsigned char usb_buf[65]; + unsigned char usb_buf[CORSAIR_LIGHTING_NODE_WRITE_PACKET_SIZE]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -221,8 +232,7 @@ void CorsairLightingNodeController::SendFirmwareRequest() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); - actual = hid_read(dev, usb_buf, 17); + actual = WriteAndRead(usb_buf); if(actual > 0) { @@ -239,7 +249,7 @@ void CorsairLightingNodeController::SendDirect unsigned char* color_data ) { - unsigned char usb_buf[65]; + unsigned char usb_buf[CORSAIR_LIGHTING_NODE_WRITE_PACKET_SIZE]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -264,13 +274,12 @@ void CorsairLightingNodeController::SendDirect /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); - hid_read_timeout(dev, usb_buf, 17, 5); + WriteAndRead(usb_buf, CORSAIR_LIGHTING_NODE_READ_TIMEOUT); } void CorsairLightingNodeController::SendCommit() { - unsigned char usb_buf[65]; + unsigned char usb_buf[CORSAIR_LIGHTING_NODE_WRITE_PACKET_SIZE]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -292,8 +301,7 @@ void CorsairLightingNodeController::SendCommit() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); - hid_read_timeout(dev, usb_buf, 17, 5); + WriteAndRead(usb_buf, CORSAIR_LIGHTING_NODE_READ_TIMEOUT); } void CorsairLightingNodeController::SendBegin @@ -301,7 +309,7 @@ void CorsairLightingNodeController::SendBegin unsigned char channel ) { - unsigned char usb_buf[65]; + unsigned char usb_buf[CORSAIR_LIGHTING_NODE_WRITE_PACKET_SIZE]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -318,8 +326,7 @@ void CorsairLightingNodeController::SendBegin /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); - hid_read(dev, usb_buf, 17); + WriteAndRead(usb_buf); } void CorsairLightingNodeController::SendEffectConfig @@ -345,7 +352,7 @@ void CorsairLightingNodeController::SendEffectConfig unsigned short temperature_2 ) { - unsigned char usb_buf[65]; + unsigned char usb_buf[CORSAIR_LIGHTING_NODE_WRITE_PACKET_SIZE]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -396,8 +403,7 @@ void CorsairLightingNodeController::SendEffectConfig /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); - hid_read(dev, usb_buf, 17); + WriteAndRead(usb_buf); } void CorsairLightingNodeController::SendTemperature() @@ -410,7 +416,7 @@ void CorsairLightingNodeController::SendReset unsigned char channel ) { - unsigned char usb_buf[65]; + unsigned char usb_buf[CORSAIR_LIGHTING_NODE_WRITE_PACKET_SIZE]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -427,8 +433,7 @@ void CorsairLightingNodeController::SendReset /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); - hid_read(dev, usb_buf, 17); + WriteAndRead(usb_buf); } void CorsairLightingNodeController::SendPortState @@ -437,7 +442,7 @@ void CorsairLightingNodeController::SendPortState unsigned char state ) { - unsigned char usb_buf[65]; + unsigned char usb_buf[CORSAIR_LIGHTING_NODE_WRITE_PACKET_SIZE]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -455,8 +460,7 @@ void CorsairLightingNodeController::SendPortState /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); - hid_read_timeout(dev, usb_buf, 17, 5); + WriteAndRead(usb_buf, CORSAIR_LIGHTING_NODE_READ_TIMEOUT); } void CorsairLightingNodeController::SendBrightness @@ -465,7 +469,7 @@ void CorsairLightingNodeController::SendBrightness unsigned char brightness ) { - unsigned char usb_buf[65]; + unsigned char usb_buf[CORSAIR_LIGHTING_NODE_WRITE_PACKET_SIZE]; /*-----------------------------------------------------*\ | Brightness goes from 0-100 | @@ -491,8 +495,7 @@ void CorsairLightingNodeController::SendBrightness /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); - hid_read(dev, usb_buf, 17); + WriteAndRead(usb_buf); } void CorsairLightingNodeController::SendLEDCount() @@ -504,3 +507,34 @@ void CorsairLightingNodeController::SendProtocol() { } + +int CorsairLightingNodeController::WriteAndRead + ( + unsigned char *buf, + int read_timeout_ms + ) +{ + int hid_read_ret; + + /*---------------------------------------------------------*\ + | HID I/O start | + \*---------------------------------------------------------*/ + { + DeviceGuardLock _ = guard_manager_ptr->AwaitExclusiveAccess(); + + hid_write(dev, buf, CORSAIR_LIGHTING_NODE_WRITE_PACKET_SIZE); + if(read_timeout_ms > 0) + { + hid_read_ret = hid_read_timeout(dev, buf, CORSAIR_LIGHTING_NODE_READ_PACKET_SIZE, read_timeout_ms); + } + else + { + hid_read_ret = hid_read(dev, buf, CORSAIR_LIGHTING_NODE_READ_PACKET_SIZE); + } + } + /*---------------------------------------------------------*\ + | HID I/O end (lock released) | + \*---------------------------------------------------------*/ + + return hid_read_ret; +} diff --git a/Controllers/CorsairLightingNodeController/CorsairLightingNodeController.h b/Controllers/CorsairLightingNodeController/CorsairLightingNodeController.h index 35d63f6a..6e5d5b37 100644 --- a/Controllers/CorsairLightingNodeController/CorsairLightingNodeController.h +++ b/Controllers/CorsairLightingNodeController/CorsairLightingNodeController.h @@ -1,16 +1,25 @@ /*---------------------------------------------------------*\ -| Definitions for Corsair Lighting Node Pro | +| CorsairLightingNodeController.h | | | -| Adam Honse (calcprogrammer1@gmail.com), 1/12/2020 | +| Driver for Corsair Lighting Node devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "RGBController.h" -#include -#include -#include - #pragma once +#include +#include +#include +#include "DeviceGuardManager.h" +#include "RGBController.h" + +#define CORSAIR_LIGHTING_NODE_WRITE_PACKET_SIZE 65 /* First byte is the report number */ +#define CORSAIR_LIGHTING_NODE_READ_PACKET_SIZE 17 /* First byte is the report number */ +#define CORSAIR_LIGHTING_NODE_READ_TIMEOUT 15 /* Timeout in milliseconds */ enum { CORSAIR_LIGHTING_NODE_PACKET_ID_FIRMWARE = 0x02, /* Get firmware version */ @@ -79,17 +88,18 @@ enum class CorsairLightingNodeController { public: - CorsairLightingNodeController(hid_device* dev_handle, const char* path); + CorsairLightingNodeController(hid_device* dev_handle, const char* path, std::string dev_name); ~CorsairLightingNodeController(); std::string GetFirmwareString(); std::string GetLocationString(); + std::string GetNameString(); std::string GetSerialString(); unsigned int GetStripsOnChannel(unsigned int channel); void SetBrightness(unsigned char brightness); - + void SetChannelEffect(unsigned char channel, unsigned char num_leds, unsigned char mode, @@ -112,12 +122,14 @@ public: void KeepaliveThread(); private: - hid_device* dev; - std::string firmware_version; - std::string location; - std::thread* keepalive_thread; - std::atomic keepalive_thread_run; - std::chrono::time_point last_commit_time; + hid_device* dev; + std::string firmware_version; + std::string location; + std::string name; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::chrono::time_point last_commit_time; + DeviceGuardManager* guard_manager_ptr; void SendFirmwareRequest(); @@ -182,4 +194,10 @@ private: void SendLEDCount(); void SendProtocol(); + + int WriteAndRead + ( + unsigned char *buf, + int read_timeout_ms = -1 + ); }; diff --git a/Controllers/CorsairLightingNodeController/CorsairLightingNodeControllerDetect.cpp b/Controllers/CorsairLightingNodeController/CorsairLightingNodeControllerDetect.cpp index 72cdbd56..f84969b5 100644 --- a/Controllers/CorsairLightingNodeController/CorsairLightingNodeControllerDetect.cpp +++ b/Controllers/CorsairLightingNodeController/CorsairLightingNodeControllerDetect.cpp @@ -1,9 +1,18 @@ +/*---------------------------------------------------------*\ +| CorsairLightingNodeControllerDetect.cpp | +| | +| Detector for Corsair Lighting Node devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "CorsairLightingNodeController.h" -#include "RGBController.h" #include "RGBController_CorsairLightingNode.h" -#include -#include #define CORSAIR_VID 0x1B1C #define CORSAIR_LIGHTING_NODE_CORE_PID 0x0C1A @@ -28,9 +37,9 @@ void DetectCorsairLightingNodeControllers(hid_device_info* info, const std::stri if(dev) { - CorsairLightingNodeController* controller = new CorsairLightingNodeController(dev, info->path); + CorsairLightingNodeController* controller = new CorsairLightingNodeController(dev, info->path, name); RGBController_CorsairLightingNode* rgb_controller = new RGBController_CorsairLightingNode(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } /* DetectCorsairLightingNodeControllers() */ @@ -41,4 +50,4 @@ REGISTER_HID_DETECTOR("Corsair Commander Pro", DetectCorsairLightingNodeCon REGISTER_HID_DETECTOR("Corsair LS100 Lighting Kit", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_LS100_PID); // 1 channel REGISTER_HID_DETECTOR("Corsair 1000D Obsidian", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_1000D_OBSIDIAN_PID); // 2 channels REGISTER_HID_DETECTOR("Corsair SPEC OMEGA RGB", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_SPEC_OMEGA_RGB_PID); // 2 channels -REGISTER_HID_DETECTOR("Corsair LT100", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_LT100_PID); // 2 channels \ No newline at end of file +REGISTER_HID_DETECTOR("Corsair LT100", DetectCorsairLightingNodeControllers, CORSAIR_VID, CORSAIR_LT100_PID); // 2 channels diff --git a/Controllers/CorsairLightingNodeController/RGBController_CorsairLightingNode.cpp b/Controllers/CorsairLightingNodeController/RGBController_CorsairLightingNode.cpp index 5f754a48..fec87bfd 100644 --- a/Controllers/CorsairLightingNodeController/RGBController_CorsairLightingNode.cpp +++ b/Controllers/CorsairLightingNodeController/RGBController_CorsairLightingNode.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_CorsairLightingNode.cpp | -| | -| Generic RGB Interface for Corsair | -| Lighting Node Pro | -| | -| Adam Honse (CalcProgrammer1) 1/12/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairLightingNode.cpp | +| | +| RGBController for Corsair Lighting Node devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CorsairLightingNode.h" @@ -24,7 +26,7 @@ RGBController_CorsairLightingNode::RGBController_CorsairLightingNode(CorsairLigh { controller = controller_ptr; - name = "Corsair Lighting Node Device"; + name = controller->GetNameString(); vendor = "Corsair"; description = "Corsair Lighting Node Device"; type = DEVICE_TYPE_LEDSTRIP; @@ -297,7 +299,7 @@ void RGBController_CorsairLightingNode::ResizeZone(int zone, int new_size) void RGBController_CorsairLightingNode::DeviceUpdateLEDs() { - for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + for(unsigned char zone_idx = 0; zone_idx < (unsigned char)zones.size(); zone_idx++) { controller->SetChannelLEDs(zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); } diff --git a/Controllers/CorsairLightingNodeController/RGBController_CorsairLightingNode.h b/Controllers/CorsairLightingNodeController/RGBController_CorsairLightingNode.h index 3fc7d0c8..72a0790f 100644 --- a/Controllers/CorsairLightingNodeController/RGBController_CorsairLightingNode.h +++ b/Controllers/CorsairLightingNodeController/RGBController_CorsairLightingNode.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_CorsairLightingNode.h | -| | -| Generic RGB Interface for Corsair | -| Lighting Node Pro | -| | -| Adam Honse (CalcProgrammer1) 1/12/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairLightingNode.h | +| | +| RGBController for Corsair Lighting Node devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "CorsairLightingNodeController.h" diff --git a/Controllers/CorsairPeripheralController/CorsairK100Controller.cpp b/Controllers/CorsairPeripheralController/CorsairK100Controller.cpp deleted file mode 100644 index f57c9cc4..00000000 --- a/Controllers/CorsairPeripheralController/CorsairK100Controller.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/*-----------------------------------------*\ -| CorsairK100Controller.cpp | -| | -| Driver for Corsair K100 Keyboard | -\*-----------------------------------------*/ - -#include "CorsairK100Controller.h" -#include "LogManager.h" - -static unsigned int keys_k100[] = {0x25, 0x31, 0x27, 0x35, 0x66, 0x65, 0x41, 0x2A, 0x6E, 0x5B, 0x36, 0x1A, 0x10, 0x00, 0x68, 0x42, - 0x62, 0x5C, 0x37, 0x1B, 0x16, 0x12, 0x19, 0x67, 0x43, 0x26, 0x77, 0x5D, 0x38, 0x1C, 0x04, 0x03, - 0x17, 0x44, 0x48, 0x7A, 0x39, 0x1D, 0x11, 0x05, 0x02, 0x28, 0x45, 0x49, 0x78, 0x58, 0x3A, 0x1E, - 0x13, 0x06, 0x15, 0x46, 0x4A, 0x79, 0x59, 0x3B, 0x1F, 0x18, 0x07, 0x01, 0x47, 0x6A, 0x4F, 0x5A, - 0x3C, 0x20, 0x14, 0x09, 0x0D, 0x6B, 0x2C, 0x69, 0x50, 0x55, 0x3D, 0x21, 0x08, 0x0A, 0x0C, 0x76, - 0x2D, 0x4E, 0x51, 0x56, 0x3E, 0x22, 0x0E, 0x0B, 0x32, 0x61, 0x4C, 0x52, 0x57, 0x3F, 0x23, 0x0F, - 0x2F, 0x33, 0x24, 0x4D, 0x53, 0x5E, 0x40, 0x29, 0x2B, 0x30, 0x34, /*Brightness,*/ - 0x4B, 0x54, 0x5F, 0x60, 0x2E, 0x7C, - 0x7F, 0x80, 0x81, 0x82, 0x83, 0x84,//Macro - 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0, 0x9F, 0x9E, 0x9D, 0x9C, 0x86, 0x87, 0x88, 0x89, 0x8A, - 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, - 0x9B, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,0xB0, 0xB1, //Light Bar - 0x85, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9,//Nameplate - 0xBA, 0xBB, 0xBC/*Logo*/}; - -CorsairK100Controller::CorsairK100Controller(hid_device* dev_handle, const char* path) -{ - dev = dev_handle; - location = path; - keyboard_type = CORSAIR_TYPE_K100; - - LightingControl(); -} -CorsairK100Controller::~CorsairK100Controller() -{ - hid_close(dev); -} - -std::string CorsairK100Controller::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string CorsairK100Controller::GetFirmwareString() -{ - return ""; -} - -std::string CorsairK100Controller::GetName() -{ - return name; -} - -void CorsairK100Controller::SetName(std::string device_name) -{ - name = device_name; -} - -CorsairKeyboardType CorsairK100Controller::GetKeyboardType() -{ - return keyboard_type; -} - -std::string CorsairK100Controller::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 CorsairK100Controller::LightingControl() -{ - unsigned char usb_buf[65]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - //This is requered - usb_buf[0x01] = 0x08; - usb_buf[0x02] = 0x01; - usb_buf[0x03] = 0x03; - usb_buf[0x05] = 0x02; - - hid_write(dev, (unsigned char *)usb_buf, 65); - - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x01] = 0x08; - usb_buf[0x02] = 0x01; - usb_buf[0x03] = 0x4A; - usb_buf[0x05] = 0x01; - - hid_write(dev, (unsigned char *)usb_buf, 65); - - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x01] = 0x08; - usb_buf[0x02] = 0x01; - usb_buf[0x03] = 0x45; - usb_buf[0x05] = 0x00; - - hid_write(dev, (unsigned char *)usb_buf, 65); - - memset(usb_buf, 0x00, sizeof(usb_buf)); - //This is requered - usb_buf[0x01] = 0x08; - usb_buf[0x02] = 0x0D; - usb_buf[0x03] = 0x01; - usb_buf[0x04] = 0x22; - - hid_write(dev, (unsigned char *)usb_buf, 65); - - /*memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x01] = 0x08; - usb_buf[0x02] = 0x05; - usb_buf[0x03] = 0x01; - - hid_write(dev, (unsigned char *)usb_buf, 65); - - memset(usb_buf, 0x00, sizeof(usb_buf)); - - int res = hid_read_timeout(dev, usb_buf, 50, 1000); - - if (res == 0 || usb_buf[1] != 0x01) - { - LOG_INFO("[Corsair-K100] This device did not allow to take control over it. recieved response: %02X", usb_buf[1]); - keyboard_type = CORSAIR_TYPE_UNKNOWN; - }*/ - -} - -void CorsairK100Controller::SetLEDs(std::vectorcolors) -{ - switch(keyboard_type) - { - case CORSAIR_TYPE_K100: - SetLEDsKeyboardFull(colors); - break; - - case CORSAIR_TYPE_UNKNOWN: - break; - } -} - -void CorsairK100Controller::SetLEDsKeyboardFull(std::vector colors) -{ - unsigned char usb_buf[600]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x01] = 0x08; - usb_buf[0x02] = 0x06; - usb_buf[0x03] = 0x01; - usb_buf[0x04] = 0x45; - usb_buf[0x05] = 0x02; - usb_buf[0x08] = 0x12; - - for(std::size_t color_idx = 0; color_idx < colors.size(); color_idx++) - { - RGBColor color = colors[color_idx]; - usb_buf[0x16 + keys_k100[color_idx]*3] = RGBGetRValue(color); - usb_buf[0x17 + keys_k100[color_idx]*3] = RGBGetGValue(color); - usb_buf[0x18 + keys_k100[color_idx]*3] = RGBGetBValue(color); - } - - hid_write(dev, (unsigned char *)usb_buf, 600); -} diff --git a/Controllers/CorsairPeripheralController/CorsairK100Controller.h b/Controllers/CorsairPeripheralController/CorsairK100Controller.h deleted file mode 100644 index b97911a5..00000000 --- a/Controllers/CorsairPeripheralController/CorsairK100Controller.h +++ /dev/null @@ -1,49 +0,0 @@ -/*-----------------------------------------*\ -| CorsairK100Controller.h | -| | -| Driver for Corsair K100 Keyboard | -\*-----------------------------------------*/ - -#ifndef CORSAIRK100CONTROLLER_H -#define CORSAIRK100CONTROLLER_H - -#include "RGBController.h" - -#include -#include - -typedef enum -{ - CORSAIR_TYPE_UNKNOWN = 0, - CORSAIR_TYPE_K100 = 1 -} CorsairKeyboardType; - -class CorsairK100Controller -{ -public: - CorsairK100Controller(hid_device* dev_handle, const char* path); - ~CorsairK100Controller(); - CorsairKeyboardType GetKeyboardType(); - std::string GetDeviceLocation(); - std::string GetFirmwareString(); - std::string GetName(); - std::string GetSerialString(); - - void SetLEDs(std::vector colors); - void SetLEDsKeyboardLimited(std::vector colors); - void SetName(std::string device_name); - -private: - hid_device* dev; - - std::string firmware_version; - std::string location; - std::string name; - device_type type; - CorsairKeyboardType keyboard_type; - - void LightingControl(); - void SetLEDsKeyboardFull(std::vector colors); -}; - -#endif // CORSAIRK100CONTROLLER_H diff --git a/Controllers/CorsairPeripheralController/CorsairK55RGBPROXTController.cpp b/Controllers/CorsairPeripheralController/CorsairK55RGBPROXTController.cpp index 4102294c..70847d25 100644 --- a/Controllers/CorsairPeripheralController/CorsairK55RGBPROXTController.cpp +++ b/Controllers/CorsairPeripheralController/CorsairK55RGBPROXTController.cpp @@ -1,19 +1,21 @@ -/*--------------------------------------------*\ -| CorsairK55RGBPROXTController.cpp | -| | -| Driver for Corsair K55 RGB PRO XT Keyboard | -\*--------------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairK55RGBPROXTController.cpp | +| | +| Driver for Corsair K55 RGB PRO XT keyboard | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "CorsairK55RGBPROXTController.h" #include "LogManager.h" - +#include "StringUtils.h" #define COLOR_BANK_SIZE 137 #define HID_PACKET_LENGTH 65 #define HID_PAYLOAD_SIZE1 (HID_PACKET_LENGTH - 12) #define HID_PAYLOAD_SIZE2 (HID_PACKET_LENGTH - 4) - static const unsigned int keys[] = { 127, 128, 129, 130, 131, 132, 37, 49, 39, 53, 102, 101, 26, 96, 104, 54, 27, 16, 0, 25, 103, 55, 28, 22, 18, 23, 56, 29, 4, 3, 2, 57, 30, 17, 5, 21, 31, 58, 32, 19, @@ -36,10 +38,11 @@ static const unsigned char filler[] = 0x6D }; -CorsairK55RGBPROXTController::CorsairK55RGBPROXTController(hid_device* dev_handle, const char* path) +CorsairK55RGBPROXTController::CorsairK55RGBPROXTController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; LightingControl(); } @@ -54,9 +57,9 @@ std::string CorsairK55RGBPROXTController::GetDeviceLocation() return("HID: " + location); } -std::string CorsairK55RGBPROXTController::GetFirmwareString() +std::string CorsairK55RGBPROXTController::GetNameString() { - return ""; + return(name); } std::string CorsairK55RGBPROXTController::GetSerialString() @@ -69,10 +72,7 @@ std::string CorsairK55RGBPROXTController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void CorsairK55RGBPROXTController::LightingControl() diff --git a/Controllers/CorsairPeripheralController/CorsairK55RGBPROXTController.h b/Controllers/CorsairPeripheralController/CorsairK55RGBPROXTController.h index c7920a3f..c01b32e1 100644 --- a/Controllers/CorsairPeripheralController/CorsairK55RGBPROXTController.h +++ b/Controllers/CorsairPeripheralController/CorsairK55RGBPROXTController.h @@ -1,25 +1,26 @@ -/*--------------------------------------------*\ -| CorsairK55RGBPROXTController.h | -| | -| Driver for Corsair K55 RGB PRO XT Keyboard | -\*--------------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairK55RGBPROXTController.h | +| | +| Driver for Corsair K55 RGB PRO XT keyboard | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#ifndef CORSAIRK55RGBPROXTCONTROLLER_H -#define CORSAIRK55RGBPROXTCONTROLLER_H - -#include "RGBController.h" +#pragma once #include -#include - +#include +#include "RGBController.h" class CorsairK55RGBPROXTController { public: - CorsairK55RGBPROXTController(hid_device* dev_handle, const char* path); + CorsairK55RGBPROXTController(hid_device* dev_handle, const char* path, std::string dev_name); ~CorsairK55RGBPROXTController(); + std::string GetDeviceLocation(); - std::string GetFirmwareString(); + std::string GetNameString(); std::string GetSerialString(); void SetLEDs(std::vector colors); @@ -33,7 +34,6 @@ public: ); void SwitchMode(bool software); - enum { CORSAIR_MODE_DIRECT_VALUE = 0xFFFF, @@ -80,11 +80,8 @@ public: private: hid_device* dev; - std::string firmware_version; std::string location; - device_type type; + std::string name; void LightingControl(); }; - -#endif // CORSAIRK55RGBPROXTCONTROLLER_H diff --git a/Controllers/CorsairPeripheralController/CorsairK65MiniController.cpp b/Controllers/CorsairPeripheralController/CorsairK65MiniController.cpp index 23864712..8853059f 100644 --- a/Controllers/CorsairPeripheralController/CorsairK65MiniController.cpp +++ b/Controllers/CorsairPeripheralController/CorsairK65MiniController.cpp @@ -1,16 +1,21 @@ +/*---------------------------------------------------------*\ +| CorsairK65MiniController.cpp | +| | +| Driver for Corsair K65 Mini keyboard | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "CorsairK65MiniController.h" -/*-----------------------------------------*\ -| CorsairK65MiniController.cpp | -| | -| Driver for Corsair K65 Mini Keyboard | -\*-----------------------------------------*/ - #include "LogManager.h" +#include "StringUtils.h" -CorsairK65MiniController::CorsairK65MiniController(hid_device* dev_handle, const char* path) +CorsairK65MiniController::CorsairK65MiniController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; LightingControl(); } @@ -25,9 +30,9 @@ std::string CorsairK65MiniController::GetDeviceLocation() return("HID: " + location); } -std::string CorsairK65MiniController::GetFirmwareString() +std::string CorsairK65MiniController::GetName() { - return ""; + return(name); } std::string CorsairK65MiniController::GetSerialString() @@ -40,10 +45,7 @@ std::string CorsairK65MiniController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void CorsairK65MiniController::LightingControl() diff --git a/Controllers/CorsairPeripheralController/CorsairK65MiniController.h b/Controllers/CorsairPeripheralController/CorsairK65MiniController.h index c6d7ea4f..7729ed3e 100644 --- a/Controllers/CorsairPeripheralController/CorsairK65MiniController.h +++ b/Controllers/CorsairPeripheralController/CorsairK65MiniController.h @@ -1,9 +1,17 @@ +/*---------------------------------------------------------*\ +| CorsairK65MiniController.cpp | +| | +| Driver for Corsair K65 Mini keyboard | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once -#include "RGBController.h" - #include -#include +#include +#include "RGBController.h" #define PACKET_LENGTH 1025 #define K65_WRITE_COMMAND 0x08 @@ -11,11 +19,10 @@ class CorsairK65MiniController { public: - CorsairK65MiniController(hid_device* dev_handle, const char* path); + CorsairK65MiniController(hid_device* dev_handle, const char* path, std::string dev_name); ~CorsairK65MiniController(); std::string GetDeviceLocation(); - std::string GetFirmwareString(); std::string GetName(); std::string GetSerialString(); void SetLEDs(std::vector colors, std::vector positions); @@ -23,8 +30,8 @@ public: private: hid_device* dev; - std::string firmware_version; std::string location; + std::string name; void LightingControl(); }; diff --git a/Controllers/CorsairPeripheralController/CorsairK95PlatinumXTController.cpp b/Controllers/CorsairPeripheralController/CorsairK95PlatinumXTController.cpp deleted file mode 100644 index 07fbcd0b..00000000 --- a/Controllers/CorsairPeripheralController/CorsairK95PlatinumXTController.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/*-----------------------------------------*\ -| CorsairK195PlatinumXTController.h | -| | -| Driver for Corsair K95 Platinum XT | -| Keyboard | -| Guimard Morgan (morg) 6/07/2022 | -\*-----------------------------------------*/ -#include "CorsairK95PlatinumXTController.h" - -CorsairK95PlatinumXTController::CorsairK95PlatinumXTController(hid_device* dev_handle, const char* path) -{ - dev = dev_handle; - location = path; - - Init(); -} - -CorsairK95PlatinumXTController::~CorsairK95PlatinumXTController() -{ - hid_close(dev); -} - -std::string CorsairK95PlatinumXTController::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string CorsairK95PlatinumXTController::GetFirmwareString() -{ - return ""; -} - -std::string CorsairK95PlatinumXTController::GetName() -{ - return name; -} - -std::string CorsairK95PlatinumXTController::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 CorsairK95PlatinumXTController::Init() -{ - unsigned char usb_buf[K95_PLATINUM_XT_REPORT_LENGTH]; - - memset(usb_buf, 0x00, K95_PLATINUM_XT_REPORT_LENGTH); - usb_buf[0x01] = K95_PLATINUM_XT_REPORT_ID; - usb_buf[0x02] = 0x01; - usb_buf[0x03] = 0x03; - usb_buf[0x05] = 0x02; - hid_write(dev, usb_buf, K95_PLATINUM_XT_REPORT_LENGTH); - - memset(usb_buf, 0x00, K95_PLATINUM_XT_REPORT_LENGTH); - usb_buf[0x01] = K95_PLATINUM_XT_REPORT_ID; - usb_buf[0x02] = 0x02; - usb_buf[0x03] = 0x6E; - hid_write(dev, usb_buf, K95_PLATINUM_XT_REPORT_LENGTH); - - memset(usb_buf, 0x00, K95_PLATINUM_XT_REPORT_LENGTH); - usb_buf[0x01] = K95_PLATINUM_XT_REPORT_ID; - usb_buf[0x02] = 0x0D; - usb_buf[0x03] = 0x01; - usb_buf[0x04] = 0x01; - hid_write(dev, usb_buf, K95_PLATINUM_XT_REPORT_LENGTH); -} - -void CorsairK95PlatinumXTController::SendDirect(const std::vector& colors, const std::vector>& leds_positions) -{ - /*-----------------------------------------------------*\ - | RGB indexes | - \*-----------------------------------------------------*/ - unsigned int red_start = 0x008; - unsigned int grn_start = 0x0A4; - unsigned int blu_start = 0x140; - - /*-----------------------------------------------------*\ - | Fill the color data array | - \*-----------------------------------------------------*/ - unsigned char color_data[K95_PLATINUM_XT_COLOR_DATA_LENGTH]; - memset(color_data, 0x00, K95_PLATINUM_XT_COLOR_DATA_LENGTH); - - color_data[0x00] = 0xD4; - color_data[0x01] = 0x01; - - for(unsigned int c = 0; c < colors.size(); c++) - { - unsigned char red = RGBGetRValue(colors[c]); - unsigned char grn = RGBGetGValue(colors[c]); - unsigned char blu = RGBGetBValue(colors[c]); - unsigned int led_pos = std::get<1>(leds_positions[c]); - - color_data[led_pos + red_start] = red; - color_data[led_pos + grn_start] = grn; - color_data[led_pos + blu_start] = blu; - } - - /*-----------------------------------------------------*\ - | Send the 8 pages of colors | - \*-----------------------------------------------------*/ - unsigned char usb_buf[K95_PLATINUM_XT_REPORT_LENGTH]; - - usb_buf[0x00] = 0x00; - usb_buf[0x01] = K95_PLATINUM_XT_REPORT_ID; - usb_buf[0x02] = 0x06; - usb_buf[0x03] = 0x01; - - for(unsigned int i = 0; i < K95_PLATINUM_XT_NUMBER_OF_PAGES; i++) - { - /*-----------------------------------------------------*\ - | Copy colors in current page | - \*-----------------------------------------------------*/ - memcpy - ( - &usb_buf[0x04], - &color_data[(K95_PLATINUM_XT_REPORT_LENGTH - 4) * i], - K95_PLATINUM_XT_REPORT_LENGTH - 4 - ); - - /*-----------------------------------------------------*\ - | Send the buffer | - \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, K95_PLATINUM_XT_REPORT_LENGTH); - - /*-----------------------------------------------------*\ - | Next pages start with 0x07 | - \*-----------------------------------------------------*/ - usb_buf[0x02] = 0x07; - } - -} diff --git a/Controllers/CorsairPeripheralController/CorsairK95PlatinumXTController.h b/Controllers/CorsairPeripheralController/CorsairK95PlatinumXTController.h deleted file mode 100644 index f2245def..00000000 --- a/Controllers/CorsairPeripheralController/CorsairK95PlatinumXTController.h +++ /dev/null @@ -1,44 +0,0 @@ -/*-----------------------------------------*\ -| CorsairK95PlatinumXTController.h | -| | -| Driver for Corsair K95 Platinum XT | -| Keyboard | -| | -| Guimard Morgan (morg) 6/07/2022 | -\*-----------------------------------------*/ -#pragma once - -#include "RGBController.h" -#include -#include - -#define K95_PLATINUM_XT_REPORT_LENGTH 65 -#define K95_PLATINUM_XT_COLOR_DATA_LENGTH 488 -#define K95_PLATINUM_XT_REPORT_ID 0x08 -#define K95_PLATINUM_XT_NUMBER_OF_PAGES 0x08 -#define K95_PLATINUM_XT_READ_COMMAND 0x02 -#define K95_PLATINUM_XT_DIRECT_START_STREAM 0x07 -#define K95_PLATINUM_XT_DIRECT_BLOCK_STREAM 0x06 - -class CorsairK95PlatinumXTController -{ -public: - CorsairK95PlatinumXTController(hid_device* dev_handle, const char* path); - ~CorsairK95PlatinumXTController(); - - std::string GetDeviceLocation(); - std::string GetFirmwareString(); - std::string GetName(); - std::string GetSerialString(); - - void SendDirect(const std::vector& colors, const std::vector>& leds_positions); - -private: - hid_device* dev; - - std::string firmware_version; - std::string location; - std::string name; - - void Init(); -}; diff --git a/Controllers/CorsairPeripheralController/CorsairPeripheralController.cpp b/Controllers/CorsairPeripheralController/CorsairPeripheralController.cpp index 77636430..0ecfb8c8 100644 --- a/Controllers/CorsairPeripheralController/CorsairPeripheralController.cpp +++ b/Controllers/CorsairPeripheralController/CorsairPeripheralController.cpp @@ -1,16 +1,18 @@ -/*-----------------------------------------*\ -| CorsairPeripheralController.cpp | -| | -| Driver for Corsair RGB keyboard, mouse, | -| and mousemat lighting controller | -| | -| Adam Honse (CalcProgrammer1) 1/9/2020 | -\*-----------------------------------------*/ - -#include "CorsairPeripheralController.h" -#include "LogManager.h" +/*---------------------------------------------------------*\ +| CorsairPeripheralController.cpp | +| | +| Driver for Corsair peripherals | +| | +| Adam Honse (CalcProgrammer1) 09 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "CorsairPeripheralController.h" +#include "LogManager.h" +#include "StringUtils.h" using namespace std::chrono_literals; @@ -59,15 +61,16 @@ static unsigned int keys_k95[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 static unsigned int st100[] = { 0x00, 0x01, 0x02, 0x03, 0x05, 0x06, 0x07, 0x08, 0x04 }; static unsigned int key_mapping_k95_plat_ansi[] = { 0x31, 0x3f, 0x41, 0x42, 0x51, 0x53, 0x55, 0x6f, 0x7e, 0x7f, 0x80, 0x81 }; -static unsigned int key_mapping_k95_plat_iso[] = { 0x3f, 0x41, 0x42, 0x48, 0x50, 0x53, 0x55, 0x6f, 0x7e, 0x7f, 0x80, 0x81 }; +static unsigned int key_mapping_k95_plat_iso[] = { 0x3f, 0x41, 0x42, 0x50, 0x53, 0x55, 0x6f, 0x78, 0x7e, 0x7f, 0x80, 0x81 }; static unsigned int key_mapping_k70_mk2_plat_iso[] = { 0x3f, 0x41, 0x42, 0x50, 0x53, 0x55, 0x6f, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81 }; #define CORSAIR_PERIPHERAL_CONTROLLER_NAME "Corsair peripheral" -CorsairPeripheralController::CorsairPeripheralController(hid_device* dev_handle, const char* path) +CorsairPeripheralController::CorsairPeripheralController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; ReadFirmwareInfo(); @@ -132,10 +135,7 @@ std::string CorsairPeripheralController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void CorsairPeripheralController::SetLEDs(std::vectorcolors) @@ -258,12 +258,12 @@ void CorsairPeripheralController::SetLEDsKeyboardFull(std::vector colo void CorsairPeripheralController::SetLEDsMouse(std::vector colors) { - SubmitMouseColors(colors.size(), &colors[0]); + SubmitMouseColors((unsigned char)colors.size(), &colors[0]); } void CorsairPeripheralController::SetLEDsMousemat(std::vector colors) { - SubmitMousematColors(colors.size(), &colors[0]); + SubmitMousematColors((unsigned char)colors.size(), &colors[0]); } void CorsairPeripheralController::SetLEDsKeyboardLimited(std::vector colors) @@ -329,13 +329,8 @@ void CorsairPeripheralController::SetLEDsKeyboardLimited(std::vector c StreamPacket(2, 60, &data_pkt[60]); StreamPacket(3, 60, &data_pkt[120]); StreamPacket(4, 36, &data_pkt[180]); - - SubmitKeyboardLimitedColors(216); -} -void CorsairPeripheralController::SetName(std::string device_name) -{ - name = device_name; + SubmitKeyboardLimitedColors(216); } void CorsairPeripheralController::SwitchMode(bool software) @@ -374,7 +369,7 @@ void CorsairPeripheralController::SwitchMode(bool software) void CorsairPeripheralController::LightingControl() { - char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; + unsigned char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -412,11 +407,11 @@ void CorsairPeripheralController::LightingControl() usb_buf[0x05] = 0x03; break; } - + /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); + hid_write(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); } /*-----------------------------------------------------*\ @@ -425,7 +420,7 @@ void CorsairPeripheralController::LightingControl() void CorsairPeripheralController::SetupK55AndK95LightingControl() { - char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; + unsigned char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -445,11 +440,11 @@ void CorsairPeripheralController::SetupK55AndK95LightingControl() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); + hid_write(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); unsigned int* skipped_identifiers = key_mapping_k95_plat_ansi; int skipped_identifiers_count = sizeof(key_mapping_k95_plat_ansi) / sizeof(key_mapping_k95_plat_ansi[0]); - + if (physical_layout == CORSAIR_LAYOUT_ISO) { if(logical_layout == CORSAIR_TYPE_K70_MK2) @@ -497,13 +492,13 @@ void CorsairPeripheralController::SetupK55AndK95LightingControl() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); + hid_write(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); } } void CorsairPeripheralController::SpecialFunctionControl() { - char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; + unsigned char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -517,17 +512,17 @@ void CorsairPeripheralController::SpecialFunctionControl() usb_buf[0x01] = CORSAIR_COMMAND_WRITE; usb_buf[0x02] = CORSAIR_PROPERTY_SPECIAL_FUNCTION; usb_buf[0x03] = CORSAIR_LIGHTING_CONTROL_SOFTWARE; - + /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); + hid_write(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); } void CorsairPeripheralController::ReadFirmwareInfo() { int actual; - char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; + unsigned char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; char offset = 0; /*-----------------------------------------------------*\ @@ -547,8 +542,8 @@ void CorsairPeripheralController::ReadFirmwareInfo() | If that fails, repeat the send and read the reply as | | a feature report. | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char*)usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); - actual = hid_read_timeout(dev, (unsigned char*)usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH, 1000); + hid_write(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); + actual = hid_read_timeout(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH, 1000); if(actual == 0) { @@ -564,8 +559,8 @@ void CorsairPeripheralController::ReadFirmwareInfo() usb_buf[0x01] = CORSAIR_COMMAND_READ; usb_buf[0x02] = CORSAIR_PROPERTY_FIRMWARE_INFO; - hid_send_feature_report(dev, (unsigned char*)usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); - actual = hid_get_feature_report(dev, (unsigned char*)usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); + hid_send_feature_report(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); + actual = hid_get_feature_report(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); offset = 1; } @@ -574,14 +569,14 @@ void CorsairPeripheralController::ReadFirmwareInfo() | 0xC0 Device is a keyboard | | 0xC1 Device is a mouse | | 0xC2 Device is a mousepad or headset stand | - \*-----------------------------------------------------*/ - LOG_DEBUG("[%s] Device type %02X", CORSAIR_PERIPHERAL_CONTROLLER_NAME, (unsigned char)usb_buf[0x14 + offset]); + \*-----------------------------------------------------*/ + LOG_DEBUG("[%s] Device type %02X", CORSAIR_PERIPHERAL_CONTROLLER_NAME, usb_buf[0x14 + offset]); - switch((unsigned char)usb_buf[0x14 + offset]) + switch(usb_buf[0x14 + offset]) { case 0xC0: { - unsigned short pid = (unsigned short)(usb_buf[0x0E] << 8) + (unsigned char)(usb_buf[0x0F]); + unsigned short pid = (unsigned short)(usb_buf[0x0E] << 8) + (unsigned short)(usb_buf[0x0F]); /*-----------------------------------------------------*\ | Get the correct Keyboard Type | @@ -619,7 +614,7 @@ void CorsairPeripheralController::ReadFirmwareInfo() | Get the correct Keyboard Layout. | | Currently unused but can be implemented in the future.| \*-----------------------------------------------------*/ - switch((unsigned char)usb_buf[0x17 + offset]) + switch(usb_buf[0x17 + offset]) { case CORSAIR_LAYOUT_ANSI: physical_layout = CORSAIR_LAYOUT_ANSI; @@ -651,7 +646,7 @@ void CorsairPeripheralController::ReadFirmwareInfo() case 0xC2: { - unsigned short pid = (unsigned short)(usb_buf[0x0F] << 8) + (unsigned char)(usb_buf[0x0E]); + unsigned short pid = (unsigned short)(usb_buf[0x0F] << 8) + (unsigned short)(usb_buf[0x0E]); switch(pid) { @@ -659,7 +654,7 @@ void CorsairPeripheralController::ReadFirmwareInfo() type = DEVICE_TYPE_HEADSET_STAND; SpecialFunctionControl(); break; - + default: type = DEVICE_TYPE_MOUSEMAT; SpecialFunctionControl(); @@ -689,7 +684,7 @@ void CorsairPeripheralController::StreamPacket unsigned char* data_ptr ) { - char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; + unsigned char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -712,7 +707,7 @@ void CorsairPeripheralController::StreamPacket /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); + hid_write(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); } void CorsairPeripheralController::SetHardwareMode @@ -822,7 +817,7 @@ void CorsairPeripheralController::SubmitKeyboardFullColors unsigned char finish_val ) { - char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; + unsigned char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -842,7 +837,7 @@ void CorsairPeripheralController::SubmitKeyboardFullColors /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); + hid_write(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); } void CorsairPeripheralController::SubmitKeyboardZonesColors @@ -852,7 +847,7 @@ void CorsairPeripheralController::SubmitKeyboardZonesColors RGBColor right ) { - char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; + unsigned char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -880,7 +875,7 @@ void CorsairPeripheralController::SubmitKeyboardZonesColors /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); + hid_write(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); } void CorsairPeripheralController::SubmitKeyboardLimitedColors @@ -888,7 +883,7 @@ void CorsairPeripheralController::SubmitKeyboardLimitedColors unsigned char byte_count ) { - char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; + unsigned char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -906,7 +901,7 @@ void CorsairPeripheralController::SubmitKeyboardLimitedColors /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); + hid_write(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); } void CorsairPeripheralController::SubmitMouseColors @@ -915,7 +910,7 @@ void CorsairPeripheralController::SubmitMouseColors RGBColor * color_data ) { - char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; + unsigned char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -945,7 +940,7 @@ void CorsairPeripheralController::SubmitMouseColors /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); + hid_write(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); } void CorsairPeripheralController::SubmitMousematColors @@ -954,7 +949,7 @@ void CorsairPeripheralController::SubmitMousematColors RGBColor * color_data ) { - char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; + unsigned char usb_buf[CORSAIR_PERIPHERAL_PACKET_LENGTH]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -984,5 +979,5 @@ void CorsairPeripheralController::SubmitMousematColors | Send packet using feature reports, as headset stand | | seems to not update completely using HID writes | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); + hid_write(dev, usb_buf, CORSAIR_PERIPHERAL_PACKET_LENGTH); } diff --git a/Controllers/CorsairPeripheralController/CorsairPeripheralController.h b/Controllers/CorsairPeripheralController/CorsairPeripheralController.h index ee8668af..fc16e7b2 100644 --- a/Controllers/CorsairPeripheralController/CorsairPeripheralController.h +++ b/Controllers/CorsairPeripheralController/CorsairPeripheralController.h @@ -1,20 +1,20 @@ -/*-----------------------------------------*\ -| CorsairPeripheralController.h | -| | -| Definitions and types for Corsair RGB | -| keyboard, mouse, and mousemat lighting | -| controller | -| | -| Adam Honse (CalcProgrammer1) 1/9/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| CorsairPeripheralController.h | +| | +| Driver for Corsair peripherals | +| | +| Adam Honse (CalcProgrammer1) 09 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + #define CORSAIR_PERIPHERAL_PACKET_LENGTH 65 enum @@ -94,7 +94,7 @@ enum class CorsairPeripheralController { public: - CorsairPeripheralController(hid_device* dev_handle, const char* path); + CorsairPeripheralController(hid_device* dev_handle, const char* path, std::string dev_name); ~CorsairPeripheralController(); int GetLogicalLayout(); @@ -110,7 +110,6 @@ public: void SetLEDsKeyboardLimited(std::vector colors); void SetLEDsMouse(std::vector colors); void SetLEDsMousemat(std::vector colors); - void SetName(std::string device_name); void SetHardwareMode ( int mode_value, @@ -139,7 +138,7 @@ private: void SpecialFunctionControl(); void ReadFirmwareInfo(); - + void StreamPacket ( unsigned char packet_id, diff --git a/Controllers/CorsairPeripheralController/CorsairPeripheralControllerDetect.cpp b/Controllers/CorsairPeripheralController/CorsairPeripheralControllerDetect.cpp index ccbc6ef7..67d32f8d 100644 --- a/Controllers/CorsairPeripheralController/CorsairPeripheralControllerDetect.cpp +++ b/Controllers/CorsairPeripheralController/CorsairPeripheralControllerDetect.cpp @@ -1,9 +1,17 @@ +/*---------------------------------------------------------*\ +| CorsairPeripheralControllerDetect.cpp | +| | +| Driver for Corsair peripherals | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + /*-----------------------------------------------------*\ | OpenRGB includes | \*-----------------------------------------------------*/ -#include +#include #include "Detector.h" -#include "CorsairK55RGBPROXTController.h" #include "LogManager.h" #include "RGBController.h" @@ -11,10 +19,8 @@ | Corsair Peripheral specific includes | \*-----------------------------------------------------*/ #include "RGBController_CorsairPeripheral.h" -#include "RGBController_CorsairK100.h" #include "RGBController_CorsairK55RGBPROXT.h" #include "RGBController_CorsairK65Mini.h" -#include "RGBController_CorsairK95PlatinumXT.h" #define CORSAIR_PERIPHERAL_CONTROLLER_NAME "Corsair peripheral" @@ -34,7 +40,7 @@ #define CORSAIR_K65_LUX_RGB_PID 0x1B37 #define CORSAIR_K65_RGB_RAPIDFIRE_PID 0x1B39 -#define CORSAIR_K68_RGB 0x1B4F +#define CORSAIR_K68_RGB_PID 0x1B4F #define CORSAIR_K70_RGB_PID 0x1B13 #define CORSAIR_K70_LUX_RGB_PID 0x1B33 @@ -45,6 +51,7 @@ #define CORSAIR_K95_RGB_PID 0x1B11 #define CORSAIR_K95_PLATINUM_PID 0x1B2D +#define CORSAIR_K95_PLATINUM_SE_PID 0x1B82 #define CORSAIR_STRAFE_PID 0x1B20 #define CORSAIR_STRAFE_RED_PID 0x1B44 @@ -54,6 +61,8 @@ | Non-RGB Keyboard product IDs | \*-----------------------------------------------------*/ #define CORSAIR_K70_LUX_PID 0x1B36 +#define CORSAIR_K68_RED_PID 0x1B3F +#define CORSAIR_K68_RED_SHADOW_PID 0x1BA5 /*-----------------------------------------------------*\ | Mouse product IDs | @@ -85,13 +94,6 @@ \*-----------------------------------------------------*/ #define CORSAIR_ST100_PID 0x0A34 -/*-----------------------------------------------------*\ -| Corsair K100 Keyboard product ID | -| This keyboard uses a separate driver | -\*-----------------------------------------------------*/ -#define CORSAIR_K100_OPTICAL_PID 0x1B7C -#define CORSAIR_K100_MXRED_PID 0x1B7D - /*-----------------------------------------------------*\ | Corsair K55 RGB PRO XT Keyboard product ID | | This keyboard uses a separate driver | @@ -104,42 +106,15 @@ \*-----------------------------------------------------*/ #define CORSAIR_K65_MINI_PID 0x1BAF -/*-----------------------------------------------------*\ -| Corsair K95 Platinum XT Keyboard product ID | -| This keyboard uses a separate driver | -\*-----------------------------------------------------*/ -#define CORSAIR_K95_PLATINUM_XT_PID 0x1B89 - -void DetectCorsairK100Controllers(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - - if(dev) - { - CorsairK100Controller* controller = new CorsairK100Controller(dev, info->path); - controller->SetName(name); - - if(controller->GetKeyboardType() != CORSAIR_TYPE_UNKNOWN) - { - RGBController_CorsairK100* rgb_controller = new RGBController_CorsairK100(controller); - ResourceManager::get()->RegisterRGBController(rgb_controller); - } - else - { - delete controller; - } - } -} /* DetectCorsairPeripheralControllers() */ - void DetectCorsairK55RGBPROXTControllers(hid_device_info* info, const std::string& name) { hid_device* dev = hid_open_path(info->path); if(dev) { - CorsairK55RGBPROXTController* controller = new CorsairK55RGBPROXTController(dev, info->path); + CorsairK55RGBPROXTController* controller = new CorsairK55RGBPROXTController(dev, info->path, name); RGBController_CorsairK55RGBPROXT* rgb_controller = new RGBController_CorsairK55RGBPROXT(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } /* DetectCorsairK55RGBPROXTControllers() */ @@ -150,22 +125,9 @@ void DetectCorsairK65MiniControllers(hid_device_info* info, const std::string& n if(dev) { - CorsairK65MiniController* controller = new CorsairK65MiniController(dev, info->path); + CorsairK65MiniController* controller = new CorsairK65MiniController(dev, info->path, name); RGBController_CorsairK65Mini* rgb_controller = new RGBController_CorsairK65Mini(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} /* DetectCorsairK65MiniControllers() */ -void DetectCorsairK95PlatinumXTControllers(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - - if(dev) - { - CorsairK95PlatinumXTController* controller = new CorsairK95PlatinumXTController(dev, info->path); - RGBController_CorsairK95PlatinumXT* rgb_controller = new RGBController_CorsairK95PlatinumXT(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } /* DetectCorsairK65MiniControllers() */ @@ -185,8 +147,7 @@ void DetectCorsairPeripheralControllers(hid_device_info* info, const std::string { LOG_DEBUG("[%s] Device opened. VID/PID %02X:%02X", CORSAIR_PERIPHERAL_CONTROLLER_NAME, info->vendor_id , info->product_id); - CorsairPeripheralController* controller = new CorsairPeripheralController(dev, info->path); - controller->SetName(name); + CorsairPeripheralController* controller = new CorsairPeripheralController(dev, info->path, name); if(controller->GetDeviceType() != DEVICE_TYPE_UNKNOWN) { @@ -212,7 +173,9 @@ REGISTER_HID_DETECTOR_IP("Corsair K55 RGB", DetectCorsairPeriphe 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); -REGISTER_HID_DETECTOR_IP("Corsair K68 RGB", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_K68_RGB, 1, 0xFFC2); +REGISTER_HID_DETECTOR_IP("Corsair K68 RGB", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_K68_RGB_PID, 1, 0xFFC2); +REGISTER_HID_DETECTOR_IP("Corsair K68 RED", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_K68_RED_PID, 1, 0xFFC2); +REGISTER_HID_DETECTOR_IP("Corsair K68 RED SHADOW", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_K68_RED_SHADOW_PID, 1, 0xFFC2); REGISTER_HID_DETECTOR_IP("Corsair K70 RGB", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_K70_RGB_PID, 1, 0xFFC2); REGISTER_HID_DETECTOR_IP("Corsair K70 LUX", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_K70_LUX_PID, 1, 0xFFC2); REGISTER_HID_DETECTOR_IP("Corsair K70 LUX RGB", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_K70_LUX_RGB_PID, 1, 0xFFC2); @@ -222,6 +185,7 @@ REGISTER_HID_DETECTOR_IP("Corsair K70 RGB MK.2 SE", DetectCorsairPeriphe REGISTER_HID_DETECTOR_IP("Corsair K70 RGB MK.2 Low Profile",DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_K70_RGB_MK2_LP_PID, 1, 0xFFC2); REGISTER_HID_DETECTOR_IP("Corsair K95 RGB", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_K95_RGB_PID, 1, 0xFFC2); REGISTER_HID_DETECTOR_IP("Corsair K95 RGB PLATINUM", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_K95_PLATINUM_PID, 1, 0xFFC2); +REGISTER_HID_DETECTOR_IP("Corsair K95 RGB PLATINUM SE", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_K95_PLATINUM_SE_PID, 1, 0xFFC2); REGISTER_HID_DETECTOR_IP("Corsair Strafe", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_STRAFE_PID, 1, 0xFFC2); REGISTER_HID_DETECTOR_IP("Corsair Strafe Red", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_STRAFE_RED_PID, 1, 0xFFC2); REGISTER_HID_DETECTOR_IP("Corsair Strafe MK.2", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_STRAFE_MK2_PID, 1, 0xFFC2); @@ -259,12 +223,6 @@ REGISTER_HID_DETECTOR_P("Corsair ST100 RGB", DetectCorsairPeriphe REGISTER_HID_DETECTOR_I("Corsair ST100 RGB", DetectCorsairPeripheralControllers, CORSAIR_VID, CORSAIR_ST100_PID, 0); #endif -/*-----------------------------------------------------------------------------------------------------*\ -| Corsair K100 Keyboard | -\*-----------------------------------------------------------------------------------------------------*/ -REGISTER_HID_DETECTOR_IP("Corsair K100", DetectCorsairK100Controllers, CORSAIR_VID, CORSAIR_K100_OPTICAL_PID, 1, 0xFF42); -REGISTER_HID_DETECTOR_IP("Corsair K100", DetectCorsairK100Controllers, CORSAIR_VID, CORSAIR_K100_MXRED_PID, 1, 0xFF42); - /*-----------------------------------------------------------------------------------------------------*\ | Corsair K65 Mini Keyboard | \*-----------------------------------------------------------------------------------------------------*/ @@ -274,9 +232,3 @@ REGISTER_HID_DETECTOR_I("Corsair K65 Mini", DetectCorsairK65Mini | Corsair K55 RGB PRO XT Keyboard | \*-----------------------------------------------------------------------------------------------------*/ REGISTER_HID_DETECTOR_IP("Corsair K55 RGB PRO XT", DetectCorsairK55RGBPROXTControllers, CORSAIR_VID, CORSAIR_K55_RGB_PRO_XT_PID, 1, 0xFF42); - - -/*-----------------------------------------------------------------------------------------------------*\ -| Corsair K95 Platinum XT Keyboard | -\*-----------------------------------------------------------------------------------------------------*/ -REGISTER_HID_DETECTOR_IP("Corsair K95 RGB PLATINUM XT", DetectCorsairK95PlatinumXTControllers, CORSAIR_VID, CORSAIR_K95_PLATINUM_XT_PID, 1, 0xFF42); diff --git a/Controllers/CorsairPeripheralController/RGBController_CorsairK100.cpp b/Controllers/CorsairPeripheralController/RGBController_CorsairK100.cpp deleted file mode 100644 index 2edca35c..00000000 --- a/Controllers/CorsairPeripheralController/RGBController_CorsairK100.cpp +++ /dev/null @@ -1,383 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_CorsairK100.cpp | -| | -| Driver for Corsair K100 Keyboard | -\*-----------------------------------------*/ - -#include "RGBControllerKeyNames.h" -#include "RGBController_CorsairK100.h" -#include "LogManager.h" - -using namespace std::chrono_literals; - -#define NA 0xFFFFFFFF - -static unsigned int matrix_map_k100[7][24] = - { { NA, 112, NA, 8, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 16, NA, NA, NA,}, - { 113, 0, NA, 10, 18, 28, 36, NA, 46, 55, 64, 74, NA, 84, 93, 102, 6, 15, 24, 33, 26, 35, 44, 53 }, - { 114, 1, 11, 19, 29, 37, 47, 56, 65, 75, 85, 94, NA, 103, 7, 25, NA, 42, 51, 60, 62, 72, 82, 91 }, - { 115, 2, NA, 12, 20, 30, 38, NA, 48, 57, 66, 76, 86, 95, 104, 70, 80, 34, 43, 52, 9, 17, 27, 100 }, - { 116, 3, NA, 13, 21, 31, 39, NA, 49, 58, 67, 77, 87, 96, 105, 98, 111, NA, NA, NA, 45, 54, 63, NA }, - { 117, 4, 110, 22, 32, 40, 50, NA, 59, NA, 68, 78, 88, 97, 106, 61, NA, NA, 81, NA, 73, 83, 92, 108 }, - { 118, 5, 14, 23, NA, NA, NA, NA, 41, NA, NA, NA, NA, 69, 79, 89, 71, 90, 99, 107, 101, NA, 109, NA } }; - -static const char* led_names_k100[] = -{ - KEY_EN_ESCAPE, //0 - KEY_EN_BACK_TICK, //1 - KEY_EN_TAB, //2 - KEY_EN_CAPS_LOCK, //3 - KEY_EN_LEFT_SHIFT, //4 - KEY_EN_LEFT_CONTROL, //5 - KEY_EN_F12, //6 - KEY_EN_EQUALS, //7 - "Key: Lock", //8 - KEY_EN_NUMPAD_7, //9 - KEY_EN_F1, //12 - KEY_EN_1, //13 - KEY_EN_Q, //14 - KEY_EN_A, //15 - KEY_EN_LEFT_WINDOWS, //17 - KEY_EN_PRINT_SCREEN, //18 - KEY_EN_MEDIA_MUTE, //20 - KEY_EN_NUMPAD_8, //21 - KEY_EN_F2, //24 - KEY_EN_2, //25 - KEY_EN_W, //26 - KEY_EN_S, //27 - KEY_EN_Z, //28 - KEY_EN_LEFT_ALT, //29 - KEY_EN_SCROLL_LOCK, //30 - KEY_EN_BACKSPACE, //31 - KEY_EN_MEDIA_STOP, //32 - KEY_EN_NUMPAD_9, //33 - KEY_EN_F3, //36 - KEY_EN_3, //37 - KEY_EN_E, //38 - KEY_EN_D, //39 - KEY_EN_X, //40 - KEY_EN_PAUSE_BREAK, //42 - KEY_EN_DELETE, //43 - KEY_EN_MEDIA_PREVIOUS, //44 - KEY_EN_F4, //48 - KEY_EN_4, //49 - KEY_EN_R, //50 - KEY_EN_F, //51 - KEY_EN_C, //52 - KEY_EN_SPACE, //53 - KEY_EN_INSERT, //54 - KEY_EN_END, //55 - KEY_EN_MEDIA_PLAY_PAUSE, //56 - KEY_EN_NUMPAD_4, //57 - KEY_EN_F5, //60 - KEY_EN_5, //61 - KEY_EN_T, //62 - KEY_EN_G, //63 - KEY_EN_V, //64 - KEY_EN_HOME, //66 - KEY_EN_PAGE_DOWN, //67 - KEY_EN_MEDIA_NEXT, //68 - KEY_EN_NUMPAD_5, //69 - KEY_EN_F6, //72 - KEY_EN_6, //73 - KEY_EN_Y, //74 - KEY_EN_H, //75 - KEY_EN_B, //76 - KEY_EN_PAGE_UP, //78 - KEY_EN_RIGHT_SHIFT, //79 - KEY_EN_NUMPAD_LOCK, //80 - KEY_EN_NUMPAD_6, //81 - KEY_EN_F7, //84 - KEY_EN_7, //85 - KEY_EN_U, //86 - KEY_EN_J, //87 - KEY_EN_N, //88 - KEY_EN_RIGHT_ALT, //89 - KEY_EN_RIGHT_BRACKET, //90 - KEY_EN_RIGHT_CONTROL, //91 - KEY_EN_NUMPAD_DIVIDE, //92 - KEY_EN_NUMPAD_1, //93 - KEY_EN_F8, //96 - KEY_EN_8, //97 - KEY_EN_I, //98 - KEY_EN_K, //99 - KEY_EN_M, //100 - KEY_EN_RIGHT_WINDOWS, //101 - KEY_EN_ANSI_BACK_SLASH, //102 - KEY_EN_UP_ARROW, //103 - KEY_EN_NUMPAD_TIMES, //104 - KEY_EN_NUMPAD_2, //105 - KEY_EN_F9, //108 - KEY_EN_9, //109 - KEY_EN_O, //110 - KEY_EN_L, //111 - KEY_EN_COMMA, //112 - KEY_EN_MENU, //113 - KEY_EN_LEFT_ARROW, //115 - KEY_EN_NUMPAD_MINUS, //116 - KEY_EN_NUMPAD_3, //117 - KEY_EN_F10, //120 - KEY_EN_0, //121 - KEY_EN_P, //122 - KEY_EN_SEMICOLON, //123 - KEY_EN_PERIOD, //124 - KEY_EN_ANSI_ENTER, //126 - KEY_EN_DOWN_ARROW, //127 - KEY_EN_NUMPAD_PLUS, //128 - KEY_EN_NUMPAD_0, //129 - KEY_EN_F11, //132 - KEY_EN_MINUS, //133 - KEY_EN_LEFT_BRACKET, //134 - KEY_EN_QUOTE, //135 - KEY_EN_FORWARD_SLASH, //136 - // "Key: Brightness", //137 - KEY_EN_RIGHT_ARROW, //139 - KEY_EN_NUMPAD_ENTER, //140 - KEY_EN_NUMPAD_PERIOD, //141 - "Key: / (ISO)", - KEY_EN_ISO_BACK_SLASH, - "Key: Preset", - "Key: G1", - "Key: G2", - "Key: G3", - "Key: G4", - "Key: G5", - "Key: G6", -}; -static const char* led_names_lightbar[] = -{ - "Underglow 1", - "Underglow 2", - "Underglow 3", - "Underglow 4", - "Underglow 5", - "Underglow 6", - "Underglow 7", - "Underglow 8", - "Underglow 9", - "Underglow 10", - "Underglow 11", - "Underglow 12", - "Underglow 13", - "Underglow 14", - "Underglow 15", - "Underglow 16", - "Underglow 17", - "Underglow 18", - "Underglow 19", - "Underglow 20", - "Underglow 21", - "Underglow 22", - "Underglow 23", - "Underglow 24", - "Underglow 25", - "Underglow 26", - "Underglow 27", - "Underglow 28", - "Underglow 29", - "Underglow 30", - "Underglow 31", - "Underglow 32", - "Underglow 33", - "Underglow 34", - "Underglow 35", - "Underglow 36", - "Underglow 37", - "Underglow 38", - "Underglow 39", - "Underglow 40", - "Underglow 41", - "Underglow 42", - "Underglow 43", - "Underglow 44", -}; -static const char* led_names_nameplate[] = -{ - "Nameplate 1", - "Nameplate 2", - "Nameplate 3", - "Nameplate 4", - "Nameplate 5", - "Nameplate 6", - "Nameplate 7", - "Nameplate 8", - "Nameplate 9", -}; -static const char* led_names_logo[] = -{ - "Logo", - "Logo", - "Logo", -}; - -typedef struct -{ - const char* name; - const unsigned int size; - const zone_type type; - const char** led_names; - matrix_map_type* matrix; -} led_zone_layout; - -/**------------------------------------------------------------------*\ - @name Corsair K100 Keyboard - @category Keyboard - @type USB - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectCorsairK100Controllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_CorsairK100::RGBController_CorsairK100(CorsairK100Controller* controller_ptr) -{ - controller = controller_ptr; - - name = controller->GetName(); - vendor = "Corsair"; - description = "Corsair K100 Keyboard Device"; - type = DEVICE_TYPE_KEYBOARD; - version = controller->GetFirmwareString(); - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - logical_layout = controller->GetKeyboardType(); - - 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 Corsair K100 requires a packet within | - | 1 minutes of sending the lighting change in order | - | to not revert back into rainbow mode. Start a thread | - | to continuously send a keepalive packet every 50 sec | - \*-----------------------------------------------------*/ - keepalive_thread_run = true; - keepalive_thread = new std::thread(&RGBController_CorsairK100::KeepaliveThread, this); -} - -RGBController_CorsairK100::~RGBController_CorsairK100() -{ - /*-----------------------------------------------------*\ - | Close keepalive thread | - \*-----------------------------------------------------*/ - keepalive_thread_run = false; - keepalive_thread->join(); - delete keepalive_thread; - - /*---------------------------------------------------------*\ - | Delete the matrix map | - \*---------------------------------------------------------*/ - for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++) - { - if(zones[zone_index].type == ZONE_TYPE_MATRIX) - { - delete zones[zone_index].matrix_map; - } - } - - delete controller; -} - -void RGBController_CorsairK100::SetupZones() -{ - std::vector selected_zone; - - switch(logical_layout) - { - case CORSAIR_TYPE_K100: - selected_zone.push_back({ZONE_EN_KEYBOARD, 119, ZONE_TYPE_MATRIX, led_names_k100, new matrix_map_type{7, 24, (unsigned int *)&matrix_map_k100}}); - selected_zone.push_back({"Underglow", 44, ZONE_TYPE_LINEAR, led_names_lightbar, NULL}); - selected_zone.push_back({"Nameplate", 9, ZONE_TYPE_LINEAR, led_names_nameplate, NULL}); - selected_zone.push_back({"Logo", 3, ZONE_TYPE_LINEAR, led_names_logo, NULL}); - break; - - case CORSAIR_TYPE_UNKNOWN: - break; - } - - /*---------------------------------------------------------*\ - | Set up zones | - \*---------------------------------------------------------*/ - for(unsigned int zone_idx = 0; zone_idx < selected_zone.size(); zone_idx++) - { - zone new_zone; - - new_zone.name = selected_zone[zone_idx].name; - new_zone.type = selected_zone[zone_idx].type; - new_zone.leds_min = selected_zone[zone_idx].size; - new_zone.leds_max = selected_zone[zone_idx].size; - new_zone.leds_count = selected_zone[zone_idx].size; - - if (new_zone.type == ZONE_TYPE_MATRIX) - { - new_zone.matrix_map = selected_zone[zone_idx].matrix; - } - else - { - new_zone.matrix_map = NULL; - } - - zones.push_back(new_zone); - - for(unsigned int led_idx = 0; led_idx < selected_zone[zone_idx].size; led_idx++) - { - led new_led; - new_led.name = selected_zone[zone_idx].led_names[led_idx]; - leds.push_back(new_led); - } - } - - SetupColors(); -} - -void RGBController_CorsairK100::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_CorsairK100::DeviceUpdateLEDs() -{ - last_update_time = std::chrono::steady_clock::now(); - - controller->SetLEDs(colors); -} - -void RGBController_CorsairK100::UpdateZoneLEDs(int /*zone*/) -{ - controller->SetLEDs(colors); -} - -void RGBController_CorsairK100::UpdateSingleLED(int /*led*/) -{ - controller->SetLEDs(colors); -} - -void RGBController_CorsairK100::DeviceUpdateMode() -{ - -} - -void RGBController_CorsairK100::KeepaliveThread() -{ - while(keepalive_thread_run.load()) - { - if(active_mode == 0) - { - if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50000)) - { - DeviceUpdateLEDs(); - } - } - std::this_thread::sleep_for(3000ms); - } -} diff --git a/Controllers/CorsairPeripheralController/RGBController_CorsairK100.h b/Controllers/CorsairPeripheralController/RGBController_CorsairK100.h deleted file mode 100644 index 7779f461..00000000 --- a/Controllers/CorsairPeripheralController/RGBController_CorsairK100.h +++ /dev/null @@ -1,40 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_CorsairK100.cpp | -| | -| Driver for Corsair K100 Keyboard | -\*-----------------------------------------*/ - -#ifndef RGBCONTROLLER_CORSAIRK100_H -#define RGBCONTROLLER_CORSAIRK100_H - -#include "RGBController.h" -#include "CorsairK100Controller.h" - -class RGBController_CorsairK100 : public RGBController -{ -public: - RGBController_CorsairK100(CorsairK100Controller* controller_ptr); - ~RGBController_CorsairK100(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - void KeepaliveThread(); - -private: - CorsairK100Controller* controller; - CorsairKeyboardType logical_layout; - - std::thread* keepalive_thread; - std::atomic keepalive_thread_run; - std::chrono::time_point last_update_time; - -}; - -#endif // RGBCONTROLLER_CORSAIRK100_H diff --git a/Controllers/CorsairPeripheralController/RGBController_CorsairK55RGBPROXT.cpp b/Controllers/CorsairPeripheralController/RGBController_CorsairK55RGBPROXT.cpp index 755ed8a3..34834ca6 100644 --- a/Controllers/CorsairPeripheralController/RGBController_CorsairK55RGBPROXT.cpp +++ b/Controllers/CorsairPeripheralController/RGBController_CorsairK55RGBPROXT.cpp @@ -1,8 +1,11 @@ -/*--------------------------------------------*\ -| RGBController_CorsairK55RGBPROXT.cpp | -| | -| Driver for Corsair K55 RGB PRO XT Keyboard | -\*--------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairK55RGBPROXT.cpp | +| | +| RGBController for Corsair K55 RGB PRO XT keyboard | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CorsairK55RGBPROXT.h" #include "RGBControllerKeyNames.h" @@ -199,14 +202,14 @@ std::vector key_names = RGBController_CorsairK55RGBPROXT::RGBController_CorsairK55RGBPROXT(CorsairK55RGBPROXTController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - vendor = "Corsair"; - description = "Corsair K55 RGB PRO XT Keyboard Device"; - type = DEVICE_TYPE_KEYBOARD; - version = controller->GetFirmwareString(); - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "Corsair"; + description = "Corsair K55 RGB PRO XT Keyboard Device"; + type = DEVICE_TYPE_KEYBOARD; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; Direct.name = "Direct"; diff --git a/Controllers/CorsairPeripheralController/RGBController_CorsairK55RGBPROXT.h b/Controllers/CorsairPeripheralController/RGBController_CorsairK55RGBPROXT.h index bafb7a33..ef0a62e0 100644 --- a/Controllers/CorsairPeripheralController/RGBController_CorsairK55RGBPROXT.h +++ b/Controllers/CorsairPeripheralController/RGBController_CorsairK55RGBPROXT.h @@ -1,11 +1,13 @@ -/*--------------------------------------------*\ -| RGBController_CorsairK55RGBPROXT.cpp | -| | -| Driver for Corsair K55 RGB PRO XT Keyboard | -\*--------------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairK55RGBPROXTController.h | +| | +| Driver for Corsair K55 RGB PRO XT keyboard | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#ifndef RGBCONTROLLER_CORSAIRK55RGBPROXT_H -#define RGBCONTROLLER_CORSAIRK55RGBPROXT_H +#pragma once #include "RGBController.h" #include "CorsairK55RGBPROXTController.h" @@ -33,5 +35,3 @@ private: std::atomic keepalive_thread_run; std::chrono::time_point last_update_time; }; - -#endif // RGBCONTROLLER_CORSAIRK55RGBPROXT_H diff --git a/Controllers/CorsairPeripheralController/RGBController_CorsairK65Mini.cpp b/Controllers/CorsairPeripheralController/RGBController_CorsairK65Mini.cpp index af0c9ea6..e036afa0 100644 --- a/Controllers/CorsairPeripheralController/RGBController_CorsairK65Mini.cpp +++ b/Controllers/CorsairPeripheralController/RGBController_CorsairK65Mini.cpp @@ -1,10 +1,13 @@ -#include "RGBController_CorsairK65Mini.h" -/*-----------------------------------------*\ -| RGBController_CorsairK65Mini.cpp | -| | -| Driver for Corsair K65 Mini Keyboard | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairK65Mini.cpp | +| | +| RGBController for Corsair K65 Mini keyboard | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include "RGBController_CorsairK65Mini.h" #include "LogManager.h" #include "RGBControllerKeyNames.h" @@ -133,21 +136,20 @@ std::vector> keys = RGBController_CorsairK65Mini::RGBController_CorsairK65Mini(CorsairK65MiniController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Corsair K65 Mini Keyboard Device"; - vendor = "Corsair"; - description = name; - type = DEVICE_TYPE_KEYBOARD; - version = controller->GetFirmwareString(); - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetName(); + vendor = "Corsair"; + description = "Corsair K65 Mini Keyboard Device"; + type = DEVICE_TYPE_KEYBOARD; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + 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(); diff --git a/Controllers/CorsairPeripheralController/RGBController_CorsairK65Mini.h b/Controllers/CorsairPeripheralController/RGBController_CorsairK65Mini.h index f2d2f887..61714b43 100644 --- a/Controllers/CorsairPeripheralController/RGBController_CorsairK65Mini.h +++ b/Controllers/CorsairPeripheralController/RGBController_CorsairK65Mini.h @@ -1,3 +1,12 @@ +/*---------------------------------------------------------*\ +| RGBController_CorsairK65Mini.h | +| | +| RGBController for Corsair K65 Mini keyboard | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include "RGBController.h" diff --git a/Controllers/CorsairPeripheralController/RGBController_CorsairK95PlatinumXT.cpp b/Controllers/CorsairPeripheralController/RGBController_CorsairK95PlatinumXT.cpp deleted file mode 100644 index fb183b39..00000000 --- a/Controllers/CorsairPeripheralController/RGBController_CorsairK95PlatinumXT.cpp +++ /dev/null @@ -1,357 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_CorsairK95PlatinumXT.h | -| | -| | -| Guimard Morgan (morg) 6/07/2022 | -\*-----------------------------------------*/ - -#include "RGBControllerKeyNames.h" -#include "RGBController_CorsairK95PlatinumXT.h" -#include "RGBControllerKeyNames.h" - -#define NA 0xFFFFFFFF - -#define K95_PLATINUM_BAR_LENGTH 19 -#define K95_PLATINUM_XT_HEIGHT 7 -#define K95_PLATINUM_XT_WIDTH 23 - -static unsigned int k95_platinum_xt_matrix_map[K95_PLATINUM_XT_HEIGHT][K95_PLATINUM_XT_WIDTH] = -{ - { NA, NA, NA, NA, 22, 28, 34, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 96, NA, NA, NA}, - { 0, 6, NA, 16, 23, 29, 35, NA, 45, 50, 55, 60, 66, 72, 76, 78, 83, 87, 92, 97, 103, 108, 114}, - { 1, 7, 12, 17, 24, 30, 36, 40, 46, 51, 56, 61, 67, 73, NA, 79, 84, 88, 93, 98, 104, 109, 115}, - { 2, 8, 13, 18, 25, 31, 37, 41, 47, 52, 57, 62, 68, 74, NA, 80, 85, 89, 94, 99, 105, 110, 116}, - { 3, 9, 14, 19, 26, 32, 38, 42, 48, 53, 58, 63, 69, NA, NA, 81, NA, NA, NA, 100, 106, 111, NA}, - { 4, 10, NA, 20, 27, 33, 39, 43, 49, 54, 59, 64, 70, NA, 77, NA, NA, 90, NA, 101, 107, 112, 117}, - { 5, 11, 15, 21, NA, NA, NA, 44, NA, NA, NA, 65, 71, 75, NA, 82, 86, 91, 95, 102, NA, 113, NA} -}; - - -static std::vector> k95_platinum_xt_leds_names_and_positions = -{ - // Top Bar - {"LED: 1", 133}, - {"LED: 2", 134}, - {"LED: 3", 135}, - {"LED: 4", 136}, - {"LED: 5", 137}, - {"LED: 6", 138}, - {"LED: 7", 139}, - {"LED: 8", 140}, - {"LED: 9", 141}, - {"LED: 10", 142}, - {"LED: 11", 143}, - {"LED: 12", 144}, - {"LED: 13", 145}, - {"LED: 14", 146}, - {"LED: 15", 147}, - {"LED: 16", 148}, - {"LED: 17", 149}, - {"LED: 18", 150}, - {"LED: 19", 151}, - - // COL 1 - {"Key: G1", 127}, - {"Key: G2", 128}, - {"Key: G3", 129}, - {"Key: G4", 130}, - {"Key: G5", 131}, - {"Key: G6", 132}, - - // COL 2 - {KEY_EN_ESCAPE, 37}, - {KEY_EN_BACK_TICK, 49}, - {KEY_EN_TAB, 39}, - {KEY_EN_CAPS_LOCK, 53}, - {KEY_EN_LEFT_SHIFT, 102}, - {KEY_EN_LEFT_CONTROL, 101}, - - // COL 3 - {KEY_EN_1, 26}, - {KEY_EN_Q, 16}, - {KEY_EN_A, 0}, - {KEY_EN_LEFT_WINDOWS, 104}, - - // COL 4 - {KEY_EN_F1, 54}, - {KEY_EN_2, 27}, - {KEY_EN_W, 22}, - {KEY_EN_S, 18}, - {KEY_EN_Z, 25}, - {KEY_EN_LEFT_ALT, 103}, - - // COL 5 - {"Key: User", 124}, - {KEY_EN_F2, 55}, - {KEY_EN_3, 28}, - {KEY_EN_E, 4}, - {KEY_EN_D, 3}, - {KEY_EN_X, 23}, - - // COL 6 - {"Key: Brightness", 109}, - {KEY_EN_F3, 56}, - {KEY_EN_4, 29}, - {KEY_EN_R, 17}, - {KEY_EN_F, 5}, - {KEY_EN_C, 2}, - - // COL 7 - {"Key: Lock", 110}, - {KEY_EN_F4, 57}, - {KEY_EN_5, 30}, - {KEY_EN_T, 19}, - {KEY_EN_G, 6}, - {KEY_EN_V, 21}, - - // COL 8 - {KEY_EN_6, 31}, - {KEY_EN_Y, 24}, - {KEY_EN_H, 7}, - {KEY_EN_B, 1}, - {KEY_EN_SPACE, 40}, - - // COL 9 - {KEY_EN_F5, 58}, - {KEY_EN_7, 32}, - {KEY_EN_U, 20}, - {KEY_EN_J, 9}, - {KEY_EN_N, 13}, - - // COL 10 - {KEY_EN_F6, 59}, - {KEY_EN_8, 33}, - {KEY_EN_I, 8}, - {KEY_EN_K, 10}, - {KEY_EN_M, 12}, - - // COL 11 - {KEY_EN_F7, 60}, - {KEY_EN_9, 34}, - {KEY_EN_O, 14}, - {KEY_EN_L, 11}, - {KEY_EN_COMMA, 50}, - - // COL 12 - {KEY_EN_F8, 61}, - {KEY_EN_0, 35}, - {KEY_EN_P, 15}, - {KEY_EN_SEMICOLON, 47}, - {KEY_EN_PERIOD, 51}, - {KEY_EN_RIGHT_ALT, 107}, - - // COL 13 - {KEY_EN_F9, 62}, - {KEY_EN_MINUS, 41}, - {KEY_EN_LEFT_BRACKET, 43}, - {KEY_EN_QUOTE, 48}, - {KEY_EN_FORWARD_SLASH, 52}, - {KEY_EN_RIGHT_WINDOWS, 108}, - - // COL 14 - {KEY_EN_F10, 63}, - {KEY_EN_EQUALS, 42}, - {KEY_EN_RIGHT_BRACKET, 44}, - {KEY_EN_MENU, 97}, - - // COL 15 - {KEY_EN_F11, 64}, - {KEY_EN_RIGHT_SHIFT, 106}, - - // COL 16 - {KEY_EN_F12, 65}, - {KEY_EN_BACKSPACE, 38}, - {KEY_EN_ANSI_BACK_SLASH, 45}, - {KEY_EN_ANSI_ENTER, 36}, - {KEY_EN_RIGHT_CONTROL, 105}, - - - // COL 17 - {KEY_EN_PRINT_SCREEN, 66}, - {KEY_EN_INSERT, 69}, - {KEY_EN_DELETE, 72}, - {KEY_EN_LEFT_ARROW, 76}, - - // COL 18 - {KEY_EN_SCROLL_LOCK, 67}, - {KEY_EN_HOME, 70}, - {KEY_EN_END, 73}, - {KEY_EN_UP_ARROW, 78}, - {KEY_EN_DOWN_ARROW, 77}, - - // COL 19 - {KEY_EN_PAUSE_BREAK, 68}, - {KEY_EN_PAGE_UP, 71}, - {KEY_EN_PAGE_DOWN, 74}, - {KEY_EN_RIGHT_ARROW, 75}, - - - // COL 20 - {KEY_EN_MEDIA_MUTE, 98}, - {KEY_EN_MEDIA_STOP, 119}, - {KEY_EN_NUMPAD_LOCK, 79}, - {KEY_EN_NUMPAD_7, 91}, - {KEY_EN_NUMPAD_4, 88}, - {KEY_EN_NUMPAD_1, 85}, - {KEY_EN_NUMPAD_0, 94}, - - // COL 21 - {KEY_EN_MEDIA_PREVIOUS, 122}, - {KEY_EN_NUMPAD_DIVIDE, 80}, - {KEY_EN_NUMPAD_8, 92}, - {KEY_EN_NUMPAD_5, 89}, - {KEY_EN_NUMPAD_2, 86}, - - // COL 22 - {KEY_EN_MEDIA_PLAY_PAUSE, 120}, - {KEY_EN_NUMPAD_TIMES, 81}, - {KEY_EN_NUMPAD_9, 93}, - {KEY_EN_NUMPAD_6, 90}, - {KEY_EN_NUMPAD_3, 87}, - {KEY_EN_NUMPAD_PERIOD, 95}, - - // COL 23 - {KEY_EN_MEDIA_NEXT, 121}, - {KEY_EN_NUMPAD_MINUS, 82}, - {KEY_EN_NUMPAD_PLUS, 83}, - {KEY_EN_NUMPAD_ENTER, 84} -}; - -/**------------------------------------------------------------------*\ - @name Corsair K95 Platinum XT Keyboard - @category Keyboard - @type USB - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectCorsairK95PlatinumXTControllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_CorsairK95PlatinumXT::RGBController_CorsairK95PlatinumXT(CorsairK95PlatinumXTController* controller_ptr) -{ - controller = controller_ptr; - - name = controller->GetName(); - vendor = "Corsair"; - description = "Corsair K95 Platinum XT Keyboard Device"; - type = DEVICE_TYPE_KEYBOARD; - version = controller->GetFirmwareString(); - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - 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(); -} - -RGBController_CorsairK95PlatinumXT::~RGBController_CorsairK95PlatinumXT() -{ - /*---------------------------------------------------------*\ - | Delete the matrix map | - \*---------------------------------------------------------*/ - for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++) - { - if(zones[zone_index].type == ZONE_TYPE_MATRIX) - { - delete zones[zone_index].matrix_map; - } - } - - delete controller; -} - -void RGBController_CorsairK95PlatinumXT::SetupZones() -{ - /*---------------------------------------------------------*\ - | Top bar zone setup | - \*---------------------------------------------------------*/ - zone top_bar_zone; - - top_bar_zone.name = "Top Bar"; - top_bar_zone.type = ZONE_TYPE_LINEAR; - top_bar_zone.leds_min = K95_PLATINUM_BAR_LENGTH; - top_bar_zone.leds_max = K95_PLATINUM_BAR_LENGTH; - top_bar_zone.leds_count = K95_PLATINUM_BAR_LENGTH; - top_bar_zone.matrix_map = nullptr; - - for(unsigned int i = 0; i < top_bar_zone.leds_count; i++) - { - led new_led; - new_led.name = std::get<0>(k95_platinum_xt_leds_names_and_positions[i]); - leds.push_back(new_led); - } - - zones.push_back(top_bar_zone); - - /*---------------------------------------------------------*\ - | Keyboard zone setup | - \*---------------------------------------------------------*/ - zone keyboard_zone; - - keyboard_zone.name = ZONE_EN_KEYBOARD; - keyboard_zone.type = ZONE_TYPE_MATRIX; - keyboard_zone.matrix_map = new matrix_map_type; - keyboard_zone.matrix_map->height = K95_PLATINUM_XT_HEIGHT; - keyboard_zone.matrix_map->width = K95_PLATINUM_XT_WIDTH; - keyboard_zone.matrix_map->map = new unsigned int[K95_PLATINUM_XT_HEIGHT * K95_PLATINUM_XT_WIDTH]; - - unsigned int keyboard_leds_count = 0; - - for(unsigned int w = 0; w < K95_PLATINUM_XT_WIDTH; w++) - { - for(unsigned int h = 0; h < K95_PLATINUM_XT_HEIGHT; h++) - { - unsigned int key = k95_platinum_xt_matrix_map[h][w]; - keyboard_zone.matrix_map->map[h * K95_PLATINUM_XT_WIDTH + w] = key; - - if(key != NA) - { - led new_led; - new_led.name = std::get<0>(k95_platinum_xt_leds_names_and_positions[top_bar_zone.leds_count + keyboard_leds_count]); - leds.push_back(new_led); - keyboard_leds_count++; - } - } - } - - keyboard_zone.leds_min = keyboard_leds_count; - keyboard_zone.leds_max = keyboard_leds_count; - keyboard_zone.leds_count = keyboard_leds_count; - - zones.push_back(keyboard_zone); - - SetupColors(); -} - -void RGBController_CorsairK95PlatinumXT::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_CorsairK95PlatinumXT::DeviceUpdateLEDs() -{ - controller->SendDirect(colors, k95_platinum_xt_leds_names_and_positions); -} - -void RGBController_CorsairK95PlatinumXT::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_CorsairK95PlatinumXT::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_CorsairK95PlatinumXT::DeviceUpdateMode() -{ - DeviceUpdateLEDs(); -} diff --git a/Controllers/CorsairPeripheralController/RGBController_CorsairK95PlatinumXT.h b/Controllers/CorsairPeripheralController/RGBController_CorsairK95PlatinumXT.h deleted file mode 100644 index ce40ff97..00000000 --- a/Controllers/CorsairPeripheralController/RGBController_CorsairK95PlatinumXT.h +++ /dev/null @@ -1,29 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_CorsairK95PlatinumXT.h | -| | -| | -| Guimard Morgan (morg) 6/07/2022 | -\*-----------------------------------------*/ -#pragma once - -#include "RGBController.h" -#include "CorsairK95PlatinumXTController.h" - -class RGBController_CorsairK95PlatinumXT : public RGBController -{ -public: - RGBController_CorsairK95PlatinumXT(CorsairK95PlatinumXTController* controller_ptr); - ~RGBController_CorsairK95PlatinumXT(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - CorsairK95PlatinumXTController* controller; -}; diff --git a/Controllers/CorsairPeripheralController/RGBController_CorsairPeripheral.cpp b/Controllers/CorsairPeripheralController/RGBController_CorsairPeripheral.cpp index 39824662..eba70806 100644 --- a/Controllers/CorsairPeripheralController/RGBController_CorsairPeripheral.cpp +++ b/Controllers/CorsairPeripheralController/RGBController_CorsairPeripheral.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_CorsairPeripheral.cpp | -| | -| Generic RGB Interface for Corsair RGB | -| keyboard, mouse, and mousemat devices | -| | -| Adam Honse (CalcProgrammer1) 1/9/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairPeripheral.cpp | +| | +| RGBController for Corsair peripherals | +| | +| Adam Honse (CalcProgrammer1) 09 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_CorsairPeripheral.h" diff --git a/Controllers/CorsairPeripheralController/RGBController_CorsairPeripheral.h b/Controllers/CorsairPeripheralController/RGBController_CorsairPeripheral.h index b9a0899d..ec0de8c2 100644 --- a/Controllers/CorsairPeripheralController/RGBController_CorsairPeripheral.h +++ b/Controllers/CorsairPeripheralController/RGBController_CorsairPeripheral.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_CorsairPeripheral.h | -| | -| Generic RGB Interface for Corsair RGB | -| keyboard, mouse, and mousemat devices | -| | -| Adam Honse (CalcProgrammer1) 1/9/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairPeripheral.h | +| | +| RGBController for Corsair peripherals | +| | +| Adam Honse (CalcProgrammer1) 09 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "CorsairPeripheralController.h" @@ -23,7 +26,7 @@ public: void SetupZones(); void ResizeZone(int zone, int new_size); - + void DeviceUpdateLEDs(); void UpdateZoneLEDs(int zone); void UpdateSingleLED(int led); diff --git a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.cpp b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.cpp index b9fc32d1..b6ce7186 100644 --- a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.cpp +++ b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.cpp @@ -1,63 +1,105 @@ -/*---------------------------------------------------------------------*\ -| CorsairPeripheralV2Controller.cpp | -| | -| Base class for the 08 based Corsair protocol | -| | -| Chris M (Dr_No) 07 Aug 2022 | -| | -\*---------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairPeripheralV2Controller.cpp | +| | +| Driver for Corsair V2 peripherals | +| | +| Chris M (Dr_No) 07 Aug 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "CorsairPeripheralV2Controller.h" +#include "StringUtils.h" using namespace std::chrono_literals; -CorsairPeripheralV2Controller::CorsairPeripheralV2Controller(hid_device* dev_handle, const char* path, std::string /*name*/, uint16_t pid) +CorsairPeripheralV2Controller::CorsairPeripheralV2Controller(hid_device* dev_handle, const char* path, std::string name) { - const uint8_t sz = HID_MAX_STR; - wchar_t tmp[sz]; - dev = dev_handle; location = path; + device_name = name; - hid_get_manufacturer_string(dev, tmp, sz); - std::wstring wName = std::wstring(tmp); - device_name = std::string(wName.begin(), wName.end()); + /*---------------------------------------------------------*\ + | Get PID | + | If the PID is in the know wireless receivers list | + | switch the write_cmd to talk to the device and retry | + \*---------------------------------------------------------*/ + unsigned int pid = GetAddress(0x12); - hid_get_product_string(dev, tmp, sz); - wName = std::wstring(tmp); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); - - for(size_t i = 0; i < CORSAIR_V2_DEVICE_COUNT; i++) + switch(pid) { - if(corsair_v2_device_list[i]->pid == pid) - { - /*---------------------------------------------------------*\ - | Set device ID | - \*---------------------------------------------------------*/ - device_index = i; - } + case CORSAIR_SLIPSTREAM_WIRELESS_PID1: + case CORSAIR_SLIPSTREAM_WIRELESS_PID2: + write_cmd = CORSAIR_V2_WRITE_WIRELESS_ID; + pid = GetAddress(0x12); + break; } + /*---------------------------------------------------------*\ + | If the hid_pid passed in from the detector does not match | + | the pid reported by the device then it is likey | + | behind a wireless receiver. | + \*---------------------------------------------------------*/ + LOG_DEBUG("[%s] Setting write CMD to %02X for %s mode for PID %04X", device_name.c_str(), + write_cmd, (write_cmd == CORSAIR_V2_WRITE_WIRELESS_ID) ? "wireless" : "wired", pid); + + /*---------------------------------------------------------*\ + | Get VID | + | NB: this can be achieved with GetAddress(0x11) but we | + | also need to set the packet length capabilities for | + | the device being set up. | + \*---------------------------------------------------------*/ + uint8_t buffer[CORSAIR_V2_PACKET_SIZE]; + buffer[1] = write_cmd; + buffer[2] = CORSAIR_V2_CMD_GET; + buffer[3] = 0x11; + hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE); + uint16_t result = hid_read_timeout(dev, buffer, CORSAIR_V2_PACKET_SIZE, CORSAIR_V2_TIMEOUT); + result++; + pkt_sze = std::max(result, (uint16_t)CORSAIR_V2_WRITE_SIZE); + LOG_DEBUG("[%s] Packet length set to %d", device_name.c_str(), pkt_sze); + /*---------------------------------------------------------*\ | NB: If the device is not found in the device list | | then wireless mode may not work reliably | \*---------------------------------------------------------*/ - bool wireless = corsair_v2_device_list[device_index]->wireless; - if(wireless) + bool not_found = true; + + for(uint16_t i = 0; i < CORSAIR_V2_DEVICE_COUNT; i++) { - write_cmd = CORSAIR_V2_WRITE_WIRELESS_ID; + LOG_DEBUG("[%s] Checking PID %04X against index %d with %04X - %smatch", device_name.c_str(), + pid, i, corsair_v2_device_list[i]->pid, corsair_v2_device_list[i]->pid == pid ? "" : "no "); + if(corsair_v2_device_list[i]->pid == pid) + { + /*---------------------------------------------------------*\ + | Set device ID | + \*---------------------------------------------------------*/ + not_found = false; + device_index = i; + break; + } + } + + if(not_found) + { + LOG_ERROR("[%s] device capabilities not found. Please creata a new device request.", + device_name.c_str()); } - LOG_DEBUG("[%s] Setting write CMD to %02X for %s mode", device_name.c_str(), - write_cmd, (wireless) ? "wireless" : "wired" ); /*---------------------------------------------------------*\ - | Get VID | + | Check lighting control endpoints | + | If lighting control endpoint 2 is unavailable | + | then use endpoint 1. | \*---------------------------------------------------------*/ - GetAddress(0x11); - /*---------------------------------------------------------*\ - | Get PID | - \*---------------------------------------------------------*/ - GetAddress(0x12); + result = StartTransaction(0); + if(result > 0) + { + light_ctrl = CORSAIR_V2_LIGHT_CTRL1; + StartTransaction(0); + } + StopTransaction(0); + LOG_DEBUG("[%s] Lighting Endpoint set to %02X", device_name.c_str(), light_ctrl); } CorsairPeripheralV2Controller::~CorsairPeripheralV2Controller() @@ -75,6 +117,21 @@ std::string CorsairPeripheralV2Controller::GetDeviceLocation() return("HID: " + location); } +std::string CorsairPeripheralV2Controller::GetErrorString(uint8_t err) +{ + switch(err) + { + case 1: + return "Invalid Value"; + case 3: + return "Failed"; + case 5: + return "Unsupported"; + default: + return "Protocol Error (Unknown)"; + } +} + std::string CorsairPeripheralV2Controller::GetFirmwareString() { return ""; @@ -87,21 +144,15 @@ std::string CorsairPeripheralV2Controller::GetName() std::string CorsairPeripheralV2Controller::GetSerialString() { - const uint8_t sz = HID_MAX_STR; - wchar_t tmp[sz]; - - int ret = hid_get_serial_number_string(dev, tmp, sz); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); if(ret != 0) { - LOG_DEBUG("[%s] Get HID Serial string failed", device_name.c_str()); return(""); } - std::wstring w_tmp = std::wstring(tmp); - std::string serial = std::string(w_tmp.begin(), w_tmp.end()); - - return serial; + return(StringUtils::wstring_to_string(serial_string)); } void CorsairPeripheralV2Controller::SetRenderMode(corsair_v2_device_mode mode) @@ -122,7 +173,7 @@ void CorsairPeripheralV2Controller::SetRenderMode(corsair_v2_device_mode mode) hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT); } -void CorsairPeripheralV2Controller::LightingControl(uint8_t opt1, uint8_t opt2) +void CorsairPeripheralV2Controller::LightingControl(uint8_t opt1) { uint8_t buffer[CORSAIR_V2_WRITE_SIZE]; @@ -140,17 +191,6 @@ void CorsairPeripheralV2Controller::LightingControl(uint8_t opt1, uint8_t opt2) hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE); hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT); - - /*---------------------------------------------------------*\ - | Open a RGB lighting handle | - \*---------------------------------------------------------*/ - buffer[2] = 0x0D; - buffer[3] = 0x00; - buffer[4] = 0x01; - buffer[5] = opt2; - - hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE); - hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT); } unsigned int CorsairPeripheralV2Controller::GetKeyboardLayout() @@ -181,13 +221,13 @@ unsigned int CorsairPeripheralV2Controller::GetAddress(uint8_t address) if(result > 0) { LOG_DEBUG("[%s] An error occurred! Get Address %02X failed - %d %s", device_name.c_str(), - address, result, (result == 5) ? "unsupported" : ""); + address, result, GetErrorString(result).c_str()); return -1; } return temp; } -void CorsairPeripheralV2Controller::StartTransaction(uint8_t opt1) +unsigned char CorsairPeripheralV2Controller::StartTransaction(uint8_t opt1) { uint8_t buffer[CORSAIR_V2_WRITE_SIZE]; @@ -196,10 +236,12 @@ void CorsairPeripheralV2Controller::StartTransaction(uint8_t opt1) buffer[1] = write_cmd; buffer[2] = CORSAIR_V2_CMD_START_TX; buffer[3] = opt1; - buffer[4] = 0x01; + buffer[4] = light_ctrl; hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE); hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT); + + return buffer[2]; } void CorsairPeripheralV2Controller::StopTransaction(uint8_t opt1) @@ -217,15 +259,28 @@ void CorsairPeripheralV2Controller::StopTransaction(uint8_t opt1) hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT); } +void CorsairPeripheralV2Controller::ClearPacketBuffer() +{ + uint8_t result = 0; + uint8_t buffer[CORSAIR_V2_PACKET_SIZE]; + + do + { + result = hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT_SHORT); + } + while(result > 0); +} + void CorsairPeripheralV2Controller::SetLEDs(uint8_t *data, uint16_t data_size) { const uint8_t offset1 = 8; const uint8_t offset2 = 4; uint16_t remaining = data_size; - uint8_t buffer[CORSAIR_V2_WRITE_SIZE]; - memset(buffer, 0, CORSAIR_V2_WRITE_SIZE); + uint8_t buffer[CORSAIR_V2_PACKET_SIZE]; + memset(buffer, 0, CORSAIR_V2_PACKET_SIZE); + ClearPacketBuffer(); StartTransaction(0); /*---------------------------------------------------------*\ | Set the data header in packet 1 with the data length | @@ -239,7 +294,7 @@ void CorsairPeripheralV2Controller::SetLEDs(uint8_t *data, uint16_t data_size) /*---------------------------------------------------------*\ | Check if the data needs more than 1 packet | \*---------------------------------------------------------*/ - uint16_t copy_bytes = CORSAIR_V2_WRITE_SIZE - offset1; + uint16_t copy_bytes = pkt_sze - offset1; if(remaining < copy_bytes) { copy_bytes = remaining; @@ -247,12 +302,12 @@ void CorsairPeripheralV2Controller::SetLEDs(uint8_t *data, uint16_t data_size) memcpy(&buffer[offset1], &data[0], copy_bytes); - hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE); - hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT_SHORT); + hid_write(dev, buffer, pkt_sze); + hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT_SHORT); remaining -= copy_bytes; buffer[2] = CORSAIR_V2_CMD_BLK_WN; - copy_bytes = CORSAIR_V2_WRITE_SIZE - offset2; + copy_bytes = pkt_sze - offset2; /*---------------------------------------------------------*\ | Send the remaining packets | @@ -268,8 +323,8 @@ void CorsairPeripheralV2Controller::SetLEDs(uint8_t *data, uint16_t data_size) memcpy(&buffer[offset2], &data[index], copy_bytes); - hid_write(dev, buffer, CORSAIR_V2_WRITE_SIZE); - hid_read_timeout(dev, buffer, CORSAIR_V2_WRITE_SIZE, CORSAIR_V2_TIMEOUT_SHORT); + hid_write(dev, buffer, pkt_sze); + hid_read_timeout(dev, buffer, pkt_sze, CORSAIR_V2_TIMEOUT_SHORT); remaining -= copy_bytes; } diff --git a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.h b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.h index 4a686741..ba5244f1 100644 --- a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.h +++ b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.h @@ -1,17 +1,19 @@ -/*---------------------------------------------------------------------*\ -| CorsairPeripheralV2Controller.h | -| | -| Base class for the 08 based Corsair protocol | -| | -| Chris M (Dr_No) 07 Aug 2022 | -| | -\*---------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairPeripheralV2Controller.h | +| | +| Driver for Corsair V2 peripherals | +| | +| Chris M (Dr_No) 07 Aug 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once #include #include -#include +#include #include "LogManager.h" #include "RGBController.h" #include "CorsairPeripheralV2Devices.h" @@ -25,6 +27,12 @@ #define CORSAIR_V2_WRITE_WIRED_ID 8 #define CORSAIR_V2_WRITE_WIRELESS_ID 9 #define CORSAIR_V2_WRITE_SIZE 65 +#define CORSAIR_V2_PACKET_SIZE 1024 + +#define CORSAIR_V2_LIGHT_CTRL1 1 +#define CORSAIR_V2_LIGHT_CTRL2 34 /* 0x22 */ +#define CORSAIR_V2_UPDATE_PERIOD 30000 +#define CORSAIR_V2_SLEEP_PERIOD 12500ms #define CORSAIR_V2_BRIGHTNESS_MIN 0 #define CORSAIR_V2_BRIGHTNESS_MAX 0xFF @@ -67,10 +75,11 @@ enum corsair_v2_color class CorsairPeripheralV2Controller { public: - CorsairPeripheralV2Controller(hid_device* dev_handle, const char* path, std::string name, uint16_t pid); + CorsairPeripheralV2Controller(hid_device* dev_handle, const char* path, std::string name); virtual ~CorsairPeripheralV2Controller(); std::string GetDeviceLocation(); + std::string GetErrorString(uint8_t err); std::string GetFirmwareString(); std::string GetName(); std::string GetSerialString(); @@ -78,7 +87,7 @@ public: unsigned int GetKeyboardLayout(); void SetRenderMode(corsair_v2_device_mode mode); - void LightingControl(uint8_t opt1, uint8_t opt2); + void LightingControl(uint8_t opt1); void SetLEDs(uint8_t *data, uint16_t data_size); void UpdateHWMode(uint16_t mode, corsair_v2_color color_mode, uint8_t speed, uint8_t direction, uint8_t brightness, std::vector colors); @@ -88,15 +97,18 @@ public: protected: uint16_t device_index; std::string device_name; + uint8_t light_ctrl = CORSAIR_V2_LIGHT_CTRL2; private: + void ClearPacketBuffer(); unsigned int GetAddress(uint8_t address); - void StartTransaction(uint8_t opt1); + unsigned char StartTransaction(uint8_t opt1); void StopTransaction(uint8_t opt1); hid_device* dev; uint8_t write_cmd = CORSAIR_V2_WRITE_WIRED_ID; + uint16_t pkt_sze = CORSAIR_V2_WRITE_SIZE; std::string firmware_version; std::string location; }; diff --git a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2ControllerDetect.cpp b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2ControllerDetect.cpp index 767e73a1..3068552e 100644 --- a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2ControllerDetect.cpp +++ b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2ControllerDetect.cpp @@ -1,10 +1,17 @@ +/*---------------------------------------------------------*\ +| CorsairPeripheralV2ControllerDetect.cpp | +| | +| Detector for Corsair V2 peripherals | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + /*-----------------------------------------------------*\ | OpenRGB includes | \*-----------------------------------------------------*/ -#include +#include #include "Detector.h" -#include "LogManager.h" -#include "RGBController.h" /*-----------------------------------------------------*\ | Corsair Peripheral specific includes | @@ -26,12 +33,12 @@ void DetectCorsairV2HardwareControllers(hid_device_info* info, const std::string if(dev) { - CorsairPeripheralV2HWController* controller = new CorsairPeripheralV2HWController(dev, info->path, name, info->product_id); + CorsairPeripheralV2HWController* controller = new CorsairPeripheralV2HWController(dev, info->path, name); RGBController_CorsairV2HW* rgb_controller = new RGBController_CorsairV2HW(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } -} /* DetectCorsairV2SoftwareControllers() */ +} /* DetectCorsairV2HardwareControllers() */ void DetectCorsairV2SoftwareControllers(hid_device_info* info, const std::string& name) { @@ -39,29 +46,49 @@ void DetectCorsairV2SoftwareControllers(hid_device_info* info, const std::string if(dev) { - CorsairPeripheralV2SWController* controller = new CorsairPeripheralV2SWController(dev, info->path, name, info->product_id); + CorsairPeripheralV2SWController* controller = new CorsairPeripheralV2SWController(dev, info->path, name); RGBController_CorsairV2SW* rgb_controller = new RGBController_CorsairV2SW(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } /* DetectCorsairV2SoftwareControllers() */ - /*-----------------------------------------------------------------------------------------------------*\ | Keyboards | \*-----------------------------------------------------------------------------------------------------*/ -REGISTER_HID_DETECTOR_IP("Corsair K55 RGB PRO", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_K55_RGB_PRO_PID, 1, 0xFF42); -REGISTER_HID_DETECTOR_IP("Corsair K60 RGB PRO", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_K60_RGB_PRO_PID, 1, 0xFF42); -REGISTER_HID_DETECTOR_IP("Corsair K60 RGB PRO Low Profile", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_K60_RGB_PRO_LP_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair K55 RGB PRO", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_K55_RGB_PRO_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair K60 RGB PRO", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_K60_RGB_PRO_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair K60 RGB PRO Low Profile", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_K60_RGB_PRO_LP_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair K60 RGB PRO TKL Black", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K60_RGB_PRO_TKL_B_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair K60 RGB PRO TKL White", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K60_RGB_PRO_TKL_W_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair K70 Core RGB", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K70_CORE_RGB_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair K70 RGB PRO", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K70_RGB_PRO_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair K70 RGB PRO V2", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K70_RGB_PRO_V2_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair K70 RGB TKL", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K70_RGB_TKL_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair K70 RGB TKL Champion Series", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K70_RGB_TKL_CS_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair K95 RGB PLATINUM XT", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K95_PLATINUM_XT_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair K100 RGB Optical", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K100_OPTICAL_V1_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair K100 RGB Optical", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K100_OPTICAL_V2_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair K100 MX Red", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_K100_MXRED_PID, 1, 0xFF42); /*-----------------------------------------------------------------------------------------------------*\ | Mice | \*-----------------------------------------------------------------------------------------------------*/ -REGISTER_HID_DETECTOR_IP("Corsair Ironclaw Wireless", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_IRONCLAW_WIRELESS_PID, 1, 0xFF42); -REGISTER_HID_DETECTOR_IP("Corsair Ironclaw Wireless (Wired)", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_IRONCLAW_WIRELESS_WIRED_PID, 1, 0xFF42); -REGISTER_HID_DETECTOR_IP("Corsair M55 RGB PRO", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_M55_RGB_PRO_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair Dark Core RGB SE (Wired)", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_DARK_CORE_RGB_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair Dark Core RGB Pro SE (Wired)", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_DARK_CORE_RGB_PRO_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair Harpoon Wireless (Wired)", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_HARPOON_WIRELESS_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair Ironclaw Wireless (Wired)", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_IRONCLAW_WIRELESS_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair Katar Pro", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_KATAR_PRO_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair Katar Pro V2", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_KATAR_PRO_V2_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair Katar Pro XT", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_KATAR_PRO_XT_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair M55 RGB PRO", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_M55_RGB_PRO_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair M65 RGB Ultra Wired", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_M65_RGB_ULTRA_WIRED_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair M65 RGB Ultra Wireless (Wired)", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_M65_RGB_ULTRA_WIRELESS_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair Slipstream Wireless Receiver HW", DetectCorsairV2HardwareControllers, CORSAIR_VID, CORSAIR_SLIPSTREAM_WIRELESS_PID1, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair Slipstream Wireless Receiver SW", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_SLIPSTREAM_WIRELESS_PID2, 1, 0xFF42); /*-----------------------------------------------------------------------------------------------------*\ | Mousemat | \*-----------------------------------------------------------------------------------------------------*/ -REGISTER_HID_DETECTOR_IP("Corsair MM700", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_MM700_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair MM700", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_MM700_PID, 1, 0xFF42); +REGISTER_HID_DETECTOR_IP("Corsair MM700 3XL", DetectCorsairV2SoftwareControllers, CORSAIR_VID, CORSAIR_MM700_3XL_PID, 1, 0xFF42); diff --git a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.cpp b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.cpp index 100dd43b..6b41627d 100644 --- a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.cpp +++ b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.cpp @@ -1,9 +1,34 @@ +/*---------------------------------------------------------*\ +| CorsairPeripheralV2Devices.cpp | +| | +| Device list for Corsair V2 peripherals | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "CorsairPeripheralV2Devices.h" /*-------------------------------------------------------------------------*\ | Corsair Key Values | \*-------------------------------------------------------------------------*/ +std::vector corsair_tkl_values = +{ + /* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK */ + 41, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + /* BKTK 1 2 3 4 5 6 7 8 9 0 - = BSPC INS HOME PGUP */ + 53, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 45, 46, 42, 73, 74, 75, + /* TAB Q W E R T Y U I O P [ ] \ DEL END PGDN */ + 43, 20, 26, 8, 21, 23, 28, 24, 12, 18, 19, 47, 48, 49, 76, 77, 78, + /* CPLK A S D F G H J K L ; " # ENTR */ + 57, 4, 22, 7, 9, 10, 11, 13, 14, 15, 51, 52, 50, 40, + /* LSFT ISO\ Z X C V B N M , . / RSFT ARWU */ + 106, 100, 29, 27, 6, 25, 5, 17, 16, 54, 55, 56, 110, 82, + /* LCTL LWIN LALT SPC RALT RFNC RMNU RCTL ARWR ARWD ARWR */ + 105, 108, 107, 44, 111, 122, 101, 109, 80, 81, 79, +}; + std::vector corsair_full_size_values = { /* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK */ @@ -12,10 +37,10 @@ std::vector corsair_full_size_values = 53, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 45, 46, 42, 73, 74, 75, 83, 84, 85, 86, /* TAB Q W E R T Y U I O P [ ] \ DEL END PGDN NM7 NM8 NM9 NMPL */ 43, 20, 26, 8, 21, 23, 28, 24, 12, 18, 19, 47, 48, 49, 76, 77, 78, 95, 96, 97, 87, - /* CPLK A S D F G H J K L ; " ENTR NM4 NM5 NM6 */ - 57, 4, 22, 7, 9, 10, 11, 13, 14, 15, 51, 52, 40, 92, 93, 94, - /* LSFT Z X C V B N M , . / RSFT ARWU NM1 NM2 NM3 NMER */ - 106, 29, 27, 6, 25, 5, 17, 16, 54, 55, 56, 110, 82, 89, 90, 91, 88, + /* CPLK A S D F G H J K L ; " # ENTR NM4 NM5 NM6 */ + 57, 4, 22, 7, 9, 10, 11, 13, 14, 15, 51, 52, 50, 40, 92, 93, 94, + /* LSFT ISO\ Z X C V B N M , . / RSFT ARWU NM1 NM2 NM3 NMER */ + 106, 100, 29, 27, 6, 25, 5, 17, 16, 54, 55, 56, 110, 82, 89, 90, 91, 88, /* LCTL LWIN LALT SPC RALT RFNC RMNU RCTL ARWR ARWD ARWR NM0 NMPD */ 105, 108, 107, 44, 111, 122, 101, 109, 80, 81, 79, 98, 99, }; @@ -29,25 +54,251 @@ keyboard_keymap_overlay_values corsair_K60_layout { corsair_full_size_values, { - { - KEYBOARD_LAYOUT_ISO_QWERTY, - { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 3, 12, 50, KEY_EN_POUND, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 4, 1, 100, KEY_EN_ISO_BACK_SLASH, KEYBOARD_OPCODE_SWAP_ONLY, }, - } - }, /* Add more regional layout fixes here */ } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + } +}; + +keyboard_keymap_overlay_values corsair_K60_tkl_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_TKL, + { + corsair_tkl_values, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + } +}; + +keyboard_keymap_overlay_values corsair_k70_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_FULL, + { + corsair_full_size_values, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + } +}; + +keyboard_keymap_overlay_values corsair_k70_pro_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_FULL, + { + corsair_full_size_values, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 128, "Profile", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, // Insert Profile into new row + { 0, 0, 1, 113, "Light", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Light key + { 0, 0, 2, 114, "Lock", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lock Key + { 0, 0, 10, 191, "Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Logo + { 0, 0, 18, 102, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Mute Key + { 0, 1, 17, 123, KEY_EN_MEDIA_STOP, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Stop Key + { 0, 1, 18, 126, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Previous Track Key + { 0, 1, 19, 124, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Play Pause Key + { 0, 1, 20, 125, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Next Tack Key + } +}; + +keyboard_keymap_overlay_values corsair_K70_TKL_cs_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_TKL, + { + corsair_tkl_values, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 1, 123, KEY_EN_MEDIA_STOP, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, // Insert Stop Key into new media keys row + { 0, 0, 2, 126, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Previous Track Key + { 0, 0, 3, 124, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Play Pause Key + { 0, 0, 4, 125, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Next Tack Key + { 0, 0, 7, 1, "Logo L", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert 'Logo Left' + { 0, 0, 8, 3, "Logo R", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert 'Logo Right' + { 0, 0, 11, 128, "Profile", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Profile + { 0, 0, 12, 113, "Light", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Light key + { 0, 0, 13, 114, "Lock", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Lock Key + { 0, 0, 14, 102, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Mute Key + } +}; + +keyboard_keymap_overlay_values corsair_k95_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_FULL, + { + corsair_full_size_values, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + //swap right fn with right windows + { 0, 5, 11, 112, KEY_EN_RIGHT_WINDOWS, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + //media keys + { 0, 0, 17, 123, KEY_EN_MEDIA_STOP, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 18, 126, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 19, 124, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 20, 125, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + //upper row + { 0, 0, 4, 128, "Profile", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, + { 0, 0, 5, 113, "Light", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 6, 114, "Lock", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 18, 102, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + //macro keys + { 0, 1, 0, 131, "G1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 0, 132, "G2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 0, 133, "G3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 0, 134, "G4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 0, 135, "G5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 0, 136, "G6", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + //top bar + { 0, 0, 0, 137, "Top Bar 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, + { 0, 0, 1, 138, "Top Bar 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 2, 139, "Top Bar 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 3, 140, "Top Bar 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 4, 141, "Top Bar 5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 5, 142, "Top Bar 6", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 6, 143, "Top Bar 7", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 7, 144, "Top Bar 8", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 8, 145, "Top Bar 9", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 9, 146, "Top Bar 10", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 10, 147, "Top Bar 11", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 11, 148, "Top Bar 12", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 12, 149, "Top Bar 13", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 13, 150, "Top Bar 14", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 14, 151, "Top Bar 15", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 15, 152, "Top Bar 16", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 16, 153, "Top Bar 17", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 17, 154, "Top Bar 18", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 18, 155, "Top Bar 19", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + } +}; + +keyboard_keymap_overlay_values corsair_k100_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_FULL, + { + corsair_full_size_values, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + //media keys + { 0, 0, 17, 123, KEY_EN_MEDIA_STOP, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 18, 126, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 19, 124, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 20, 125, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + //upper row + { 0, 0, 1, 128, "Profile", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, + { 0, 0, 2, 137, "iCue", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 3, 114, "Lock", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 10, 190, "Logo L", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 11, 191, "Logo M", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 12, 192, "Logo R", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 18, 102, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + //macro keys + { 0, 1, 0, 131, "G1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 0, 132, "G2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 0, 133, "G3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 0, 134, "G4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 0, 135, "G5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 0, 136, "G6", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + //underglow 44 entries + //underglow upper + { 0, 0, 0, 138, "Underglow 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, + { 0, 0, 1, 139, "Underglow 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 2, 140, "Underglow 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 3, 141, "Underglow 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 4, 142, "Underglow 5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 5, 143, "Underglow 6", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 6, 144, "Underglow 7", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 7, 145, "Underglow 8", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 8, 146, "Underglow 9", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 9, 147, "Underglow 10", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 10, 148, "Underglow 11", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 11, 149, "Underglow 12", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 12, 150, "Underglow 13", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 13, 151, "Underglow 14", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 14, 152, "Underglow 15", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 15, 153, "Underglow 16", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 16, 154, "Underglow 17", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 17, 155, "Underglow 18", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 18, 156, "Underglow 19", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 19, 157, "Underglow 20", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 20, 158, "Underglow 21", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 21, 159, "Underglow 22", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + //underglow left + { 0, 0, 0, 160, "Underglow 23", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 0, 161, "Underglow 24", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 0, 162, "Underglow 25", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 0, 163, "Underglow 26", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 0, 164, "Underglow 27", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 0, 165, "Underglow 28", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 0, 166, "Underglow 29", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 7, 0, 167, "Underglow 30", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 8, 0, 168, "Underglow 31", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 9, 0, 169, "Underglow 32", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 10, 0, 170, "Underglow 33", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + //underglow right + { 0, 0, 23, 171, "Underglow 34", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 23, 172, "Underglow 35", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 23, 173, "Underglow 36", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 23, 174, "Underglow 37", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 23, 175, "Underglow 38", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 23, 176, "Underglow 39", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 6, 23, 177, "Underglow 40", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 7, 23, 178, "Underglow 41", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 8, 23, 179, "Underglow 42", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 9, 23, 180, "Underglow 43", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 10, 23, 181, "Underglow 44", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + //wheel + { 0, 0, 0, 182, "Wheel 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, + { 0, 0, 1, 183, "Wheel 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 2, 184, "Wheel 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 3, 185, "Wheel 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 4, 186, "Wheel 5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 5, 187, "Wheel 6", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 6, 188, "Wheel 7", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 7, 189, "Wheel 8", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, } }; @@ -56,8 +307,225 @@ keyboard_keymap_overlay_values corsair_K60_layout \*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------*\ -| Corsair Ironclaw Wireless 1B1C:1B66 | -| Corsair Ironclaw Wireless (Wired) 1B1C:1B4C | +| Corsair Dark Core SE 1B1C:1B4B | +| | +| Zone "Scroll Wheel" | +| Single | +| | +| Zone "Side Buttons" | +| Linear | +| 1 Row, 4 Columns | +| | +| Zone "Rear Left" | +| Single | +| | +| Zone "Logo" | +| Single | +| | +| Zone "Rear Right" | +| Single | +| | +| Zone "DPI & Indicator" | +| Linear | +| 1 Row, 4 Columns | +\*-------------------------------------------------------------*/ +static const corsair_v2_zone dark_core_se_scroll_zone = +{ + "Scroll Wheel", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_zone dark_core_se_button_zone = +{ + "Side Buttons", + ZONE_TYPE_LINEAR, + 1, + 4 +}; + +static const corsair_v2_zone dark_core_se_left_zone = +{ + "Rear Left", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_zone dark_core_se_logo_zone = +{ + "Logo", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_zone dark_core_se_right_zone = +{ + "Rear Right", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_zone dark_core_se_dpi_zone = +{ + "DPI & Indicator Zone", + ZONE_TYPE_LINEAR, + 1, + 4 +}; + +static const corsair_v2_device dark_core_se_device = +{ + CORSAIR_DARK_CORE_RGB_PID, + DEVICE_TYPE_MOUSE, + 1, + 12, + { + &dark_core_se_scroll_zone, + &dark_core_se_button_zone, + &dark_core_se_left_zone, + &dark_core_se_logo_zone, + &dark_core_se_right_zone, + &dark_core_se_dpi_zone + }, + nullptr +}; + +/*-------------------------------------------------------------*\ +| Corsair Dark Core Pro SE 1B1C:1B7E | +| | +| Zone "Scroll Wheel" | +| Single | +| | +| Zone "Side Buttons" | +| Linear | +| 1 Row, 4 Columns | +| | +| Zone "Rear Left" | +| Single | +| | +| Zone "Logo" | +| Single | +| | +| Zone "Rear Right" | +| Single | +| | +| Zone "DPI & Indicator" | +| Linear | +| 1 Row, 4 Columns | +\*-------------------------------------------------------------*/ +static const corsair_v2_zone dark_core_pro_se_scroll_zone = +{ + "Scroll Wheel", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_zone dark_core_pro_se_button_zone = +{ + "Side Buttons", + ZONE_TYPE_LINEAR, + 1, + 4 +}; + +static const corsair_v2_zone dark_core_pro_se_left_zone = +{ + "Rear Left", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_zone dark_core_pro_se_logo_zone = +{ + "Logo", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_zone dark_core_pro_se_right_zone = +{ + "Rear Right", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_zone dark_core_pro_se_dpi_zone = +{ + "DPI & Indicator Zone", + ZONE_TYPE_LINEAR, + 1, + 4 +}; + +static const corsair_v2_device dark_core_pro_se_device = +{ + CORSAIR_DARK_CORE_RGB_PRO_PID, + DEVICE_TYPE_MOUSE, + 1, + 12, + { + &dark_core_pro_se_scroll_zone, + &dark_core_pro_se_button_zone, + &dark_core_pro_se_left_zone, + &dark_core_pro_se_logo_zone, + &dark_core_pro_se_right_zone, + &dark_core_pro_se_dpi_zone + }, + nullptr +}; + +/*-------------------------------------------------------------*\ +| Corsair Harpoon Wireless 1B1C:1B5E | +| | +| Zone "Logo" | +| Single | +| | +| Zone "Scroll Wheel" | +| Single | +\*-------------------------------------------------------------*/ +static const corsair_v2_zone harpoon_indicator_zone = +{ + "Indicator", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_zone harpoon_logo_zone = +{ + "Logo", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_device harpoon_wireless_device = +{ + CORSAIR_HARPOON_WIRELESS_PID, + DEVICE_TYPE_MOUSE, + 1, + 2, + { + &harpoon_indicator_zone, + &harpoon_logo_zone, + nullptr, + nullptr, + nullptr, + nullptr + }, + nullptr +}; + +/*-------------------------------------------------------------*\ +| Corsair Ironclaw Wireless 1B1C:1B4C | | | | Zone "Logo" | | Single | @@ -104,12 +572,10 @@ static const corsair_v2_zone ironclaw_side_zone = 3 }; -static const corsair_v2_device ironclaw_wired_device = +static const corsair_v2_device ironclaw_wireless_device = { - CORSAIR_IRONCLAW_WIRELESS_WIRED_PID, - false, + CORSAIR_IRONCLAW_WIRELESS_PID, DEVICE_TYPE_MOUSE, - CORSAIR_V2_TYPE_SW_COLOUR_BLOCK, 1, 6, { @@ -123,19 +589,129 @@ static const corsair_v2_device ironclaw_wired_device = nullptr }; -static const corsair_v2_device ironclaw_wireless_device = +/*-------------------------------------------------------------*\ +| Corsair Katar Pro 1B1C:1B93 | +| | +| Zone "Scroll Wheel" | +| Single | +| | +| Zone "DPI" | +| Single | +| | +\*-------------------------------------------------------------*/ +static const corsair_v2_zone katar_pro_scroll_zone = { - CORSAIR_IRONCLAW_WIRELESS_PID, - true, - DEVICE_TYPE_MOUSE, - CORSAIR_V2_TYPE_SW_COLOUR_BLOCK, + "Scroll Wheel", + ZONE_TYPE_SINGLE, 1, - 6, + 1 +}; + +static const corsair_v2_zone katar_pro_dpi_zone = +{ + "DPI", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_device katar_pro_device = +{ + CORSAIR_KATAR_PRO_PID, + DEVICE_TYPE_MOUSE, + 1, + 2, { - &ironclaw_logo_zone, - &ironclaw_scroll_zone, - &ironclaw_button_zone, - &ironclaw_side_zone, + &katar_pro_scroll_zone, + &katar_pro_dpi_zone, + nullptr, + nullptr, + nullptr, + nullptr + }, + nullptr +}; + +/*-------------------------------------------------------------*\ +| Corsair Katar Pro V2 1B1C:1BBA | +| | +| Zone "Scroll Wheel" | +| Single | +| | +| Zone "DPI" | +| Single | +| | +\*-------------------------------------------------------------*/ +static const corsair_v2_zone katar_pro_v2_scroll_zone = +{ + "Scroll Wheel", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_zone katar_pro_v2_dpi_zone = +{ + "DPI", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_device katar_pro_v2_device = +{ + CORSAIR_KATAR_PRO_V2_PID, + DEVICE_TYPE_MOUSE, + 1, + 2, + { + &katar_pro_v2_scroll_zone, + &katar_pro_v2_dpi_zone, + nullptr, + nullptr, + nullptr, + nullptr + }, + nullptr +}; + +/*-------------------------------------------------------------*\ +| Corsair Katar Pro XT 1B1C:1BAC | +| | +| Zone "Scroll Wheel" | +| Single | +| | +| Zone "DPI" | +| Single | +| | +\*-------------------------------------------------------------*/ +static const corsair_v2_zone katar_pro_xt_scroll_zone = +{ + "Scroll Wheel", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_zone katar_pro_xt_dpi_zone = +{ + "DPI", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_device katar_pro_xt_device = +{ + CORSAIR_KATAR_PRO_XT_PID, + DEVICE_TYPE_MOUSE, + 1, + 2, + { + &katar_pro_xt_scroll_zone, + &katar_pro_xt_dpi_zone, + nullptr, + nullptr, nullptr, nullptr }, @@ -160,9 +736,7 @@ static const corsair_v2_zone k55_rgb_pro_zone = static const corsair_v2_device k55_rgb_pro_device = { CORSAIR_K55_RGB_PRO_PID, - false, DEVICE_TYPE_KEYBOARD, - CORSAIR_V2_TYPE_SW_COLOUR_BLOCK, 1, 6, { @@ -194,9 +768,7 @@ static const corsair_v2_zone k60_rgb_pro_zone = static const corsair_v2_device k60_rgb_pro_device = { CORSAIR_K60_RGB_PRO_PID, - false, DEVICE_TYPE_KEYBOARD, - CORSAIR_V2_TYPE_SW_COLOUR_BLOCK, 6, 21, { @@ -228,9 +800,7 @@ static const corsair_v2_zone k60_rgb_pro_lp_zone = static const corsair_v2_device k60_rgb_pro_lp_device = { CORSAIR_K60_RGB_PRO_LP_PID, - false, DEVICE_TYPE_KEYBOARD, - CORSAIR_V2_TYPE_SW_COLOUR_BLOCK, 6, 21, { @@ -244,6 +814,340 @@ static const corsair_v2_device k60_rgb_pro_lp_device = &corsair_K60_layout }; +/*-------------------------------------------------------------*\ +| Corsair K60 RGB Pro TKL 1B1C:1BC7 (black) | +| Corsair K60 RGB Pro TKL 1B1C:1BED (white) | +| | +| Zone "Keyboard" | +| Matrix | +| 6 Rows, 21 Columns | +\*-------------------------------------------------------------*/ +static const corsair_v2_zone k60_rgb_pro_tkl_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 6, + 21 +}; + +static const corsair_v2_device k60_rgb_pro_tkl_device_b = +{ + CORSAIR_K60_RGB_PRO_TKL_B_PID, + DEVICE_TYPE_KEYBOARD, + 6, + 21, + { + &k60_rgb_pro_lp_zone, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr + }, + &corsair_K60_tkl_layout +}; + +static const corsair_v2_device k60_rgb_pro_tkl_device_w = +{ + CORSAIR_K60_RGB_PRO_TKL_W_PID, + DEVICE_TYPE_KEYBOARD, + 6, + 21, + { + &k60_rgb_pro_lp_zone, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr + }, + &corsair_K60_tkl_layout +}; + + +/*-------------------------------------------------------------*\ +| Corsair K70 Core RGB 1B1C:1BFD | +| | +| Zone "Keyboard" | +| Matrix | +| 6 Rows, 21 Columns | +\*-------------------------------------------------------------*/ +static const corsair_v2_zone k70_core_rgb_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 6, + 21 +}; + +static const corsair_v2_device k70_core_rgb_device = +{ + CORSAIR_K70_CORE_RGB_PID, + DEVICE_TYPE_KEYBOARD, + 6, + 21, + { + &k70_core_rgb_zone, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr + }, + &corsair_k70_layout +}; + +/*-------------------------------------------------------------*\ +| Corsair K70 RGB TKL 1B1C:1B73 | +| | +| Zone "Keyboard" | +| Matrix | +| 7 Rows, 17 Columns | +\*-------------------------------------------------------------*/ +static const corsair_v2_zone k70_rgb_tkl_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 7, + 17 +}; + +static const corsair_v2_device k70_rgb_tkl_device = +{ + CORSAIR_K70_RGB_TKL_PID, + DEVICE_TYPE_KEYBOARD, + 7, + 17, + { + &k70_rgb_tkl_zone, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr + }, + &corsair_K70_TKL_cs_layout +}; + +/*-------------------------------------------------------------*\ +| Corsair K70 RGB TKL Champion Series 1B1C:1BB9 | +| | +| Zone "Keyboard" | +| Matrix | +| 7 Rows, 17 Columns | +\*-------------------------------------------------------------*/ +static const corsair_v2_zone k70_rgb_tkl_cs_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 7, + 17 +}; + +static const corsair_v2_device k70_rgb_tkl_cs_device = +{ + CORSAIR_K70_RGB_TKL_CS_PID, + DEVICE_TYPE_KEYBOARD, + 7, + 17, + { + &k70_rgb_tkl_cs_zone, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr + }, + &corsair_K70_TKL_cs_layout +}; + +/*-------------------------------------------------------------*\ +| Corsair K70 RGB Pro 1B1C:1BC4 | +| | +| Zone "Keyboard" | +| Matrix | +| 6 Rows, 21 Columns | +\*-------------------------------------------------------------*/ +static const corsair_v2_zone k70_rgb_pro_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 7, + 21 +}; + +static const corsair_v2_device k70_rgb_pro_device = +{ + CORSAIR_K70_RGB_PRO_PID, + DEVICE_TYPE_KEYBOARD, + 7, + 21, + { + &k70_rgb_pro_zone, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr + }, + &corsair_k70_pro_layout +}; + +/*-------------------------------------------------------------*\ +| Corsair K70 RGB Pro V2 1B1C:1BB3 | +| | +| Zone "Keyboard" | +| Matrix | +| 6 Rows, 21 Columns | +\*-------------------------------------------------------------*/ +static const corsair_v2_device k70_rgb_pro_v2_device = + { + CORSAIR_K70_RGB_PRO_V2_PID, + DEVICE_TYPE_KEYBOARD, + 7, + 21, + { + &k70_rgb_pro_zone, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr + }, + &corsair_k70_pro_layout +}; + +/*-------------------------------------------------------------*\ +| Corsair K95 RGB PLATINUM XT 1B1C:1B89 | +| | +| Zone "Keyboard" | +| Matrix | +| 8 Rows, 22 Columns | +\*-------------------------------------------------------------*/ + +static const corsair_v2_zone k95_platinum_xt_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 8, + 22 +}; + +/*--------------------------------------------------------------------------------*\ +| TODO: Add a "Top Bar" zone for the lights defined in the device layout | +| currently, a bug in the device controller causes linear zones to have | +| incorrect led values, this can be done once it's fixed: | +| https://gitlab.com/CalcProgrammer1/OpenRGB/-/merge_requests/2951#note_2679300236 | +\*--------------------------------------------------------------------------------*/ + +static const corsair_v2_device k95_platinum_xt_device = +{ + CORSAIR_K95_PLATINUM_XT_PID, + DEVICE_TYPE_KEYBOARD, + 8, + 22, + { + &k95_platinum_xt_zone, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr + }, + &corsair_k95_layout +}; + +/*-------------------------------------------------------------*\ +| Corsair K100 MX Red 1B1C:1B7D | +| | +| Zone "Keyboard" | +| Matrix | +| 12 Rows, 24 Columns | +\*-------------------------------------------------------------*/ + +static const corsair_v2_zone k100_mx_red_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 12, + 24 +}; + +static const corsair_v2_device k100_mx_red_device = +{ + CORSAIR_K100_MXRED_PID, + DEVICE_TYPE_KEYBOARD, + 12, + 24, + { + &k100_mx_red_zone, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr + }, + &corsair_k100_layout +}; + +/*-------------------------------------------------------------*\ +| Corsair K100 RGB Optical V1 1B1C:1B7C | +| | +| Zone "Keyboard" | +| Matrix | +| 12 Rows, 24 Columns | +\*-------------------------------------------------------------*/ + +static const corsair_v2_zone k100_rgb_opt_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 12, + 24 +}; + +static const corsair_v2_device k100_rgb_opt_v1_device = +{ + CORSAIR_K100_OPTICAL_V1_PID, + DEVICE_TYPE_KEYBOARD, + 12, + 24, + { + &k100_rgb_opt_zone, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr + }, + &corsair_k100_layout +}; + +/*-------------------------------------------------------------*\ +| Corsair K100 RGB Optical V2 1B1C:1BC5 | +| | +| Zone "Keyboard" | +| Matrix | +| 12 Rows, 24 Columns | +\*-------------------------------------------------------------*/ + +static const corsair_v2_device k100_rgb_opt_v2_device = +{ + CORSAIR_K100_OPTICAL_V2_PID, + DEVICE_TYPE_KEYBOARD, + 12, + 24, + { + &k100_rgb_opt_zone, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr + }, + &corsair_k100_layout +}; + /*-------------------------------------------------------------*\ | Corsair M55 1B1C:1B70 | | | @@ -273,9 +1177,7 @@ static const corsair_v2_zone m55_logo_zone = static const corsair_v2_device m55_device = { CORSAIR_M55_RGB_PRO_PID, - false, DEVICE_TYPE_MOUSE, - CORSAIR_V2_TYPE_SW_COLOUR_BLOCK, 1, 2, { @@ -289,6 +1191,102 @@ static const corsair_v2_device m55_device = nullptr }; +/*-------------------------------------------------------------*\ +| Corsair M65 RGB Ultra Wired 1B1C:1B9E | +| | +| Zone "Scroll Wheel" | +| Single | +| | +| Zone "Logo" | +| Single | +| | +| Zone "Indicator" | +| Single | +| | +\*-------------------------------------------------------------*/ +static const corsair_v2_zone m65_rgb_ultra_wired_scroll_zone = +{ + "Scroll Wheel", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_zone m65_rgb_ultra_wired_logo_zone = +{ + "Logo", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_zone m65_rgb_ultra_wired_indicator_zone = +{ + "Indicator", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_device m65_rgb_ultra_wired_device = +{ + CORSAIR_M65_RGB_ULTRA_WIRED_PID, + DEVICE_TYPE_MOUSE, + 1, + 3, + { + &m65_rgb_ultra_wired_logo_zone, + &m65_rgb_ultra_wired_scroll_zone, + &m65_rgb_ultra_wired_indicator_zone, + nullptr, + nullptr, + nullptr + }, + nullptr +}; + +/*-------------------------------------------------------------*\ +| Corsair M65 RGB Ultra Wireless 1B1C:1BB5 | +| | +| Zone "Logo" | +| Single | +| | +| Zone "DPI" | +| Single | +\*-------------------------------------------------------------*/ +static const corsair_v2_zone m65_ultra_rgb_logo_zone = +{ + "Logo", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_zone m65_ultra_rgb_dpi_zone = +{ + "DPI", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const corsair_v2_device m65_ultra_rgb_device = +{ + CORSAIR_M65_RGB_ULTRA_WIRELESS_PID, + DEVICE_TYPE_MOUSE, + 1, + 2, + { + &m65_ultra_rgb_logo_zone, + &m65_ultra_rgb_dpi_zone, + nullptr, + nullptr, + nullptr, + nullptr + }, + nullptr +}; + /*-------------------------------------------------------------*\ | Corsair MM700 1B1C:1B9B | | | @@ -326,9 +1324,24 @@ static const corsair_v2_zone mm700_left_zone = static const corsair_v2_device mm700_device = { CORSAIR_MM700_PID, - false, DEVICE_TYPE_MOUSEMAT, - CORSAIR_V2_TYPE_SW_COLOUR_BLOCK, + 1, + 3, + { + &mm700_left_zone, + &mm700_right_zone, + &mm700_logo_zone, + nullptr, + nullptr, + nullptr + }, + nullptr +}; + +static const corsair_v2_device mm700_3xl_device = +{ + CORSAIR_MM700_3XL_PID, + DEVICE_TYPE_MOUSEMAT, 1, 3, { @@ -353,18 +1366,37 @@ const corsair_v2_device* corsair_v2_device_list_data[] = &k55_rgb_pro_device, &k60_rgb_pro_device, &k60_rgb_pro_lp_device, + &k60_rgb_pro_tkl_device_b, + &k60_rgb_pro_tkl_device_w, + &k70_core_rgb_device, + &k70_rgb_pro_device, + &k70_rgb_pro_v2_device, + &k70_rgb_tkl_device, + &k70_rgb_tkl_cs_device, + &k95_platinum_xt_device, + &k100_mx_red_device, + &k100_rgb_opt_v1_device, + &k100_rgb_opt_v2_device, /*-----------------------------------------------------------------*\ | MICE | \*-----------------------------------------------------------------*/ - &ironclaw_wired_device, + &dark_core_se_device, + &dark_core_pro_se_device, + &harpoon_wireless_device, &ironclaw_wireless_device, + &katar_pro_device, + &katar_pro_v2_device, + &katar_pro_xt_device, &m55_device, + &m65_rgb_ultra_wired_device, + &m65_ultra_rgb_device, /*-----------------------------------------------------------------*\ | MOUSEMATS | \*-----------------------------------------------------------------*/ &mm700_device, + &mm700_3xl_device, }; const unsigned int CORSAIR_V2_DEVICE_COUNT = (sizeof(corsair_v2_device_list_data) / sizeof(corsair_v2_device_list_data[ 0 ])); diff --git a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.h b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.h index 9c7a1d7d..62a691fd 100644 --- a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.h +++ b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.h @@ -1,3 +1,12 @@ +/*---------------------------------------------------------*\ +| CorsairPeripheralV2Devices.h | +| | +| Device list for Corsair V2 peripherals | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include @@ -49,9 +58,7 @@ typedef struct typedef struct { uint16_t pid; - bool wireless; device_type type; - corsair_v2_supports protocol; uint8_t rows; uint8_t cols; const corsair_v2_zone* zones[CORSAIR_ZONES_MAX]; @@ -64,18 +71,39 @@ typedef struct #define CORSAIR_K55_RGB_PRO_PID 0x1BA4 #define CORSAIR_K60_RGB_PRO_PID 0x1BA0 #define CORSAIR_K60_RGB_PRO_LP_PID 0x1BAD +#define CORSAIR_K60_RGB_PRO_TKL_B_PID 0x1BC7 +#define CORSAIR_K60_RGB_PRO_TKL_W_PID 0x1BED +#define CORSAIR_K70_CORE_RGB_PID 0x1BFD +#define CORSAIR_K70_RGB_PRO_PID 0x1BC4 +#define CORSAIR_K70_RGB_PRO_V2_PID 0x1BB3 +#define CORSAIR_K70_RGB_TKL_PID 0x1B73 +#define CORSAIR_K70_RGB_TKL_CS_PID 0x1BB9 +#define CORSAIR_K95_PLATINUM_XT_PID 0x1B89 +#define CORSAIR_K100_OPTICAL_V1_PID 0x1B7C +#define CORSAIR_K100_OPTICAL_V2_PID 0x1BC5 +#define CORSAIR_K100_MXRED_PID 0x1B7D /*-----------------------------------------------------*\ | Corsair V2 Protocol Mice | \*-----------------------------------------------------*/ -#define CORSAIR_IRONCLAW_WIRELESS_PID 0x1BA6 -#define CORSAIR_IRONCLAW_WIRELESS_WIRED_PID 0x1B4C +#define CORSAIR_DARK_CORE_RGB_PID 0x1B4B +#define CORSAIR_DARK_CORE_RGB_PRO_PID 0x1B7E +#define CORSAIR_HARPOON_WIRELESS_PID 0x1B5E +#define CORSAIR_IRONCLAW_WIRELESS_PID 0x1B4C +#define CORSAIR_KATAR_PRO_PID 0x1B93 +#define CORSAIR_KATAR_PRO_V2_PID 0x1BBA +#define CORSAIR_KATAR_PRO_XT_PID 0x1BAC #define CORSAIR_M55_RGB_PRO_PID 0x1B70 +#define CORSAIR_M65_RGB_ULTRA_WIRED_PID 0x1B9E +#define CORSAIR_M65_RGB_ULTRA_WIRELESS_PID 0x1BB5 +#define CORSAIR_SLIPSTREAM_WIRELESS_PID1 0x1BA6 +#define CORSAIR_SLIPSTREAM_WIRELESS_PID2 0x1B65 /*-----------------------------------------------------*\ | Corsair V2 Protocol Mousemats | \*-----------------------------------------------------*/ #define CORSAIR_MM700_PID 0x1B9B +#define CORSAIR_MM700_3XL_PID 0x1BC9 /*-----------------------------------------------------*\ | These constant values are defined in | diff --git a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.cpp b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.cpp index c13db697..b8873f9b 100644 --- a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.cpp +++ b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.cpp @@ -1,19 +1,21 @@ -/*---------------------------------------------------------------------*\ -| CorsairPeripheralV2HardwareController.cpp | -| | -| Driver for the newer Corsair peripherals that use the '08' | -| based USB protocol and support hardware lighting modes. | -| | -| Chris M (Dr_No) 07 Dec 2022 | -\*---------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairPeripheralV2HardwareController.cpp | +| | +| Driver for Corsair V2 peripherals - hardware modes | +| | +| Chris M (Dr_No) 07 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "LogManager.h" #include "CorsairPeripheralV2HardwareController.h" -CorsairPeripheralV2HWController::CorsairPeripheralV2HWController(hid_device* dev_handle, const char* path, std::string name, uint16_t pid) : CorsairPeripheralV2Controller(dev_handle, path, name, pid) +CorsairPeripheralV2HWController::CorsairPeripheralV2HWController(hid_device* dev_handle, const char* path, std::string name) : CorsairPeripheralV2Controller(dev_handle, path, name) { SetRenderMode(CORSAIR_V2_MODE_SW); - LightingControl(0x5F, 0x00); + LightingControl(0x5F); } CorsairPeripheralV2HWController::~CorsairPeripheralV2HWController() @@ -23,41 +25,38 @@ CorsairPeripheralV2HWController::~CorsairPeripheralV2HWController() void CorsairPeripheralV2HWController::SetLedsDirect(std::vectorcolors) { - switch(corsair_v2_device_list[device_index]->protocol) + switch(light_ctrl) { - case CORSAIR_V2_TYPE_HW_TRIPLETS: - SetLedsDirectTriplets(colors); - break; - case CORSAIR_V2_TYPE_HW_COLOUR_BLOCK: + case CORSAIR_V2_LIGHT_CTRL1: SetLedsDirectColourBlocks(colors); break; + case CORSAIR_V2_LIGHT_CTRL2: + SetLedsDirectTriplets(colors); + break; default: - LOG_ERROR("[%s] Error setting Direct mode: Device supportes returned %i", device_name.c_str(), - corsair_v2_device_list[device_index]->protocol); + LOG_ERROR("[%s] Error setting Direct mode: Device supportes returned %i", + device_name.c_str(), light_ctrl); break; } } void CorsairPeripheralV2HWController::SetLedsDirectColourBlocks(std::vectorcolors) { - uint16_t count = colors.size(); - uint16_t green = count + CORSAIR_V2HW_DATA_OFFSET; - uint16_t blue = (count * 2) + CORSAIR_V2HW_DATA_OFFSET; - uint16_t length = (count * 3) + CORSAIR_V2HW_DATA_OFFSET; + uint16_t count = (uint16_t)colors.size(); + uint16_t green = count; + uint16_t blue = (count * 2); + uint16_t length = (count * 3); uint8_t* buffer = new uint8_t[length]; memset(buffer, 0, length); - buffer[0] = CORSAIR_V2_MODE_DIRECT & 0xFF; - buffer[1] = CORSAIR_V2_MODE_DIRECT >> 8; for(std::size_t i = 0; i < count; i++) { RGBColor color = *colors[i]; - std::size_t idx = i + CORSAIR_V2HW_DATA_OFFSET; - buffer[idx] = RGBGetRValue(color); - buffer[idx + green] = RGBGetGValue(color); - buffer[idx + blue] = RGBGetBValue(color); + buffer[i] = RGBGetRValue(color); + buffer[i + green] = RGBGetGValue(color); + buffer[i + blue] = RGBGetBValue(color); } SetLEDs(buffer, length); @@ -66,7 +65,7 @@ void CorsairPeripheralV2HWController::SetLedsDirectColourBlocks(std::vectorcolors) { - uint16_t count = colors.size(); + uint16_t count = (uint16_t)colors.size(); uint16_t length = (count * 3) + CORSAIR_V2HW_DATA_OFFSET; uint8_t* buffer = new uint8_t[length]; diff --git a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.h b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.h index d8011698..9b62dabc 100644 --- a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.h +++ b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.h @@ -1,18 +1,21 @@ -/*---------------------------------------------------------------------*\ -| CorsairPeripheralV2HardwareController.h | -| | -| Driver for the newer Corsair peripherals that use the '08' | -| based USB protocol and support hardware lighting modes. | -| | -| Chris M (Dr_No) 07 Dec 2022 | -\*---------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairPeripheralV2HardwareController.h | +| | +| Driver for Corsair V2 peripherals - hardware modes | +| | +| Chris M (Dr_No) 07 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include "RGBController.h" #include "CorsairPeripheralV2Controller.h" #include -#include +#include #undef CORSAIR_V2_WRITE_SIZE #define CORSAIR_V2_WRITE_SIZE 1025 @@ -21,7 +24,7 @@ class CorsairPeripheralV2HWController : public CorsairPeripheralV2Controller { public: - CorsairPeripheralV2HWController(hid_device* dev_handle, const char* path, std::string name, uint16_t pid); + CorsairPeripheralV2HWController(hid_device* dev_handle, const char* path, std::string name); ~CorsairPeripheralV2HWController(); void SetLedsDirect(std::vector colors); diff --git a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2SoftwareController.cpp b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2SoftwareController.cpp index 03280608..8a1fa8da 100644 --- a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2SoftwareController.cpp +++ b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2SoftwareController.cpp @@ -1,19 +1,21 @@ -/*---------------------------------------------------------------------*\ -| CorsairPeripheralV2SoftwareController.cpp | -| | -| Common driver for the newer Corsair peripherals that use | -| the `08` based USB protocol | -| | -| Chris M (Dr_No) 11 Aug 2022 | -\*---------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairPeripheralV2SoftwareController.cpp | +| | +| Driver for Corsair V2 peripherals - software modes | +| | +| Chris M (Dr_No) 11 Aug 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "LogManager.h" #include "CorsairPeripheralV2SoftwareController.h" -CorsairPeripheralV2SWController::CorsairPeripheralV2SWController(hid_device* dev_handle, const char* path, std::string name, uint16_t pid) : CorsairPeripheralV2Controller(dev_handle, path, name, pid) +CorsairPeripheralV2SWController::CorsairPeripheralV2SWController(hid_device* dev_handle, const char* path, std::string name) : CorsairPeripheralV2Controller(dev_handle, path, name) { SetRenderMode(CORSAIR_V2_MODE_SW); - LightingControl(0x5F, 0x00); + LightingControl(0x5F); } CorsairPeripheralV2SWController::~CorsairPeripheralV2SWController() @@ -23,7 +25,7 @@ CorsairPeripheralV2SWController::~CorsairPeripheralV2SWController() void CorsairPeripheralV2SWController::SetLedsDirect(std::vectorcolors) { - uint16_t count = colors.size(); + uint16_t count = (uint16_t)colors.size(); uint16_t green = count; uint16_t blue = count * 2; uint16_t length = count * 3; diff --git a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2SoftwareController.h b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2SoftwareController.h index ddb79f09..4fdd6ae6 100644 --- a/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2SoftwareController.h +++ b/Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2SoftwareController.h @@ -1,23 +1,26 @@ -/*---------------------------------------------------------------------*\ -| CorsairPeripheralV2SoftwareController.h | -| | -| Common driver for the newer Corsair peripherals that use | -| the `08` based USB protocol | -| | -| Chris M (Dr_No) 11 Aug 2022 | -\*---------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairPeripheralV2SoftwareController.h | +| | +| Driver for Corsair V2 peripherals - software modes | +| | +| Chris M (Dr_No) 11 Aug 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include "RGBController.h" #include "CorsairPeripheralV2Controller.h" #include -#include +#include class CorsairPeripheralV2SWController : public CorsairPeripheralV2Controller { public: - CorsairPeripheralV2SWController(hid_device* dev_handle, const char* path, std::string name, uint16_t pid); + CorsairPeripheralV2SWController(hid_device* dev_handle, const char* path, std::string name); ~CorsairPeripheralV2SWController(); void SetLedsDirect(std::vector colors); diff --git a/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.cpp b/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.cpp index 30f5a809..e6d48006 100644 --- a/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.cpp +++ b/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.cpp @@ -1,11 +1,15 @@ -/*---------------------------------------------------------------------*\ -| RGBController_CorsairV2HardwareController.cpp | -| | -| Driver for the newer Corsair peripherals that use the '08' | -| based USB protocol and support hardware lighting modes. | -| | -| Chris M (Dr_No) 10 Dec 2022 | -\*---------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairV2HardwareController.cpp | +| | +| RGBController for Corsair V2 peripherals - hardware | +| modes | +| | +| Chris M (Dr_No) 10 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "LogManager.h" #include "RGBController_CorsairV2Hardware.h" @@ -27,8 +31,9 @@ RGBController_CorsairV2HW::RGBController_CorsairV2HW(CorsairPeripheralV2Controll controller = controller_ptr; const corsair_v2_device* corsair = controller->GetDeviceData(); + name = controller->GetName(); vendor = "Corsair"; - description = controller->GetName(); + description = "Corsair Peripheral V2 HW Device"; type = corsair->type; version = controller->GetFirmwareString(); location = controller->GetDeviceLocation(); @@ -145,7 +150,6 @@ void RGBController_CorsairV2HW::SetupZones() /*---------------------------------------------------------*\ | Minor adjustments to keyboard layout | \*---------------------------------------------------------*/ - new_zone.leds_count = new_kb.GetKeyCount(); keyboard_keymap_overlay_values* temp = corsair->layout_new; new_kb.ChangeKeys(*temp); @@ -159,7 +163,11 @@ void RGBController_CorsairV2HW::SetupZones() | Create LEDs for the Matrix zone | | Place keys in the layout to populate the matrix | \*---------------------------------------------------------*/ - for(size_t led_idx = 0; led_idx < new_zone.leds_count; led_idx++) + new_zone.leds_count = new_kb.GetKeyCount(); + LOG_DEBUG("[%s] Created KB matrix with %d rows and %d columns containing %d keys", + controller->GetName().c_str(), new_kb.GetRowCount(), new_kb.GetColumnCount(), new_zone.leds_count); + + for(unsigned int led_idx = 0; led_idx < new_zone.leds_count; led_idx++) { led new_led; @@ -189,7 +197,7 @@ void RGBController_CorsairV2HW::SetupZones() new_led.name = new_zone.name + " "; new_led.name.append(std::to_string( led_idx )); - new_led.value = leds.size(); + new_led.value = (unsigned int)leds.size(); leds.push_back(new_led); } @@ -197,7 +205,10 @@ void RGBController_CorsairV2HW::SetupZones() max_led_value = std::max(max_led_value, (unsigned int)leds.size()); } - LOG_DEBUG("[%s] Creating a %s zone: %s with %d LEDs", name.c_str(), + /*---------------------------------------------------------*\ + | name is not set yet so description is used instead | + \*---------------------------------------------------------*/ + LOG_DEBUG("[%s] Creating a %s zone: %s with %d LEDs", description.c_str(), ((new_zone.type == ZONE_TYPE_MATRIX) ? "matrix": "linear"), new_zone.name.c_str(), new_zone.leds_count); new_zone.leds_min = new_zone.leds_count; @@ -258,11 +269,12 @@ void RGBController_CorsairV2HW::KeepaliveThread() { if(active_mode == 0) { - if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50000)) + if((std::chrono::steady_clock::now() - last_update_time) > + std::chrono::milliseconds(CORSAIR_V2_UPDATE_PERIOD)) { DeviceUpdateLEDs(); } } - std::this_thread::sleep_for(30000ms); + std::this_thread::sleep_for(CORSAIR_V2_SLEEP_PERIOD); } } diff --git a/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.h b/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.h index d6cff4a2..947cc239 100644 --- a/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.h +++ b/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.h @@ -1,11 +1,15 @@ -/*---------------------------------------------------------------------*\ -| RGBController_CorsairV2HardwareController.h | -| | -| Driver for the newer Corsair peripherals that use the '08' | -| based USB protocol and support hardware lighting modes. | -| | -| Chris M (Dr_No) 10 Dec 2022 | -\*---------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairV2HardwareController.h | +| | +| RGBController for Corsair V2 peripherals - hardware | +| modes | +| | +| Chris M (Dr_No) 10 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include "RGBController.h" diff --git a/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.cpp b/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.cpp index 43002e87..8d6c5865 100644 --- a/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.cpp +++ b/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.cpp @@ -1,11 +1,14 @@ -/*---------------------------------------------------------------------*\ -| RGBController_CorsairV2SoftwareController.cpp | -| | -| Common driver for the newer Corsair peripherals that use | -| the `08` based USB protocol | -| | -| Chris M (Dr_No) 11 Aug 2022 | -\*---------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairV2SoftwareController.cpp | +| | +| RGBController for Corsair V2 peripherals - software | +| modes | +| | +| Chris M (Dr_No) 11 Aug 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "LogManager.h" #include "RGBController_CorsairV2Software.h" @@ -28,35 +31,20 @@ RGBController_CorsairV2SW::RGBController_CorsairV2SW(CorsairPeripheralV2Controll controller = controller_ptr; const corsair_v2_device* corsair = controller->GetDeviceData(); + name = controller->GetName(); vendor = "Corsair"; - description = controller->GetName(); + description = "Corsair Peripheral V2 SW Device"; type = corsair->type; version = controller->GetFirmwareString(); location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); - if(corsair->protocol & CORSAIR_V2_TYPE_SW_COLOUR_BLOCK) - { - mode Direct; - Direct.name = "Direct"; - Direct.value = CORSAIR_V2_MODE_DIRECT; - 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 = CORSAIR_V2_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Static.colors_min = 1; - Static.colors_max = 1; - Static.colors.resize(Static.colors_max); - Static.brightness_min = CORSAIR_V2_BRIGHTNESS_MIN; - Static.brightness_max = CORSAIR_V2_BRIGHTNESS_MAX; - Static.brightness = CORSAIR_V2_BRIGHTNESS_MAX; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; - modes.push_back(Static); - } + mode Direct; + Direct.name = "Direct"; + Direct.value = CORSAIR_V2_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); SetupZones(); /*-----------------------------------------------------*\ @@ -149,7 +137,6 @@ void RGBController_CorsairV2SW::SetupZones() /*---------------------------------------------------------*\ | Minor adjustments to keyboard layout | \*---------------------------------------------------------*/ - new_zone.leds_count = new_kb.GetKeyCount(); keyboard_keymap_overlay_values* temp = corsair->layout_new; new_kb.ChangeKeys(*temp); @@ -163,7 +150,11 @@ void RGBController_CorsairV2SW::SetupZones() | Create LEDs for the Matrix zone | | Place keys in the layout to populate the matrix | \*---------------------------------------------------------*/ - for(size_t led_idx = 0; led_idx < new_zone.leds_count; led_idx++) + new_zone.leds_count = new_kb.GetKeyCount(); + LOG_DEBUG("[%s] Created KB matrix with %d rows and %d columns containing %d keys", + controller->GetName().c_str(), new_kb.GetRowCount(), new_kb.GetColumnCount(), new_zone.leds_count); + + for(unsigned int led_idx = 0; led_idx < new_zone.leds_count; led_idx++) { led new_led; @@ -193,7 +184,7 @@ void RGBController_CorsairV2SW::SetupZones() new_led.name = new_zone.name + " "; new_led.name.append(std::to_string( led_idx )); - new_led.value = leds.size(); + new_led.value = (unsigned int)leds.size(); leds.push_back(new_led); } @@ -201,7 +192,10 @@ void RGBController_CorsairV2SW::SetupZones() max_led_value = std::max(max_led_value, (unsigned int)leds.size()); } - LOG_DEBUG("[%s] Creating a %s zone: %s with %d LEDs", name.c_str(), + /*---------------------------------------------------------*\ + | name is not set yet so description is used instead | + \*---------------------------------------------------------*/ + LOG_DEBUG("[%s] Creating a %s zone: %s with %d LEDs", description.c_str(), ((new_zone.type == ZONE_TYPE_MATRIX) ? "matrix": "linear"), new_zone.name.c_str(), new_zone.leds_count); new_zone.leds_min = new_zone.leds_count; @@ -262,11 +256,12 @@ void RGBController_CorsairV2SW::KeepaliveThread() { if(active_mode == 0) { - if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50000)) + if((std::chrono::steady_clock::now() - last_update_time) > + std::chrono::milliseconds(CORSAIR_V2_UPDATE_PERIOD)) { DeviceUpdateLEDs(); } } - std::this_thread::sleep_for(30000ms); + std::this_thread::sleep_for(CORSAIR_V2_SLEEP_PERIOD); } } diff --git a/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.h b/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.h index c594eceb..8aeab417 100644 --- a/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.h +++ b/Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.h @@ -1,11 +1,15 @@ -/*---------------------------------------------------------------------*\ -| RGBController_CorsairV2SoftwareController.cpp | -| | -| Common driver for the newer Corsair peripherals that use | -| the `08` based USB protocol | -| | -| Chris M (Dr_No) 11 Aug 2022 | -\*---------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairV2SoftwareController.h | +| | +| RGBController for Corsair V2 peripherals - software | +| modes | +| | +| Chris M (Dr_No) 11 Aug 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include "RGBController.h" diff --git a/Controllers/CorsairVengeanceController/CorsairVengeanceController.cpp b/Controllers/CorsairVengeanceController/CorsairVengeanceController.cpp index 600afebf..da68934a 100644 --- a/Controllers/CorsairVengeanceController/CorsairVengeanceController.cpp +++ b/Controllers/CorsairVengeanceController/CorsairVengeanceController.cpp @@ -1,14 +1,17 @@ -/*-----------------------------------------*\ -| CorsairVengeanceController.h | -| | -| Driver for Corsair Vengeance RGB RAM | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 3/8/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairVengeanceController.cpp | +| | +| Driver for original single-zone Corsair Vengeance DDR4 | +| RGB RAM | +| | +| Adam Honse (CalcProgrammer1) 08 Mar 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "CorsairVengeanceController.h" #include +#include "CorsairVengeanceController.h" CorsairVengeanceController::CorsairVengeanceController(i2c_smbus_interface* bus, corsair_dev_id dev) { diff --git a/Controllers/CorsairVengeanceController/CorsairVengeanceController.h b/Controllers/CorsairVengeanceController/CorsairVengeanceController.h index ef71e1a0..036fe934 100644 --- a/Controllers/CorsairVengeanceController/CorsairVengeanceController.h +++ b/Controllers/CorsairVengeanceController/CorsairVengeanceController.h @@ -1,17 +1,20 @@ -/*-----------------------------------------*\ -| CorsairVengeanceController.h | -| | -| Definitions and types for Corsair | -| Vengeance RGB RAM lighting controller | -| | -| Adam Honse (CalcProgrammer1) 3/8/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairVengeanceController.h | +| | +| Driver for original single-zone Corsair Vengeance DDR4 | +| RGB RAM | +| | +| Adam Honse (CalcProgrammer1) 08 Mar 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" -#pragma once - typedef unsigned char corsair_dev_id; typedef unsigned char corsair_cmd; diff --git a/Controllers/CorsairVengeanceController/CorsairVengeanceControllerDetect.cpp b/Controllers/CorsairVengeanceController/CorsairVengeanceControllerDetect.cpp index 5ca5a70c..04ee9b0d 100644 --- a/Controllers/CorsairVengeanceController/CorsairVengeanceControllerDetect.cpp +++ b/Controllers/CorsairVengeanceController/CorsairVengeanceControllerDetect.cpp @@ -1,12 +1,21 @@ +/*---------------------------------------------------------*\ +| CorsairVengeanceControllerDetect.cpp | +| | +| Detector for original single-zone Corsair Vengeance | +| DDR4 RGB RAM | +| | +| Adam Honse (CalcProgrammer1) 08 Mar 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "CorsairVengeanceController.h" -#include "RGBController.h" #include "RGBController_CorsairVengeance.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include /******************************************************************************************\ * * @@ -47,40 +56,41 @@ bool TestForCorsairVengeanceController(i2c_smbus_interface* bus, unsigned char a * * * Detect Corsair controllers on the enumerated I2C busses. * * * -* bus - pointer to i2c_smbus_interface where Aura device is connected * -* dev - I2C address of Aura device * +* bus - pointer to i2c_smbus_interface where device is connected * +* slots - list of SPD entries with matching JEDEC ID * * * \******************************************************************************************/ -void DetectCorsairVengeanceControllers(std::vector &busses) +void DetectCorsairVengeanceControllers(i2c_smbus_interface* bus, std::vector &slots, const std::string &/*name*/) { - for(unsigned int bus = 0; bus < busses.size(); bus++) + for(SPDWrapper *slot : slots) { - IF_DRAM_SMBUS(busses[bus]->pci_vendor, busses[bus]->pci_device) + /*-------------------------------------------------*\ + | Test first address range 0x58-0x5F | + \*-------------------------------------------------*/ + unsigned char address = slot->address() + 8; + + if(TestForCorsairVengeanceController(bus, address)) { - for(unsigned char addr = 0x58; addr <= 0x5F; addr++) - { - if(TestForCorsairVengeanceController(busses[bus], addr)) - { - CorsairVengeanceController* new_controller = new CorsairVengeanceController(busses[bus], addr); - RGBController_CorsairVengeance* new_rgbcontroller = new RGBController_CorsairVengeance(new_controller); - - ResourceManager::get()->RegisterRGBController(new_rgbcontroller); - } - } - for(unsigned char addr = 0x18; addr <= 0x1F; addr++) - { - if(TestForCorsairVengeanceController(busses[bus], addr)) - { - CorsairVengeanceController* new_controller = new CorsairVengeanceController(busses[bus], addr); - RGBController_CorsairVengeance* new_rgbcontroller = new RGBController_CorsairVengeance(new_controller); - - ResourceManager::get()->RegisterRGBController(new_rgbcontroller); - } - } + CorsairVengeanceController* new_controller = new CorsairVengeanceController(bus, address); + RGBController_CorsairVengeance* new_rgbcontroller = new RGBController_CorsairVengeance(new_controller); + + ResourceManager::get()->RegisterRGBController(new_rgbcontroller); + } + + /*-------------------------------------------------*\ + | Test second address range 0x18-0x1F | + \*-------------------------------------------------*/ + address = slot->address() - 0x40 + 8; + + if(TestForCorsairVengeanceController(bus, address)) + { + CorsairVengeanceController* new_controller = new CorsairVengeanceController(bus, address); + RGBController_CorsairVengeance* new_rgbcontroller = new RGBController_CorsairVengeance(new_controller); + + ResourceManager::get()->RegisterRGBController(new_rgbcontroller); } } - } /* DetectCorsairVengeanceControllers() */ -REGISTER_I2C_DETECTOR("Corsair Vengeance", DetectCorsairVengeanceControllers); +REGISTER_I2C_DIMM_DETECTOR("Corsair Vengeance RGB DRAM", DetectCorsairVengeanceControllers, JEDEC_CORSAIR, SPD_DDR4_SDRAM); diff --git a/Controllers/CorsairVengeanceController/RGBController_CorsairVengeance.cpp b/Controllers/CorsairVengeanceController/RGBController_CorsairVengeance.cpp index a580b49b..5e07238f 100644 --- a/Controllers/CorsairVengeanceController/RGBController_CorsairVengeance.cpp +++ b/Controllers/CorsairVengeanceController/RGBController_CorsairVengeance.cpp @@ -1,11 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_CorsairVengeance.cpp | -| | -| Generic RGB Interface for OpenAuraSDK | -| Corsair Vengeance RGB driver | -| | -| Adam Honse (CalcProgrammer1) 6/13/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairVengeance.cpp | +| | +| RGBController for original single-zone Corsair | +| Vengeance DDR4 RGB RAM | +| | +| Adam Honse (CalcProgrammer1) 16 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CorsairVengeance.h" diff --git a/Controllers/CorsairVengeanceController/RGBController_CorsairVengeance.h b/Controllers/CorsairVengeanceController/RGBController_CorsairVengeance.h index ce2209bc..ed04ef8f 100644 --- a/Controllers/CorsairVengeanceController/RGBController_CorsairVengeance.h +++ b/Controllers/CorsairVengeanceController/RGBController_CorsairVengeance.h @@ -1,11 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_CorsairVengeance.h | -| | -| Generic RGB Interface for OpenAuraSDK | -| Corsair Vengeance RGB driver | -| | -| Adam Honse (CalcProgrammer1) 6/13/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairVengeance.h | +| | +| RGBController for original single-zone Corsair | +| Vengeance DDR4 RGB RAM | +| | +| Adam Honse (CalcProgrammer1) 16 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/CorsairVengeanceProController/CorsairVengeanceProController.cpp b/Controllers/CorsairVengeanceProController/CorsairVengeanceProController.cpp index cfb2e59e..9b7cdef0 100644 --- a/Controllers/CorsairVengeanceProController/CorsairVengeanceProController.cpp +++ b/Controllers/CorsairVengeanceProController/CorsairVengeanceProController.cpp @@ -1,14 +1,17 @@ -/*-----------------------------------------*\ -| CorsairVengeanceProController.cpp | -| | -| Definitions and types for Corsair | -| Vengeance Pro RGB RAM lighting controller| -| | -| Adam Honse (CalcProgrammer1) 6/30/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairVengeanceProController.cpp | +| | +| Driver for Corsair Vengeance Pro RGB RAM | +| | +| Adam Honse (CalcProgrammer1) 30 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "CorsairVengeanceProController.h" #include +#include +#include "CorsairVengeanceProController.h" using namespace std::chrono_literals; @@ -22,7 +25,7 @@ CorsairVengeanceProController::CorsairVengeanceProController(i2c_smbus_interface direct_mode = false; effect_mode = CORSAIR_PRO_MODE_STATIC; - + for (unsigned int i = 0; i < led_count; i++) { led_red[i] = 0; diff --git a/Controllers/CorsairVengeanceProController/CorsairVengeanceProController.h b/Controllers/CorsairVengeanceProController/CorsairVengeanceProController.h index fd9cc0a9..6035b28f 100644 --- a/Controllers/CorsairVengeanceProController/CorsairVengeanceProController.h +++ b/Controllers/CorsairVengeanceProController/CorsairVengeanceProController.h @@ -1,18 +1,20 @@ -/*-----------------------------------------*\ -| CorsairVengeanceProController.h | -| | -| Definitions and types for Corsair | -| Vengeance Pro RGB RAM lighting controller| -| | -| Adam Honse (CalcProgrammer1) 6/30/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| CorsairVengeanceProController.h | +| | +| Driver for Corsair Vengeance Pro RGB RAM | +| | +| Adam Honse (CalcProgrammer1) 30 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" #include "CRC.h" -#pragma once - typedef unsigned char corsair_dev_id; #define CORSAIR_PRO_LED_COUNT ( 10 ) diff --git a/Controllers/CorsairVengeanceProController/CorsairVengeanceProControllerDetect.cpp b/Controllers/CorsairVengeanceProController/CorsairVengeanceProControllerDetect.cpp index b7a37ef1..59c63489 100644 --- a/Controllers/CorsairVengeanceProController/CorsairVengeanceProControllerDetect.cpp +++ b/Controllers/CorsairVengeanceProController/CorsairVengeanceProControllerDetect.cpp @@ -1,13 +1,21 @@ +/*---------------------------------------------------------*\ +| CorsairVengeanceProControllerDetect.cpp | +| | +| Detector for Corsair Vengeance Pro RGB RAM | +| | +| Adam Honse (CalcProgrammer1) 30 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "CorsairVengeanceProController.h" -#include "RGBController.h" #include "RGBController_CorsairVengeancePro.h" #include "i2c_smbus.h" #include "pci_ids.h" #include "LogManager.h" -#include -#include -#include using namespace std::chrono_literals; diff --git a/Controllers/CorsairVengeanceProController/RGBController_CorsairVengeancePro.cpp b/Controllers/CorsairVengeanceProController/RGBController_CorsairVengeancePro.cpp index 5be32c43..f87b6ab1 100644 --- a/Controllers/CorsairVengeanceProController/RGBController_CorsairVengeancePro.cpp +++ b/Controllers/CorsairVengeanceProController/RGBController_CorsairVengeancePro.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_CorsairVengeancePro.cpp | -| | -| Generic RGB Interface for OpenAuraSDK | -| Corsair Vengeance Pro RGB driver | -| | -| Adam Honse (CalcProgrammer1) 6/30/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairVengeancePro.cpp | +| | +| RGBController for Corsair Vengeance Pro RGB RAM | +| | +| Adam Honse (CalcProgrammer1) 30 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CorsairVengeancePro.h" @@ -213,7 +215,7 @@ void RGBController_CorsairVengeancePro::ResizeZone(int /*zone*/, int /*new_size* void RGBController_CorsairVengeancePro::DeviceUpdateLEDs() { - for(std::size_t led = 0; led < colors.size(); led++) + for(unsigned int led = 0; led < (unsigned int)colors.size(); led++) { RGBColor color = colors[led]; unsigned char red = RGBGetRValue(color); diff --git a/Controllers/CorsairVengeanceProController/RGBController_CorsairVengeancePro.h b/Controllers/CorsairVengeanceProController/RGBController_CorsairVengeancePro.h index 606e0105..353cdffb 100644 --- a/Controllers/CorsairVengeanceProController/RGBController_CorsairVengeancePro.h +++ b/Controllers/CorsairVengeanceProController/RGBController_CorsairVengeancePro.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_CorsairVengeancePro.h | -| | -| Generic RGB Interface for OpenAuraSDK | -| Corsair Vengeance Pro RGB driver | -| | -| Adam Honse (CalcProgrammer1) 6/30/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairVengeancePro.h | +| | +| RGBController for Corsair Vengeance Pro RGB RAM | +| | +| Adam Honse (CalcProgrammer1) 30 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/CorsairWirelessController/CorsairWirelessController.cpp b/Controllers/CorsairWirelessController/CorsairWirelessController.cpp index 0173e317..ead3e09a 100644 --- a/Controllers/CorsairWirelessController/CorsairWirelessController.cpp +++ b/Controllers/CorsairWirelessController/CorsairWirelessController.cpp @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| CorsairWirelessController.cpp | -| | -| Driver for Corsair RGB wireless keyboard | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 5/8/2021 | -\*-----------------------------------------*/ - -#include "CorsairWirelessController.h" +/*---------------------------------------------------------*\ +| CorsairWirelessController.cpp | +| | +| Driver for Corsair wireless keyboard | +| | +| Adam Honse (CalcProgrammer1) 08 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "CorsairWirelessController.h" +#include "StringUtils.h" using namespace std::chrono_literals; @@ -58,10 +60,7 @@ std::string CorsairWirelessController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void CorsairWirelessController::SetLEDs(std::vectorcolors) @@ -97,7 +96,7 @@ void CorsairWirelessController::SetName(std::string device_name) void CorsairWirelessController::EnterDirectMode() { - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -118,13 +117,13 @@ void CorsairWirelessController::EnterDirectMode() | Send packet using feature reports, as headset stand | | seems to not update completely using HID writes | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, 65); + hid_write(dev, usb_buf, 65); } void CorsairWirelessController::StartDirectMode() { - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -144,13 +143,13 @@ void CorsairWirelessController::StartDirectMode() | Send packet using feature reports, as headset stand | | seems to not update completely using HID writes | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, 65); + hid_write(dev, usb_buf, 65); } void CorsairWirelessController::ExitDirectMode() { - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -171,13 +170,13 @@ void CorsairWirelessController::ExitDirectMode() | Send packet using feature reports, as headset stand | | seems to not update completely using HID writes | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, 65); + hid_write(dev, usb_buf, 65); } void CorsairWirelessController::SendDirectFrame(bool first_frame, unsigned char* data) { - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -214,5 +213,5 @@ void CorsairWirelessController::SendDirectFrame(bool first_frame, unsigned char* | Send packet using feature reports, as headset stand | | seems to not update completely using HID writes | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, 65); + hid_write(dev, usb_buf, 65); } diff --git a/Controllers/CorsairWirelessController/CorsairWirelessController.h b/Controllers/CorsairWirelessController/CorsairWirelessController.h index f60a8b72..fc6da913 100644 --- a/Controllers/CorsairWirelessController/CorsairWirelessController.h +++ b/Controllers/CorsairWirelessController/CorsairWirelessController.h @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| CorsairWirelessController.h | -| | -| Definitions and types for Corsair RGB | -| wireless keyboard lighting controller | -| | -| Adam Honse (CalcProgrammer1) 5/8/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| CorsairWirelessController.h | +| | +| Driver for Corsair wireless keyboard | +| | +| Adam Honse (CalcProgrammer1) 08 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + class CorsairWirelessController { public: diff --git a/Controllers/CorsairWirelessController/CorsairWirelessControllerDetect.cpp b/Controllers/CorsairWirelessController/CorsairWirelessControllerDetect.cpp index a5ee2262..2a67a679 100644 --- a/Controllers/CorsairWirelessController/CorsairWirelessControllerDetect.cpp +++ b/Controllers/CorsairWirelessController/CorsairWirelessControllerDetect.cpp @@ -1,8 +1,19 @@ +/*---------------------------------------------------------*\ +| CorsairWirelessControllerDetect.cpp | +| | +| Detector for Corsair wireless keyboard | +| | +| Adam Honse (CalcProgrammer1) 08 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "CorsairWirelessController.h" #include "RGBController.h" #include "RGBController_CorsairWireless.h" -#include /*-----------------------------------------------------*\ | Corsair vendor ID | diff --git a/Controllers/CorsairWirelessController/RGBController_CorsairWireless.cpp b/Controllers/CorsairWirelessController/RGBController_CorsairWireless.cpp index c9d96d1c..bad5dff9 100644 --- a/Controllers/CorsairWirelessController/RGBController_CorsairWireless.cpp +++ b/Controllers/CorsairWirelessController/RGBController_CorsairWireless.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_CorsairWireless.cpp | -| | -| Generic RGB Interface for Corsair RGB | -| wireless keyboard devices | -| | -| Adam Honse (CalcProgrammer1) 5/8/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairWireless.cpp | +| | +| RGBController for Corsair wireless keyboard | +| | +| Adam Honse (CalcProgrammer1) 08 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_CorsairWireless.h" diff --git a/Controllers/CorsairWirelessController/RGBController_CorsairWireless.h b/Controllers/CorsairWirelessController/RGBController_CorsairWireless.h index 49c1709f..6a507f0e 100644 --- a/Controllers/CorsairWirelessController/RGBController_CorsairWireless.h +++ b/Controllers/CorsairWirelessController/RGBController_CorsairWireless.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_CorsairWireless.h | -| | -| Generic RGB Interface for Corsair RGB | -| wireless keyboard devices | -| | -| Adam Honse (CalcProgrammer1) 5/8/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CorsairWireless.h | +| | +| RGBController for Corsair wireless keyboard | +| | +| Adam Honse (CalcProgrammer1) 08 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "CorsairWirelessController.h" diff --git a/Controllers/CougarController/CougarControllerDetect.cpp b/Controllers/CougarController/CougarControllerDetect.cpp index a9c88a35..65758431 100644 --- a/Controllers/CougarController/CougarControllerDetect.cpp +++ b/Controllers/CougarController/CougarControllerDetect.cpp @@ -1,6 +1,13 @@ -#include "Detector.h" -#include "RGBController.h" +/*---------------------------------------------------------*\ +| CougarControllerDetect.cpp | +| | +| Detector for Cougar devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include "Detector.h" #include "RGBController_CougarKeyboard.h" #include "RGBController_CougarRevengerST.h" @@ -22,28 +29,25 @@ void DetectCougarRevengerSTControllers(hid_device_info* info, const std::string& if(dev) { - CougarRevengerSTController* controller = new CougarRevengerSTController(dev, *info); + CougarRevengerSTController* controller = new CougarRevengerSTController(dev, *info, name); RGBController_CougarRevengerST* rgb_controller = new RGBController_CougarRevengerST(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } - void DetectCougar700kEvo(hid_device_info* info, const std::string& name) { hid_device* dev = hid_open_path(info->path); if (dev) { - CougarKeyboardController* controller = new CougarKeyboardController(dev, info->path); + CougarKeyboardController* controller = new CougarKeyboardController(dev, info->path, name); RGBController_CougarKeyboard* rgb_controller = new RGBController_CougarKeyboard(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } - REGISTER_HID_DETECTOR_IPU("Cougar 700K EVO Gaming Keyboard", DetectCougar700kEvo, COUGAR_VID_2, COUGAR_700K_EVO_PID, 3, 0xFF00, 1); REGISTER_HID_DETECTOR_IPU("Cougar Revenger ST", DetectCougarRevengerSTControllers, COUGAR_VID, COUGAR_REVENGER_ST_PID, 0, 0x0001, 2); diff --git a/Controllers/CougarController/CougarKeyboardController.cpp b/Controllers/CougarController/CougarKeyboardController/CougarKeyboardController.cpp similarity index 84% rename from Controllers/CougarController/CougarKeyboardController.cpp rename to Controllers/CougarController/CougarKeyboardController/CougarKeyboardController.cpp index 3fe1f951..b2df09a8 100644 --- a/Controllers/CougarController/CougarKeyboardController.cpp +++ b/Controllers/CougarController/CougarKeyboardController/CougarKeyboardController.cpp @@ -1,13 +1,17 @@ -/*-------------------------------------------------------------------*\ -| CougarKeyboardController.cpp | -| | -| Driver for CougarKeyboard USB Controller | -| | -| Chris M (DrNo) 5 Apr 2022 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| CougarKeyboardController.cpp | +| | +| Driver for Cougar keyboard | +| | +| Chris M (DrNo) 05 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include #include "CougarKeyboardController.h" +#include "StringUtils.h" using namespace std::chrono_literals; @@ -50,21 +54,11 @@ static uint8_t keyvalue_map[113] = 149, 150, 151 }; -CougarKeyboardController::CougarKeyboardController(hid_device* dev_handle, const char* path) +CougarKeyboardController::CougarKeyboardController(hid_device* dev_handle, const char* path, std::string dev_name) { - const uint8_t sz = HID_MAX_STR; - wchar_t tmp[sz]; - dev = dev_handle; location = path; - - hid_get_manufacturer_string(dev, tmp, sz); - std::wstring wName = std::wstring(tmp); - device_name = std::string(wName.begin(), wName.end()); - - hid_get_product_string(dev, tmp, sz); - wName = std::wstring(tmp); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); + name = dev_name; } CougarKeyboardController::~CougarKeyboardController() @@ -74,25 +68,20 @@ CougarKeyboardController::~CougarKeyboardController() std::string CougarKeyboardController::GetDeviceName() { - return device_name; + return(name); } std::string CougarKeyboardController::GetSerial() { - const uint8_t sz = HID_MAX_STR; - wchar_t tmp[sz]; + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); - int ret = hid_get_serial_number_string(dev, tmp, sz); - - if (ret != 0) + if(ret != 0) { return(""); } - std::wstring w_tmp = std::wstring(tmp); - std::string serial = std::string(w_tmp.begin(), w_tmp.end()); - - return serial; + return(StringUtils::wstring_to_string(serial_string)); } std::string CougarKeyboardController::GetLocation() @@ -137,11 +126,11 @@ void CougarKeyboardController::SetMode(uint8_t mode, uint8_t speed, uint8_t brig case COUGARKEYBOARDCONTROLLER_MODE_RIPPLE: case COUGARKEYBOARDCONTROLLER_MODE_SCAN: { - uint8_t count = colours.size(); + uint8_t count = (uint8_t)colours.size(); uint8_t timer = 100 / count; buffer[COUGARKEYBOARDCONTROLLER_DATA_BYTE + 1] = count; - for(size_t i = 0; i < count; i++) + for(uint8_t i = 0; i < count; i++) { uint8_t offset = 11 + (i * 4); @@ -169,7 +158,7 @@ void CougarKeyboardController::SetMode(uint8_t mode, uint8_t speed, uint8_t brig void CougarKeyboardController::SetLedsDirect(std::vector colours) { uint8_t max_leds = 14; - uint8_t leds_remaining = colours.size(); + uint8_t leds_remaining = (uint8_t)colours.size(); uint8_t packet_flag = COUGARKEYBOARDCONTROLLER_DIRECTION_BYTE; uint8_t buffer[COUGARKEYBOARDCONTROLLER_WRITE_PACKET_SIZE] = { 0x00, 0x14, 0x2C, 0x0B, 0x00, 0xFF, 0x64, 0x00, 0x01 }; @@ -177,7 +166,7 @@ void CougarKeyboardController::SetLedsDirect(std::vector colours) | Set up Direct packet | | keyvalue_map is the index of the Key from full_matrix_map | \*-----------------------------------------------------------------*/ - for(size_t leds2send = 0; leds2send < leds_remaining; leds2send += max_leds) + for(uint8_t leds2send = 0; leds2send < leds_remaining; leds2send += max_leds) { /*-----------------------------------------------------------------*\ | Check if there is enough leds for another pass | @@ -192,7 +181,7 @@ void CougarKeyboardController::SetLedsDirect(std::vector colours) buffer[packet_flag] = 3; } - for(size_t i = 0; i < max_leds; i++) + for(uint8_t i = 0; i < max_leds; i++) { uint8_t offset = COUGARKEYBOARDCONTROLLER_DATA_BYTE + (i * 4); uint8_t led_num = leds2send + i; diff --git a/Controllers/CougarController/CougarKeyboardController.h b/Controllers/CougarController/CougarKeyboardController/CougarKeyboardController.h similarity index 80% rename from Controllers/CougarController/CougarKeyboardController.h rename to Controllers/CougarController/CougarKeyboardController/CougarKeyboardController.h index 7120ec34..2945d5ce 100644 --- a/Controllers/CougarController/CougarKeyboardController.h +++ b/Controllers/CougarController/CougarKeyboardController/CougarKeyboardController.h @@ -1,17 +1,20 @@ -/*-------------------------------------------------------------------*\ -| CougarKeyboardController.h | -| | -| Driver for CougarKeyboard USB Controller | -| | -| Chris M (DrNo) 5 Apr 2022 | -\*-------------------------------------------------------------------*/ - -#include -#include -#include "RGBController.h" +/*---------------------------------------------------------*\ +| CougarKeyboardController.h | +| | +| Driver for Cougar keyboard | +| | +| Chris M (DrNo) 05 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + #define COUGARKEYBOARDCONTROLLER_WRITE_PACKET_SIZE 65 //Buffer requires a prepended ReportID hence + 1 #define HID_MAX_STR 255 @@ -63,7 +66,7 @@ enum Cougar_Keyboard_Controller_Speeds class CougarKeyboardController { public: - CougarKeyboardController(hid_device* dev_handle, const char* path); + CougarKeyboardController(hid_device* dev_handle, const char* path, std::string dev_name); ~CougarKeyboardController(); std::string GetDeviceName(); @@ -75,8 +78,8 @@ public: void Save(uint8_t flag); void SendProfile(uint8_t profile, uint8_t light); private: - std::string device_name; std::string serial; std::string location; + std::string name; hid_device* dev; }; diff --git a/Controllers/CougarController/RGBController_CougarKeyboard.cpp b/Controllers/CougarController/CougarKeyboardController/RGBController_CougarKeyboard.cpp similarity index 96% rename from Controllers/CougarController/RGBController_CougarKeyboard.cpp rename to Controllers/CougarController/CougarKeyboardController/RGBController_CougarKeyboard.cpp index 9b59c739..cc8ca4ae 100644 --- a/Controllers/CougarController/RGBController_CougarKeyboard.cpp +++ b/Controllers/CougarController/CougarKeyboardController/RGBController_CougarKeyboard.cpp @@ -1,10 +1,13 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CougarKeyboard.cpp | -| | -| Driver for CougarKeyboard USB Controller | -| | -| Chris M (DrNo) 5 Apr 2022 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CougarKeyboard.cpp | +| | +| RGBController for Cougar keyboard | +| | +| Chris M (DrNo) 05 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #define NA 0xFFFFFFFF @@ -167,10 +170,10 @@ RGBController_CougarKeyboard::RGBController_CougarKeyboard(CougarKeyboardControl { controller = controller_ptr; - name = "CougarKeyboard"; + name = controller->GetDeviceName(); vendor = "Cougar"; type = DEVICE_TYPE_KEYBOARD; - description = controller->GetDeviceName(); + description = "Cougar Keyboard Device"; serial = controller->GetSerial(); location = controller->GetLocation(); diff --git a/Controllers/CougarController/CougarKeyboardController/RGBController_CougarKeyboard.h b/Controllers/CougarController/CougarKeyboardController/RGBController_CougarKeyboard.h new file mode 100644 index 00000000..cc4bf6d3 --- /dev/null +++ b/Controllers/CougarController/CougarKeyboardController/RGBController_CougarKeyboard.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------*\ +| RGBController_CougarKeyboard.h | +| | +| RGBController for Cougar keyboard | +| | +| Chris M (DrNo) 05 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "LogManager.h" +#include "RGBController.h" +#include "CougarKeyboardController.h" + +class RGBController_CougarKeyboard : public RGBController +{ +public: + RGBController_CougarKeyboard(CougarKeyboardController* controller_ptr); + ~RGBController_CougarKeyboard(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + int GetDeviceMode(); + int GetLED_Zone(int led_idx); + + CougarKeyboardController* controller; +}; diff --git a/Controllers/CougarController/CougarRevengerSTController.cpp b/Controllers/CougarController/CougarRevengerSTController/CougarRevengerSTController.cpp similarity index 86% rename from Controllers/CougarController/CougarRevengerSTController.cpp rename to Controllers/CougarController/CougarRevengerSTController/CougarRevengerSTController.cpp index 2d42c94f..5409065b 100644 --- a/Controllers/CougarController/CougarRevengerSTController.cpp +++ b/Controllers/CougarController/CougarRevengerSTController/CougarRevengerSTController.cpp @@ -1,33 +1,25 @@ -/*-----------------------------------------*\ -| CougarRevengerSTController.cpp | -| | -| Driver for Cougar Revenger ST lighting | -| controller | -| | -| Guimard Morgan (morg) 3/17/2022 | -\*-----------------------------------------*/ -#include "CougarRevengerSTController.h" -#include +/*---------------------------------------------------------*\ +| CougarRevengerSTController.cpp | +| | +| Driver for Cougar Revenger ST | +| | +| Morgan Guimard (morg) 17 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -CougarRevengerSTController::CougarRevengerSTController(hid_device* dev_handle, const hid_device_info& info) +#include +#include "CougarRevengerSTController.h" +#include "StringUtils.h" + +CougarRevengerSTController::CougarRevengerSTController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) { dev = dev_handle; location = info.path; + name = dev_name; version = ""; - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } - ActivateMode(0, DIRECT_MODE_VALUE); ActivateMode(1, DIRECT_MODE_VALUE); ActivateMode(2, DIRECT_MODE_VALUE); @@ -43,9 +35,22 @@ std::string CougarRevengerSTController::GetDeviceLocation() return("HID: " + location); } +std::string CougarRevengerSTController::GetNameString() +{ + return(name); +} + std::string CougarRevengerSTController::GetSerialString() { - return(serial_number); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } std::string CougarRevengerSTController::GetFirmwareVersion() @@ -81,7 +86,7 @@ void CougarRevengerSTController::SetDirect(unsigned char zone, RGBColor color, u } void CougarRevengerSTController::SetModeData(unsigned char zone, unsigned char mode_value, std::vector colors, unsigned char brightness, unsigned char speed) -{ +{ unsigned char usb_buf[PACKET_DATA_LENGTH]; const cougar_mode& m = modes_mapping.at(mode_value); @@ -195,7 +200,7 @@ void CougarRevengerSTController::ActivateMode(unsigned char zone, unsigned char } void CougarRevengerSTController::Apply() -{ +{ unsigned char usb_buf[PACKET_DATA_LENGTH]; memset(usb_buf, 0x00, PACKET_DATA_LENGTH); diff --git a/Controllers/CougarController/CougarRevengerSTController.h b/Controllers/CougarController/CougarRevengerSTController/CougarRevengerSTController.h similarity index 84% rename from Controllers/CougarController/CougarRevengerSTController.h rename to Controllers/CougarController/CougarRevengerSTController/CougarRevengerSTController.h index ae3cf151..85482e9a 100644 --- a/Controllers/CougarController/CougarRevengerSTController.h +++ b/Controllers/CougarController/CougarRevengerSTController/CougarRevengerSTController.h @@ -1,17 +1,20 @@ -/*-----------------------------------------*\ -| CougarRevengerSTController.h | -| | -| Driver for Cougar Revenger ST lighting | -| controller - header file | -| | -| Guimard Morgan (morg) 3/17/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| CougarRevengerSTController.h | +| | +| Driver for Cougar Revenger ST | +| | +| Morgan Guimard (morg) 17 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include "RGBController.h" #include #include -#include +#include #define PACKET_DATA_LENGTH 9 @@ -225,12 +228,13 @@ static const std::map modes_mapping = class CougarRevengerSTController { public: - CougarRevengerSTController(hid_device* dev_handle, const hid_device_info& info); + CougarRevengerSTController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); ~CougarRevengerSTController(); std::string GetSerialString(); std::string GetDeviceLocation(); std::string GetFirmwareVersion(); + std::string GetNameString(); void ActivateMode(unsigned char zone, unsigned char mode_value); void SetDirect(unsigned char zone, RGBColor color, unsigned char brightness); @@ -239,7 +243,7 @@ public: private: hid_device* dev; std::string location; - std::string serial_number; + std::string name; std::string version; void Apply(); diff --git a/Controllers/CougarController/RGBController_CougarRevengerST.cpp b/Controllers/CougarController/CougarRevengerSTController/RGBController_CougarRevengerST.cpp similarity index 89% rename from Controllers/CougarController/RGBController_CougarRevengerST.cpp rename to Controllers/CougarController/CougarRevengerSTController/RGBController_CougarRevengerST.cpp index 5ec48c23..89966da6 100644 --- a/Controllers/CougarController/RGBController_CougarRevengerST.cpp +++ b/Controllers/CougarController/CougarRevengerSTController/RGBController_CougarRevengerST.cpp @@ -1,16 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_CougarRevengerST.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Cougar Revenger ST USB Driver | -| | -| Guimard Morgan (morg) 3/17/2022 | -\*-----------------------------------------*/ - -#include "RGBController_CougarRevengerST.h" +/*---------------------------------------------------------*\ +| RGBController_CougarRevengerST.cpp | +| | +| RGBController for Cougar Revenger ST | +| | +| Morgan Guimard (morg) 17 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include #include +#include "RGBController_CougarRevengerST.h" /**------------------------------------------------------------------*\ @name Cougar Revenger ST @@ -27,10 +28,10 @@ RGBController_CougarRevengerST::RGBController_CougarRevengerST(CougarRevengerSTC { controller = controller_ptr; - name = "Cougar Revenger ST USB Device"; + name = controller->GetNameString(); vendor = "Cougar"; type = DEVICE_TYPE_MOUSE; - description = name; + description = "Cougar Revenger ST Device"; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); version = controller->GetFirmwareVersion(); diff --git a/Controllers/CougarController/CougarRevengerSTController/RGBController_CougarRevengerST.h b/Controllers/CougarController/CougarRevengerSTController/RGBController_CougarRevengerST.h new file mode 100644 index 00000000..b621c2ea --- /dev/null +++ b/Controllers/CougarController/CougarRevengerSTController/RGBController_CougarRevengerST.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_CougarRevengerST.h | +| | +| RGBController for Cougar Revenger ST | +| | +| Morgan Guimard (morg) 17 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "CougarRevengerSTController.h" + +class RGBController_CougarRevengerST : public RGBController +{ +public: + RGBController_CougarRevengerST(CougarRevengerSTController* controller_ptr); + ~RGBController_CougarRevengerST(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + CougarRevengerSTController* controller; +}; diff --git a/Controllers/CougarController/RGBController_CougarKeyboard.h b/Controllers/CougarController/RGBController_CougarKeyboard.h deleted file mode 100644 index a546f466..00000000 --- a/Controllers/CougarController/RGBController_CougarKeyboard.h +++ /dev/null @@ -1,36 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_CougarKeyboardController.h | -| | -| Driver for CougarKeyboard USB Controller | -| | -| Chris M (DrNo) 5 Apr 2022 | -\*-------------------------------------------------------------------*/ - -#pragma once -#include "LogManager.h" -#include "RGBController.h" -#include "CougarKeyboardController.h" -#include - -class RGBController_CougarKeyboard : public RGBController -{ -public: - RGBController_CougarKeyboard(CougarKeyboardController* controller_ptr); - ~RGBController_CougarKeyboard(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - int GetDeviceMode(); - int GetLED_Zone(int led_idx); - - CougarKeyboardController* controller; -}; diff --git a/Controllers/CougarController/RGBController_CougarRevengerST.h b/Controllers/CougarController/RGBController_CougarRevengerST.h deleted file mode 100644 index 77897078..00000000 --- a/Controllers/CougarController/RGBController_CougarRevengerST.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_CougarRevengerST.h | -| | -| Generic RGB Interface for OpenRGB | -| Cougar Revenger ST USB Driver | -| | -| Guimard Morgan (morg) 3/17/2022 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "CougarRevengerSTController.h" - -class RGBController_CougarRevengerST : public RGBController -{ -public: - RGBController_CougarRevengerST(CougarRevengerSTController* controller_ptr); - ~RGBController_CougarRevengerST(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - CougarRevengerSTController* controller; -}; diff --git a/Controllers/CreativeController/CreativeControllerDetect.cpp b/Controllers/CreativeController/CreativeControllerDetect.cpp index a02a7ec7..26bdbd18 100644 --- a/Controllers/CreativeController/CreativeControllerDetect.cpp +++ b/Controllers/CreativeController/CreativeControllerDetect.cpp @@ -1,7 +1,16 @@ +/*---------------------------------------------------------*\ +| CreativeControllerDetect.cpp | +| | +| Detector for Creative devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "CreativeSoundBlasterXG6Controller.h" #include "RGBController_CreativeSoundBlasterXG6.h" #include "Detector.h" -#include /*-----------------------------------------------------*\ | Creative vendor ID | @@ -15,12 +24,12 @@ void DetectCreativeDevice(hid_device_info* info, const std::string& name) { hid_device* dev = hid_open_path(info->path); - + if(dev) { - CreativeSoundBlasterXG6Controller* controller = new CreativeSoundBlasterXG6Controller(dev, info->path); + CreativeSoundBlasterXG6Controller* controller = new CreativeSoundBlasterXG6Controller(dev, info->path, name); RGBController_CreativeSoundBlasterXG6* rgb_controller = new RGBController_CreativeSoundBlasterXG6(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } diff --git a/Controllers/CreativeController/CreativeSoundBlasterXG6Controller.cpp b/Controllers/CreativeController/CreativeSoundBlasterXG6Controller.cpp index 2680970f..6db11fbb 100644 --- a/Controllers/CreativeController/CreativeSoundBlasterXG6Controller.cpp +++ b/Controllers/CreativeController/CreativeSoundBlasterXG6Controller.cpp @@ -1,9 +1,19 @@ +/*---------------------------------------------------------*\ +| CreativeSoundBlasterXG6Controller.cpp | +| | +| Driver for Creative SoundBlaster XG6 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "CreativeSoundBlasterXG6Controller.h" -CreativeSoundBlasterXG6Controller::CreativeSoundBlasterXG6Controller(hid_device* dev_handle, const char* path) +CreativeSoundBlasterXG6Controller::CreativeSoundBlasterXG6Controller(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } CreativeSoundBlasterXG6Controller::~CreativeSoundBlasterXG6Controller() @@ -16,7 +26,15 @@ std::string CreativeSoundBlasterXG6Controller::GetDeviceLocation() return("HID " + location); } -void CreativeSoundBlasterXG6Controller::SetLedColor (unsigned char red, unsigned char green, unsigned char blue) +std::string CreativeSoundBlasterXG6Controller::GetDeviceName() +{ + return(name); +} + +void CreativeSoundBlasterXG6Controller::SetLedColor (unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char brightness) { unsigned char usb_buf[64]; @@ -69,7 +87,7 @@ void CreativeSoundBlasterXG6Controller::SetLedColor (unsigned char red, unsigned usb_buf[0x06] = 0x03; usb_buf[0x07] = 0x01; usb_buf[0x08] = 0x01; - usb_buf[0x09] = 0x0FF; + usb_buf[0x09] = brightness; usb_buf[0x0A] = blue; usb_buf[0x0B] = green; diff --git a/Controllers/CreativeController/CreativeSoundBlasterXG6Controller.h b/Controllers/CreativeController/CreativeSoundBlasterXG6Controller.h index e3b3affb..b3b7db84 100644 --- a/Controllers/CreativeController/CreativeSoundBlasterXG6Controller.h +++ b/Controllers/CreativeController/CreativeSoundBlasterXG6Controller.h @@ -1,20 +1,35 @@ -#include "RGBController.h" -#include -#include +/*---------------------------------------------------------*\ +| CreativeSoundBlasterXG6Controller.h | +| | +| Driver for Creative SoundBlaster XG6 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + class CreativeSoundBlasterXG6Controller { public: - CreativeSoundBlasterXG6Controller(hid_device* dev_handle, const char* path); + CreativeSoundBlasterXG6Controller(hid_device* dev_handle, const char* path, std::string dev_name); ~CreativeSoundBlasterXG6Controller(); - void SetLedColor (unsigned char red, unsigned char green, unsigned char blue); - std::string GetDeviceLocation(); - std::string GetSerialString(); + void SetLedColor(unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char brightness); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + std::string GetSerialString(); private: hid_device* dev; std::string location; + std::string name; }; diff --git a/Controllers/CreativeController/RGBController_CreativeSoundBlasterXG6.cpp b/Controllers/CreativeController/RGBController_CreativeSoundBlasterXG6.cpp index 4b1da93a..8a4ab5c8 100644 --- a/Controllers/CreativeController/RGBController_CreativeSoundBlasterXG6.cpp +++ b/Controllers/CreativeController/RGBController_CreativeSoundBlasterXG6.cpp @@ -1,3 +1,12 @@ +/*---------------------------------------------------------*\ +| RGBController_CreativeSoundBlasterXG6.cpp | +| | +| RGBController for Creative SoundBlaster XG6 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "RGBController_CreativeSoundBlasterXG6.h" /**------------------------------------------------------------------*\ @@ -13,20 +22,23 @@ RGBController_CreativeSoundBlasterXG6::RGBController_CreativeSoundBlasterXG6(CreativeSoundBlasterXG6Controller* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Creative SoundBlasterX G6 Device"; - vendor = "Creative"; - type = DEVICE_TYPE_HEADSET; - description = "Creative SoundBlasterX G6 Device"; - location = controller->GetDeviceLocation(); - serial = ""; + name = controller->GetDeviceName(); + vendor = "Creative"; + type = DEVICE_TYPE_HEADSET; + description = "Creative SoundBlasterX G6 Device"; + location = controller->GetDeviceLocation(); + serial = ""; mode Static; - Static.name = "Direct"; - Static.value = 0; - Static.flags = MODE_COLORS_PER_LED; - Static.color_mode = MODE_COLORS_PER_LED; + Static.name = "Direct"; + Static.value = 0; + Static.flags = MODE_COLORS_PER_LED | MODE_FLAG_HAS_BRIGHTNESS; + Static.color_mode = MODE_COLORS_PER_LED; + Static.brightness_min = XG6_BRIGHTNESS_MIN; + Static.brightness_max = XG6_BRIGHTNESS_MAX; + Static.brightness = XG6_BRIGHTNESS_MAX; modes.push_back(Static); SetupZones(); @@ -68,7 +80,7 @@ void RGBController_CreativeSoundBlasterXG6::DeviceUpdateLEDs() unsigned char grn = RGBGetGValue(colors[0]); unsigned char blu = RGBGetBValue(colors[0]); - controller->SetLedColor(red, grn, blu); + controller->SetLedColor(red, grn, blu, modes[active_mode].brightness); } void RGBController_CreativeSoundBlasterXG6::UpdateZoneLEDs(int /*zone*/) diff --git a/Controllers/CreativeController/RGBController_CreativeSoundBlasterXG6.h b/Controllers/CreativeController/RGBController_CreativeSoundBlasterXG6.h index 08894a22..b279cd6b 100644 --- a/Controllers/CreativeController/RGBController_CreativeSoundBlasterXG6.h +++ b/Controllers/CreativeController/RGBController_CreativeSoundBlasterXG6.h @@ -1,7 +1,20 @@ +/*---------------------------------------------------------*\ +| RGBController_CreativeSoundBlasterXG6.h | +| | +| RGBController for Creative SoundBlaster XG6 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once + #include "RGBController.h" #include "CreativeSoundBlasterXG6Controller.h" +#define XG6_BRIGHTNESS_MIN 0x00 +#define XG6_BRIGHTNESS_MAX 0xFF + class RGBController_CreativeSoundBlasterXG6: public RGBController { public: diff --git a/Controllers/CrucialController/CrucialController.cpp b/Controllers/CrucialController/CrucialController.cpp index 1adc682b..519f3757 100644 --- a/Controllers/CrucialController/CrucialController.cpp +++ b/Controllers/CrucialController/CrucialController.cpp @@ -1,15 +1,16 @@ -/*-----------------------------------------*\ -| CrucialController.cpp | -| | -| Driver for Crucial Ballistix RGB lighting| -| controller | -| | -| Adam Honse (CalcProgrammer1) 1/19/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| CrucialController.cpp | +| | +| Driver for Crucial Ballistix RAM | +| | +| Adam Honse (CalcProgrammer1) 19 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController.h" #include "CrucialController.h" -#include CrucialController::CrucialController(i2c_smbus_interface* bus, crucial_dev_id dev) { @@ -94,7 +95,7 @@ void CrucialController::SendDirectColors(RGBColor* color_buf) { color_blk[led] = RGBGetGValue(color_buf[led]); } - + //Green Channels CrucialRegisterWriteBlock(0x8340, color_blk, 8); @@ -102,7 +103,7 @@ void CrucialController::SendDirectColors(RGBColor* color_buf) { color_blk[led] = RGBGetBValue(color_buf[led]); } - + //Blue Channels CrucialRegisterWriteBlock(0x8380, color_blk, 8); } diff --git a/Controllers/CrucialController/CrucialController.h b/Controllers/CrucialController/CrucialController.h index 8550016f..7d7ef957 100644 --- a/Controllers/CrucialController/CrucialController.h +++ b/Controllers/CrucialController/CrucialController.h @@ -1,18 +1,20 @@ -/*-----------------------------------------*\ -| CrucialController.h | -| | -| Definitions and types for Crucial | -| Ballistix RGB lighting controller | -| | -| Adam Honse (CalcProgrammer1) 1/19/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include "i2c_smbus.h" +/*---------------------------------------------------------*\ +| CrucialController.h | +| | +| Driver for Crucial Ballistix RAM | +| | +| Adam Honse (CalcProgrammer1) 19 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include "RGBController.h" +#include "i2c_smbus.h" + typedef unsigned char crucial_dev_id; typedef unsigned short crucial_register; @@ -68,7 +70,7 @@ private: unsigned int green, unsigned int blue ); - + void SendDirectColors(RGBColor* color_buf); void SendBrightness(unsigned char brightness); void SendEffectMode(unsigned char mode, unsigned char speed); diff --git a/Controllers/CrucialController/CrucialControllerDetect.cpp b/Controllers/CrucialController/CrucialControllerDetect.cpp index 51b97431..bb508faf 100644 --- a/Controllers/CrucialController/CrucialControllerDetect.cpp +++ b/Controllers/CrucialController/CrucialControllerDetect.cpp @@ -1,13 +1,22 @@ +/*---------------------------------------------------------*\ +| CrucialControllerDetect.cpp | +| | +| Detector for Crucial Ballistix RAM | +| | +| Adam Honse (CalcProgrammer1) 19 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include #include "Detector.h" #include "CrucialController.h" #include "LogManager.h" -#include "RGBController.h" #include "RGBController_Crucial.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include using namespace std::chrono_literals; @@ -224,4 +233,4 @@ void DetectCrucialControllers(std::vector &busses) } /* DetectCrucialControllers() */ -REGISTER_I2C_DETECTOR("Crucial", DetectCrucialControllers); +REGISTER_I2C_DETECTOR("Crucial Ballistix", DetectCrucialControllers); diff --git a/Controllers/CrucialController/RGBController_Crucial.cpp b/Controllers/CrucialController/RGBController_Crucial.cpp index 1b881112..195c5b1c 100644 --- a/Controllers/CrucialController/RGBController_Crucial.cpp +++ b/Controllers/CrucialController/RGBController_Crucial.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_Crucial.cpp | -| | -| Generic RGB Interface for Crucial | -| Ballistix RGB controller | -| | -| Adam Honse (CalcProgrammer1) 1/19/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Crucial.cpp | +| | +| RGBController for Crucial Ballistix RAM | +| | +| Adam Honse (CalcProgrammer1) 19 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_Crucial.h" diff --git a/Controllers/CrucialController/RGBController_Crucial.h b/Controllers/CrucialController/RGBController_Crucial.h index 8ab523ef..703b6e71 100644 --- a/Controllers/CrucialController/RGBController_Crucial.h +++ b/Controllers/CrucialController/RGBController_Crucial.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_Crucial.h | -| | -| Generic RGB Interface for Crucial | -| Ballistix RGB controller | -| | -| Adam Honse (CalcProgrammer1) 1/19/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Crucial.h | +| | +| RGBController for Crucial Ballistix RAM | +| | +| Adam Honse (CalcProgrammer1) 19 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once @@ -21,7 +23,7 @@ public: void SetupZones(); void ResizeZone(int zone, int new_size); - + void DeviceUpdateLEDs(); void UpdateZoneLEDs(int zone); void UpdateSingleLED(int led); diff --git a/Controllers/CryorigH7QuadLumiController/CryorigH7QuadLumiController.cpp b/Controllers/CryorigH7QuadLumiController/CryorigH7QuadLumiController.cpp index 5eca8925..6e9e4d82 100644 --- a/Controllers/CryorigH7QuadLumiController/CryorigH7QuadLumiController.cpp +++ b/Controllers/CryorigH7QuadLumiController/CryorigH7QuadLumiController.cpp @@ -1,21 +1,27 @@ /*---------------------------------------------------------*\ -| Processing Code for Cryorig H7 Quad Lumi | +| CryorigH7QuadLumiController.cpp | | | -| Adam Honse (calcprogrammer1@gmail.com), 4/15/2023 | +| Driver for Cryorig H7 Quad Lumi | +| | +| Adam Honse (calcprogrammer1@gmail.com) 15 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "CryorigH7QuadLumiController.h" -#include "LogManager.h" - +#include #include #include #include -#include +#include "CryorigH7QuadLumiController.h" +#include "LogManager.h" +#include "StringUtils.h" -CryorigH7QuadLumiController::CryorigH7QuadLumiController(hid_device* dev_handle, const char* path) +CryorigH7QuadLumiController::CryorigH7QuadLumiController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; SendFirmwareRequest(); } @@ -30,6 +36,11 @@ std::string CryorigH7QuadLumiController::GetLocation() return("HID: " + location); } +std::string CryorigH7QuadLumiController::GetName() +{ + return(name); +} + std::string CryorigH7QuadLumiController::GetFirmwareVersion() { return(firmware_version); @@ -45,10 +56,7 @@ std::string CryorigH7QuadLumiController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void CryorigH7QuadLumiController::SetChannelEffect @@ -79,12 +87,12 @@ void CryorigH7QuadLumiController::SetChannelEffect \*-----------------------------------------------------*/ else if(num_colors <= 8) { - for(std::size_t color_idx = 0; color_idx < num_colors; color_idx++) + for(unsigned int color_idx = 0; color_idx < num_colors; color_idx++) { /*-----------------------------------------------------*\ | Fill in color data (5 entries per color) | \*-----------------------------------------------------*/ - for (std::size_t idx = 0; idx < 40; idx++) + for(int idx = 0; idx < 40; idx++) { int pixel_idx = idx * 3; RGBColor color = colors[color_idx]; @@ -96,7 +104,7 @@ void CryorigH7QuadLumiController::SetChannelEffect /*-----------------------------------------------------*\ | Send mode and color data | \*-----------------------------------------------------*/ - SendPacket(channel, mode, direction, color_idx, speed, 5, &color_data[0]); + SendPacket(channel, mode, direction, (unsigned char)color_idx, speed, 5, &color_data[0]); } } /*-----------------------------------------------------*\ @@ -107,9 +115,9 @@ void CryorigH7QuadLumiController::SetChannelEffect /*-----------------------------------------------------*\ | Fill in color data (up to 40 colors) | \*-----------------------------------------------------*/ - for (std::size_t idx = 0; idx < num_colors; idx++) + for(unsigned int idx = 0; idx < num_colors; idx++) { - int pixel_idx = idx * 3; + unsigned int pixel_idx = idx * 3; RGBColor color = colors[idx]; color_data[pixel_idx + 0x00] = RGBGetGValue(color); color_data[pixel_idx + 0x01] = RGBGetRValue(color); @@ -135,9 +143,9 @@ void CryorigH7QuadLumiController::SetChannelLEDs /*-----------------------------------------------------*\ | Fill in color data (up to 40 colors) | \*-----------------------------------------------------*/ - for (std::size_t idx = 0; idx < num_colors; idx++) + for(unsigned int idx = 0; idx < num_colors; idx++) { - int pixel_idx = idx * 3; + unsigned int pixel_idx = idx * 3; RGBColor color = colors[idx]; color_data[pixel_idx + 0x00] = RGBGetGValue(color); color_data[pixel_idx + 0x01] = RGBGetRValue(color); diff --git a/Controllers/CryorigH7QuadLumiController/CryorigH7QuadLumiController.h b/Controllers/CryorigH7QuadLumiController/CryorigH7QuadLumiController.h index 931ddc79..65f54583 100644 --- a/Controllers/CryorigH7QuadLumiController/CryorigH7QuadLumiController.h +++ b/Controllers/CryorigH7QuadLumiController/CryorigH7QuadLumiController.h @@ -1,15 +1,20 @@ /*---------------------------------------------------------*\ -| Definitions for Cryorig H7 Quad Lumi | +| CryorigH7QuadLumiController.h | | | -| Adam Honse (calcprogrammer1@gmail.com), 4/15/2023 | +| Driver for Cryorig H7 Quad Lumi | +| | +| Adam Honse (calcprogrammer1@gmail.com) 15 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "RGBController.h" +#pragma once + #include #include -#include - -#pragma once +#include +#include "RGBController.h" enum { @@ -43,11 +48,12 @@ enum class CryorigH7QuadLumiController { public: - CryorigH7QuadLumiController(hid_device* dev_handle, const char* path); + CryorigH7QuadLumiController(hid_device* dev_handle, const char* path, std::string dev_name); ~CryorigH7QuadLumiController(); std::string GetFirmwareVersion(); std::string GetLocation(); + std::string GetName(); std::string GetSerialString(); void SetChannelEffect @@ -72,6 +78,7 @@ private: char firmware_version[16]; std::string location; + std::string name; void SendPacket ( diff --git a/Controllers/CryorigH7QuadLumiController/CryorigH7QuadLumiControllerDetect.cpp b/Controllers/CryorigH7QuadLumiController/CryorigH7QuadLumiControllerDetect.cpp index 24ca3519..c773e2b6 100644 --- a/Controllers/CryorigH7QuadLumiController/CryorigH7QuadLumiControllerDetect.cpp +++ b/Controllers/CryorigH7QuadLumiController/CryorigH7QuadLumiControllerDetect.cpp @@ -1,8 +1,18 @@ +/*---------------------------------------------------------*\ +| CryorigH7QuadLumiControllerDetect.cpp | +| | +| Detector for Cryorig H7 Quad Lumi | +| | +| Adam Honse (calcprogrammer1@gmail.com) 15 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "CryorigH7QuadLumiController.h" -#include "RGBController.h" #include "RGBController_CryorigH7QuadLumi.h" -#include /*-----------------------------------------------------*\ | CRYORIG/NZXT USB IDs | @@ -16,9 +26,8 @@ static void DetectCryorigH7QuadLumi(hid_device_info* info, const std::string& na if(dev) { - CryorigH7QuadLumiController* controller = new CryorigH7QuadLumiController(dev, info->path); + CryorigH7QuadLumiController* controller = new CryorigH7QuadLumiController(dev, info->path, name); RGBController_CryorigH7QuadLumi* rgb_controller = new RGBController_CryorigH7QuadLumi(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } diff --git a/Controllers/CryorigH7QuadLumiController/RGBController_CryorigH7QuadLumi.cpp b/Controllers/CryorigH7QuadLumiController/RGBController_CryorigH7QuadLumi.cpp index 0aab99b6..25ed78d0 100644 --- a/Controllers/CryorigH7QuadLumiController/RGBController_CryorigH7QuadLumi.cpp +++ b/Controllers/CryorigH7QuadLumiController/RGBController_CryorigH7QuadLumi.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_CryorigH7QuadLumi.cpp | -| | -| Generic RGB Interface for Cryorig H7 | -| Quad Lumi | -| | -| Adam Honse (CalcProgrammer1) 4/15/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CryorigH7QuadLumi.cpp | +| | +| RGBController for Cryorig H7 Quad Lumi | +| | +| Adam Honse (CalcProgrammer1) 15 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_CryorigH7QuadLumi.h" @@ -24,7 +26,7 @@ RGBController_CryorigH7QuadLumi::RGBController_CryorigH7QuadLumi(CryorigH7QuadLu { controller = controller_ptr; - name = "CRYORIG H7 Quad Lumi"; + name = controller->GetName(); vendor = "CRYORIG"; type = DEVICE_TYPE_COOLER; description = "CRYORIG H7 Quad Lumi Device"; @@ -187,7 +189,7 @@ void RGBController_CryorigH7QuadLumi::ResizeZone(int /*zone*/, int /*new_size*/) void RGBController_CryorigH7QuadLumi::DeviceUpdateLEDs() { - for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + for(unsigned char zone_idx = 0; zone_idx < (unsigned char)zones.size(); zone_idx++) { controller->SetChannelLEDs(zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); } @@ -205,11 +207,6 @@ void RGBController_CryorigH7QuadLumi::UpdateSingleLED(int led) controller->SetChannelLEDs(zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); } -void RGBController_CryorigH7QuadLumi::SetCustomMode() -{ - active_mode = 0; -} - void RGBController_CryorigH7QuadLumi::DeviceUpdateMode() { if(modes[active_mode].value == CRYORIG_H7_QUAD_LUMI_MODE_FIXED) @@ -218,7 +215,7 @@ void RGBController_CryorigH7QuadLumi::DeviceUpdateMode() } else { - for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + for(unsigned char zone_idx = 0; zone_idx < (unsigned char)zones.size(); zone_idx++) { RGBColor* colors = NULL; bool direction = false; @@ -240,7 +237,7 @@ void RGBController_CryorigH7QuadLumi::DeviceUpdateMode() modes[active_mode].speed, direction, colors, - modes[active_mode].colors.size() + (unsigned int)modes[active_mode].colors.size() ); } } diff --git a/Controllers/CryorigH7QuadLumiController/RGBController_CryorigH7QuadLumi.h b/Controllers/CryorigH7QuadLumiController/RGBController_CryorigH7QuadLumi.h index 5b924bf2..e59b12df 100644 --- a/Controllers/CryorigH7QuadLumiController/RGBController_CryorigH7QuadLumi.h +++ b/Controllers/CryorigH7QuadLumiController/RGBController_CryorigH7QuadLumi.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_CryorigH7QuadLumi.h | -| | -| Generic RGB Interface for Cryorig H7 | -| Quad Lumi | -| | -| Adam Honse (CalcProgrammer1) 4/15/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_CryorigH7QuadLumi.h | +| | +| RGBController for Cryorig H7 Quad Lumi | +| | +| Adam Honse (CalcProgrammer1) 15 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "CryorigH7QuadLumiController.h" @@ -25,7 +28,6 @@ public: void UpdateZoneLEDs(int zone); void UpdateSingleLED(int led); - void SetCustomMode(); void DeviceUpdateMode(); private: diff --git a/Controllers/DDPController/DDPController.cpp b/Controllers/DDPController/DDPController.cpp new file mode 100644 index 00000000..aab284f0 --- /dev/null +++ b/Controllers/DDPController/DDPController.cpp @@ -0,0 +1,309 @@ +/*---------------------------------------------------------*\ +| DDPController.cpp | +| | +| Driver for DDP protocol devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "DDPController.h" +#include "LogManager.h" +#include +#include + +DDPController::DDPController(const std::vector& device_list) +{ + devices = device_list; + unique_endpoints = NULL; + num_endpoints = 0; + sequence_number = 0; + keepalive_time_ms = 1000; + keepalive_thread_run = false; + + InitializeNetPorts(); + + if(!devices.empty()) + { + keepalive_thread_run = true; + keepalive_thread = std::thread(&DDPController::KeepaliveThreadFunction, this); + } +} + +DDPController::~DDPController() +{ + keepalive_thread_run = false; + if(keepalive_thread.joinable()) + { + keepalive_thread.join(); + } + + CloseNetPorts(); + if(unique_endpoints != NULL) + { + delete[] unique_endpoints; + } +} + +bool DDPController::InitializeNetPorts() +{ + if(devices.empty()) + { + return true; + } + + num_endpoints = 0; + + for(unsigned int dev_idx = 0; dev_idx < devices.size(); dev_idx++) + { + bool found = false; + for(unsigned int ep_idx = 0; ep_idx < num_endpoints; ep_idx++) + { + if(strcmp(unique_endpoints[ep_idx].ip, devices[dev_idx].ip.c_str()) == 0 && + unique_endpoints[ep_idx].port == devices[dev_idx].port) + { + found = true; + break; + } + } + if(!found) + { + num_endpoints++; + } + } + + unique_endpoints = new DDPEndpoint[num_endpoints]; + unsigned int endpoint_count = 0; + + for(unsigned int dev_idx = 0; dev_idx < devices.size(); dev_idx++) + { + bool found = false; + for(unsigned int ep_idx = 0; ep_idx < endpoint_count; ep_idx++) + { + if(strcmp(unique_endpoints[ep_idx].ip, devices[dev_idx].ip.c_str()) == 0 && + unique_endpoints[ep_idx].port == devices[dev_idx].port) + { + found = true; + break; + } + } + if(!found) + { + strncpy(unique_endpoints[endpoint_count].ip, devices[dev_idx].ip.c_str(), 15); + unique_endpoints[endpoint_count].ip[15] = '\0'; + unique_endpoints[endpoint_count].port = devices[dev_idx].port; + endpoint_count++; + } + } + + for(unsigned int ep_idx = 0; ep_idx < num_endpoints; ep_idx++) + { + net_port* port = new net_port(); + char port_str[16]; + snprintf(port_str, 16, "%d", unique_endpoints[ep_idx].port); + + if(port->udp_client(unique_endpoints[ep_idx].ip, port_str)) + { + udp_ports.push_back(port); + } + else + { + udp_ports.push_back(NULL); + } + } + + return true; +} + +void DDPController::CloseNetPorts() +{ + for(unsigned int port_idx = 0; port_idx < udp_ports.size(); port_idx++) + { + if(udp_ports[port_idx] != NULL) + { + delete udp_ports[port_idx]; + } + } + udp_ports.clear(); +} + +int DDPController::GetPortIndex(const DDPDevice& device) +{ + for(unsigned int ep_idx = 0; ep_idx < num_endpoints; ep_idx++) + { + if(strcmp(unique_endpoints[ep_idx].ip, device.ip.c_str()) == 0 && + unique_endpoints[ep_idx].port == device.port) + { + return (int)ep_idx; + } + } + return -1; +} + +void DDPController::UpdateLEDs(const std::vector& colors) +{ + if(udp_ports.empty()) return; + + { + std::lock_guard lock(last_update_mutex); + last_colors = colors; + last_update_time = std::chrono::steady_clock::now(); + } + + unsigned int color_index = 0; + + for(unsigned int dev_idx = 0; dev_idx < devices.size(); dev_idx++) + { + if(color_index >= colors.size()) break; + + unsigned int bytes_per_pixel = 3; + unsigned int total_bytes = devices[dev_idx].num_leds * bytes_per_pixel; + std::vector device_data(total_bytes); + + for(unsigned int led_idx = 0; led_idx < devices[dev_idx].num_leds && (color_index + led_idx) < colors.size(); led_idx++) + { + unsigned int color = colors[color_index + led_idx]; + unsigned char r = color & 0xFF; + unsigned char g = (color >> 8) & 0xFF; + unsigned char b = (color >> 16) & 0xFF; + unsigned int pixel_offset = led_idx * bytes_per_pixel; + + device_data[pixel_offset + 0] = r; + device_data[pixel_offset + 1] = g; + device_data[pixel_offset + 2] = b; + } + + unsigned int max_data_per_packet = DDP_MAX_DATA_SIZE; + unsigned int bytes_sent = 0; + + while(bytes_sent < total_bytes) + { + unsigned int chunk_size = (max_data_per_packet < (total_bytes - bytes_sent)) ? max_data_per_packet : (total_bytes - bytes_sent); + + if(!SendDDPPacket(devices[dev_idx], device_data.data() + bytes_sent, (unsigned short)chunk_size, bytes_sent)) + break; + + bytes_sent += chunk_size; + } + + color_index += devices[dev_idx].num_leds; + } + + sequence_number++; +} + +bool DDPController::SendDDPPacket(const DDPDevice& device, const unsigned char* data, unsigned short length, unsigned int offset) +{ + int port_index = GetPortIndex(device); + if(port_index < 0 || port_index >= (int)udp_ports.size()) + { + return false; + } + + if(udp_ports[port_index] == NULL) + { + net_port* port = new net_port(); + char port_str[16]; + snprintf(port_str, 16, "%d", unique_endpoints[port_index].port); + + if(port->udp_client(unique_endpoints[port_index].ip, port_str)) + { + udp_ports[port_index] = port; + } + else + { + delete port; + return false; + } + } + + std::vector packet(DDP_HEADER_SIZE + length); + ddp_header* header = (ddp_header*)packet.data(); + + header->flags = DDP_FLAG_VER_1 | DDP_FLAG_PUSH; + header->sequence = sequence_number & 0x0F; + header->data_type = 1; + header->dest_id = 1; + header->data_offset = htonl(offset); + header->data_length = htons(length); + + memcpy(packet.data() + DDP_HEADER_SIZE, data, length); + + int bytes_sent = udp_ports[port_index]->udp_write((char*)packet.data(), (int)packet.size()); + + return bytes_sent == (int)packet.size(); +} + +void DDPController::SetKeepaliveTime(unsigned int time_ms) +{ + keepalive_time_ms = time_ms; +} + +void DDPController::KeepaliveThreadFunction() +{ + while(keepalive_thread_run) + { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + + if(keepalive_time_ms == 0) + continue; + + std::vector colors_to_send; + bool should_send = false; + + { + std::lock_guard lock(last_update_mutex); + std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now(); + long long time_since_update = std::chrono::duration_cast(now - last_update_time).count(); + + if(time_since_update >= keepalive_time_ms && !last_colors.empty()) + { + colors_to_send = last_colors; + should_send = true; + last_update_time = now; + } + } + + if(should_send) + { + unsigned int color_index = 0; + + for(unsigned int dev_idx = 0; dev_idx < devices.size(); dev_idx++) + { + if(color_index >= colors_to_send.size()) break; + + unsigned int bytes_per_pixel = 3; + unsigned int total_bytes = devices[dev_idx].num_leds * bytes_per_pixel; + std::vector device_data(total_bytes); + + for(unsigned int led_idx = 0; led_idx < devices[dev_idx].num_leds && (color_index + led_idx) < colors_to_send.size(); led_idx++) + { + unsigned int color = colors_to_send[color_index + led_idx]; + unsigned char r = color & 0xFF; + unsigned char g = (color >> 8) & 0xFF; + unsigned char b = (color >> 16) & 0xFF; + unsigned int pixel_offset = led_idx * bytes_per_pixel; + + device_data[pixel_offset + 0] = r; + device_data[pixel_offset + 1] = g; + device_data[pixel_offset + 2] = b; + } + + unsigned int max_data_per_packet = DDP_MAX_DATA_SIZE; + unsigned int bytes_sent = 0; + + while(bytes_sent < total_bytes) + { + unsigned int chunk_size = (max_data_per_packet < (total_bytes - bytes_sent)) ? max_data_per_packet : (total_bytes - bytes_sent); + + if(!SendDDPPacket(devices[dev_idx], device_data.data() + bytes_sent, (unsigned short)chunk_size, bytes_sent)) + break; + + bytes_sent += chunk_size; + } + + color_index += devices[dev_idx].num_leds; + } + } + } +} diff --git a/Controllers/DDPController/DDPController.h b/Controllers/DDPController/DDPController.h new file mode 100644 index 00000000..268792fa --- /dev/null +++ b/Controllers/DDPController/DDPController.h @@ -0,0 +1,97 @@ +/*---------------------------------------------------------*\ +| DDPController.h | +| | +| Driver for DDP protocol devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include "net_port.h" + +#define DDP_DEFAULT_PORT 4048 +#define DDP_HEADER_SIZE 10 +#define DDP_HEADER_SIZE_TC 14 +#define DDP_VERSION 1 +#define DDP_MAX_PACKET_SIZE 1450 +#define DDP_MAX_DATA_SIZE 1440 + +#define DDP_FLAG_VER_MASK 0xC0 +#define DDP_FLAG_VER_1 0x40 +#define DDP_FLAG_TIMECODE 0x10 +#define DDP_FLAG_STORAGE 0x08 +#define DDP_FLAG_REPLY 0x04 +#define DDP_FLAG_QUERY 0x02 +#define DDP_FLAG_PUSH 0x01 + +#define DDP_TYPE_RGB8 0x0B +#define DDP_TYPE_RGB_SIMPLE 1 + +#pragma pack(push, 1) +struct ddp_header +{ + unsigned char flags; + unsigned char sequence; + unsigned char data_type; + unsigned char dest_id; + unsigned int data_offset; + unsigned short data_length; +}; +#pragma pack(pop) + +struct DDPDevice +{ + std::string name; + std::string ip; + unsigned short port; + unsigned int num_leds; +}; + +struct DDPEndpoint +{ + char ip[16]; + unsigned short port; +}; + +class DDPController +{ +public: + DDPController(const std::vector& devices); + ~DDPController(); + + void UpdateLEDs(const std::vector& colors); + void SetKeepaliveTime(unsigned int time_ms); + +private: + std::vector devices; + std::vector udp_ports; + DDPEndpoint* unique_endpoints; + unsigned int num_endpoints; + unsigned char sequence_number; + + + std::atomic keepalive_thread_run; + std::thread keepalive_thread; + std::mutex last_update_mutex; + std::chrono::steady_clock::time_point last_update_time; + std::vector last_colors; + unsigned int keepalive_time_ms; + + bool InitializeNetPorts(); + void CloseNetPorts(); + int GetPortIndex(const DDPDevice& device); + bool SendDDPPacket(const DDPDevice& device, + const unsigned char* data, + unsigned short length, + unsigned int offset = 0); + void KeepaliveThreadFunction(); +}; diff --git a/Controllers/DDPController/DDPControllerDetect.cpp b/Controllers/DDPController/DDPControllerDetect.cpp new file mode 100644 index 00000000..46fe6ea8 --- /dev/null +++ b/Controllers/DDPController/DDPControllerDetect.cpp @@ -0,0 +1,92 @@ +/*---------------------------------------------------------*\ +| DDPControllerDetect.cpp | +| | +| Detector for DDP devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "Detector.h" +#include "RGBController.h" +#include "RGBController_DDP.h" +#include "SettingsManager.h" +#include "LogManager.h" +#include "nlohmann/json.hpp" + +using json = nlohmann::json; + +void DetectDDPControllers() +{ + json ddp_settings; + std::vector> device_lists; + DDPDevice dev; + + ddp_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("DDPDevices"); + + if(ddp_settings.contains("devices")) + { + for(unsigned int device_idx = 0; device_idx < ddp_settings["devices"].size(); device_idx++) + { + dev.name = ""; + dev.ip = ""; + dev.port = DDP_DEFAULT_PORT; + dev.num_leds = 0; + + if(ddp_settings["devices"][device_idx].contains("name")) + dev.name = ddp_settings["devices"][device_idx]["name"]; + if(ddp_settings["devices"][device_idx].contains("ip")) + dev.ip = ddp_settings["devices"][device_idx]["ip"]; + if(ddp_settings["devices"][device_idx].contains("port")) + dev.port = ddp_settings["devices"][device_idx]["port"]; + if(ddp_settings["devices"][device_idx].contains("num_leds")) + dev.num_leds = ddp_settings["devices"][device_idx]["num_leds"]; + + if(dev.name.empty()) + dev.name = "DDP Device " + std::to_string(device_idx + 1); + if(dev.ip.empty()) + { + continue; + } + if(dev.num_leds == 0) + { + continue; + } + + bool device_added_to_existing_list = false; + + for(unsigned int list_idx = 0; list_idx < device_lists.size(); list_idx++) + { + for(unsigned int existing_device_idx = 0; existing_device_idx < device_lists[list_idx].size(); existing_device_idx++) + { + if(dev.ip == device_lists[list_idx][existing_device_idx].ip && + dev.port == device_lists[list_idx][existing_device_idx].port) + { + device_lists[list_idx].push_back(dev); + device_added_to_existing_list = true; + break; + } + } + if(device_added_to_existing_list) + break; + } + + if(!device_added_to_existing_list) + { + std::vector new_list; + new_list.push_back(dev); + device_lists.push_back(new_list); + } + } + + for(unsigned int list_idx = 0; list_idx < device_lists.size(); list_idx++) + { + RGBController_DDP* rgb_controller = new RGBController_DDP(device_lists[list_idx]); + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + } +} + +REGISTER_DETECTOR("DDP", DetectDDPControllers); diff --git a/Controllers/DDPController/RGBController_DDP.cpp b/Controllers/DDPController/RGBController_DDP.cpp new file mode 100644 index 00000000..087a7e0b --- /dev/null +++ b/Controllers/DDPController/RGBController_DDP.cpp @@ -0,0 +1,131 @@ +/*---------------------------------------------------------*\ +| RGBController_DDP.cpp | +| | +| RGBController for DDP devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_DDP.h" + +/**------------------------------------------------------------------*\ + @name DDP Devices + @category LEDStrip + @type Network + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectDDPControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_DDP::RGBController_DDP(std::vector device_list) +{ + devices = device_list; + name = "DDP Device Group"; + type = DEVICE_TYPE_LEDSTRIP; + description = "Distributed Display Protocol Device"; + location = "DDP: "; + + if(devices.size() == 1) + name = devices[0].name; + else if(!devices[0].ip.empty()) + name += " (" + devices[0].ip + ")"; + + if(!devices[0].ip.empty()) + location += devices[0].ip + ":" + std::to_string(devices[0].port); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = 0; + Direct.brightness_max = 100; + Direct.brightness = 100; + modes.push_back(Direct); + + controller = new DDPController(devices); + SetupZones(); +} + +RGBController_DDP::~RGBController_DDP() +{ + delete controller; +} + +void RGBController_DDP::SetupZones() +{ + for(unsigned int zone_idx = 0; zone_idx < devices.size(); zone_idx++) + { + zone led_zone; + led_zone.name = devices[zone_idx].name; + led_zone.type = ZONE_TYPE_LINEAR; + led_zone.leds_min = devices[zone_idx].num_leds; + led_zone.leds_max = devices[zone_idx].num_leds; + led_zone.leds_count = devices[zone_idx].num_leds; + led_zone.matrix_map = NULL; + zones.push_back(led_zone); + } + + 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); + new_led.value = 0; + leds.push_back(new_led); + } + } + SetupColors(); +} + +void RGBController_DDP::ResizeZone(int /*zone*/, int /*new_size*/) +{ +} + +void RGBController_DDP::DeviceUpdateLEDs() +{ + std::vector brightness_adjusted_colors; + brightness_adjusted_colors.reserve(colors.size()); + float brightness_scale = (float)modes[active_mode].brightness / 100.0f; + + for(unsigned int color_idx = 0; color_idx < colors.size(); color_idx++) + { + unsigned int color = colors[color_idx]; + unsigned char r = color & 0xFF; + unsigned char g = (color >> 8) & 0xFF; + unsigned char b = (color >> 16) & 0xFF; + r = (unsigned char)(r * brightness_scale); + g = (unsigned char)(g * brightness_scale); + b = (unsigned char)(b * brightness_scale); + unsigned int adjusted_color = r | (g << 8) | (b << 16); + brightness_adjusted_colors.push_back(adjusted_color); + } + + controller->UpdateLEDs(brightness_adjusted_colors); +} + +void RGBController_DDP::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_DDP::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_DDP::DeviceUpdateMode() +{ +} + +void RGBController_DDP::SetKeepaliveTime(unsigned int time_ms) +{ + if(controller != nullptr) + { + controller->SetKeepaliveTime(time_ms); + } +} diff --git a/Controllers/DDPController/RGBController_DDP.h b/Controllers/DDPController/RGBController_DDP.h new file mode 100644 index 00000000..699df8db --- /dev/null +++ b/Controllers/DDPController/RGBController_DDP.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_DDP.h | +| | +| RGBController for DDP devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "DDPController.h" + +class RGBController_DDP : public RGBController +{ +public: + RGBController_DDP(std::vector device_list); + ~RGBController_DDP(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + void SetKeepaliveTime(unsigned int time_ms); + +private: + std::vector devices; + DDPController* controller; +}; diff --git a/Controllers/DMXController/DMXControllerDetect.cpp b/Controllers/DMXController/DMXControllerDetect.cpp index 0ecba081..ec852baa 100644 --- a/Controllers/DMXController/DMXControllerDetect.cpp +++ b/Controllers/DMXController/DMXControllerDetect.cpp @@ -1,16 +1,18 @@ -#include "Detector.h" -#include "RGBController.h" -#include "RGBController_DMX.h" -#include "SettingsManager.h" -#include -#include -#include +/*---------------------------------------------------------*\ +| DMXControllerDetect.cpp | +| | +| Detector for DMX devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include -#include -#include -#include #include +#include +#include "Detector.h" +#include "RGBController_DMX.h" +#include "SettingsManager.h" /******************************************************************************************\ * * diff --git a/Controllers/DMXController/RGBController_DMX.cpp b/Controllers/DMXController/RGBController_DMX.cpp index 514d7034..a8ed9703 100644 --- a/Controllers/DMXController/RGBController_DMX.cpp +++ b/Controllers/DMXController/RGBController_DMX.cpp @@ -1,16 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_DMX.cpp | -| | -| Generic RGB Interface for OpenAuraSDK | -| DMX interface | -| | -| Adam Honse (CalcProgrammer1) 4/30/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_DMX.cpp | +| | +| RGBController for DMX devices | +| | +| Adam Honse (CalcProgrammer1) 30 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_DMX.h" #include - #include "LogManager.h" +#include "RGBController_DMX.h" using namespace std::chrono_literals; diff --git a/Controllers/DMXController/RGBController_DMX.h b/Controllers/DMXController/RGBController_DMX.h index ab38b4a3..6ef323e8 100644 --- a/Controllers/DMXController/RGBController_DMX.h +++ b/Controllers/DMXController/RGBController_DMX.h @@ -1,18 +1,20 @@ -/*-----------------------------------------*\ -| RGBController_DMX.h | -| | -| Generic RGB Interface for OpenAuraSDK | -| DMX interface | -| | -| Adam Honse (CalcProgrammer1) 4/30/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_DMX.h | +| | +| RGBController for DMX devices | +| | +| Adam Honse (CalcProgrammer1) 30 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include "RGBController.h" -#include "serial_port.h" + #include #include - +#include "RGBController.h" +#include "serial_port.h" struct DMXDevice { std::string name; diff --git a/Controllers/DRGBController/DRGBController.cpp b/Controllers/DRGBController/DRGBController.cpp new file mode 100644 index 00000000..4af6cb6e --- /dev/null +++ b/Controllers/DRGBController/DRGBController.cpp @@ -0,0 +1,163 @@ +/*---------------------------------------------------------*\ +| DRGBController.cpp | +| | +| Driver for DRGBmods | +| | +| Zhi Yan 25 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "DRGBController.h" +#include "StringUtils.h" + +using namespace std::chrono_literals; + +DRGBController::DRGBController(hid_device* dev_handle, const char* path, unsigned short pid, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + device_pid = pid; + + /*-----------------------------------------------------*\ + | Exit hardware effects. Start a thread to continuously| + | send a keepalive packet every 500ms | + \*-----------------------------------------------------*/ + keepalive_thread_run = 1; + keepalive_thread = new std::thread(&DRGBController::KeepaliveThread, this); +} + +DRGBController::~DRGBController() +{ + keepalive_thread_run = 0; + keepalive_thread->join(); + delete keepalive_thread; + hid_close(dev); +} + +void DRGBController::KeepaliveThread() +{ + unsigned char sleep_buf[65]; + sleep_buf[0] = 0x65; + while(keepalive_thread_run.load()) + { + if((std::chrono::steady_clock::now() - last_commit_time) > std::chrono::seconds(1)) + { + SendPacketFS(sleep_buf, 1, 0); + } + std::this_thread::sleep_for(500ms); + } +} + +std::string DRGBController::GetFirmwareString() +{ + return "v"+std::to_string(version[0]) + "." + std::to_string(version[1]) + "." + std::to_string(version[2]) + "." + std::to_string(version[3]); +} + +std::string DRGBController::GetLocationString() +{ + return("HID: " + location); +} + +std::string DRGBController::GetNameString() +{ + return(name); +} + +std::string DRGBController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +unsigned short DRGBController::GetDevicePID() +{ + return(device_pid); +} + +void DRGBController::SetChannelLEDs(unsigned char /*channel*/, RGBColor* /*colors*/, unsigned int /*num_colors*/) +{ + +} + +void DRGBController::SendPacket(unsigned char* colors, unsigned int buf_packets , unsigned int LEDtotal) +{ + unsigned char usb_buf[1025]; + unsigned int buf_idx = 0; + memset(usb_buf, 0x00, sizeof(usb_buf)); + usb_buf[0x00] = 0x00; + unsigned int HigCount = LEDtotal / 256 >= 1 ? 1 : 0; + unsigned int LowCount = LEDtotal >= DRGB_V4_ONE_PACKAGE_SIZE ? 60 : (LEDtotal % 256) ; + LEDtotal = LEDtotal <= DRGB_V4_ONE_PACKAGE_SIZE ? 0 : (LEDtotal-DRGB_V4_ONE_PACKAGE_SIZE); + for(unsigned int i = 0; i < buf_packets; i++) + { + usb_buf[1] = i + 100 ; + usb_buf[2] = buf_packets + 99 ; + usb_buf[3] = HigCount; + usb_buf[4] = LowCount; + buf_idx = i*1020; + for(unsigned int k=0;k<1020;k++) + { + usb_buf[k+5] = colors[buf_idx + k]; + } + hid_write(dev, usb_buf, 1025); + if(LEDtotal) + { + HigCount = LEDtotal / 256 >= 1 ? 1 : 0; + LowCount = LEDtotal >= DRGB_V4_PACKAGE_SIZE ? 84 : (LEDtotal % 256) ; + LEDtotal = LEDtotal <= DRGB_V4_PACKAGE_SIZE ? 0 : (LEDtotal-DRGB_V4_PACKAGE_SIZE); + } + } +} + +void DRGBController::SendPacketFS(unsigned char* colors, unsigned int buf_packets , unsigned int Array) +{ + unsigned char usb_buf[65]; + unsigned int buf_idx = 0; + memset(usb_buf, 0x00, sizeof(usb_buf)); + usb_buf[0x00] = 0x00; + if(Array == 0x64) + { + for(unsigned int i = 0; i < buf_packets; i++) + { + usb_buf[1] = i == buf_packets - 1 ? Array + 100 + i : Array + i; + buf_idx = i*63; + for(unsigned int k=0;k<63;k++) + { + usb_buf[k+2] = colors[buf_idx + k]; + } + hid_write(dev, usb_buf, 65); + } + } + else if(Array == 0x47) + { + for(unsigned int i = 0; i < buf_packets; i++) + { + usb_buf[1] = i == buf_packets - 1 ? Array + 92 + i : Array + i; + buf_idx = i*63; + for(unsigned int k=0;k<63;k++) + { + usb_buf[k+2] = colors[buf_idx + k]; + } + hid_write(dev, usb_buf, 65); + } + } + else + { + for(unsigned int e=0;e<64;e++) + { + usb_buf[e+1] = colors[e]; + } + hid_write(dev, usb_buf, 65); + } +} diff --git a/Controllers/DRGBController/DRGBController.h b/Controllers/DRGBController/DRGBController.h new file mode 100644 index 00000000..dc2aebea --- /dev/null +++ b/Controllers/DRGBController/DRGBController.h @@ -0,0 +1,48 @@ +/*---------------------------------------------------------*\ +| DRGBController.h | +| | +| Driver for DRGBmods | +| | +| Zhi Yan 25 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" + +#define DRGB_V4_ONE_PACKAGE_SIZE 316 +#define DRGB_V4_PACKAGE_SIZE 340 +#define DRGB_V3_PACKAGE_SIZE 21 +#define DRGB_V2_PACKAGE_SIZE 20 + +class DRGBController +{ +public: + DRGBController(hid_device* dev_handle, const char* path, unsigned short pid, std::string dev_name); + ~DRGBController(); + + void KeepaliveThread(); + std::string GetFirmwareString(); + std::string GetLocationString(); + std::string GetNameString(); + std::string GetSerialString(); + unsigned short GetDevicePID(); + void SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors); + void SendPacket(unsigned char* colors,unsigned int buf_packets ,unsigned int LEDtotal); + void SendPacketFS(unsigned char* colors,unsigned int buf_packets ,unsigned int Array); +private: + hid_device* dev; + std::string location; + std::string name; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::chrono::time_point last_commit_time; + unsigned char version[4] = {0, 0, 0,0}; + unsigned short device_pid; +}; diff --git a/Controllers/DRGBController/DRGBControllerDetect.cpp b/Controllers/DRGBController/DRGBControllerDetect.cpp new file mode 100644 index 00000000..b3887e93 --- /dev/null +++ b/Controllers/DRGBController/DRGBControllerDetect.cpp @@ -0,0 +1,63 @@ +/*---------------------------------------------------------*\ +| DRGBControllerDetect.cpp | +| | +| Driver for DRGBmods | +| | +| Zhi Yan 25 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "DRGBController.h" +#include "RGBController_DRGB.h" + +void DetectDRGBControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + wchar_t product[128]; + hid_get_product_string(dev, product, 128); + std::wstring product_str(product); + + DRGBController* controller = new DRGBController(dev, info->path, info->product_id, name); + RGBController_DRGB* rgb_controller = new RGBController_DRGB(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR("DRGB LED V4", DetectDRGBControllers, DRGBV4_VID, DRGB_LED_V4_PID); +REGISTER_HID_DETECTOR("DRGB ULTRA V4F", DetectDRGBControllers, DRGBV4_VID, DRGB_ULTRA_V4F_PID); +REGISTER_HID_DETECTOR("DRGB CORE V4F", DetectDRGBControllers, DRGBV4_VID, DRGB_CORE_V4F_PID); +REGISTER_HID_DETECTOR("DRGB SIG V4F", DetectDRGBControllers, DRGBV4_VID, DRGB_SIG_V4F_PID); +REGISTER_HID_DETECTOR("Airgoo AG-DRGB04", DetectDRGBControllers, DRGBV4_VID, DRGB_AG_04_V4F_PID); +REGISTER_HID_DETECTOR("Airgoo AG-DRGB16", DetectDRGBControllers, DRGBV4_VID, DRGB_AG_16_V4F_PID); + +REGISTER_HID_DETECTOR("DRGB LED V5", DetectDRGBControllers, DRGBV4_VID, DRGB_LED_V5_PID); +REGISTER_HID_DETECTOR("DRGB ULTRA V5", DetectDRGBControllers, DRGBV4_VID, DRGB_ULTRA_V5_PID); +REGISTER_HID_DETECTOR("DRGB ULTRA V5F", DetectDRGBControllers, DRGBV4_VID, DRGB_ULTRA_V5F_PID); +REGISTER_HID_DETECTOR("DRGB CORE V5", DetectDRGBControllers, DRGBV4_VID, DRGB_CORE_V5_PID); +REGISTER_HID_DETECTOR("DRGB CORE V5F", DetectDRGBControllers, DRGBV4_VID, DRGB_CORE_V5F_PID); +REGISTER_HID_DETECTOR("DRGB SIG V5F", DetectDRGBControllers, DRGBV4_VID, DRGB_SIG_V5F_PID); + +REGISTER_HID_DETECTOR("DRGB LED", DetectDRGBControllers, DRGBV3_VID, DRGB_LED_V3_PID); +REGISTER_HID_DETECTOR("DRGB Ultra V3", DetectDRGBControllers, DRGBV3_VID, DRGB_Ultra_V3_PID); +REGISTER_HID_DETECTOR("DRGB CORE V3", DetectDRGBControllers, DRGBV3_VID, DRGB_CORE_V3_PID); +REGISTER_HID_DETECTOR("DRGB ELITE", DetectDRGBControllers, DRGBV3_VID, DRGB_ELITE_PID); +REGISTER_HID_DETECTOR("NEEDMAX 10 ELITE", DetectDRGBControllers, DRGBV3_VID, DM_10_PID); +REGISTER_HID_DETECTOR("JPU ELITE", DetectDRGBControllers, DRGBV3_VID, JPU_12_PID); + +REGISTER_HID_DETECTOR("DRGB LED Controller", DetectDRGBControllers, DRGBV2_VID, DRGB_LED_PID); +REGISTER_HID_DETECTOR("DRGB ULTRA", DetectDRGBControllers, DRGBV2_VID, DRGB_ULTRA_PID); +REGISTER_HID_DETECTOR("DRGB SIG AB", DetectDRGBControllers, DRGBV2_VID, DRGB_SIG_AB_PID); +REGISTER_HID_DETECTOR("DRGB SIG CD", DetectDRGBControllers, DRGBV2_VID, DRGB_SIG_CD_PID); +REGISTER_HID_DETECTOR("DRGB Strimer Controller", DetectDRGBControllers, DRGBV2_VID, DRGB_Strimer_PID); + +REGISTER_HID_DETECTOR("YICO 8 ELITE", DetectDRGBControllers, YICO_VID, YICO_8_PID); +REGISTER_HID_DETECTOR("YICO 08 ELITE", DetectDRGBControllers, YICO_VID, YICO_08_PID); +REGISTER_HID_DETECTOR("YICO 08 ELITE", DetectDRGBControllers, YICO_VID, YICO_08_1_PID); diff --git a/Controllers/DRGBController/RGBController_DRGB.cpp b/Controllers/DRGBController/RGBController_DRGB.cpp new file mode 100644 index 00000000..fbf66984 --- /dev/null +++ b/Controllers/DRGBController/RGBController_DRGB.cpp @@ -0,0 +1,469 @@ +/*---------------------------------------------------------*\ +| RGBController_DRGB.cpp | +| | +| Driver for DRGBmods | +| | +| Zhi Yan 25 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "RGBController_DRGB.h" + +/**------------------------------------------------------------------*\ + @name DRGB Controller + @category LEDStrip + @type USB + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectDRGBControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_DRGB::RGBController_DRGB(DRGBController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "DRGB"; + description = "DRGB Controller Device"; + type = DEVICE_TYPE_LEDSTRIP; + version = controller->GetFirmwareString(); + location = controller->GetLocationString(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + SetupZones(); +} + +RGBController_DRGB::~RGBController_DRGB() +{ + delete controller; +} + +void RGBController_DRGB::SetupZones() +{ + /*-------------------------------------------------*\ + | Only set LED count on the first run | + \*-------------------------------------------------*/ + bool first_run = false; + if(zones.size() == 0) + { + first_run = true; + } + leds.clear(); + colors.clear(); + + unsigned int NUM_CHANNELS = 0; + unsigned int NUM_Channel_led = 0; + switch(controller->GetDevicePID()) + { + case DRGB_LED_V4_PID: + NUM_CHANNELS = 8; + NUM_Channel_led = 512; + Version = 4; + break; + case DRGB_ULTRA_V4F_PID: + NUM_CHANNELS = 16; + NUM_Channel_led = 256; + Version = 4; + break; + case DRGB_CORE_V4F_PID: + NUM_CHANNELS = 32; + NUM_Channel_led = 256; + Version = 4; + break; + case DRGB_SIG_V4F_PID: + NUM_CHANNELS = 36; + NUM_Channel_led = 256; + Version = 4; + break; + case DRGB_AG_04_V4F_PID: + NUM_CHANNELS = 4; + NUM_Channel_led = 256; + Version = 4; + break; + case DRGB_AG_16_V4F_PID: + NUM_CHANNELS = 16; + NUM_Channel_led = 256; + Version = 4; + break; + + case DRGB_LED_V5_PID: + NUM_CHANNELS = 8; + NUM_Channel_led = 512; + Version = 4; + break; + case DRGB_ULTRA_V5_PID: + NUM_CHANNELS = 16; + NUM_Channel_led = 256; + Version = 4; + break; + case DRGB_ULTRA_V5F_PID: + NUM_CHANNELS = 16; + NUM_Channel_led = 256; + Version = 4; + break; + case DRGB_CORE_V5_PID: + NUM_CHANNELS = 32; + NUM_Channel_led = 256; + Version = 4; + break; + case DRGB_CORE_V5F_PID: + NUM_CHANNELS = 32; + NUM_Channel_led = 256; + Version = 4; + break; + case DRGB_SIG_V5F_PID: + NUM_CHANNELS = 32; + NUM_Channel_led = 256; + Version = 4; + break; + + case DRGB_LED_V3_PID: + NUM_CHANNELS = 8; + NUM_Channel_led = 256; + Version = 3; + break; + case DRGB_Ultra_V3_PID: + NUM_CHANNELS = 16; + NUM_Channel_led = 256; + Version = 3; + break; + case DRGB_CORE_V3_PID: + NUM_CHANNELS = 30; + NUM_Channel_led = 256; + Version = 3; + break; + case DRGB_ELITE_PID: + NUM_CHANNELS = 8; + NUM_Channel_led = 132; + Version = 1; + break; + case DM_10_PID: + NUM_CHANNELS = 10; + NUM_Channel_led = 132; + Version = 1; + break; + case JPU_12_PID: + NUM_CHANNELS = 12; + NUM_Channel_led = 60; + Version = 1; + break; + + case DRGB_LED_PID: + NUM_CHANNELS = 8; + NUM_Channel_led = 256; + Version = 2; + break; + case DRGB_ULTRA_PID: + NUM_CHANNELS = 16; + NUM_Channel_led = 256; + Version = 2; + break; + case DRGB_SIG_AB_PID: + NUM_CHANNELS = 16; + NUM_Channel_led = 256; + Version = 2; + break; + case DRGB_SIG_CD_PID: + NUM_CHANNELS = 6; + NUM_Channel_led = 256; + Version = 2; + break; + case DRGB_Strimer_PID: + NUM_CHANNELS = 6; + NUM_Channel_led = 256; + Version = 2; + break; + + case YICO_8_PID: + NUM_CHANNELS = 8; + NUM_Channel_led = 256; + Version = 3; + break; + case YICO_08_PID: + NUM_CHANNELS = 8; + NUM_Channel_led = 256; + Version = 3; + break; + case YICO_08_1_PID: + NUM_CHANNELS = 8; + NUM_Channel_led = 132; + Version = 3; + break; + } + + zones.resize(NUM_CHANNELS); + + for(unsigned int channel_idx = 0; channel_idx < NUM_CHANNELS; channel_idx++) + { + char ch_idx_string[4]; + if(NUM_CHANNELS == 6) + { + if(channel_idx==0) + { + snprintf(ch_idx_string, 2, "%d", channel_idx+1 ); + zones[channel_idx].name = "Strimer ATX"; + } + else if(channel_idx<3) + { + snprintf(ch_idx_string, 2, "%d", channel_idx ); + zones[channel_idx].name = "Channel C"; + } + else if(channel_idx==3) + { + snprintf(ch_idx_string, 2, "%d", channel_idx-2 ); + zones[channel_idx].name = "Strimer GPU"; + } + else if(channel_idx<6) + { + snprintf(ch_idx_string, 2, "%d", channel_idx -3); + zones[channel_idx].name = "Channel D"; + } + } + else if(NUM_CHANNELS == 10 || NUM_CHANNELS == 12) + { + snprintf(ch_idx_string, 4, "%d", channel_idx+1 ); + zones[channel_idx].name = "Channel "; + } + else if(channel_idx<8) + { + snprintf(ch_idx_string, 2, "%d", channel_idx + 1); + zones[channel_idx].name = "Channel A"; + } + else if(channel_idx<16) + { + snprintf(ch_idx_string, 2, "%d", channel_idx -7); + zones[channel_idx].name = "Channel B"; + } + else if(NUM_CHANNELS == 30) + { + if(channel_idx<24) + { + snprintf(ch_idx_string, 2, "%d", channel_idx -15); + zones[channel_idx].name = "Channel C"; + } + else if(channel_idx<30) + { + snprintf(ch_idx_string, 2, "%d", channel_idx -23); + zones[channel_idx].name = "Channel D"; + } + } + else if(channel_idx<22) + { + snprintf(ch_idx_string, 2, "%d", channel_idx -15); + zones[channel_idx].name = "Channel C"; + } + else if(channel_idx<28) + { + snprintf(ch_idx_string, 2, "%d", channel_idx -21); + zones[channel_idx].name = "Channel D"; + } + else if(channel_idx<36) + { + snprintf(ch_idx_string, 2, "%d", channel_idx -27); + zones[channel_idx].name = "Channel E"; + } + zones[channel_idx].name.append(ch_idx_string); + zones[channel_idx].type = ZONE_TYPE_LINEAR; + zones[channel_idx].leds_min = 0; + zones[channel_idx].leds_max = NUM_Channel_led; + + if(first_run) + { + zones[channel_idx].leds_count = 0; + } + + zones[channel_idx].matrix_map = NULL; + + for(unsigned int led_ch_idx = 0; led_ch_idx < zones[channel_idx].leds_count; led_ch_idx++) + { + char led_idx_string[4]; + snprintf(led_idx_string, 4, "%d", led_ch_idx + 1); + led new_led; + new_led.name = "LED "; + new_led.name.append(led_idx_string); + leds.push_back(new_led); + leds_channel.push_back(channel_idx); + } + } + + SetupColors(); + +} + +void RGBController_DRGB::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_DRGB::DeviceUpdateLEDs() +{ + switch(Version) + { + case 4: + { + unsigned int led_index = 0; + unsigned char RGBData[8192*3 + 72] = {0}; + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + unsigned char LEDnum = zones[zone_idx].leds_count; + unsigned int HighCount = (LEDnum & 0xFFFF)>>8; + unsigned int LowCount = LEDnum & 0xFF; + RGBData[zone_idx * 2 ] = HighCount; + RGBData[zone_idx * 2 + 1] = LowCount; + for(unsigned int i=0; i> 8) & 0xFF; + RGBData[led_index * 3 +74] = (RGBcolors >> 16) & 0xFF; + led_index++; + } + if(led_index>8192) + { + break; + } + } + unsigned int col_packets = 1 ; + if(led_index > DRGB_V4_ONE_PACKAGE_SIZE) + { + col_packets = 1 + ((led_index - DRGB_V4_ONE_PACKAGE_SIZE) / DRGB_V4_PACKAGE_SIZE) + (((led_index - DRGB_V4_ONE_PACKAGE_SIZE) % DRGB_V4_PACKAGE_SIZE) > 0); + } + controller->SendPacket(&RGBData[0], col_packets,led_index); + break; + } + + case 3: + { + unsigned int led_index = 0; + unsigned char RGBData[1801*3] = {0}; + unsigned char ArrayData[64] = {0}; + ArrayData[0] = 0x60; + ArrayData[1] = 0xBB; + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + unsigned char LEDnum = zones[zone_idx].leds_count; + unsigned int HighCount = (LEDnum & 0xFFFF)>>8; + unsigned int LowCount = LEDnum & 0xFF; + ArrayData[zone_idx * 2 + 2] = HighCount; + ArrayData[zone_idx * 2 + 3] = LowCount; + for(unsigned int i=0; i> 8) & 0xFF; + RGBData[led_index * 3 +2] = (RGBcolors >> 16) & 0xFF; + led_index++; + } + if(led_index>1800) + { + break; + } + } + unsigned int col_packets = (led_index / DRGB_V3_PACKAGE_SIZE) + ((led_index % DRGB_V3_PACKAGE_SIZE) > 0); + controller->SendPacketFS(&ArrayData[0], 1,0); + controller->SendPacketFS(&RGBData[0], col_packets,0x64); + break; + } + + case 2: + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + unsigned char RGBData[256*3] = {0}; + unsigned char ArrayData[64] = {0}; + unsigned char LEDnum = zones[zone_idx].leds_count; + for(unsigned int i = 0; i < LEDnum; i++) + { + unsigned int RGBcolors = zones[zone_idx].colors[i]; + RGBData[i * 3] = RGBcolors & 0xFF; + RGBData[i * 3 +1] = (RGBcolors >> 8) & 0xFF; + RGBData[i * 3 +2] = (RGBcolors >> 16) & 0xFF; + } + + unsigned char NumPackets = LEDnum / DRGB_V2_PACKAGE_SIZE + ((LEDnum % DRGB_V2_PACKAGE_SIZE) > 0); + for(unsigned char CurrPacket = 1; CurrPacket <= NumPackets; CurrPacket++) + { + ArrayData[0] = CurrPacket; + ArrayData[1] = NumPackets; + ArrayData[2] = (unsigned char)zone_idx; + ArrayData[3] = 0xBB; + for(unsigned int i=0; i<60;i++) + { + ArrayData[4+i] = RGBData[(CurrPacket -1)*60 + i]; + } + controller->SendPacketFS(&ArrayData[0], 1,0); + } + } + break; + + case 1: + { + unsigned int led_index = 0; + unsigned char RGBData[1801*3] = {0}; + unsigned char ArrayData[64] = {0}; + ArrayData[0] = 0x46; + ArrayData[1] = 0xBB; + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + unsigned char LEDnum = zones[zone_idx].leds_count; + unsigned int HighCount = (LEDnum & 0xFFFF)>>8; + unsigned int LowCount = LEDnum & 0xFF; + ArrayData[zone_idx * 2 + 2] = HighCount; + ArrayData[zone_idx * 2 + 3] = LowCount; + for(unsigned int i=0; i> 8) & 0xFF; + RGBData[led_index * 3 +2] = (RGBcolors >> 16) & 0xFF; + led_index++; + } + if(led_index>1800) + { + break; + } + } + unsigned int col_packets = (led_index / DRGB_V3_PACKAGE_SIZE) + ((led_index % DRGB_V3_PACKAGE_SIZE) > 0); + controller->SendPacketFS(&ArrayData[0], 1,0); + controller->SendPacketFS(&RGBData[0], col_packets,0x47); + break; + } + } +} + +void RGBController_DRGB::UpdateZoneLEDs(int zone) +{ + controller->SetChannelLEDs(zone, zones[zone].colors, zones[zone].leds_count); +} + +void RGBController_DRGB::UpdateSingleLED(int led) +{ + unsigned int channel = leds_channel[led]; + controller->SetChannelLEDs(channel, zones[channel].colors, zones[channel].leds_count); +} + +void RGBController_DRGB::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} diff --git a/Controllers/DRGBController/RGBController_DRGB.h b/Controllers/DRGBController/RGBController_DRGB.h new file mode 100644 index 00000000..ae9a0fab --- /dev/null +++ b/Controllers/DRGBController/RGBController_DRGB.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------*\ +| RGBController_DRGB.h | +| | +| Driver for DRGBmods | +| | +| Zhi Yan 25 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "DRGBController.h" + +#define DRGBV4_VID 0x2486 +#define DRGB_LED_V4_PID 0x3608 +#define DRGB_ULTRA_V4F_PID 0x3616 +#define DRGB_CORE_V4F_PID 0x3628 +#define DRGB_SIG_V4F_PID 0x3636 +#define DRGB_AG_04_V4F_PID 0x3204 +#define DRGB_AG_16_V4F_PID 0x3216 + +#define DRGB_LED_V5_PID 0x3208 +#define DRGB_ULTRA_V5_PID 0x3215 +#define DRGB_ULTRA_V5F_PID 0x3217 +#define DRGB_CORE_V5_PID 0x3228 +#define DRGB_CORE_V5F_PID 0x3229 +#define DRGB_SIG_V5F_PID 0x3232 + +#define DRGBV3_VID 0x2023 +#define DRGB_LED_V3_PID 0x1209 +#define DRGB_Ultra_V3_PID 0x1221 +#define DRGB_CORE_V3_PID 0x1226 +#define DRGB_ELITE_PID 0x1408 +#define DM_10_PID 0x1410 +#define JPU_12_PID 0x1412 + +#define DRGBV2_VID 0x2023 +#define DRGB_LED_PID 0x1208 +#define DRGB_ULTRA_PID 0x1220 +#define DRGB_SIG_AB_PID 0x1210 +#define DRGB_SIG_CD_PID 0x1211 +#define DRGB_Strimer_PID 0x1215 + +#define YICO_VID 0x1368 +#define YICO_8_PID 0x6077 +#define YICO_08_PID 0x6078 +#define YICO_08_1_PID 0x6079 + +class RGBController_DRGB : public RGBController +{ +public: + RGBController_DRGB(DRGBController* controller_ptr); + ~RGBController_DRGB(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + void DeviceUpdateMode(); + +private: + DRGBController* controller; + std::vector leds_channel; + std::vector zones_channel; + unsigned int Version = 4; +}; diff --git a/Controllers/DarkProject/DarkProjectControllerDetect.cpp b/Controllers/DarkProject/DarkProjectControllerDetect.cpp index 58304ccd..ab4c6055 100644 --- a/Controllers/DarkProject/DarkProjectControllerDetect.cpp +++ b/Controllers/DarkProject/DarkProjectControllerDetect.cpp @@ -1,6 +1,15 @@ -#include "Detector.h" -#include "RGBController.h" +/*---------------------------------------------------------*\ +| DarkProjectControllerDetect.cpp | +| | +| Detector for Dark Project devices | +| | +| Chris M (DrNo) 08 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include "Detector.h" #include "RGBController_DarkProjectKeyboard.h" /*---------------------------------------------------------*\ @@ -19,9 +28,9 @@ void DetectDarkProjectKeyboardControllers(hid_device_info* info, const std::stri if(dev) { - DarkProjectKeyboardController* controller = new DarkProjectKeyboardController(dev, info->path); + DarkProjectKeyboardController* controller = new DarkProjectKeyboardController(dev, info->path, name); RGBController_DarkProjectKeyboard* rgb_controller = new RGBController_DarkProjectKeyboard(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } diff --git a/Controllers/DarkProject/DarkProjectKeyboardController.cpp b/Controllers/DarkProject/DarkProjectKeyboardController.cpp index 62d6c7ab..1b963cce 100644 --- a/Controllers/DarkProject/DarkProjectKeyboardController.cpp +++ b/Controllers/DarkProject/DarkProjectKeyboardController.cpp @@ -1,14 +1,17 @@ -/*-------------------------------------------------------------------*\ -| DarkProjectKeyboardController.cpp | -| | -| Driver for DarkProjectKeyboard USB Controller | -| | -| Chris M (DrNo) 8 Apr 2022 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| DarkProjectKeyboardController.cpp | +| | +| Driver for Dark Project keyboard | +| | +| Chris M (DrNo) 08 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "LogManager.h" #include "DarkProjectKeyboardController.h" +#include "LogManager.h" +#include "StringUtils.h" static uint8_t packet_map[88] = { @@ -42,10 +45,11 @@ static uint8_t packet_map[88] = /* Missing Indexes 9, 22, 28, 40, 46, 70, 74, 75, 82, 86, 87, 92, 98, 99, 101 */ }; -DarkProjectKeyboardController::DarkProjectKeyboardController(hid_device* dev_handle, const char* path) +DarkProjectKeyboardController::DarkProjectKeyboardController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } DarkProjectKeyboardController::~DarkProjectKeyboardController() @@ -53,33 +57,27 @@ DarkProjectKeyboardController::~DarkProjectKeyboardController() hid_close(dev); } -std::string DarkProjectKeyboardController::GetDeviceName() +std::string DarkProjectKeyboardController::GetLocation() { - const int szTemp = HID_MAX_STR; - wchar_t tmpName[szTemp]; + return("HID: " + location); +} - hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - std::string name = std::string(wName.begin(), wName.end()); - - return name; +std::string DarkProjectKeyboardController::GetName() +{ + return(name); } std::string DarkProjectKeyboardController::GetSerial() { - const int szTemp = HID_MAX_STR; - wchar_t tmpName[szTemp]; + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); - hid_get_serial_number_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - std::string serial = std::string(wName.begin(), wName.end()); + if(ret != 0) + { + return(""); + } - return serial; -} - -std::string DarkProjectKeyboardController::GetLocation() -{ - return("HID: " + location); + return(StringUtils::wstring_to_string(serial_string)); } void DarkProjectKeyboardController::SetLedsDirect(std::vector colors) diff --git a/Controllers/DarkProject/DarkProjectKeyboardController.h b/Controllers/DarkProject/DarkProjectKeyboardController.h index d942bc51..05f7a76d 100644 --- a/Controllers/DarkProject/DarkProjectKeyboardController.h +++ b/Controllers/DarkProject/DarkProjectKeyboardController.h @@ -1,18 +1,20 @@ -/*-------------------------------------------------------------------*\ -| DarkProjectKeyboardController.h | -| | -| Driver for DarkProjectKeyboard USB Controller | -| | -| Chris M (DrNo) 8 Apr 2022 | -| | -\*-------------------------------------------------------------------*/ - -#include -#include -#include "RGBController.h" +/*---------------------------------------------------------*\ +| DarkProjectKeyboardController.h | +| | +| Driver for Dark Project keyboard | +| | +| Chris M (DrNo) 08 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + #define NA 0xFFFFFFFF #define HID_MAX_STR 255 @@ -35,15 +37,16 @@ enum class DarkProjectKeyboardController { public: - DarkProjectKeyboardController(hid_device* dev_handle, const char* path); + DarkProjectKeyboardController(hid_device* dev_handle, const char* path, std::string dev_name); ~DarkProjectKeyboardController(); - std::string GetDeviceName(); - std::string GetSerial(); std::string GetLocation(); + std::string GetName(); + std::string GetSerial(); void SetLedsDirect(std::vector colors); private: - std::string location; hid_device* dev; + std::string location; + std::string name; }; diff --git a/Controllers/DarkProject/RGBController_DarkProjectKeyboard.cpp b/Controllers/DarkProject/RGBController_DarkProjectKeyboard.cpp index 5e0f3f49..91543460 100644 --- a/Controllers/DarkProject/RGBController_DarkProjectKeyboard.cpp +++ b/Controllers/DarkProject/RGBController_DarkProjectKeyboard.cpp @@ -1,11 +1,13 @@ -/*-------------------------------------------------------------------*\ -| RGBController_DarkProjectKeyboard.cpp | -| | -| Driver for DarkProjectKeyboard USB Controller | -| | -| Chris M (DrNo) 8 Apr 2022 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_DarkProjectKeyboard.cpp | +| | +| RGBController for Dark Project keyboard | +| | +| Chris M (DrNo) 08 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_DarkProjectKeyboard.h" @@ -132,10 +134,10 @@ RGBController_DarkProjectKeyboard::RGBController_DarkProjectKeyboard(DarkProject { controller = controller_ptr; - name = "Dark Project Keyboard"; + name = controller->GetName(); vendor = "Dark Project"; type = DEVICE_TYPE_KEYBOARD; - description = controller->GetDeviceName(); + description = "Dark Project Keyboard Device"; serial = controller->GetSerial(); location = controller->GetLocation(); diff --git a/Controllers/DarkProject/RGBController_DarkProjectKeyboard.h b/Controllers/DarkProject/RGBController_DarkProjectKeyboard.h index 74758969..579c2f60 100644 --- a/Controllers/DarkProject/RGBController_DarkProjectKeyboard.h +++ b/Controllers/DarkProject/RGBController_DarkProjectKeyboard.h @@ -1,17 +1,20 @@ -/*-------------------------------------------------------------------*\ -| RGBController_DarkProjectKeyboard.h | -| | -| Driver for DarkProjectKeyboard USB Controller | -| | -| Chris M (DrNo) 8 Apr 2022 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_DarkProjectKeyboard.h | +| | +| RGBController for Dark Project keyboard | +| | +| Chris M (DrNo) 08 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + +#include #include "LogManager.h" #include "RGBController.h" #include "DarkProjectKeyboardController.h" -#include class RGBController_DarkProjectKeyboard : public RGBController { diff --git a/Controllers/DasKeyboardController/DasKeyboardController.cpp b/Controllers/DasKeyboardController/DasKeyboardController.cpp index e36c7038..a93522d5 100644 --- a/Controllers/DasKeyboardController/DasKeyboardController.cpp +++ b/Controllers/DasKeyboardController/DasKeyboardController.cpp @@ -1,21 +1,25 @@ -/*-----------------------------------------*\ -| DasKeyboardController.cpp | -| | -| Driver for Das Keyboard RGB keyboard | -| lighting controller | -| | -| Frank Niessen (denk_mal) 12/16/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| DasKeyboardController.cpp | +| | +| Driver for Das Keyboard keyboard | +| | +| Frank Niessen (denk_mal) 16 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include #include "DasKeyboardController.h" +#include "StringUtils.h" using namespace std::chrono_literals; -DasKeyboardController::DasKeyboardController(hid_device *dev_handle, const char *path) +DasKeyboardController::DasKeyboardController(hid_device *dev_handle, const char *path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; version = ""; useTraditionalSendData = false; @@ -27,36 +31,54 @@ DasKeyboardController::~DasKeyboardController() hid_close(dev); } -std::string DasKeyboardController::GetDeviceLocation() +std::string DasKeyboardController::GetLayoutString() { - return "HID: " + location; + /*-----------------------------------------------------------*\ + | Experimental for now; should be '16 or 63' for US and '28' | + | for EU layout | + \*-----------------------------------------------------------*/ + if(version.length() < 17) + { + return("NONE"); + } + std::string layout_id = version.substr(3, 2); + + if(layout_id == "16" || layout_id == "63") + { + return("US"); + } + + return("EU"); +} + +std::string DasKeyboardController::GetLocationString() +{ + return("HID: " + location); +} + +std::string DasKeyboardController::GetNameString() +{ + return(name); } std::string DasKeyboardController::GetSerialString() { - wchar_t serial_string[128] = {}; - int err = hid_get_serial_number_string(dev, serial_string, 128); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); - std::string return_string; - if(err == 0) + if(ret != 0) { - std::wstring return_wstring = serial_string; - return_string = std::string(return_wstring.begin(), return_wstring.end()); + return(""); } - if(return_string.empty()) - { - return_string = version; - } - - return return_string; + return(StringUtils::wstring_to_string(serial_string)); } std::string DasKeyboardController::GetVersionString() { if(version.length() < 17) { - return version; + return(version); } std::string fw_version = "V"; @@ -65,27 +87,7 @@ std::string DasKeyboardController::GetVersionString() fw_version += version.substr(15, 2); fw_version += ".0"; - return fw_version; -} - -std::string DasKeyboardController::GetLayoutString() -{ - /*-----------------------------------------------------*\ - | Experimental for now; should be '16' for US and '28' | - | for EU layout | - \*-----------------------------------------------------*/ - if(version.length() < 17) - { - return "NONE"; - } - std::string layout_id = version.substr(3, 2); - - if(layout_id == "16") - { - return "US"; - } - - return "EU"; + return(fw_version); } void DasKeyboardController::SendColors(unsigned char key_id, unsigned char mode, @@ -322,30 +324,31 @@ int DasKeyboardController::ReceiveData(unsigned char *data, const unsigned int m \*-----------------------------------------------------*/ if(chk_sum) { - return -1; + return(-1); } - size_t response_size = 0; + unsigned int response_size = 0; if(receive_buf.size() > 1) { response_size = receive_buf.at(1); + if(response_size + 2 > receive_buf.size()) { - return -1; + return(-1); } if(response_size > max_length) { - response_size = static_cast(max_length); + response_size = max_length; } /*-----------------------------------------------------*\ | Remove first two bytes (signature?) and content length| \*-----------------------------------------------------*/ - for(size_t ii = 0; ii < response_size - 1; ii++) + for(unsigned int ii = 0; ii < response_size - 1; ii++) { data[ii] = receive_buf.at(ii + 2); } } - return response_size; + return(response_size); } diff --git a/Controllers/DasKeyboardController/DasKeyboardController.h b/Controllers/DasKeyboardController/DasKeyboardController.h index 72bdc1bb..e5f4e828 100644 --- a/Controllers/DasKeyboardController/DasKeyboardController.h +++ b/Controllers/DasKeyboardController/DasKeyboardController.h @@ -1,42 +1,41 @@ -/*-----------------------------------------*\ -| DasKeyboardController.h | -| | -| Definitions and types for Das Keyboard | -| RGB keyboard lighting controller | -| | -| Frank Niessen (denk_mal) 12/16/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| DasKeyboardController.h | +| | +| Driver for Das Keyboard keyboard | +| | +| Frank Niessen (denk_mal) 16 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + class DasKeyboardController { public: - DasKeyboardController(hid_device *dev_handle, const char *path); + DasKeyboardController(hid_device *dev_handle, const char *path, std::string dev_name); ~DasKeyboardController(); - std::string GetDeviceLocation(); - + std::string GetLayoutString(); + std::string GetLocationString(); + std::string GetNameString(); std::string GetSerialString(); - std::string GetVersionString(); - std::string GetLayoutString(); - - void SendColors(unsigned char key_id, unsigned char mode, - unsigned char red, unsigned char green, unsigned char blue); + void SendColors(unsigned char key_id, unsigned char mode, unsigned char red, unsigned char green, unsigned char blue); void SendApply(); private: hid_device *dev; std::string location; + std::string name; std::string version; bool useTraditionalSendData; diff --git a/Controllers/DasKeyboardController/DasKeyboardControllerDetect.cpp b/Controllers/DasKeyboardController/DasKeyboardControllerDetect.cpp index 3de53f4d..19338dbe 100644 --- a/Controllers/DasKeyboardController/DasKeyboardControllerDetect.cpp +++ b/Controllers/DasKeyboardController/DasKeyboardControllerDetect.cpp @@ -1,8 +1,18 @@ +/*---------------------------------------------------------*\ +| DasKeyboardControllerDetect.cpp | +| | +| Detector for Das Keyboard keyboard | +| | +| Frank Niessen (denk_mal) 16 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "DasKeyboardController.h" -#include "RGBController.h" #include "RGBController_DasKeyboard.h" -#include +#include /*-----------------------------------------------------*\ | Das Keyboard vendor ID | @@ -25,33 +35,13 @@ * * \******************************************************************************************/ -void DetectDasKeyboardControllers(hid_device_info *info_in, const std::string &name) +void DetectDasKeyboardControllers(hid_device_info *info, const std::string &name) { - hid_device_info *info = info_in; - - while(info) - { - if(info->vendor_id == DAS_KEYBOARD_VID && - (info->product_id == DAS_KEYBOARD_Q4_PID || - info->product_id == DAS_KEYBOARD_Q5_PID || - info->product_id == DAS_KEYBOARD_Q5S_PID) && - info->interface_number == 1) - { - break; - } - info = info->next; - } - - if(!info) - { - return; - } - hid_device *dev = hid_open_path(info->path); if(dev) { - DasKeyboardController *controller = new DasKeyboardController(dev, info->path); + DasKeyboardController *controller = new DasKeyboardController(dev, info->path, name); if(controller->GetLayoutString() == "NONE") { @@ -60,37 +50,12 @@ void DetectDasKeyboardControllers(hid_device_info *info_in, const std::string &n else { RGBController_DasKeyboard *rgb_controller = new RGBController_DasKeyboard(controller); - rgb_controller->SetupZones(); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } } /* DetectDasKeyboardControllers() */ -void DetectDas4QKeyboard(hid_device_info *info, const std::string &name) -{ - hid_device *dev = hid_open_path(info->path); - - if(dev) - { - DasKeyboardController *controller = new DasKeyboardController(dev, info->path); - - if(controller->GetLayoutString() == "NONE") - { - delete controller; - } - else - { - RGBController_DasKeyboard *rgb_controller = new RGBController_DasKeyboard(controller); - rgb_controller->SetupZones(); - rgb_controller->name = name; - - ResourceManager::get()->RegisterRGBController(rgb_controller); - } - } -} /* DetectDas4QKeyboard() */ - -REGISTER_HID_DETECTOR_IPU("Das Keyboard Q4 RGB", DetectDas4QKeyboard, DAS_KEYBOARD_VID, DAS_KEYBOARD_Q4_PID, 1, 0x01, 0x80); +REGISTER_HID_DETECTOR_IPU("Das Keyboard Q4 RGB", DetectDasKeyboardControllers, DAS_KEYBOARD_VID, DAS_KEYBOARD_Q4_PID, 1, 0x01, 0x80); REGISTER_HID_DETECTOR_I ("Das Keyboard Q5 RGB", DetectDasKeyboardControllers, DAS_KEYBOARD_VID, DAS_KEYBOARD_Q5_PID, 1); REGISTER_HID_DETECTOR_I ("Das Keyboard Q5S RGB", DetectDasKeyboardControllers, DAS_KEYBOARD_VID, DAS_KEYBOARD_Q5S_PID, 1); diff --git a/Controllers/DasKeyboardController/RGBController_DasKeyboard.cpp b/Controllers/DasKeyboardController/RGBController_DasKeyboard.cpp index 3bf3609e..2b60f00e 100644 --- a/Controllers/DasKeyboardController/RGBController_DasKeyboard.cpp +++ b/Controllers/DasKeyboardController/RGBController_DasKeyboard.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_DasKeyboard.cpp | -| | -| Generic RGB Interface for Das Keyboard | -| RGB keyboard devices | -| | -| Frank Niessen (denk_mal) 12/16/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_DasKeyboard.cpp | +| | +| RGBController for Das Keyboard keyboard | +| | +| Frank Niessen (denk_mal) 16 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_DasKeyboard.h" @@ -15,10 +17,10 @@ using namespace std::chrono_literals; //0xFFFFFFFF indicates an unused entry in matrix #define NA 0xFFFFFFFF -// US Layout TODO: mus be checked/corrected +// US Layout static unsigned int matrix_map_us[7][21] = { - {NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 126, NA, NA, NA}, + {NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA}, { 5, NA, 17, 23, 29, 35, 41, 47, 53, 59, 65, 71, 77, 83, 89, 95, 101, 127, 128, 129, 130}, { 4, 10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, 76, 82, 88, 94, 100, 106, 112, 118, 124}, { 3, 9, 15, 21, 27, 33, 39, 45, 51, 57, 63, 69, 75, 7, 87, 93, 99, 105, 111, 117, 123}, @@ -212,11 +214,11 @@ RGBController_DasKeyboard::RGBController_DasKeyboard(DasKeyboardController* cont updateDevice = true; - name = "Das Keyboard Device"; + name = controller->GetNameString(); vendor = "Metadot"; type = DEVICE_TYPE_KEYBOARD; description = "Das Keyboard Device"; - location = controller->GetDeviceLocation(); + location = controller->GetLocationString(); serial = controller->GetSerialString(); version = controller->GetVersionString(); @@ -240,6 +242,8 @@ RGBController_DasKeyboard::RGBController_DasKeyboard(DasKeyboardController* cont modes[3].value = DAS_KEYBOARD_MODE_SPECTRUM_CYCLE; modes[3].flags = MODE_FLAG_HAS_PER_LED_COLOR; modes[3].color_mode = MODE_COLORS_PER_LED; + + SetupZones(); } RGBController_DasKeyboard::~RGBController_DasKeyboard() @@ -247,7 +251,7 @@ RGBController_DasKeyboard::~RGBController_DasKeyboard() /*---------------------------------------------------------*\ | Delete the matrix map | \*---------------------------------------------------------*/ - unsigned int zone_size = zones.size(); + unsigned int zone_size = (unsigned int)zones.size(); for(unsigned int zone_index = 0; zone_index < zone_size; zone_index++) { diff --git a/Controllers/DasKeyboardController/RGBController_DasKeyboard.h b/Controllers/DasKeyboardController/RGBController_DasKeyboard.h index 02b7f5a4..516a588e 100644 --- a/Controllers/DasKeyboardController/RGBController_DasKeyboard.h +++ b/Controllers/DasKeyboardController/RGBController_DasKeyboard.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_DasKeyboard.h | -| | -| Generic RGB Interface for Das Keyboard | -| RGB keyboard devices | -| | -| Frank Niessen (denk_mal) 12/16/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_DasKeyboard.h | +| | +| RGBController for Das Keyboard keyboard | +| | +| Frank Niessen (denk_mal) 16 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once @@ -20,7 +22,6 @@ enum DAS_KEYBOARD_MODE_SPECTRUM_CYCLE = 0x14 }; - class RGBController_DasKeyboard : public RGBController { public: diff --git a/Controllers/DebugController/DebugControllerDetect.cpp b/Controllers/DebugController/DebugControllerDetect.cpp index cb944518..1007ef5a 100644 --- a/Controllers/DebugController/DebugControllerDetect.cpp +++ b/Controllers/DebugController/DebugControllerDetect.cpp @@ -1,34 +1,24 @@ +/*---------------------------------------------------------*\ +| DebugControllerDetect.cpp | +| | +| Detector for debug devices | +| | +| Adam Honse 31 Jul 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "RGBController.h" #include "RGBController_Debug.h" -#include "RGBController_Dummy.h" -#include "RGBControllerKeyNames.h" -#include "KeyboardLayoutManager.h" #include "SettingsManager.h" -#include -#include -#include - -#include -#include -#include -#include -#include - - -//0xFFFFFFFF indicates an unused entry in matrix -#define NA 0xFFFFFFFF - -static unsigned int dummy_keyboard_underglow_map[3][10] = - { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, - { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }, - { 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 } }; /******************************************************************************************\ * * * DetectDebugControllers * * * -* Add dummy controllers based on the DebugDevices key in the settings json * +* Add debug controllers based on the DebugDevices key in the settings json * * * \******************************************************************************************/ @@ -36,696 +26,50 @@ void DetectDebugControllers() { json debug_settings; - /*-------------------------------------------------*\ - | Get Debug Device settings from settings manager | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Get Debug Device settings from settings manager | + \*-----------------------------------------------------*/ debug_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("DebugDevices"); - /*-------------------------------------------------*\ - | If the Debug settings contains devices, process | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | If the Debug settings contains devices, process | + \*-----------------------------------------------------*/ if(debug_settings.contains("devices")) { for(unsigned int device_idx = 0; device_idx < debug_settings["devices"].size(); device_idx++) { - std::string type = ""; - - if(debug_settings["devices"][device_idx].contains("type")) - { - type = debug_settings["devices"][device_idx]["type"]; - } - - if(type == "motherboard") - { - /*---------------------------------------------------------*\ - | Create a dummy motherboard | - \*---------------------------------------------------------*/ - RGBController_Dummy* dummy_motherboard = new RGBController_Dummy(); - - dummy_motherboard->name = "Debug Motherboard"; - dummy_motherboard->type = DEVICE_TYPE_MOTHERBOARD; - dummy_motherboard->description = "Debug Motherboard Device"; - dummy_motherboard->location = "Debug Motherboard Location"; - dummy_motherboard->version = "Debug Motherboard Version"; - dummy_motherboard->serial = "Debug Motherboard Serial"; - - /*---------------------------------------------------------*\ - | Create a direct mode for the dummy motherboard | - \*---------------------------------------------------------*/ - mode dummy_motherboard_direct_mode; - - dummy_motherboard_direct_mode.name = "Direct"; - dummy_motherboard_direct_mode.value = 0; - dummy_motherboard_direct_mode.flags = MODE_FLAG_HAS_PER_LED_COLOR; - dummy_motherboard_direct_mode.color_mode = MODE_COLORS_PER_LED; - - dummy_motherboard->modes.push_back(dummy_motherboard_direct_mode); - - /*---------------------------------------------------------*\ - | Create a single zone/LED for the dummy motherboard | - \*---------------------------------------------------------*/ - zone dummy_motherboard_single_zone; - - dummy_motherboard_single_zone.name = "Single Zone"; - dummy_motherboard_single_zone.type = ZONE_TYPE_SINGLE; - dummy_motherboard_single_zone.leds_min = 1; - dummy_motherboard_single_zone.leds_max = 1; - dummy_motherboard_single_zone.leds_count = 1; - dummy_motherboard_single_zone.matrix_map = NULL; - - dummy_motherboard->zones.push_back(dummy_motherboard_single_zone); - - led dummy_motherboard_single_led; - - dummy_motherboard_single_led.name = "Single LED"; - - dummy_motherboard->leds.push_back(dummy_motherboard_single_led); - - /*---------------------------------------------------------*\ - | Create a linear zone for the dummy motherboard | - \*---------------------------------------------------------*/ - zone dummy_motherboard_linear_zone; - - dummy_motherboard_linear_zone.name = "Linear Zone"; - dummy_motherboard_linear_zone.type = ZONE_TYPE_LINEAR; - dummy_motherboard_linear_zone.leds_min = 10; - dummy_motherboard_linear_zone.leds_max = 10; - dummy_motherboard_linear_zone.leds_count = 10; - dummy_motherboard_linear_zone.matrix_map = NULL; - - dummy_motherboard->zones.push_back(dummy_motherboard_linear_zone); - - for(std::size_t led_idx = 0; led_idx < 10; led_idx++) - { - led dummy_motherboard_linear_led; - - dummy_motherboard_linear_led.name = "Linear LED " + std::to_string(led_idx); - - dummy_motherboard->leds.push_back(dummy_motherboard_linear_led); - } - - dummy_motherboard->SetupColors(); - - /*---------------------------------------------------------*\ - | Push the dummy motherboard onto the controller list | - \*---------------------------------------------------------*/ - ResourceManager::get()->RegisterRGBController(dummy_motherboard); - } - else if(type == "dram") - { - /*---------------------------------------------------------*\ - | Create a dummy DRAM | - \*---------------------------------------------------------*/ - RGBController_Dummy* dummy_dram = new RGBController_Dummy(); - - dummy_dram->name = "Debug DRAM"; - dummy_dram->type = DEVICE_TYPE_DRAM; - dummy_dram->description = "Debug DRAM Device"; - dummy_dram->location = "Debug DRAM Location"; - dummy_dram->version = "Debug DRAM Version"; - dummy_dram->serial = "Debug DRAM Serial"; - - /*---------------------------------------------------------*\ - | Create a direct mode for the dummy DRAM | - \*---------------------------------------------------------*/ - mode dummy_dram_direct_mode; - - dummy_dram_direct_mode.name = "Direct"; - dummy_dram_direct_mode.value = 0; - dummy_dram_direct_mode.flags = MODE_FLAG_HAS_PER_LED_COLOR; - dummy_dram_direct_mode.color_mode = MODE_COLORS_PER_LED; - - dummy_dram->modes.push_back(dummy_dram_direct_mode); - - /*---------------------------------------------------------*\ - | Create a single zone/LED for the dummy DRAM | - \*---------------------------------------------------------*/ - zone dummy_dram_single_zone; - - dummy_dram_single_zone.name = "Single Zone"; - dummy_dram_single_zone.type = ZONE_TYPE_SINGLE; - dummy_dram_single_zone.leds_min = 1; - dummy_dram_single_zone.leds_max = 1; - dummy_dram_single_zone.leds_count = 1; - dummy_dram_single_zone.matrix_map = NULL; - - dummy_dram->zones.push_back(dummy_dram_single_zone); - - led dummy_dram_single_led; - - dummy_dram_single_led.name = "Single LED"; - - dummy_dram->leds.push_back(dummy_dram_single_led); - - /*---------------------------------------------------------*\ - | Create a linear zone for the dummy DRAM | - \*---------------------------------------------------------*/ - zone dummy_dram_linear_zone; - - dummy_dram_linear_zone.name = "Linear Zone"; - dummy_dram_linear_zone.type = ZONE_TYPE_LINEAR; - dummy_dram_linear_zone.leds_min = 5; - dummy_dram_linear_zone.leds_max = 5; - dummy_dram_linear_zone.leds_count = 5; - dummy_dram_linear_zone.matrix_map = NULL; - - dummy_dram->zones.push_back(dummy_dram_linear_zone); - - for(std::size_t led_idx = 0; led_idx < 5; led_idx++) - { - led dummy_dram_linear_led; - - dummy_dram_linear_led.name = "Linear LED " + std::to_string(led_idx); - - dummy_dram->leds.push_back(dummy_dram_linear_led); - } - - dummy_dram->SetupColors(); - - /*---------------------------------------------------------*\ - | Push the dummy DRAM onto the controller list | - \*---------------------------------------------------------*/ - ResourceManager::get()->RegisterRGBController(dummy_dram); - } - else if(type == "gpu") - { - /*---------------------------------------------------------*\ - | Create a dummy GPU | - \*---------------------------------------------------------*/ - RGBController_Dummy* dummy_gpu = new RGBController_Dummy(); - - dummy_gpu->name = "Debug GPU"; - dummy_gpu->type = DEVICE_TYPE_GPU; - dummy_gpu->description = "Debug GPU Device"; - dummy_gpu->location = "Debug GPU Location"; - dummy_gpu->version = "Debug GPU Version"; - dummy_gpu->serial = "Debug GPU Serial"; - - /*---------------------------------------------------------*\ - | Create a direct mode for the dummy GPU | - \*---------------------------------------------------------*/ - mode dummy_gpu_direct_mode; - - dummy_gpu_direct_mode.name = "Direct"; - dummy_gpu_direct_mode.value = 0; - dummy_gpu_direct_mode.flags = MODE_FLAG_HAS_PER_LED_COLOR; - dummy_gpu_direct_mode.color_mode = MODE_COLORS_PER_LED; - - dummy_gpu->modes.push_back(dummy_gpu_direct_mode); - - /*---------------------------------------------------------*\ - | Create a single zone/LED for the dummy GPU | - \*---------------------------------------------------------*/ - zone dummy_gpu_single_zone; - - dummy_gpu_single_zone.name = "Single Zone"; - dummy_gpu_single_zone.type = ZONE_TYPE_SINGLE; - dummy_gpu_single_zone.leds_min = 1; - dummy_gpu_single_zone.leds_max = 1; - dummy_gpu_single_zone.leds_count = 1; - dummy_gpu_single_zone.matrix_map = NULL; - - dummy_gpu->zones.push_back(dummy_gpu_single_zone); - - led dummy_gpu_single_led; - - dummy_gpu_single_led.name = "Single LED"; - - dummy_gpu->leds.push_back(dummy_gpu_single_led); - - /*---------------------------------------------------------*\ - | Create a linear zone for the dummy GPU | - \*---------------------------------------------------------*/ - zone dummy_gpu_linear_zone; - - dummy_gpu_linear_zone.name = "Linear Zone"; - dummy_gpu_linear_zone.type = ZONE_TYPE_LINEAR; - dummy_gpu_linear_zone.leds_min = 15; - dummy_gpu_linear_zone.leds_max = 15; - dummy_gpu_linear_zone.leds_count = 15; - dummy_gpu_linear_zone.matrix_map = NULL; - - dummy_gpu->zones.push_back(dummy_gpu_linear_zone); - - for(std::size_t led_idx = 0; led_idx < 15; led_idx++) - { - led dummy_gpu_linear_led; - - dummy_gpu_linear_led.name = "Linear LED " + std::to_string(led_idx); - - dummy_gpu->leds.push_back(dummy_gpu_linear_led); - } - - dummy_gpu->SetupColors(); - - /*---------------------------------------------------------*\ - | Push the dummy GPU onto the controller list | - \*---------------------------------------------------------*/ - ResourceManager::get()->RegisterRGBController(dummy_gpu); - } - else if(type == "keyboard") - { - json json_kbd = debug_settings["devices"][device_idx]; - KEYBOARD_LAYOUT layout = KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_ANSI_QWERTY; - KEYBOARD_SIZE size = KEYBOARD_SIZE::KEYBOARD_SIZE_FULL; - - if(json_kbd.contains("layout")) - { - layout = json_kbd["layout"]; - } - - if(json_kbd.contains("size")) - { - size = json_kbd["size"]; - } - - /*---------------------------------------------------------*\ - | Create a dummy Keyboard | - \*---------------------------------------------------------*/ - RGBController_Dummy* dummy_keyboard = new RGBController_Dummy(); - KeyboardLayoutManager new_kb(layout, size); - - /*---------------------------------------------------------*\ - | Check for custom key inserts and swaps | - \*---------------------------------------------------------*/ - std::vector change; - - if(json_kbd.contains("insert")) - { - - for(size_t i = 0; i < json_kbd["insert"].size(); i++) - { - keyboard_led* key = new keyboard_led; - - key->zone = json_kbd["insert"][i]["Zone"]; - key->row = json_kbd["insert"][i]["Row"]; - key->col = json_kbd["insert"][i]["Col"]; - key->value = json_kbd["insert"][i]["Val"]; - key->name = json_kbd["insert"][i]["Name"].get_ref().c_str(); - key->opcode = KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT; - - change.push_back(*key); - } - } - - if(json_kbd.contains("swap")) - { - for(size_t i = 0; i < json_kbd["swap"].size(); i++) - { - keyboard_led* key = new keyboard_led; - - key->zone = json_kbd["swap"][i]["Zone"]; - key->row = json_kbd["swap"][i]["Row"]; - key->col = json_kbd["swap"][i]["Col"]; - key->value = json_kbd["swap"][i]["Val"]; - key->name = json_kbd["swap"][i]["Name"].get_ref().c_str(); - key->opcode = KEYBOARD_OPCODE_SWAP_ONLY; - - change.push_back(*key); - } - } - - new_kb.ChangeKeys(change); - - dummy_keyboard->name = new_kb.GetName(); - dummy_keyboard->type = DEVICE_TYPE_KEYBOARD; - dummy_keyboard->description = dummy_keyboard->name; - dummy_keyboard->description.append(" Debug Keyboard"); - dummy_keyboard->location = "Debug Keyboard Location"; - dummy_keyboard->version = "Debug Keyboard Version"; - dummy_keyboard->serial = "Debug Keyboard Serial"; - - /*---------------------------------------------------------*\ - | Create a direct mode for the dummy keyboard | - \*---------------------------------------------------------*/ - mode dummy_keyboard_direct_mode; - - dummy_keyboard_direct_mode.name = "Direct"; - dummy_keyboard_direct_mode.value = 0; - dummy_keyboard_direct_mode.flags = MODE_FLAG_HAS_PER_LED_COLOR; - dummy_keyboard_direct_mode.color_mode = MODE_COLORS_PER_LED; - - dummy_keyboard->modes.push_back(dummy_keyboard_direct_mode); - - /*---------------------------------------------------------*\ - | Create a matrix zone for the debug Keyboard | - \*---------------------------------------------------------*/ - zone dummy_keyboard_matrix_zone; - - dummy_keyboard_matrix_zone.name = "Keyboard Matrix Zone"; - dummy_keyboard_matrix_zone.type = ZONE_TYPE_MATRIX; - dummy_keyboard_matrix_zone.leds_min = new_kb.GetKeyCount(); - dummy_keyboard_matrix_zone.leds_max = new_kb.GetKeyCount(); - dummy_keyboard_matrix_zone.leds_count = new_kb.GetKeyCount(); - dummy_keyboard_matrix_zone.matrix_map = new matrix_map_type; - dummy_keyboard_matrix_zone.matrix_map->height = new_kb.GetRowCount(); - dummy_keyboard_matrix_zone.matrix_map->width = new_kb.GetColumnCount(); - dummy_keyboard_matrix_zone.matrix_map->map = new unsigned int[dummy_keyboard_matrix_zone.matrix_map->height - * dummy_keyboard_matrix_zone.matrix_map->width]; - new_kb.GetKeyMap(dummy_keyboard_matrix_zone.matrix_map->map, KEYBOARD_MAP_FILL_TYPE_COUNT); - - dummy_keyboard->zones.push_back(dummy_keyboard_matrix_zone); - - for(std::size_t led_idx = 0; led_idx < dummy_keyboard_matrix_zone.leds_count; led_idx++) - { - led dummy_keyboard_led; - dummy_keyboard_led.name = new_kb.GetKeyNameAt(led_idx); - dummy_keyboard->leds.push_back(dummy_keyboard_led); - } - - /*-----------------------------------------------------------------*\ - | Add another matrix zone so that is can resemble a huntsman elite | - \*-----------------------------------------------------------------*/ - bool underglow = true; - if(json_kbd.contains("underglow")) - { - underglow = json_kbd["underglow"]; - } - - if(underglow) - { - zone dummy_keyboard_underglow_matrix_zone; - - dummy_keyboard_underglow_matrix_zone.name = "Underglow"; - dummy_keyboard_underglow_matrix_zone.type = ZONE_TYPE_MATRIX; - dummy_keyboard_underglow_matrix_zone.leds_min = 30; - dummy_keyboard_underglow_matrix_zone.leds_max = 30; - dummy_keyboard_underglow_matrix_zone.leds_count = 30; - dummy_keyboard_underglow_matrix_zone.matrix_map = new matrix_map_type; - dummy_keyboard_underglow_matrix_zone.matrix_map->height = 3; - dummy_keyboard_underglow_matrix_zone.matrix_map->width = 10; - dummy_keyboard_underglow_matrix_zone.matrix_map->map = (unsigned int*)&dummy_keyboard_underglow_map; - - dummy_keyboard->zones.push_back(dummy_keyboard_underglow_matrix_zone); - - for(std::size_t led_idx = 0; led_idx < dummy_keyboard_underglow_matrix_zone.leds_count; led_idx++) - { - led dummy_keyboard_led; - dummy_keyboard_led.name = dummy_keyboard_underglow_matrix_zone.name + " LED "; - dummy_keyboard_led.name.append(std::to_string(led_idx)); - dummy_keyboard->leds.push_back(dummy_keyboard_led); - } - } - - /*---------------------------------------------------------*\ - | Create a linear zone for the dummy Keyboard | - \*---------------------------------------------------------*/ - bool linear = true; - if(json_kbd.contains("linear")) - { - linear = json_kbd["linear"]; - } - - if(linear) - { - zone dummy_keyboard_linear_zone; - - dummy_keyboard_linear_zone.name = "Linear Zone"; - dummy_keyboard_linear_zone.type = ZONE_TYPE_LINEAR; - dummy_keyboard_linear_zone.leds_min = 18; - dummy_keyboard_linear_zone.leds_max = 18; - dummy_keyboard_linear_zone.leds_count = 18; - dummy_keyboard_linear_zone.matrix_map = NULL; - - dummy_keyboard->zones.push_back(dummy_keyboard_linear_zone); - - for(std::size_t led_idx = 0; led_idx < dummy_keyboard_linear_zone.leds_count; led_idx++) - { - led dummy_keyboard_led; - dummy_keyboard_led.name = "RGB Strip "; - dummy_keyboard_led.name.append(std::to_string(led_idx)); - dummy_keyboard->leds.push_back(dummy_keyboard_led); - } - } - - dummy_keyboard->SetupColors(); - - /*---------------------------------------------------------*\ - | Push the dummy Keyboard onto the controller list | - \*---------------------------------------------------------*/ - ResourceManager::get()->RegisterRGBController(dummy_keyboard); - } - else if(type == "argb") - { - /*---------------------------------------------------------*\ - | Create a dummy ARGB | - \*---------------------------------------------------------*/ - RGBController_Debug* dummy_argb = new RGBController_Debug(); - - dummy_argb->name = "Debug ARGB"; - dummy_argb->type = DEVICE_TYPE_LEDSTRIP; - dummy_argb->description = "Debug ARGB Device"; - dummy_argb->location = "Debug ARGB Location"; - dummy_argb->version = "Debug ARGB Version"; - dummy_argb->serial = "Debug ARGB Serial"; - - /*---------------------------------------------------------*\ - | Create a direct mode for the dummy ARGB | - \*---------------------------------------------------------*/ - mode dummy_argb_direct_mode; - - dummy_argb_direct_mode.name = "Direct"; - dummy_argb_direct_mode.value = 0; - dummy_argb_direct_mode.flags = MODE_FLAG_HAS_PER_LED_COLOR; - dummy_argb_direct_mode.color_mode = MODE_COLORS_PER_LED; - - dummy_argb->modes.push_back(dummy_argb_direct_mode); - - /*---------------------------------------------------------*\ - | Create a linear zone for the dummy ARGB | - \*---------------------------------------------------------*/ - zone dummy_argb_linear_zone; - - dummy_argb_linear_zone.name = "Resizable zone"; - dummy_argb_linear_zone.type = ZONE_TYPE_LINEAR; - dummy_argb_linear_zone.leds_min = 1; - dummy_argb_linear_zone.leds_max = 100; - dummy_argb_linear_zone.leds_count = 0; - dummy_argb_linear_zone.matrix_map = NULL; - - dummy_argb->zones.push_back(dummy_argb_linear_zone); - - dummy_argb->SetupColors(); - dummy_argb->ResizeZone(0, 60); - - /*---------------------------------------------------------*\ - | Push the dummy ARGB onto the controller list | - \*---------------------------------------------------------*/ - ResourceManager::get()->RegisterRGBController(dummy_argb); - } + RGBController_Debug * debug_controller = new RGBController_Debug(false, debug_settings["devices"][device_idx]); + ResourceManager::get()->RegisterRGBController(debug_controller); } } if (debug_settings.contains("CustomDevices")) { - for (int CustomDevice = 0; CustomDevice < (int)debug_settings["CustomDevices"].size(); CustomDevice++) + for(unsigned int device_idx = 0; device_idx < debug_settings["CustomDevices"].size(); device_idx++) { - json CustomDev = debug_settings["CustomDevices"][CustomDevice]; - /*---------------------------*\ - | Create a custom controller | - \*---------------------------*/ - RGBController_Debug* dummy_custom = new RGBController_Debug(); + json custom_device_settings = debug_settings["CustomDevices"][device_idx]; - /*----------------------------------------------------------------------*\ - | if ANY of the attributes are missing then go ahead and skip the entry | - \*----------------------------------------------------------------------*/ - if ( - !CustomDev.contains("DeviceName") || - !CustomDev.contains("DeviceType") || - !CustomDev.contains("DeviceDescription") || - !CustomDev.contains("DeviceLocation") || - !CustomDev.contains("DeviceVersion") || - !CustomDev.contains("DeviceSerial") || - !CustomDev.contains("DeviceZones") - ) + /*---------------------------------------------*\ + | If ANY of the attributes are missing then go | + | ahead and skip the entry | + \*---------------------------------------------*/ + if( + !custom_device_settings.contains("DeviceName") || + !custom_device_settings.contains("DeviceType") || + !custom_device_settings.contains("DeviceDescription") || + !custom_device_settings.contains("DeviceLocation") || + !custom_device_settings.contains("DeviceVersion") || + !custom_device_settings.contains("DeviceSerial") || + !custom_device_settings.contains("DeviceZones") + ) { continue; } - - - /*-------------*\ - | Set the name | - \*-------------*/ - dummy_custom->name = CustomDev["DeviceName"]; - - /*---------------------*\ - | Find the device type | - \*---------------------*/ - if (CustomDev["DeviceType"] == "motherboard") dummy_custom->type = DEVICE_TYPE_MOTHERBOARD; - else if (CustomDev["DeviceType"] == "dram") dummy_custom->type = DEVICE_TYPE_DRAM; - else if (CustomDev["DeviceType"] == "gpu") dummy_custom->type = DEVICE_TYPE_GPU; - else if (CustomDev["DeviceType"] == "cooler") dummy_custom->type = DEVICE_TYPE_COOLER; - else if (CustomDev["DeviceType"] == "led_strip") dummy_custom->type = DEVICE_TYPE_LEDSTRIP; - else if (CustomDev["DeviceType"] == "keyboard") dummy_custom->type = DEVICE_TYPE_KEYBOARD; - else if (CustomDev["DeviceType"] == "mouse") dummy_custom->type = DEVICE_TYPE_MOUSE; - else if (CustomDev["DeviceType"] == "mousemat") dummy_custom->type = DEVICE_TYPE_MOUSEMAT; - else if (CustomDev["DeviceType"] == "headset") dummy_custom->type = DEVICE_TYPE_HEADSET; - else if (CustomDev["DeviceType"] == "headset_stand") dummy_custom->type = DEVICE_TYPE_HEADSET_STAND; - else if (CustomDev["DeviceType"] == "gamepad") dummy_custom->type = DEVICE_TYPE_GAMEPAD; - else if (CustomDev["DeviceType"] == "light") dummy_custom->type = DEVICE_TYPE_LIGHT; - else if (CustomDev["DeviceType"] == "speaker") dummy_custom->type = DEVICE_TYPE_SPEAKER; - else if (CustomDev["DeviceType"] == "unknown") dummy_custom->type = DEVICE_TYPE_UNKNOWN; - - /*-----------------------------------------------*\ - | Set description, location, version, and serial | - \*-----------------------------------------------*/ - dummy_custom->description = CustomDev["DeviceDescription"]; - dummy_custom->location = CustomDev["DeviceLocation"]; - dummy_custom->version = CustomDev["DeviceVersion"]; - dummy_custom->serial = CustomDev["DeviceSerial"]; - - /*----------------*\ - | Create the mode | - \*----------------*/ - mode dummy_custom_direct; - dummy_custom_direct.name = "Direct"; - dummy_custom_direct.value = 0; - dummy_custom_direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - dummy_custom_direct.color_mode = MODE_COLORS_PER_LED; - dummy_custom->modes.push_back(dummy_custom_direct); - - /*--------------*\ - | Fill in zones | - \*--------------*/ - for (int ZoneID = 0; ZoneID < (int)CustomDev["DeviceZones"].size(); ZoneID++) + else { - json ZoneJson = CustomDev["DeviceZones"][ZoneID]; - if - ( - !ZoneJson.contains("name") || - !ZoneJson.contains("type") || - !ZoneJson.contains("leds_min") || - !ZoneJson.contains("leds_max") || - !ZoneJson.contains("leds_count") - ) - { - continue; - } - zone custom_zone; - - custom_zone.name = ZoneJson["name"]; - - if (ZoneJson["type"] == "linear") custom_zone.type = ZONE_TYPE_LINEAR; - else if (ZoneJson["type"] == "matrix") custom_zone.type = ZONE_TYPE_MATRIX; - else if (ZoneJson["type"] == "single") custom_zone.type = ZONE_TYPE_SINGLE; - else - { - continue; - } - - custom_zone.leds_min = ZoneJson["leds_min"]; - custom_zone.leds_max = ZoneJson["leds_max"]; - custom_zone.leds_count = ZoneJson["leds_count"]; - - /*-----------------------*\ - | Fill in the matrix map | - \*-----------------------*/ - bool BadVal = false; - if (custom_zone.type == ZONE_TYPE_MATRIX) - { - if - ( - !ZoneJson.contains("matrix_height") || - !ZoneJson.contains("matrix_width") || - !ZoneJson.contains("matrix_map") - ) - { - /*--------------------------------------------------------------*\ - | If there is no map then the zone can't be valid. Don't add it | - \*--------------------------------------------------------------*/ - continue; - } - - custom_zone.matrix_map = new matrix_map_type; - - custom_zone.matrix_map->width = ZoneJson["matrix_width"]; - custom_zone.matrix_map->height = ZoneJson["matrix_height"]; - - int H = custom_zone.matrix_map->height; - int W = custom_zone.matrix_map->width; - - BadVal = (ZoneJson["matrix_map"].size() != custom_zone.matrix_map->height); - - unsigned int* MatrixARR = new unsigned int[H * W]; - for (int MatrixMapRow = 0; MatrixMapRow < H; MatrixMapRow++) - { - /*-----------------------------------------------------------------------------------------------------*\ - | If something went wrong then make no attempt to recover and just move on in a way that doesn't crash | - | Even 1 bad row can corrupt the map so skip the zone entirely | - \*-----------------------------------------------------------------------------------------------------*/ - if ((custom_zone.matrix_map->width != ZoneJson["matrix_map"][MatrixMapRow].size()) || BadVal) - { - BadVal = true; - break; - } - - for (int MatrixMapCol = 0; MatrixMapCol < W; MatrixMapCol++) - { - int Val = ZoneJson["matrix_map"][MatrixMapRow][MatrixMapCol]; - - if ((signed)Val == -1) - { - MatrixARR[MatrixMapRow * W + MatrixMapCol] = NA; - } - else - { - MatrixARR[MatrixMapRow * W + MatrixMapCol] = (unsigned)Val; - } - } - } - - custom_zone.matrix_map->map = MatrixARR; - } - - /*------------------------------------*\ - | Don't add the zone if it is invalid | - \*------------------------------------*/ - if (BadVal) - { - continue; - } - - bool UseCustomLabels = false; - if (ZoneJson.contains("custom_labels")) - { - /*-------------------------------------------------------*\ - | If the count is correct and the zone is non-resizeable | - \*-------------------------------------------------------*/ - if ((ZoneJson["custom_labels"].size() == custom_zone.leds_count) && (custom_zone.leds_min == custom_zone.leds_max)) - { - UseCustomLabels = true; - } - } - - /*------------------*\ - | Set the LED names | - \*------------------*/ - for (int LED_ID = 0; LED_ID < (int)custom_zone.leds_count; LED_ID++) - { - led custom_led; - if (UseCustomLabels) - { - /*----------------------------------------*\ - | Set the label to the user defined label | - \*----------------------------------------*/ - custom_led.name = ZoneJson["custom_labels"][LED_ID]; - } - else - { - /*------------------------------------------------*\ - | Set default labels because something went wrong | - \*------------------------------------------------*/ - custom_led.name = ("Custom LED. Zone " + std::to_string(ZoneID) + ", LED " + std::to_string(LED_ID)); - } - dummy_custom->leds.push_back(custom_led); - } - - dummy_custom->zones.push_back(custom_zone); + RGBController_Debug * debug_controller = new RGBController_Debug(true, custom_device_settings); + ResourceManager::get()->RegisterRGBController(debug_controller); } - - dummy_custom->SetupColors(); - - ResourceManager::get()->RegisterRGBController(dummy_custom); } } diff --git a/Controllers/DebugController/RGBController_Debug.cpp b/Controllers/DebugController/RGBController_Debug.cpp index b783dca8..65c3abe9 100644 --- a/Controllers/DebugController/RGBController_Debug.cpp +++ b/Controllers/DebugController/RGBController_Debug.cpp @@ -1,7 +1,19 @@ -#include "RGBController_Debug.h" +/*---------------------------------------------------------*\ +| RGBController_Debug.cpp | +| | +| Debug RGBController that can mimic various devices for | +| development and test purposes | +| | +| Adam Honse (CalcProgrammer1) 31 Jul 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include #include +#include "KeyboardLayoutManager.h" +#include "RGBController_Debug.h" /**------------------------------------------------------------------*\ @name Debug @@ -14,7 +26,548 @@ @comment \*-------------------------------------------------------------------*/ -RGBController_Debug::RGBController_Debug() +//0xFFFFFFFF indicates an unused entry in matrix +#define NA 0xFFFFFFFF + +#define NUM_LAYOUTS 6 + +static const std::string layout_names[] = +{ + "Default", + "ANSI QWERTY", + "ISO QWERTY", + "ISO QWERTZ", + "ISO AZERTY", + "JIS" +}; + +static unsigned int debug_keyboard_underglow_map[3][10] = + { { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, + { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }, + { 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 } }; + +RGBController_Debug::RGBController_Debug(bool custom_controller, json debug_settings) +{ + if(custom_controller) + { + /*-------------------------------------------------*\ + | Set the name | + \*-------------------------------------------------*/ + name = debug_settings["DeviceName"]; + + /*-------------------------------------------------*\ + | Find the device type | + \*-------------------------------------------------*/ + if (debug_settings["DeviceType"] == "motherboard") type = DEVICE_TYPE_MOTHERBOARD; + else if (debug_settings["DeviceType"] == "dram") type = DEVICE_TYPE_DRAM; + else if (debug_settings["DeviceType"] == "gpu") type = DEVICE_TYPE_GPU; + else if (debug_settings["DeviceType"] == "cooler") type = DEVICE_TYPE_COOLER; + else if (debug_settings["DeviceType"] == "led_strip") type = DEVICE_TYPE_LEDSTRIP; + else if (debug_settings["DeviceType"] == "keyboard") type = DEVICE_TYPE_KEYBOARD; + else if (debug_settings["DeviceType"] == "mouse") type = DEVICE_TYPE_MOUSE; + else if (debug_settings["DeviceType"] == "mousemat") type = DEVICE_TYPE_MOUSEMAT; + else if (debug_settings["DeviceType"] == "headset") type = DEVICE_TYPE_HEADSET; + else if (debug_settings["DeviceType"] == "headset_stand") type = DEVICE_TYPE_HEADSET_STAND; + else if (debug_settings["DeviceType"] == "gamepad") type = DEVICE_TYPE_GAMEPAD; + else if (debug_settings["DeviceType"] == "light") type = DEVICE_TYPE_LIGHT; + else if (debug_settings["DeviceType"] == "speaker") type = DEVICE_TYPE_SPEAKER; + else if (debug_settings["DeviceType"] == "unknown") type = DEVICE_TYPE_UNKNOWN; + + /*-------------------------------------------------*\ + | Set description, location, version, and serial | + \*-------------------------------------------------*/ + description = debug_settings["DeviceDescription"]; + location = debug_settings["DeviceLocation"]; + version = debug_settings["DeviceVersion"]; + serial = debug_settings["DeviceSerial"]; + + /*-------------------------------------------------*\ + | Create the mode | + \*-------------------------------------------------*/ + 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); + + /*-------------------------------------------------*\ + | Fill in zones | + \*-------------------------------------------------*/ + for(int ZoneID = 0; ZoneID < (int)debug_settings["DeviceZones"].size(); ZoneID++) + { + json ZoneJson = debug_settings["DeviceZones"][ZoneID]; + + if + ( + !ZoneJson.contains("name") || + !ZoneJson.contains("type") || + !ZoneJson.contains("leds_min") || + !ZoneJson.contains("leds_max") || + !ZoneJson.contains("leds_count") + ) + { + continue; + } + zone custom_zone; + + custom_zone.name = ZoneJson["name"]; + + if (ZoneJson["type"] == "linear") custom_zone.type = ZONE_TYPE_LINEAR; + else if (ZoneJson["type"] == "matrix") custom_zone.type = ZONE_TYPE_MATRIX; + else if (ZoneJson["type"] == "single") custom_zone.type = ZONE_TYPE_SINGLE; + else + { + continue; + } + + custom_zone.leds_min = ZoneJson["leds_min"]; + custom_zone.leds_max = ZoneJson["leds_max"]; + custom_zone.leds_count = ZoneJson["leds_count"]; + + /*---------------------------------------------*\ + | Fill in the matrix map | + \*---------------------------------------------*/ + bool BadVal = false; + + if(custom_zone.type == ZONE_TYPE_MATRIX) + { + if + ( + !ZoneJson.contains("matrix_height") || + !ZoneJson.contains("matrix_width") || + !ZoneJson.contains("matrix_map") + ) + { + /*-------------------------------------*\ + | If there is no map then the zone | + | can't be valid. Don't add it | + \*-------------------------------------*/ + continue; + } + + custom_zone.matrix_map = new matrix_map_type; + + custom_zone.matrix_map->width = ZoneJson["matrix_width"]; + custom_zone.matrix_map->height = ZoneJson["matrix_height"]; + + int H = custom_zone.matrix_map->height; + int W = custom_zone.matrix_map->width; + + BadVal = (ZoneJson["matrix_map"].size() != custom_zone.matrix_map->height); + + unsigned int* MatrixARR = new unsigned int[H * W]; + + for(int MatrixMapRow = 0; MatrixMapRow < H; MatrixMapRow++) + { + /*-------------------------------------*\ + | If something went wrong then make no | + | attempt to recover and just move on | + | in a way that doesn't crash. Even 1 | + | bad row can corrupt the map so skip | + | the zone entirely | + \*-------------------------------------*/ + if((custom_zone.matrix_map->width != ZoneJson["matrix_map"][MatrixMapRow].size()) || BadVal) + { + BadVal = true; + break; + } + + for(int MatrixMapCol = 0; MatrixMapCol < W; MatrixMapCol++) + { + int Val = ZoneJson["matrix_map"][MatrixMapRow][MatrixMapCol]; + + if((signed)Val == -1) + { + MatrixARR[MatrixMapRow * W + MatrixMapCol] = NA; + } + else + { + MatrixARR[MatrixMapRow * W + MatrixMapCol] = (unsigned)Val; + } + } + } + + custom_zone.matrix_map->map = MatrixARR; + } + + /*---------------------------------------------*\ + | Don't add the zone if it is invalid | + \*---------------------------------------------*/ + if(BadVal) + { + continue; + } + + bool UseCustomLabels = false; + if(ZoneJson.contains("custom_labels")) + { + /*-----------------------------------------*\ + | If the count is correct and the zone is | + | non-resizeable | + \*-----------------------------------------*/ + if((ZoneJson["custom_labels"].size() == custom_zone.leds_count) && (custom_zone.leds_min == custom_zone.leds_max)) + { + UseCustomLabels = true; + } + } + + /*---------------------------------------------*\ + | Set the LED names | + \*---------------------------------------------*/ + for(int LED_ID = 0; LED_ID < (int)custom_zone.leds_count; LED_ID++) + { + led custom_led; + if(UseCustomLabels) + { + /*-------------------------------------*\ + | Set the label to the user defined | + | label | + \*-------------------------------------*/ + custom_led.name = ZoneJson["custom_labels"][LED_ID]; + } + else + { + /*-------------------------------------*\ + | Set default labels because something | + | went wrong | + \*-------------------------------------*/ + custom_led.name = ("Custom LED. Zone " + std::to_string(ZoneID) + ", LED " + std::to_string(LED_ID)); + } + + leds.push_back(custom_led); + } + + zones.push_back(custom_zone); + } + + SetupColors(); + } + else + { + bool zone_single = true; + bool zone_linear = true; + bool zone_resizable = false; + bool zone_keyboard = false; + bool zone_underglow = false; + std::string name_setting = ""; + std::string type_setting = "keyboard"; + + if(debug_settings.contains("name")) + { + name_setting = debug_settings["name"]; + } + + if(debug_settings.contains("type")) + { + type_setting = debug_settings["type"]; + } + + if(debug_settings.contains("single")) + { + zone_single = debug_settings["single"]; + } + + if(debug_settings.contains("linear")) + { + zone_linear = debug_settings["linear"]; + } + + if(debug_settings.contains("resizable")) + { + zone_resizable = debug_settings["resizable"]; + } + + if(debug_settings.contains("keyboard")) + { + zone_keyboard = debug_settings["keyboard"]; + } + + if(debug_settings.contains("underglow")) + { + zone_underglow = debug_settings["underglow"]; + } + + if(type_setting == "motherboard") + { + name = "Debug Motherboard"; + type = DEVICE_TYPE_MOTHERBOARD; + } + else if(type_setting == "dram") + { + name = "Debug DRAM"; + type = DEVICE_TYPE_DRAM; + } + else if(type_setting == "gpu") + { + name = "Debug GPU"; + type = DEVICE_TYPE_GPU; + } + else if(type_setting == "keyboard") + { + name = "Debug Keyboard"; + type = DEVICE_TYPE_KEYBOARD; + } + else if(type_setting == "mouse") + { + name = "Debug Mouse"; + type = DEVICE_TYPE_MOUSE; + } + else if(type_setting == "argb") + { + name = "Debug ARGB Controller"; + type = DEVICE_TYPE_LEDSTRIP; + } + + /*---------------------------------------------------------*\ + | Fill in debug controller information | + \*---------------------------------------------------------*/ + description = name + " Device"; + vendor = name + " Vendor String"; + location = name + " Location String"; + version = name + " Version String"; + serial = name + " Serial String"; + + if(name_setting != "") + { + name = name_setting; + } + + /*---------------------------------------------------------*\ + | Create a direct mode | + \*---------------------------------------------------------*/ + 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); + + /*---------------------------------------------------------*\ + | Create a single zone/LED | + \*---------------------------------------------------------*/ + if(zone_single) + { + zone single_zone; + + single_zone.name = "Single Zone"; + single_zone.type = ZONE_TYPE_SINGLE; + single_zone.leds_min = 1; + single_zone.leds_max = 1; + single_zone.leds_count = 1; + single_zone.matrix_map = NULL; + + zones.push_back(single_zone); + + led single_led; + + single_led.name = "Single LED"; + + leds.push_back(single_led); + + led_alt_names.push_back(""); + } + + /*---------------------------------------------------------*\ + | Create a linear zone | + \*---------------------------------------------------------*/ + if(zone_linear) + { + zone linear_zone; + + linear_zone.name = "Linear Zone"; + linear_zone.type = ZONE_TYPE_LINEAR; + linear_zone.leds_min = 10; + linear_zone.leds_max = 10; + linear_zone.leds_count = 10; + linear_zone.matrix_map = NULL; + + zones.push_back(linear_zone); + + for(std::size_t led_idx = 0; led_idx < 10; led_idx++) + { + led linear_led; + + linear_led.name = "Linear LED " + std::to_string(led_idx); + + leds.push_back(linear_led); + + led_alt_names.push_back(""); + } + } + /*---------------------------------------------------------*\ + | Create a keyboard matrix zone | + \*---------------------------------------------------------*/ + if(zone_keyboard) + { + KEYBOARD_LAYOUT layout = KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_ANSI_QWERTY; + KEYBOARD_SIZE size = KEYBOARD_SIZE::KEYBOARD_SIZE_FULL; + + if(debug_settings.contains("layout")) + { + KEYBOARD_LAYOUT temp_layout = debug_settings["layout"]; + + if(temp_layout < NUM_LAYOUTS) + { + layout = temp_layout; + } + } + + if(debug_settings.contains("size")) + { + size = debug_settings["size"]; + } + + KeyboardLayoutManager new_kb(layout, size); + + description += ", Layout: " + layout_names[layout] + ", Size: " + new_kb.GetName(); + + /*-----------------------------------------------------*\ + | Check for custom key inserts and swaps | + \*-----------------------------------------------------*/ + const char* change_keys = "change_keys"; + + if(debug_settings.contains(change_keys)) + { + std::vector change; + + const char* ins_row = "ins_row"; + const char* rmv_key = "rmv_key"; + const char* rmv_row = "rmv_row"; + const char* swp_key = "swp_key"; + + const char* dbg_zone = "Zone"; + const char* dbg_row = "Row"; + const char* dbg_col = "Col"; + const char* dbg_val = "Val"; + const char* dbg_name = "Name"; + const char* dbg_opcode = "Opcode"; + + for(size_t i = 0; i < debug_settings[change_keys].size(); i++) + { + keyboard_led* key = new keyboard_led; + + key->zone = debug_settings[change_keys][i][dbg_zone]; + key->row = debug_settings[change_keys][i][dbg_row]; + key->col = debug_settings[change_keys][i][dbg_col]; + key->value = debug_settings[change_keys][i][dbg_val]; + key->name = debug_settings[change_keys][i][dbg_name].get_ref().c_str(); + + if(debug_settings[change_keys][i][dbg_opcode] == ins_row) + { + key->opcode = KEYBOARD_OPCODE_INSERT_ROW; + } + else if(debug_settings[change_keys][i][dbg_opcode] == rmv_key) + { + key->opcode = KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT; + } + else if(debug_settings[change_keys][i][dbg_opcode] == rmv_row) + { + key->opcode = KEYBOARD_OPCODE_REMOVE_ROW; + } + else if(debug_settings[change_keys][i][dbg_opcode] == swp_key) + { + key->opcode = KEYBOARD_OPCODE_SWAP_ONLY; + } + else + { + key->opcode = KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT; + } + + change.push_back(*key); + } + + new_kb.ChangeKeys(change); + } + + zone keyboard_zone; + + keyboard_zone.name = "Keyboard Zone"; + keyboard_zone.type = ZONE_TYPE_MATRIX; + keyboard_zone.leds_min = new_kb.GetKeyCount(); + keyboard_zone.leds_max = new_kb.GetKeyCount(); + keyboard_zone.leds_count = new_kb.GetKeyCount(); + keyboard_zone.matrix_map = new matrix_map_type; + keyboard_zone.matrix_map->height = new_kb.GetRowCount(); + keyboard_zone.matrix_map->width = new_kb.GetColumnCount(); + keyboard_zone.matrix_map->map = new unsigned int[keyboard_zone.matrix_map->height * keyboard_zone.matrix_map->width]; + + new_kb.GetKeyMap(keyboard_zone.matrix_map->map, KEYBOARD_MAP_FILL_TYPE_COUNT); + + zones.push_back(keyboard_zone); + + for(unsigned int led_idx = 0; led_idx < keyboard_zone.leds_count; led_idx++) + { + led keyboard_led; + + keyboard_led.name = new_kb.GetKeyNameAt(led_idx); + + leds.push_back(keyboard_led); + + led_alt_names.push_back(new_kb.GetKeyAltNameAt(led_idx)); + } + } + /*---------------------------------------------------------*\ + | Create an underglow matrix zone | + \*---------------------------------------------------------*/ + if(zone_underglow) + { + zone underglow_zone; + + underglow_zone.name = "Underglow Zone"; + underglow_zone.type = ZONE_TYPE_MATRIX; + underglow_zone.leds_min = 30; + underglow_zone.leds_max = 30; + underglow_zone.leds_count = 30; + underglow_zone.matrix_map = new matrix_map_type; + underglow_zone.matrix_map->height = 3; + underglow_zone.matrix_map->width = 10; + underglow_zone.matrix_map->map = (unsigned int*)&debug_keyboard_underglow_map; + + zones.push_back(underglow_zone); + + for(std::size_t led_idx = 0; led_idx < underglow_zone.leds_count; led_idx++) + { + led underglow_led; + + underglow_led.name = "Underglow LED " + std::to_string(led_idx);; + + leds.push_back(underglow_led); + + led_alt_names.push_back(""); + } + } + /*---------------------------------------------------------*\ + | Create a resizable linear zone | + \*---------------------------------------------------------*/ + if(zone_resizable) + { + zone resizable_zone; + + resizable_zone.name = "Resizable Zone"; + resizable_zone.type = ZONE_TYPE_LINEAR; + resizable_zone.leds_min = 0; + resizable_zone.leds_max = 100; + resizable_zone.leds_count = 0; + resizable_zone.matrix_map = NULL; + + zones.push_back(resizable_zone); + } + } + + SetupColors(); +} + +RGBController_Debug::~RGBController_Debug() +{ + +} + +void RGBController_Debug::SetupZones() { } @@ -58,3 +611,23 @@ void RGBController_Debug::ResizeZone(int index, int new_size) SetupColors(); } + +void RGBController_Debug::DeviceUpdateLEDs() +{ + +} + +void RGBController_Debug::UpdateZoneLEDs(int /*zone*/) +{ + +} + +void RGBController_Debug::UpdateSingleLED(int /*led*/) +{ + +} + +void RGBController_Debug::DeviceUpdateMode() +{ + +} diff --git a/Controllers/DebugController/RGBController_Debug.h b/Controllers/DebugController/RGBController_Debug.h index 2f6c2c78..db01efe7 100644 --- a/Controllers/DebugController/RGBController_Debug.h +++ b/Controllers/DebugController/RGBController_Debug.h @@ -1,15 +1,35 @@ -#ifndef RGBCONTROLLER_DEBUG_H -#define RGBCONTROLLER_DEBUG_H +/*---------------------------------------------------------*\ +| RGBController_Debug.h | +| | +| Debug RGBController that can mimic various devices for | +| development and test purposes | +| | +| Adam Honse (CalcProgrammer1) 31 Jul 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_Dummy.h" +#pragma once -// A variation of Dummy controller that allows the zones to be resized +#include +#include "RGBController.h" -class RGBController_Debug : public RGBController_Dummy +using json = nlohmann::json; + +class RGBController_Debug : public RGBController { public: - RGBController_Debug(); - void ResizeZone(int zone, int newSize) override; -}; + RGBController_Debug(bool custom_controller, json debug_settings); + ~RGBController_Debug(); -#endif // RGBCONTROLLER_DEBUG_H + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); +}; diff --git a/Controllers/DreamCheekyController/DreamCheekyController.cpp b/Controllers/DreamCheekyController/DreamCheekyController.cpp new file mode 100644 index 00000000..c7dea61c --- /dev/null +++ b/Controllers/DreamCheekyController/DreamCheekyController.cpp @@ -0,0 +1,89 @@ +/*---------------------------------------------------------*\ +| DreamCheekyController.cpp | +| | +| Driver for Dream Cheeky devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 06 Sep 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "DreamCheekyController.h" +#include "StringUtils.h" + +DreamCheekyController::DreamCheekyController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + + /*-----------------------------------------------------*\ + | The Dream Cheeky Webmail Notifier requires four | + | initialization packets before sending colors. | + \*-----------------------------------------------------*/ + const unsigned char init_0[9] = { 0x00, 0x1F, 0x02, 0x00, 0x5F, 0x00, 0x00, 0x1F, 0x03 }; + const unsigned char init_1[9] = { 0x00, 0x00, 0x02, 0x00, 0x5F, 0x00, 0x00, 0x1F, 0x04 }; + const unsigned char init_2[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x05 }; + const unsigned char init_3[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; + + hid_write(dev, init_0, sizeof(init_0)); + hid_write(dev, init_1, sizeof(init_1)); + hid_write(dev, init_2, sizeof(init_2)); + hid_write(dev, init_3, sizeof(init_3)); +} + +DreamCheekyController::~DreamCheekyController() +{ + hid_close(dev); +} + +std::string DreamCheekyController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string DreamCheekyController::GetNameString() +{ + return(name); +} + +std::string DreamCheekyController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void DreamCheekyController::SetColor(unsigned char red, unsigned char grn, unsigned char blu) +{ + unsigned char usb_buf[9]; + + memset(usb_buf, 0, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | The Dream Cheeky Webmail Notifier color values range | + | from 0-64, so we scale the 0-255 input range down by | + | right shifting by 2 to get the range 0-63. Add 1 if | + | the value is exactly 255 because otherwise the maximum| + | value of 64 would never be reached. | + \*-----------------------------------------------------*/ + usb_buf[0] = 0x00; + usb_buf[1] = (red >> 2) + (red == 255); + usb_buf[2] = (grn >> 2) + (grn == 255); + usb_buf[3] = (blu >> 2) + (blu == 255); + usb_buf[4] = 0x00; + usb_buf[5] = 0x00; + usb_buf[6] = 0x00; + usb_buf[7] = 0x1F; + usb_buf[8] = 0x05; + + hid_write(dev, usb_buf, sizeof(usb_buf)); +} diff --git a/Controllers/DreamCheekyController/DreamCheekyController.h b/Controllers/DreamCheekyController/DreamCheekyController.h new file mode 100644 index 00000000..840da757 --- /dev/null +++ b/Controllers/DreamCheekyController/DreamCheekyController.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------*\ +| DreamCheekyController.h | +| | +| Driver for Dream Cheeky devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 06 Sep 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include + +class DreamCheekyController +{ +public: + DreamCheekyController(hid_device* dev_handle, const char* path, std::string dev_name); + ~DreamCheekyController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SetColor(unsigned char red, unsigned char grn, unsigned char blu); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/DreamCheekyController/DreamCheekyControllerDetect.cpp b/Controllers/DreamCheekyController/DreamCheekyControllerDetect.cpp new file mode 100644 index 00000000..71f175e1 --- /dev/null +++ b/Controllers/DreamCheekyController/DreamCheekyControllerDetect.cpp @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| DreamCheekyControllerDetect.cpp | +| | +| Detector for Dream Cheeky devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 06 Sep 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "DreamCheekyController.h" +#include "RGBController_DreamCheeky.h" + +/*---------------------------------------------------------*\ +| Dream Cheeky USB Vendor ID | +\*---------------------------------------------------------*/ +#define DREAM_CHEEKY_VID 0x1D34 + +/*---------------------------------------------------------*\ +| Dream Cheeky USB Product ID | +\*---------------------------------------------------------*/ +#define DREAM_CHEEKY_WEBMAIL_NOTIFIER_PID 0x0004 + +void DetectDreamCheekyControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + DreamCheekyController* controller = new DreamCheekyController(dev, info->path, name); + RGBController_DreamCheeky* rgb_controller = new RGBController_DreamCheeky(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR( "Dream Cheeky Webmail Notifier", DetectDreamCheekyControllers, DREAM_CHEEKY_VID, DREAM_CHEEKY_WEBMAIL_NOTIFIER_PID ); diff --git a/Controllers/DreamCheekyController/RGBController_DreamCheeky.cpp b/Controllers/DreamCheekyController/RGBController_DreamCheeky.cpp new file mode 100644 index 00000000..cdb86fb7 --- /dev/null +++ b/Controllers/DreamCheekyController/RGBController_DreamCheeky.cpp @@ -0,0 +1,94 @@ +/*---------------------------------------------------------*\ +| RGBController_DreamCheeky.cpp | +| | +| RGBController for Dream Cheeky devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 06 Sep 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_DreamCheeky.h" + +RGBController_DreamCheeky::RGBController_DreamCheeky(DreamCheekyController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + type = DEVICE_TYPE_ACCESSORY; + vendor = "Dream Cheeky"; + description = "Dream Cheeky Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + 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(); +} + +RGBController_DreamCheeky::~RGBController_DreamCheeky() +{ + +} + +void RGBController_DreamCheeky::SetupZones() +{ + zone mail_zone; + mail_zone.name = "LED"; + mail_zone.type = ZONE_TYPE_SINGLE; + mail_zone.leds_min = 1; + mail_zone.leds_max = 1; + mail_zone.leds_count = 1; + mail_zone.matrix_map = NULL; + zones.push_back(mail_zone); + + led mail_led; + mail_led.name = "LED"; + leds.push_back(mail_led); + + SetupColors(); +} + +void RGBController_DreamCheeky::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*-----------------------------------------------------*\ + | This device does not support resizing zones | + \*-----------------------------------------------------*/ +} + +void RGBController_DreamCheeky::DeviceUpdateLEDs() +{ + unsigned char red = RGBGetRValue(colors[0]); + unsigned char grn = RGBGetGValue(colors[0]); + unsigned char blu = RGBGetBValue(colors[0]); + + controller->SetColor(red, grn, blu); +} + +void RGBController_DreamCheeky::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_DreamCheeky::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_DreamCheeky::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} + +void RGBController_DreamCheeky::DeviceSaveMode() +{ + /*-----------------------------------------------------*\ + | This device does not support saving | + \*-----------------------------------------------------*/ +} diff --git a/Controllers/DreamCheekyController/RGBController_DreamCheeky.h b/Controllers/DreamCheekyController/RGBController_DreamCheeky.h new file mode 100644 index 00000000..657ce2ce --- /dev/null +++ b/Controllers/DreamCheekyController/RGBController_DreamCheeky.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_DreamCheeky.h | +| | +| RGBController for Dream Cheeky devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 06 Sep 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "DreamCheekyController.h" +#include "RGBController.h" + +class RGBController_DreamCheeky : public RGBController +{ +public: + RGBController_DreamCheeky(DreamCheekyController* controller_ptr); + ~RGBController_DreamCheeky(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + DreamCheekyController* controller; +}; diff --git a/Controllers/DuckyKeyboardController/DuckyKeyboardController.cpp b/Controllers/DuckyKeyboardController/DuckyKeyboardController.cpp index 0d23eab3..5ef8d87b 100644 --- a/Controllers/DuckyKeyboardController/DuckyKeyboardController.cpp +++ b/Controllers/DuckyKeyboardController/DuckyKeyboardController.cpp @@ -1,19 +1,23 @@ -/*-----------------------------------------*\ -| DuckyKeyboardController.cpp | -| | -| Driver for Ducky RGB keyboardlighting | -| controller | -| | -| Adam Honse (CalcProgrammer1) 7/4/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| DuckyKeyboardController.cpp | +| | +| Driver for Ducky keyboard | +| | +| Adam Honse (CalcProgrammer1) 04 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include #include "DuckyKeyboardController.h" +#include "StringUtils.h" -DuckyKeyboardController::DuckyKeyboardController(hid_device* dev_handle, const char* path, const unsigned short pid) +DuckyKeyboardController::DuckyKeyboardController(hid_device* dev_handle, const char* path, const unsigned short pid, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; usb_pid = pid; SendInitialize(); @@ -24,11 +28,16 @@ DuckyKeyboardController::~DuckyKeyboardController() hid_close(dev); } -std::string DuckyKeyboardController::GetDeviceLocation() +std::string DuckyKeyboardController::GetLocationString() { return("HID: " + location); } +std::string DuckyKeyboardController::GetNameString() +{ + return(name); +} + std::string DuckyKeyboardController::GetSerialString() { wchar_t serial_string[128]; @@ -39,10 +48,7 @@ std::string DuckyKeyboardController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } unsigned short DuckyKeyboardController::GetUSBPID() @@ -74,7 +80,7 @@ void DuckyKeyboardController::SendColors void DuckyKeyboardController::SendInitialize() { - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -91,13 +97,13 @@ void DuckyKeyboardController::SendInitialize() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, 65); + hid_write(dev, usb_buf, 65); std::this_thread::sleep_for(std::chrono::milliseconds(2)); } void DuckyKeyboardController::SendInitializeColorPacket() { - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -120,7 +126,7 @@ void DuckyKeyboardController::SendInitializeColorPacket() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, 65); + hid_write(dev, usb_buf, 65); std::this_thread::sleep_for(std::chrono::milliseconds(2)); } @@ -132,7 +138,7 @@ unsigned int DuckyKeyboardController::SendColorDataPacket ) { unsigned int bytes_sent; - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -188,7 +194,7 @@ unsigned int DuckyKeyboardController::SendColorDataPacket /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, 65); + hid_write(dev, usb_buf, 65); std::this_thread::sleep_for(std::chrono::milliseconds(2)); return(bytes_sent); @@ -196,7 +202,7 @@ unsigned int DuckyKeyboardController::SendColorDataPacket void DuckyKeyboardController::SendTerminateColorPacket() { - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -214,6 +220,6 @@ void DuckyKeyboardController::SendTerminateColorPacket() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, 65); + hid_write(dev, usb_buf, 65); std::this_thread::sleep_for(std::chrono::milliseconds(2)); } diff --git a/Controllers/DuckyKeyboardController/DuckyKeyboardController.h b/Controllers/DuckyKeyboardController/DuckyKeyboardController.h index db9f8dda..f6e34e22 100644 --- a/Controllers/DuckyKeyboardController/DuckyKeyboardController.h +++ b/Controllers/DuckyKeyboardController/DuckyKeyboardController.h @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| DuckyKeyboardController.h | -| | -| Definitions and types for Ducky RGB | -| keyboard lighting controller | -| | -| Adam Honse (CalcProgrammer1) 7/4/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| DuckyKeyboardController.h | +| | +| Driver for Ducky keyboard | +| | +| Adam Honse (CalcProgrammer1) 04 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + /*-----------------------------------------------------*\ | Ducky vendor ID | \*-----------------------------------------------------*/ @@ -28,13 +29,14 @@ class DuckyKeyboardController { public: - DuckyKeyboardController(hid_device* dev_handle, const char* path, const unsigned short pid); + DuckyKeyboardController(hid_device* dev_handle, const char* path, const unsigned short pid, std::string dev_name); ~DuckyKeyboardController(); - std::string GetDeviceLocation(); + std::string GetLocationString(); + std::string GetNameString(); std::string GetSerialString(); unsigned short GetUSBPID(); - + void SendColors ( unsigned char* color_data, @@ -44,6 +46,7 @@ public: private: hid_device* dev; std::string location; + std::string name; unsigned short usb_pid; void SendInitialize(); diff --git a/Controllers/DuckyKeyboardController/DuckyKeyboardControllerDetect.cpp b/Controllers/DuckyKeyboardController/DuckyKeyboardControllerDetect.cpp index b4aa999e..bd82478e 100644 --- a/Controllers/DuckyKeyboardController/DuckyKeyboardControllerDetect.cpp +++ b/Controllers/DuckyKeyboardController/DuckyKeyboardControllerDetect.cpp @@ -1,8 +1,18 @@ +/*---------------------------------------------------------*\ +| DuckyKeyboardControllerDetect.cpp | +| | +| Detector for Ducky keyboard | +| | +| Adam Honse (CalcProgrammer1) 04 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "DuckyKeyboardController.h" -#include "RGBController.h" #include "RGBController_DuckyKeyboard.h" -#include +#include /******************************************************************************************\ * * @@ -18,9 +28,9 @@ void DetectDuckyKeyboardControllers(hid_device_info* info, const std::string& na if(dev) { - DuckyKeyboardController* controller = new DuckyKeyboardController(dev, info->path, info->product_id); + DuckyKeyboardController* controller = new DuckyKeyboardController(dev, info->path, info->product_id, name); RGBController_DuckyKeyboard* rgb_controller = new RGBController_DuckyKeyboard(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } /* DetectDuckyKeyboardControllers() */ diff --git a/Controllers/DuckyKeyboardController/RGBController_DuckyKeyboard.cpp b/Controllers/DuckyKeyboardController/RGBController_DuckyKeyboard.cpp index d3ede854..624f6511 100644 --- a/Controllers/DuckyKeyboardController/RGBController_DuckyKeyboard.cpp +++ b/Controllers/DuckyKeyboardController/RGBController_DuckyKeyboard.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_DuckyKeyboard.cpp | -| | -| Generic RGB Interface for Ducky RGB | -| keyboard devices | -| | -| Adam Honse (CalcProgrammer1) 7/4/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_DuckyKeyboard.cpp | +| | +| RGBController for Ducky keyboard | +| | +| Adam Honse (CalcProgrammer1) 04 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_DuckyKeyboard.h" @@ -201,11 +203,11 @@ RGBController_DuckyKeyboard::RGBController_DuckyKeyboard(DuckyKeyboardController { controller = controller_ptr; - name = "Ducky Keyboard Device"; + name = controller->GetNameString(); vendor = "Ducky"; type = DEVICE_TYPE_KEYBOARD; description = "Ducky Keyboard Device"; - location = controller->GetDeviceLocation(); + location = controller->GetLocationString(); serial = controller->GetSerialString(); mode Direct; diff --git a/Controllers/DuckyKeyboardController/RGBController_DuckyKeyboard.h b/Controllers/DuckyKeyboardController/RGBController_DuckyKeyboard.h index 47f58c80..fefc376b 100644 --- a/Controllers/DuckyKeyboardController/RGBController_DuckyKeyboard.h +++ b/Controllers/DuckyKeyboardController/RGBController_DuckyKeyboard.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_DuckyKeyboard.h | -| | -| Generic RGB Interface for Ducky RGB | -| keyboard devices | -| | -| Adam Honse (CalcProgrammer1) 7/4/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_DuckyKeyboard.h | +| | +| RGBController for Ducky keyboard | +| | +| Adam Honse (CalcProgrammer1) 04 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "DuckyKeyboardController.h" @@ -20,7 +23,7 @@ public: void SetupZones(); void ResizeZone(int zone, int new_size); - + void DeviceUpdateLEDs(); void UpdateZoneLEDs(int zone); void UpdateSingleLED(int led); @@ -29,4 +32,4 @@ public: private: DuckyKeyboardController* controller; -}; \ No newline at end of file +}; diff --git a/Controllers/DygmaRaiseController/DygmaRaiseController.cpp b/Controllers/DygmaRaiseController/DygmaRaiseController.cpp index 38292801..46a2a9b5 100644 --- a/Controllers/DygmaRaiseController/DygmaRaiseController.cpp +++ b/Controllers/DygmaRaiseController/DygmaRaiseController.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| DygmaRaiseController.cpp | -| | -| Driver for Dygma Raise keyboard | -| | -| Timo Schlegel (@eispalast) 12/12/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| DygmaRaiseController.cpp | +| | +| Driver for Dygma Raise keyboard | +| | +| Timo Schlegel (@eispalast) Dec 12 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "DygmaRaiseController.h" @@ -27,13 +30,13 @@ static int val_char_len(int number) } } -DygmaRaiseController::DygmaRaiseController() +DygmaRaiseController::DygmaRaiseController() { - + } -DygmaRaiseController::~DygmaRaiseController() -{ +DygmaRaiseController::~DygmaRaiseController() +{ serialport->serial_close(); delete serialport; } @@ -41,17 +44,17 @@ DygmaRaiseController::~DygmaRaiseController() void DygmaRaiseController::Initialize(char* port) { port_name = port; - + serialport = new serial_port(port_name.c_str(), DYGMA_RAISE_BAUD); } -std::string DygmaRaiseController::GetDeviceLocation() +std::string DygmaRaiseController::GetDeviceLocation() { return("COM: " + port_name); } void DygmaRaiseController::SendDirect(std::vectorcolors, size_t led_num) -{ +{ char serial_buf[MAX_LEN]; /*-----------------------------------------------------*\ @@ -76,7 +79,7 @@ void DygmaRaiseController::SendDirect(std::vectorcolors, size_t led_nu sprintf(serial_buf+actual_length," %d",r); actual_length += val_char_len(r) + 1; - + sprintf(serial_buf+actual_length," %d",g); actual_length += val_char_len(g) + 1; @@ -88,7 +91,7 @@ void DygmaRaiseController::SendDirect(std::vectorcolors, size_t led_nu | Add the final newline | \*-----------------------------------------------------*/ sprintf(serial_buf+actual_length,"\n"); - actual_length++; + actual_length++; /*-----------------------------------------------------*\ | Send packet | diff --git a/Controllers/DygmaRaiseController/DygmaRaiseController.h b/Controllers/DygmaRaiseController/DygmaRaiseController.h index d0348cea..1fcea40d 100644 --- a/Controllers/DygmaRaiseController/DygmaRaiseController.h +++ b/Controllers/DygmaRaiseController/DygmaRaiseController.h @@ -1,19 +1,21 @@ -/*-----------------------------------------*\ -| DygmaRaiseController.h | -| | -| Driver for Dygma Raise keyboard | -| | -| Timo Schlegel (@eispalast) 12/12/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| DygmaRaiseController.h | +| | +| Driver for Dygma Raise keyboard | +| | +| Timo Schlegel (@eispalast) Dec 12 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include "RGBController.h" + #include #include +#include "RGBController.h" #include "serial_port.h" -#pragma once - #define DYGMA_RAISE_VID 0x1209 #define DYGMA_RAISE_PID 0x2201 @@ -33,4 +35,4 @@ private: std::string location; std::string port_name; serial_port * serialport = nullptr; -}; \ No newline at end of file +}; diff --git a/Controllers/DygmaRaiseController/DygmaRaiseControllerDetect.cpp b/Controllers/DygmaRaiseController/DygmaRaiseControllerDetect.cpp index 33f4b1c8..0e488865 100644 --- a/Controllers/DygmaRaiseController/DygmaRaiseControllerDetect.cpp +++ b/Controllers/DygmaRaiseController/DygmaRaiseControllerDetect.cpp @@ -1,11 +1,19 @@ +/*---------------------------------------------------------*\ +| DygmaRaiseControllerDetect.cpp | +| | +| Detector for Dygma Raise keyboard | +| | +| Timo Schlegel (@eispalast) Dec 12 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "DygmaRaiseController.h" -#include "RGBController.h" #include "RGBController_DygmaRaise.h" #include "find_usb_serial_port.h" #include -#include - #define DYGMA_RAISE_VID 0x1209 #define DYGMA_RAISE_PID 0x2201 diff --git a/Controllers/DygmaRaiseController/RGBController_DygmaRaise.cpp b/Controllers/DygmaRaiseController/RGBController_DygmaRaise.cpp index a39117d9..30510dd4 100644 --- a/Controllers/DygmaRaiseController/RGBController_DygmaRaise.cpp +++ b/Controllers/DygmaRaiseController/RGBController_DygmaRaise.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_DygmaRaise.cpp | -| | -| RGB Interface DygmaRaise keyboard | -| | -| Timo Schlegel (@eispalast) 12/12/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_DygmaRaise.cpp | +| | +| RGBController for Dygma Raise keyboard | +| | +| Timo Schlegel (@eispalast) Dec 12 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_DygmaRaise.h" @@ -34,7 +37,6 @@ static unsigned int underglow_matrix[11][14] = { 23, NA, NA, NA, NA, 16, NA, 47, NA, NA, NA, NA, NA, 55 }, { 22, 21, 20, 19, 18, 17, NA, 48, 49, 50, 51, 52, 53, 54, } }; - static const char* zone_names[] = { ZONE_EN_KEYBOARD, @@ -234,7 +236,6 @@ void RGBController_DygmaRaise::ResizeZone(int /*zone*/, int /*new_size*/) \*---------------------------------------------------------*/ } - void RGBController_DygmaRaise::DeviceUpdateLEDs() { controller->SendDirect(colors,leds.size()); diff --git a/Controllers/DygmaRaiseController/RGBController_DygmaRaise.h b/Controllers/DygmaRaiseController/RGBController_DygmaRaise.h index 7ef70107..08ca073f 100644 --- a/Controllers/DygmaRaiseController/RGBController_DygmaRaise.h +++ b/Controllers/DygmaRaiseController/RGBController_DygmaRaise.h @@ -1,12 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_DygmaRaise.h | -| | -| RGB Interface for DygmaRaise keyboard | -| | -| Timo Schlegel (@eispalast) 12/12/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_DygmaRaise.h | +| | +| RGBController for Dygma Raise keyboard | +| | +| Timo Schlegel (@eispalast) Dec 12 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "DygmaRaiseController.h" diff --git a/Controllers/E131Controller/E131ControllerDetect.cpp b/Controllers/E131Controller/E131ControllerDetect.cpp index 68235644..724168e9 100644 --- a/Controllers/E131Controller/E131ControllerDetect.cpp +++ b/Controllers/E131Controller/E131ControllerDetect.cpp @@ -1,16 +1,19 @@ +/*---------------------------------------------------------*\ +| E131ControllerDetect.cpp | +| | +| Detector for E1.31 devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include #include "Detector.h" #include "RGBController.h" #include "RGBController_E131.h" #include "SettingsManager.h" -#include -#include -#include - -#include -#include -#include -#include -#include /******************************************************************************************\ * * diff --git a/Controllers/E131Controller/RGBController_E131.cpp b/Controllers/E131Controller/RGBController_E131.cpp index bde23f66..56fd2b47 100644 --- a/Controllers/E131Controller/RGBController_E131.cpp +++ b/Controllers/E131Controller/RGBController_E131.cpp @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_LEDStrip.cpp | -| | -| Generic RGB Interface for OpenAuraSDK | -| E1.31 Streaming ACN interface | -| | -| Adam Honse (CalcProgrammer1) 10/18/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_E131.cpp | +| | +| RGBController for E1.31 devices | +| | +| Adam Honse (CalcProgrammer1) 18 Oct 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_E131.h" #include #include +#include "RGBController_E131.h" using namespace std::chrono_literals; @@ -71,8 +73,8 @@ RGBController_E131::RGBController_E131(std::vector device_list) for(unsigned int device_idx = 0; device_idx < devices.size(); device_idx++) { - float universe_size = devices[device_idx].universe_size; - unsigned int total_universes = ceil( ( ( devices[device_idx].num_leds * 3 ) + devices[device_idx].start_channel ) / universe_size ); + float universe_size = (float)devices[device_idx].universe_size; + unsigned int total_universes = (unsigned int)ceil( ( ( devices[device_idx].num_leds * 3 ) + devices[device_idx].start_channel ) / universe_size ); for(unsigned int univ_idx = 0; univ_idx < total_universes; univ_idx++) { @@ -157,8 +159,8 @@ RGBController_E131::RGBController_E131(std::vector device_list) /*-----------------------------------------*\ | Add Universes | \*-----------------------------------------*/ - float universe_size = devices[device_idx].universe_size; - unsigned int total_universes = ceil( ( ( devices[device_idx].num_leds * 3 ) + devices[device_idx].start_channel ) / universe_size ); + float universe_size = (float)devices[device_idx].universe_size; + unsigned int total_universes = (unsigned int)ceil( ( ( devices[device_idx].num_leds * 3 ) + devices[device_idx].start_channel ) / universe_size ); for (unsigned int univ_idx = 0; univ_idx < total_universes; univ_idx++) { @@ -178,7 +180,7 @@ RGBController_E131::RGBController_E131(std::vector device_list) e131_packet_t packet; e131_addr_t dest_addr; - e131_pkt_init(&packet, universe, universe_size); + e131_pkt_init(&packet, (uint16_t)universe, (uint16_t)universe_size); if(multicast) { @@ -384,8 +386,8 @@ void RGBController_E131::DeviceUpdateLEDs() for(std::size_t device_idx = 0; device_idx < devices.size(); device_idx++) { - float universe_size = devices[device_idx].universe_size; - unsigned int total_universes = ceil( ( ( devices[device_idx].num_leds * 3 ) + devices[device_idx].start_channel ) / universe_size ); + float universe_size = (float)devices[device_idx].universe_size; + unsigned int total_universes = (unsigned int)ceil( ( ( devices[device_idx].num_leds * 3 ) + devices[device_idx].start_channel ) / universe_size ); unsigned int channel_idx = devices[device_idx].start_channel; unsigned int led_idx = 0; unsigned int rgb_idx = 0; diff --git a/Controllers/E131Controller/RGBController_E131.h b/Controllers/E131Controller/RGBController_E131.h index 62b13501..21ecd0ea 100644 --- a/Controllers/E131Controller/RGBController_E131.h +++ b/Controllers/E131Controller/RGBController_E131.h @@ -1,17 +1,20 @@ -/*-----------------------------------------*\ -| RGBController_E131.h | -| | -| Generic RGB Interface for OpenAuraSDK | -| E1.31 Streaming ACN interface | -| | -| Adam Honse (CalcProgrammer1) 10/18/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_E131.h | +| | +| RGBController for E1.31 devices | +| | +| Adam Honse (CalcProgrammer1) 18 Oct 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include "RGBController.h" -#include + #include #include +#include +#include "RGBController.h" typedef unsigned int e131_rgb_order; diff --git a/Controllers/EKController/EKController.cpp b/Controllers/EKController/EKController.cpp index 45789b42..fd283c43 100644 --- a/Controllers/EKController/EKController.cpp +++ b/Controllers/EKController/EKController.cpp @@ -1,13 +1,16 @@ -/*-------------------------------------------------------------------*\ -| EKController.cpp | -| | -| Driver for EK Loop Connect | -| | -| Chris M (Dr_No) 16th Jul 2020 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| EKController.cpp | +| | +| Driver for EK Loop Connect | +| | +| Chris M (Dr_No) 16 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "EKController.h" +#include "StringUtils.h" static unsigned char ek_colour_mode_data[][16] = { @@ -46,24 +49,19 @@ static unsigned char ek_speed_mode_data[][9] = EKController::EKController(hid_device* dev_handle, char *_path) { - const int szTemp = 256; - wchar_t tmpName[szTemp]; + dev = dev_handle; + location = _path; - dev = dev_handle; + /*---------------------------------------------------------*\ + | Get device name from HID manufacturer and product strings | + \*---------------------------------------------------------*/ + wchar_t name_string[HID_MAX_STR]; - hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - device_name = std::string(wName.begin(), wName.end()); + hid_get_manufacturer_string(dev, name_string, HID_MAX_STR); + device_name = StringUtils::wstring_to_string(name_string); - hid_get_product_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); - - hid_get_serial_number_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - serial = std::string(wName.begin(), wName.end()); - - location = _path; + hid_get_product_string(dev, name_string, HID_MAX_STR); + device_name.append(" ").append(StringUtils::wstring_to_string(name_string)); current_mode = EK_MODE_STATIC; current_speed = EK_SPEED_NORMAL; @@ -81,7 +79,15 @@ std::string EKController::GetDeviceName() std::string EKController::GetSerial() { - return serial; + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } std::string EKController::GetLocation() diff --git a/Controllers/EKController/EKController.h b/Controllers/EKController/EKController.h index 7a57251c..f3443392 100644 --- a/Controllers/EKController/EKController.h +++ b/Controllers/EKController/EKController.h @@ -1,21 +1,23 @@ -/*-------------------------------------------------------------------*\ -| EKController.h | -| | -| Driver for EK Loop Connect | -| | -| Chris M (Dr_No) 16th Jul 2020 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| EKController.h | +| | +| Driver for EK Loop Connect | +| | +| Chris M (Dr_No) 16 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#ifndef EKCONTROLLER_H -#define EKCONTROLLER_H +#pragma once #include -#include +#include -#define EK_COLOUR_MODE_DATA_SIZE (sizeof(ek_colour_mode_data[0]) / sizeof(ek_colour_mode_data[0][0])) -#define EK_DEVICE_NAME_SIZE (sizeof(device_name) / sizeof(device_name[ 0 ])) -#define EK_PACKET_LENGTH 0x3F +#define EK_COLOUR_MODE_DATA_SIZE (sizeof(ek_colour_mode_data[0]) / sizeof(ek_colour_mode_data[0][0])) +#define EK_DEVICE_NAME_SIZE (sizeof(device_name) / sizeof(device_name[ 0 ])) +#define EK_PACKET_LENGTH 0x3F +#define HID_MAX_STR 255 enum { @@ -67,7 +69,6 @@ public: private: std::string device_name; - std::string serial; std::string location; hid_device* dev; @@ -80,5 +81,3 @@ private: void SendUpdate(); }; - -#endif // EKCONTROLLER_H diff --git a/Controllers/EKController/EKControllerDetect.cpp b/Controllers/EKController/EKControllerDetect.cpp index daebee09..515a46b8 100644 --- a/Controllers/EKController/EKControllerDetect.cpp +++ b/Controllers/EKController/EKControllerDetect.cpp @@ -1,8 +1,18 @@ +/*---------------------------------------------------------*\ +| EKControllerDetect.cpp | +| | +| Detector for EK Loop Connect | +| | +| Chris M (Dr_No) 16 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "EKController.h" -#include "RGBController.h" #include "RGBController_EKController.h" -#include #define EK_VID 0x0483 #define EK_LOOP_CONNECT 0x5750 diff --git a/Controllers/EKController/RGBController_EKController.cpp b/Controllers/EKController/RGBController_EKController.cpp index 81a7c17c..c22bdadc 100644 --- a/Controllers/EKController/RGBController_EKController.cpp +++ b/Controllers/EKController/RGBController_EKController.cpp @@ -1,11 +1,13 @@ -/*-------------------------------------------------------------------*\ -| RGBController_EKController.cpp | -| | -| Driver for EK Loop Connect | -| | -| Chris M (Dr_No) 16th Jul 2020 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_EKController.cpp | +| | +| RGBController for EK Loop Connect | +| | +| Chris M (Dr_No) 16 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_EKController.h" diff --git a/Controllers/EKController/RGBController_EKController.h b/Controllers/EKController/RGBController_EKController.h index 1b4b50aa..22248876 100644 --- a/Controllers/EKController/RGBController_EKController.h +++ b/Controllers/EKController/RGBController_EKController.h @@ -1,17 +1,18 @@ -/*-------------------------------------------------------------------*\ -| RGBController_EKController.h | -| | -| Driver for EK Loop Connect | -| | -| Chris M (Dr_No) 16th Jul 2020 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_EKController.h | +| | +| RGBController for EK Loop Connect | +| | +| Chris M (Dr_No) 16 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#ifndef RGBCONTROLLER_EKCONTROLLER_H -#define RGBCONTROLLER_EKCONTROLLER_H +#pragma once #include "RGBController.h" -#include "Controllers/EKController/EKController.h" +#include "EKController.h" class RGBController_EKController : public RGBController { @@ -31,5 +32,3 @@ public: private: EKController* controller; }; - -#endif // RGBCONTROLLER_EKCONTROLLER_H diff --git a/Controllers/ENESMBusController/ENESMBusController.cpp b/Controllers/ENESMBusController/ENESMBusController.cpp index d7639465..e47cd7bc 100644 --- a/Controllers/ENESMBusController/ENESMBusController.cpp +++ b/Controllers/ENESMBusController/ENESMBusController.cpp @@ -1,18 +1,17 @@ -/*-----------------------------------------*\ -| ENESMBusController.cpp | -| | -| Driver for ENE SMBus RGB lighting | -| controller | -| | -| Formerly known as ASUS Aura SMBus. ASUS | -| AURA chips are rebranded ENE controllers | -| | -| Adam Honse (CalcProgrammer1) 8/19/2018 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| ENESMBusController.cpp | +| | +| Driver for ENE SMBus devices | +| | +| Adam Honse (CalcProgrammer1) 19 Aug 2018 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include "ENESMBusController.h" #include "LogManager.h" -#include static const char* ene_channels[] = /* ENE channel strings */ { @@ -26,77 +25,105 @@ static const char* ene_channels[] = /* ENE channel strings "RGB Header", "RGB Header 2", "RGB Header", + "SSD", "Unknown", }; -ENESMBusController::ENESMBusController(ENESMBusInterface* interface, ene_dev_id dev) +ENESMBusController::ENESMBusController(ENESMBusInterface* interface, ene_dev_id dev, std::string dev_name, device_type dev_type) { this->interface = interface; this->dev = dev; + this->name = dev_name; + this->type = dev_type; supports_mode_14 = false; - UpdateDeviceName(); - - // Read the device configuration table - for (int i = 0; i < 64; i++) + if(interface->GetInterfaceType() != ENE_INTERFACE_TYPE_ROG_ARION) { - config_table[i] = ENERegisterRead(ENE_REG_CONFIG_TABLE + i); + UpdateDeviceName(); + + /*-------------------------------------------------*\ + | Read the device configuration table | + \*-------------------------------------------------*/ + for(int i = 0; i < 64; i++) + { + config_table[i] = ENERegisterRead(ENE_REG_CONFIG_TABLE + i); + } + + /*-------------------------------------------------*\ + | If this is running with TRACE or higher loglevel | + | then dump the entire Feature list to log | + \*-------------------------------------------------*/ + if(LogManager::get()->getLoglevel() >= LL_TRACE) + { + LOG_TRACE("[ENE SMBus] ENE config table for 0x%02X:", dev); + LOG_TRACE(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", config_table[0], config_table[1], config_table[2], config_table[3], + config_table[4], config_table[5], config_table[6], config_table[7], + config_table[8], config_table[9], config_table[10], config_table[11], + config_table[12], config_table[13], config_table[14], config_table[15]); + + LOG_TRACE(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", config_table[16], config_table[17], config_table[18], config_table[19], + config_table[20], config_table[21], config_table[22], config_table[23], + config_table[24], config_table[25], config_table[26], config_table[27], + config_table[28], config_table[29], config_table[30], config_table[31]); + + LOG_TRACE(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", config_table[32], config_table[33], config_table[34], config_table[35], + config_table[36], config_table[37], config_table[38], config_table[39], + config_table[40], config_table[41], config_table[42], config_table[43], + config_table[44], config_table[45], config_table[46], config_table[47]); + + LOG_TRACE(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", config_table[48], config_table[49], config_table[50], config_table[51], + config_table[52], config_table[53], config_table[54], config_table[55], + config_table[56], config_table[57], config_table[58], config_table[59], + config_table[60], config_table[61], config_table[62], config_table[63]); + } + } + else + { + LOG_TRACE("[ENE SMBus] ROG STRIX ARION detected, filling in hard coded config table entries.", dev); + memset(config_table, 0, sizeof(config_table)); + config_table[ENE_CONFIG_LED_COUNT] = 4; + config_table[0x03] = 4; + strcpy(device_version, "ROG STRIX ARION"); } - /*-----------------------------------------------------------------*\ - | If this is running with TRACE or higher loglevel then | - | dump the entire Feature list to log | - \*-----------------------------------------------------------------*/ - if(LogManager::get()->getLoglevel() >= LL_TRACE) - { - LOG_TRACE("[ENE SMBus] ENE config table for 0x%02X:", dev); - LOG_TRACE(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", config_table[0], config_table[1], config_table[2], config_table[3], - config_table[4], config_table[5], config_table[6], config_table[7], - config_table[8], config_table[9], config_table[10], config_table[11], - config_table[12], config_table[13], config_table[14], config_table[15]); - - LOG_TRACE(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", config_table[16], config_table[17], config_table[18], config_table[19], - config_table[20], config_table[21], config_table[22], config_table[23], - config_table[24], config_table[25], config_table[26], config_table[27], - config_table[28], config_table[29], config_table[30], config_table[31]); - - LOG_TRACE(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", config_table[32], config_table[33], config_table[34], config_table[35], - config_table[36], config_table[37], config_table[38], config_table[39], - config_table[40], config_table[41], config_table[42], config_table[43], - config_table[44], config_table[45], config_table[46], config_table[47]); - - LOG_TRACE(" %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", config_table[48], config_table[49], config_table[50], config_table[51], - config_table[52], config_table[53], config_table[54], config_table[55], - config_table[56], config_table[57], config_table[58], config_table[59], - config_table[60], config_table[61], config_table[62], config_table[63]); - } - - // Read LED count from configuration table + /*-----------------------------------------------------*\ + | Read LED count from configuration table | + \*-----------------------------------------------------*/ led_count = config_table[ENE_CONFIG_LED_COUNT]; - // LED-0116 - First generation motherboard controller - if (strcmp(device_name, "LED-0116") == 0) + /*-----------------------------------------------------*\ + | LED-0116 - First generation motherboard controller | + \*-----------------------------------------------------*/ + if(strcmp(device_version, "LED-0116") == 0) { direct_reg = ENE_REG_COLORS_DIRECT; effect_reg = ENE_REG_COLORS_EFFECT; channel_cfg = ENE_CONFIG_CHANNEL_V1; } - // DIMM_LED-0102 - First generation DRAM controller (Trident Z RGB) - else if (strcmp(device_name, "DIMM_LED-0102") == 0) + /*-----------------------------------------------------*\ + | DIMM_LED-0102 - First generation DRAM controller | + | (Trident Z RGB) | + \*-----------------------------------------------------*/ + else if(strcmp(device_version, "DIMM_LED-0102") == 0) { direct_reg = ENE_REG_COLORS_DIRECT; effect_reg = ENE_REG_COLORS_EFFECT; channel_cfg = ENE_CONFIG_CHANNEL_V1; } - // AUDA0-E6K5-0101 - Second generation DRAM controller (Geil Super Luce) - else if (strcmp(device_name, "AUDA0-E6K5-0101") == 0) + /*-----------------------------------------------------*\ + | AUDA0-E6K5-0101 - Second generation DRAM controller | + | (Geil Super Luce) | + \*-----------------------------------------------------*/ + else if(strcmp(device_version, "AUDA0-E6K5-0101") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V1; - // Check for Mode 14 support, only known to exist on modules where the - // DRAM 3 zone ID exists + /*-------------------------------------------------*\ + | Check for Mode 14 support, only known to exist on | + | modules where the DRAM 3 zone ID exists | + \*-------------------------------------------------*/ for(std::size_t cfg_zone_idx = 0; cfg_zone_idx < ENE_NUM_ZONES; cfg_zone_idx++) { if(config_table[channel_cfg + cfg_zone_idx] == (unsigned char)ENE_LED_CHANNEL_DRAM_3) @@ -106,67 +133,154 @@ ENESMBusController::ENESMBusController(ENESMBusInterface* interface, ene_dev_id } } } - // AUMA0-E6K5-0106 - Second generation motherboard controller - else if (strcmp(device_name, "AUMA0-E6K5-0106") == 0) + /*-----------------------------------------------------*\ + | AUMA0-E6K5-0106 - Second generation motherboard | + | controller | + \*-----------------------------------------------------*/ + else if(strcmp(device_version, "AUMA0-E6K5-0106") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V2; } - // AUMA0-E6K5-0105 - Second generation motherboard controller - else if (strcmp(device_name, "AUMA0-E6K5-0105") == 0) + /*-----------------------------------------------------*\ + | AUMA0-E6K5-0105 - Second generation motherboard | + | controller | + \*-----------------------------------------------------*/ + else if(strcmp(device_version, "AUMA0-E6K5-0105") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V2; } - // AUMA0-E6K5-0104 - Second generation motherboard controller - else if (strcmp(device_name, "AUMA0-E6K5-0104") == 0) + /*-----------------------------------------------------*\ + | AUMA0-E6K5-0104 - Second generation motherboard | + | controller | + \*-----------------------------------------------------*/ + else if(strcmp(device_version, "AUMA0-E6K5-0104") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V2; } - // AUMA0-E8K4-0101 - First generation motherboard controller - else if (strcmp(device_name, "AUMA0-E8K4-0101") == 0) + /*-----------------------------------------------------*\ + | AUMA0-E8K4-0101 - First generation motherboard | + | controller | + \*-----------------------------------------------------*/ + else if(strcmp(device_version, "AUMA0-E8K4-0101") == 0) { direct_reg = ENE_REG_COLORS_DIRECT; effect_reg = ENE_REG_COLORS_EFFECT; channel_cfg = ENE_CONFIG_CHANNEL_V1; } - // AUMA0-E6K5-0107 - Second generation GPU controller - else if (strcmp(device_name, "AUMA0-E6K5-0107") == 0) + /*-----------------------------------------------------*\ + | AUMA0-E6K5-0107 - Second generation GPU controller | + \*-----------------------------------------------------*/ + else if(strcmp(device_version, "AUMA0-E6K5-0107") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V2; - // Read LED count from configuration table + /*-------------------------------------------------*\ + | Read LED count from configuration table | + \*-------------------------------------------------*/ led_count = config_table[ENE_CONFIG_LED_COUNT_0107]; } - // AUMA0-E6K5-1110 - Third generation GPU controller? - // found an ASUS ROG Strix 4080 OC, seems to be equal to AUMA0-E6K5-0107 - else if (strcmp(device_name, "AUMA0-E6K5-1110") == 0) + /*-----------------------------------------------------*\ + | AUMA0-E6K5-1110 - Third generation GPU controller? | + | found an ASUS ROG Strix 4080 OC, seems to be equal to | + | AUMA0-E6K5-0107 | + \*-----------------------------------------------------*/ + else if(strcmp(device_version, "AUMA0-E6K5-1110") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V2; - // Read LED count from configuration table + /*-------------------------------------------------*\ + | Read LED count from configuration table | + \*-------------------------------------------------*/ led_count = config_table[ENE_CONFIG_LED_COUNT_1110]; } - // AUMA0-E6K5-1107 - Second generation GPU controller - // Found on ASUS TUF 4070 TI OC, seems to be equal to AUMA0-E6K5-0107 - else if (strcmp(device_name, "AUMA0-E6K5-1107") == 0) + /*-----------------------------------------------------*\ + | AUMA0-E6K5-1111 - Fourth generation GPU controller? | + | found on ASUS ROG Strix 4090 OC EVA-02 Edition, seems | + | to be equal to AUMA0-E6K5-0107 | + \*-----------------------------------------------------*/ + else if(strcmp(device_version, "AUMA0-E6K5-1111") == 0) { direct_reg = ENE_REG_COLORS_DIRECT_V2; effect_reg = ENE_REG_COLORS_EFFECT_V2; channel_cfg = ENE_CONFIG_CHANNEL_V2; - // Read LED count from configuration table + /*-------------------------------------------------*\ + | Read LED count from configuration table | + \*-------------------------------------------------*/ led_count = config_table[ENE_CONFIG_LED_COUNT_0107]; } - // Assume first generation controller if string does not match + /*-----------------------------------------------------*\ + | AUMA0-E6K5-1107 - Second generation GPU controller | + | Found on ASUS TUF 4070 TI OC, seems to be equal to | + | AUMA0-E6K5-0107 | + \*-----------------------------------------------------*/ + else if(strcmp(device_version, "AUMA0-E6K5-1107") == 0) + { + direct_reg = ENE_REG_COLORS_DIRECT_V2; + effect_reg = ENE_REG_COLORS_EFFECT_V2; + channel_cfg = ENE_CONFIG_CHANNEL_V2; + + /*-------------------------------------------------*\ + | Read LED count from configuration table | + \*-------------------------------------------------*/ + led_count = config_table[ENE_CONFIG_LED_COUNT_0107]; + } + /*-----------------------------------------------------*\ + | AUMA0-E6K5-0008 | + | Found on ASUS STRIX 4070 Super OC | + \*-----------------------------------------------------*/ + else if(strcmp(device_version, "AUMA0-E6K5-0008") == 0) + { + direct_reg = ENE_REG_COLORS_DIRECT_V2; + effect_reg = ENE_REG_COLORS_EFFECT_V2; + channel_cfg = ENE_CONFIG_CHANNEL_V1; + + /*-------------------------------------------------*\ + | Read LED count from configuration table | + \*-------------------------------------------------*/ + led_count = config_table[ENE_CONFIG_LED_COUNT_0107]; + } + /*-----------------------------------------------------*\ + | AUMA0-E6K5-1113 | + | Found on ASUS ASTRAL 5080 OC | + \*-----------------------------------------------------*/ + else if(strcmp(device_version, "AUMA0-E6K5-1113") == 0) + { + direct_reg = ENE_REG_COLORS_DIRECT_V2; + effect_reg = ENE_REG_COLORS_EFFECT_V2; + channel_cfg = ENE_CONFIG_CHANNEL_V2; + + /*-------------------------------------------------*\ + | Read LED count from configuration table | + \*-------------------------------------------------*/ + led_count = config_table[ENE_CONFIG_LED_COUNT_0107]; + } + /*-----------------------------------------------------*\ + | ROG ARION - ASUS ROG Arion external SSD enclosure | + | This device does not support ENE read, so we fake the | + | device name string if the interface is ROG Arion type.| + | It uses second generation registers. | + \*-----------------------------------------------------*/ + else if(strcmp(device_version, "ROG STRIX ARION") == 0) + { + direct_reg = ENE_REG_COLORS_DIRECT_V2; + effect_reg = ENE_REG_COLORS_EFFECT_V2; + channel_cfg = ENE_CONFIG_CHANNEL_V2; + } + /*-----------------------------------------------------*\ + | Assume first generation controller if string does not | + | match | + \*-----------------------------------------------------*/ else { direct_reg = ENE_REG_COLORS_DIRECT; @@ -180,12 +294,7 @@ ENESMBusController::~ENESMBusController() delete interface; } -std::string ENESMBusController::GetDeviceName() -{ - return(device_name); -} - -std::string ENESMBusController::GetDeviceLocation() +std::string ENESMBusController::GetLocation() { std::string return_string = interface->GetLocation(); @@ -197,63 +306,85 @@ std::string ENESMBusController::GetDeviceLocation() return(return_string); } +std::string ENESMBusController::GetName() +{ + return(name); +} + +std::string ENESMBusController::GetVersion() +{ + return(device_version); +} + +device_type ENESMBusController::GetType() +{ + return(type); +} + const char * ENESMBusController::GetChannelName(unsigned int cfg_zone) { - LOG_TRACE("[%s] Config table for zone %02d: %02d", device_name, cfg_zone, config_table[channel_cfg + cfg_zone]); + LOG_TRACE("[%s] Config table for zone %02d: %02d", device_version, cfg_zone, config_table[channel_cfg + cfg_zone]); - switch(config_table[channel_cfg + cfg_zone]) + if(interface->GetInterfaceType() == ENE_INTERFACE_TYPE_ROG_ARION) { - case (unsigned char)ENE_LED_CHANNEL_AUDIO: - return(ene_channels[0]); - break; - - case (unsigned char)ENE_LED_CHANNEL_BACKPLATE: - return(ene_channels[1]); - break; - - case (unsigned char)ENE_LED_CHANNEL_BACK_IO: - return(ene_channels[2]); - break; - - case (unsigned char)ENE_LED_CHANNEL_CENTER: - return(ene_channels[3]); - break; - - case (unsigned char)ENE_LED_CHANNEL_CENTER_START: - return(ene_channels[4]); - break; - - case (unsigned char)ENE_LED_CHANNEL_DRAM: - case (unsigned char)ENE_LED_CHANNEL_DRAM_2: - case (unsigned char)ENE_LED_CHANNEL_DRAM_3: - return(ene_channels[5]); - break; - - case (unsigned char)ENE_LED_CHANNEL_PCIE: - return(ene_channels[6]); - break; - - case (unsigned char)ENE_LED_CHANNEL_RGB_HEADER: - return(ene_channels[7]); - break; - - case (unsigned char)ENE_LED_CHANNEL_RGB_HEADER_2: - return(ene_channels[8]); - break; - - case (unsigned char)ENE_LED_CHANNEL_RGB_HEADER_3: - return(ene_channels[9]); - break; - - default: return(ene_channels[10]); - break; + } + else + { + switch(config_table[channel_cfg + cfg_zone]) + { + case (unsigned char)ENE_LED_CHANNEL_AUDIO: + return(ene_channels[0]); + break; + + case (unsigned char)ENE_LED_CHANNEL_BACKPLATE: + return(ene_channels[1]); + break; + + case (unsigned char)ENE_LED_CHANNEL_BACK_IO: + return(ene_channels[2]); + break; + + case (unsigned char)ENE_LED_CHANNEL_CENTER: + return(ene_channels[3]); + break; + + case (unsigned char)ENE_LED_CHANNEL_CENTER_START: + return(ene_channels[4]); + break; + + case (unsigned char)ENE_LED_CHANNEL_DRAM: + case (unsigned char)ENE_LED_CHANNEL_DRAM_2: + case (unsigned char)ENE_LED_CHANNEL_DRAM_3: + return(ene_channels[5]); + break; + + case (unsigned char)ENE_LED_CHANNEL_PCIE: + return(ene_channels[6]); + break; + + case (unsigned char)ENE_LED_CHANNEL_RGB_HEADER: + return(ene_channels[7]); + break; + + case (unsigned char)ENE_LED_CHANNEL_RGB_HEADER_2: + return(ene_channels[8]); + break; + + case (unsigned char)ENE_LED_CHANNEL_RGB_HEADER_3: + return(ene_channels[9]); + break; + + default: + return(ene_channels[11]); + break; + } } } unsigned int ENESMBusController::GetLEDCount(unsigned int cfg_zone) { - LOG_TRACE("[%s] LED Count for zone %02d: %02d", device_name, cfg_zone, config_table[0x03 + cfg_zone]); + LOG_TRACE("[%s] LED Count for zone %02d: %02d", device_version, cfg_zone, config_table[0x03 + cfg_zone]); return(config_table[0x03 + cfg_zone]); } @@ -392,7 +523,7 @@ void ENESMBusController::UpdateDeviceName() { for (int i = 0; i < 16; i++) { - device_name[i] = ENERegisterRead(ENE_REG_DEVICE_NAME + i); + device_version[i] = ENERegisterRead(ENE_REG_DEVICE_NAME + i); } } diff --git a/Controllers/ENESMBusController/ENESMBusController.h b/Controllers/ENESMBusController/ENESMBusController.h index 035146fd..b2b105b9 100644 --- a/Controllers/ENESMBusController/ENESMBusController.h +++ b/Controllers/ENESMBusController/ENESMBusController.h @@ -1,24 +1,24 @@ -/*-----------------------------------------*\ -| ENESMBusController.h | -| | -| Definitions and types for ENE SMBus RGB | -| lighting controller | -| | -| Formerly known as ASUS Aura SMBus. ASUS | -| AURA chips are rebranded ENE controllers | -| | -| Adam Honse (CalcProgrammer1) 8/19/2018 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| ENESMBusController.h | +| | +| Driver for ENE SMBus devices | +| | +| Adam Honse (CalcProgrammer1) 19 Aug 2018 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "ENESMBusInterface.h" #include "RGBController.h" -#pragma once - #define ENE_APPLY_VAL 0x01 /* Value for Apply Changes Register */ #define ENE_SAVE_VAL 0xAA /* Value for Save Changes */ #define ENE_NUM_ZONES 8 /* Number of ENE config table zones */ + enum { ENE_REG_DEVICE_NAME = 0x1000, /* Device String 16 bytes */ @@ -100,11 +100,14 @@ enum class ENESMBusController { public: - ENESMBusController(ENESMBusInterface* interface, ene_dev_id dev); + ENESMBusController(ENESMBusInterface* interface, ene_dev_id dev, std::string dev_name, device_type dev_type); ~ENESMBusController(); - std::string GetDeviceName(); - std::string GetDeviceLocation(); + std::string GetLocation(); + std::string GetName(); + std::string GetVersion(); + device_type GetType(); + const char* GetChannelName(unsigned int cfg_zone); unsigned int GetLEDCount(unsigned int cfg_zone); unsigned char GetLEDRed(unsigned int led); @@ -129,7 +132,7 @@ public: void ENERegisterWriteBlock(ene_register reg, unsigned char * data, unsigned char sz); private: - char device_name[16]; + char device_version[16]; unsigned char config_table[64]; unsigned int led_count; ene_register direct_reg; @@ -138,4 +141,6 @@ private: ENESMBusInterface* interface; ene_dev_id dev; bool supports_mode_14; + std::string name; + device_type type; }; diff --git a/Controllers/ENESMBusController/ENESMBusControllerDetect.cpp b/Controllers/ENESMBusController/ENESMBusControllerDetect.cpp index 5eaa181b..9bb3e738 100644 --- a/Controllers/ENESMBusController/ENESMBusControllerDetect.cpp +++ b/Controllers/ENESMBusController/ENESMBusControllerDetect.cpp @@ -1,16 +1,22 @@ +/*---------------------------------------------------------*\ +| ENESMBusControllerDetect.cpp | +| | +| Detector for ENE SMBus devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "ENESMBusController.h" #include "ENESMBusInterface_i2c_smbus.h" -#include "ENESMBusInterface_SpectrixS40G.h" #include "LogManager.h" #include "RGBController.h" #include "RGBController_ENESMBus.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include -#include "dependencies/dmiinfo.h" +#include "dmiinfo.h" #define DETECTOR_NAME "ENE (ASUS Aura) SMBus Controller" #define VENDOR_NAME "ASUS" //This should match the Vendor name from DMI @@ -18,7 +24,7 @@ using namespace std::chrono_literals; /*----------------------------------------------------------------------*\ -| Windows defines "interface" for some reason. Work around this | +| Windows defines "interface" for some reason. Work around this | \*----------------------------------------------------------------------*/ #ifdef interface #undef interface @@ -78,7 +84,7 @@ static const unsigned char aura_mobo_addresses[] = * * \******************************************************************************************/ -unsigned char ENERegisterRead(i2c_smbus_interface* bus, ene_dev_id dev, ene_register reg) +static unsigned char ENERegisterRead(i2c_smbus_interface* bus, ene_dev_id dev, ene_register reg) { //Write ENE register bus->i2c_smbus_write_word_data(dev, 0x00, ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF)); @@ -97,7 +103,7 @@ unsigned char ENERegisterRead(i2c_smbus_interface* bus, ene_dev_id dev, ene_regi * * \******************************************************************************************/ -void ENERegisterWrite(i2c_smbus_interface* bus, ene_dev_id dev, ene_register reg, unsigned char val) +static void ENERegisterWrite(i2c_smbus_interface* bus, ene_dev_id dev, ene_register reg, unsigned char val) { //Write ENE register bus->i2c_smbus_write_word_data(dev, 0x00, ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF)); @@ -148,6 +154,7 @@ bool TestForENESMBusController(i2c_smbus_interface* bus, unsigned char address) LOG_VERBOSE("[ENE SMBus] Detection failed testing register %02X. Expected %02X, got %02X.", i, (i - 0xA0), res); pass = false; + break; } } @@ -202,7 +209,7 @@ void DetectENESMBusDRAMControllers(std::vector &busses) { int res = busses[bus]->i2c_smbus_write_quick(0x77, I2C_SMBUS_WRITE); - if (res < 0) + if(res < 0) { LOG_DEBUG("[ENE SMBus DRAM] No device detected at 0x77, aborting remap"); @@ -240,7 +247,7 @@ void DetectENESMBusDRAMControllers(std::vector &busses) if (TestForENESMBusController(busses[bus], ene_ram_addresses[address_list_idx])) { ENESMBusInterface_i2c_smbus* interface = new ENESMBusInterface_i2c_smbus(busses[bus]); - ENESMBusController* controller = new ENESMBusController(interface, ene_ram_addresses[address_list_idx]); + ENESMBusController* controller = new ENESMBusController(interface, ene_ram_addresses[address_list_idx], "ENE DRAM", DEVICE_TYPE_DRAM); RGBController_ENESMBus* rgb_controller = new RGBController_ENESMBus(controller); ResourceManager::get()->RegisterRGBController(rgb_controller); @@ -281,11 +288,9 @@ void DetectENESMBusMotherboardControllers(std::vector &bus DMIInfo dmi; ENESMBusInterface_i2c_smbus* interface = new ENESMBusInterface_i2c_smbus(busses[bus]); - ENESMBusController* controller = new ENESMBusController(interface, aura_mobo_addresses[address_list_idx]); + ENESMBusController* controller = new ENESMBusController(interface, aura_mobo_addresses[address_list_idx], "ASUS " + dmi.getMainboard(), DEVICE_TYPE_MOTHERBOARD); RGBController_ENESMBus* rgb_controller = new RGBController_ENESMBus(controller); - rgb_controller->name = "ASUS " + dmi.getMainboard(); - ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -315,12 +320,9 @@ void DetectENESMBusGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, co if(TestForENESMBusController(bus, i2c_addr)) { ENESMBusInterface_i2c_smbus* interface = new ENESMBusInterface_i2c_smbus(bus); - ENESMBusController* controller = new ENESMBusController(interface, i2c_addr); + ENESMBusController* controller = new ENESMBusController(interface, i2c_addr, name, DEVICE_TYPE_GPU); RGBController_ENESMBus* rgb_controller = new RGBController_ENESMBus(controller); - rgb_controller->name = name; - rgb_controller->type = DEVICE_TYPE_GPU; - ResourceManager::get()->RegisterRGBController(rgb_controller); } else @@ -333,88 +335,169 @@ REGISTER_I2C_DETECTOR("ENE SMBus DRAM", DetectENESMBusDRAMContro REGISTER_I2C_DETECTOR("ASUS Aura SMBus Motherboard", DetectENESMBusMotherboardControllers); /*-----------------------------------------*\ -| NVidia GPUs | +| Nvidia GPUs | \*-----------------------------------------*/ -REGISTER_I2C_PCI_DETECTOR("ASUS KO RTX 3060 OC O12G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, ASUS_SUB_VEN, ASUS_KO_RTX_3060_OC_O12G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF 3060 O12G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3060_O12G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF 3060 O12G V2 GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3060_O12G_V2_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF 3060 O12G V2 GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3060_O12G_LHR_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3060 12G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3060_12G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3060 O12G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3060_O12G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3060 O12G V2 GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3060_O12G_LHR_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS KO RTX 3060 O12G V2 GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, ASUS_SUB_VEN, ASUS_KO_RTX_3060_O12G_V2_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS KO RTX 3060Ti O8G V2 GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, ASUS_SUB_VEN, ASUS_KO_RTX3060TI_O8G_V2_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3060Ti O8G", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_GDDR6X_DEV,ASUS_SUB_VEN, ASUS_TUF_RTX_3060_TI_O8G, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS KO RTX 3060Ti O8G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, ASUS_SUB_VEN, ASUS_KO_RTX3060TI_O8G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3060Ti O8G OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3060_TI_O8G_OC, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3060Ti O8G OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_3060_TI_O8G_OC, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3060Ti O8G OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3060_TI_O8G_OC_V2, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3060Ti O8G V2", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3060TI_O8G_V2_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3070 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3070_OC, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3070 O8G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3070_O8G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3070 O8G White", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3070_O8G_WHITE, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3070 O8G V2 GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3070_O8G_V2_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3070 O8G V2 White", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3070_O8G_V2_WHITE, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3070 8G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3070_8G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3070 O8G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3070_O8G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS KO RTX 3070 O8G V2 GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, ASUS_SUB_VEN, ASUS_KO_RTX_3070_O8G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3070 O8G V2 GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3070_O8G_V2_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3070Ti O8G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3070TI_O8G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3070Ti O8G V2 GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3070TI_O8G_V2_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3070Ti O8G V2 GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_GA102_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3070TI_O8G_V2_GAMING_2, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3070Ti O8G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3070TI_O8G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3080 10G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080_10G_GAMING_PD, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3080 10G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080_10G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG RTX 3080 10G GUNDAM EDITION", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080_10G_GUNDAM_EDITION, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3080 O10G OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080_O10G_OC, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3080 10G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_10G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3080 O10G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_O10G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3080 O10G WHITE", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_O10G_WHITE, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3080 10G V2 GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_10G_V2_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3080 O10G V2 GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_O10G_V2_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3080 O10G V2 WHITE", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_O10G_V2_WHITE, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3080 O10G V2 GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080_O10G_V2_GAMING_8822, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3080 O10G V2 GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080_O10G_V2_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3080 O12G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080_O12G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 3080 12G", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_12G, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 3080 O12G", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_O12G_OC, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 3080 O12G EVA EDITION", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_O12G_EVA, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3080Ti 12G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080TI_12G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3080Ti O12G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080TI_O12G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3080Ti O12G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080TI_O12G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX LC 3080Ti O12G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080TI_O12G_GAMING_LC, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3090 24G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3090_24G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3090 O24G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3090_O24G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX 3090 O24G GAMING White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3090_O24G_GAMING_WHITE, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3090 O24G", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3090_O24G, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3090 O24G OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3090_O24G_OC, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 3090Ti O24G OC GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3090TI_O24G_OC_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 4070 Ti 12G Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4070TI_12G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 4070 Ti O12G Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4070TI_O12G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 4080 16G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4080_16G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 4080 O16G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4080_O16G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 4080 O16G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4080_O16G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 4080 O16G OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4080_O16G_OC_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 4090 O24G OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4090_O24G_OC_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RTX 4090 O24G", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4090_O24G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 4090 O24G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4090_O24G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RTX 4090 24G GAMING", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4090_24G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3050 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3050_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX3050_8G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS KO GeForce RTX 3060 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, ASUS_SUB_VEN, ASUS_KO_RTX_3060_OC_O12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3060 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3060_O12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3060 V2 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3060_O12G_V2_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3060 V2 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3060_O12G_LHR_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3060 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3060_12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3060 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3060_O12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3060 V2 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3060_O12G_LHR_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS KO GeForce RTX 3060 V2 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, ASUS_SUB_VEN, ASUS_KO_RTX_3060_O12G_V2_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS KO GeForce RTX 3060 Ti V2 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, ASUS_SUB_VEN, ASUS_KO_RTX3060TI_O8G_V2_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3060 Ti OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_GDDR6X_DEV,ASUS_SUB_VEN, ASUS_TUF_RTX_3060TI_O8G, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS KO GeForce RTX 3060 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, ASUS_SUB_VEN, ASUS_KO_RTX3060TI_O8G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS KO GeForce RTX 3060 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, ASUS_SUB_VEN, ASUS_KO_RTX3060TI_08G_GAMING_2, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3060 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3060TI_O8G_OC, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3060 Ti OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3060TI_O8G_OC, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3060 Ti OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3060TI_O8G_OC_V2, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3060 Ti V2 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3060TI_O8G_V2_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3070 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3070_OC, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3070 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3070_O8G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3070 White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3070_O8G_WHITE, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3070 V2 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3070_8G_V2_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3070 V2 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3070_O8G_V2_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3070 V2 White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3070_O8G_V2_WHITE, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3070 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3070_8G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3070 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3070_O8G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS KO GeForce RTX 3070 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, ASUS_SUB_VEN, ASUS_KO_RTX_3070_O8G_GAMING_V1, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS KO GeForce RTX 3070 V2 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, ASUS_SUB_VEN, ASUS_KO_RTX_3070_O8G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS KO GeForce RTX 3070 V2 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, ASUS_SUB_VEN, ASUS_KO_RTX_3070_O8G_GAMING_V2, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3070 V2 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3070_O8G_V2_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3070 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3070TI_O8G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3070 Ti V2 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3070TI_O8G_V2_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3070 Ti V2 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_GA102_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3070TI_O8G_V2_GAMING_2, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3070 Ti V2 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_GA102_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3070TI_O8G_V2_GAMING_3, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3070 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3070TI_O8G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3080 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080_10G_GAMING_PD, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3080 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080_10G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG GeForce RTX 3080 GUNDAM EDITION", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080_10G_GUNDAM_EDITION, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3080 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080_O10G_OC, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3080 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_10G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3080 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_O10G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3080 White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_O10G_WHITE, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3080 V2 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_10G_V2_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3080 V2 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_O10G_V2_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3080 V2 White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_O10G_V2_WHITE, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3080 V2 Gaming OC ", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080_O10G_V2_GAMING_8822, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3080 V2 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080_O10G_V2_GAMING_882B, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3080 V2 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080_O10G_V2_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3080 12G Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080_12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3080 12G Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080_O12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3080 12G", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_12G, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3080 12G OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_O12G_OC, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3080 12G OC EVA EDITION", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080_O12G_EVA, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3090 OC EVA EDITION", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3090_O24G_EVA, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3090 GUNDAM EDITION", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3090_GUNDAM_EDITION, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3080 Ti Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080TI_12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3080 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3080TI_O12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG GeForce RTX STRIX 3080 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080TI_O12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX LC GeForce RTX 3080 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3080TI_O12G_GAMING_LC, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3090 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3090_24G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3090 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3090_24G_GAMING_V2, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3090 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3090_O24G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 3090 Gaming White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_3090_O24G_GAMING_WHITE, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3090 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3090_O24G, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3090 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3090_O24G_OC, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3090 Ti Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3090TI_24G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 3090 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_3090TI_O24G_OC_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX LC GeForce RTX 3090 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_LC_RTX_3090TI_O24G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4060 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4060TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4060TI_O8G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4060 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4060_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4060_O8G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4060 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4060TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4060TI_O8G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4070 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4070_12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4070 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4070_O12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4070 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4070_O12G_GAMING_2, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4070 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4070_O12G_GAMING_3, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4070 SUPER Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4070S_12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4070 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4070_O12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4070 SUPER Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4070S_12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4070 SUPER Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4070S_O12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4070 Ti Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4070TI_12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4070 Ti Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4070TI_12G_GAMING_88DD, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4070 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4070TI_O12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4070 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4070TI_O12G_GAMING_88DC, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4070 Ti Gaming White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4070TI_O12G_GAMING_WHITE, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4070 Ti SUPER Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4070TI_SUPER_16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4070 Ti SUPER Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4070TI_SUPER_O16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4070 Ti SUPER Gaming White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4070TI_SUPER_O16G_GAMING_WHITE, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4070 Ti Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4070TI_12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4070 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4070TI_O12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4070 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4070TI_O12G_GAMING_2, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4070 Ti SUPER Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4070TI_SUPER_16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4070 Ti SUPER Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4070TI_SUPER_O16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4080 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4080_16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4080 Gaming White", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4080_16G_GAMING_WHITE, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4080 Gaming White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4080_O16G_GAMING_WHITE, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4080 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4080_O16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4080 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4080_O16G_GAMING_2, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4080 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4080_16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4080 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4080_16G_GAMING_2, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4080 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4080_O16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4080 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4080_O16G_OC_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4080 SUPER Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080S_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4080S_16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4080 SUPER OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4080S_016G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4080 SUPER White", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4080S_16G_GAMING_WHITE, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4080 SUPER White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080S_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4080S_016G_GAMING_WHITE, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4080 SUPER Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080S_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4080S_O16G_OC_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4080 SUPER Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080S_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4080S_O16G_OC_GAMING_2, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4090 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4090_O24G_OC_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4090 Gaming OG OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4090_O24G_OG_OC_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4090 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4090_O24G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4090 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4090_O24G_GAMING_2, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 4090 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_4090_O24G_GAMING_3, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX LC GeForce RTX 4090 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_LC_RTX_4090_O24G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4090 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4090_24G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4090 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4090_O24G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4090 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4090_O24G_GAMING_213S, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4090 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4090_24G_GAMING_88F0, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4090 OC EVA-02", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4090_024G_EVA_02, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4090 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4090_O24G_GAMING_8932, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4090 Gaming White", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4090_24G_GAMING_WHITE, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4090 Gaming White", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4090_24G_GAMING_WHITE_2, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4090 Gaming White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4090_O24G_GAMING_WHITE, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 4090 Gaming White OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_4090_O24G_GAMING_WHITE_2, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG MATRIX PLATINUM GeForce RTX 4090", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ASUS_SUB_VEN, ASUS_ROG_MATRIX_PLATINUM_RTX_4090_24G, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5070 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5070_O12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5070 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5070TI_O16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX GeForce RTX 5070 Ti Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RTX_5070TI_O16G_GAMING_OC, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5080 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5080_O16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5090 Gaming OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5090_O32G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF GeForce RTX 5090 Gaming", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_TUF_RTX_5090_32G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5080 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5080_O16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5080", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5080_16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5090 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5090 OC BTF", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING_BTF, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL GeForce RTX 5090 OC WHITE", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_RTX_5090_O32G_GAMING_WHITE, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG ASTRAL LC GeForce RTX 5090 OC", DetectENESMBusGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, ASUS_SUB_VEN, ASUS_ROG_ASTRAL_LC_RTX_5090_O32G_GAMING, 0x67); /*-----------------------------------------*\ | AMD GPUs | \*-----------------------------------------*/ -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RX 6700XT O12G GAMING", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_6700XT_O12G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RX 6700XT O12G GAMING", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RX_6700XT_O12G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RX 6750XT O12G GAMING", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RX_6750XT_O12G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS RX 6800 TUF Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, ASUS_SUB_VEN, ASUS_RX6800_TUF_GAMING_OC, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX RX 6800 O16G Gaming", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, ASUS_SUB_VEN, ASUS_ROG_STRIX_RX_6800_O16G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RX 6800XT O16G GAMING", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, ASUS_SUB_VEN, ASUS_TUF_RX_6800XT_O16G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX LC RX 6800XT O16G GAMING", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, ASUS_SUB_VEN, ASUS_ROG_STRIX_LC_RX6800XT_O16G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX LC RX 6900XT O16G GAMING", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, ASUS_SUB_VEN, ASUS_ROG_STRIX_LC_RX6900XT_O16G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX LC RX 6900XT O16G GAMING TOP",DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV2, ASUS_SUB_VEN, ASUS_ROG_STRIX_LC_RX6900XT_O16G_GAMING_TOP, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RX 6900XT O16G GAMING", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, ASUS_SUB_VEN, ASUS_TUF_RX_6900XT_O16G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RX 6900XT T16G GAMING", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV2, ASUS_SUB_VEN, ASUS_TUF_RX_6900XT_T16G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS TUF RX 6950XT O16G GAMING", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV3, ASUS_SUB_VEN, ASUS_TUF_RX_6950XT_016G_GAMING, 0x67); -REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX LC RX 6950XT O16G GAMING", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV3, ASUS_SUB_VEN, ASUS_ROG_STRIX_LC_RX_6950XT_O16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 6600 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI23_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RX_6600XT_O8G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 6650 XT Gaming", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI23_DEV1, ASUS_SUB_VEN, ASUS_ROG_STRIX_RX_6650XT_O8G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 6700 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_6700XT_O12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 6700 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RX_6700XT_O12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 6750 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, ASUS_SUB_VEN, ASUS_ROG_STRIX_RX_6750XT_O12G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 6800 Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, ASUS_SUB_VEN, ASUS_RX6800_TUF_GAMING_OC, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX Radeon RX 6800 Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, ASUS_SUB_VEN, ASUS_ROG_STRIX_RX_6800_O16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 6800 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, ASUS_SUB_VEN, ASUS_TUF_RX_6800XT_O16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX LC Radeon RX 6800 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, ASUS_SUB_VEN, ASUS_ROG_STRIX_LC_RX6800XT_O16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX LC Radeon RX 6900 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, ASUS_SUB_VEN, ASUS_ROG_STRIX_LC_RX6900XT_O16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX LC Radeon RX 6900 XT Gaming OC TOP", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV2, ASUS_SUB_VEN, ASUS_ROG_STRIX_LC_RX6900XT_O16G_GAMING_TOP, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 6900 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, ASUS_SUB_VEN, ASUS_TUF_RX_6900XT_O16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 6900 XT T16G Gaming", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV2, ASUS_SUB_VEN, ASUS_TUF_RX_6900XT_T16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 6950 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV3, ASUS_SUB_VEN, ASUS_TUF_RX_6950XT_016G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS ROG STRIX LC Radeon RX 6950 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV3, ASUS_SUB_VEN, ASUS_ROG_STRIX_LC_RX_6950XT_O16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 7600 XT O16G Gaming", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI33_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_7600XT_O16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 7700 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI32_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_7700XT_012G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 7800 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI32_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_7800XT_O16G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 7800 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI32_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_7800XT_O16G_GAMING_0606, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 7800 XT Gaming White OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI32_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_7800XT_O16G_WHITE_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 7900 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_7900XT_020G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 7900 XTX Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_7900XTX_O24G_GAMING, 0x67); +REGISTER_I2C_PCI_DETECTOR("ASUS TUF Radeon RX 9070 XT Gaming OC", DetectENESMBusGPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, ASUS_SUB_VEN, ASUS_TUF_RX_9070XT_016G_GAMING, 0x67); diff --git a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface.h b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface.h index 7a2062d6..be1371aa 100644 --- a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface.h +++ b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface.h @@ -1,26 +1,41 @@ -/*-----------------------------------------*\ -| ENESMBusInterface.h | -| | -| Definitions and types for ENE interface | -| | -| Adam Honse (CalcProgrammer1) 11/21/2021 | -\*-----------------------------------------*/ - -#include +/*---------------------------------------------------------*\ +| ENESMBusInterface.h | +| | +| ENE SMBus interface | +| | +| Adam Honse (CalcProgrammer1) 21 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include + typedef unsigned short ene_register; typedef unsigned char ene_dev_id; +typedef unsigned int ene_interface_type; + +/*-----------------------------------------*\ +| Known interface types | +\*-----------------------------------------*/ +enum +{ + ENE_INTERFACE_TYPE_I2C_SMBUS, + ENE_INTERFACE_TYPE_SPECTRIX_S40G, + ENE_INTERFACE_TYPE_ROG_ARION, +}; class ENESMBusInterface { public: - virtual ~ENESMBusInterface() = default; + virtual ~ENESMBusInterface() = default; - virtual std::string GetLocation() = 0; - virtual int GetMaxBlock() = 0; - virtual unsigned char ENERegisterRead(ene_dev_id dev, ene_register reg) = 0; - virtual void ENERegisterWrite(ene_dev_id dev, ene_register reg, unsigned char val) = 0; - virtual void ENERegisterWriteBlock(ene_dev_id dev, ene_register reg, unsigned char * data, unsigned char sz) = 0; + virtual ene_interface_type GetInterfaceType() = 0; + virtual std::string GetLocation() = 0; + virtual int GetMaxBlock() = 0; + virtual unsigned char ENERegisterRead(ene_dev_id dev, ene_register reg) = 0; + virtual void ENERegisterWrite(ene_dev_id dev, ene_register reg, unsigned char val) = 0; + virtual void ENERegisterWriteBlock(ene_dev_id dev, ene_register reg, unsigned char * data, unsigned char sz) = 0; }; diff --git a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_ROGArion.cpp b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_ROGArion.cpp new file mode 100644 index 00000000..f4fb3bf6 --- /dev/null +++ b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_ROGArion.cpp @@ -0,0 +1,96 @@ +/*---------------------------------------------------------*\ +| ENESMBusInterface_ROGArion.cpp | +| | +| ENE SMBus interface for ASUS ROG Arion | +| | +| Adam Honse (CalcProgrammer1) 17 Sep 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "ENESMBusInterface_ROGArion.h" + +ENESMBusInterface_ROGArion::ENESMBusInterface_ROGArion(scsi_device* dev_handle, char* dev_path) +{ + scsi_dev = dev_handle; + path = dev_path; +} + +ENESMBusInterface_ROGArion::~ENESMBusInterface_ROGArion() +{ + +} + +ene_interface_type ENESMBusInterface_ROGArion::GetInterfaceType() +{ + return(ENE_INTERFACE_TYPE_ROG_ARION); +} + +std::string ENESMBusInterface_ROGArion::GetLocation() +{ + std::string str(path.begin(), path.end()); + return("SCSI: " + str); +} + +int ENESMBusInterface_ROGArion::GetMaxBlock() +{ + return(24); +} + +unsigned char ENESMBusInterface_ROGArion::ENERegisterRead(ene_dev_id /*dev*/, ene_register /*reg*/) +{ + /*-----------------------------------------------------------------------------*\ + | This interface does not support reading | + \*-----------------------------------------------------------------------------*/ + return( 0 ); +} + +void ENESMBusInterface_ROGArion::ENERegisterWrite(ene_dev_id /*dev*/, ene_register reg, unsigned char val) +{ + SendPacket(reg, &val, sizeof(unsigned char)); +} + +void ENESMBusInterface_ROGArion::ENERegisterWriteBlock(ene_dev_id /*dev*/, ene_register reg, unsigned char * data, unsigned char sz) +{ + SendPacket(reg, data, sz); +} + +void ENESMBusInterface_ROGArion::SendPacket + ( + ene_register reg, + unsigned char * packet, + unsigned char packet_sz + ) +{ + /*-----------------------------------------------------------------------------*\ + | Create buffer to hold CDB | + \*-----------------------------------------------------------------------------*/ + unsigned char cdb[16] = {0}; + cdb[0] = 0xEC; + cdb[1] = 0x41; + cdb[2] = 0x53; + cdb[3] = ((reg >> 8) & 0x00FF); + cdb[4] = ( reg & 0x00FF ); + cdb[5] = 0x00; + cdb[6] = 0x00; + cdb[7] = 0x00; + cdb[8] = 0x00; + cdb[9] = 0x00; + cdb[10] = 0x00; + cdb[11] = 0x00; + cdb[12] = 0x00; + cdb[13] = packet_sz; + cdb[14] = 0x00; + cdb[15] = 0x00; + + /*-----------------------------------------------------------------------------*\ + | Create buffer to hold sense data | + \*-----------------------------------------------------------------------------*/ + unsigned char sense[32] = {0}; + + /*-----------------------------------------------------------------------------*\ + | Write SCSI packet | + \*-----------------------------------------------------------------------------*/ + scsi_write(scsi_dev, packet, packet_sz, cdb, 16, sense, 32); +} diff --git a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_ROGArion.h b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_ROGArion.h new file mode 100644 index 00000000..95aef59e --- /dev/null +++ b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_ROGArion.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------*\ +| ENESMBusInterface_ROGArion.h | +| | +| ENE SMBus interface for ASUS ROG Arion | +| | +| Adam Honse (CalcProgrammer1) 17 Sep 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "ENESMBusInterface.h" +#include "scsiapi.h" + +class ENESMBusInterface_ROGArion : public ENESMBusInterface +{ +public: + ENESMBusInterface_ROGArion(scsi_device* dev_handle, char* dev_path); + ~ENESMBusInterface_ROGArion(); + + ene_interface_type GetInterfaceType(); + std::string GetLocation(); + int GetMaxBlock(); + unsigned char ENERegisterRead(ene_dev_id dev, ene_register reg); + void ENERegisterWrite(ene_dev_id dev, ene_register reg, unsigned char val); + void ENERegisterWriteBlock(ene_dev_id dev, ene_register reg, unsigned char * data, unsigned char sz); + +private: + scsi_device* scsi_dev; + std::string path; + + void SendPacket + ( + ene_register reg, + unsigned char * packet, + unsigned char packet_sz + ); +}; diff --git a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G.cpp b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G.cpp deleted file mode 100644 index 17080edb..00000000 --- a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G.cpp +++ /dev/null @@ -1,208 +0,0 @@ -/*-----------------------------------------*\ -| ENESMBusInterface_SpectrixS40G.cpp | -| | -| Code for ENE XPG Spectrix S40G NVMe | -| interface | -| | -| Adam Honse (CalcProgrammer1) 11/21/2021 | -\*-----------------------------------------*/ - -#include "ENESMBusInterface_SpectrixS40G.h" -#include -#include -#include - -/*---------------------------------------------------------------------*\ -| Functions for submitting NVME admin passthrough command taken from | -| libnvme: https://github.com/linux-nvme/libnvme | -\*---------------------------------------------------------------------*/ - -#define NVME_IOCTL_ADMIN_CMD _IOWR('N', 0x41, struct nvme_passthru_cmd) - -struct nvme_passthru_cmd -{ - uint8_t opcode; - uint8_t flags; - uint16_t rsvd1; - uint32_t nsid; - uint32_t cdw2; - uint32_t cdw3; - uint64_t metadata; - uint64_t addr; - uint32_t metadata_len; - uint32_t data_len; - uint32_t cdw10; - uint32_t cdw11; - uint32_t cdw12; - uint32_t cdw13; - uint32_t cdw14; - uint32_t cdw15; - uint32_t timeout_ms; - uint32_t result; -}; - -static int nvme_submit_passthru(int fd, unsigned long ioctl_cmd, - struct nvme_passthru_cmd *cmd, uint32_t *result) -{ - int err = ioctl(fd, ioctl_cmd, cmd); - - if (err >= 0 && result) - *result = cmd->result; - return err; -} - -static int nvme_passthru(int fd, unsigned long ioctl_cmd, uint8_t opcode, - uint8_t flags, uint16_t rsvd, uint32_t nsid, uint32_t cdw2, - uint32_t cdw3, uint32_t cdw10, uint32_t cdw11, uint32_t cdw12, - uint32_t cdw13, uint32_t cdw14, uint32_t cdw15, uint32_t data_len, - void *data, uint32_t metadata_len, void *metadata, - uint32_t timeout_ms, uint32_t *result) -{ - struct nvme_passthru_cmd cmd = { - .opcode = opcode, - .flags = flags, - .rsvd1 = rsvd, - .nsid = nsid, - .cdw2 = cdw2, - .cdw3 = cdw3, - .metadata = (uint64_t)(uintptr_t)metadata, - .addr = (uint64_t)(uintptr_t)data, - .metadata_len = metadata_len, - .data_len = data_len, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw13 = cdw13, - .cdw14 = cdw14, - .cdw15 = cdw15, - .timeout_ms = timeout_ms, - .result = 0, - }; - - return nvme_submit_passthru(fd, ioctl_cmd, &cmd, result); -} - -int nvme_admin_passthru(int fd, uint8_t opcode, uint8_t flags, uint16_t rsvd, - uint32_t nsid, uint32_t cdw2, uint32_t cdw3, uint32_t cdw10, - uint32_t cdw11, uint32_t cdw12, uint32_t cdw13, uint32_t cdw14, - uint32_t cdw15, uint32_t data_len, void *data, - uint32_t metadata_len, void *metadata, uint32_t timeout_ms, - uint32_t *result) -{ - return nvme_passthru(fd, NVME_IOCTL_ADMIN_CMD, opcode, flags, rsvd, - nsid, cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, - cdw14, cdw15, data_len, data, metadata_len, - metadata, timeout_ms, result); -} - -/*---------------------------------------------------------------------*\ -| ENESMBusInterface_SpectrixS40G implementation | -\*---------------------------------------------------------------------*/ - -ENESMBusInterface_SpectrixS40G::ENESMBusInterface_SpectrixS40G(int fd, char* path) -{ - this->nvme_fd = fd; - this->path = path; -} - -ENESMBusInterface_SpectrixS40G::~ENESMBusInterface_SpectrixS40G() -{ - -} - -std::string ENESMBusInterface_SpectrixS40G::GetLocation() -{ - return("NVMe: " + path); -} - -int ENESMBusInterface_SpectrixS40G::GetMaxBlock() -{ - return(24); -} - -unsigned char ENESMBusInterface_SpectrixS40G::ENERegisterRead(ene_dev_id dev, ene_register reg) -{ - struct nvme_passthru_cmd cfg; - - memset(&cfg, 0, sizeof(nvme_passthru_cmd)); - - unsigned short corrected_reg = ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF); - - cfg.opcode = 0xFA; - cfg.cdw12 = (corrected_reg << 16) | (dev << 1); - cfg.cdw13 = 0x81100001; - cfg.data_len = 1; - - unsigned char data[1]; - unsigned char metadata[1]; - unsigned int result; - - /*-----------------------------------------------------------------------------*\ - | Send the command to the device | - \*-----------------------------------------------------------------------------*/ - nvme_admin_passthru(nvme_fd, cfg.opcode, cfg.flags, cfg.rsvd1, - cfg.nsid, cfg.cdw2, cfg.cdw3, cfg.cdw10, - cfg.cdw11, cfg.cdw12, cfg.cdw13, cfg.cdw14, - cfg.cdw15, cfg.data_len, data, cfg.metadata_len, - metadata, cfg.timeout_ms, &result); - - return(data[0]); -} - -void ENESMBusInterface_SpectrixS40G::ENERegisterWrite(ene_dev_id dev, ene_register reg, unsigned char val) -{ - struct nvme_passthru_cmd cfg; - - memset(&cfg, 0, sizeof(nvme_passthru_cmd)); - - unsigned short corrected_reg = ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF); - - cfg.opcode = 0xFB; - cfg.cdw12 = (corrected_reg << 16) | (dev << 1); - cfg.cdw13 = 0x01100001; - cfg.data_len = 1; - - unsigned char data[1]; - - data[0] = val; - - unsigned char metadata[1]; - unsigned int result; - - /*-----------------------------------------------------------------------------*\ - | Send the command to the device | - \*-----------------------------------------------------------------------------*/ - nvme_admin_passthru(nvme_fd, cfg.opcode, cfg.flags, cfg.rsvd1, - cfg.nsid, cfg.cdw2, cfg.cdw3, cfg.cdw10, - cfg.cdw11, cfg.cdw12, cfg.cdw13, cfg.cdw14, - cfg.cdw15, cfg.data_len, data, cfg.metadata_len, - metadata, cfg.timeout_ms, &result); - -} - -void ENESMBusInterface_SpectrixS40G::ENERegisterWriteBlock(ene_dev_id dev, ene_register reg, unsigned char * data, unsigned char sz) -{ - struct nvme_passthru_cmd cfg; - - memset(&cfg, 0, sizeof(nvme_passthru_cmd)); - - unsigned short corrected_reg = ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF); - - cfg.opcode = 0xFB; - cfg.cdw12 = (corrected_reg << 16) | (dev << 1); - cfg.cdw13 = 0x03100000 | sz; - cfg.data_len = sz; - - unsigned char metadata[1]; - unsigned int result; - - /*-----------------------------------------------------------------------------*\ - | Send the command to the device | - \*-----------------------------------------------------------------------------*/ - nvme_admin_passthru(nvme_fd, cfg.opcode, cfg.flags, cfg.rsvd1, - cfg.nsid, cfg.cdw2, cfg.cdw3, cfg.cdw10, - cfg.cdw11, cfg.cdw12, cfg.cdw13, cfg.cdw14, - cfg.cdw15, cfg.data_len, data, cfg.metadata_len, - metadata, cfg.timeout_ms, &result); - -} diff --git a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G.h b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G.h deleted file mode 100644 index e0f6d067..00000000 --- a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G.h +++ /dev/null @@ -1,29 +0,0 @@ -/*-----------------------------------------*\ -| ENESMBusInterface_SpectrixS40G.h | -| | -| Definitions and types for ENE XPG | -| Spectrix S40G NVMe interface | -| | -| Adam Honse (CalcProgrammer1) 11/21/2021 | -\*-----------------------------------------*/ - -#include "ENESMBusInterface.h" - -#pragma once - -class ENESMBusInterface_SpectrixS40G : public ENESMBusInterface -{ -public: - ENESMBusInterface_SpectrixS40G(int fd, char* path); - ~ENESMBusInterface_SpectrixS40G(); - - std::string GetLocation(); - int GetMaxBlock(); - unsigned char ENERegisterRead(ene_dev_id dev, ene_register reg); - void ENERegisterWrite(ene_dev_id dev, ene_register reg, unsigned char val); - void ENERegisterWriteBlock(ene_dev_id dev, ene_register reg, unsigned char * data, unsigned char sz); - -private: - int nvme_fd; - std::string path; -}; diff --git a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Linux.cpp b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Linux.cpp new file mode 100644 index 00000000..fcd4e306 --- /dev/null +++ b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Linux.cpp @@ -0,0 +1,215 @@ +/*---------------------------------------------------------*\ +| ENESMBusInterface_SpectrixS40G_Linux.cpp | +| | +| ENE SMBus interface for XPG Spectrix S40G (Linux) | +| | +| Adam Honse (CalcProgrammer1) 21 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include "ENESMBusInterface_SpectrixS40G_Linux.h" + +/*---------------------------------------------------------------------*\ +| Functions for submitting NVME admin passthrough command taken from | +| libnvme: https://github.com/linux-nvme/libnvme | +\*---------------------------------------------------------------------*/ + +#define NVME_IOCTL_ADMIN_CMD _IOWR('N', 0x41, struct nvme_passthru_cmd) + +struct nvme_passthru_cmd +{ + uint8_t opcode; + uint8_t flags; + uint16_t rsvd1; + uint32_t nsid; + uint32_t cdw2; + uint32_t cdw3; + uint64_t metadata; + uint64_t addr; + uint32_t metadata_len; + uint32_t data_len; + uint32_t cdw10; + uint32_t cdw11; + uint32_t cdw12; + uint32_t cdw13; + uint32_t cdw14; + uint32_t cdw15; + uint32_t timeout_ms; + uint32_t result; +}; + +static int nvme_submit_passthru(int fd, unsigned long ioctl_cmd, + struct nvme_passthru_cmd *cmd, uint32_t *result) +{ + int err = ioctl(fd, ioctl_cmd, cmd); + + if (err >= 0 && result) + *result = cmd->result; + return err; +} + +static int nvme_passthru(int fd, unsigned long ioctl_cmd, uint8_t opcode, + uint8_t flags, uint16_t rsvd, uint32_t nsid, uint32_t cdw2, + uint32_t cdw3, uint32_t cdw10, uint32_t cdw11, uint32_t cdw12, + uint32_t cdw13, uint32_t cdw14, uint32_t cdw15, uint32_t data_len, + void *data, uint32_t metadata_len, void *metadata, + uint32_t timeout_ms, uint32_t *result) +{ + struct nvme_passthru_cmd cmd = { + .opcode = opcode, + .flags = flags, + .rsvd1 = rsvd, + .nsid = nsid, + .cdw2 = cdw2, + .cdw3 = cdw3, + .metadata = (uint64_t)(uintptr_t)metadata, + .addr = (uint64_t)(uintptr_t)data, + .metadata_len = metadata_len, + .data_len = data_len, + .cdw10 = cdw10, + .cdw11 = cdw11, + .cdw12 = cdw12, + .cdw13 = cdw13, + .cdw14 = cdw14, + .cdw15 = cdw15, + .timeout_ms = timeout_ms, + .result = 0, + }; + + return nvme_submit_passthru(fd, ioctl_cmd, &cmd, result); +} + +int nvme_admin_passthru(int fd, uint8_t opcode, uint8_t flags, uint16_t rsvd, + uint32_t nsid, uint32_t cdw2, uint32_t cdw3, uint32_t cdw10, + uint32_t cdw11, uint32_t cdw12, uint32_t cdw13, uint32_t cdw14, + uint32_t cdw15, uint32_t data_len, void *data, + uint32_t metadata_len, void *metadata, uint32_t timeout_ms, + uint32_t *result) +{ + return nvme_passthru(fd, NVME_IOCTL_ADMIN_CMD, opcode, flags, rsvd, + nsid, cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, + cdw14, cdw15, data_len, data, metadata_len, + metadata, timeout_ms, result); +} + +/*---------------------------------------------------------------------*\ +| ENESMBusInterface_SpectrixS40G implementation | +\*---------------------------------------------------------------------*/ + +ENESMBusInterface_SpectrixS40G::ENESMBusInterface_SpectrixS40G(int fd, char* path) +{ + this->nvme_fd = fd; + this->path = path; +} + +ENESMBusInterface_SpectrixS40G::~ENESMBusInterface_SpectrixS40G() +{ + +} + +ene_interface_type ENESMBusInterface_SpectrixS40G::GetInterfaceType() +{ + return(ENE_INTERFACE_TYPE_SPECTRIX_S40G); +} + +std::string ENESMBusInterface_SpectrixS40G::GetLocation() +{ + return("NVMe: " + path); +} + +int ENESMBusInterface_SpectrixS40G::GetMaxBlock() +{ + return(24); +} + +unsigned char ENESMBusInterface_SpectrixS40G::ENERegisterRead(ene_dev_id dev, ene_register reg) +{ + struct nvme_passthru_cmd cfg; + + memset(&cfg, 0, sizeof(nvme_passthru_cmd)); + + unsigned short corrected_reg = ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF); + + cfg.opcode = 0xFA; + cfg.cdw12 = (corrected_reg << 16) | (dev << 1); + cfg.cdw13 = 0x81100001; + cfg.data_len = 1; + + unsigned char data[1]; + unsigned char metadata[1]; + unsigned int result; + + /*-----------------------------------------------------------------------------*\ + | Send the command to the device | + \*-----------------------------------------------------------------------------*/ + nvme_admin_passthru(nvme_fd, cfg.opcode, cfg.flags, cfg.rsvd1, + cfg.nsid, cfg.cdw2, cfg.cdw3, cfg.cdw10, + cfg.cdw11, cfg.cdw12, cfg.cdw13, cfg.cdw14, + cfg.cdw15, cfg.data_len, data, cfg.metadata_len, + metadata, cfg.timeout_ms, &result); + + return(data[0]); +} + +void ENESMBusInterface_SpectrixS40G::ENERegisterWrite(ene_dev_id dev, ene_register reg, unsigned char val) +{ + struct nvme_passthru_cmd cfg; + + memset(&cfg, 0, sizeof(nvme_passthru_cmd)); + + unsigned short corrected_reg = ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF); + + cfg.opcode = 0xFB; + cfg.cdw12 = (corrected_reg << 16) | (dev << 1); + cfg.cdw13 = 0x01100001; + cfg.data_len = 1; + + unsigned char data[1]; + + data[0] = val; + + unsigned char metadata[1]; + unsigned int result; + + /*-----------------------------------------------------------------------------*\ + | Send the command to the device | + \*-----------------------------------------------------------------------------*/ + nvme_admin_passthru(nvme_fd, cfg.opcode, cfg.flags, cfg.rsvd1, + cfg.nsid, cfg.cdw2, cfg.cdw3, cfg.cdw10, + cfg.cdw11, cfg.cdw12, cfg.cdw13, cfg.cdw14, + cfg.cdw15, cfg.data_len, data, cfg.metadata_len, + metadata, cfg.timeout_ms, &result); + +} + +void ENESMBusInterface_SpectrixS40G::ENERegisterWriteBlock(ene_dev_id dev, ene_register reg, unsigned char * data, unsigned char sz) +{ + struct nvme_passthru_cmd cfg; + + memset(&cfg, 0, sizeof(nvme_passthru_cmd)); + + unsigned short corrected_reg = ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF); + + cfg.opcode = 0xFB; + cfg.cdw12 = (corrected_reg << 16) | (dev << 1); + cfg.cdw13 = 0x03100000 | sz; + cfg.data_len = sz; + + unsigned char metadata[1]; + unsigned int result; + + /*-----------------------------------------------------------------------------*\ + | Send the command to the device | + \*-----------------------------------------------------------------------------*/ + nvme_admin_passthru(nvme_fd, cfg.opcode, cfg.flags, cfg.rsvd1, + cfg.nsid, cfg.cdw2, cfg.cdw3, cfg.cdw10, + cfg.cdw11, cfg.cdw12, cfg.cdw13, cfg.cdw14, + cfg.cdw15, cfg.data_len, data, cfg.metadata_len, + metadata, cfg.timeout_ms, &result); + +} diff --git a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Linux.h b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Linux.h new file mode 100644 index 00000000..45d9057d --- /dev/null +++ b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Linux.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------*\ +| ENESMBusInterface_SpectrixS40G_Linux.h | +| | +| ENE SMBus interface for XPG Spectrix S40G (Linux) | +| | +| Adam Honse (CalcProgrammer1) 21 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "ENESMBusInterface.h" + +class ENESMBusInterface_SpectrixS40G : public ENESMBusInterface +{ +public: + ENESMBusInterface_SpectrixS40G(int fd, char* path); + ~ENESMBusInterface_SpectrixS40G(); + + ene_interface_type GetInterfaceType(); + std::string GetLocation(); + int GetMaxBlock(); + unsigned char ENERegisterRead(ene_dev_id dev, ene_register reg); + void ENERegisterWrite(ene_dev_id dev, ene_register reg, unsigned char val); + void ENERegisterWriteBlock(ene_dev_id dev, ene_register reg, unsigned char * data, unsigned char sz); + +private: + int nvme_fd; + std::string path; +}; diff --git a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Windows.cpp b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Windows.cpp index d9c05412..35b1cf0b 100644 --- a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Windows.cpp +++ b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Windows.cpp @@ -1,18 +1,21 @@ -/*-----------------------------------------*\ -| ENESMBusInterface_SpectrixS40G_Windows | -| | -| Code for ENE XPG Spectrix S40G NVMe | -| interface | -| Windows implementation | -| | -| Adam Honse (CalcProgrammer1) 11/21/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| ENESMBusInterface_SpectrixS40G_Windows.cpp | +| | +| ENE SMBus interface for XPG Spectrix S40G (Windows) | +| | +| Adam Honse (CalcProgrammer1) 21 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include #include "ENESMBusInterface_SpectrixS40G_Windows.h" - -#include -#include -#include +#include "StringUtils.h" ENESMBusInterface_SpectrixS40G::ENESMBusInterface_SpectrixS40G(HANDLE fd, wchar_t* path) { @@ -25,10 +28,14 @@ ENESMBusInterface_SpectrixS40G::~ENESMBusInterface_SpectrixS40G() } +ene_interface_type ENESMBusInterface_SpectrixS40G::GetInterfaceType() +{ + return(ENE_INTERFACE_TYPE_SPECTRIX_S40G); +} + std::string ENESMBusInterface_SpectrixS40G::GetLocation() { - std::string str(path.begin(), path.end()); - return("NVMe: " + str); + return("NVMe: " + StringUtils::wstring_to_string(path)); } int ENESMBusInterface_SpectrixS40G::GetMaxBlock() @@ -96,10 +103,7 @@ unsigned char ENESMBusInterface_SpectrixS40G::ENERegisterRead(ene_dev_id dev, en | Send the STORAGE_PROTOCOL_COMMAND to the device | \*-----------------------------------------------------------------------------*/ DWORD bytesreturned = 0; - while(bytesreturned != sizeof(buffer)) - { - DeviceIoControl(nvme_fd, IOCTL_STORAGE_PROTOCOL_COMMAND, buffer, sizeof(buffer), buffer, sizeof(buffer), &bytesreturned, (LPOVERLAPPED)0x0); - } + DeviceIoControl(nvme_fd, IOCTL_STORAGE_PROTOCOL_COMMAND, buffer, sizeof(buffer), buffer, sizeof(buffer), &bytesreturned, (LPOVERLAPPED)0x0); /*-----------------------------------------------------------------------------*\ | Copy the ENE Register Write extra data into the STORAGE_PROTOCOL_COMMAND | @@ -110,6 +114,7 @@ unsigned char ENESMBusInterface_SpectrixS40G::ENERegisterRead(ene_dev_id dev, en return((unsigned char)ExtraValue[16]); } + return(0); } void ENESMBusInterface_SpectrixS40G::ENERegisterWrite(ene_dev_id dev, ene_register reg, unsigned char val) diff --git a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Windows.h b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Windows.h index d6eeec4d..ad530c6a 100644 --- a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Windows.h +++ b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Windows.h @@ -1,29 +1,31 @@ -/*-----------------------------------------*\ -| ENESMBusInterface_SpectrixS40G_Windows.h | -| | -| Definitions and types for ENE XPG | -| Spectrix S40G NVMe interface | -| Windows implementation | -| | -| Adam Honse (CalcProgrammer1) 11/21/2021 | -\*-----------------------------------------*/ - -#include "ENESMBusInterface.h" -#include +/*---------------------------------------------------------*\ +| ENESMBusInterface_SpectrixS40G_Windows.h | +| | +| ENE SMBus interface for XPG Spectrix S40G (Windows) | +| | +| Adam Honse (CalcProgrammer1) 21 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include "ENESMBusInterface.h" + class ENESMBusInterface_SpectrixS40G : public ENESMBusInterface { public: ENESMBusInterface_SpectrixS40G(HANDLE fd, wchar_t* path); ~ENESMBusInterface_SpectrixS40G(); - std::string GetLocation(); - int GetMaxBlock(); - unsigned char ENERegisterRead(ene_dev_id dev, ene_register reg); - void ENERegisterWrite(ene_dev_id dev, ene_register reg, unsigned char val); - void ENERegisterWriteBlock(ene_dev_id dev, ene_register reg, unsigned char * data, unsigned char sz); + ene_interface_type GetInterfaceType(); + std::string GetLocation(); + int GetMaxBlock(); + unsigned char ENERegisterRead(ene_dev_id dev, ene_register reg); + void ENERegisterWrite(ene_dev_id dev, ene_register reg, unsigned char val); + void ENERegisterWriteBlock(ene_dev_id dev, ene_register reg, unsigned char * data, unsigned char sz); private: HANDLE nvme_fd; diff --git a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_i2c_smbus.cpp b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_i2c_smbus.cpp index 0bbdb807..b15403aa 100644 --- a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_i2c_smbus.cpp +++ b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_i2c_smbus.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| ENESMBusInterface_i2c_smbus.cpp | -| | -| Code for ENE I2C/SMBus interface | -| | -| Adam Honse (CalcProgrammer1) 11/21/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| ENESMBusInterface_i2c_smbus.cpp | +| | +| ENE SMBus interface for I2C/SMBus | +| | +| Adam Honse (CalcProgrammer1) 21 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "ENESMBusInterface_i2c_smbus.h" @@ -18,6 +21,11 @@ ENESMBusInterface_i2c_smbus::~ENESMBusInterface_i2c_smbus() } +ene_interface_type ENESMBusInterface_i2c_smbus::GetInterfaceType() +{ + return(ENE_INTERFACE_TYPE_I2C_SMBUS); +} + std::string ENESMBusInterface_i2c_smbus::GetLocation() { std::string return_string(bus->device_name); diff --git a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_i2c_smbus.h b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_i2c_smbus.h index 48275f37..8680fa5e 100644 --- a/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_i2c_smbus.h +++ b/Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_i2c_smbus.h @@ -1,28 +1,31 @@ -/*-----------------------------------------*\ -| ENESMBusInterface_i2c_smbus.h | -| | -| Definitions and types for ENE I2C/SMBus | -| interface | -| | -| Adam Honse (CalcProgrammer1) 11/21/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| ENESMBusInterface_i2c_smbus.h | +| | +| ENE SMBus interface for I2C/SMBus | +| | +| Adam Honse (CalcProgrammer1) 21 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include "ENESMBusInterface.h" #include "i2c_smbus.h" -#pragma once - class ENESMBusInterface_i2c_smbus : public ENESMBusInterface { public: ENESMBusInterface_i2c_smbus(i2c_smbus_interface* bus); ~ENESMBusInterface_i2c_smbus(); - std::string GetLocation(); - int GetMaxBlock(); - unsigned char ENERegisterRead(ene_dev_id dev, ene_register reg); - void ENERegisterWrite(ene_dev_id dev, ene_register reg, unsigned char val); - void ENERegisterWriteBlock(ene_dev_id dev, ene_register reg, unsigned char * data, unsigned char sz); + ene_interface_type GetInterfaceType(); + std::string GetLocation(); + int GetMaxBlock(); + unsigned char ENERegisterRead(ene_dev_id dev, ene_register reg); + void ENERegisterWrite(ene_dev_id dev, ene_register reg, unsigned char val); + void ENERegisterWriteBlock(ene_dev_id dev, ene_register reg, unsigned char * data, unsigned char sz); private: i2c_smbus_interface * bus; diff --git a/Controllers/ENESMBusController/RGBController_ENESMBus.cpp b/Controllers/ENESMBusController/RGBController_ENESMBus.cpp index 8858a358..789974f8 100644 --- a/Controllers/ENESMBusController/RGBController_ENESMBus.cpp +++ b/Controllers/ENESMBusController/RGBController_ENESMBus.cpp @@ -1,13 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_ENESMBus.cpp | -| | -| Generic RGB Interface for ENE SMBus | -| | -| Adam Honse (CalcProgrammer1) 6/13/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ENESMBus.cpp | +| | +| RGBController for ENE SMBus devices | +| | +| Adam Honse (CalcProgrammer1) 13 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_ENESMBus.h" #include "LogManager.h" +#include "SettingsManager.h" #include "ResourceManager.h" /**------------------------------------------------------------------*\ @@ -23,17 +27,17 @@ RGBController_ENESMBus::RGBController_ENESMBus(ENESMBusController * controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; /*---------------------------------------------------------*\ | Get ENEController settings | \*---------------------------------------------------------*/ - json ene_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("ENESMBusSettings"); + json ene_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("ENESMBusSettings"); /*---------------------------------------------------------*\ | Check if save to device is enabled | \*---------------------------------------------------------*/ - unsigned int save_flag = 0; + unsigned int save_flag = 0; if(ene_settings.contains("enable_save")) { @@ -47,24 +51,29 @@ RGBController_ENESMBus::RGBController_ENESMBus(ENESMBusController * controller_p | Determine name and type (DRAM or Motherboard) by checking | | the ENE controller's version string | \*---------------------------------------------------------*/ - version = controller->GetDeviceName(); + name = controller->GetName(); + description = "ENE SMBus Device"; + version = controller->GetVersion(); + location = controller->GetLocation(); + type = controller->GetType(); if((version.find("DIMM_LED") != std::string::npos) || (version.find("AUDA") != std::string::npos) ) { - type = DEVICE_TYPE_DRAM; - name = "ENE DRAM"; - vendor = "ENE"; + vendor = "ENE"; + } + else if(version.find("ROG STRIX ARION") != std::string::npos) + { + vendor = "ASUS"; + } + else if(location.find("NVMe:") != std::string::npos) + { + vendor = "XPG"; } else { - type = DEVICE_TYPE_MOTHERBOARD; - name = "ASUS Aura Motherboard"; - vendor = "ASUS"; + vendor = "ASUS"; } - location = controller->GetDeviceLocation(); - description = "ENE SMBus Device"; - mode Direct; Direct.name = "Direct"; Direct.value = 0xFFFF; @@ -228,7 +237,7 @@ int RGBController_ENESMBus::GetDeviceMode() break; } - for(std::size_t mode = 0; mode < modes.size(); mode++) + for(int mode = 0; mode < (int)modes.size(); mode++) { if(modes[mode].value == dev_mode) { @@ -335,7 +344,7 @@ void RGBController_ENESMBus::SetupZones() | Search through all LEDs and create zones for each channel | | type | \*---------------------------------------------------------*/ - for(std::size_t cfg_zone_idx = 0; cfg_zone_idx < ENE_NUM_ZONES; cfg_zone_idx++) + for(unsigned int cfg_zone_idx = 0; cfg_zone_idx < ENE_NUM_ZONES; cfg_zone_idx++) { /*---------------------------------------------------------*\ | Get the number of LEDs in the zone | @@ -416,7 +425,7 @@ void RGBController_ENESMBus::SetupZones() /*---------------------------------------------------------*\ | Create LED entries for each zone | \*---------------------------------------------------------*/ - std::size_t led_idx = 0; + unsigned int led_idx = 0; for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) { for(std::size_t zone_led_idx = 0; zone_led_idx < zones[zone_idx].leds_count; zone_led_idx++) diff --git a/Controllers/ENESMBusController/RGBController_ENESMBus.h b/Controllers/ENESMBusController/RGBController_ENESMBus.h index 80ac9647..702ec903 100644 --- a/Controllers/ENESMBusController/RGBController_ENESMBus.h +++ b/Controllers/ENESMBusController/RGBController_ENESMBus.h @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_ENESMBus.h | -| | -| Generic RGB Interface for ENE SMBus | -| | -| Adam Honse (CalcProgrammer1) 6/13/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ENESMBus.h | +| | +| RGBController for ENE SMBus devices | +| | +| Adam Honse (CalcProgrammer1) 13 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/ENESMBusController/ROGArionDetect.cpp b/Controllers/ENESMBusController/ROGArionDetect.cpp new file mode 100644 index 00000000..65c7be44 --- /dev/null +++ b/Controllers/ENESMBusController/ROGArionDetect.cpp @@ -0,0 +1,50 @@ +/*---------------------------------------------------------*\ +| ROGArionDetect.cpp | +| | +| Detector for ASUS ROG Arion | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "ENESMBusController.h" +#include "ENESMBusInterface_ROGArion.h" +#include "RGBController_ENESMBus.h" +#include "scsiapi.h" + +/******************************************************************************************\ +* * +* DetectROGArionControllers * +* * +* Detects ENE SMBus controllers on ASUS ROG Arion devices * +* * +\******************************************************************************************/ + +void DetectROGArionControllers() +{ + scsi_device_info * info = scsi_enumerate(NULL, NULL); + + while(info) + { + if(strncmp(info->vendor, "ROG", 3) == 0 && strncmp(info->product, "ESD-S1C", 7) == 0) + { + scsi_device * dev = scsi_open_path(info->path); + + if(dev) + { + ENESMBusInterface_ROGArion* interface = new ENESMBusInterface_ROGArion(dev, info->path); + ENESMBusController* controller = new ENESMBusController(interface, 0x67, "Asus ROG Strix Arion", DEVICE_TYPE_STORAGE); + RGBController_ENESMBus* rgb_controller = new RGBController_ENESMBus(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + } + info = info->next; + } + + scsi_free_enumeration(info); + +} /* DetectROGArionControllers() */ + +REGISTER_DETECTOR("ASUS ROG Arion", DetectROGArionControllers); diff --git a/Controllers/ENESMBusController/XPGSpectrixS40GDetect.cpp b/Controllers/ENESMBusController/XPGSpectrixS40GDetect.cpp deleted file mode 100644 index c6c765ef..00000000 --- a/Controllers/ENESMBusController/XPGSpectrixS40GDetect.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "Detector.h" -#include "ENESMBusController.h" -#include "ENESMBusInterface_SpectrixS40G.h" -#include "LogManager.h" -#include "RGBController.h" -#include "RGBController_ENESMBus.h" -#include -#include -#include - -#include -#include -#include - -/******************************************************************************************\ -* * -* DetectSpectrixS40GControllers * -* * -* Detects ENE SMBus controllers on XPG Spectrix S40G NVMe devices * -* * -\******************************************************************************************/ - -void DetectSpectrixS40GControllers() -{ - /*---------------------------------------------------------------------*\ - | Search for /dev/nvmeX nodes with model matching "XPG SPECTRIX S40G" | - \*---------------------------------------------------------------------*/ - unsigned int nvme_idx = 0; - - while(1) - { - /*-------------------------------------------------*\ - | Create the nvme class model path | - \*-------------------------------------------------*/ - char nvme_dev_buf[1024]; - - snprintf(nvme_dev_buf, 1024, "/sys/class/nvme/nvme%d/model", nvme_idx); - - /*-------------------------------------------------*\ - | Open the input event path to get the name | - \*-------------------------------------------------*/ - int nvme_model_fd = open(nvme_dev_buf, O_RDONLY|O_NONBLOCK); - - if(nvme_model_fd < 0) - { - break; - } - - memset(nvme_dev_buf, 0, 1024); - - if(read(nvme_model_fd, nvme_dev_buf, 1024) < 0) - { - LOG_WARNING("[XPG Spectrix S40G] Probing %d, failed to read NVMe model", nvme_idx); - } - else - { - LOG_DEBUG("[XPG Spectrix S40G] Probing %d, model: %s", nvme_idx, nvme_dev_buf); - } - - close(nvme_model_fd); - - /*-------------------------------------------------*\ - | Check if this NVMe device is a SPECTRIX S40G | - \*-------------------------------------------------*/ - if(strncmp(nvme_dev_buf, "XPG SPECTRIX S40G", 17) == 0) - { - snprintf(nvme_dev_buf, 1024, "/dev/nvme%d", nvme_idx); - - int nvme_fd = open(nvme_dev_buf, O_RDWR); - - if(nvme_fd > 0) - { - ENESMBusInterface_SpectrixS40G* interface = new ENESMBusInterface_SpectrixS40G(nvme_fd, nvme_dev_buf); - ENESMBusController* controller = new ENESMBusController(interface, 0x67); - RGBController_ENESMBus* rgb_controller = new RGBController_ENESMBus(controller); - - rgb_controller->name = "XPG Spectrix S40G"; - rgb_controller->type = DEVICE_TYPE_STORAGE; - rgb_controller->vendor = "XPG"; - - ResourceManager::get()->RegisterRGBController(rgb_controller); - } - } - - nvme_idx++; - } -} /* DetectSpectrixS40GControllers() */ - -REGISTER_DETECTOR( "XPG Spectrix S40G", DetectSpectrixS40GControllers); diff --git a/Controllers/ENESMBusController/XPGSpectrixS40GDetect_Linux.cpp b/Controllers/ENESMBusController/XPGSpectrixS40GDetect_Linux.cpp new file mode 100644 index 00000000..8bde74c5 --- /dev/null +++ b/Controllers/ENESMBusController/XPGSpectrixS40GDetect_Linux.cpp @@ -0,0 +1,93 @@ +/*---------------------------------------------------------*\ +| XPGSpectrixS40GDetect_Linux.cpp | +| | +| Detector for XPG Spectrix S40G (Linux) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include "Detector.h" +#include "ENESMBusController.h" +#include "ENESMBusInterface_SpectrixS40G_Linux.h" +#include "LogManager.h" +#include "RGBController.h" +#include "RGBController_ENESMBus.h" + +/******************************************************************************************\ +* * +* DetectSpectrixS40GControllers * +* * +* Detects ENE SMBus controllers on XPG Spectrix S40G NVMe devices * +* * +\******************************************************************************************/ + +void DetectSpectrixS40GControllers() +{ + /*---------------------------------------------------------------------*\ + | Search for /dev/nvmeX nodes with model matching "XPG SPECTRIX S40G" | + \*---------------------------------------------------------------------*/ + unsigned int nvme_idx = 0; + + while(1) + { + /*-------------------------------------------------*\ + | Create the nvme class model path | + \*-------------------------------------------------*/ + char nvme_dev_buf[1024]; + + snprintf(nvme_dev_buf, 1024, "/sys/class/nvme/nvme%d/model", nvme_idx); + + /*-------------------------------------------------*\ + | Open the input event path to get the name | + \*-------------------------------------------------*/ + int nvme_model_fd = open(nvme_dev_buf, O_RDONLY|O_NONBLOCK); + + if(nvme_model_fd < 0) + { + break; + } + + memset(nvme_dev_buf, 0, 1024); + + if(read(nvme_model_fd, nvme_dev_buf, 1024) < 0) + { + LOG_WARNING("[XPG Spectrix S40G] Probing %d, failed to read NVMe model", nvme_idx); + } + else + { + LOG_DEBUG("[XPG Spectrix S40G] Probing %d, model: %s", nvme_idx, nvme_dev_buf); + } + + close(nvme_model_fd); + + /*-------------------------------------------------*\ + | Check if this NVMe device is a SPECTRIX S40G | + \*-------------------------------------------------*/ + if(strncmp(nvme_dev_buf, "XPG SPECTRIX S40G", 17) == 0) + { + snprintf(nvme_dev_buf, 1024, "/dev/nvme%d", nvme_idx); + + int nvme_fd = open(nvme_dev_buf, O_RDWR); + + if(nvme_fd > 0) + { + ENESMBusInterface_SpectrixS40G* interface = new ENESMBusInterface_SpectrixS40G(nvme_fd, nvme_dev_buf); + ENESMBusController* controller = new ENESMBusController(interface, 0x67, "XPG Spectrix S40G", DEVICE_TYPE_STORAGE); + RGBController_ENESMBus* rgb_controller = new RGBController_ENESMBus(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + } + + nvme_idx++; + } +} /* DetectSpectrixS40GControllers() */ + +REGISTER_DETECTOR( "XPG Spectrix S40G", DetectSpectrixS40GControllers); diff --git a/Controllers/ENESMBusController/XPGSpectrixS40GDetect_Windows.cpp b/Controllers/ENESMBusController/XPGSpectrixS40GDetect_Windows.cpp index 072d52a4..240604a1 100644 --- a/Controllers/ENESMBusController/XPGSpectrixS40GDetect_Windows.cpp +++ b/Controllers/ENESMBusController/XPGSpectrixS40GDetect_Windows.cpp @@ -1,16 +1,23 @@ +/*---------------------------------------------------------*\ +| XPGSpectrixS40GDetect_Windows.cpp | +| | +| Detector for XPG Spectrix S40G (Windows) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include #include "Detector.h" #include "ENESMBusController.h" #include "ENESMBusInterface_SpectrixS40G_Windows.h" -#include "LogManager.h" #include "RGBController.h" #include "RGBController_ENESMBus.h" -#include -#include -#include #define DEVBUFSIZE (128 * 1024) -#include -#include /*----------------------------------------------------------------------*\ | Windows defines "interface" for some reason. Work around this | @@ -48,7 +55,7 @@ int Search(wchar_t *dev_name) return 1; } - i += wcslen(buff + i); + i += (int)wcslen(buff + i); } return 0; @@ -106,13 +113,9 @@ void DetectSpectrixS40GControllers() if(nvme_fd != INVALID_HANDLE_VALUE) { ENESMBusInterface_SpectrixS40G* interface = new ENESMBusInterface_SpectrixS40G(nvme_fd, dev_name); - ENESMBusController* controller = new ENESMBusController(interface, 0x67); + ENESMBusController* controller = new ENESMBusController(interface, 0x67, "XPG Spectrix S40G", DEVICE_TYPE_STORAGE); RGBController_ENESMBus* rgb_controller = new RGBController_ENESMBus(controller); - rgb_controller->name = "XPG Spectrix S40G"; - rgb_controller->type = DEVICE_TYPE_STORAGE; - rgb_controller->vendor = "XPG"; - ResourceManager::get()->RegisterRGBController(rgb_controller); } } diff --git a/Controllers/EVGAAmpereGPUController/EVGAAmpereGPUControllerDetect.cpp b/Controllers/EVGAAmpereGPUController/EVGAAmpereGPUControllerDetect.cpp index af36f368..b9e0ee81 100644 --- a/Controllers/EVGAAmpereGPUController/EVGAAmpereGPUControllerDetect.cpp +++ b/Controllers/EVGAAmpereGPUController/EVGAAmpereGPUControllerDetect.cpp @@ -1,13 +1,20 @@ +/*---------------------------------------------------------*\ +| EVGAAmpereGPUControllerDetect.cpp | +| | +| Detector for EVGA V3 (Ampere) GPU | +| | +| TheRogueZeta 15 Jul 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "EVGAGPUv3Controller.h" #include "LogManager.h" -#include "RGBController.h" #include "RGBController_EVGAGPUv3.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include /******************************************************************************************\ * * @@ -27,37 +34,39 @@ void DetectEVGAAmpereGPUControllers(i2c_smbus_interface* bus, uint8_t address, c EVGAGPUv3Controller* controller; RGBController_EVGAGPUv3* rgb_controller; - controller = new EVGAGPUv3Controller(bus, address); - controller-> evgaGPUName = name.c_str(); // Pass name of the card into the controller for logging. + controller = new EVGAGPUv3Controller(bus, address, name); if(controller-> ReadFWVersion() != "") { rgb_controller = new RGBController_EVGAGPUv3(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } else { - LOG_INFO("[%s] Failed to get a valid FW version, does the i2c interface support `i2c_smbus_read_i2c_block_data`?", controller-> evgaGPUName); + LOG_INFO("[%s] Failed to get a valid FW version, does the i2c interface support `i2c_smbus_read_i2c_block_data`?", controller->GetDeviceName().c_str()); delete controller; } } } /* DetectEVGAAmpereGPUControllers() */ -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3060TI FTW3 Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, EVGA_SUB_VEN, EVGA_RTX3060TI_FTW3_GAMING_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3060TI FTW3 Ultra" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, EVGA_SUB_VEN, EVGA_RTX3060TI_FTW3_ULTRA_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3060TI FTW3 Ultra LHR" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, EVGA_SUB_VEN, EVGA_RTX3060TI_FTW3_ULTRA_KL_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3060 Ti FTW3 Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, EVGA_SUB_VEN, EVGA_RTX3060TI_FTW3_GAMING_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3060 Ti FTW3 Ultra" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, EVGA_SUB_VEN, EVGA_RTX3060TI_FTW3_ULTRA_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3060 Ti FTW3 Ultra LHR" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, EVGA_SUB_VEN, EVGA_RTX3060TI_FTW3_ULTRA_KL_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3060 Ti FTW3 Ultra Gaming LHR" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, EVGA_SUB_VEN, EVGA_RTX3060TI_FTW3_ULTRA_GAMING_LHR_SUB_DEV, 0x2D); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070 Black Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, EVGA_SUB_VEN, EVGA_RTX3070_XC3_BLACK_SUB_DEV, 0x2D); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070 XC3 Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, EVGA_SUB_VEN, EVGA_RTX3070_XC3_GAMING_SUB_DEV, 0x2D); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070 XC3 Ultra" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, EVGA_SUB_VEN, EVGA_RTX3070_XC3_ULTRA_SUB_DEV, 0x2D); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070 XC3 Ultra LHR" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, EVGA_SUB_VEN, EVGA_RTX3070_XC3_ULTRA_LHR_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070 XC3 Ultra Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, EVGA_SUB_VEN, EVGA_RTX3070_XC3_ULTRA_GAMING_LHR_SUB_DEV, 0x2D); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070 FTW3 Ultra" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, EVGA_SUB_VEN, EVGA_RTX3070_FTW3_ULTRA_SUB_DEV, 0x2D); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070 FTW3 Ultra LHR" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, EVGA_SUB_VEN, EVGA_RTX3070_FTW3_ULTRA_LHR_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070Ti XC3 Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, EVGA_SUB_VEN, EVGA_RTX3070TI_XC3_GAMING_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070Ti XC3 Ultra" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, EVGA_SUB_VEN, EVGA_RTX3070TI_XC3_ULTRA_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070Ti XC3 Ultra v2" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, EVGA_SUB_VEN, EVGA_RTX3070TI_XC3_ULTRA_V2_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070Ti FTW3 Ultra" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, EVGA_SUB_VEN, EVGA_RTX3070TI_FTW3_ULTRA_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070Ti FTW3 Ultra v2" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, EVGA_SUB_VEN, EVGA_RTX3070TI_FTW3_ULTRA_V2_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070 FTW3 Ultra LHR" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, EVGA_SUB_VEN, EVGA_RTX3070_FTW3_ULTRA_LHR_ALT_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070 Ti XC3 Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, EVGA_SUB_VEN, EVGA_RTX3070TI_XC3_GAMING_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070 Ti XC3 Ultra" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, EVGA_SUB_VEN, EVGA_RTX3070TI_XC3_ULTRA_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070 Ti XC3 Ultra v2" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, EVGA_SUB_VEN, EVGA_RTX3070TI_XC3_ULTRA_V2_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070 Ti FTW3 Ultra" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, EVGA_SUB_VEN, EVGA_RTX3070TI_FTW3_ULTRA_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3070 Ti FTW3 Ultra v2" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, EVGA_SUB_VEN, EVGA_RTX3070TI_FTW3_ULTRA_V2_SUB_DEV, 0x2D); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080 XC3 Black" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, EVGA_SUB_VEN, EVGA_RTX3080_XC3_BLACK_SUB_DEV, 0x2D); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080 XC3 Black LHR" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, EVGA_SUB_VEN, EVGA_RTX3080_XC3_BLACK_LHR_SUB_DEV, 0x2D); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080 XC3 Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, EVGA_SUB_VEN, EVGA_RTX3080_XC3_GAMING_SUB_DEV, 0x2D); @@ -78,13 +87,13 @@ REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080 FTW3 Ultra Hydro Copper" REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080 XC3 Ultra 12G" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, EVGA_SUB_VEN, EVGA_RTX3080_12G_XC3_ULTRA_SUB_DEV, 0x2D); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080 FTW3 Ultra 12GB" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, EVGA_SUB_VEN, EVGA_RTX3080_12G_FTW3_ULTRA_SUB_DEV, 0x2D); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080 FTW3 Ultra Hydro Copper 12G" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, EVGA_SUB_VEN, EVGA_RTX3080_12G_FTW3_ULTRA_HC_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080Ti XC3 Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, EVGA_SUB_VEN, EVGA_RTX3080TI_XC3_GAMING_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080Ti XC3 Ultra Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, EVGA_SUB_VEN, EVGA_RTX3080TI_XC3_ULTRA_GAMING_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080Ti XC3 Gaming Hybrid" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, EVGA_SUB_VEN, EVGA_RTX3080TI_XC3_GAMING_HYBRID_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080Ti XC3 Gaming Hydro Copper" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, EVGA_SUB_VEN, EVGA_RTX3080TI_XC3_GAMING_HC_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080Ti FTW3 Ultra" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, EVGA_SUB_VEN, EVGA_RTX3080TI_FTW3_ULTRA_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080Ti FTW3 Ultra Hybrid" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, EVGA_SUB_VEN, EVGA_RTX3080TI_FTW3_ULTRA_HYBRID_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080Ti FTW3 Ultra Hydro Copper" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, EVGA_SUB_VEN, EVGA_RTX3080TI_FTW3_ULTRA_HC_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080 Ti XC3 Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, EVGA_SUB_VEN, EVGA_RTX3080TI_XC3_GAMING_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080 Ti XC3 Ultra Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, EVGA_SUB_VEN, EVGA_RTX3080TI_XC3_ULTRA_GAMING_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080 Ti XC3 Gaming Hybrid" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, EVGA_SUB_VEN, EVGA_RTX3080TI_XC3_GAMING_HYBRID_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080 Ti XC3 Gaming Hydro Copper" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, EVGA_SUB_VEN, EVGA_RTX3080TI_XC3_GAMING_HC_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080 Ti FTW3 Ultra" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, EVGA_SUB_VEN, EVGA_RTX3080TI_FTW3_ULTRA_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080 Ti FTW3 Ultra Hybrid" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, EVGA_SUB_VEN, EVGA_RTX3080TI_FTW3_ULTRA_HYBRID_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3080 Ti FTW3 Ultra Hydro Copper" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, EVGA_SUB_VEN, EVGA_RTX3080TI_FTW3_ULTRA_HC_SUB_DEV, 0x2D); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3090 XC3 Black" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, EVGA_SUB_VEN, EVGA_RTX3090_XC3_BLACK_SUB_DEV, 0x2D); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3090 XC3 Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, EVGA_SUB_VEN, EVGA_RTX3090_XC3_GAMING_SUB_DEV, 0x2D); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3090 XC3 Ultra" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, EVGA_SUB_VEN, EVGA_RTX3090_XC3_ULTRA_SUB_DEV, 0x2D); @@ -97,6 +106,7 @@ REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3090 FTW3 Ultra Hybrid" REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3090 FTW3 Ultra Hydro Copper" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, EVGA_SUB_VEN, EVGA_RTX3090_FTW3_ULTRA_HC_SUB_DEV, 0x2D); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3090 K|NGP|N Hybrid" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, EVGA_SUB_VEN, EVGA_RTX3090_KINGPIN_HYBRID_SUB_DEV, 0x2D); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3090 K|NGP|N Hydro Copper" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, EVGA_SUB_VEN, EVGA_RTX3090_KINGPIN_HC_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3090Ti FTW3 Black Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, EVGA_SUB_VEN, EVGA_RTX3090TI_FTW3_BLACK_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3090Ti FTW3 Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, EVGA_SUB_VEN, EVGA_RTX3090TI_FTW3_GAMING_SUB_DEV, 0x2D); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3090Ti FTW3 Ultra Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, EVGA_SUB_VEN, EVGA_RTX3090TI_FTW3_ULTRA_GAMING_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3090 Ti FTW3 Black Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, EVGA_SUB_VEN, EVGA_RTX3090TI_FTW3_BLACK_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3090 Ti FTW3 Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, EVGA_SUB_VEN, EVGA_RTX3090TI_FTW3_GAMING_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3090 Ti FTW3 Ultra Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, EVGA_SUB_VEN, EVGA_RTX3090TI_FTW3_ULTRA_GAMING_SUB_DEV, 0x2D); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 3090 Ti FTW3 Ultra Hybrid Gaming" , DetectEVGAAmpereGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, EVGA_SUB_VEN, EVGA_RTX3090TI_FTW3_ULTRA_HYBRID_GAMING_SUB_DEV,0x2D); diff --git a/Controllers/EVGAAmpereGPUController/EVGAGPUv3Controller.cpp b/Controllers/EVGAAmpereGPUController/EVGAGPUv3Controller.cpp index 46d5c114..b0ed3149 100644 --- a/Controllers/EVGAAmpereGPUController/EVGAGPUv3Controller.cpp +++ b/Controllers/EVGAAmpereGPUController/EVGAGPUv3Controller.cpp @@ -1,19 +1,22 @@ -/*-----------------------------------------*\ -| EVGAGPUv3Controller.cpp | -| | -| Driver for EVGA GPU RGB V3 (Ampere) | -| lighting controller | -| | -| TheRogueZeta 7/15/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| EVGAGPUv3Controller.cpp | +| | +| Driver for EVGA V3 (Ampere) GPU | +| | +| TheRogueZeta 15 Jul 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "EVGAGPUv3Controller.h" #include "LogManager.h" -EVGAGPUv3Controller::EVGAGPUv3Controller(i2c_smbus_interface* bus, evga_dev_id dev) +EVGAGPUv3Controller::EVGAGPUv3Controller(i2c_smbus_interface* bus, evga_dev_id dev, std::string dev_name) { - this->bus = bus; - this->dev = dev; + this->bus = bus; + this->dev = dev; + this->name = dev_name; } EVGAGPUv3Controller::~EVGAGPUv3Controller() @@ -32,9 +35,14 @@ std::string EVGAGPUv3Controller::GetDeviceLocation() return("I2C: " + return_string); } +std::string EVGAGPUv3Controller::GetDeviceName() +{ + return(name); +} + void EVGAGPUv3Controller::GetDeviceModes() { - LOG_DEBUG("[%s] Getting Zone and LED count from HW", evgaGPUName); + LOG_DEBUG("[%s] Getting Zone and LED count from HW", name.c_str()); uint8_t data_pkt[I2C_SMBUS_BLOCK_MAX] = {}; uint8_t result = bus->i2c_smbus_read_i2c_block_data(dev, EVGA_GPU_V3_REG_MODE, 10, data_pkt); @@ -44,14 +52,14 @@ void EVGAGPUv3Controller::GetDeviceModes() { zone_modes[zone] = data_pkt[zone + 1]; zone_led_count[zone] = data_pkt[zone + 5]; - LOG_DEBUG("[%s] Zone %1d LED count: %02d, mode: %02d", evgaGPUName, zone + 1, zone_led_count[zone], zone_modes[zone]); + LOG_DEBUG("[%s] Zone %1d LED count: %02d, mode: %02d", name.c_str(), zone + 1, zone_led_count[zone], zone_modes[zone]); } zone_sync = data_pkt[9]; - LOG_DEBUG("[%s] Zone Sync is %1d", evgaGPUName, zone_sync); + LOG_DEBUG("[%s] Zone Sync is %1d", name.c_str(), zone_sync); } else { - LOG_DEBUG("[%s] Invalid block read result: %02d", evgaGPUName, result); + LOG_DEBUG("[%s] Invalid block read result: %02d", name.c_str(), result); memset(zone_led_count, 0, sizeof(zone_led_count)); memset(zone_modes, 0, sizeof(zone_modes)); } @@ -65,7 +73,7 @@ std::string EVGAGPUv3Controller::GetFWVersion() std::string EVGAGPUv3Controller::ReadFWVersion() { - LOG_TRACE("[%s] Getting FW from HW", evgaGPUName); + LOG_TRACE("[%s] Getting FW from HW", name.c_str()); uint8_t data_pkt[I2C_SMBUS_BLOCK_MAX] = {}; std::string return_string = ""; char version[10]; @@ -78,7 +86,7 @@ std::string EVGAGPUv3Controller::ReadFWVersion() snprintf(version, 10, "1.%02d.%02d", major, minor); return_string.append(version); - LOG_TRACE("[%s] Firmware %s", evgaGPUName, version); + LOG_TRACE("[%s] Firmware %s", name.c_str(), version); fwVersion = return_string; return(return_string); } @@ -104,7 +112,7 @@ EVGAv3_config EVGAGPUv3Controller::GetZoneConfig(uint8_t zone, uint8_t mode) zone_config.numberOfColors = 0; zone_config.speed = EVGA_GPU_V3_SPEED_GENERIC_NORMAL; - LOG_DEBUG("[%s] Retriving Zone %1d config for mode %1d from HW", evgaGPUName, zone, mode); + LOG_DEBUG("[%s] Retriving Zone %1d config for mode %1d from HW", name.c_str(), zone, mode); uint8_t data_pkt[I2C_SMBUS_BLOCK_MAX] = {}; switch (mode) @@ -130,7 +138,7 @@ EVGAv3_config EVGAGPUv3Controller::GetZoneConfig(uint8_t zone, uint8_t mode) } } break; - + case EVGA_GPU_V3_MODE_BREATHING: { uint8_t result = bus->i2c_smbus_read_i2c_block_data(dev, EVGA_GPU_V3_REG_BREATHING + zone, 10, data_pkt); @@ -147,8 +155,8 @@ EVGAv3_config EVGAGPUv3Controller::GetZoneConfig(uint8_t zone, uint8_t mode) uint8_t blue2 = data_pkt[7]; zone_config.colors[1] = ToRGBColor(red2, green2, blue2); zone_config.numberOfColors= (zone_config.colors[1] != 0 ) ? 2 : 1 ; - speed16.LSB = data_pkt[8]; - speed16.MSB = data_pkt[9]; + speed16.lsb = data_pkt[8]; + speed16.msb = data_pkt[9]; zone_config.speed = speed16.u16; zone_config.direction = 0; } @@ -169,8 +177,8 @@ EVGAv3_config EVGAGPUv3Controller::GetZoneConfig(uint8_t zone, uint8_t mode) //Load data zone_config.brightness = data_pkt[1]; zone_config.numberOfColors = 0; - speed16.LSB = data_pkt[2]; - speed16.MSB = data_pkt[3]; + speed16.lsb = data_pkt[2]; + speed16.msb = data_pkt[3]; zone_config.speed = speed16.u16; } else @@ -192,8 +200,8 @@ EVGAv3_config EVGAGPUv3Controller::GetZoneConfig(uint8_t zone, uint8_t mode) uint8_t blue = data_pkt[4]; zone_config.colors[0] = ToRGBColor(red, green, blue); zone_config.numberOfColors = 1; - speed16.LSB = data_pkt[5]; - speed16.MSB = data_pkt[6]; + speed16.lsb = data_pkt[5]; + speed16.msb = data_pkt[6]; zone_config.speed = speed16.u16; } else @@ -230,7 +238,7 @@ EVGAv3_config EVGAGPUv3Controller::GetZoneConfig(uint8_t zone, uint8_t mode) { readFail = true; } - + } else { @@ -257,11 +265,11 @@ EVGAv3_config EVGAGPUv3Controller::GetZoneConfig(uint8_t zone, uint8_t mode) uint8_t blue = data_pkt[(color_index * 4) + 4]; zone_config.colors[color_index] = ToRGBColor(red, green, blue); } - speed16.LSB = data_pkt[29]; - speed16.MSB = data_pkt[30]; + speed16.lsb = data_pkt[29]; + speed16.msb = data_pkt[30]; zone_config.speed = speed16.u16; } - else + else { readFail = true; } @@ -274,12 +282,12 @@ EVGAv3_config EVGAGPUv3Controller::GetZoneConfig(uint8_t zone, uint8_t mode) if(readFail == false) { - LOG_TRACE("[%s] Zone %1d Brightness: 0x%02X, Colors: %1d, Speed: 0x%04X, Direction %1d.", evgaGPUName, zone, zone_config.brightness, zone_config.numberOfColors, zone_config.speed, zone_config.direction); + LOG_TRACE("[%s] Zone %1d Brightness: 0x%02X, Colors: %1d, Speed: 0x%04X, Direction %1d.", name.c_str(), zone, zone_config.brightness, zone_config.numberOfColors, zone_config.speed, zone_config.direction); for(uint8_t color_index = 0; color_index < zone_config.numberOfColors; color_index++) { - LOG_TRACE("[%s] Color Index [%2d]: 0x%06X", evgaGPUName, color_index, zone_config.colors[color_index]); + LOG_TRACE("[%s] Color Index [%2d]: 0x%06X", name.c_str(), color_index, zone_config.colors[color_index]); } - LOG_DEBUG("[%s] Done loading Zone %1d configuration from HW", evgaGPUName, zone); + LOG_DEBUG("[%s] Done loading Zone %1d configuration from HW", name.c_str(), zone); } else { @@ -288,8 +296,8 @@ EVGAv3_config EVGAGPUv3Controller::GetZoneConfig(uint8_t zone, uint8_t mode) for(uint8_t i = 0; i < 7; i++) { zone_config.colors[i] = 0; - } - LOG_DEBUG("[%s] Failed while loading Zone %1d configuration from HW", evgaGPUName, zone); + } + LOG_DEBUG("[%s] Failed while loading Zone %1d configuration from HW", name.c_str(), zone); } return zone_config; } @@ -300,13 +308,13 @@ void EVGAGPUv3Controller::initCard() // NvAPI_I2CWriteEx: Dev: 0x2D RegSize: 0x01 Reg: 0xB2 Size: 0x05 Data: 0x04 0xC6 0xEB 0xEA 0x15 uint8_t data_pkt[5] = {0x04, 0xC6, 0xEB, 0xEA, 0x15}; bus->i2c_smbus_write_i2c_block_data(dev, EVGA_GPU_V3_REG_ENABLE, sizeof(data_pkt), data_pkt); - LOG_TRACE("[%s] Sending SW int packet", evgaGPUName); + LOG_TRACE("[%s] Sending SW int packet", name.c_str()); return; } void EVGAGPUv3Controller::SaveConfig() { - LOG_DEBUG("[%s] Sending save packet", evgaGPUName); + LOG_DEBUG("[%s] Sending save packet", name.c_str()); //NvAPI_I2CWriteEx: Dev: 0x2D RegSize: 0x01 Reg: 0x90 Size: 0x05 Data: 0x04 0x9E 0xEB 0x00 0x90 //Sent on close of PX1 uint8_t data_pkt[5] = {0x04, 0x9E, 0xEB, 0x00, 0x90}; @@ -326,7 +334,7 @@ void EVGAGPUv3Controller::ResizeARGB(uint8_t newSize) newSize = EVGAGPUV3_LEDS_MAX; } - LOG_DEBUG("[%s] Resizing ARGB header with %02d size", evgaGPUName, newSize); + LOG_DEBUG("[%s] Resizing ARGB header with %02d size", name.c_str(), newSize); uint8_t data_pkt[EVGAGPUV3_MODE_PACKET_SIZE] = { 0x09, EVGAGPUV3_INIT, EVGAGPUV3_INIT, EVGAGPUV3_INIT, EVGAGPUV3_INIT, EVGAGPUV3_INIT, EVGAGPUV3_INIT, EVGAGPUV3_INIT, newSize, EVGAGPUV3_INIT}; @@ -359,7 +367,7 @@ void EVGAGPUv3Controller::SetAllModes(uint8_t zone_0_mode, uint8_t zone_1_mode,u mode_pkt[9] = sync; bus->i2c_smbus_write_i2c_block_data(dev, EVGA_GPU_V3_REG_MODE, EVGAGPUV3_MODE_PACKET_SIZE, mode_pkt); - //LOG_TRACE("[%s] Setting all zones to mode: %02d, %2d, %2d, %2d, zone sync %1d.", evgaGPUName, zone_0_mode, zone_1_mode, zone_2_mode, zone_3_mode, sync); + //LOG_TRACE("[%s] Setting all zones to mode: %02d, %2d, %2d, %2d, zone sync %1d.", name.c_str(), zone_0_mode, zone_1_mode, zone_2_mode, zone_3_mode, sync); } void EVGAGPUv3Controller::SetZoneMode(uint8_t zone, uint8_t mode) @@ -379,7 +387,7 @@ void EVGAGPUv3Controller::SetZoneMode(uint8_t zone, uint8_t mode) mode_pkt[zone + 1] = mode; bus->i2c_smbus_write_i2c_block_data(dev, EVGA_GPU_V3_REG_MODE, EVGAGPUV3_MODE_PACKET_SIZE, mode_pkt); - //LOG_TRACE("[%s] Setting individual zone %1d to mode %02d", evgaGPUName, zone, mode); + //LOG_TRACE("[%s] Setting individual zone %1d to mode %02d", name.c_str(), zone, mode); } void EVGAGPUv3Controller::SetZone(uint8_t zone, uint8_t mode, EVGAv3_config zone_config) @@ -423,8 +431,8 @@ void EVGAGPUv3Controller::SetZone(uint8_t zone, uint8_t mode, EVGAv3_config zone zone_pkt[5] = RGBGetRValue(zone_config.colors[1]); zone_pkt[6] = RGBGetGValue(zone_config.colors[1]); zone_pkt[7] = RGBGetBValue(zone_config.colors[1]); - zone_pkt[8] = speed16.LSB; - zone_pkt[9] = speed16.MSB; + zone_pkt[8] = speed16.lsb; + zone_pkt[9] = speed16.msb; bus->i2c_smbus_write_i2c_block_data(dev, EVGA_GPU_V3_REG_STATIC + ((mode -1) * 4) + zone, sizeof(zone_pkt), zone_pkt); } @@ -439,8 +447,8 @@ void EVGAGPUv3Controller::SetZone(uint8_t zone, uint8_t mode, EVGAv3_config zone zone_pkt[0] = sizeof(zone_pkt) - 1; zone_pkt[1] = zone_config.brightness; - zone_pkt[2] = speed16.LSB; - zone_pkt[3] = speed16.MSB; + zone_pkt[2] = speed16.lsb; + zone_pkt[3] = speed16.msb; bus->i2c_smbus_write_i2c_block_data(dev, EVGA_GPU_V3_REG_STATIC + ((mode -1) * 4) + zone, sizeof(zone_pkt), zone_pkt); } @@ -456,8 +464,8 @@ void EVGAGPUv3Controller::SetZone(uint8_t zone, uint8_t mode, EVGAv3_config zone zone_pkt[2] = RGBGetRValue(zone_config.colors[0]); zone_pkt[3] = RGBGetGValue(zone_config.colors[0]); zone_pkt[4] = RGBGetBValue(zone_config.colors[0]); - zone_pkt[5] = speed16.LSB; - zone_pkt[6] = speed16.MSB; + zone_pkt[5] = speed16.lsb; + zone_pkt[6] = speed16.msb; bus->i2c_smbus_write_i2c_block_data(dev, EVGA_GPU_V3_REG_STATIC + ((mode -1) * 4) + zone, sizeof(zone_pkt), zone_pkt); } @@ -480,8 +488,8 @@ void EVGAGPUv3Controller::SetZone(uint8_t zone, uint8_t mode, EVGAv3_config zone zone_pkt[3 + color_index * 4] = RGBGetGValue(zone_config.colors[color_index]); zone_pkt[4 + color_index * 4] = RGBGetBValue(zone_config.colors[color_index]); } - zone_pkt[29] = speed16.LSB; - zone_pkt[30] = speed16.MSB; + zone_pkt[29] = speed16.lsb; + zone_pkt[30] = speed16.msb; // Color Count packet construction color_cnt_pkt[0] = sizeof(color_cnt_pkt) - 1; @@ -508,7 +516,7 @@ void EVGAGPUv3Controller::SetZone(uint8_t zone, uint8_t mode, EVGAv3_config zone break; default: { - LOG_TRACE("[%s] Mode %02d not found", evgaGPUName, mode); + LOG_TRACE("[%s] Mode %02d not found", name.c_str(), mode); } break; } diff --git a/Controllers/EVGAAmpereGPUController/EVGAGPUv3Controller.h b/Controllers/EVGAAmpereGPUController/EVGAGPUv3Controller.h index bbd30931..e9aaf10e 100644 --- a/Controllers/EVGAAmpereGPUController/EVGAGPUv3Controller.h +++ b/Controllers/EVGAAmpereGPUController/EVGAGPUv3Controller.h @@ -1,18 +1,20 @@ -/*-----------------------------------------*\ -| EVGAGPUv3Controller.h | -| | -| Definitions and types for EVGA GPU RGB | -| V3 (Ampere) lighting controller | -| | -| TheRogueZeta 7/15/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| EVGAGPUv3Controller.h | +| | +| Driver for EVGA V3 (Ampere) GPU | +| | +| TheRogueZeta 15 Jul 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" #include "RGBController.h" -#pragma once - typedef unsigned char evga_dev_id; #define SPEED_MULTIPLIER 10 @@ -27,8 +29,8 @@ union u16_to_u8 uint16_t u16; struct { - uint8_t LSB; - uint8_t MSB; + uint8_t lsb; + uint8_t msb; }; }; @@ -67,7 +69,7 @@ enum //Control registers and offsets enum //Mode values for EVGA_GPU_V3_REG_MODE { EVGA_GPU_V3_MODE_OFF = 0x00, - EVGA_GPU_V3_MODE_STATIC = 0x01, + EVGA_GPU_V3_MODE_STATIC = 0x01, EVGA_GPU_V3_MODE_BREATHING = 0x02, EVGA_GPU_V3_MODE_RAINBOW = 0x03, EVGA_GPU_V3_MODE_COLOR_CYCLE = 0x04, @@ -96,14 +98,14 @@ enum // Value limits for speeds class EVGAGPUv3Controller { public: - EVGAGPUv3Controller(i2c_smbus_interface* bus, evga_dev_id dev); + EVGAGPUv3Controller(i2c_smbus_interface* bus, evga_dev_id dev, std::string dev_name); ~EVGAGPUv3Controller(); uint8_t zone_led_count[4]; uint8_t zone_modes[4]; - const char * evgaGPUName; std::string GetDeviceLocation(); + std::string GetDeviceName(); std::string GetFWVersion(); std::string ReadFWVersion(); @@ -121,6 +123,8 @@ private: i2c_smbus_interface* bus; evga_dev_id dev; bool zone_sync; - void initCard(); std::string fwVersion; + std::string name; + + void initCard(); }; diff --git a/Controllers/EVGAAmpereGPUController/RGBController_EVGAGPUv3.cpp b/Controllers/EVGAAmpereGPUController/RGBController_EVGAGPUv3.cpp index 55672528..b1e8fe83 100644 --- a/Controllers/EVGAAmpereGPUController/RGBController_EVGAGPUv3.cpp +++ b/Controllers/EVGAAmpereGPUController/RGBController_EVGAGPUv3.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_EVGAGPUv3.cpp | -| | -| Generic RGB Interface for OpenRGB EVGA | -| GPU V3 (Ampere) Driver | -| | -| TheRogueZeta 7/15/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_EVGAGPUv3.cpp | +| | +| RGBController for EVGA V3 (Ampere) GPU | +| | +| TheRogueZeta 15 Jul 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_EVGAGPUv3.h" #include "LogManager.h" @@ -30,17 +32,16 @@ static const char* evga_v3_zone_names[] = is only able to set all LED's to a single color. \*-------------------------------------------------------------------*/ -RGBController_EVGAGPUv3::RGBController_EVGAGPUv3(EVGAGPUv3Controller* evga_ptr) +RGBController_EVGAGPUv3::RGBController_EVGAGPUv3(EVGAGPUv3Controller* controller_ptr) { - evga = evga_ptr; + controller = controller_ptr; - name = "EVGA GPU"; + name = controller->GetDeviceName(); vendor = "EVGA"; description = "EVGA Ampere RGB GPU Device"; - location = evga->GetDeviceLocation(); - version = evga->GetFWVersion(); - - type = DEVICE_TYPE_GPU; + location = controller->GetDeviceLocation(); + version = controller->GetFWVersion(); + type = DEVICE_TYPE_GPU; mode Off; Off.name = "Off"; @@ -167,11 +168,11 @@ RGBController_EVGAGPUv3::RGBController_EVGAGPUv3(EVGAGPUv3Controller* evga_ptr) // Initialize active mode for( uint8_t zone_idx = 0; zone_idx < zoneIndexMap.size(); zone_idx++) { - active_mode = evga->GetZoneMode(0); // Hard coding zone 0 until per zone modes are available. + active_mode = controller->GetZoneMode(0); // Hard coding zone 0 until per zone modes are available. if(active_mode != EVGA_GPU_V3_MODE_OFF) { - EVGAv3_config hw_config = evga->GetZoneConfig(zoneIndexMap[zone_idx], active_mode); + EVGAv3_config hw_config = controller->GetZoneConfig(zoneIndexMap[zone_idx], active_mode); /*---------------------------------------------------------*\ | The LED color (color[0]) will always be set. Mode colors | @@ -204,7 +205,7 @@ RGBController_EVGAGPUv3::RGBController_EVGAGPUv3(EVGAGPUv3Controller* evga_ptr) RGBController_EVGAGPUv3::~RGBController_EVGAGPUv3() { - delete evga; + delete controller; } uint8_t RGBController_EVGAGPUv3::getModeIndex(uint8_t mode_value) @@ -227,11 +228,11 @@ void RGBController_EVGAGPUv3::SetupZones() | Resizing is only possible on zone 4, addressable header | \*---------------------------------------------------------*/ - evga->GetDeviceModes(); + controller->GetDeviceModes(); for(uint8_t zone_idx = 0; zone_idx < 4; zone_idx++) { - if(evga->zone_led_count[zone_idx] > 0) + if(controller->zone_led_count[zone_idx] > 0) { zone* new_zone = new zone(); led* new_led = new led(); @@ -257,7 +258,7 @@ void RGBController_EVGAGPUv3::SetupZones() void RGBController_EVGAGPUv3::ResizeZone(int /*zone*/, int newSize) { - evga->ResizeARGB(newSize); + controller->ResizeARGB(newSize); } void RGBController_EVGAGPUv3::DeviceUpdateLEDs() @@ -284,20 +285,20 @@ void RGBController_EVGAGPUv3::DeviceUpdateLEDs() zone_config.colors[i] = modes[active_mode].colors[i]; } } - //LOG_TRACE("[%s] Updating LED %1d", evga->evgaGPUName, zone_idx); - evga->SetZone(zoneIndexMap[zone_idx], modes[active_mode].value, zone_config); + //LOG_TRACE("[%s] Updating LED %1d", controller->evgaGPUName, zone_idx); + controller->SetZone(zoneIndexMap[zone_idx], modes[active_mode].value, zone_config); } } void RGBController_EVGAGPUv3::UpdateZoneLEDs(int /*zone*/) { - //LOG_TRACE("[%s] Updating zone %1d", evga->evgaGPUName, zone); + //LOG_TRACE("[%s] Updating zone %1d", controller->evgaGPUName, zone); DeviceUpdateLEDs(); } void RGBController_EVGAGPUv3::UpdateSingleLED(int /*led*/) { - //LOG_TRACE("[%s] Updating single LED %1d", evga->evgaGPUName, led); + //LOG_TRACE("[%s] Updating single LED %1d", controller->evgaGPUName, led); DeviceUpdateLEDs(); } @@ -306,15 +307,15 @@ void RGBController_EVGAGPUv3::DeviceUpdateMode() /* Update all zone modes in a loop, each one with a packet to be use with per zone control for(uint8_t zone = 0; zone < 4; zone++) { - evga->SetZoneMode(zone, modes[active_mode].value); + controller->SetZoneMode(zone, modes[active_mode].value); } */ - //LOG_TRACE("[%s] Updating to mode %1d", evga->evgaGPUName, modes[active_mode].value); + //LOG_TRACE("[%s] Updating to mode %1d", controller->evgaGPUName, modes[active_mode].value); DeviceUpdateLEDs(); - evga->SetAllModes(modes[active_mode].value, modes[active_mode].value, modes[active_mode].value,modes[active_mode].value, true); //Set all zones to the same mode + controller->SetAllModes(modes[active_mode].value, modes[active_mode].value, modes[active_mode].value,modes[active_mode].value, true); //Set all zones to the same mode } void RGBController_EVGAGPUv3::DeviceSaveMode() { - evga->SaveConfig(); + controller->SaveConfig(); } diff --git a/Controllers/EVGAAmpereGPUController/RGBController_EVGAGPUv3.h b/Controllers/EVGAAmpereGPUController/RGBController_EVGAGPUv3.h index 94a14b47..a714cf94 100644 --- a/Controllers/EVGAAmpereGPUController/RGBController_EVGAGPUv3.h +++ b/Controllers/EVGAAmpereGPUController/RGBController_EVGAGPUv3.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_EVGAGPUv3.h | -| | -| Generic RGB Interface for OpenRGB | -| EVGA GPU RGB V3 (Ampere) Driver | -| | -| TheRogueZeta 7/15/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_EVGAGPUv3.h | +| | +| RGBController for EVGA V3 (Ampere) GPU | +| | +| TheRogueZeta 15 Jul 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once @@ -15,7 +17,7 @@ class RGBController_EVGAGPUv3 : public RGBController { public: - RGBController_EVGAGPUv3(EVGAGPUv3Controller* evga_ptr); + RGBController_EVGAGPUv3(EVGAGPUv3Controller* controller_ptr); ~RGBController_EVGAGPUv3(); void SetupZones(); @@ -30,7 +32,8 @@ public: void DeviceSaveMode(); private: - uint8_t getModeIndex(uint8_t mode_value); - EVGAGPUv3Controller* evga; + EVGAGPUv3Controller* controller; std::vector zoneIndexMap; + + uint8_t getModeIndex(uint8_t mode_value); }; diff --git a/Controllers/EVGAGP102GPUController/EVGAGP102Controller.cpp b/Controllers/EVGAGP102GPUController/EVGAGP102Controller.cpp index 92db1594..6118cb0c 100644 --- a/Controllers/EVGAGP102GPUController/EVGAGP102Controller.cpp +++ b/Controllers/EVGAGP102GPUController/EVGAGP102Controller.cpp @@ -1,20 +1,22 @@ -/*-----------------------------------------*\ -| EVGAGP102Controller.cpp | -| | -| Driver for EVGA GP102-based Nvidia GPUs | -| RGB controller for use with GeForce | -| GTX 1080 Ti FTW3 and K|NGP|N. | -| | -| Fabricio Murta (avengerx) 1/31/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| EVGAGP102Controller.cpp | +| | +| Driver for EVGA GP102 GPU | +| | +| Fabricio Murta (avengerx) 31 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "EVGAGP102Controller.h" #include "LogManager.h" -EVGAGP102Controller::EVGAGP102Controller(i2c_smbus_interface* bus_ptr, zoneinfo info) +EVGAGP102Controller::EVGAGP102Controller(i2c_smbus_interface* bus_ptr, zoneinfo info, std::string dev_name) { - bus = bus_ptr; - zi = info; + bus = bus_ptr; + zi = info; + name = dev_name; } EVGAGP102Controller::~EVGAGP102Controller() @@ -31,6 +33,16 @@ std::string EVGAGP102Controller::GetDeviceLocation() return("I2C: " + return_string); } +std::string EVGAGP102Controller::GetDeviceName() +{ + return(name); +} + +std::string EVGAGP102Controller::GetZoneName() +{ + return(zi.zone_name); +} + void EVGAGP102Controller::SetColor(unsigned char red, unsigned char green, unsigned char blue) { SendCommand(EVGA_GP102_CMD_BEGIN); @@ -62,8 +74,8 @@ bool EVGAGP102Controller::IsValid() { for (int i = 0; i < 3; i++) { - char res = bus->i2c_smbus_read_byte_data(zi.dev_addr, EVGA_GP102_REG_VALID); - if (res == 0x1F) + unsigned char res = bus->i2c_smbus_read_byte_data(zi.dev_addr, EVGA_GP102_REG_VALID); + if (res == 0x1F || res == 0x91) { LOG_TRACE("[%s] Zone discovery successful on address: 0x%02X.", EVGA_GP102_CONTROLLER_NAME, zi.dev_addr); return true; @@ -124,8 +136,3 @@ void EVGAGP102Controller::SaveSettings() //bus->i2c_smbus_write_byte_data(zi.dev_addr, 0x21, 0xE5); //bus->i2c_smbus_write_byte_data(zi.dev_addr, 0x22, 0xE7); } - -std::string EVGAGP102Controller::GetName() -{ - return zi.zone_name; -} diff --git a/Controllers/EVGAGP102GPUController/EVGAGP102Controller.h b/Controllers/EVGAGP102GPUController/EVGAGP102Controller.h index 6806e589..29a35085 100644 --- a/Controllers/EVGAGP102GPUController/EVGAGP102Controller.h +++ b/Controllers/EVGAGP102GPUController/EVGAGP102Controller.h @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| EVGAGP102Controller.h | -| | -| Definitions and types for EVGA | -| GP102-based Nvidia GPUs' RGB controller | -| GeForce GTX 1080 Ti K|NGP|N and FTW3. | -| | -| Fabricio Murta (avengerx) 1/31/2021 | -\*-----------------------------------------*/ - -#include -#include "i2c_smbus.h" -#include +/*---------------------------------------------------------*\ +| EVGAGP102Controller.h | +| | +| Driver for EVGA GP102 GPU | +| | +| Fabricio Murta (avengerx) 31 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "i2c_smbus.h" + #define EVGA_GP102_CONTROLLER_NAME "EVGA GP102 Nvidia GPU" enum @@ -63,23 +64,31 @@ const static zoneinfo gpuzoneinfos[] 0x00 }, { - "Backplate", + "Backplate", // for 1080Ti K|NGP|N 0x2A, {0x30, 0x31, 0x32}, 0xE9, 0xE0 - } + }, + { + "Backplate", // for 1080Ti FTW3 + 0x4F, + {0x30, 0x31, 0x32}, + 0x03, + 0x00 + }, }; class EVGAGP102Controller { public: - EVGAGP102Controller(i2c_smbus_interface* bus, zoneinfo info); + EVGAGP102Controller(i2c_smbus_interface* bus, zoneinfo info, std::string dev_name); ~EVGAGP102Controller(); bool IsValid(); std::string GetDeviceLocation(); - std::string GetName(); + std::string GetDeviceName(); + std::string GetZoneName(); unsigned char GetMode(); void SetColor(unsigned char red, unsigned char green, unsigned char blue); @@ -88,6 +97,10 @@ public: void SaveSettings(); private: + i2c_smbus_interface* bus; + zoneinfo zi; + std::string name; + bool CommandAcknowledged(); bool CommandCompleted(); s32 QueryCommand(s32 command); @@ -95,8 +108,4 @@ private: unsigned char GetRed(); unsigned char GetGreen(); unsigned char GetBlue(); - - i2c_smbus_interface* bus; - zoneinfo zi; - }; diff --git a/Controllers/EVGAGP102GPUController/EVGAGP102GPUControllerDetect.cpp b/Controllers/EVGAGP102GPUController/EVGAGP102GPUControllerDetect.cpp index 8a978cdf..1773e78f 100644 --- a/Controllers/EVGAGP102GPUController/EVGAGP102GPUControllerDetect.cpp +++ b/Controllers/EVGAGP102GPUController/EVGAGP102GPUControllerDetect.cpp @@ -1,37 +1,22 @@ +/*---------------------------------------------------------*\ +| EVGAGP102ControllerDetect.cpp | +| | +| Detector for EVGA GP102 GPU | +| | +| Fabricio Murta (avengerx) 31 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "EVGAGP102Controller.h" #include "LogManager.h" -#include "RGBController.h" #include "RGBController_EVGAGP102.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include - -typedef struct -{ - int pci_vendor; - int pci_device; - int pci_subsystem_vendor; - int pci_subsystem_device; - const char * name; -} gpu_pci_device; - -#define GPU_NUM_DEVICES (sizeof(device_list) / sizeof(device_list[ 0 ])) - -static const gpu_pci_device device_list[] = -{ - - { NVIDIA_VEN, NVIDIA_GTX1070_DEV, EVGA_SUB_VEN, EVGA_GTX1070_FTW2_SUB_DEV, "EVGA GeForce GTX 1070 FTW2 Gaming" }, - { NVIDIA_VEN, NVIDIA_GTX1080_DEV, EVGA_SUB_VEN, EVGA_GTX1080_FTW2_SUB_DEV, "EVGA GeForce GTX 1080 FTW2 Gaming" }, - { NVIDIA_VEN, NVIDIA_GTX1080_DEV, EVGA_SUB_VEN, EVGA_GTX1080_FTW2_11G_SUB_DEV, "EVGA GeForce GTX 1080 FTW2 11G" }, - { NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, EVGA_SUB_VEN, EVGA_GTX1080TI_SC2_GAMING_SUB_DEV, "EVGA GTX 1080 Ti SC2 Gaming" }, - { NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, EVGA_SUB_VEN, EVGA_GTX1080TI_FTW3_SUB_DEV, "EVGA GTX 1080 Ti FTW3" }, - { NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, EVGA_SUB_VEN, EVGA_GTX1080TI_FTW3_HYBRID_SUB_DEV, "EVGA 1080Ti FTW3 Hybrid" }, - { NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, EVGA_SUB_VEN, EVGA_GTX1080TI_KINGPIN_SUB_DEV, "EVGA GTX 1080 Ti K|NGP|N" }, - }; /******************************************************************************************\ * * * DetectEVGAGP102GPUControllers * @@ -39,51 +24,50 @@ static const gpu_pci_device device_list[] = * Detect EVGA GP102 GPU controllers on the enumerated I2C busses at address 0x49. * * * * bus - pointer to i2c_smbus_interface where EVGA GPU device is connected * -* dev - I2C address of EVGA GPU device * +* address - unused, the address comes from the GPU zone info table * +* name - name string of detected PCI device * * * \******************************************************************************************/ -void DetectEVGAGP102GPUControllers(std::vector& busses) +void DetectEVGAGP102GPUControllers(i2c_smbus_interface* bus, uint8_t /*address*/, const std::string& name) { - for (unsigned int bus = 0; bus < busses.size(); bus++) + if(bus->port_id == 1) { - for(unsigned int dev_idx = 0; dev_idx < GPU_NUM_DEVICES; dev_idx++) + RGBController_EVGAGP102* new_rgbcontroller; + std::vector controllers; + + for(unsigned int i = 0; i < sizeof(gpuzoneinfos) / sizeof(zoneinfo); i++) { - if (busses[bus]->port_id != 1) - { - break; - } + EVGAGP102Controller* controller = new EVGAGP102Controller(bus, gpuzoneinfos[i], name); - if(busses[bus]->pci_vendor == device_list[dev_idx].pci_vendor && - busses[bus]->pci_device == device_list[dev_idx].pci_device && - busses[bus]->pci_subsystem_vendor == device_list[dev_idx].pci_subsystem_vendor && - busses[bus]->pci_subsystem_device == device_list[dev_idx].pci_subsystem_device) + if(controller->IsValid()) { - LOG_DEBUG(GPU_DETECT_MESSAGE, EVGA_GP102_CONTROLLER_NAME, bus, device_list[dev_idx].pci_device, device_list[dev_idx].pci_subsystem_device, device_list[dev_idx].name ); - RGBController_EVGAGP102* new_rgbcontroller; - std::vector controllers; - - for(unsigned int i = 0; i < sizeof(gpuzoneinfos) / sizeof(zoneinfo); i++) - { - EVGAGP102Controller* contr = new EVGAGP102Controller(busses[bus], gpuzoneinfos[i]); - if (contr->IsValid()) - { - controllers.push_back(contr); - } - else - { - delete contr; - } - } - if(controllers.size() != 0) - { - new_rgbcontroller = new RGBController_EVGAGP102(controllers); - new_rgbcontroller->name = device_list[dev_idx].name; - ResourceManager::get()->RegisterRGBController(new_rgbcontroller); - } + controllers.push_back(controller); } + else + { + delete controller; + } + } + + if(controllers.size() != 0) + { + new_rgbcontroller = new RGBController_EVGAGP102(controllers); + + ResourceManager::get()->RegisterRGBController(new_rgbcontroller); } } } /* DetectEVGAGP102GPUControllers() */ -REGISTER_I2C_DETECTOR("EVGA GP102 GPU", DetectEVGAGP102GPUControllers); +/*---------------------------------------------------------*\ +| The I2C address is provided by the GPU Zone Info table, | +| as these GPUs have multiple I2C devices per card. | +\*---------------------------------------------------------*/ +REGISTER_I2C_PCI_DETECTOR( "EVGA GeForce GTX 1070 FTW2 Gaming", DetectEVGAGP102GPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, EVGA_SUB_VEN, EVGA_GTX1070_FTW2_SUB_DEV, 0x00 ); +REGISTER_I2C_PCI_DETECTOR( "EVGA GeForce GTX 1080 FTW2 Gaming", DetectEVGAGP102GPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, EVGA_SUB_VEN, EVGA_GTX1080_FTW2_SUB_DEV, 0x00 ); +REGISTER_I2C_PCI_DETECTOR( "EVGA GeForce GTX 1080 FTW2 11G", DetectEVGAGP102GPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, EVGA_SUB_VEN, EVGA_GTX1080_FTW2_11G_SUB_DEV, 0x00 ); +REGISTER_I2C_PCI_DETECTOR( "EVGA GeForce GTX 1080 FTW2 DT", DetectEVGAGP102GPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, EVGA_SUB_VEN, EVGA_GTX1080_FTW2_DT_SUB_DEV, 0x00 ); +REGISTER_I2C_PCI_DETECTOR( "EVGA GeForce GTX 1080 Ti SC2 Gaming", DetectEVGAGP102GPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, EVGA_SUB_VEN, EVGA_GTX1080TI_SC2_GAMING_SUB_DEV, 0x00 ); +REGISTER_I2C_PCI_DETECTOR( "EVGA GeForce GTX 1080 Ti FTW3", DetectEVGAGP102GPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, EVGA_SUB_VEN, EVGA_GTX1080TI_FTW3_SUB_DEV, 0x00 ); +REGISTER_I2C_PCI_DETECTOR( "EVGA GeForce GTX 1080 Ti FTW3 Hybrid", DetectEVGAGP102GPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, EVGA_SUB_VEN, EVGA_GTX1080TI_FTW3_HYBRID_SUB_DEV, 0x00 ); +REGISTER_I2C_PCI_DETECTOR( "EVGA GeForce GTX 1080 Ti K|NGP|N", DetectEVGAGP102GPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, EVGA_SUB_VEN, EVGA_GTX1080TI_KINGPIN_SUB_DEV, 0x00 ); diff --git a/Controllers/EVGAGP102GPUController/RGBController_EVGAGP102.cpp b/Controllers/EVGAGP102GPUController/RGBController_EVGAGP102.cpp index 6a80f373..1e0c7035 100644 --- a/Controllers/EVGAGP102GPUController/RGBController_EVGAGP102.cpp +++ b/Controllers/EVGAGP102GPUController/RGBController_EVGAGP102.cpp @@ -1,14 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_EVGAGPUv1.cpp | -| | -| Generic RGB Interface for OpenRGB EVGA | -| GP102-based Nvidia GPUs. | -| | -| Fabricio Murta (avengerx) 1/31/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_EVGAGP102.cpp | +| | +| RGBController for EVGA GP102 GPU | +| | +| Fabricio Murta (avengerx) 31 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_EVGAGP102.h" #include +#include "RGBController_EVGAGP102.h" /**------------------------------------------------------------------*\ @name EVGA GP102 GPU @@ -21,40 +23,40 @@ @comment \*-------------------------------------------------------------------*/ -RGBController_EVGAGP102::RGBController_EVGAGP102(std::vector evga_ptr) +RGBController_EVGAGP102::RGBController_EVGAGP102(std::vector controller_list) { - evga = evga_ptr; + controllers = controller_list; - name = "EVGA GP102 GPU"; - vendor = "EVGA"; - description = "EVGA GP102-based RGB GPU Device"; + name = controllers[0]->GetDeviceName(); + vendor = "EVGA"; + description = "EVGA GP102-based RGB GPU Device"; for(unsigned int i = 0; i < zones.size(); i++) { - location += evga[i]->GetDeviceLocation() + " "; + location += controllers[i]->GetDeviceLocation() + " "; } type = DEVICE_TYPE_GPU; mode Off; - Off.name = "Off"; - Off.value = EVGA_GP102_MODE_OFF; - Off.flags = 0; - Off.color_mode = MODE_COLORS_NONE; + Off.name = "Off"; + Off.value = EVGA_GP102_MODE_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; modes.push_back(Off); mode Direct; - Direct.name = "Direct"; - Direct.value = EVGA_GP102_MODE_CUSTOM; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = EVGA_GP102_MODE_CUSTOM; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); SetupZones(); // Initialize active mode and stored color - unsigned char raw_active_mode = evga[0]->GetMode(); + unsigned char raw_active_mode = controllers[0]->GetMode(); active_mode = 0; for(unsigned int i = 0; i < modes.size(); i++) @@ -67,7 +69,7 @@ RGBController_EVGAGP102::RGBController_EVGAGP102(std::vector rgb = evga[i]->GetColor(); + std::array rgb = controllers[i]->GetColor(); colors[i] = ToRGBColor(rgb[0], rgb[1], rgb[2]); } @@ -75,9 +77,9 @@ RGBController_EVGAGP102::RGBController_EVGAGP102(std::vectorGetName(); + new_zone.name = controllers[i]->GetZoneName(); new_zone.type = ZONE_TYPE_SINGLE; new_zone.leds_min = 1; new_zone.leds_max = 1; new_zone.leds_count = 1; new_zone.matrix_map = NULL; - new_led.name = evga[i]->GetName(); + new_led.name = controllers[i]->GetZoneName(); leds.push_back(new_led); zones.push_back(new_zone); @@ -131,7 +133,7 @@ void RGBController_EVGAGP102::UpdateZoneLEDs(int zone) unsigned char red = RGBGetRValue(color); unsigned char grn = RGBGetGValue(color); unsigned char blu = RGBGetBValue(color); - evga[zone]->SetColor(red, grn, blu); + controllers[zone]->SetColor(red, grn, blu); } void RGBController_EVGAGP102::UpdateSingleLED(int /*led*/) @@ -141,9 +143,9 @@ void RGBController_EVGAGP102::UpdateSingleLED(int /*led*/) void RGBController_EVGAGP102::DeviceUpdateMode() { - for(unsigned int i = 0; i < evga.size(); i++) + for(unsigned int i = 0; i < controllers.size(); i++) { - evga[i]->SetMode((unsigned char)modes[(unsigned int)active_mode].value); + controllers[i]->SetMode((unsigned char)modes[(unsigned int)active_mode].value); } } diff --git a/Controllers/EVGAGP102GPUController/RGBController_EVGAGP102.h b/Controllers/EVGAGP102GPUController/RGBController_EVGAGP102.h index 59edf12d..e8d796df 100644 --- a/Controllers/EVGAGP102GPUController/RGBController_EVGAGP102.h +++ b/Controllers/EVGAGP102GPUController/RGBController_EVGAGP102.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_EVGAGP102.h | -| | -| EVGA Generic RGB Interface for OpenRGB | -| EVGA GP102-based Nvidia GPUs. | -| | -| Fabricio Murta (avengerx) 1/31/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_EVGAGP102.h | +| | +| RGBController for EVGA GP102 GPU | +| | +| Fabricio Murta (avengerx) 31 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once @@ -15,7 +17,7 @@ class RGBController_EVGAGP102 : public RGBController { public: - RGBController_EVGAGP102(std::vector evga_ptr); + RGBController_EVGAGP102(std::vector controller_list); ~RGBController_EVGAGP102(); void SetupZones(); @@ -30,5 +32,5 @@ public: void DeviceSaveMode(); private: - std::vector evga; + std::vector controllers; }; diff --git a/Controllers/EVGAPascalGPUController/EVGAGPUv1Controller.cpp b/Controllers/EVGAPascalGPUController/EVGAGPUv1Controller.cpp index e243ce0f..d0b03727 100644 --- a/Controllers/EVGAPascalGPUController/EVGAGPUv1Controller.cpp +++ b/Controllers/EVGAPascalGPUController/EVGAGPUv1Controller.cpp @@ -1,18 +1,21 @@ -/*-----------------------------------------*\ -| EVGAGPUv1Controller.cpp | -| | -| Driver for EVGA GPU RGB V1 (Pascal) | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 9/11/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| EVGAGPUv1Controller.cpp | +| | +| Driver for EVGA V1 (Pascal) GPU | +| | +| Adam Honse (CalcProgrammer1) 11 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "EVGAGPUv1Controller.h" -EVGAGPUv1Controller::EVGAGPUv1Controller(i2c_smbus_interface* bus, evga_dev_id dev) +EVGAGPUv1Controller::EVGAGPUv1Controller(i2c_smbus_interface* bus, evga_dev_id dev, std::string dev_name) { - this->bus = bus; - this->dev = dev; + this->bus = bus; + this->dev = dev; + this->name = dev_name; } EVGAGPUv1Controller::~EVGAGPUv1Controller() @@ -30,6 +33,11 @@ std::string EVGAGPUv1Controller::GetDeviceLocation() return("I2C: " + return_string); } +std::string EVGAGPUv1Controller::GetDeviceName() +{ + return(name); +} + unsigned char EVGAGPUv1Controller::GetMode() { return(bus->i2c_smbus_read_byte_data(dev, EVGA_GPU_V1_REG_MODE)); diff --git a/Controllers/EVGAPascalGPUController/EVGAGPUv1Controller.h b/Controllers/EVGAPascalGPUController/EVGAGPUv1Controller.h index abeb97db..eef2d0a4 100644 --- a/Controllers/EVGAPascalGPUController/EVGAGPUv1Controller.h +++ b/Controllers/EVGAPascalGPUController/EVGAGPUv1Controller.h @@ -1,17 +1,19 @@ -/*-----------------------------------------*\ -| EVGAGPUv1Controller.h | -| | -| Definitions and types for EVGA GPU RGB | -| V1 (Pascal) lighting controller | -| | -| Adam Honse (CalcProgrammer1) 9/11/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| EVGAGPUv1Controller.h | +| | +| Driver for EVGA V1 (Pascal) GPU | +| | +| Adam Honse (CalcProgrammer1) 11 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" -#pragma once - typedef unsigned char evga_dev_id; #define EVGAGPUV1_CONTROLLER_NAME "EVGAv1" @@ -35,10 +37,11 @@ enum class EVGAGPUv1Controller { public: - EVGAGPUv1Controller(i2c_smbus_interface* bus, evga_dev_id dev); + EVGAGPUv1Controller(i2c_smbus_interface* bus, evga_dev_id dev, std::string dev_name); ~EVGAGPUv1Controller(); std::string GetDeviceLocation(); + std::string GetDeviceName(); unsigned char GetMode(); unsigned char GetRed(); @@ -52,5 +55,5 @@ public: private: i2c_smbus_interface* bus; evga_dev_id dev; - + std::string name; }; diff --git a/Controllers/EVGAPascalGPUController/EVGAPascalGPUControllerDetect.cpp b/Controllers/EVGAPascalGPUController/EVGAPascalGPUControllerDetect.cpp index 05128e89..5f83f753 100644 --- a/Controllers/EVGAPascalGPUController/EVGAPascalGPUControllerDetect.cpp +++ b/Controllers/EVGAPascalGPUController/EVGAPascalGPUControllerDetect.cpp @@ -1,33 +1,21 @@ +/*---------------------------------------------------------*\ +| EVGAGPUv1ControllerDetect.cpp | +| | +| Detector for EVGA V1 (Pascal) GPU | +| | +| Adam Honse (CalcProgrammer1) 11 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "EVGAGPUv1Controller.h" #include "LogManager.h" -#include "RGBController.h" #include "RGBController_EVGAGPUv1.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include -typedef struct -{ - int pci_vendor; - int pci_device; - int pci_subsystem_vendor; - int pci_subsystem_device; - const char * name; -} gpu_pci_device; - -#define GPU_NUM_DEVICES (sizeof(device_list) / sizeof(device_list[ 0 ])) - -static const gpu_pci_device device_list[] = -{ - { NVIDIA_VEN, NVIDIA_GTX1070_DEV, EVGA_SUB_VEN, EVGA_GTX1070_FTW_DT_GAMING_SUB_DEV, "EVGA GeForce GTX 1070 FTW DT Gaming" }, - { NVIDIA_VEN, NVIDIA_GTX1070_DEV, EVGA_SUB_VEN, EVGA_GTX1070_FTW_SUB_DEV, "EVGA GeForce GTX 1070 FTW" }, - { NVIDIA_VEN, NVIDIA_GTX1070_DEV, EVGA_SUB_VEN, EVGA_GTX1070_FTW_HYBRID_SUB_DEV, "EVGA GeForce GTX 1070 FTW HYBRID" }, - { NVIDIA_VEN, NVIDIA_GTX1070TI_DEV, EVGA_SUB_VEN, EVGA_GTX1070TI_FTW2_SUB_DEV, "EVGA GeForce GTX 1070 Ti FTW2" }, - { NVIDIA_VEN, NVIDIA_GTX1080_DEV, EVGA_SUB_VEN, EVGA_GTX1080_FTW_SUB_DEV, "EVGA GeForce GTX 1080 FTW" }, -}; /******************************************************************************************\ * * * DetectEVGAGPUControllers * @@ -39,33 +27,19 @@ static const gpu_pci_device device_list[] = * * \******************************************************************************************/ -void DetectEVGAPascalGPUControllers(std::vector& busses) +void DetectEVGAPascalGPUControllers(i2c_smbus_interface* bus, uint8_t address, const std::string& name) { - for (unsigned int bus = 0; bus < busses.size(); bus++) + if(bus->port_id == 1) { - for(unsigned int dev_idx = 0; dev_idx < GPU_NUM_DEVICES; dev_idx++) - { - if (busses[bus]->port_id != 1) - { - break; - } + EVGAGPUv1Controller* controller = new EVGAGPUv1Controller(bus, address, name); + RGBController_EVGAGPUv1* rgb_controller = new RGBController_EVGAGPUv1(controller); - if(busses[bus]->pci_vendor == device_list[dev_idx].pci_vendor && - busses[bus]->pci_device == device_list[dev_idx].pci_device && - busses[bus]->pci_subsystem_vendor == device_list[dev_idx].pci_subsystem_vendor && - busses[bus]->pci_subsystem_device == device_list[dev_idx].pci_subsystem_device) - { - LOG_DEBUG(GPU_DETECT_MESSAGE, EVGAGPUV1_CONTROLLER_NAME, bus, device_list[dev_idx].pci_device, device_list[dev_idx].pci_subsystem_device, device_list[dev_idx].name ); - EVGAGPUv1Controller* new_controller; - RGBController_EVGAGPUv1* new_rgbcontroller; - - new_controller = new EVGAGPUv1Controller(busses[bus], 0x49); - new_rgbcontroller = new RGBController_EVGAGPUv1(new_controller); - new_rgbcontroller->name = device_list[dev_idx].name; - ResourceManager::get()->RegisterRGBController(new_rgbcontroller); - } - } + ResourceManager::get()->RegisterRGBController(rgb_controller); } } /* DetectEVGAPascalGPUControllers() */ -REGISTER_I2C_DETECTOR("EVGA Pascal GPU", DetectEVGAPascalGPUControllers); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce GTX 1070 FTW DT Gaming", DetectEVGAPascalGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, EVGA_SUB_VEN, EVGA_GTX1070_FTW_DT_GAMING_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce GTX 1070 FTW", DetectEVGAPascalGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, EVGA_SUB_VEN, EVGA_GTX1070_FTW_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce GTX 1070 FTW HYBRID", DetectEVGAPascalGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, EVGA_SUB_VEN, EVGA_GTX1070_FTW_HYBRID_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce GTX 1070 Ti FTW2", DetectEVGAPascalGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070TI_DEV, EVGA_SUB_VEN, EVGA_GTX1070TI_FTW2_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce GTX 1080 FTW", DetectEVGAPascalGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, EVGA_SUB_VEN, EVGA_GTX1080_FTW_SUB_DEV, 0x49); diff --git a/Controllers/EVGAPascalGPUController/RGBController_EVGAGPUv1.cpp b/Controllers/EVGAPascalGPUController/RGBController_EVGAGPUv1.cpp index f01b7693..66082d45 100644 --- a/Controllers/EVGAPascalGPUController/RGBController_EVGAGPUv1.cpp +++ b/Controllers/EVGAPascalGPUController/RGBController_EVGAGPUv1.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_EVGAGPUv1.cpp | -| | -| Generic RGB Interface for OpenRGB EVGA | -| GPU V1 (Pascal) Driver | -| | -| Adam Honse (CalcProgrammer1) 9/11/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_EVGAGPUv1.cpp | +| | +| RGBController for EVGA V1 (Pascal) GPU | +| | +| Adam Honse (CalcProgrammer1) 11 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_EVGAGPUv1.h" @@ -20,50 +22,49 @@ @comment \*-------------------------------------------------------------------*/ -RGBController_EVGAGPUv1::RGBController_EVGAGPUv1(EVGAGPUv1Controller* evga_ptr) +RGBController_EVGAGPUv1::RGBController_EVGAGPUv1(EVGAGPUv1Controller* controller_ptr) { - evga = evga_ptr; + controller = controller_ptr; - name = "EVGA GPU"; - vendor = "EVGA"; - description = "EVGA RGB v1 GPU Device"; - location = evga->GetDeviceLocation(); - - type = DEVICE_TYPE_GPU; + name = controller->GetDeviceName(); + vendor = "EVGA"; + description = "EVGA RGB v1 GPU Device"; + location = controller->GetDeviceLocation(); + type = DEVICE_TYPE_GPU; mode Off; - Off.name = "Off"; - Off.value = EVGA_GPU_V1_MODE_OFF; - Off.flags = MODE_FLAG_MANUAL_SAVE; - Off.color_mode = MODE_COLORS_NONE; + Off.name = "Off"; + Off.value = EVGA_GPU_V1_MODE_OFF; + Off.flags = MODE_FLAG_MANUAL_SAVE; + Off.color_mode = MODE_COLORS_NONE; modes.push_back(Off); mode Direct; - Direct.name = "Direct"; - Direct.value = EVGA_GPU_V1_MODE_CUSTOM; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = EVGA_GPU_V1_MODE_CUSTOM; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); mode Rainbow; - Rainbow.name = "Rainbow"; - Rainbow.value = EVGA_GPU_V1_MODE_RAINBOW; - Rainbow.flags = MODE_FLAG_MANUAL_SAVE; - Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.name = "Rainbow"; + Rainbow.value = EVGA_GPU_V1_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_MANUAL_SAVE; + Rainbow.color_mode = MODE_COLORS_NONE; modes.push_back(Rainbow); mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = EVGA_GPU_V1_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; - Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.name = "Breathing"; + Breathing.value = EVGA_GPU_V1_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + Breathing.color_mode = MODE_COLORS_PER_LED; modes.push_back(Breathing); SetupZones(); // Initialize active mode and stored color - unsigned char raw_active_mode = evga->GetMode(); + unsigned char raw_active_mode = controller->GetMode(); active_mode = 0; for(unsigned int i = 0; i < modes.size(); i++) @@ -75,9 +76,9 @@ RGBController_EVGAGPUv1::RGBController_EVGAGPUv1(EVGAGPUv1Controller* evga_ptr) } } - unsigned char r = evga->GetRed(); - unsigned char g = evga->GetGreen(); - unsigned char b = evga->GetBlue(); + unsigned char r = controller->GetRed(); + unsigned char g = controller->GetGreen(); + unsigned char b = controller->GetBlue(); RGBColor color = ToRGBColor(r, g, b); colors[0] = color; @@ -85,7 +86,7 @@ RGBController_EVGAGPUv1::RGBController_EVGAGPUv1(EVGAGPUv1Controller* evga_ptr) RGBController_EVGAGPUv1::~RGBController_EVGAGPUv1() { - delete evga; + delete controller; } void RGBController_EVGAGPUv1::SetupZones() @@ -129,7 +130,7 @@ void RGBController_EVGAGPUv1::DeviceUpdateLEDs() unsigned char grn = RGBGetGValue(color); unsigned char blu = RGBGetBValue(color); - evga->SetColor(red, grn, blu); + controller->SetColor(red, grn, blu); } void RGBController_EVGAGPUv1::UpdateZoneLEDs(int /*zone*/) @@ -144,10 +145,10 @@ void RGBController_EVGAGPUv1::UpdateSingleLED(int /*led*/) void RGBController_EVGAGPUv1::DeviceUpdateMode() { - evga->SetMode((unsigned char)modes[(unsigned int)active_mode].value); + controller->SetMode((unsigned char)modes[(unsigned int)active_mode].value); } void RGBController_EVGAGPUv1::DeviceSaveMode() { - evga->SaveSettings(); + controller->SaveSettings(); } diff --git a/Controllers/EVGAPascalGPUController/RGBController_EVGAGPUv1.h b/Controllers/EVGAPascalGPUController/RGBController_EVGAGPUv1.h index 716b0dfa..a3efd49f 100644 --- a/Controllers/EVGAPascalGPUController/RGBController_EVGAGPUv1.h +++ b/Controllers/EVGAPascalGPUController/RGBController_EVGAGPUv1.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_EVGAGPUv1.h | -| | -| Generic RGB Interface for OpenRGB | -| EVGA GPU RGB V1 (Pascal) Driver | -| | -| Adam Honse (CalcProgrammer1) 9/11/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_EVGAGPUv1.h | +| | +| RGBController for EVGA V1 (Pascal) GPU | +| | +| Adam Honse (CalcProgrammer1) 11 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once @@ -15,7 +17,7 @@ class RGBController_EVGAGPUv1 : public RGBController { public: - RGBController_EVGAGPUv1(EVGAGPUv1Controller* evga_ptr); + RGBController_EVGAGPUv1(EVGAGPUv1Controller* controller_ptr); ~RGBController_EVGAGPUv1(); void SetupZones(); @@ -30,5 +32,5 @@ public: void DeviceSaveMode(); private: - EVGAGPUv1Controller* evga; + EVGAGPUv1Controller* controller; }; diff --git a/Controllers/EVGASMBusController/EVGAACX30SMBusController.cpp b/Controllers/EVGASMBusController/EVGAACX30SMBusController.cpp new file mode 100644 index 00000000..88b82ba7 --- /dev/null +++ b/Controllers/EVGASMBusController/EVGAACX30SMBusController.cpp @@ -0,0 +1,109 @@ +/*---------------------------------------------------------*\ +| EVGAACX30SMBusController.cpp | +| | +| Driver for SMBus EVGA ACX 30 motherboards | +| | +| Balázs Triszka (balika011) 21 May 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "EVGAACX30SMBusController.h" +#include "dmiinfo.h" +#include "LogManager.h" + +using namespace std::chrono_literals; + +EVGAACX30SMBusController::EVGAACX30SMBusController(i2c_smbus_interface *bus, uint8_t dev) +{ + this->bus = bus; + this->dev = dev; + + DMIInfo dmi; + + device_name = "EVGA " + dmi.getMainboard(); +} + +EVGAACX30SMBusController::~EVGAACX30SMBusController() +{ + +} + +std::string EVGAACX30SMBusController::GetDeviceLocation() +{ + std::string return_string(bus->device_name); + char addr[5]; + snprintf(addr, 5, "0x%02X", dev); + return_string.append(", address "); + return_string.append(addr); + return("I2C: " + return_string); +} + +std::string EVGAACX30SMBusController::GetDeviceName() +{ + return(device_name); +} + +std::string EVGAACX30SMBusController::GetFirmwareVersion() +{ + uint16_t version = bus->i2c_smbus_read_byte_data(dev, ACX30_REG_VER_HIGH) << 8 | bus->i2c_smbus_read_byte_data(dev, ACX30_REG_VER_LOW); + uint8_t ptype = bus->i2c_smbus_read_byte_data(dev, ACX30_REG_PTYPE); + + char ver[9]; + snprintf(ver, 9, "0x%X", version); + char pt[9]; + snprintf(pt, 9, "0x%X", ptype); + + std::string return_string; + return_string.append(ver); + return_string.append(", ptype "); + return_string.append(pt); + return return_string; +} + +uint8_t EVGAACX30SMBusController::GetMode() +{ + return bus->i2c_smbus_read_byte_data(dev, ACX30_REG_MODE); +} + +void EVGAACX30SMBusController::Unlock() +{ + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_CONTROL, 0xE5); + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_CONTROL, 0xE9); + bus->i2c_smbus_read_byte_data(dev, ACX30_REG_CONTROL); +} + +void EVGAACX30SMBusController::Lock() +{ + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_CONTROL, 0xE0); + bus->i2c_smbus_read_byte_data(dev, ACX30_REG_CONTROL); +} + +void EVGAACX30SMBusController::SetColors(uint8_t red, uint8_t green, uint8_t blue) +{ + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_RED, red); + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_GREEN, green); + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_BLUE, blue); +} + +void EVGAACX30SMBusController::SetMode(uint8_t mode) +{ + if (mode == ACX30_MODE_OFF) + { + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_21, 0xE7); + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_22, 0xCE); + } + else + { + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_21, 0xE5); + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_22, 0xE7); + } + + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_MODE, mode); +} + +void EVGAACX30SMBusController::SetSpeed(uint8_t speed) +{ + bus->i2c_smbus_write_byte_data(dev, ACX30_REG_SPEED, speed); +} diff --git a/Controllers/EVGASMBusController/EVGAACX30SMBusController.h b/Controllers/EVGASMBusController/EVGAACX30SMBusController.h new file mode 100644 index 00000000..0fb92721 --- /dev/null +++ b/Controllers/EVGASMBusController/EVGAACX30SMBusController.h @@ -0,0 +1,76 @@ +/*---------------------------------------------------------*\ +| EVGAACX30SMBusController.h | +| | +| Driver for SMBus EVGA ACX 30 motherboards | +| | +| Balázs Triszka (balika011) 21 May 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "i2c_smbus.h" + +enum +{ + /*------------------------------------------------------------------------------------------*\ + | Acx30 Common Registers | + \*------------------------------------------------------------------------------------------*/ + ACX30_REG_01 = 0x01, + ACX30_REG_PTYPE = 0x03, + ACX30_REG_VER_LOW = 0x04, + ACX30_REG_VER_HIGH = 0x05, + ACX30_REG_RED = 0x09, + ACX30_REG_GREEN = 0x0A, + ACX30_REG_BLUE = 0x0B, + ACX30_REG_MODE = 0x0C, + ACX30_REG_CONTROL = 0x0E, + ACX30_REG_SPEED = 0x19, + ACX30_REG_20 = 0x20, + ACX30_REG_21 = 0x21, + ACX30_REG_22 = 0x22, +}; + +/*----------------------------------------------------------------------------------------------*\ +| Definitions for Acx30 | +\*----------------------------------------------------------------------------------------------*/ + +enum +{ + ACX30_MODE_OFF = 0x00, /* OFF mode */ + ACX30_MODE_STATIC = 0x01, /* Static color mode */ + ACX30_MODE_SPECTRUM_CYCLE = 0x02, /* Spectrum Cycle effect mode */ + ACX30_MODE_BREATHING = 0x05, /* Breathing effect mode */ +}; + +enum +{ + ACX30_SPEED_MIN = 0x00, /* Slowest speed */ + ACX30_SPEED_DEFAULT = 0x04, /* Default speed */ + ACX30_SPEED_MAX = 0xFF, /* Fastest speed */ +}; + +class EVGAACX30SMBusController +{ +public: + EVGAACX30SMBusController(i2c_smbus_interface *bus, uint8_t dev); + ~EVGAACX30SMBusController(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + std::string GetFirmwareVersion(); + uint8_t GetMode(); + void Unlock(); + void Lock(); + void SetColors(uint8_t red, uint8_t green, uint8_t blue); + void SetMode(uint8_t mode); + void SetSpeed(uint8_t speed); + +private: + std::string device_name; + i2c_smbus_interface* bus; + uint8_t dev; +}; diff --git a/Controllers/EVGASMBusController/EVGASMBusControllerDetect.cpp b/Controllers/EVGASMBusController/EVGASMBusControllerDetect.cpp new file mode 100644 index 00000000..48bb8e2a --- /dev/null +++ b/Controllers/EVGASMBusController/EVGASMBusControllerDetect.cpp @@ -0,0 +1,87 @@ +/*---------------------------------------------------------*\ +| EVGASMBusControllerDetect.cpp | +| | +| Detector for SMBus EVGA ACX 30 motherboards | +| | +| Balázs Triszka (balika011) 21 May 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "EVGAACX30SMBusController.h" +#include "LogManager.h" +#include "RGBController_EVGAACX30SMBus.h" +#include "i2c_smbus.h" +#include "pci_ids.h" + +/******************************************************************************************\ +* * +* TestForAcx30SMBusController * +* * +* Tests the given address to see if an EVGA ACX 30 controller exists there. * +* First does a quick write to test for a response * +* Then checks if it has 1st bit set in register 1 * +* * +\******************************************************************************************/ + +#define EVGA_DETECTOR_NAME "EVGA SMBus Detectector" +#define VENDOR_NAME "EVGA" +#define SMBUS_ADDRESS 0x28 + +bool TestForAcx30SMBusController(i2c_smbus_interface *bus, uint8_t address) +{ + bool pass = false; + + int res = bus->i2c_smbus_write_quick(address, I2C_SMBUS_WRITE); + + if (res >= 0) + { + res = bus->i2c_smbus_read_byte_data(address, 0x01); + + if (res > 0 && (res & 1)) + { + pass = true; + } + } + + return(pass); +} /* TestForAcx30SMBusController() */ + +/******************************************************************************************\ +* * +* DetectAcx30SMBusControllers * +* * +* Detect EVGA ACX 30 SMBus controllers on the enumerated I2C busses at address 0x28. * +* * +\******************************************************************************************/ + +void DetectAcx30SMBusControllers(std::vector &busses) +{ + for(unsigned int bus = 0; bus < busses.size(); bus++) + { + IF_MOBO_SMBUS(busses[bus]->pci_vendor, busses[bus]->pci_device) + { + if(busses[bus]->pci_subsystem_vendor == EVGA_SUB_VEN) + { + LOG_DEBUG(SMBUS_CHECK_DEVICE_MESSAGE_EN, EVGA_DETECTOR_NAME, bus, VENDOR_NAME, SMBUS_ADDRESS); + // Check for ACX 30 controller at 0x28 + if(TestForAcx30SMBusController(busses[bus], SMBUS_ADDRESS)) + { + EVGAACX30SMBusController *controller = new EVGAACX30SMBusController(busses[bus], SMBUS_ADDRESS); + RGBController_EVGAACX30SMBus *rgb_controller = new RGBController_EVGAACX30SMBus(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + } + else + { + LOG_DEBUG(SMBUS_CHECK_DEVICE_FAILURE_EN, EVGA_DETECTOR_NAME, bus, VENDOR_NAME); + } + } + } +} /* DetectAcx30SMBusControllers() */ + +REGISTER_I2C_DETECTOR("EVGA Motherboard SMBus Controllers", DetectAcx30SMBusControllers); diff --git a/Controllers/EVGASMBusController/RGBController_EVGAACX30SMBus.cpp b/Controllers/EVGASMBusController/RGBController_EVGAACX30SMBus.cpp new file mode 100644 index 00000000..469f8bae --- /dev/null +++ b/Controllers/EVGASMBusController/RGBController_EVGAACX30SMBus.cpp @@ -0,0 +1,163 @@ +/*---------------------------------------------------------*\ +| RGBController_EVGAACX30SMBus.cpp | +| | +| RGBController for SMBus EVGA ACX 30 motherboards | +| | +| Balázs Triszka (balika011) 21 May 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_EVGAACX30SMBus.h" + +/**------------------------------------------------------------------*\ + @name EVGA ACX 30 + @category Motherboard + @type SMBus + @save :robot: + @direct :x: + @effects :white_check_mark: + @detectors DetectAcx30SMBusControllers + @comment EVGA ACX 30 LED controllers will save with each update. + Per ARGB LED support is not possible with these devices. +\*-------------------------------------------------------------------*/ + +RGBController_EVGAACX30SMBus::RGBController_EVGAACX30SMBus(EVGAACX30SMBusController *controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "EVGA"; + version = controller->GetFirmwareVersion(); + type = DEVICE_TYPE_MOTHERBOARD; + description = "EVGA ACX 30 LED Device"; + location = controller->GetDeviceLocation(); + active_mode = controller->GetMode(); + + mode Off; + Off.name = "Off"; + Off.value = ACX30_MODE_OFF; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Static; + Static.name = "Static"; + Static.value = ACX30_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Static.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Static); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = ACX30_MODE_SPECTRUM_CYCLE; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + SpectrumCycle.speed_min = ACX30_SPEED_MIN; + SpectrumCycle.speed_max = ACX30_SPEED_MAX; + SpectrumCycle.speed = ACX30_SPEED_DEFAULT; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + modes.push_back(SpectrumCycle); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = ACX30_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.speed_min = ACX30_SPEED_MIN; + Breathing.speed_max = ACX30_SPEED_MAX; + Breathing.speed = ACX30_SPEED_DEFAULT; + Breathing.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Breathing); + + SetupZones(); +} + +RGBController_EVGAACX30SMBus::~RGBController_EVGAACX30SMBus() +{ + delete controller; +} + +void RGBController_EVGAACX30SMBus::SetupZones() +{ + /*---------------------------------------------------------*\ + | Acx30 motherboards only have a single zone/LED | + \*---------------------------------------------------------*/ + + /*---------------------------------------------------------*\ + | Set up zones | + \*---------------------------------------------------------*/ + zone* new_zone = new zone(); + + /*---------------------------------------------------------*\ + | Set single zone name to "Motherboard" | + \*---------------------------------------------------------*/ + new_zone->name = "Motherboard"; + new_zone->type = ZONE_TYPE_SINGLE; + new_zone->leds_min = 1; + new_zone->leds_max = 1; + new_zone->leds_count = 1; + new_zone->matrix_map = NULL; + + /*---------------------------------------------------------*\ + | Push new zone to zones vector | + \*---------------------------------------------------------*/ + zones.push_back(*new_zone); + + /*---------------------------------------------------------*\ + | Set up LEDs | + \*---------------------------------------------------------*/ + led* new_led = new led(); + + /*---------------------------------------------------------*\ + | Set single LED name to "Motherboard" | + \*---------------------------------------------------------*/ + new_led->name = "Motherboard"; + + /*---------------------------------------------------------*\ + | Push new LED to LEDs vector | + \*---------------------------------------------------------*/ + leds.push_back(*new_led); + + SetupColors(); +} + +void RGBController_EVGAACX30SMBus::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_EVGAACX30SMBus::DeviceUpdateLEDs() +{ + for(unsigned int led = 0; led < colors.size(); led++) + { + UpdateSingleLED(led); + } +} + +void RGBController_EVGAACX30SMBus::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_EVGAACX30SMBus::UpdateSingleLED(int led) +{ + unsigned char red = RGBGetRValue(colors[led]); + unsigned char grn = RGBGetGValue(colors[led]); + unsigned char blu = RGBGetBValue(colors[led]); + + controller->Unlock(); + controller->SetColors(red, grn, blu); + controller->Lock(); +} + +void RGBController_EVGAACX30SMBus::DeviceUpdateMode() +{ + controller->Unlock(); + controller->SetMode(modes[active_mode].value); + controller->SetSpeed(modes[active_mode].speed); + controller->Lock(); + + DeviceUpdateLEDs(); +} diff --git a/Controllers/EVGASMBusController/RGBController_EVGAACX30SMBus.h b/Controllers/EVGASMBusController/RGBController_EVGAACX30SMBus.h new file mode 100644 index 00000000..72ffd438 --- /dev/null +++ b/Controllers/EVGASMBusController/RGBController_EVGAACX30SMBus.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_EVGAACX30SMBus.h | +| | +| RGBController for SMBus EVGA ACX 30 motherboards | +| | +| Balázs Triszka (balika011) 21 May 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "EVGAACX30SMBusController.h" + +class RGBController_EVGAACX30SMBus : public RGBController +{ +public: + RGBController_EVGAACX30SMBus(EVGAACX30SMBusController* controller_ptr); + ~RGBController_EVGAACX30SMBus(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + EVGAACX30SMBusController *controller; +}; diff --git a/Controllers/EVGATuringGPUController/EVGAGPUv2Controller.cpp b/Controllers/EVGATuringGPUController/EVGAGPUv2Controller.cpp index 39413d2c..928f92a0 100644 --- a/Controllers/EVGATuringGPUController/EVGAGPUv2Controller.cpp +++ b/Controllers/EVGATuringGPUController/EVGAGPUv2Controller.cpp @@ -1,18 +1,21 @@ -/*-----------------------------------------*\ -| EVGAGPUv2Controller.cpp | -| | -| Driver for EVGA GPU RGB V2 (Turing) | -| lighting controller | -| | -| TheRogueZeta 4/15/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| EVGAGPUv2Controller.cpp | +| | +| Driver for EVGA V2 (Turing) GPU | +| | +| TheRogueZeta 15 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "EVGAGPUv2Controller.h" -EVGAGPUv2Controller::EVGAGPUv2Controller(i2c_smbus_interface* bus, evga_dev_id dev) +EVGAGPUv2Controller::EVGAGPUv2Controller(i2c_smbus_interface* bus, evga_dev_id dev, std::string dev_name) { - this->bus = bus; - this->dev = dev; + this->bus = bus; + this->dev = dev; + this->name = dev_name; } EVGAGPUv2Controller::~EVGAGPUv2Controller() @@ -31,6 +34,11 @@ std::string EVGAGPUv2Controller::GetDeviceLocation() return("I2C: " + return_string); } +std::string EVGAGPUv2Controller::GetDeviceName() +{ + return(name); +} + unsigned char EVGAGPUv2Controller::GetBrightnessA() { return(bus->i2c_smbus_read_byte_data(dev, EVGA_GPU_V2_REG_COLOR_A_BRIGHTNESS)); @@ -70,7 +78,7 @@ unsigned char EVGAGPUv2Controller::GetMode() return_mode = EVGA_GPU_V2_RGB_MODE_OFF; } break; - + case EVGA_GPU_V2_MODE_STATIC: { return_mode = EVGA_GPU_V2_RGB_MODE_STATIC; @@ -87,8 +95,8 @@ unsigned char EVGAGPUv2Controller::GetMode() { u16_to_u8 speed_16 = { (uint16_t) 0 }; - speed_16.LSB = bus->i2c_smbus_read_byte_data(dev, EVGA_GPU_V2_REG_B_TO_A_SPEED_LSB); - speed_16.MSB = bus->i2c_smbus_read_byte_data(dev, EVGA_GPU_V2_REG_B_TO_A_SPEED_MSB); + speed_16.lsb = bus->i2c_smbus_read_byte_data(dev, EVGA_GPU_V2_REG_B_TO_A_SPEED_LSB); + speed_16.msb = bus->i2c_smbus_read_byte_data(dev, EVGA_GPU_V2_REG_B_TO_A_SPEED_MSB); if (speed_16.u16 == 0) { @@ -112,8 +120,8 @@ unsigned char EVGAGPUv2Controller::GetSpeed() { u16_to_u8 speed_16 = { (uint16_t) 0 }; - speed_16.LSB = bus->i2c_smbus_read_byte_data(dev, EVGA_GPU_V2_REG_COLOR_A_ONTIME_LSB); - speed_16.MSB = bus->i2c_smbus_read_byte_data(dev, EVGA_GPU_V2_REG_COLOR_A_ONTIME_MSB); + speed_16.lsb = bus->i2c_smbus_read_byte_data(dev, EVGA_GPU_V2_REG_COLOR_A_ONTIME_LSB); + speed_16.msb = bus->i2c_smbus_read_byte_data(dev, EVGA_GPU_V2_REG_COLOR_A_ONTIME_MSB); speed_16.u16 /= SPEED_MULTIPLIER; @@ -235,16 +243,16 @@ void EVGAGPUv2Controller::SendMode(uint8_t mode) void EVGAGPUv2Controller::SendSpeed(u16_to_u8 aOnTime, u16_to_u8 bOnTime, u16_to_u8 b2a, u16_to_u8 a2b, u16_to_u8 speed_un) { - bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_COLOR_B_UN_LSB, (unsigned char) speed_un.LSB ); - bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_COLOR_B_UN_MSB, (unsigned char) speed_un.MSB ); - bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_B_TO_A_SPEED_LSB, (unsigned char) b2a.LSB ); - bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_B_TO_A_SPEED_MSB, (unsigned char) b2a.MSB ); - bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_COLOR_B_ONTIME_LSB, (unsigned char) bOnTime.LSB ); - bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_COLOR_B_ONTIME_MSB, (unsigned char) bOnTime.MSB ); - bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_A_TO_B_SPEED_LSB, (unsigned char) a2b.LSB ); - bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_A_TO_B_SPEED_MSB, (unsigned char) a2b.MSB ); - bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_COLOR_A_ONTIME_LSB, (unsigned char) aOnTime.LSB ); - bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_COLOR_A_ONTIME_MSB, (unsigned char) aOnTime.MSB ); + bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_COLOR_B_UN_LSB, (unsigned char) speed_un.lsb ); + bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_COLOR_B_UN_MSB, (unsigned char) speed_un.msb ); + bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_B_TO_A_SPEED_LSB, (unsigned char) b2a.lsb ); + bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_B_TO_A_SPEED_MSB, (unsigned char) b2a.msb ); + bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_COLOR_B_ONTIME_LSB, (unsigned char) bOnTime.lsb ); + bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_COLOR_B_ONTIME_MSB, (unsigned char) bOnTime.msb ); + bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_A_TO_B_SPEED_LSB, (unsigned char) a2b.lsb ); + bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_A_TO_B_SPEED_MSB, (unsigned char) a2b.msb ); + bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_COLOR_A_ONTIME_LSB, (unsigned char) aOnTime.lsb ); + bus->i2c_smbus_write_byte_data(dev, EVGA_GPU_V2_REG_COLOR_A_ONTIME_MSB, (unsigned char) aOnTime.msb ); } void EVGAGPUv2Controller::SetColor(RGBColor colorA, RGBColor colorB, uint8_t brightness) diff --git a/Controllers/EVGATuringGPUController/EVGAGPUv2Controller.h b/Controllers/EVGATuringGPUController/EVGAGPUv2Controller.h index fba55feb..334e881c 100644 --- a/Controllers/EVGATuringGPUController/EVGAGPUv2Controller.h +++ b/Controllers/EVGATuringGPUController/EVGAGPUv2Controller.h @@ -1,18 +1,20 @@ -/*-----------------------------------------*\ -| EVGAGPUv2Controller.h | -| | -| Definitions and types for EVGA GPU RGB | -| V2 (Turing) lighting controller | -| | -| TheRogueZeta 4/15/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| EVGAGPUv2Controller.h | +| | +| Driver for EVGA V2 (Turing) GPU | +| | +| TheRogueZeta 15 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" #include "RGBController.h" -#pragma once - typedef unsigned char evga_dev_id; #define SPEED_MULTIPLIER 10 @@ -26,8 +28,8 @@ union u16_to_u8 uint16_t u16; struct { - uint8_t LSB; - uint8_t MSB; + uint8_t lsb; + uint8_t msb; }; }; @@ -66,7 +68,7 @@ enum enum { EVGA_GPU_V2_MODE_OFF = 0x00, - EVGA_GPU_V2_MODE_STATIC = 0x01, + EVGA_GPU_V2_MODE_STATIC = 0x01, EVGA_GPU_V2_MODE_RAINBOW = 0x0F, EVGA_GPU_V2_MODE_BREATHING = 0x22, }; @@ -84,10 +86,11 @@ enum class EVGAGPUv2Controller { public: - EVGAGPUv2Controller(i2c_smbus_interface* bus, evga_dev_id dev); + EVGAGPUv2Controller(i2c_smbus_interface* bus, evga_dev_id dev, std::string dev_name); ~EVGAGPUv2Controller(); std::string GetDeviceLocation(); + std::string GetDeviceName(); unsigned char GetBrightnessA(); RGBColor GetColorA(); @@ -108,4 +111,5 @@ private: i2c_smbus_interface* bus; evga_dev_id dev; + std::string name; }; diff --git a/Controllers/EVGATuringGPUController/EVGATuringGPUControllerDetect.cpp b/Controllers/EVGATuringGPUController/EVGATuringGPUControllerDetect.cpp index d6d262d0..1b013357 100644 --- a/Controllers/EVGATuringGPUController/EVGATuringGPUControllerDetect.cpp +++ b/Controllers/EVGATuringGPUController/EVGATuringGPUControllerDetect.cpp @@ -1,12 +1,19 @@ +/*---------------------------------------------------------*\ +| EVGATuringGPUControllerDetect.cpp | +| | +| Detector for EVGA V2 (Turing) GPU | +| | +| TheRogueZeta 15 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "EVGAGPUv2Controller.h" -#include "RGBController.h" #include "RGBController_EVGAGPUv2.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include /******************************************************************************************\ * * @@ -21,14 +28,11 @@ void DetectEVGATuringGPUControllers(i2c_smbus_interface* bus, uint8_t address, const std::string& name) { - if (bus->port_id == 1) + if(bus->port_id == 1) { - EVGAGPUv2Controller* controller; - RGBController_EVGAGPUv2* rgb_controller; + EVGAGPUv2Controller* controller = new EVGAGPUv2Controller(bus, address, name); + RGBController_EVGAGPUv2* rgb_controller = new RGBController_EVGAGPUv2(controller); - controller = new EVGAGPUv2Controller(bus, address); - rgb_controller = new RGBController_EVGAGPUv2(controller); - rgb_controller->name = name.c_str(); ResourceManager::get()->RegisterRGBController(rgb_controller); } } /* DetectEVGATuringGPUControllers() */ @@ -45,13 +49,14 @@ REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080 Black" REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080 XC Black" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, EVGA_SUB_VEN, EVGA_RTX2080_XC_BLACK_SUB_DEV, 0x49); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080 XC Gaming" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, EVGA_SUB_VEN, EVGA_RTX2080_XC_GAMING_SUB_DEV, 0x49); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080 XC Ultra Gaming" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, EVGA_SUB_VEN, EVGA_RTX2080_XC_ULTRA_GAMING_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080 XC Hybrid Gaming" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, EVGA_SUB_VEN, EVGA_RTX2080_XC_HYBRID_GAMING_SUB_DEV, 0x49); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080 SUPER XC Gaming" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, EVGA_SUB_VEN, EVGA_RTX2080S_XC_GAMING_SUB_DEV, 0x49); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080 SUPER XC Ultra" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, EVGA_SUB_VEN, EVGA_RTX2080S_XC_ULTRA_SUB_DEV, 0x49); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080 SUPER FTW3 Ultra" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, EVGA_SUB_VEN, EVGA_RTX2080S_FTW3_ULTRA_SUB_DEV, 0x49); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080 SUPER FTW3 Hybrid OC" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, EVGA_SUB_VEN, EVGA_RTX2080S_FTW3_HYBRID_OC_SUB_DEV, 0x49); REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080 SUPER FTW3 Ultra Hydro Copper" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, EVGA_SUB_VEN, EVGA_RTX2080S_FTW3_ULTRA_HC_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080Ti Black" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_DEV, EVGA_SUB_VEN, EVGA_RTX2080TI_BLACK_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080Ti XC Ultra" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, EVGA_SUB_VEN, EVGA_RTX2080TI_XC_ULTRA_GAMING_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080Ti XC HYBRID GAMING" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, EVGA_SUB_VEN, EVGA_RTX2080TI_XC_HYBRID_GAMING_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080Ti XC HYDRO COPPER" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_DEV, EVGA_SUB_VEN, EVGA_RTX2080TI_XC_HYDRO_COPPER_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080Ti FTW3 Ultra" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, EVGA_SUB_VEN, EVGA_RTX2080TI_FTW3_ULTRA_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080 Ti Black" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_DEV, EVGA_SUB_VEN, EVGA_RTX2080TI_BLACK_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080 Ti XC Ultra" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, EVGA_SUB_VEN, EVGA_RTX2080TI_XC_ULTRA_GAMING_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080 Ti XC HYBRID GAMING" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, EVGA_SUB_VEN, EVGA_RTX2080TI_XC_HYBRID_GAMING_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080 Ti XC HYDRO COPPER" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_DEV, EVGA_SUB_VEN, EVGA_RTX2080TI_XC_HYDRO_COPPER_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("EVGA GeForce RTX 2080 Ti FTW3 Ultra" , DetectEVGATuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, EVGA_SUB_VEN, EVGA_RTX2080TI_FTW3_ULTRA_SUB_DEV, 0x49); diff --git a/Controllers/EVGATuringGPUController/RGBController_EVGAGPUv2.cpp b/Controllers/EVGATuringGPUController/RGBController_EVGAGPUv2.cpp index f93b4e52..997a825e 100644 --- a/Controllers/EVGATuringGPUController/RGBController_EVGAGPUv2.cpp +++ b/Controllers/EVGATuringGPUController/RGBController_EVGAGPUv2.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_EVGAGPUv2.cpp | -| | -| Generic RGB Interface for OpenRGB EVGA | -| GPU V2 (Turing) Driver | -| | -| TheRogueZeta 4/15/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_EVGAGPUv2.cpp | +| | +| RGBController for EVGA V2 (Turing) GPU | +| | +| TheRogueZeta 15 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_EVGAGPUv2.h" @@ -20,16 +22,15 @@ @comment \*-------------------------------------------------------------------*/ -RGBController_EVGAGPUv2::RGBController_EVGAGPUv2(EVGAGPUv2Controller* evga_ptr) +RGBController_EVGAGPUv2::RGBController_EVGAGPUv2(EVGAGPUv2Controller* controller_ptr) { - evga = evga_ptr; + controller = controller_ptr; - name = "EVGA GPU"; - vendor = "EVGA"; - description = "EVGA Turing RGB GPU Device"; - location = evga->GetDeviceLocation(); - - type = DEVICE_TYPE_GPU; + name = controller->GetDeviceName(); + vendor = "EVGA"; + description = "EVGA Turing RGB GPU Device"; + location = controller->GetDeviceLocation(); + type = DEVICE_TYPE_GPU; mode Off; Off.name = "Off"; @@ -97,7 +98,7 @@ RGBController_EVGAGPUv2::RGBController_EVGAGPUv2(EVGAGPUv2Controller* evga_ptr) SetupZones(); // Initialize active mode - active_mode = getModeIndex(evga->GetMode()); + active_mode = getModeIndex(controller->GetMode()); /*---------------------------------------------------------*\ | The LED color (color[0]) will always be set. Mode colors | @@ -105,8 +106,8 @@ RGBController_EVGAGPUv2::RGBController_EVGAGPUv2(EVGAGPUv2Controller* evga_ptr) | by extension colorB is only necessary if its not black | \*---------------------------------------------------------*/ - colors[0] = evga->GetColorA(); - RGBColor colorB = evga->GetColorB(); + colors[0] = controller->GetColorA(); + RGBColor colorB = controller->GetColorB(); int breathing_mode_index = getModeIndex(EVGA_GPU_V2_RGB_MODE_BREATHING); int pulse_mode_index = getModeIndex(EVGA_GPU_V2_RGB_MODE_PULSE); @@ -122,26 +123,26 @@ RGBController_EVGAGPUv2::RGBController_EVGAGPUv2(EVGAGPUv2Controller* evga_ptr) } // Load speed settings from the card: - modes[active_mode].speed = evga->GetSpeed(); - modes[active_mode].brightness = evga->GetBrightnessA(); + modes[active_mode].speed = controller->GetSpeed(); + modes[active_mode].brightness = controller->GetBrightnessA(); } RGBController_EVGAGPUv2::~RGBController_EVGAGPUv2() { - delete evga; + delete controller; } int RGBController_EVGAGPUv2::getModeIndex(unsigned char mode_value) { - for(std::size_t mode_index = 0; mode_index < modes.size(); mode_index++) + for(int mode_index = 0; mode_index < (int)modes.size(); mode_index++) { - if (modes[mode_index].value == mode_value) + if(modes[mode_index].value == mode_value) { - return mode_index; + return(mode_index); } } - return 0; + return(0); } void RGBController_EVGAGPUv2::SetupZones() @@ -185,7 +186,7 @@ void RGBController_EVGAGPUv2::DeviceUpdateLEDs() | modes and as such colorB will always be black (0x000000) | \*---------------------------------------------------------*/ - evga->SetColor(colors[0], /* colorB*/ 0, modes[active_mode].brightness); + controller->SetColor(colors[0], /* colorB*/ 0, modes[active_mode].brightness); } void RGBController_EVGAGPUv2::UpdateZoneLEDs(int /*zone*/) @@ -215,10 +216,10 @@ void RGBController_EVGAGPUv2::DeviceUpdateMode() colorB = (modes[active_mode].colors.size() == 2) ? modes[active_mode].colors[1] : 0 ; } - evga->SetMode( modes[active_mode].value, colorA, colorB, modes[active_mode].speed, modes[active_mode].brightness); + controller->SetMode( modes[active_mode].value, colorA, colorB, modes[active_mode].speed, modes[active_mode].brightness); } void RGBController_EVGAGPUv2::DeviceSaveMode() { - evga->SaveSettings(); + controller->SaveSettings(); } diff --git a/Controllers/EVGATuringGPUController/RGBController_EVGAGPUv2.h b/Controllers/EVGATuringGPUController/RGBController_EVGAGPUv2.h index 31b8876b..d6a0c471 100644 --- a/Controllers/EVGATuringGPUController/RGBController_EVGAGPUv2.h +++ b/Controllers/EVGATuringGPUController/RGBController_EVGAGPUv2.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_EVGAGPUv2.h | -| | -| Generic RGB Interface for OpenRGB | -| EVGA GPU RGB V2 (Turing) Driver | -| | -| TheRogueZeta 4/15/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_EVGAGPUv2.h | +| | +| RGBController for EVGA V2 (Turing) GPU | +| | +| TheRogueZeta 15 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once @@ -15,7 +17,7 @@ class RGBController_EVGAGPUv2 : public RGBController { public: - RGBController_EVGAGPUv2(EVGAGPUv2Controller* evga_ptr); + RGBController_EVGAGPUv2(EVGAGPUv2Controller* controller_ptr); ~RGBController_EVGAGPUv2(); void SetupZones(); @@ -30,6 +32,7 @@ public: void DeviceSaveMode(); private: + EVGAGPUv2Controller* controller; + int getModeIndex(unsigned char mode_value); - EVGAGPUv2Controller* evga; }; diff --git a/Controllers/EVGAUSBController/EVGAKeyboardController.cpp b/Controllers/EVGAUSBController/EVGAKeyboardController/EVGAKeyboardController.cpp similarity index 88% rename from Controllers/EVGAUSBController/EVGAKeyboardController.cpp rename to Controllers/EVGAUSBController/EVGAKeyboardController/EVGAKeyboardController.cpp index b877c95e..15ba5f3d 100644 --- a/Controllers/EVGAUSBController/EVGAKeyboardController.cpp +++ b/Controllers/EVGAUSBController/EVGAKeyboardController/EVGAKeyboardController.cpp @@ -1,13 +1,16 @@ -/*-------------------------------------------------------------------*\ -| EVGAKeyboardController.cpp | -| | -| Driver for EVGA Z15 Keyboard | -| | -| Chris M (Dr_No) 25 Nov 2021 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| EVGAKeyboardController.cpp | +| | +| Driver for EVGA keyboard | +| | +| Chris M (Dr_No) 25 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "EVGAKeyboardController.h" +#include "StringUtils.h" static uint8_t packet_map[EVGA_KEYBOARD_FULL_SIZE_KEYCOUNT + EVGA_KEYBOARD_Z20_EXTRA_KEYS] = { @@ -54,23 +57,13 @@ static uint8_t packet_map[EVGA_KEYBOARD_FULL_SIZE_KEYCOUNT + EVGA_KEYBOARD_Z20_E 82, 102 }; -EVGAKeyboardController::EVGAKeyboardController(hid_device* dev_handle, const char* path, uint16_t kb_pid) +EVGAKeyboardController::EVGAKeyboardController(hid_device* dev_handle, const char* path, uint16_t kb_pid, std::string dev_name) { - const uint8_t sz = HID_MAX_STR; - wchar_t tmp[sz]; - dev = dev_handle; location = path; + name = dev_name; pid = kb_pid; - hid_get_manufacturer_string(dev, tmp, sz); - std::wstring w_tmp = std::wstring(tmp); - device_name = std::string(w_tmp.begin(), w_tmp.end()); - - hid_get_product_string(dev, tmp, sz); - w_tmp = std::wstring(tmp); - device_name.append(" ").append(std::string(w_tmp.begin(), w_tmp.end())); - SetSleepTime(); } @@ -79,27 +72,22 @@ EVGAKeyboardController::~EVGAKeyboardController() hid_close(dev); } -std::string EVGAKeyboardController::GetDeviceName() +std::string EVGAKeyboardController::GetName() { - return device_name; + return(name); } std::string EVGAKeyboardController::GetSerial() { - const uint8_t sz = HID_MAX_STR; - wchar_t tmp[sz]; + wchar_t serial_string[HID_MAX_STR]; + int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); - int ret = hid_get_serial_number_string(dev, tmp, sz); - - if (ret != 0) + if(ret != 0) { return(""); } - std::wstring w_tmp = std::wstring(tmp); - std::string serial = std::string(w_tmp.begin(), w_tmp.end()); - - return serial; + return(StringUtils::wstring_to_string(serial_string)); } std::string EVGAKeyboardController::GetLocation() @@ -109,7 +97,7 @@ std::string EVGAKeyboardController::GetLocation() uint16_t EVGAKeyboardController::GetPid() { - return pid; + return(pid); } void EVGAKeyboardController::SetLedsDirect(std::vector colors) @@ -199,11 +187,11 @@ void EVGAKeyboardController::GetStatus(mode *mode) mode->speed = buffer[EVGA_KB_SPEED_LSB]; break; } - LOG_DEBUG("[%s] Mode %d Setup with %d colours @ %04X speed and %02X brightness", device_name.c_str(), mode->value, mode->colors.size(), mode->speed, mode->brightness); + LOG_DEBUG("[%s] Mode %d Setup with %d colours @ %04X speed and %02X brightness", name.c_str(), mode->value, mode->colors.size(), mode->speed, mode->brightness); } else { - LOG_INFO("[%s] An error occured reading data for mode %d", device_name.c_str(), mode->value); + LOG_INFO("[%s] An error occured reading data for mode %d", name.c_str(), mode->value); } } @@ -248,7 +236,7 @@ void EVGAKeyboardController::SendColour(uint8_t mode, uint16_t speed, uint8_t br | Static, Breathing and Star modes have fixed colour sizes | | buffer[26] will be overwritten for these modes | \*-----------------------------------------------------------------*/ - buffer[EVGA_KB_COLORS_SZ] = colors.size(); + buffer[EVGA_KB_COLORS_SZ] = (uint8_t)colors.size(); switch(mode) { @@ -259,7 +247,7 @@ void EVGAKeyboardController::SendColour(uint8_t mode, uint16_t speed, uint8_t br case EVGA_KEYBOARD_CONTROLLER_MODE_BREATHING: for(size_t i = 0; i < colors.size(); i++) { - uint8_t offset = 26 + (i * 5); + uint8_t offset = (uint8_t)(26 + (i * 5)); buffer[offset + 0] = 0x0A; buffer[offset + 1] = brightness; @@ -316,7 +304,7 @@ void EVGAKeyboardController::FillColours(uint8_t * buffer, uint8_t brightness, s { for(size_t i = 0; i < colors.size(); i++) { - uint8_t offset = (i * 4); + uint8_t offset = (uint8_t)(i * 4); buffer[offset + 0] = brightness; buffer[offset + 1] = RGBGetRValue(colors[i]); @@ -334,7 +322,7 @@ uint8_t EVGAKeyboardController::GetChecksum(uint8_t * data, size_t count) checksum -= data[i]; } - return checksum; + return(checksum); } uint8_t EVGAKeyboardController::FindDirection(uint8_t mode, uint8_t direction) @@ -353,7 +341,7 @@ uint8_t EVGAKeyboardController::FindDirection(uint8_t mode, uint8_t direction) } } - return temp; + return(temp); } uint8_t EVGAKeyboardController::FindColours(uint8_t * data, uint8_t count, std::vector &colors) @@ -365,12 +353,12 @@ uint8_t EVGAKeyboardController::FindColours(uint8_t * data, uint8_t count, std:: for(size_t i = 0; i < count; i++) { - uint8_t offset = (i * 4); + uint8_t offset = (uint8_t)(i * 4); colors.push_back(ToRGBColor(data[offset + 1],data[offset + 2],data[offset + 3])); } - return data[0]; + return(data[0]); } uint8_t EVGAKeyboardController::GetMode() @@ -391,13 +379,13 @@ uint8_t EVGAKeyboardController::GetMode() if(result > 0) { - LOG_DEBUG("[%s] Returned mode %02X - %02X %02X %02X %02X %02X", device_name.c_str(), buffer[index], buffer[index-2], buffer[index-1], buffer[index], buffer[index+1], buffer[index+2]); - return buffer[index]; + LOG_DEBUG("[%s] Returned mode %02X - %02X %02X %02X %02X %02X", name.c_str(), buffer[index], buffer[index-2], buffer[index-1], buffer[index], buffer[index+1], buffer[index+2]); + return(buffer[index]); } else { - LOG_INFO("[%s] An error occured reading current mode", device_name.c_str()); - return 0; + LOG_INFO("[%s] An error occured reading current mode", name.c_str()); + return(0); } } diff --git a/Controllers/EVGAUSBController/EVGAKeyboardController.h b/Controllers/EVGAUSBController/EVGAKeyboardController/EVGAKeyboardController.h similarity index 85% rename from Controllers/EVGAUSBController/EVGAKeyboardController.h rename to Controllers/EVGAUSBController/EVGAKeyboardController/EVGAKeyboardController.h index 9a9114a3..c26a0eb1 100644 --- a/Controllers/EVGAUSBController/EVGAKeyboardController.h +++ b/Controllers/EVGAUSBController/EVGAKeyboardController/EVGAKeyboardController.h @@ -1,19 +1,21 @@ -/*-------------------------------------------------------------------*\ -| EVGAKeyboardController.h | -| | -| Driver for EVGA Z15 Keyboard | -| | -| Chris M (Dr_No) 25 Nov 2021 | -| | -\*-------------------------------------------------------------------*/ - -#include -#include -#include "LogManager.h" -#include "RGBController.h" +/*---------------------------------------------------------*\ +| EVGAKeyboardController.h | +| | +| Driver for EVGA keyboard | +| | +| Chris M (Dr_No) 25 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "LogManager.h" +#include "RGBController.h" + #define NA 0xFFFFFFFF #define HID_MAX_STR 255 @@ -89,10 +91,10 @@ enum EVGA_Keyboard_Controller_Speed class EVGAKeyboardController { public: - EVGAKeyboardController(hid_device* dev_handle, const char* path, uint16_t kb_pid); + EVGAKeyboardController(hid_device* dev_handle, const char* path, uint16_t kb_pid, std::string dev_name); ~EVGAKeyboardController(); - std::string GetDeviceName(); + std::string GetName(); std::string GetSerial(); std::string GetLocation(); @@ -106,7 +108,7 @@ public: uint8_t GetMode(); uint16_t GetPid(); private: - std::string device_name; + std::string name; std::string location; hid_device* dev; uint16_t pid; diff --git a/Controllers/EVGAUSBController/RGBController_EVGAKeyboard.cpp b/Controllers/EVGAUSBController/EVGAKeyboardController/RGBController_EVGAKeyboard.cpp similarity index 95% rename from Controllers/EVGAUSBController/RGBController_EVGAKeyboard.cpp rename to Controllers/EVGAUSBController/EVGAKeyboardController/RGBController_EVGAKeyboard.cpp index 61eeb416..3559334c 100644 --- a/Controllers/EVGAUSBController/RGBController_EVGAKeyboard.cpp +++ b/Controllers/EVGAUSBController/EVGAKeyboardController/RGBController_EVGAKeyboard.cpp @@ -1,11 +1,13 @@ -/*-------------------------------------------------------------------*\ -| RGBController_EVGAKeyboard.cpp | -| | -| Driver for EVGA Z15 Keyboard | -| | -| Chris M (Dr_No) 25 Nov 2021 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_EVGAKeyboard.cpp | +| | +| RGBController for EVGA keyboard | +| | +| Chris M (Dr_No) 25 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include #include "Colors.h" @@ -199,14 +201,14 @@ RGBController_EVGAKeyboard::RGBController_EVGAKeyboard(EVGAKeyboardController* c /*-----------------------------------------------------*\ | Initialise the random functions from the clock | \*-----------------------------------------------------*/ - std::srand(time(NULL)); + std::srand((unsigned int)time(NULL)); controller = controller_ptr; - name = "EVGA USB Keyboard"; + name = controller->GetName(); vendor = "EVGA"; type = DEVICE_TYPE_KEYBOARD; - description = controller->GetDeviceName(); + description = "EVGA Keyboard Device"; serial = controller->GetSerial(); location = controller->GetLocation(); @@ -413,7 +415,7 @@ void RGBController_EVGAKeyboard::SetupZones() /*-------------------------------------------------*\ | Add configuration for the Z20 | \*-------------------------------------------------*/ - if(controller->GetPid() == 0x260A) + if(controller->GetPid() == 0x260A || controller->GetPid() == 0x2610) { for(uint8_t i = 0; i < EVGA_KEYBOARD_Z20_EXTRA_ZONES; i++) @@ -455,7 +457,7 @@ void RGBController_EVGAKeyboard::SetupZones() \*---------------------------------------------------------*/ for(std::size_t zone_index = 0; zone_index < zones.size(); zone_index++) { - int zone_offset = leds.size(); + unsigned int zone_offset = (unsigned int)leds.size(); for(unsigned int led_index = 0; led_index < zones[zone_index].leds_count; led_index++) { diff --git a/Controllers/EVGAUSBController/EVGAKeyboardController/RGBController_EVGAKeyboard.h b/Controllers/EVGAUSBController/EVGAKeyboardController/RGBController_EVGAKeyboard.h new file mode 100644 index 00000000..244aa9c5 --- /dev/null +++ b/Controllers/EVGAUSBController/EVGAKeyboardController/RGBController_EVGAKeyboard.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------*\ +| RGBController_EVGAKeyboard.h | +| | +| RGBController for EVGA keyboard | +| | +| Chris M (Dr_No) 25 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "EVGAKeyboardController.h" + +class RGBController_EVGAKeyboard : public RGBController +{ +public: + RGBController_EVGAKeyboard(EVGAKeyboardController* controller_ptr); + ~RGBController_EVGAKeyboard(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + uint8_t current_mode; + + int GetDeviceMode(); + RGBColor GetRandomColor(); + + EVGAKeyboardController* controller; +}; diff --git a/Controllers/EVGAUSBController/EVGAMouseController.cpp b/Controllers/EVGAUSBController/EVGAMouseController/EVGAMouseController.cpp similarity index 86% rename from Controllers/EVGAUSBController/EVGAMouseController.cpp rename to Controllers/EVGAUSBController/EVGAMouseController/EVGAMouseController.cpp index b17d2616..1d0315d0 100644 --- a/Controllers/EVGAUSBController/EVGAMouseController.cpp +++ b/Controllers/EVGAUSBController/EVGAMouseController/EVGAMouseController.cpp @@ -1,19 +1,21 @@ -/*-------------------------------------------------*\ -| EVGAMouseController.cpp | -| | -| Driver for EVGA X20 Gaming Mouse RGB Controller. | -| | -| Cooper Knaak 1/23/2022 | -\*-------------------------------------------------*/ - -#include "EVGAMouseController.h" -#include "LogManager.h" +/*---------------------------------------------------------*\ +| EVGAMouseController.cpp | +| | +| Driver for EVGA mouse | +| | +| Cooper Knaak 23 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include #include #include -#include - +#include "EVGAMouseController.h" +#include "LogManager.h" +#include "StringUtils.h" #define HID_MAX_STR 255 #define EVGA_PERIPHERAL_LED_SOURCE_OF_TRUTH EVGA_PERIPHERAL_LED_LOGO @@ -44,27 +46,13 @@ static bool BuffersAreEqual(unsigned char *buffer1, unsigned char *buffer2, int return true; } -EVGAMouseController::EVGAMouseController(hid_device* dev_handle, char *_path, int connection_type) +EVGAMouseController::EVGAMouseController(hid_device* dev_handle, char * path, int connection_type, std::string dev_name) { dev = dev_handle; - location = _path; + location = path; + name = dev_name; this->connection_type = connection_type; - const int szTemp = HID_MAX_STR; - wchar_t tmpName[szTemp]; - - hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - device_name = std::string(wName.begin(), wName.end()); - - hid_get_product_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); - - hid_get_indexed_string(dev, 2, tmpName, szTemp); - wName = std::wstring(tmpName); - serial = std::string(wName.begin(), wName.end()); - led_states.resize(EVGA_PERIPHERAL_LED_COUNT); for(EVGAMouseControllerDeviceState &led_state : led_states) { @@ -78,17 +66,25 @@ EVGAMouseController::EVGAMouseController(hid_device* dev_handle, char *_path, in EVGAMouseController::~EVGAMouseController() { - + hid_close(dev); } -std::string EVGAMouseController::GetDeviceName() +std::string EVGAMouseController::GetName() { - return device_name; + return(name); } std::string EVGAMouseController::GetSerial() { - return serial; + wchar_t serial_string[HID_MAX_STR]; + int ret = hid_get_indexed_string(dev, 2, serial_string, HID_MAX_STR); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } std::string EVGAMouseController::GetLocation() @@ -128,14 +124,14 @@ void EVGAMouseController::SetMode(uint8_t mode, uint8_t index) if(err == -1) { const wchar_t* err_str = hid_error(dev); - LOG_DEBUG("[%s] Error writing buffer %s", device_name.c_str(), err_str); + LOG_DEBUG("[%s] Error writing buffer %s", name.c_str(), err_str); } led_states[index].mode = mode; err = hid_get_feature_report(dev, buffer, EVGA_PERIPHERAL_PACKET_SIZE); if(err == -1) { const wchar_t* err_str = hid_error(dev); - LOG_DEBUG("[%s] Error reading buffer %s", device_name.c_str(), err_str); + LOG_DEBUG("[%s] Error reading buffer %s", name.c_str(), err_str); } } @@ -207,7 +203,7 @@ void EVGAMouseController::SetLed(uint8_t index, uint8_t brightness, uint8_t spee /*-----------------------------------------------------------------------*\ | 7 is the maximum number of colors that can be set from the vendor's UI. | \*-----------------------------------------------------------------------*/ - unsigned char color_count = std::min(colors.size(), static_cast::size_type>(7)); + unsigned char color_count = (unsigned char)std::min(colors.size(), static_cast::size_type>(7)); buffer[EVGA_PERIPHERAL_COLOR_COUNT_BYTE] = color_count; for(unsigned char i = 0; i < color_count; i++) { @@ -219,7 +215,7 @@ void EVGAMouseController::SetLed(uint8_t index, uint8_t brightness, uint8_t spee if(err == -1) { const wchar_t* err_str = hid_error(dev); - LOG_DEBUG("[%s] Error writing buffer %s", device_name.c_str(), err_str); + LOG_DEBUG("[%s] Error writing buffer %s", name.c_str(), err_str); } led_states[index].brightness = brightness; led_states[index].speed = speed; @@ -251,7 +247,7 @@ void EVGAMouseController::RefreshDeviceState(int led) if(err == -1) { const wchar_t* err_str = hid_error(dev); - LOG_DEBUG("[%s] Error writing buffer %s", device_name.c_str(), err_str); + LOG_DEBUG("[%s] Error writing buffer %s", name.c_str(), err_str); } /*------------------------------------------------------------------------------*\ | Wait in wireless mode or else packets might be sent too quickly to take effect | @@ -262,7 +258,7 @@ void EVGAMouseController::RefreshDeviceState(int led) int color_count = buffer[EVGA_PERIPHERAL_COLOR_COUNT_BYTE]; if(color_count == 0) { - LOG_VERBOSE("[%s] No colors read from response. The device is likely asleep.", device_name.c_str()); + LOG_VERBOSE("[%s] No colors read from response. The device is likely asleep.", name.c_str()); return; } led_states[led].mode = buffer[EVGA_PERIPHERAL_MODE_BYTE]; @@ -285,17 +281,17 @@ bool EVGAMouseController::ReadPacketOrLogErrors(unsigned char *buffer, int max_a if(bytes_read == -1) { const wchar_t* err_str = hid_error(dev); - LOG_DEBUG("[%s] Error reading buffer %s", device_name.c_str(), err_str); + LOG_DEBUG("[%s] Error reading buffer %s", name.c_str(), err_str); return false; } else if(IsResponseNotReadyPacket(buffer)) { - LOG_VERBOSE("[%s] Retries exhausted reading from device. Write may have failed.", device_name.c_str()); + LOG_VERBOSE("[%s] Retries exhausted reading from device. Write may have failed.", name.c_str()); return false; } else if(IsAsleepPacket(buffer)) { - LOG_VERBOSE("[%s] Device is asleep. Cannot send or receive packets until the device is awoken.", device_name.c_str()); + LOG_VERBOSE("[%s] Device is asleep. Cannot send or receive packets until the device is awoken.", name.c_str()); return false; } return true; diff --git a/Controllers/EVGAUSBController/EVGAMouseController.h b/Controllers/EVGAUSBController/EVGAMouseController/EVGAMouseController.h similarity index 91% rename from Controllers/EVGAUSBController/EVGAMouseController.h rename to Controllers/EVGAUSBController/EVGAMouseController/EVGAMouseController.h index 750b7a3f..2978ecfa 100644 --- a/Controllers/EVGAUSBController/EVGAMouseController.h +++ b/Controllers/EVGAUSBController/EVGAMouseController/EVGAMouseController.h @@ -1,17 +1,19 @@ -/*-----------------------------------*\ -| EVGAMouseController.h | -| | -| Definitions and types for EVGA X20 | -| Gaming Mouse. | -| | -| Cooper Knaak 1/23/2022 | -\*-----------------------------------*/ +/*---------------------------------------------------------*\ +| EVGAMouseController.h | +| | +| Driver for EVGA mouse | +| | +| Cooper Knaak 23 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include #include -#include +#include +#include #include "RGBController.h" #define EVGA_PERIPHERAL_PACKET_SIZE 65 @@ -89,10 +91,10 @@ struct EVGAMouseControllerDeviceState class EVGAMouseController { public: - EVGAMouseController(hid_device* dev_handle, char *_path, int connection_type); + EVGAMouseController(hid_device* dev_handle, char * path, int connection_type, std::string dev_name); ~EVGAMouseController(); - std::string GetDeviceName(); + std::string GetName(); std::string GetSerial(); std::string GetLocation(); @@ -142,6 +144,12 @@ public: void SetAllLedsAndActivate(uint8_t brightness, uint8_t speed, const std::vector& colors); private: + hid_device* dev; + std::string location; + std::string name; + int connection_type; + + std::vector led_states; /*----------------------------------------------------------------------------------------------------------------*\ | Sets the led to the given colors with the given brightness and speed. if activate is true, activates the current | @@ -194,14 +202,5 @@ private: | read from the device should be retried at a later time. | \*------------------------------------------------------------------------------*/ bool IsResponseNotReadyPacket(unsigned char *buffer); - - std::string device_name; - std::string serial; - std::string location; - hid_device* dev; - - int connection_type; - - std::vector led_states; }; diff --git a/Controllers/EVGAUSBController/RGBController_EVGAMouse.cpp b/Controllers/EVGAUSBController/EVGAMouseController/RGBController_EVGAMouse.cpp similarity index 92% rename from Controllers/EVGAUSBController/RGBController_EVGAMouse.cpp rename to Controllers/EVGAUSBController/EVGAMouseController/RGBController_EVGAMouse.cpp index cd391359..0e4344ad 100644 --- a/Controllers/EVGAUSBController/RGBController_EVGAMouse.cpp +++ b/Controllers/EVGAUSBController/EVGAMouseController/RGBController_EVGAMouse.cpp @@ -1,10 +1,13 @@ -/*----------------------------------------------*\ -| RGBController_EVGAMouse.cpp | -| | -| RGB Implementation for EVGA X20 Gaming Mouse. | -| | -| Cooper Knaak 1/23/2022 | -\*----------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_EVGAMouse.cpp | +| | +| RGBController for EVGA mouse | +| | +| Cooper Knaak 23 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_EVGAMouse.h" #include "Colors.h" @@ -24,10 +27,10 @@ RGBController_EVGAMouse::RGBController_EVGAMouse(EVGAMouseController* controller { controller = controller_ptr; - name = controller->GetDeviceName(); + name = controller->GetName(); vendor = "EVGA"; type = DEVICE_TYPE_MOUSE; - description = controller->GetDeviceName(); + description = "EVGA Mouse Device"; serial = controller->GetSerial(); location = controller->GetLocation(); @@ -91,7 +94,7 @@ RGBController_EVGAMouse::RGBController_EVGAMouse(EVGAMouseController* controller modes.push_back(Pulse); mode Trigger; - Trigger.name = "Trigger"; + Trigger.name = "Trigger"; /*-----------------------------------*\ | Pulse to Trigger skips from 4 to 6. | \*-----------------------------------*/ diff --git a/Controllers/EVGAUSBController/EVGAMouseController/RGBController_EVGAMouse.h b/Controllers/EVGAUSBController/EVGAMouseController/RGBController_EVGAMouse.h new file mode 100644 index 00000000..51c118e4 --- /dev/null +++ b/Controllers/EVGAUSBController/EVGAMouseController/RGBController_EVGAMouse.h @@ -0,0 +1,44 @@ +/*---------------------------------------------------------*\ +| RGBController_EVGAMouse.h | +| | +| RGBController for EVGA mouse | +| | +| Cooper Knaak 23 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "EVGAMouseController.h" + +#define EVGA_PERIPHERAL_BRIGHTNESS_MIN 0 +#define EVGA_PERIPHERAL_BRIGHTNESS_MAX 100 +#define EVGA_PERIPHERAL_SPEED_SLOWEST 0 +#define EVGA_PERIPHERAL_SPEED_FASTEST 100 + +class RGBController_EVGAMouse : public RGBController +{ +public: + RGBController_EVGAMouse(EVGAMouseController* evga); + ~RGBController_EVGAMouse(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + void Init_Controller(); + int GetDeviceMode(); + + EVGAMouseController* controller; +}; diff --git a/Controllers/EVGAUSBController/EVGAUSBControllerDetect.cpp b/Controllers/EVGAUSBController/EVGAUSBControllerDetect.cpp index c0fb3210..44e77975 100644 --- a/Controllers/EVGAUSBController/EVGAUSBControllerDetect.cpp +++ b/Controllers/EVGAUSBController/EVGAUSBControllerDetect.cpp @@ -1,9 +1,16 @@ +/*---------------------------------------------------------*\ +| EVGAUSBControllerDetect.cpp | +| | +| Detector for EVGA USB devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" -#include "LogManager.h" -#include "RGBController.h" #include "RGBController_EVGAKeyboard.h" #include "RGBController_EVGAMouse.h" -#include /*-----------------------------------------------------*\ | EVGA USB vendor ID | @@ -30,24 +37,22 @@ void DetectEVGAKeyboardControllers(hid_device_info* info, const std::string& nam if(dev) { - EVGAKeyboardController* controller = new EVGAKeyboardController(dev, info->path, info->product_id); + EVGAKeyboardController* controller = new EVGAKeyboardController(dev, info->path, info->product_id, name); RGBController_EVGAKeyboard* rgb_controller = new RGBController_EVGAKeyboard(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } -void DetectEVGAMouse(hid_device_info* info, const std::string &, int connection_type) +void DetectEVGAMouse(hid_device_info* info, const std::string &name, int connection_type) { hid_device* dev = hid_open_path(info->path); - if (dev) + + if(dev) { - EVGAMouseController* controller = new EVGAMouseController(dev, info->path, connection_type); + EVGAMouseController* controller = new EVGAMouseController(dev, info->path, connection_type, name); RGBController_EVGAMouse* rgb_controller = new RGBController_EVGAMouse(controller); - /*-------------------------*\ - | Constructor sets the name | - \*-------------------------*/ + ResourceManager::get()->RegisterRGBController(rgb_controller); } } diff --git a/Controllers/EVGAUSBController/RGBController_EVGAKeyboard.h b/Controllers/EVGAUSBController/RGBController_EVGAKeyboard.h deleted file mode 100644 index 368d008b..00000000 --- a/Controllers/EVGAUSBController/RGBController_EVGAKeyboard.h +++ /dev/null @@ -1,37 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_EVGAKeyboard.h | -| | -| Driver for EVGA Z15 Keyboard | -| | -| Chris M (Dr_No) 25 Nov 2021 | -| | -\*-------------------------------------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "EVGAKeyboardController.h" - -class RGBController_EVGAKeyboard : public RGBController -{ -public: - RGBController_EVGAKeyboard(EVGAKeyboardController* controller_ptr); - ~RGBController_EVGAKeyboard(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - uint8_t current_mode; - - int GetDeviceMode(); - RGBColor GetRandomColor(); - - EVGAKeyboardController* controller; -}; diff --git a/Controllers/EVGAUSBController/RGBController_EVGAMouse.h b/Controllers/EVGAUSBController/RGBController_EVGAMouse.h deleted file mode 100644 index e070684d..00000000 --- a/Controllers/EVGAUSBController/RGBController_EVGAMouse.h +++ /dev/null @@ -1,43 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_EVGAMouse.h | -| | -| RGB Interface for EVGA X20 Gaming Mouse. | -| | -| Cooper Knaak 1/23/2022 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "EVGAMouseController.h" -#include - -#define EVGA_PERIPHERAL_BRIGHTNESS_MIN 0 -#define EVGA_PERIPHERAL_BRIGHTNESS_MAX 100 -#define EVGA_PERIPHERAL_SPEED_SLOWEST 0 -#define EVGA_PERIPHERAL_SPEED_FASTEST 100 - -class RGBController_EVGAMouse : public RGBController -{ -public: - RGBController_EVGAMouse(EVGAMouseController* evga); - ~RGBController_EVGAMouse(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - void Init_Controller(); - int GetDeviceMode(); - - EVGAMouseController* controller; - -}; - diff --git a/Controllers/EVisionKeyboardController/EVisionKeyboardController.cpp b/Controllers/EVisionKeyboardController/EVisionKeyboardController.cpp index 8d4e5168..8f0cb9d3 100644 --- a/Controllers/EVisionKeyboardController/EVisionKeyboardController.cpp +++ b/Controllers/EVisionKeyboardController/EVisionKeyboardController.cpp @@ -1,23 +1,24 @@ -/*-----------------------------------------*\ -| EVisionKeyboardController.cpp | -| | -| Driver for EVision RGB keyboard lighting | -| controller | -| | -| EVision is used by Redragon, Glorious, | -| Ajazz, Tecware, and many other brands | -| | -| Adam Honse (CalcProgrammer1) 3/15/2020 | -\*-----------------------------------------*/ - -#include "EVisionKeyboardController.h" +/*---------------------------------------------------------*\ +| EVisionKeyboardController.cpp | +| | +| Driver for EVision keyboard (Redragon, Glorious, Ajazz, | +| Tecware, and many other brands) | +| | +| Adam Honse (CalcProgrammer1) 15 Mar 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "EVisionKeyboardController.h" +#include "StringUtils.h" -EVisionKeyboardController::EVisionKeyboardController(hid_device* dev_handle, const char* path) +EVisionKeyboardController::EVisionKeyboardController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } EVisionKeyboardController::~EVisionKeyboardController() @@ -30,6 +31,11 @@ std::string EVisionKeyboardController::GetDeviceLocation() return("HID: " + location); } +std::string EVisionKeyboardController::GetNameString() +{ + return(name); +} + std::string EVisionKeyboardController::GetSerialString() { wchar_t serial_string[128]; @@ -40,10 +46,7 @@ std::string EVisionKeyboardController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void EVisionKeyboardController::SetKeyboardColors @@ -65,7 +68,7 @@ void EVisionKeyboardController::SetKeyboardColors { packet_size = size; } - + SendKeyboardData ( &color_data[packet_offset], @@ -150,7 +153,7 @@ void EVisionKeyboardController::SendKeyboardBegin() usb_buf[0x01] = EVISION_KB_COMMAND_BEGIN; usb_buf[0x02] = 0x00; usb_buf[0x03] = EVISION_KB_COMMAND_BEGIN; - + /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ @@ -176,7 +179,7 @@ void EVisionKeyboardController::SendKeyboardEnd() usb_buf[0x01] = EVISION_KB_COMMAND_END; usb_buf[0x02] = 0x00; usb_buf[0x03] = EVISION_KB_COMMAND_END; - + /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ @@ -212,7 +215,7 @@ void EVisionKeyboardController::SendKeyboardData | Copy in data bytes | \*-----------------------------------------------------*/ memcpy(&usb_buf[0x08], data, data_size); - + /*-----------------------------------------------------*\ | Compute Checksum | \*-----------------------------------------------------*/ diff --git a/Controllers/EVisionKeyboardController/EVisionKeyboardController.h b/Controllers/EVisionKeyboardController/EVisionKeyboardController.h index 2bf16346..ebb2c140 100644 --- a/Controllers/EVisionKeyboardController/EVisionKeyboardController.h +++ b/Controllers/EVisionKeyboardController/EVisionKeyboardController.h @@ -1,22 +1,21 @@ -/*-----------------------------------------*\ -| EVisionKeyboardController.h | -| | -| Definitions and types for EVision RGB | -| keyboard lighting controller | -| | -| EVision is used by Redragon, Glorious, | -| Ajazz, Tecware, and many other brands | -| | -| Adam Honse (CalcProgrammer1) 3/15/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| EVisionKeyboardController.h | +| | +| Driver for EVision keyboard (Redragon, Glorious, Ajazz, | +| Tecware, and many other brands) | +| | +| Adam Honse (CalcProgrammer1) 15 Mar 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + #define EVISION_KB_MAX_PACKET_SIZE ( 0x36 )/* max packet size for color*/ /* update packets */ enum @@ -95,10 +94,11 @@ enum class EVisionKeyboardController { public: - EVisionKeyboardController(hid_device* dev_handle, const char* path); + EVisionKeyboardController(hid_device* dev_handle, const char* path, std::string dev_name); ~EVisionKeyboardController(); std::string GetDeviceLocation(); + std::string GetNameString(); std::string GetSerialString(); void SetKeyboardColors @@ -138,6 +138,7 @@ public: private: hid_device* dev; std::string location; + std::string name; void ComputeChecksum ( diff --git a/Controllers/EVisionKeyboardController/EVisionKeyboardControllerDetect.cpp b/Controllers/EVisionKeyboardController/EVisionKeyboardControllerDetect.cpp index 88d30e55..2b910638 100644 --- a/Controllers/EVisionKeyboardController/EVisionKeyboardControllerDetect.cpp +++ b/Controllers/EVisionKeyboardController/EVisionKeyboardControllerDetect.cpp @@ -1,25 +1,42 @@ +/*---------------------------------------------------------*\ +| EVisionKeyboardControllerDetect.cpp | +| | +| Detector for EVision keyboards | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "EVisionKeyboardController.h" -#include "RGBController.h" +#include "EVisionV2KeyboardController.h" #include "RGBController_EVisionKeyboard.h" -#include -#include +#include "RGBController_EVisionV2Keyboard.h" +#include "SettingsManager.h" /*-----------------------------------------------------*\ | Keyboard product IDs | \*-----------------------------------------------------*/ -#define EVISION_KEYBOARD_VID 0x0C45 -#define EVISION_KEYBOARD2_VID 0x320F -#define EVISION_KEYBOARD_USAGE_PAGE 0xFF1C -#define GLORIOUS_GMMK_TKL_PID 0x5064 -#define REDRAGON_K550_PID 0x5204 -#define REDRAGON_K552_PID 0x5104 -#define REDRAGON_K552_V2_PID 0x5000 -#define REDRAGON_K556_PID 0x5004 -#define TECWARE_PHANTOM_ELITE_PID 0x652F -#define WARRIOR_KANE_TC235 0x8520 -#define WOMIER_K87_PID 0x502A -#define WOMIER_K66_PID 0x7698 +#define EVISION_KEYBOARD_VID 0x0C45 +#define EVISION_KEYBOARD2_VID 0x320F +#define EVISION_KEYBOARD3_VID 0x3299 +#define EVISION_KEYBOARD_USAGE_PAGE 0xFF1C +#define ENDORFY_OMNIS_PID 0x0012 +#define DEXP_BLAZE_PID 0x5084 +#define GLORIOUS_GMMK_TKL_PID 0x5064 +#define REDRAGON_K550_PID 0x5204 +#define MARS_GAMING_MKMINI_PID 0x5078 +#define SKILLKORP_K5_PID 0x505B +#define REDRAGON_K552_PID 0x5104 +#define REDRAGON_K552_V2_PID 0x5000 +#define REDRAGON_K556_PID 0x5004 +#define TECWARE_PHANTOM_ELITE_PID 0x652F +#define WARRIOR_KANE_TC235 0x8520 +#define WOMIER_K87_PID 0x502A +#define WOMIER_K66_PID 0x7698 +#define BYGG_CSB_ICL01_PID 0x5041 +#define GAMEPOWER_OGRE_RGB_PID 0x7672 /******************************************************************************************\ * * @@ -29,28 +46,80 @@ * * \******************************************************************************************/ -void DetectEVisionKeyboards(hid_device_info* info, const std::string& /*name*/) +void DetectEVisionKeyboards(hid_device_info* info, const std::string& name) { hid_device* dev = hid_open_path(info->path); if(dev) { - EVisionKeyboardController* controller = new EVisionKeyboardController(dev, info->path); + EVisionKeyboardController* controller = new EVisionKeyboardController(dev, info->path, name); RGBController_EVisionKeyboard* rgb_controller = new RGBController_EVisionKeyboard(controller); - rgb_controller->name = "EVision Keyboard"; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } +void DetectEVisionV2Keyboards(hid_device_info* info, const std::string& name) +{ + json settings = ResourceManager::get()->GetSettingsManager()->GetSettings("EVision2Settings"); + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + EVisionV2KeyboardController* controller = new EVisionV2KeyboardController(dev, info->path, EVISION_V2_KEYBOARD_LAYOUT, name); + RGBController_EVisionV2Keyboard* rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_KEYBOARD); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + + if(!settings.contains("AdditionalZones") || settings["AdditionalZones"] == true) + { + rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_LOGO); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + + rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_EDGE); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + } +} + +void DetectEndorfyKeyboards(hid_device_info* info, const std::string& name) +{ + json settings = ResourceManager::get()->GetSettingsManager()->GetSettings("EndorfySettings"); + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + EVisionV2KeyboardController* controller = new EVisionV2KeyboardController(dev, info->path, ENDORFY_KEYBOARD_LAYOUT, name); + RGBController_EVisionV2Keyboard* rgb_controller = new RGBController_EVisionV2Keyboard(controller, EVISION_V2_KEYBOARD_PART_KEYBOARD); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + + if(!settings.contains("AdditionalZones") || settings["AdditionalZones"] == true) + { + rgb_controller = new RGBController_EVisionV2Keyboard(controller, ENDORFY_KEYBOARD_PART_EDGE); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + } +} + /*---------------------------------------------------------------------------------------------------------------------------------------------*\ | Keyboards | \*---------------------------------------------------------------------------------------------------------------------------------------------*/ -REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5204", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, REDRAGON_K550_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); -REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5104", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, REDRAGON_K552_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); -REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5000", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, REDRAGON_K552_V2_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); -REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5004", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, REDRAGON_K556_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); -REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:652F", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, TECWARE_PHANTOM_ELITE_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); -REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:8520", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, WARRIOR_KANE_TC235, 1, EVISION_KEYBOARD_USAGE_PAGE); -REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:502A", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, WOMIER_K87_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); -REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:7698", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, WOMIER_K66_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); -REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5064", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, GLORIOUS_GMMK_TKL_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5078", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, MARS_GAMING_MKMINI_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5204", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, REDRAGON_K550_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5104", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, REDRAGON_K552_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5000", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, REDRAGON_K552_V2_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:5004", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, REDRAGON_K556_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:652F", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, TECWARE_PHANTOM_ELITE_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:8520", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, WARRIOR_KANE_TC235, 1, EVISION_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:502A", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, WOMIER_K87_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("EVision Keyboard 0C45:7698", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, WOMIER_K66_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5064", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, GLORIOUS_GMMK_TKL_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:5084", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, DEXP_BLAZE_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("EVision Keyboard 320F:505B", DetectEVisionKeyboards, EVISION_KEYBOARD2_VID, SKILLKORP_K5_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("Endorfy Omnis", DetectEndorfyKeyboards, EVISION_KEYBOARD3_VID, ENDORFY_OMNIS_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("CSB/ICL01 Keyboard", DetectEVisionV2Keyboards, EVISION_KEYBOARD2_VID, BYGG_CSB_ICL01_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("Gamepower Ogre RGB 0C45:7672", DetectEVisionKeyboards, EVISION_KEYBOARD_VID, GAMEPOWER_OGRE_RGB_PID, 1, EVISION_KEYBOARD_USAGE_PAGE); diff --git a/Controllers/EVisionKeyboardController/EVisionV2KeyboardController.cpp b/Controllers/EVisionKeyboardController/EVisionV2KeyboardController.cpp new file mode 100644 index 00000000..79423b8c --- /dev/null +++ b/Controllers/EVisionKeyboardController/EVisionV2KeyboardController.cpp @@ -0,0 +1,465 @@ +/*---------------------------------------------------------*\ +| EVisionV2KeyboardController.cpp | +| | +| Driver for EVision V2 keyboard | +| | +| Le Philousophe 25 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "LogManager.h" +#include "EVisionV2KeyboardController.h" +#include "StringUtils.h" + +#define BLANK_SPACE 6 +#define query_check_buffer(c) \ + do \ + { \ + if(!(c)) \ + { \ + return -256; \ + } \ + } while(0) + +using namespace std::chrono_literals; + +static uint8_t evisionv2_map[EVISION_V2_MATRIX_WIDTH * EVISION_V2_MATRIX_HEIGHT] = +{ + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 19 19 20 */ + 0, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 96, + 1, 7, 13, 19, 25, 31, 37, 43, 49, 55, 61, 67, 73, 79, 85, 91, 97, 103, 109, 115, 121, + 2, 8, 14, 20, 26, 32, 38, 44, 50, 56, 62, 68, 74, 80, 86, 92, 98, 104, 110, 116, 122, + 3, 9, 15, 21, 27, 33, 39, 45, 51, 57, 63, 69, 75, 81, 105, 111, 117, + 4, 10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, 82, 94, 106, 112, 118, 124, + 5, 11, 17, 41, 65, 71, 77, 83, 89, 95, 101, 113, 119, +}; + +static uint8_t endorfy_map[EVISION_V2_MATRIX_WIDTH * EVISION_V2_MATRIX_HEIGHT] = +{ + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 19 19 20 */ + 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 76, 80, 81, 82, + 84, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 97, 99, 101, 102, 103, 104, + 105, 106, 107, 111, 115, 116, 117, 118, 119, 120, 121, 123, 124, +}; + +EVisionV2KeyboardController::EVisionV2KeyboardController(hid_device* dev_handle, const char* path, EVisionV2KeyboardLayout dev_layout, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + layout = dev_layout; + + /*---------------------------------------------------------*\ + | Get capabilities and layout | + \*---------------------------------------------------------*/ + uint8_t buffer[7]; + if(Read(EVISION_V2_CMD_READ_CAPABILITIES, 0, sizeof(buffer), buffer) < 0) + { + return; + } + if(buffer[0] != 0xAA && buffer[1] != 0x55) + { + return; + } + + map_size = buffer[5]; + macros_size = buffer[6] * 0x80; + + switch(layout) + { + case EVISION_V2_KEYBOARD_LAYOUT: + keyvalue_map = evisionv2_map; + led_count = 106; + break; + + case ENDORFY_KEYBOARD_LAYOUT: + keyvalue_map = endorfy_map; + led_count = 104; + break; + } +} + +EVisionV2KeyboardController::~EVisionV2KeyboardController() +{ + hid_close(dev); +} + +std::string EVisionV2KeyboardController::GetName() +{ + return(name); +} + +std::string EVisionV2KeyboardController::GetSerial() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string EVisionV2KeyboardController::GetLocation() +{ + return("HID: " + location); +} + +int EVisionV2KeyboardController::Query(uint8_t cmd, uint16_t offset, const uint8_t* idata, uint8_t size, uint8_t* odata) +{ + uint8_t buffer[EVISION_V2_PACKET_SIZE]; + memset(buffer, 0, sizeof(buffer)); + + buffer[0] = EVISION_V2_REPORT_ID; + buffer[3] = cmd; + buffer[4] = size; + buffer[5] = offset & 0xff; + buffer[6] = (offset >> 8) & 0xff; + + if(idata) + { + memcpy(buffer + 8, idata, size); + } + + uint16_t chksum = 0; + for(uint8_t* p = &buffer[3]; p != &buffer[EVISION_V2_PACKET_SIZE]; p++) + { + chksum += *p; + } + buffer[1] = chksum & 0xff; + buffer[2] = (chksum >> 8) & 0xff; + + int bytes_read; + { + const std::lock_guard lock(query_mutex); + + hid_write(dev, buffer, sizeof(buffer)); + + do + { + bytes_read = hid_read(dev, buffer, sizeof(buffer)); + } while(bytes_read != 0 && buffer[0] != EVISION_V2_REPORT_ID); + } + query_check_buffer(bytes_read == sizeof(buffer)); + + query_check_buffer(buffer[0] == EVISION_V2_REPORT_ID); + query_check_buffer(buffer[1] == (chksum & 0xff)); + query_check_buffer(buffer[2] == ((chksum >> 8) & 0xff)); + query_check_buffer(buffer[3] == cmd); + query_check_buffer(buffer[5] == (offset & 0xff)); + query_check_buffer(buffer[6] == ((offset >> 8) & 0xff)); + + if(buffer[7] != 0) + { + return -buffer[7]; + } + + size = buffer[4]; + if(size > EVISION_V2_PACKET_SIZE - 8) + { + return -256; + } + + if(odata) + { + memcpy(odata, buffer + 8, size); + } + + return size; +} + +int EVisionV2KeyboardController::BeginConfigure() +{ + return Query(EVISION_V2_CMD_BEGIN_CONFIGURE); +} + +int EVisionV2KeyboardController::EndConfigure() +{ + return Query(EVISION_V2_CMD_END_CONFIGURE); +} + +int EVisionV2KeyboardController::Read(uint8_t cmd, uint16_t offset, uint16_t size, uint8_t* odata) +{ + while(size > 0) + { + uint8_t pktsz = (uint8_t)std::min(size, EVISION_V2_PACKET_SIZE - 8); + int result = Query(cmd, offset, nullptr, pktsz, odata); + if(result <= 0) + { + return result; + } + else if(result > size) + { + return -256; + } + offset += result; + odata += result; + size -= result; + } + return 0; +} + +int EVisionV2KeyboardController::Write(uint8_t cmd, uint16_t offset, const uint8_t* idata, uint16_t size) +{ + while(size > 0) + { + uint8_t pktsz = (uint8_t)std::min(size, EVISION_V2_PACKET_SIZE - 8); + int result = Query(cmd, offset, idata, pktsz); + if(result <= 0) + { + return result; + } + offset += pktsz; + idata += pktsz; + size -= pktsz; + } + return 0; +} + +int EVisionV2KeyboardController::GetMode(EVisionV2KeyboardPart part, EvisionV2ModeConfig& config) +{ + uint8_t buffer[18]; + memset(buffer, 0, sizeof(buffer)); + + uint8_t current_profile; + int ret = Read(EVISION_V2_CMD_READ_CONFIG, EVISION_V2_OFFSET_CURRENT_PROFILE, 1, ¤t_profile); + if(ret < 0) + { + return ret; + } + if(current_profile > 2) + { + current_profile = 0; + } + + uint16_t offset; + uint8_t size; + + offset = current_profile * 0x40 + EVISION_V2_OFFSET_FIRST_PROFILE; + + switch(part) + { + case EVISION_V2_KEYBOARD_PART_KEYBOARD: + size = sizeof(buffer); + break; + case EVISION_V2_KEYBOARD_PART_LOGO: + case ENDORFY_KEYBOARD_PART_EDGE: + offset += EVISION_V2_PARAMETER_LOGO; + size = EVISION_V2_PARAMETER_LOGO_ON_OFF - EVISION_V2_PARAMETER_LOGO + 1; + break; + case EVISION_V2_KEYBOARD_PART_EDGE: + offset += EVISION_V2_PARAMETER_EDGE; + size = EVISION_V2_PARAMETER_END - EVISION_V2_PARAMETER_EDGE; + break; + default: + size = 0; + break; + } + + ret = Read(EVISION_V2_CMD_READ_CONFIG, offset, size, buffer); + if(ret < 0) + { + return ret; + } + + config.mode = buffer[EVISION_V2_PARAMETER_MODE]; + config.brightness = buffer[EVISION_V2_PARAMETER_BRIGHTNESS]; + config.speed = buffer[EVISION_V2_PARAMETER_SPEED]; + config.direction = buffer[EVISION_V2_PARAMETER_DIRECTION]; + config.random_colours = buffer[EVISION_V2_PARAMETER_RANDOM_COLOR_FLAG] != 0; + config.colour = ToRGBColor(buffer[EVISION_V2_PARAMETER_MODE_COLOR + 0], + buffer[EVISION_V2_PARAMETER_MODE_COLOR + 1], buffer[EVISION_V2_PARAMETER_MODE_COLOR + 2]); + if(part == EVISION_V2_KEYBOARD_PART_KEYBOARD) + { + config.ledmode = buffer[EVISION_V2_PARAMETER_LED_MODE_COLOR]; + if(config.mode == EVISION_V2_MODE_CUSTOM) + { + ret = Read(EVISION_V2_CMD_READ_CONFIG, current_profile * 0x40 + EVISION_V2_OFFSET_FIRST_PROFILE + EVISION_V2_PARAMETER_CURRENT_CUSTOM_MODE, sizeof(config.ledmode), &config.ledmode); + if(ret < 0) + { + return ret; + } + } + } + else if(part == EVISION_V2_KEYBOARD_PART_LOGO || part == ENDORFY_KEYBOARD_PART_EDGE) + { + // Use ledmode for logo on/off + config.ledmode = buffer[EVISION_V2_PARAMETER_LOGO_ON_OFF - EVISION_V2_PARAMETER_LOGO]; + } + + return 0; +} + +void EVisionV2KeyboardController::SetMode(EVisionV2KeyboardPart part, const EvisionV2ModeConfig& config) +{ + uint8_t buffer[18]; + memset(buffer, 0, sizeof(buffer)); + + buffer[EVISION_V2_PARAMETER_MODE] = config.mode; + buffer[EVISION_V2_PARAMETER_BRIGHTNESS] = config.brightness; + buffer[EVISION_V2_PARAMETER_SPEED] = config.speed; + buffer[EVISION_V2_PARAMETER_DIRECTION] = config.direction; + buffer[EVISION_V2_PARAMETER_RANDOM_COLOR_FLAG] = (config.random_colours) ? 255 : 0; + buffer[EVISION_V2_PARAMETER_MODE_COLOR + 0] = RGBGetRValue(config.colour); + buffer[EVISION_V2_PARAMETER_MODE_COLOR + 1] = RGBGetGValue(config.colour); + buffer[EVISION_V2_PARAMETER_MODE_COLOR + 2] = RGBGetBValue(config.colour); + if(part == EVISION_V2_KEYBOARD_PART_KEYBOARD) + { + buffer[EVISION_V2_PARAMETER_COLOR_OFFSET] = 0; + if(config.mode != EVISION_V2_MODE_CUSTOM) + { + buffer[EVISION_V2_PARAMETER_LED_MODE_COLOR] = config.ledmode; + } + } + else if(part == EVISION_V2_KEYBOARD_PART_LOGO || part == ENDORFY_KEYBOARD_PART_EDGE) + { + // Use ledmode for logo on/off + buffer[EVISION_V2_PARAMETER_LOGO_ON_OFF - EVISION_V2_PARAMETER_LOGO] = config.ledmode; + } + + BeginConfigure(); + uint8_t current_profile; + + int ret = Read(EVISION_V2_CMD_READ_CONFIG, EVISION_V2_OFFSET_CURRENT_PROFILE, 1, ¤t_profile); + if(ret < 0) + { + return; + } + if(current_profile > 2) + { + current_profile = 0; + Write(EVISION_V2_CMD_WRITE_CONFIG, EVISION_V2_OFFSET_CURRENT_PROFILE, ¤t_profile, 1); + } + + uint16_t offset = 0; + uint8_t size = 0; + + offset = current_profile * 0x40 + EVISION_V2_OFFSET_FIRST_PROFILE; + + switch(part) + { + case EVISION_V2_KEYBOARD_PART_KEYBOARD: + size = sizeof(buffer); + break; + case EVISION_V2_KEYBOARD_PART_LOGO: + case ENDORFY_KEYBOARD_PART_EDGE: + offset += EVISION_V2_PARAMETER_LOGO; + size = EVISION_V2_PARAMETER_LOGO_ON_OFF - EVISION_V2_PARAMETER_LOGO + 1; + break; + case EVISION_V2_KEYBOARD_PART_EDGE: + offset += EVISION_V2_PARAMETER_EDGE; + size = EVISION_V2_PARAMETER_END - EVISION_V2_PARAMETER_EDGE; + break; + } + + Write(EVISION_V2_CMD_WRITE_CONFIG, offset, buffer, size); + if((part == EVISION_V2_KEYBOARD_PART_KEYBOARD) && (config.mode == EVISION_V2_MODE_CUSTOM)) + { + Write(EVISION_V2_CMD_WRITE_CONFIG, current_profile * 0x40 + EVISION_V2_OFFSET_FIRST_PROFILE + EVISION_V2_PARAMETER_CURRENT_CUSTOM_MODE, &config.ledmode, sizeof(config.ledmode)); + } + EndConfigure(); +} + +void EVisionV2KeyboardController::SetLedsDirect(const std::vector& colours) +{ + const size_t colours_num = std::min(colours.size(), led_count); + + uint8_t* buffer = new uint8_t[3 * map_size]; + memset(buffer, 0, 3 * map_size); + + for(size_t i = 0; i < colours_num; i++) + { + size_t j = (size_t)keyvalue_map[i] * 3; + buffer[j + 0] = RGBGetRValue(colours[i]); + buffer[j + 1] = RGBGetGValue(colours[i]); + buffer[j + 2] = RGBGetBValue(colours[i]); + } + + Write(EVISION_V2_CMD_SEND_DYNAMIC_COLORS, 0, buffer, (uint16_t)(3 * map_size)); + + delete[] buffer; +} + +void EVisionV2KeyboardController::SetLedDirect(int led, RGBColor colour) +{ + uint8_t buffer[3]; + buffer[0] = RGBGetRValue(colour); + buffer[1] = RGBGetGValue(colour); + buffer[2] = RGBGetBValue(colour); + + Write(EVISION_V2_CMD_SEND_DYNAMIC_COLORS, keyvalue_map[led] * 3, buffer, sizeof(buffer)); +} + +void EVisionV2KeyboardController::RefreshLedDirect() +{ + // Write one zero byte in the first blank space + Query(EVISION_V2_CMD_SEND_DYNAMIC_COLORS, BLANK_SPACE * 3, nullptr, 1, nullptr); +} + +void EVisionV2KeyboardController::EndLedsDirect() +{ + Query(EVISION_V2_CMD_END_DYNAMIC_COLORS); +} + +int EVisionV2KeyboardController::GetLedsCustom(uint8_t colorset, std::vector& colours) +{ + if(colorset > 9) + { + return -256; + } + + const size_t colours_num = std::min(colours.size(), led_count); + + uint8_t* buffer = new uint8_t[3 * map_size]; + memset(buffer, 0, 3 * map_size); + + int ret = Read(EVISION_V2_CMD_READ_CUSTOM_COLORS, 512 * colorset, (uint16_t)(3 * map_size), buffer); + if(ret < 0) + { + return ret; + } + + for(size_t i = 0; i < colours_num; i++) + { + size_t j = (size_t)keyvalue_map[i] * 3; + colours[i] = ToRGBColor(buffer[j + 0], buffer[j + 1], buffer[j + 2]); + } + + delete[] buffer; + return 0; +} + +void EVisionV2KeyboardController::SetLedsCustom(uint8_t colorset, const std::vector& colours) +{ + if(colorset > 9) + { + return; + } + + const size_t colours_num = std::min(colours.size(), led_count); + + uint8_t* buffer = new uint8_t[3 * map_size]; + memset(buffer, 0, 3 * map_size); + + for(size_t i = 0; i < colours_num; i++) + { + size_t j = (size_t)keyvalue_map[i] * 3; + buffer[j + 0] = RGBGetRValue(colours[i]); + buffer[j + 1] = RGBGetGValue(colours[i]); + buffer[j + 2] = RGBGetBValue(colours[i]); + } + + BeginConfigure(); + Write(EVISION_V2_CMD_WRITE_CUSTOM_COLORS, 512 * colorset, buffer, (uint16_t)(3 * map_size)); + EndConfigure(); + + delete[] buffer; +} diff --git a/Controllers/EVisionKeyboardController/EVisionV2KeyboardController.h b/Controllers/EVisionKeyboardController/EVisionV2KeyboardController.h new file mode 100644 index 00000000..605f7cd2 --- /dev/null +++ b/Controllers/EVisionKeyboardController/EVisionV2KeyboardController.h @@ -0,0 +1,197 @@ +/*---------------------------------------------------------*\ +| EVisionV2KeyboardController.h | +| | +| Driver for EVision V2 keyboard | +| | +| Le Philousophe 25 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define EVISION_V2_PACKET_SIZE 64 +#define HID_MAX_STR 255 + +#define EVISION_V2_REPORT_ID 4 + +#define EVISION_V2_MATRIX_HEIGHT 6 +#define EVISION_V2_MATRIX_WIDTH 21 + +enum +{ + EVISION_V2_MODE_COLOR_WAVE_SHORT = 0x01, /* "Go with the stream" */ + EVISION_V2_MODE_COLOR_WAVE_LONG = 0x02, /* "Clouds fly" */ + EVISION_V2_MODE_COLOR_WHEEL = 0x03, /* "Winding paths" */ + EVISION_V2_MODE_SPECTRUM_CYCLE = 0x04, /* "Spectrum" */ + EVISION_V2_MODE_BREATHING = 0x05, /* "Breath" */ + EVISION_V2_MODE_STATIC = 0x06, /* "Normal" */ + EVISION_V2_MODE_REACTIVE = 0x07, /* "Pass without trace" */ + EVISION_V2_MODE_REACTIVE_RIPPLE = 0x08, /* "Ripples" */ + EVISION_V2_MODE_REACTIVE_LINE = 0x09, /* "Stream" */ + EVISION_V2_MODE_STARLIGHT_FAST = 0x0A, /* "Stars" */ + EVISION_V2_MODE_BLOOMING = 0x0B, /* "Flowers" */ + EVISION_V2_MODE_RAINBOW_WAVE_VERTICAL = 0x0C, /* "Swift action" */ + EVISION_V2_MODE_HURRICANE = 0x0D, /* "Hurricane" */ + EVISION_V2_MODE_ACCUMULATE = 0x0E, /* "Cartoon" */ + EVISION_V2_MODE_STARLIGHT_SLOW = 0x0F, /* "Digital times" */ + EVISION_V2_MODE_VISOR = 0x10, /* "Both ways" */ + EVISION_V2_MODE_SURMOUNT = 0x11, /* "Surmount" */ + EVISION_V2_MODE_RAINBOW_WAVE_CIRCLE = 0x12, /* "Speed" */ + EVISION_V2_MODE_CUSTOM = 0x14, /* "Custom" */ + + EVISION_V2_MODE_DIRECT = 0xFF, /* Software controlled mode */ +}; + +enum +{ + EVISION_V2_MODE2_COLOR_WAVE = 0x00, /* "Pulsation" */ + EVISION_V2_MODE2_BREATHING = 0x01, /* "Breath" */ + EVISION_V2_MODE2_YOYO = 0x02, /* "Yoyo" */ + EVISION_V2_MODE2_BLINK = 0x03, /* "Blink" */ + EVISION_V2_MODE2_STATIC = 0x04, /* "Normal" */ + EVISION_V2_MODE2_OFF = 0x05, /* "Off" */ +}; + +enum +{ + /* Official software doesn't support changing edges */ + ENDORFY_MODE2_FREEZE = 0x00, + ENDORFY_MODE2_COLOR_WAVE = 0x01, + ENDORFY_MODE2_SPECTRUM_CYCLE = 0x02, + ENDORFY_MODE2_BREATHING = 0x03, + ENDORFY_MODE2_STATIC = 0x04, + ENDORFY_MODE2_OFF = 0x05, +}; + +enum +{ + EVISION_V2_CMD_BEGIN_CONFIGURE = 0x01, + EVISION_V2_CMD_END_CONFIGURE = 0x02, + EVISION_V2_CMD_READ_CAPABILITIES = 0x03, + //EVISION_V2_CMD_WRITE_CAPABILITIES = 0x04, + EVISION_V2_CMD_READ_CONFIG = 0x05, + EVISION_V2_CMD_WRITE_CONFIG = 0x06, + EVISION_V2_CMD_READ_CUSTOM_COLORS = 0x0A, + EVISION_V2_CMD_WRITE_CUSTOM_COLORS = 0x0B, + EVISION_V2_CMD_SEND_DYNAMIC_COLORS = 0x12, + EVISION_V2_CMD_END_DYNAMIC_COLORS = 0x13, +}; + +enum +{ + EVISION_V2_OFFSET_CURRENT_PROFILE = 0x00, + EVISION_V2_OFFSET_FIRST_PROFILE = 0x01, + EVISION_V2_OFFSET_SECOND_PROFILE = 0x41, + EVISION_V2_OFFSET_THIRD_PROFILE = 0x81, +}; + +enum +{ + EVISION_V2_PARAMETER_MODE = 0x00, /* Mode parameter */ + EVISION_V2_PARAMETER_BRIGHTNESS = 0x01, /* Brightness parameter */ + EVISION_V2_PARAMETER_SPEED = 0x02, /* Speed parameter */ + EVISION_V2_PARAMETER_DIRECTION = 0x03, /* Direction parameter */ + EVISION_V2_PARAMETER_RANDOM_COLOR_FLAG = 0x04, /* Random color parameter */ + EVISION_V2_PARAMETER_MODE_COLOR = 0x05, /* Mode color (RGB) */ + EVISION_V2_PARAMETER_COLOR_OFFSET = 0x08, /* Unknown color offset */ + EVISION_V2_PARAMETER_LED_MODE_COLOR = 0x11, /* Led mode color */ + EVISION_V2_PARAMETER_CURRENT_CUSTOM_MODE = 0x19, /* Custom mode current colorset */ + EVISION_V2_PARAMETER_LOGO = 0x1a, /* Logo parameters */ + EVISION_V2_PARAMETER_LOGO_ON_OFF = 0x23, /* Logo on/off */ + EVISION_V2_PARAMETER_EDGE = 0x24, /* Edge parameters */ + EVISION_V2_PARAMETER_END = 0x2b, /* Address after last parameter */ +}; + +enum +{ + EVISION_V2_BRIGHTNESS_LOWEST = 0x00, /* Lowest brightness (off) */ + EVISION_V2_BRIGHTNESS_HIGHEST = 0x04, /* Highest brightness */ +}; + +enum +{ + EVISION_V2_SPEED_SLOWEST = 0x05, /* Slowest speed setting */ + EVISION_V2_SPEED_NORMAL = 0x03, /* Normal speed setting */ + EVISION_V2_SPEED_FASTEST = 0x00, /* Fastest speed setting */ +}; + +enum +{ + EVISION_V2_SURMOUNT_MODE_COLOR_RED = 0x00, /* Red surmount color */ + EVISION_V2_SURMOUNT_MODE_COLOR_YELLOW = 0x01, /* Yellow surmount color */ + EVISION_V2_SURMOUNT_MODE_COLOR_GREEN = 0x02, /* Green surmount color */ + EVISION_V2_SURMOUNT_MODE_COLOR_CYAN = 0x03, /* Cyan surmount color */ +}; + +enum EVisionV2KeyboardLayout +{ + EVISION_V2_KEYBOARD_LAYOUT, + ENDORFY_KEYBOARD_LAYOUT, +}; + +enum EVisionV2KeyboardPart +{ + EVISION_V2_KEYBOARD_PART_KEYBOARD, + EVISION_V2_KEYBOARD_PART_LOGO, + EVISION_V2_KEYBOARD_PART_EDGE, + ENDORFY_KEYBOARD_PART_EDGE, +}; + +struct EvisionV2ModeConfig +{ + uint8_t mode; + uint8_t brightness; + uint8_t speed; + uint8_t direction; + bool random_colours; + RGBColor colour; + uint8_t ledmode; +}; + +class EVisionV2KeyboardController +{ +public: + EVisionV2KeyboardController(hid_device* dev_handle, const char* path, EVisionV2KeyboardLayout dev_layout, std::string dev_name); + ~EVisionV2KeyboardController(); + + std::string GetName(); + std::string GetSerial(); + std::string GetLocation(); + + int Query(uint8_t cmd, uint16_t offset = 0, const uint8_t* idata = nullptr, uint8_t size = 0, uint8_t* odata = nullptr); + int BeginConfigure(); + int EndConfigure(); + int Read(uint8_t cmd, uint16_t offset, uint16_t size, uint8_t* odata); + int Write(uint8_t cmd, uint16_t offset, const uint8_t* idata, uint16_t size); + + int GetMode(EVisionV2KeyboardPart part, EvisionV2ModeConfig& config); + void SetMode(EVisionV2KeyboardPart part, const EvisionV2ModeConfig& config); + void SetLedsDirect(const std::vector& colours); + void SetLedDirect(int led, RGBColor colours); + void RefreshLedDirect(); + void EndLedsDirect(); + int GetLedsCustom(uint8_t colorset, std::vector& colours); + void SetLedsCustom(uint8_t colorset, const std::vector& colours); + + EVisionV2KeyboardLayout layout; + +private: + std::string name; + std::string serial; + std::string location; + hid_device* dev; + + size_t map_size; + size_t macros_size; + + uint8_t * keyvalue_map; + size_t led_count; + + std::mutex query_mutex; +}; diff --git a/Controllers/EVisionKeyboardController/RGBController_EVisionKeyboard.cpp b/Controllers/EVisionKeyboardController/RGBController_EVisionKeyboard.cpp index 70717d3f..56d77d9e 100644 --- a/Controllers/EVisionKeyboardController/RGBController_EVisionKeyboard.cpp +++ b/Controllers/EVisionKeyboardController/RGBController_EVisionKeyboard.cpp @@ -1,11 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_EVisionKeyboard.cpp | -| | -| Generic RGB Interface for EVision RGB | -| Keyboard | -| | -| Adam Honse (CalcProgrammer1) 3/25/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_EVisionKeyboard.cpp | +| | +| RGBController for EVision keyboard (Redragon, Glorious, | +| Ajazz, Tecware, and many other brands) | +| | +| Adam Honse (CalcProgrammer1) 25 Mar 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_EVisionKeyboard.h" @@ -33,264 +36,264 @@ static unsigned int matrix_map[6][23] = RGBController_EVisionKeyboard::RGBController_EVisionKeyboard(EVisionKeyboardController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "EVision Keyboard Device"; - vendor = "EVision"; - type = DEVICE_TYPE_KEYBOARD; - description = "EVision Keyboard Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "EVision"; + type = DEVICE_TYPE_KEYBOARD; + description = "EVision Keyboard Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Custom; - Custom.name = "Custom"; - Custom.value = EVISION_KB_MODE_CUSTOM; - Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Custom.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - Custom.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - Custom.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - Custom.color_mode = MODE_COLORS_PER_LED; + Custom.name = "Custom"; + Custom.value = EVISION_KB_MODE_CUSTOM; + Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Custom.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + Custom.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + Custom.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + Custom.color_mode = MODE_COLORS_PER_LED; modes.push_back(Custom); mode ColorWave; - ColorWave.name = "Color Wave"; - ColorWave.value = EVISION_KB_MODE_COLOR_WAVE_LONG; - ColorWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_AUTOMATIC_SAVE; - ColorWave.speed_min = EVISION_KB_SPEED_SLOWEST; - ColorWave.speed_max = EVISION_KB_SPEED_FASTEST; - ColorWave.speed = EVISION_KB_SPEED_NORMAL; - ColorWave.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - ColorWave.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - ColorWave.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - ColorWave.direction = MODE_DIRECTION_LEFT; - ColorWave.colors_min = 1; - ColorWave.colors_max = 1; - ColorWave.color_mode = MODE_COLORS_MODE_SPECIFIC; + ColorWave.name = "Color Wave"; + ColorWave.value = EVISION_KB_MODE_COLOR_WAVE_LONG; + ColorWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_AUTOMATIC_SAVE; + ColorWave.speed_min = EVISION_KB_SPEED_SLOWEST; + ColorWave.speed_max = EVISION_KB_SPEED_FASTEST; + ColorWave.speed = EVISION_KB_SPEED_NORMAL; + ColorWave.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + ColorWave.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + ColorWave.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + ColorWave.direction = MODE_DIRECTION_LEFT; + ColorWave.colors_min = 1; + ColorWave.colors_max = 1; + ColorWave.color_mode = MODE_COLORS_MODE_SPECIFIC; ColorWave.colors.resize(1); modes.push_back(ColorWave); mode ColorWaveShort; - ColorWaveShort.name = "Color Wave (Short)"; - ColorWaveShort.value = EVISION_KB_MODE_COLOR_WAVE_SHORT; - ColorWaveShort.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_AUTOMATIC_SAVE; - ColorWaveShort.speed_min = EVISION_KB_SPEED_SLOWEST; - ColorWaveShort.speed_max = EVISION_KB_SPEED_FASTEST; - ColorWaveShort.speed = EVISION_KB_SPEED_NORMAL; - ColorWaveShort.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - ColorWaveShort.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - ColorWaveShort.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - ColorWaveShort.direction = MODE_DIRECTION_LEFT; - ColorWaveShort.colors_min = 1; - ColorWaveShort.colors_max = 1; - ColorWaveShort.color_mode = MODE_COLORS_MODE_SPECIFIC; + ColorWaveShort.name = "Color Wave (Short)"; + ColorWaveShort.value = EVISION_KB_MODE_COLOR_WAVE_SHORT; + ColorWaveShort.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_AUTOMATIC_SAVE; + ColorWaveShort.speed_min = EVISION_KB_SPEED_SLOWEST; + ColorWaveShort.speed_max = EVISION_KB_SPEED_FASTEST; + ColorWaveShort.speed = EVISION_KB_SPEED_NORMAL; + ColorWaveShort.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + ColorWaveShort.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + ColorWaveShort.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + ColorWaveShort.direction = MODE_DIRECTION_LEFT; + ColorWaveShort.colors_min = 1; + ColorWaveShort.colors_max = 1; + ColorWaveShort.color_mode = MODE_COLORS_MODE_SPECIFIC; ColorWaveShort.colors.resize(1); modes.push_back(ColorWaveShort); mode ColorWheel; - ColorWheel.name = "Color Wheel"; - ColorWheel.value = EVISION_KB_MODE_COLOR_WHEEL; - ColorWheel.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_AUTOMATIC_SAVE; - ColorWheel.speed_min = EVISION_KB_SPEED_SLOWEST; - ColorWheel.speed_max = EVISION_KB_SPEED_FASTEST; - ColorWheel.speed = EVISION_KB_SPEED_NORMAL; - ColorWheel.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - ColorWheel.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - ColorWheel.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - ColorWheel.direction = MODE_DIRECTION_LEFT; - ColorWheel.colors_min = 1; - ColorWheel.colors_max = 1; - ColorWheel.color_mode = MODE_COLORS_MODE_SPECIFIC; + ColorWheel.name = "Color Wheel"; + ColorWheel.value = EVISION_KB_MODE_COLOR_WHEEL; + ColorWheel.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_AUTOMATIC_SAVE; + ColorWheel.speed_min = EVISION_KB_SPEED_SLOWEST; + ColorWheel.speed_max = EVISION_KB_SPEED_FASTEST; + ColorWheel.speed = EVISION_KB_SPEED_NORMAL; + ColorWheel.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + ColorWheel.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + ColorWheel.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + ColorWheel.direction = MODE_DIRECTION_LEFT; + ColorWheel.colors_min = 1; + ColorWheel.colors_max = 1; + ColorWheel.color_mode = MODE_COLORS_MODE_SPECIFIC; ColorWheel.colors.resize(1); modes.push_back(ColorWheel); mode SpectrumCycle; - SpectrumCycle.name = "Spectrum Cycle"; - SpectrumCycle.value = EVISION_KB_MODE_SPECTRUM_CYCLE; - SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - SpectrumCycle.speed_min = EVISION_KB_SPEED_SLOWEST; - SpectrumCycle.speed_max = EVISION_KB_SPEED_FASTEST; - SpectrumCycle.speed = EVISION_KB_SPEED_NORMAL; - SpectrumCycle.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - SpectrumCycle.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - SpectrumCycle.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = EVISION_KB_MODE_SPECTRUM_CYCLE; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + SpectrumCycle.speed_min = EVISION_KB_SPEED_SLOWEST; + SpectrumCycle.speed_max = EVISION_KB_SPEED_FASTEST; + SpectrumCycle.speed = EVISION_KB_SPEED_NORMAL; + SpectrumCycle.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + SpectrumCycle.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + SpectrumCycle.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + SpectrumCycle.color_mode = MODE_COLORS_NONE; modes.push_back(SpectrumCycle); mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = EVISION_KB_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Breathing.speed_min = EVISION_KB_SPEED_SLOWEST; - Breathing.speed_max = EVISION_KB_SPEED_FASTEST; - Breathing.speed = EVISION_KB_SPEED_NORMAL; - Breathing.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - Breathing.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - Breathing.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - Breathing.colors_min = 1; - Breathing.colors_max = 1; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.name = "Breathing"; + Breathing.value = EVISION_KB_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.speed_min = EVISION_KB_SPEED_SLOWEST; + Breathing.speed_max = EVISION_KB_SPEED_FASTEST; + Breathing.speed = EVISION_KB_SPEED_NORMAL; + Breathing.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + Breathing.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + Breathing.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; Breathing.colors.resize(1); modes.push_back(Breathing); mode Hurricane; - Hurricane.name = "Hurricane"; - Hurricane.value = EVISION_KB_MODE_HURRICANE; - Hurricane.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Hurricane.speed_min = EVISION_KB_SPEED_SLOWEST; - Hurricane.speed_max = EVISION_KB_SPEED_FASTEST; - Hurricane.speed = EVISION_KB_SPEED_NORMAL; - Hurricane.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - Hurricane.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - Hurricane.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - Hurricane.colors_min = 1; - Hurricane.colors_max = 1; - Hurricane.color_mode = MODE_COLORS_MODE_SPECIFIC; + Hurricane.name = "Hurricane"; + Hurricane.value = EVISION_KB_MODE_HURRICANE; + Hurricane.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Hurricane.speed_min = EVISION_KB_SPEED_SLOWEST; + Hurricane.speed_max = EVISION_KB_SPEED_FASTEST; + Hurricane.speed = EVISION_KB_SPEED_NORMAL; + Hurricane.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + Hurricane.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + Hurricane.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + Hurricane.colors_min = 1; + Hurricane.colors_max = 1; + Hurricane.color_mode = MODE_COLORS_MODE_SPECIFIC; Hurricane.colors.resize(1); modes.push_back(Hurricane); mode Accumulate; - Accumulate.name = "Accumulate"; - Accumulate.value = EVISION_KB_MODE_ACCUMULATE; - Accumulate.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Accumulate.speed_min = EVISION_KB_SPEED_SLOWEST; - Accumulate.speed_max = EVISION_KB_SPEED_FASTEST; - Accumulate.speed = EVISION_KB_SPEED_NORMAL; - Accumulate.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - Accumulate.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - Accumulate.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - Accumulate.colors_min = 1; - Accumulate.colors_max = 1; - Accumulate.color_mode = MODE_COLORS_MODE_SPECIFIC; + Accumulate.name = "Accumulate"; + Accumulate.value = EVISION_KB_MODE_ACCUMULATE; + Accumulate.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Accumulate.speed_min = EVISION_KB_SPEED_SLOWEST; + Accumulate.speed_max = EVISION_KB_SPEED_FASTEST; + Accumulate.speed = EVISION_KB_SPEED_NORMAL; + Accumulate.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + Accumulate.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + Accumulate.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + Accumulate.colors_min = 1; + Accumulate.colors_max = 1; + Accumulate.color_mode = MODE_COLORS_MODE_SPECIFIC; Accumulate.colors.resize(1); modes.push_back(Accumulate); mode Starlight; - Starlight.name = "Starlight"; - Starlight.value = EVISION_KB_MODE_STARLIGHT_FAST; - Starlight.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Starlight.speed_min = EVISION_KB_SPEED_SLOWEST; - Starlight.speed_max = EVISION_KB_SPEED_FASTEST; - Starlight.speed = EVISION_KB_SPEED_NORMAL; - Starlight.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - Starlight.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - Starlight.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - Starlight.colors_min = 1; - Starlight.colors_max = 1; - Starlight.color_mode = MODE_COLORS_MODE_SPECIFIC; + Starlight.name = "Starlight"; + Starlight.value = EVISION_KB_MODE_STARLIGHT_FAST; + Starlight.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Starlight.speed_min = EVISION_KB_SPEED_SLOWEST; + Starlight.speed_max = EVISION_KB_SPEED_FASTEST; + Starlight.speed = EVISION_KB_SPEED_NORMAL; + Starlight.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + Starlight.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + Starlight.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + Starlight.colors_min = 1; + Starlight.colors_max = 1; + Starlight.color_mode = MODE_COLORS_MODE_SPECIFIC; Starlight.colors.resize(1); modes.push_back(Starlight); mode Visor; - Visor.name = "Visor"; - Visor.value = EVISION_KB_MODE_VISOR; - Visor.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Visor.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - Visor.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - Visor.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - Visor.colors_min = 1; - Visor.colors_max = 1; - Visor.color_mode = MODE_COLORS_MODE_SPECIFIC; + Visor.name = "Visor"; + Visor.value = EVISION_KB_MODE_VISOR; + Visor.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Visor.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + Visor.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + Visor.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + Visor.colors_min = 1; + Visor.colors_max = 1; + Visor.color_mode = MODE_COLORS_MODE_SPECIFIC; Visor.colors.resize(1); modes.push_back(Visor); mode Static; - Static.name = "Static"; - Static.value = EVISION_KB_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Static.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - Static.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - Static.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - Static.colors_min = 1; - Static.colors_max = 1; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.name = "Static"; + Static.value = EVISION_KB_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Static.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + Static.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + Static.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + Static.colors_min = 1; + Static.colors_max = 1; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; Static.colors.resize(1); modes.push_back(Static); mode RainbowCircle; - RainbowCircle.name = "Rainbow Circle"; - RainbowCircle.value = EVISION_KB_MODE_RAINBOW_WAVE_CIRCLE; - RainbowCircle.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - RainbowCircle.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - RainbowCircle.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - RainbowCircle.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - RainbowCircle.color_mode = MODE_COLORS_RANDOM; + RainbowCircle.name = "Rainbow Circle"; + RainbowCircle.value = EVISION_KB_MODE_RAINBOW_WAVE_CIRCLE; + RainbowCircle.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + RainbowCircle.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + RainbowCircle.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + RainbowCircle.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + RainbowCircle.color_mode = MODE_COLORS_RANDOM; modes.push_back(RainbowCircle); mode VerticalRainbow; - VerticalRainbow.name = "Vertical Rainbow"; - VerticalRainbow.value = EVISION_KB_MODE_RAINBOW_WAVE_VERTICAL; - VerticalRainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_AUTOMATIC_SAVE; - VerticalRainbow.speed_min = EVISION_KB_SPEED_SLOWEST; - VerticalRainbow.speed_max = EVISION_KB_SPEED_FASTEST; - VerticalRainbow.speed = EVISION_KB_SPEED_NORMAL; - VerticalRainbow.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - VerticalRainbow.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - VerticalRainbow.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - VerticalRainbow.direction = MODE_DIRECTION_UP; - VerticalRainbow.colors_min = 1; - VerticalRainbow.colors_max = 1; - VerticalRainbow.color_mode = MODE_COLORS_MODE_SPECIFIC; + VerticalRainbow.name = "Vertical Rainbow"; + VerticalRainbow.value = EVISION_KB_MODE_RAINBOW_WAVE_VERTICAL; + VerticalRainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_AUTOMATIC_SAVE; + VerticalRainbow.speed_min = EVISION_KB_SPEED_SLOWEST; + VerticalRainbow.speed_max = EVISION_KB_SPEED_FASTEST; + VerticalRainbow.speed = EVISION_KB_SPEED_NORMAL; + VerticalRainbow.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + VerticalRainbow.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + VerticalRainbow.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + VerticalRainbow.direction = MODE_DIRECTION_UP; + VerticalRainbow.colors_min = 1; + VerticalRainbow.colors_max = 1; + VerticalRainbow.color_mode = MODE_COLORS_MODE_SPECIFIC; VerticalRainbow.colors.resize(1); modes.push_back(VerticalRainbow); mode Blooming; - Blooming.name = "Blooming"; - Blooming.value = EVISION_KB_MODE_BLOOMING; - Blooming.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Blooming.speed_min = EVISION_KB_SPEED_SLOWEST; - Blooming.speed_max = EVISION_KB_SPEED_FASTEST; - Blooming.speed = EVISION_KB_SPEED_NORMAL; - Blooming.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - Blooming.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - Blooming.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - Blooming.color_mode = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Blooming.name = "Blooming"; + Blooming.value = EVISION_KB_MODE_BLOOMING; + Blooming.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Blooming.speed_min = EVISION_KB_SPEED_SLOWEST; + Blooming.speed_max = EVISION_KB_SPEED_FASTEST; + Blooming.speed = EVISION_KB_SPEED_NORMAL; + Blooming.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + Blooming.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + Blooming.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + Blooming.color_mode = MODE_COLORS_RANDOM; modes.push_back(Blooming); mode Reactive; - Reactive.name = "Reactive"; - Reactive.value = EVISION_KB_MODE_REACTIVE; - Reactive.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Reactive.speed_min = EVISION_KB_SPEED_SLOWEST; - Reactive.speed_max = EVISION_KB_SPEED_FASTEST; - Reactive.speed = EVISION_KB_SPEED_NORMAL; - Reactive.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - Reactive.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - Reactive.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - Reactive.colors_min = 1; - Reactive.colors_max = 1; - Reactive.color_mode = MODE_COLORS_MODE_SPECIFIC; + Reactive.name = "Reactive"; + Reactive.value = EVISION_KB_MODE_REACTIVE; + Reactive.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Reactive.speed_min = EVISION_KB_SPEED_SLOWEST; + Reactive.speed_max = EVISION_KB_SPEED_FASTEST; + Reactive.speed = EVISION_KB_SPEED_NORMAL; + Reactive.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + Reactive.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + Reactive.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + Reactive.colors_min = 1; + Reactive.colors_max = 1; + Reactive.color_mode = MODE_COLORS_MODE_SPECIFIC; Reactive.colors.resize(1); modes.push_back(Reactive); mode ReactiveRipple; - ReactiveRipple.name = "Reactive Ripple"; - ReactiveRipple.value = EVISION_KB_MODE_REACTIVE_RIPPLE; - ReactiveRipple.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - ReactiveRipple.speed_min = EVISION_KB_SPEED_SLOWEST; - ReactiveRipple.speed_max = EVISION_KB_SPEED_FASTEST; - ReactiveRipple.speed = EVISION_KB_SPEED_NORMAL; - ReactiveRipple.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - ReactiveRipple.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - ReactiveRipple.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - ReactiveRipple.colors_min = 1; - ReactiveRipple.colors_max = 1; - ReactiveRipple.color_mode = MODE_COLORS_MODE_SPECIFIC; + ReactiveRipple.name = "Reactive Ripple"; + ReactiveRipple.value = EVISION_KB_MODE_REACTIVE_RIPPLE; + ReactiveRipple.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + ReactiveRipple.speed_min = EVISION_KB_SPEED_SLOWEST; + ReactiveRipple.speed_max = EVISION_KB_SPEED_FASTEST; + ReactiveRipple.speed = EVISION_KB_SPEED_NORMAL; + ReactiveRipple.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + ReactiveRipple.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + ReactiveRipple.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + ReactiveRipple.colors_min = 1; + ReactiveRipple.colors_max = 1; + ReactiveRipple.color_mode = MODE_COLORS_MODE_SPECIFIC; ReactiveRipple.colors.resize(1); modes.push_back(ReactiveRipple); mode ReactiveLine; - ReactiveLine.name = "Reactive Line"; - ReactiveLine.value = EVISION_KB_MODE_REACTIVE_LINE; - ReactiveLine.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - ReactiveLine.speed_min = EVISION_KB_SPEED_SLOWEST; - ReactiveLine.speed_max = EVISION_KB_SPEED_FASTEST; - ReactiveLine.speed = EVISION_KB_SPEED_NORMAL; - ReactiveLine.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; - ReactiveLine.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; - ReactiveLine.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; - ReactiveLine.colors_min = 1; - ReactiveLine.colors_max = 1; - ReactiveLine.color_mode = MODE_COLORS_MODE_SPECIFIC; + ReactiveLine.name = "Reactive Line"; + ReactiveLine.value = EVISION_KB_MODE_REACTIVE_LINE; + ReactiveLine.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + ReactiveLine.speed_min = EVISION_KB_SPEED_SLOWEST; + ReactiveLine.speed_max = EVISION_KB_SPEED_FASTEST; + ReactiveLine.speed = EVISION_KB_SPEED_NORMAL; + ReactiveLine.brightness_min = EVISION_KB_BRIGHTNESS_LOWEST; + ReactiveLine.brightness_max = EVISION_KB_BRIGHTNESS_HIGHEST; + ReactiveLine.brightness = EVISION_KB_BRIGHTNESS_HIGHEST; + ReactiveLine.colors_min = 1; + ReactiveLine.colors_max = 1; + ReactiveLine.color_mode = MODE_COLORS_MODE_SPECIFIC; ReactiveLine.colors.resize(1); modes.push_back(ReactiveLine); diff --git a/Controllers/EVisionKeyboardController/RGBController_EVisionKeyboard.h b/Controllers/EVisionKeyboardController/RGBController_EVisionKeyboard.h index 6622b8cc..74e9547e 100644 --- a/Controllers/EVisionKeyboardController/RGBController_EVisionKeyboard.h +++ b/Controllers/EVisionKeyboardController/RGBController_EVisionKeyboard.h @@ -1,13 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_EVisionKeyboard.h | -| | -| Generic RGB Interface for EVision RGB | -| Keyboard | -| | -| Adam Honse (CalcProgrammer1) 3/25/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_EVisionKeyboard.h | +| | +| RGBController for EVision keyboard (Redragon, Glorious, | +| Ajazz, Tecware, and many other brands) | +| | +| Adam Honse (CalcProgrammer1) 25 Mar 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "EVisionKeyboardController.h" diff --git a/Controllers/EVisionKeyboardController/RGBController_EVisionV2Keyboard.cpp b/Controllers/EVisionKeyboardController/RGBController_EVisionV2Keyboard.cpp new file mode 100644 index 00000000..e1835d26 --- /dev/null +++ b/Controllers/EVisionKeyboardController/RGBController_EVisionV2Keyboard.cpp @@ -0,0 +1,1041 @@ +/*---------------------------------------------------------*\ +| RGBController_EVisionV2Keyboard.cpp | +| | +| RGBController for EVision V2 keyboard | +| | +| Le Philousophe 25 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#define NA 0xFFFFFFFF + +#include +#include "hsv.h" +#include "RGBControllerKeyNames.h" +#include "RGBController_EVisionV2Keyboard.h" + +using namespace std::chrono_literals; + +static unsigned int evisionv2_matrix[EVISION_V2_MATRIX_HEIGHT][EVISION_V2_MATRIX_WIDTH] = +{ + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 19 19 20 */ + { 0, NA, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, NA, NA, NA, NA }, + { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36 }, + { 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57 }, + { 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, NA, NA, NA, 72, 73, 74, NA }, + { 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, NA, 87, NA, 88, NA, 89, 90, 91, 92 }, + { 93, 94, 95, NA, NA, NA, 96, NA, NA, NA, 97, 98, 99, 100, 101, 102, 103, NA, 104, 105, NA } +}; + +static unsigned int endorfy_matrix[EVISION_V2_MATRIX_HEIGHT][EVISION_V2_MATRIX_WIDTH] = +{ + /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 19 19 20 */ + { 0, NA, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, NA, NA, NA, NA }, + { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36 }, + { 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57 }, + { 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, NA, 70, NA, NA, NA, 71, 72, 73, NA }, + { 74, NA, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, NA, NA, 86, NA, 87, 88, 89, 90 }, + { 91, 92, 93, NA, NA, NA, 94, NA, NA, NA, 95, 96, 97, 98, 99, 100, 101, 102, NA, 103, NA } +}; + +static const char *led_evisionv2[] = +{ + KEY_EN_ESCAPE, //00 + KEY_EN_F1, + KEY_EN_F2, + KEY_EN_F3, + KEY_EN_F4, + KEY_EN_F5, + KEY_EN_F6, + KEY_EN_F7, + KEY_EN_F8, + KEY_EN_F9, + KEY_EN_F10, //10 + KEY_EN_F11, + KEY_EN_F12, + KEY_EN_PRINT_SCREEN, + KEY_EN_SCROLL_LOCK, + KEY_EN_PAUSE_BREAK, + + KEY_EN_BACK_TICK, //16 + KEY_EN_1, + KEY_EN_2, + KEY_EN_3, + KEY_EN_4, //20 + KEY_EN_5, + KEY_EN_6, + KEY_EN_7, + KEY_EN_8, + KEY_EN_9, + KEY_EN_0, + KEY_EN_MINUS, + KEY_EN_EQUALS, + KEY_EN_BACKSPACE, + KEY_EN_INSERT, + KEY_EN_HOME, //30 + KEY_EN_PAGE_UP, + KEY_EN_NUMPAD_LOCK, + KEY_EN_NUMPAD_DIVIDE, + KEY_EN_NUMPAD_TIMES, + KEY_EN_NUMPAD_MINUS, + + KEY_EN_TAB, //37 + KEY_EN_Q, + KEY_EN_W, + KEY_EN_E, //40 + KEY_EN_R, + KEY_EN_T, + KEY_EN_Y, + KEY_EN_U, + KEY_EN_I, + KEY_EN_O, + KEY_EN_P, + KEY_EN_LEFT_BRACKET, + KEY_EN_RIGHT_BRACKET, + KEY_EN_ANSI_BACK_SLASH, //50 + KEY_EN_DELETE, + KEY_EN_END, + KEY_EN_PAGE_DOWN, + KEY_EN_NUMPAD_7, + KEY_EN_NUMPAD_8, + KEY_EN_NUMPAD_9, + KEY_EN_NUMPAD_PLUS, + + KEY_EN_CAPS_LOCK, //58 + KEY_EN_A, + KEY_EN_S, + KEY_EN_D, + KEY_EN_F, + KEY_EN_G, + KEY_EN_H, + KEY_EN_J, + KEY_EN_K, + KEY_EN_L, + KEY_EN_SEMICOLON, + KEY_EN_QUOTE, + KEY_EN_POUND, //70 + KEY_EN_ISO_ENTER, + KEY_EN_NUMPAD_4, + KEY_EN_NUMPAD_5, + KEY_EN_NUMPAD_6, + + KEY_EN_LEFT_SHIFT, //75 + KEY_EN_ISO_BACK_SLASH, + KEY_EN_Z, + KEY_EN_X, + KEY_EN_C, + KEY_EN_V, //80 + KEY_EN_B, + KEY_EN_N, + KEY_EN_M, + KEY_EN_COMMA, + KEY_EN_PERIOD, + KEY_EN_FORWARD_SLASH, + KEY_EN_RIGHT_SHIFT, + KEY_EN_UP_ARROW, + KEY_EN_NUMPAD_1, + KEY_EN_NUMPAD_2, //90 + KEY_EN_NUMPAD_3, + KEY_EN_NUMPAD_ENTER, + + KEY_EN_LEFT_CONTROL, //93 + KEY_EN_LEFT_WINDOWS, + KEY_EN_LEFT_ALT, + KEY_EN_SPACE, + KEY_EN_RIGHT_ALT, + KEY_EN_RIGHT_WINDOWS, + KEY_EN_RIGHT_FUNCTION, + KEY_EN_RIGHT_CONTROL, //100 + KEY_EN_LEFT_ARROW, + KEY_EN_DOWN_ARROW, + KEY_EN_RIGHT_ARROW, + KEY_EN_NUMPAD_0, + KEY_EN_NUMPAD_PERIOD, +}; + +static const char *led_endorfy[] = +{ + KEY_EN_ESCAPE, //00 + KEY_EN_F1, + KEY_EN_F2, + KEY_EN_F3, + KEY_EN_F4, + KEY_EN_F5, + KEY_EN_F6, + KEY_EN_F7, + KEY_EN_F8, + KEY_EN_F9, + KEY_EN_F10, //10 + KEY_EN_F11, + KEY_EN_F12, + KEY_EN_PRINT_SCREEN, + KEY_EN_SCROLL_LOCK, + KEY_EN_PAUSE_BREAK, + + KEY_EN_BACK_TICK, //16 + KEY_EN_1, + KEY_EN_2, + KEY_EN_3, + KEY_EN_4, //20 + KEY_EN_5, + KEY_EN_6, + KEY_EN_7, + KEY_EN_8, + KEY_EN_9, + KEY_EN_0, + KEY_EN_MINUS, + KEY_EN_EQUALS, + KEY_EN_BACKSPACE, + KEY_EN_INSERT, + KEY_EN_HOME, //30 + KEY_EN_PAGE_UP, + KEY_EN_NUMPAD_LOCK, + KEY_EN_NUMPAD_DIVIDE, + KEY_EN_NUMPAD_TIMES, + KEY_EN_NUMPAD_MINUS, + + KEY_EN_TAB, //37 + KEY_EN_Q, + KEY_EN_W, + KEY_EN_E, //40 + KEY_EN_R, + KEY_EN_T, + KEY_EN_Y, + KEY_EN_U, + KEY_EN_I, + KEY_EN_O, + KEY_EN_P, + KEY_EN_LEFT_BRACKET, + KEY_EN_RIGHT_BRACKET, + KEY_EN_ANSI_BACK_SLASH, //50 + KEY_EN_DELETE, + KEY_EN_END, + KEY_EN_PAGE_DOWN, + KEY_EN_NUMPAD_7, + KEY_EN_NUMPAD_8, + KEY_EN_NUMPAD_9, + KEY_EN_NUMPAD_PLUS, + + KEY_EN_CAPS_LOCK, //58 + KEY_EN_A, + KEY_EN_S, + KEY_EN_D, + KEY_EN_F, + KEY_EN_G, + KEY_EN_H, + KEY_EN_J, + KEY_EN_K, + KEY_EN_L, + KEY_EN_SEMICOLON, + KEY_EN_QUOTE, + KEY_EN_ANSI_ENTER, //70 + KEY_EN_NUMPAD_4, + KEY_EN_NUMPAD_5, + KEY_EN_NUMPAD_6, + + KEY_EN_LEFT_SHIFT, + KEY_EN_Z, //75 + KEY_EN_X, + KEY_EN_C, + KEY_EN_V, + KEY_EN_B, //80 + KEY_EN_N, + KEY_EN_M, + KEY_EN_COMMA, + KEY_EN_PERIOD, + KEY_EN_FORWARD_SLASH, + KEY_EN_RIGHT_SHIFT, + KEY_EN_UP_ARROW, + KEY_EN_NUMPAD_1, + KEY_EN_NUMPAD_2, + KEY_EN_NUMPAD_3, //90 + KEY_EN_NUMPAD_ENTER, + + KEY_EN_LEFT_CONTROL, + KEY_EN_LEFT_WINDOWS, //93 + KEY_EN_LEFT_ALT, + KEY_EN_SPACE, + KEY_EN_RIGHT_ALT, + KEY_EN_RIGHT_FUNCTION, + KEY_EN_MENU, + KEY_EN_RIGHT_CONTROL, + KEY_EN_LEFT_ARROW, //100 + KEY_EN_DOWN_ARROW, + KEY_EN_RIGHT_ARROW, + KEY_EN_NUMPAD_0, + KEY_EN_NUMPAD_PERIOD, +}; + +/**------------------------------------------------------------------*\ + @name EVision V2 Keyboard + @category Keyboard + @type USB + @save :white_check_mark: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectEVisionV2Keyboard + @comment The Evision V2 controller implements all hardware modes + found in the OEM software. Some options may not be named correctly + like directions for some modes. +\*-------------------------------------------------------------------*/ + +RGBController_EVisionV2Keyboard::RGBController_EVisionV2Keyboard(EVisionV2KeyboardController* controller_ptr, EVisionV2KeyboardPart kb_part) +{ + controller = controller_ptr; + part = kb_part; + + name = controller->GetName(); + vendor = "Evision"; + type = DEVICE_TYPE_KEYBOARD; + description = "EVision Keyboard Device"; + location = controller->GetLocation(); + serial = controller->GetSerial(); + layout = controller->layout; + + switch(part) + { + case EVISION_V2_KEYBOARD_PART_KEYBOARD: + SetupKeyboardModes(); + break; + + case EVISION_V2_KEYBOARD_PART_LOGO: + name += " Logo"; + SetupLogoEdgeModes(); + break; + + case EVISION_V2_KEYBOARD_PART_EDGE: + name += " Edge"; + SetupLogoEdgeModes(); + break; + + case ENDORFY_KEYBOARD_PART_EDGE: + SetupEdgeModes(); + break; + } + + SetupZones(); + + LoadConfig(); + + keepalive_thread_run = false; + keepalive_thread = nullptr; + if(part == EVISION_V2_KEYBOARD_PART_KEYBOARD) + { + keepalive_thread_run = true; + keepalive_thread = new std::thread(&RGBController_EVisionV2Keyboard::KeepaliveThread, this); + } +} + +RGBController_EVisionV2Keyboard::~RGBController_EVisionV2Keyboard() +{ + if(keepalive_thread) + { + keepalive_thread_run = false; + keepalive_thread->join(); + delete keepalive_thread; + } + + delete controller; +} + +void RGBController_EVisionV2Keyboard::SetupKeyboardModes() +{ + mode Direct; + Direct.name = "Direct"; + Direct.value = EVISION_V2_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode ColorWave; + ColorWave.name = "Color Wave short"; + ColorWave.value = EVISION_V2_MODE_COLOR_WAVE_SHORT; + ColorWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + ColorWave.speed_min = EVISION_V2_SPEED_SLOWEST; + ColorWave.speed_max = EVISION_V2_SPEED_FASTEST; + ColorWave.speed = EVISION_V2_SPEED_NORMAL; + ColorWave.colors_min = 1; + ColorWave.colors_max = 1; + ColorWave.color_mode = MODE_COLORS_RANDOM; + ColorWave.colors.resize(1); + ColorWave.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + ColorWave.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + ColorWave.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(ColorWave); + + mode ColorWaveLong; + ColorWaveLong.name = "Color Wave long"; + ColorWaveLong.value = EVISION_V2_MODE_COLOR_WAVE_LONG; + ColorWaveLong.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + ColorWaveLong.speed_min = EVISION_V2_SPEED_SLOWEST; + ColorWaveLong.speed_max = EVISION_V2_SPEED_FASTEST; + ColorWaveLong.speed = EVISION_V2_SPEED_NORMAL; + ColorWaveLong.colors_min = 1; + ColorWaveLong.colors_max = 1; + ColorWaveLong.color_mode = MODE_COLORS_RANDOM; + ColorWaveLong.colors.resize(1); + ColorWaveLong.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + ColorWaveLong.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + ColorWaveLong.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(ColorWaveLong); + + mode ColorWheel; + ColorWheel.name = "Color Wheel"; + ColorWheel.value = EVISION_V2_MODE_COLOR_WHEEL; + ColorWheel.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + ColorWheel.speed_min = EVISION_V2_SPEED_SLOWEST; + ColorWheel.speed_max = EVISION_V2_SPEED_FASTEST; + ColorWheel.speed = EVISION_V2_SPEED_NORMAL; + ColorWheel.colors_min = 1; + ColorWheel.colors_max = 1; + ColorWheel.color_mode = MODE_COLORS_RANDOM; + ColorWheel.colors.resize(1); + ColorWheel.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + ColorWheel.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + ColorWheel.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(ColorWheel); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = EVISION_V2_MODE_SPECTRUM_CYCLE; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + SpectrumCycle.speed_min = EVISION_V2_SPEED_SLOWEST; + SpectrumCycle.speed_max = EVISION_V2_SPEED_FASTEST; + SpectrumCycle.speed = EVISION_V2_SPEED_NORMAL; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + SpectrumCycle.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + SpectrumCycle.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(SpectrumCycle); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = EVISION_V2_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.speed_min = EVISION_V2_SPEED_SLOWEST; + Breathing.speed_max = EVISION_V2_SPEED_FASTEST; + Breathing.speed = EVISION_V2_SPEED_NORMAL; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.color_mode = MODE_COLORS_RANDOM; + Breathing.colors.resize(1); + Breathing.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + Breathing.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + Breathing.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(Breathing); + + mode Static; + Static.name = "Static"; + Static.value = EVISION_V2_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Static.colors_min = 1; + Static.colors_max = 1; + Static.color_mode = MODE_COLORS_RANDOM; + Static.colors.resize(1); + Static.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + Static.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + Static.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(Static); + + mode Reactive; + Reactive.name = "Reactive"; + Reactive.value = EVISION_V2_MODE_REACTIVE; + Reactive.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Reactive.speed_min = EVISION_V2_SPEED_SLOWEST; + Reactive.speed_max = EVISION_V2_SPEED_FASTEST; + Reactive.speed = EVISION_V2_SPEED_NORMAL; + Reactive.colors_min = 1; + Reactive.colors_max = 1; + Reactive.color_mode = MODE_COLORS_RANDOM; + Reactive.colors.resize(1); + Reactive.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + Reactive.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + Reactive.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(Reactive); + + mode ReactiveRipple; + ReactiveRipple.name = "Reactive Ripple"; + ReactiveRipple.value = EVISION_V2_MODE_REACTIVE_RIPPLE; + ReactiveRipple.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + ReactiveRipple.speed_min = EVISION_V2_SPEED_SLOWEST; + ReactiveRipple.speed_max = EVISION_V2_SPEED_FASTEST; + ReactiveRipple.speed = EVISION_V2_SPEED_NORMAL; + ReactiveRipple.colors_min = 1; + ReactiveRipple.colors_max = 1; + ReactiveRipple.color_mode = MODE_COLORS_RANDOM; + ReactiveRipple.colors.resize(1); + ReactiveRipple.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + ReactiveRipple.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + ReactiveRipple.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(ReactiveRipple); + + mode ReactiveLine; + ReactiveLine.name = "Reactive Line"; + ReactiveLine.value = EVISION_V2_MODE_REACTIVE_LINE; + ReactiveLine.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + ReactiveLine.speed_min = EVISION_V2_SPEED_SLOWEST; + ReactiveLine.speed_max = EVISION_V2_SPEED_FASTEST; + ReactiveLine.speed = EVISION_V2_SPEED_NORMAL; + ReactiveLine.colors_min = 1; + ReactiveLine.colors_max = 1; + ReactiveLine.color_mode = MODE_COLORS_RANDOM; + ReactiveLine.colors.resize(1); + ReactiveLine.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + ReactiveLine.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + ReactiveLine.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(ReactiveLine); + + mode Starlight; + Starlight.name = "Starlight"; + Starlight.value = EVISION_V2_MODE_STARLIGHT_FAST; + Starlight.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Starlight.speed_min = EVISION_V2_SPEED_SLOWEST; + Starlight.speed_max = EVISION_V2_SPEED_FASTEST; + Starlight.speed = EVISION_V2_SPEED_NORMAL; + Starlight.colors_min = 1; + Starlight.colors_max = 1; + Starlight.color_mode = MODE_COLORS_RANDOM; + Starlight.colors.resize(1); + Starlight.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + Starlight.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + Starlight.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(Starlight); + + mode Blooming; + Blooming.name = "Blooming"; + Blooming.value = EVISION_V2_MODE_BLOOMING; + Blooming.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Blooming.speed_min = EVISION_V2_SPEED_SLOWEST; + Blooming.speed_max = EVISION_V2_SPEED_FASTEST; + Blooming.speed = EVISION_V2_SPEED_NORMAL; + Blooming.color_mode = MODE_COLORS_NONE; + Blooming.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + Blooming.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + Blooming.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(Blooming); + + mode RainbowWaveVertical; + RainbowWaveVertical.name = "Rainbow Wave vertical"; + RainbowWaveVertical.value = EVISION_V2_MODE_RAINBOW_WAVE_VERTICAL; + RainbowWaveVertical.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + RainbowWaveVertical.speed_min = EVISION_V2_SPEED_SLOWEST; + RainbowWaveVertical.speed_max = EVISION_V2_SPEED_FASTEST; + RainbowWaveVertical.speed = EVISION_V2_SPEED_NORMAL; + RainbowWaveVertical.color_mode = MODE_COLORS_NONE; + RainbowWaveVertical.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + RainbowWaveVertical.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + RainbowWaveVertical.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(RainbowWaveVertical); + + mode Hurricane; + Hurricane.name = "Hurricane"; + Hurricane.value = EVISION_V2_MODE_HURRICANE; + Hurricane.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Hurricane.speed_min = EVISION_V2_SPEED_SLOWEST; + Hurricane.speed_max = EVISION_V2_SPEED_FASTEST; + Hurricane.speed = EVISION_V2_SPEED_NORMAL; + Hurricane.colors_min = 1; + Hurricane.colors_max = 1; + Hurricane.color_mode = MODE_COLORS_RANDOM; + Hurricane.colors.resize(1); + Hurricane.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + Hurricane.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + Hurricane.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(Hurricane); + + mode Accumulate; + Accumulate.name = "Accumulate"; + Accumulate.value = EVISION_V2_MODE_ACCUMULATE; + Accumulate.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Accumulate.speed_min = EVISION_V2_SPEED_SLOWEST; + Accumulate.speed_max = EVISION_V2_SPEED_FASTEST; + Accumulate.speed = EVISION_V2_SPEED_NORMAL; + Accumulate.colors_min = 1; + Accumulate.colors_max = 1; + Accumulate.color_mode = MODE_COLORS_RANDOM; + Accumulate.colors.resize(1); + Accumulate.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + Accumulate.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + Accumulate.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(Accumulate); + + mode StarlightSlow; + StarlightSlow.name = "Starlight slow"; + StarlightSlow.value = EVISION_V2_MODE_STARLIGHT_SLOW; + StarlightSlow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + StarlightSlow.speed_min = EVISION_V2_SPEED_SLOWEST; + StarlightSlow.speed_max = EVISION_V2_SPEED_FASTEST; + StarlightSlow.speed = EVISION_V2_SPEED_NORMAL; + StarlightSlow.colors_min = 1; + StarlightSlow.colors_max = 1; + StarlightSlow.color_mode = MODE_COLORS_RANDOM; + StarlightSlow.colors.resize(1); + StarlightSlow.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + StarlightSlow.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + StarlightSlow.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(StarlightSlow); + + mode Visor; + Visor.name = "Visor"; + Visor.value = EVISION_V2_MODE_VISOR; + Visor.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Visor.speed_min = EVISION_V2_SPEED_SLOWEST; + Visor.speed_max = EVISION_V2_SPEED_FASTEST; + Visor.speed = EVISION_V2_SPEED_NORMAL; + Visor.colors_min = 1; + Visor.colors_max = 1; + Visor.color_mode = MODE_COLORS_RANDOM; + Visor.colors.resize(1); + Visor.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + Visor.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + Visor.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(Visor); + + mode Surmount; + Surmount.name = "Surmount"; + Surmount.value = EVISION_V2_MODE_SURMOUNT; + Surmount.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Surmount.colors_min = 1; + Surmount.colors_max = 1; + Surmount.color_mode = MODE_COLORS_MODE_SPECIFIC; + Surmount.colors.resize(1); + Surmount.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + Surmount.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + Surmount.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(Surmount); + + mode RainbowCircle; + RainbowCircle.name = "Rainbow Circle"; + RainbowCircle.value = EVISION_V2_MODE_RAINBOW_WAVE_CIRCLE; + RainbowCircle.flags = MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + RainbowCircle.color_mode = MODE_COLORS_NONE; + RainbowCircle.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + RainbowCircle.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + RainbowCircle.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(RainbowCircle); + + for(unsigned int i = 0; i < 10; i++) + { + mode Custom; + Custom.name = "Custom "; + Custom.name += std::to_string(i+1); + Custom.value = EVISION_V2_MODE_CUSTOM | i << 8; + Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Custom.color_mode = MODE_COLORS_PER_LED; + Custom.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + Custom.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + Custom.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(Custom); + } +} + +void RGBController_EVisionV2Keyboard::SetupLogoEdgeModes() +{ + mode ColorWave; + ColorWave.name = "Color Wave"; + ColorWave.value = EVISION_V2_MODE2_COLOR_WAVE; + ColorWave.flags = MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + ColorWave.speed_min = EVISION_V2_SPEED_SLOWEST; + ColorWave.speed_max = EVISION_V2_SPEED_FASTEST; + ColorWave.speed = EVISION_V2_SPEED_NORMAL; + ColorWave.colors_min = 1; + ColorWave.colors_max = 1; + ColorWave.color_mode = MODE_COLORS_RANDOM; + ColorWave.colors.resize(1); + ColorWave.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + ColorWave.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + ColorWave.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(ColorWave); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = EVISION_V2_MODE2_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.speed_min = EVISION_V2_SPEED_SLOWEST; + Breathing.speed_max = EVISION_V2_SPEED_FASTEST; + Breathing.speed = EVISION_V2_SPEED_NORMAL; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.color_mode = MODE_COLORS_RANDOM; + Breathing.colors.resize(1); + Breathing.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + Breathing.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + Breathing.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(Breathing); + + mode Yoyo; + Yoyo.name = "Yoyo"; + Yoyo.value = EVISION_V2_MODE2_YOYO; + Yoyo.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Yoyo.speed_min = EVISION_V2_SPEED_SLOWEST; + Yoyo.speed_max = EVISION_V2_SPEED_FASTEST; + Yoyo.speed = EVISION_V2_SPEED_NORMAL; + Yoyo.colors_min = 1; + Yoyo.colors_max = 1; + Yoyo.color_mode = MODE_COLORS_RANDOM; + Yoyo.colors.resize(1); + Yoyo.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + Yoyo.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + Yoyo.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(Yoyo); + + mode Blink; + Blink.name = "Blink"; + Blink.value = EVISION_V2_MODE2_BLINK; + Blink.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Blink.speed_min = EVISION_V2_SPEED_SLOWEST; + Blink.speed_max = EVISION_V2_SPEED_FASTEST; + Blink.speed = EVISION_V2_SPEED_NORMAL; + Blink.colors_min = 1; + Blink.colors_max = 1; + Blink.color_mode = MODE_COLORS_RANDOM; + Blink.colors.resize(1); + Blink.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + Blink.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + Blink.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(Blink); + + mode Static; + Static.name = "Static"; + Static.value = EVISION_V2_MODE2_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Static.colors_min = 1; + Static.colors_max = 1; + Static.color_mode = MODE_COLORS_RANDOM; + Static.colors.resize(1); + Static.brightness_min = EVISION_V2_BRIGHTNESS_LOWEST; + Static.brightness_max = EVISION_V2_BRIGHTNESS_HIGHEST; + Static.brightness = EVISION_V2_BRIGHTNESS_HIGHEST; + modes.push_back(Static); + + mode Off; + Off.name = "Off"; + Off.value = EVISION_V2_MODE2_OFF; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + modes.push_back(Off); +} + +void RGBController_EVisionV2Keyboard::SetupEdgeModes() +{ + mode Freeze; + Freeze.name = "Freeze"; + Freeze.value = ENDORFY_MODE2_FREEZE; + Freeze.flags = MODE_FLAG_AUTOMATIC_SAVE; + modes.push_back(Freeze); + + mode ColorWave; + ColorWave.name = "Color Wave"; + ColorWave.value = ENDORFY_MODE2_COLOR_WAVE; + ColorWave.flags = MODE_FLAG_AUTOMATIC_SAVE; + modes.push_back(ColorWave); + + mode Spectrum; + Spectrum.name = "Spectrum Cycle"; + Spectrum.value = ENDORFY_MODE2_SPECTRUM_CYCLE; + Spectrum.flags = MODE_FLAG_AUTOMATIC_SAVE; + modes.push_back(Spectrum); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = ENDORFY_MODE2_BREATHING; + Breathing.flags = MODE_FLAG_AUTOMATIC_SAVE; + modes.push_back(Breathing); + + mode Static; + Static.name = "Static"; + Static.value = ENDORFY_MODE2_STATIC; + Static.flags = MODE_FLAG_AUTOMATIC_SAVE; + modes.push_back(Static); + + mode Off; + Off.name = "Off"; + Off.value = ENDORFY_MODE2_OFF; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + modes.push_back(Off); +} + +void RGBController_EVisionV2Keyboard::SetupZones() +{ + unsigned short leds_count; + unsigned int *matrix_map; + const char **led_names; + + switch(layout) + { + default: + case EVISION_V2_KEYBOARD_LAYOUT: + led_names = led_evisionv2; + matrix_map = (unsigned int *)evisionv2_matrix; + leds_count = 106; + break; + case ENDORFY_KEYBOARD_LAYOUT: + led_names = led_endorfy; + matrix_map = (unsigned int *)endorfy_matrix; + leds_count = 104; + break; + } + + /*-------------------------------------------------*\ + | Clear any existing color/LED configuration | + \*-------------------------------------------------*/ + zone KB_zone; + KB_zone.name = ZONE_EN_KEYBOARD; + KB_zone.type = ZONE_TYPE_MATRIX; + KB_zone.leds_count = leds_count; + KB_zone.leds_min = KB_zone.leds_count; + KB_zone.leds_max = KB_zone.leds_count; + + KB_zone.matrix_map = new matrix_map_type; + KB_zone.matrix_map->height = EVISION_V2_MATRIX_HEIGHT; + KB_zone.matrix_map->width = EVISION_V2_MATRIX_WIDTH; + KB_zone.matrix_map->map = matrix_map; + zones.push_back(KB_zone); + + /*-------------------------------------------------*\ + | Clear any existing color/LED configuration | + \*-------------------------------------------------*/ + leds.clear(); + colors.clear(); + + /*---------------------------------------------------------*\ + | Set up zones | + \*---------------------------------------------------------*/ + for(std::size_t zone_index = 0; zone_index < zones.size(); zone_index++) + { + for(unsigned int led_index = 0; led_index < zones[zone_index].leds_count; led_index++) + { + led new_led; + new_led.name = led_names[led_index]; + new_led.value = led_index; + leds.push_back(new_led); + } + } + + SetupColors(); +} + +void RGBController_EVisionV2Keyboard::LoadConfig() +{ + EvisionV2ModeConfig config; + + controller->GetMode(part, config); + + int mode = config.mode; + if((part == EVISION_V2_KEYBOARD_PART_KEYBOARD) && (mode == EVISION_V2_MODE_CUSTOM)) + { + mode |= config.ledmode << 8; + } + config.direction = (config.direction == 0) ? 0 : 1; + + // Define default colors + for(int mode_index = 0; mode_index < (int)modes.size(); mode_index++) + { + if(config.random_colours) + { + if(modes[mode_index].flags & MODE_FLAG_HAS_RANDOM_COLOR) + { + modes[mode_index].color_mode = MODE_COLORS_RANDOM; + } + if(modes[mode_index].colors.size() > 0) + { + modes[mode_index].colors[0] = 0xffffff; + } + } + else + { + if(modes[mode_index].flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR) + { + modes[mode_index].color_mode = MODE_COLORS_MODE_SPECIFIC; + } + if(modes[mode_index].colors.size() > 0) + { + modes[mode_index].colors[0] = config.colour; + } + } + if(modes[mode_index].value == mode) + { + modes[mode_index].brightness = config.brightness; + modes[mode_index].speed = config.speed; + if(modes[mode_index].flags & MODE_FLAG_HAS_DIRECTION_LR) + { + modes[mode_index].direction = (1 - config.direction) + MODE_DIRECTION_LEFT; + } + else if(modes[mode_index].flags & MODE_FLAG_HAS_DIRECTION_UD) + { + modes[mode_index].direction = (1 - config.direction) + MODE_DIRECTION_UP; + } + else if(modes[mode_index].flags & MODE_FLAG_HAS_DIRECTION_HV) + { + modes[mode_index].direction = (1 - config.direction) + MODE_DIRECTION_HORIZONTAL; + } + + if(part == EVISION_V2_KEYBOARD_PART_KEYBOARD) + { + if(mode == EVISION_V2_MODE_SURMOUNT) + { + switch(config.ledmode) + { + case EVISION_V2_SURMOUNT_MODE_COLOR_RED: + modes[mode_index].colors[0] = ToRGBColor(0xff, 0, 0); + break; + case EVISION_V2_SURMOUNT_MODE_COLOR_YELLOW: + modes[mode_index].colors[0] = ToRGBColor(0xff, 0xff, 0); + break; + case EVISION_V2_SURMOUNT_MODE_COLOR_GREEN: + modes[mode_index].colors[0] = ToRGBColor(0, 0xff, 0); + break; + case EVISION_V2_SURMOUNT_MODE_COLOR_CYAN: + modes[mode_index].colors[0] = ToRGBColor(0, 0xff, 0xff); + break; + default: + break; + } + } + else if(config.mode == EVISION_V2_MODE_CUSTOM) + { + controller->GetLedsCustom(config.ledmode, colors); + } + } + + active_mode = mode_index; + } + } +} + +void RGBController_EVisionV2Keyboard::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_EVisionV2Keyboard::DeviceUpdateLEDs() +{ + if(part != EVISION_V2_KEYBOARD_PART_KEYBOARD) + { + return; + } + + controller->SetLedsDirect(colors); + has_color_set = true; + last_update_time = std::chrono::steady_clock::now(); +} + +void RGBController_EVisionV2Keyboard::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_EVisionV2Keyboard::UpdateSingleLED(int led) +{ + if(part != EVISION_V2_KEYBOARD_PART_KEYBOARD) + { + return; + } + + controller->SetLedDirect(led, colors[led]); + has_color_set = true; + last_update_time = std::chrono::steady_clock::now(); +} + +void RGBController_EVisionV2Keyboard::DeviceUpdateMode() +{ + mode set_mode = modes[active_mode]; + + // No mode set packets required for Direct mode + if((part == EVISION_V2_KEYBOARD_PART_KEYBOARD) && (set_mode.value == EVISION_V2_MODE_DIRECT)) + { + return; + } + + EvisionV2ModeConfig config; + + config.mode = set_mode.value & 0xff; + config.brightness = set_mode.brightness; + config.speed = set_mode.speed; + config.direction = 1 - (set_mode.direction & 0x1); + config.random_colours = (set_mode.color_mode == MODE_COLORS_RANDOM); + config.colour = 0; + if(modes[active_mode].colors.size() > 0) + { + config.colour = set_mode.colors[0]; + } + + config.ledmode = 0; + if(part == EVISION_V2_KEYBOARD_PART_KEYBOARD) + { + if(config.mode == EVISION_V2_MODE_SURMOUNT) + { + hsv_t temp; + rgb2hsv(config.colour, &temp); + + if(temp.hue <= 30 || temp.hue > 300) + { + config.ledmode = EVISION_V2_SURMOUNT_MODE_COLOR_RED; + } + else if(temp.hue > 30 && temp.hue <= 90) + { + config.ledmode = EVISION_V2_SURMOUNT_MODE_COLOR_YELLOW; + } + else if(temp.hue > 90 && temp.hue <= 150) + { + config.ledmode = EVISION_V2_SURMOUNT_MODE_COLOR_GREEN; + } + else if(temp.hue > 150 && temp.hue <= 300) + { + config.ledmode = EVISION_V2_SURMOUNT_MODE_COLOR_CYAN; + } + } + else if(config.mode == EVISION_V2_MODE_CUSTOM) + { + config.ledmode = (set_mode.value >> 8) & 0xff; + } + } + + controller->SetMode(part, config); + + if((part == EVISION_V2_KEYBOARD_PART_KEYBOARD) && (config.mode == EVISION_V2_MODE_CUSTOM)) + { + controller->GetLedsCustom(config.ledmode, colors); + SignalUpdate(); + } +} + +void RGBController_EVisionV2Keyboard::DeviceSaveMode() +{ + if(part != EVISION_V2_KEYBOARD_PART_KEYBOARD) + { + return; + } + int value = modes[active_mode].value; + if((value & 0xff) == EVISION_V2_MODE_CUSTOM) + { + controller->SetLedsCustom((value >> 8) & 0xff, colors); + } +} + +void RGBController_EVisionV2Keyboard::KeepaliveThread() +{ + bool was_active = false; + while(keepalive_thread_run.load()) + { + if(modes[active_mode].value == EVISION_V2_MODE_DIRECT && has_color_set) + { + if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(200)) + { + controller->RefreshLedDirect(); + last_update_time = std::chrono::steady_clock::now(); + was_active = true; + } + } + else if(was_active) + { + controller->EndLedsDirect(); + was_active = false; + } + std::this_thread::sleep_for(100ms); + } + controller->EndLedsDirect(); +} diff --git a/Controllers/EVisionKeyboardController/RGBController_EVisionV2Keyboard.h b/Controllers/EVisionKeyboardController/RGBController_EVisionV2Keyboard.h new file mode 100644 index 00000000..c177b7b4 --- /dev/null +++ b/Controllers/EVisionKeyboardController/RGBController_EVisionV2Keyboard.h @@ -0,0 +1,51 @@ +/*---------------------------------------------------------*\ +| RGBController_EVisionV2Keyboard.h | +| | +| RGBController for EVision V2 keyboard | +| | +| Le Philousophe 25 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "LogManager.h" +#include "RGBController.h" +#include "EVisionV2KeyboardController.h" + +class RGBController_EVisionV2Keyboard : public RGBController +{ +public: + RGBController_EVisionV2Keyboard(EVisionV2KeyboardController* controller_ptr, EVisionV2KeyboardPart kb_part); + ~RGBController_EVisionV2Keyboard(); + + void SetupZones() override; + void ResizeZone(int zone, int new_size) override; + + void DeviceUpdateLEDs() override; + void UpdateZoneLEDs(int zone) override; + void UpdateSingleLED(int led) override; + + void DeviceUpdateMode() override; + void DeviceSaveMode() override; + +private: + void SetupKeyboardModes(); + void SetupLogoEdgeModes(); + void SetupEdgeModes(); + void LoadConfig(); + + void KeepaliveThread(); + + EVisionV2KeyboardController* controller; + EVisionV2KeyboardPart part; + EVisionV2KeyboardLayout layout; + + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::atomic has_color_set; + std::chrono::time_point last_update_time; +}; diff --git a/Controllers/ElgatoKeyLightController/ElgatoKeyLightController.cpp b/Controllers/ElgatoKeyLightController/ElgatoKeyLightController.cpp index 3d687590..bb5e137b 100644 --- a/Controllers/ElgatoKeyLightController/ElgatoKeyLightController.cpp +++ b/Controllers/ElgatoKeyLightController/ElgatoKeyLightController.cpp @@ -1,12 +1,17 @@ /*---------------------------------------------------------*\ -| Driver for Elgato Key Light | +| ElgatoKeyLightController.cpp | | | -| Monks (imtherealestmonkey@gmail.com), 11/03/2021 | +| Driver for Elgato Key Light | +| | +| Monks (imtherealestmonkey@gmail.com), 03 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "ElgatoKeyLightController.h" -#include "json.hpp" #include +#include "ElgatoKeyLightController.h" +#include using json = nlohmann::json; @@ -59,7 +64,7 @@ void ElgatoKeyLightController::SetColor(hsv_t hsv_color) port.tcp_client_connect(); std::string buf = GetRequest(hsv_color.value, k_value); - port.tcp_client_write((char *)buf.c_str(), buf.length() + 1); + port.tcp_client_write((char *)buf.c_str(), (int)buf.length() + 1); port.tcp_close(); } diff --git a/Controllers/ElgatoKeyLightController/ElgatoKeyLightController.h b/Controllers/ElgatoKeyLightController/ElgatoKeyLightController.h index 3f00168b..ef1b5827 100644 --- a/Controllers/ElgatoKeyLightController/ElgatoKeyLightController.h +++ b/Controllers/ElgatoKeyLightController/ElgatoKeyLightController.h @@ -1,19 +1,23 @@ /*---------------------------------------------------------*\ -| Definitions for Elgato Key Light | +| ElgatoKeyLightController.h | | | -| Monks (imtherealestmonkey@gmail.com), 11/11/2021 | +| Driver for Elgato Key Light | +| | +| Monks (imtherealestmonkey@gmail.com), 11 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "RGBController.h" -#include "net_port.h" -#include "hsv.h" +#pragma once #include #include #include #include - -#pragma once +#include "RGBController.h" +#include "net_port.h" +#include "hsv.h" class ElgatoKeyLightController { diff --git a/Controllers/ElgatoKeyLightController/ElgatoKeyLightControllerDetect.cpp b/Controllers/ElgatoKeyLightController/ElgatoKeyLightControllerDetect.cpp index a68605c5..52b783a3 100644 --- a/Controllers/ElgatoKeyLightController/ElgatoKeyLightControllerDetect.cpp +++ b/Controllers/ElgatoKeyLightController/ElgatoKeyLightControllerDetect.cpp @@ -1,11 +1,16 @@ +/*---------------------------------------------------------*\ +| ElgatoKeyLightControllerDetect.cpp | +| | +| Detector for Elgato Key Light | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "ElgatoKeyLightController.h" -#include "RGBController.h" #include "RGBController_ElgatoKeyLight.h" #include "SettingsManager.h" -#include -#include -#include /******************************************************************************************\ * * diff --git a/Controllers/ElgatoKeyLightController/RGBController_ElgatoKeyLight.cpp b/Controllers/ElgatoKeyLightController/RGBController_ElgatoKeyLight.cpp index 17531b7d..901a9f49 100644 --- a/Controllers/ElgatoKeyLightController/RGBController_ElgatoKeyLight.cpp +++ b/Controllers/ElgatoKeyLightController/RGBController_ElgatoKeyLight.cpp @@ -1,10 +1,13 @@ -/*------------------------------------------------*\ -| RGBController_ElgatoKeyLight.cpp | -| | -| Generic RGB Interface for ElgatoKeyLight | -| | -| Monks (@iamtherealestmonkey) 11/03/2021 | -\*------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ElgatoKeyLight.cpp | +| | +| RGBController for Elgato Key Light | +| | +| Monks (@iamtherealestmonkey) 03 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_ElgatoKeyLight.h" #include "hsv.h" diff --git a/Controllers/ElgatoKeyLightController/RGBController_ElgatoKeyLight.h b/Controllers/ElgatoKeyLightController/RGBController_ElgatoKeyLight.h index 86641f09..6658cf1e 100644 --- a/Controllers/ElgatoKeyLightController/RGBController_ElgatoKeyLight.h +++ b/Controllers/ElgatoKeyLightController/RGBController_ElgatoKeyLight.h @@ -1,12 +1,16 @@ -/*--------------------------------------------------*\ -| RGBController_ElgatoKeyLight.h | -| | -| Generic RGB Interface for Elgato KeyLight | -| | -| Monks (imtherealestmonkey@gmail.com) 11/1/2021 | -\*--------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ElgatoKeyLight.h | +| | +| RGBController for Elgato Key Light | +| | +| Monks (@iamtherealestmonkey) 01 Nov 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "ElgatoKeyLightController.h" diff --git a/Controllers/ElgatoLightStripController/ElgatoLightStripController.cpp b/Controllers/ElgatoLightStripController/ElgatoLightStripController.cpp new file mode 100644 index 00000000..a5a41ee1 --- /dev/null +++ b/Controllers/ElgatoLightStripController/ElgatoLightStripController.cpp @@ -0,0 +1,159 @@ +/*---------------------------------------------------------*\ +| ElgatoLightStripController.cpp | +| | +| Driver for Elgato Light Strip | +| | +| Monks (@iamtherealestmonkey) 03 Nov 2021 | +| DomePlaysHD 14 Mar 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include "ElgatoLightStripController.h" +#include +#include "LogManager.h" + +using json = nlohmann::json; +using namespace std::chrono_literals; + +ElgatoLightStripController::ElgatoLightStripController(std::string ip) +{ + /*-----------------------------------------------------------------*\ + | Fill in location string with device's IP address | + \*-----------------------------------------------------------------*/ + location = "IP: " + ip; + + /*-----------------------------------------------------------------*\ + | Open a TCP client sending to the device's IP, port 9123 | + \*-----------------------------------------------------------------*/ + port.tcp_client(ip.c_str(), "9123"); + + /*-----------------------------------------------------------*\ + | Handle responses received from the Elgato LightStrip device | + \*-----------------------------------------------------------*/ + port.tcp_client_connect(); + std::string buf = "GET /elgato/accessory-info HTTP/1.1\r\nContent-Type: application/json\r\nConnection: close\r\n\r\n"; + port.tcp_client_write((char *)buf.c_str(), (int)buf.length() + 1); + + char recv_buf[1024]; + int size = port.tcp_listen(recv_buf, sizeof(recv_buf)); + port.tcp_close(); + + if(size > 0) + { + /*-----------------------------------------------------------*\ + | Get response body | + \*-----------------------------------------------------------*/ + std::istringstream recv_stream(recv_buf); + std::vector recv_list; + std::string current_line; + + while(std::getline(recv_stream, current_line, '\n')) + { + recv_list.push_back(current_line); + } + + std::string result = recv_list[5]; + json elgato_lightstrip_data = json::parse(result); + + firmware_version = elgato_lightstrip_data["firmwareVersion"]; + serialnumber = elgato_lightstrip_data["serialNumber"]; + displayname = elgato_lightstrip_data["displayName"]; + + LOG_DEBUG("[ElgatoLightStrip] [%s]", result.data()); + } +} + +ElgatoLightStripController::~ElgatoLightStripController() +{ +} + +std::string ElgatoLightStripController::GetLocation() +{ + return(location); +} + +std::string ElgatoLightStripController::GetName() +{ + return(displayname); +} + +std::string ElgatoLightStripController::GetVersion() +{ + return(firmware_version); +} + +std::string ElgatoLightStripController::GetManufacturer() +{ + return("Elgato"); +} + +std::string ElgatoLightStripController::GetUniqueID() +{ + return(serialnumber); +} + +void ElgatoLightStripController::SetColor(hsv_t hsv_color) +{ + if(hsv_color.hue > 360) + { + hsv_color.hue = 360; + } + + if(hsv_color.saturation > 100) + { + hsv_color.saturation = 100; + } + + /*-------------------------------------------------*\ + | Delay to prevent it from getting stuck on effects | + \*-------------------------------------------------*/ + std::this_thread::sleep_for(std::chrono::milliseconds(150)); + + port.tcp_client_connect(); + std::string buf = GetRequest(hsv_color.hue, hsv_color.saturation, GetBrightness()); + port.tcp_client_write((char *)buf.c_str(), (int)buf.length() + 1); + port.tcp_close(); +} + +std::string ElgatoLightStripController::GetRequest(int hue, int saturation, int brightness) +{ + json command; + + command["numberOfLights"] = 1; + + json lights = json::array(); + lights.push_back(json::object({ {"on", 1}, {"hue", hue}, {"saturation", saturation}, {"brightness", brightness}})); + command["lights"] = lights; + + std::string command_str = command.dump(); + std::string buf = "PUT /elgato/lights HTTP/1.1\r\nContent-Type: application/json\r\nContent-Length: " + + std::to_string(command_str.length()) + + "\r\nConnection: close\r\n\r\n" + command_str + "\r\n\r\n"; + + return(buf); +} + +int ElgatoLightStripController::GetBrightness() +{ + if(device_brightness > 100 || device_brightness < 0) + { + device_brightness = 100; + } + + return device_brightness; +} + +void ElgatoLightStripController::SetBrightness(int brightness) +{ + if(brightness > 100 || device_brightness < 0) + { + brightness = 100; + } + + device_brightness = brightness; +} diff --git a/Controllers/ElgatoLightStripController/ElgatoLightStripController.h b/Controllers/ElgatoLightStripController/ElgatoLightStripController.h new file mode 100644 index 00000000..d0dc5566 --- /dev/null +++ b/Controllers/ElgatoLightStripController/ElgatoLightStripController.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------*\ +| ElgatoLightStripController.h | +| | +| Driver for Elgato Light Strip | +| | +| Monks (@iamtherealestmonkey) 03 Nov 2021 | +| DomePlaysHD 12 Mar 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "net_port.h" +#include "hsv.h" + +class ElgatoLightStripController +{ + public: + ElgatoLightStripController(std::string ip); + ~ElgatoLightStripController(); + + std::string GetLocation(); + std::string GetName(); + std::string GetVersion(); + std::string GetManufacturer(); + std::string GetUniqueID(); + + void SetColor(hsv_t hsv_color); + int GetBrightness(); + void SetBrightness(int brightness); + + private: + std::string GetRequest(int hue, int saturation, int brightness); + std::string location; + std::string firmware_version; + std::string serialnumber; + std::string displayname; + net_port port; + int device_brightness; +}; diff --git a/Controllers/ElgatoLightStripController/ElgatoLightStripControllerDetect.cpp b/Controllers/ElgatoLightStripController/ElgatoLightStripControllerDetect.cpp new file mode 100644 index 00000000..45830486 --- /dev/null +++ b/Controllers/ElgatoLightStripController/ElgatoLightStripControllerDetect.cpp @@ -0,0 +1,50 @@ +/*---------------------------------------------------------*\ +| ElgatoLightStripControllerDetect.cpp | +| | +| Detector for Elgato Light Strip | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "ElgatoLightStripController.h" +#include "RGBController_ElgatoLightStrip.h" +#include "SettingsManager.h" + +/******************************************************************************************\ +* * +* Detect Elgato LightStrip devices * +* * +\******************************************************************************************/ + +void DetectElgatoLightStripControllers() +{ + json elgato_lightstrip_settings; + + /*-------------------------------------------------*\ + | Get LightStrip settings from settings manager | + \*-------------------------------------------------*/ + elgato_lightstrip_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("ElgatoLightStripDevices"); + + /*------------------------------------------------------------*\ + | If the Elgato Light Strip settings contains devices, process | + \*------------------------------------------------------------*/ + if(elgato_lightstrip_settings.contains("devices")) + { + for(unsigned int device_idx = 0; device_idx < elgato_lightstrip_settings["devices"].size(); device_idx++) + { + if(elgato_lightstrip_settings["devices"][device_idx].contains("ip")) + { + std::string elgato_lightstrip_ip = elgato_lightstrip_settings["devices"][device_idx]["ip"]; + + ElgatoLightStripController* controller = new ElgatoLightStripController(elgato_lightstrip_ip); + RGBController_ElgatoLightStrip* rgb_controller = new RGBController_ElgatoLightStrip(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + } + } +} + +REGISTER_DETECTOR("Elgato Light Strip", DetectElgatoLightStripControllers); diff --git a/Controllers/ElgatoLightStripController/RGBController_ElgatoLightStrip.cpp b/Controllers/ElgatoLightStripController/RGBController_ElgatoLightStrip.cpp new file mode 100644 index 00000000..67b5347d --- /dev/null +++ b/Controllers/ElgatoLightStripController/RGBController_ElgatoLightStrip.cpp @@ -0,0 +1,93 @@ +/*---------------------------------------------------------*\ +| RGBController_ElgatoLightStrip.cpp | +| | +| RGBController for Elgato Light Strip | +| | +| Monks (@iamtherealestmonkey) 03 Nov 2021 | +| DomePlaysHD 12 Mar 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_ElgatoLightStrip.h" +#include "hsv.h" + +RGBController_ElgatoLightStrip::RGBController_ElgatoLightStrip(ElgatoLightStripController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = controller->GetManufacturer(); + type = DEVICE_TYPE_LEDSTRIP; + version = controller->GetVersion(); + description = "Elgato LightStrip Device"; + serial = controller->GetUniqueID(); + location = controller->GetLocation(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = 0; + Direct.brightness_max = 100; + Direct.brightness = 100; + modes.push_back(Direct); + + SetupZones(); +} + +RGBController_ElgatoLightStrip::~RGBController_ElgatoLightStrip() +{ + delete controller; +} + +void RGBController_ElgatoLightStrip::SetupZones() +{ + zone led_zone; + led_zone.name = "Lightstrip"; + 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 = "Lightstrip"; + leds.push_back(new_led); + + SetupColors(); +} + +void RGBController_ElgatoLightStrip::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_ElgatoLightStrip::DeviceUpdateLEDs() +{ + RGBColor rgb_color = colors[0]; + hsv_t hsv_color; + rgb2hsv(rgb_color, &hsv_color); + controller->SetColor(hsv_color); + controller->SetBrightness((unsigned char)modes[(unsigned int)active_mode].brightness); +} + +void RGBController_ElgatoLightStrip::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_ElgatoLightStrip::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_ElgatoLightStrip::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} diff --git a/Controllers/ElgatoLightStripController/RGBController_ElgatoLightStrip.h b/Controllers/ElgatoLightStripController/RGBController_ElgatoLightStrip.h new file mode 100644 index 00000000..ed959eb0 --- /dev/null +++ b/Controllers/ElgatoLightStripController/RGBController_ElgatoLightStrip.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_ElgatoLightStrip.h | +| | +| RGBController for Elgato Light Strip | +| | +| Monks (@iamtherealestmonkey) 01 Nov 2021 | +| DomePlaysHD 12 Mar 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "ElgatoLightStripController.h" + +class RGBController_ElgatoLightStrip : public RGBController +{ + public: + RGBController_ElgatoLightStrip(ElgatoLightStripController* controller_ptr); + ~RGBController_ElgatoLightStrip(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + private: + ElgatoLightStripController* controller; +}; diff --git a/Controllers/EpomakerController/EpomakerController.cpp b/Controllers/EpomakerController/EpomakerController.cpp index 54de1f54..35295c49 100644 --- a/Controllers/EpomakerController/EpomakerController.cpp +++ b/Controllers/EpomakerController/EpomakerController.cpp @@ -1,42 +1,40 @@ -/*-------------------------------------------------------------------*\ -| EpomakerController.cpp | -| | -| Driver for Epomaker Keyboard | -| | -| Alvaro Munoz (alvaromunoz) 2023-06-05 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| EpomakerController.cpp | +| | +| Driver for Epomaker keyboard | +| | +| Alvaro Munoz (alvaromunoz) 05 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "EpomakerController.h" #include +#include "EpomakerController.h" +#include "LogManager.h" +#include "StringUtils.h" EpomakerController::EpomakerController(hid_device* dev_handle, char *_path) { - const int szTemp = 256; - wchar_t tmpName[szTemp]; + dev = dev_handle; + location = _path; - dev = dev_handle; + /*---------------------------------------------------------*\ + | Get device name from HID manufacturer and product strings | + \*---------------------------------------------------------*/ + wchar_t name_string[HID_MAX_STR]; - hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - device_name = std::string(wName.begin(), wName.end()); + hid_get_manufacturer_string(dev, name_string, HID_MAX_STR); + device_name = StringUtils::wstring_to_string(name_string); - hid_get_product_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); - - hid_get_serial_number_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - serial = std::string(wName.begin(), wName.end()); - - location = _path; - - current_mode = Epomaker_MODE_ALWAYS_ON; - current_speed = Epomaker_SPEED_DEFAULT; - current_brightness = Epomaker_BRIGHTNESS_DEFAULT; - current_dazzle = Epomaker_OPTION_DAZZLE_OFF; - current_option = Epomaker_OPTION_DEFAULT; + hid_get_product_string(dev, name_string, HID_MAX_STR); + device_name.append(" ").append(StringUtils::wstring_to_string(name_string)); + current_mode = EPOMAKER_MODE_ALWAYS_ON; + current_speed = EPOMAKER_SPEED_DEFAULT; + current_brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + current_dazzle = EPOMAKER_OPTION_DAZZLE_OFF; + current_option = EPOMAKER_OPTION_DEFAULT; } EpomakerController::~EpomakerController() @@ -46,17 +44,25 @@ EpomakerController::~EpomakerController() std::string EpomakerController::GetDeviceName() { - return (device_name); + return(device_name); } std::string EpomakerController::GetSerial() { - return (serial); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } std::string EpomakerController::GetLocation() { - return ("HID: " + location); + return("HID: " + location); } void EpomakerController::SetMode(unsigned char mode, unsigned char speed, unsigned char brightness) @@ -81,11 +87,11 @@ void EpomakerController::SetDazzle(bool is_dazzle) { if(is_dazzle) { - current_dazzle = Epomaker_OPTION_DAZZLE_ON; + current_dazzle = EPOMAKER_OPTION_DAZZLE_ON; } else { - current_dazzle = Epomaker_OPTION_DAZZLE_OFF; + current_dazzle = EPOMAKER_OPTION_DAZZLE_OFF; } } @@ -96,33 +102,32 @@ void EpomakerController::SetOption(unsigned char option) void EpomakerController::SendUpdate() { - unsigned char command[Epomaker_PACKET_LENGTH] = { 0x00 }; - command[0] = 0xf6; - command[1] = 0x0a; + unsigned char buffer[EPOMAKER_PACKET_LENGTH + 1] = { 0x00 }; - unsigned char buffer[Epomaker_PACKET_LENGTH] = { 0x00 }; - int buffer_size = (sizeof(buffer) / sizeof(buffer[0])); - - buffer[Epomaker_BYTE_COMMAND] = Epomaker_COMMAND_RGB; - buffer[Epomaker_BYTE_MODE] = current_mode; - buffer[Epomaker_BYTE_SPEED] = current_speed; - buffer[Epomaker_BYTE_BRIGHTNESS] = current_brightness; - buffer[Epomaker_BYTE_FLAGS] = current_option | current_dazzle; - buffer[Epomaker_BYTE_RED] = current_red; - buffer[Epomaker_BYTE_GREEN] = current_green; - buffer[Epomaker_BYTE_BLUE] = current_blue; + buffer[EPOMAKER_BYTE_COMMAND] = EPOMAKER_COMMAND_RGB; + buffer[EPOMAKER_BYTE_MODE] = current_mode; + buffer[EPOMAKER_BYTE_SPEED] = current_speed; + buffer[EPOMAKER_BYTE_BRIGHTNESS] = current_brightness; + buffer[EPOMAKER_BYTE_FLAGS] = current_option | current_dazzle; + buffer[EPOMAKER_BYTE_RED] = current_red; + buffer[EPOMAKER_BYTE_GREEN] = current_green; + buffer[EPOMAKER_BYTE_BLUE] = current_blue; int sum_bits = 0; - for (int i=Epomaker_BYTE_COMMAND; i<=Epomaker_BYTE_BLUE; i++) + for(int i = EPOMAKER_BYTE_COMMAND; i <= EPOMAKER_BYTE_BLUE; i++) { sum_bits += buffer[i]; } - int next_pow2 = pow(2, ceil(log2(sum_bits))); + int next_pow2 = (int)(pow(2, ceil(log2((double)(sum_bits))))); int filler = next_pow2 - sum_bits - 1; - buffer[Epomaker_BYTE_FILLER] = filler; + buffer[EPOMAKER_BYTE_FILLER] = filler; + + int send_buffer_result = hid_send_feature_report(dev, buffer, (sizeof(buffer) / sizeof(buffer[0]))); + if(send_buffer_result<0) + { + LOG_ERROR("[EPOMAKER]: Send Buffer Error. HIDAPI Error: %ls", hid_error(dev)); + } - hid_send_feature_report(dev, command, buffer_size); - hid_send_feature_report(dev, buffer, buffer_size); } diff --git a/Controllers/EpomakerController/EpomakerController.h b/Controllers/EpomakerController/EpomakerController.h index 3e5b6192..3f070434 100644 --- a/Controllers/EpomakerController/EpomakerController.h +++ b/Controllers/EpomakerController/EpomakerController.h @@ -1,91 +1,93 @@ -/*-------------------------------------------------------------------*\ -| EpomakerController.h | -| | -| Driver for Epomaker Keyboard | -| | -| Alvaro Munoz (alvaromunoz) 2023-06-05 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| EpomakerController.h | +| | +| Driver for Epomaker keyboard | +| | +| Alvaro Munoz (alvaromunoz) 05 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#ifndef EpomakerCONTROLLER_H -#define EpomakerCONTROLLER_H +#pragma once #include -#include +#include -#define Epomaker_PACKET_LENGTH 0x40 -#define Epomaker_COMMAND_RGB 0x07 -#define Epomaker_COMMAND_SET 0xf60a -#define Epomaker_COMMAND_PING 0xf7 +#define EPOMAKER_PACKET_LENGTH 0x40 +#define EPOMAKER_COMMAND_RGB 0x07 +#define EPOMAKER_COMMAND_SET 0xF60A +#define EPOMAKER_COMMAND_PING 0xF7 +#define HID_MAX_STR 255 enum { - Epomaker_BYTE_COMMAND = 0, - Epomaker_BYTE_MODE = 1, - Epomaker_BYTE_SPEED = 2, - Epomaker_BYTE_BRIGHTNESS = 3, - Epomaker_BYTE_FLAGS = 4, - Epomaker_BYTE_RED = 5, - Epomaker_BYTE_GREEN = 6, - Epomaker_BYTE_BLUE = 7, - Epomaker_BYTE_FILLER = 8 + EPOMAKER_BYTE_COMMAND = 1, + EPOMAKER_BYTE_MODE = 2, + EPOMAKER_BYTE_SPEED = 3, + EPOMAKER_BYTE_BRIGHTNESS = 4, + EPOMAKER_BYTE_FLAGS = 5, + EPOMAKER_BYTE_RED = 6, + EPOMAKER_BYTE_GREEN = 7, + EPOMAKER_BYTE_BLUE = 8, + EPOMAKER_BYTE_FILLER = 9 }; enum { - Epomaker_MODE_ALWAYS_ON = 0x01, - Epomaker_MODE_DYNAMIC_BREATHING = 0x02, - Epomaker_MODE_SPECTRUM_CYCLE = 0x03, - Epomaker_MODE_DRIFT = 0x04, - Epomaker_MODE_WAVES_RIPPLE = 0x05, - Epomaker_MODE_STARS_TWINKLE = 0x06, - Epomaker_MODE_STEADY_STREAM = 0x07, - Epomaker_MODE_SHADOWING = 0x08, - Epomaker_MODE_PEAKS_RISING_ONE_AFTER_ANOTHER = 0x09, - Epomaker_MODE_SINE_WAVE = 0x0a, - Epomaker_MODE_CAISPRING_SURGING = 0x0b, - Epomaker_MODE_FLOWERS_BLOOMING = 0x0c, - Epomaker_MODE_LASER = 0x0e, - Epomaker_MODE_PEAK_TURN = 0x0f, - Epomaker_MODE_INCLINED_RAIN = 0x10, - Epomaker_MODE_SNOW = 0x11, - Epomaker_MODE_METEOR = 0x12, - Epomaker_MODE_THROUGH_THE_SNOW_NON_TRACE = 0x13, - Epomaker_MODE_LIGHT_SHADOW = 0x15 + EPOMAKER_MODE_ALWAYS_ON = 0x01, + EPOMAKER_MODE_DYNAMIC_BREATHING = 0x02, + EPOMAKER_MODE_SPECTRUM_CYCLE = 0x03, + EPOMAKER_MODE_DRIFT = 0x04, + EPOMAKER_MODE_WAVES_RIPPLE = 0x05, + EPOMAKER_MODE_STARS_TWINKLE = 0x06, + EPOMAKER_MODE_STEADY_STREAM = 0x07, + EPOMAKER_MODE_SHADOWING = 0x08, + EPOMAKER_MODE_PEAKS_RISING_ONE_AFTER_ANOTHER = 0x09, + EPOMAKER_MODE_SINE_WAVE = 0x0a, + EPOMAKER_MODE_CAISPRING_SURGING = 0x0b, + EPOMAKER_MODE_FLOWERS_BLOOMING = 0x0c, + EPOMAKER_MODE_LASER = 0x0e, + EPOMAKER_MODE_PEAK_TURN = 0x0f, + EPOMAKER_MODE_INCLINED_RAIN = 0x10, + EPOMAKER_MODE_SNOW = 0x11, + EPOMAKER_MODE_METEOR = 0x12, + EPOMAKER_MODE_THROUGH_THE_SNOW_NON_TRACE = 0x13, + EPOMAKER_MODE_LIGHT_SHADOW = 0x15 }; enum { - Epomaker_SPEED_MIN = 0x00, - Epomaker_SPEED_MAX = 0x05, - Epomaker_SPEED_MAX_SPECIAL = 0x04, - Epomaker_SPEED_DEFAULT = 0x04 + EPOMAKER_SPEED_MIN = 0x00, + EPOMAKER_SPEED_MAX = 0x05, + EPOMAKER_SPEED_MAX_SPECIAL = 0x04, + EPOMAKER_SPEED_DEFAULT = 0x04 }; enum { - Epomaker_BRIGHTNESS_MIN = 0x00, - Epomaker_BRIGHTNESS_MAX = 0x04, - Epomaker_BRIGHTNESS_DEFAULT = 0x04 + EPOMAKER_BRIGHTNESS_MIN = 0x00, + EPOMAKER_BRIGHTNESS_MAX = 0x04, + EPOMAKER_BRIGHTNESS_DEFAULT = 0x04 }; enum { - Epomaker_OPTION_DAZZLE_OFF = 0x07, - Epomaker_OPTION_DAZZLE_ON = 0x08, - Epomaker_OPTION_DEFAULT = 0x00, - Epomaker_OPTION_DRIFT_RIGHT = 0X00, - Epomaker_OPTION_DRIFT_LEFT = 0X10, - Epomaker_OPTION_DRIFT_DOWN = 0X20, - Epomaker_OPTION_DRIFT_UP = 0X30, - Epomaker_OPTION_STEADY_STREAM_ZIG_ZAG = 0x00, - Epomaker_OPTION_STEADY_STREAM_RETURN = 0x10, - Epomaker_OPTION_CAISPRING_SURGING_OUT = 0x00, - Epomaker_OPTION_CAISPRING_SURGING_IN = 0x10, - Epomaker_OPTION_FLOWERS_BLOOMING_RIGHT = 0x00, - Epomaker_OPTION_FLOWERS_BLOOMING_LEFT = 0x10, - Epomaker_OPTION_PEAK_TURN_ANTI_CLOCKWISE = 0x00, - Epomaker_OPTION_PEAK_TURN_CLOCKWISE = 0x10, + EPOMAKER_OPTION_DAZZLE_OFF = 0x07, + EPOMAKER_OPTION_DAZZLE_ON = 0x08, + EPOMAKER_OPTION_DEFAULT = 0x00, + EPOMAKER_OPTION_DRIFT_RIGHT = 0X00, + EPOMAKER_OPTION_DRIFT_LEFT = 0X10, + EPOMAKER_OPTION_DRIFT_DOWN = 0X20, + EPOMAKER_OPTION_DRIFT_UP = 0X30, + EPOMAKER_OPTION_STEADY_STREAM_ZIG_ZAG = 0x00, + EPOMAKER_OPTION_STEADY_STREAM_RETURN = 0x10, + EPOMAKER_OPTION_CAISPRING_SURGING_OUT = 0x00, + EPOMAKER_OPTION_CAISPRING_SURGING_IN = 0x10, + EPOMAKER_OPTION_FLOWERS_BLOOMING_RIGHT = 0x00, + EPOMAKER_OPTION_FLOWERS_BLOOMING_LEFT = 0x10, + EPOMAKER_OPTION_PEAK_TURN_ANTI_CLOCKWISE = 0x00, + EPOMAKER_OPTION_PEAK_TURN_CLOCKWISE = 0x10, }; class EpomakerController @@ -106,7 +108,6 @@ public: private: std::string device_name; - std::string serial; std::string location; hid_device* dev; @@ -122,5 +123,3 @@ private: void SendUpdate(); }; - -#endif // EpomakerCONTROLLER_H diff --git a/Controllers/EpomakerController/EpomakerControllerDetect.cpp b/Controllers/EpomakerController/EpomakerControllerDetect.cpp index b9a11e56..378390fc 100644 --- a/Controllers/EpomakerController/EpomakerControllerDetect.cpp +++ b/Controllers/EpomakerController/EpomakerControllerDetect.cpp @@ -1,13 +1,25 @@ +/*---------------------------------------------------------*\ +| EpomakerControllerDetect.cpp | +| | +| Detector for Epomaker keyboard | +| | +| Alvaro Munoz (alvaromunoz) 05 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "EpomakerController.h" -#include "RGBController.h" #include "RGBController_EpomakerController.h" -#include -#define Epomaker_VID 0x3151 -#define Epomaker_TH80_Pro_USB_PID 0x4010 -#define Epomaker_TH80_Pro_Dongle_PID 0x4011 -#define Epomaker_TH80_Pro_BT_PID 0x4013 +#define EPOMAKER_VID 0x3151 +#define EPOMAKER_TH80_Pro_USB_PID 0x4010 +#define ATTACKSHARK_K86_USB_PID 0x4015 +#define EPOMAKER_TH80_Pro_Dongle_PID 0x4011 /* Attack shark's Dongle is the same. */ +#define EPOMAKER_TH80_Pro_BT_PID 0x4013 +#define ATTACKSHARK_K86_BT_PID 0x4012 /******************************************************************************************\ * * @@ -30,10 +42,12 @@ void DetectEpomakerControllers(hid_device_info* info, const std::string&) } } /* DetectEpomakerControllers() */ -REGISTER_HID_DETECTOR_IPU("Epomaker TH80 Pro (USB Cable)", DetectEpomakerControllers, Epomaker_VID, Epomaker_TH80_Pro_USB_PID, 1, 1, 2); -REGISTER_HID_DETECTOR_IPU("Epomaker TH80 Pro (USB Dongle)", DetectEpomakerControllers, Epomaker_VID, Epomaker_TH80_Pro_Dongle_PID, 1, 1, 2); +REGISTER_HID_DETECTOR_I("Epomaker TH80 Pro (USB Cable)", DetectEpomakerControllers, EPOMAKER_VID, EPOMAKER_TH80_Pro_USB_PID, 2); +REGISTER_HID_DETECTOR_I("Epomaker TH80 Pro (USB Dongle)", DetectEpomakerControllers, EPOMAKER_VID, EPOMAKER_TH80_Pro_Dongle_PID, 2); +REGISTER_HID_DETECTOR_I("Attack Shark K86 (USB Cable)", DetectEpomakerControllers, EPOMAKER_VID, ATTACKSHARK_K86_USB_PID, 2); /*---------------------------------------------------------*\ | Bluetooth Not implemented | \*---------------------------------------------------------*/ -//REGISTER_HID_DETECTOR("Epomaker TH80 Pro (Bluetooth)", DetectEpomakerControllers, Epomaker_VID, Epomaker_TH80_Pro_BT_PID); +//REGISTER_HID_DETECTOR("Epomaker TH80 Pro (Bluetooth)", DetectEpomakerControllers, EPOMAKER_VID, EPOMAKER_TH80_Pro_BT_PID); +//REGISTER_HID_DETECTOR("Attack Shark K86 (Bluetooth)", DetectEpomakerControllers, EPOMAKER_VID, ATTACKSHARK_K86_BT_PID); diff --git a/Controllers/EpomakerController/RGBController_EpomakerController.cpp b/Controllers/EpomakerController/RGBController_EpomakerController.cpp index a2c05b64..27e78c90 100644 --- a/Controllers/EpomakerController/RGBController_EpomakerController.cpp +++ b/Controllers/EpomakerController/RGBController_EpomakerController.cpp @@ -1,11 +1,13 @@ -/*-------------------------------------------------------------------*\ -| RGBController_EpomakerController.cpp | -| | -| Driver for Epomaker Keyboard | -| | -| Alvaro Munoz (alvaromunoz) 2023-06-05 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_EpomakerController.cpp | +| | +| RGBController for Epomaker keyboard | +| | +| Alvaro Munoz (alvaromunoz) 05 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_EpomakerController.h" @@ -17,7 +19,7 @@ @save :robot: @direct :x: @effects :white_check_mark: - @detectors EpomakerControllerDetect + @detectors DetectEpomakerControllers @comment \*-------------------------------------------------------------------*/ @@ -40,231 +42,231 @@ RGBController_EpomakerController::RGBController_EpomakerController(EpomakerContr modes.push_back(Off); mode Always_on; - Always_on.name = "Static"; - Always_on.value = Epomaker_MODE_ALWAYS_ON; + Always_on.name = "Direct"; + Always_on.value = EPOMAKER_MODE_ALWAYS_ON; Always_on.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; Always_on.color_mode = MODE_COLORS_PER_LED | MODE_COLORS_RANDOM; - Always_on.brightness_min = Epomaker_BRIGHTNESS_MIN; - Always_on.brightness_max = Epomaker_BRIGHTNESS_MAX; - Always_on.brightness = Epomaker_BRIGHTNESS_DEFAULT; + Always_on.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Always_on.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Always_on.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; modes.push_back(Always_on); mode Dynamic_breathing; Dynamic_breathing.name = "Breathing"; - Dynamic_breathing.value = Epomaker_MODE_DYNAMIC_BREATHING; + Dynamic_breathing.value = EPOMAKER_MODE_DYNAMIC_BREATHING; Dynamic_breathing.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR; Dynamic_breathing.color_mode = MODE_COLORS_PER_LED; - Dynamic_breathing.brightness_min = Epomaker_BRIGHTNESS_MIN; - Dynamic_breathing.brightness_max = Epomaker_BRIGHTNESS_MAX; - Dynamic_breathing.brightness = Epomaker_BRIGHTNESS_DEFAULT; - Dynamic_breathing.speed_min = Epomaker_SPEED_MIN; - Dynamic_breathing.speed_max = Epomaker_SPEED_MAX; - Dynamic_breathing.speed = Epomaker_SPEED_DEFAULT; + Dynamic_breathing.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Dynamic_breathing.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Dynamic_breathing.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + Dynamic_breathing.speed_min = EPOMAKER_SPEED_MIN; + Dynamic_breathing.speed_max = EPOMAKER_SPEED_MAX; + Dynamic_breathing.speed = EPOMAKER_SPEED_DEFAULT; modes.push_back(Dynamic_breathing); mode Spectrum_cycle; Spectrum_cycle.name = "Spectrum Cycle"; - Spectrum_cycle.value = Epomaker_MODE_SPECTRUM_CYCLE; + Spectrum_cycle.value = EPOMAKER_MODE_SPECTRUM_CYCLE; Spectrum_cycle.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; Spectrum_cycle.color_mode = MODE_COLORS_NONE; - Spectrum_cycle.brightness_min = Epomaker_BRIGHTNESS_MIN; - Spectrum_cycle.brightness_max = Epomaker_BRIGHTNESS_MAX; - Spectrum_cycle.brightness = Epomaker_BRIGHTNESS_DEFAULT; - Spectrum_cycle.speed_min = Epomaker_SPEED_MIN; - Spectrum_cycle.speed_max = Epomaker_SPEED_MAX_SPECIAL; - Spectrum_cycle.speed = Epomaker_SPEED_DEFAULT; + Spectrum_cycle.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Spectrum_cycle.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Spectrum_cycle.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + Spectrum_cycle.speed_min = EPOMAKER_SPEED_MIN; + Spectrum_cycle.speed_max = EPOMAKER_SPEED_MAX_SPECIAL; + Spectrum_cycle.speed = EPOMAKER_SPEED_DEFAULT; modes.push_back(Spectrum_cycle); mode Drift; Drift.name = "Drift"; - Drift.value = Epomaker_MODE_DRIFT; + Drift.value = EPOMAKER_MODE_DRIFT; Drift.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD; Drift.color_mode = MODE_COLORS_PER_LED | MODE_COLORS_RANDOM; - Drift.brightness_min = Epomaker_BRIGHTNESS_MIN; - Drift.brightness_max = Epomaker_BRIGHTNESS_MAX; - Drift.brightness = Epomaker_BRIGHTNESS_DEFAULT; - Drift.speed_min = Epomaker_SPEED_MIN; - Drift.speed_max = Epomaker_SPEED_MAX; - Drift.speed = Epomaker_SPEED_DEFAULT; + Drift.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Drift.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Drift.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + Drift.speed_min = EPOMAKER_SPEED_MIN; + Drift.speed_max = EPOMAKER_SPEED_MAX; + Drift.speed = EPOMAKER_SPEED_DEFAULT; modes.push_back(Drift); mode Waves_ripple; Waves_ripple.name = "Waves ripple"; - Waves_ripple.value = Epomaker_MODE_WAVES_RIPPLE; + Waves_ripple.value = EPOMAKER_MODE_WAVES_RIPPLE; Waves_ripple.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; Waves_ripple.color_mode = MODE_COLORS_PER_LED | MODE_COLORS_RANDOM; - Waves_ripple.brightness_min = Epomaker_BRIGHTNESS_MIN; - Waves_ripple.brightness_max = Epomaker_BRIGHTNESS_MAX; - Waves_ripple.brightness = Epomaker_BRIGHTNESS_DEFAULT; + Waves_ripple.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Waves_ripple.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Waves_ripple.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; modes.push_back(Waves_ripple); mode Stars_twinkle; Stars_twinkle.name = "Stars twinkle"; - Stars_twinkle.value = Epomaker_MODE_STARS_TWINKLE; + Stars_twinkle.value = EPOMAKER_MODE_STARS_TWINKLE; Stars_twinkle.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; Stars_twinkle.color_mode = MODE_COLORS_PER_LED | MODE_COLORS_RANDOM; - Stars_twinkle.brightness_min = Epomaker_BRIGHTNESS_MIN; - Stars_twinkle.brightness_max = Epomaker_BRIGHTNESS_MAX; - Stars_twinkle.brightness = Epomaker_BRIGHTNESS_DEFAULT; - Stars_twinkle.speed_min = Epomaker_SPEED_MIN; - Stars_twinkle.speed_max = Epomaker_SPEED_MAX; - Stars_twinkle.speed = Epomaker_SPEED_DEFAULT; + Stars_twinkle.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Stars_twinkle.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Stars_twinkle.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + Stars_twinkle.speed_min = EPOMAKER_SPEED_MIN; + Stars_twinkle.speed_max = EPOMAKER_SPEED_MAX; + Stars_twinkle.speed = EPOMAKER_SPEED_DEFAULT; modes.push_back(Stars_twinkle); mode Steady_stream; Steady_stream.name = "Steady stream"; - Steady_stream.value = Epomaker_MODE_STEADY_STREAM; + Steady_stream.value = EPOMAKER_MODE_STEADY_STREAM; Steady_stream.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_DIRECTION_LR; Steady_stream.color_mode = MODE_COLORS_PER_LED | MODE_COLORS_RANDOM; - Steady_stream.brightness_min = Epomaker_BRIGHTNESS_MIN; - Steady_stream.brightness_max = Epomaker_BRIGHTNESS_MAX; - Steady_stream.brightness = Epomaker_BRIGHTNESS_DEFAULT; - Steady_stream.speed_min = Epomaker_SPEED_MIN; - Steady_stream.speed_max = Epomaker_SPEED_MAX; - Steady_stream.speed = Epomaker_SPEED_DEFAULT; + Steady_stream.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Steady_stream.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Steady_stream.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + Steady_stream.speed_min = EPOMAKER_SPEED_MIN; + Steady_stream.speed_max = EPOMAKER_SPEED_MAX; + Steady_stream.speed = EPOMAKER_SPEED_DEFAULT; modes.push_back(Steady_stream); mode Shadowing; Shadowing.name = "Reactive"; - Shadowing.value = Epomaker_MODE_SHADOWING; + Shadowing.value = EPOMAKER_MODE_SHADOWING; Shadowing.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; Shadowing.color_mode = MODE_COLORS_PER_LED | MODE_COLORS_RANDOM; - Shadowing.brightness_min = Epomaker_BRIGHTNESS_MIN; - Shadowing.brightness_max = Epomaker_BRIGHTNESS_MAX; - Shadowing.brightness = Epomaker_BRIGHTNESS_DEFAULT; - Shadowing.speed_min = Epomaker_SPEED_MIN; - Shadowing.speed_max = Epomaker_SPEED_MAX; - Shadowing.speed = Epomaker_SPEED_DEFAULT; + Shadowing.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Shadowing.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Shadowing.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + Shadowing.speed_min = EPOMAKER_SPEED_MIN; + Shadowing.speed_max = EPOMAKER_SPEED_MAX; + Shadowing.speed = EPOMAKER_SPEED_DEFAULT; modes.push_back(Shadowing); mode Peaks_rising; Peaks_rising.name = "Peaks rising one after another"; - Peaks_rising.value = Epomaker_MODE_PEAKS_RISING_ONE_AFTER_ANOTHER; + Peaks_rising.value = EPOMAKER_MODE_PEAKS_RISING_ONE_AFTER_ANOTHER; Peaks_rising.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; Peaks_rising.color_mode = MODE_COLORS_PER_LED | MODE_COLORS_RANDOM; - Peaks_rising.brightness_min = Epomaker_BRIGHTNESS_MIN; - Peaks_rising.brightness_max = Epomaker_BRIGHTNESS_MAX; - Peaks_rising.brightness = Epomaker_BRIGHTNESS_DEFAULT; - Peaks_rising.speed_min = Epomaker_SPEED_MIN; - Peaks_rising.speed_max = Epomaker_SPEED_MAX; - Peaks_rising.speed = Epomaker_SPEED_DEFAULT; + Peaks_rising.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Peaks_rising.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Peaks_rising.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + Peaks_rising.speed_min = EPOMAKER_SPEED_MIN; + Peaks_rising.speed_max = EPOMAKER_SPEED_MAX; + Peaks_rising.speed = EPOMAKER_SPEED_DEFAULT; modes.push_back(Peaks_rising); mode Sine_wave; Sine_wave.name = "Sine wave"; - Sine_wave.value = Epomaker_MODE_SINE_WAVE; + Sine_wave.value = EPOMAKER_MODE_SINE_WAVE; Sine_wave.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; Sine_wave.color_mode = MODE_COLORS_PER_LED | MODE_COLORS_RANDOM; - Sine_wave.brightness_min = Epomaker_BRIGHTNESS_MIN; - Sine_wave.brightness_max = Epomaker_BRIGHTNESS_MAX; - Sine_wave.brightness = Epomaker_BRIGHTNESS_DEFAULT; - Sine_wave.speed_min = Epomaker_SPEED_MIN; - Sine_wave.speed_max = Epomaker_SPEED_MAX; - Sine_wave.speed = Epomaker_SPEED_DEFAULT; + Sine_wave.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Sine_wave.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Sine_wave.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + Sine_wave.speed_min = EPOMAKER_SPEED_MIN; + Sine_wave.speed_max = EPOMAKER_SPEED_MAX; + Sine_wave.speed = EPOMAKER_SPEED_DEFAULT; modes.push_back(Sine_wave); mode Caispring; Caispring.name = "Caispring Surging"; - Caispring.value = Epomaker_MODE_CAISPRING_SURGING; + Caispring.value = EPOMAKER_MODE_CAISPRING_SURGING; Caispring.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_DIRECTION_LR; Caispring.color_mode = MODE_COLORS_PER_LED | MODE_COLORS_RANDOM; - Caispring.brightness_min = Epomaker_BRIGHTNESS_MIN; - Caispring.brightness_max = Epomaker_BRIGHTNESS_MAX; - Caispring.brightness = Epomaker_BRIGHTNESS_DEFAULT; - Caispring.speed_min = Epomaker_SPEED_MIN; - Caispring.speed_max = Epomaker_SPEED_MAX; - Caispring.speed = Epomaker_SPEED_DEFAULT; + Caispring.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Caispring.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Caispring.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + Caispring.speed_min = EPOMAKER_SPEED_MIN; + Caispring.speed_max = EPOMAKER_SPEED_MAX; + Caispring.speed = EPOMAKER_SPEED_DEFAULT; modes.push_back(Caispring); mode Flowers_blooming; Flowers_blooming.name = "Flowers blooming"; - Flowers_blooming.value = Epomaker_MODE_FLOWERS_BLOOMING; + Flowers_blooming.value = EPOMAKER_MODE_FLOWERS_BLOOMING; Flowers_blooming.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_DIRECTION_LR; Flowers_blooming.color_mode = MODE_COLORS_PER_LED | MODE_COLORS_RANDOM; - Flowers_blooming.brightness_min = Epomaker_BRIGHTNESS_MIN; - Flowers_blooming.brightness_max = Epomaker_BRIGHTNESS_MAX; - Flowers_blooming.brightness = Epomaker_BRIGHTNESS_DEFAULT; - Flowers_blooming.speed_min = Epomaker_SPEED_MIN; - Flowers_blooming.speed_max = Epomaker_SPEED_MAX; - Flowers_blooming.speed = Epomaker_SPEED_DEFAULT; + Flowers_blooming.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Flowers_blooming.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Flowers_blooming.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + Flowers_blooming.speed_min = EPOMAKER_SPEED_MIN; + Flowers_blooming.speed_max = EPOMAKER_SPEED_MAX; + Flowers_blooming.speed = EPOMAKER_SPEED_DEFAULT; modes.push_back(Flowers_blooming); mode Laser; Laser.name = "Laser"; - Laser.value = Epomaker_MODE_LASER; + Laser.value = EPOMAKER_MODE_LASER; Laser.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; Laser.color_mode = MODE_COLORS_PER_LED | MODE_COLORS_RANDOM; - Laser.brightness_min = Epomaker_BRIGHTNESS_MIN; - Laser.brightness_max = Epomaker_BRIGHTNESS_MAX; - Laser.brightness = Epomaker_BRIGHTNESS_DEFAULT; - Laser.speed_min = Epomaker_SPEED_MIN; - Laser.speed_max = Epomaker_SPEED_MAX; - Laser.speed = Epomaker_SPEED_DEFAULT; + Laser.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Laser.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Laser.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + Laser.speed_min = EPOMAKER_SPEED_MIN; + Laser.speed_max = EPOMAKER_SPEED_MAX; + Laser.speed = EPOMAKER_SPEED_DEFAULT; modes.push_back(Laser); mode Peak_turn; Peak_turn.name = "Peak turn"; - Peak_turn.value = Epomaker_MODE_PEAK_TURN; + Peak_turn.value = EPOMAKER_MODE_PEAK_TURN; Peak_turn.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_DIRECTION_LR; Peak_turn.color_mode = MODE_COLORS_PER_LED | MODE_COLORS_RANDOM; - Peak_turn.brightness_min = Epomaker_BRIGHTNESS_MIN; - Peak_turn.brightness_max = Epomaker_BRIGHTNESS_MAX; - Peak_turn.brightness = Epomaker_BRIGHTNESS_DEFAULT; - Peak_turn.speed_min = Epomaker_SPEED_MIN; - Peak_turn.speed_max = Epomaker_SPEED_MAX_SPECIAL; - Peak_turn.speed = Epomaker_SPEED_DEFAULT; + Peak_turn.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Peak_turn.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Peak_turn.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + Peak_turn.speed_min = EPOMAKER_SPEED_MIN; + Peak_turn.speed_max = EPOMAKER_SPEED_MAX_SPECIAL; + Peak_turn.speed = EPOMAKER_SPEED_DEFAULT; modes.push_back(Peak_turn); mode Inclined_rain; Inclined_rain.name = "Inclined Rain"; - Inclined_rain.value = Epomaker_MODE_INCLINED_RAIN; + Inclined_rain.value = EPOMAKER_MODE_INCLINED_RAIN; Inclined_rain.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; Inclined_rain.color_mode = MODE_COLORS_PER_LED | MODE_COLORS_RANDOM; - Inclined_rain.brightness_min = Epomaker_BRIGHTNESS_MIN; - Inclined_rain.brightness_max = Epomaker_BRIGHTNESS_MAX; - Inclined_rain.brightness = Epomaker_BRIGHTNESS_DEFAULT; - Inclined_rain.speed_min = Epomaker_SPEED_MIN; - Inclined_rain.speed_max = Epomaker_SPEED_MAX; - Inclined_rain.speed = Epomaker_SPEED_DEFAULT; + Inclined_rain.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Inclined_rain.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Inclined_rain.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + Inclined_rain.speed_min = EPOMAKER_SPEED_MIN; + Inclined_rain.speed_max = EPOMAKER_SPEED_MAX; + Inclined_rain.speed = EPOMAKER_SPEED_DEFAULT; modes.push_back(Inclined_rain); mode Snow; Snow.name = "Snow"; - Snow.value = Epomaker_MODE_SNOW; + Snow.value = EPOMAKER_MODE_SNOW; Snow.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; Snow.color_mode = MODE_COLORS_PER_LED | MODE_COLORS_RANDOM; - Snow.brightness_min = Epomaker_BRIGHTNESS_MIN; - Snow.brightness_max = Epomaker_BRIGHTNESS_MAX; - Snow.brightness = Epomaker_BRIGHTNESS_DEFAULT; - Snow.speed_min = Epomaker_SPEED_MIN; - Snow.speed_max = Epomaker_SPEED_MAX_SPECIAL; - Snow.speed = Epomaker_SPEED_DEFAULT; + Snow.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Snow.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Snow.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + Snow.speed_min = EPOMAKER_SPEED_MIN; + Snow.speed_max = EPOMAKER_SPEED_MAX_SPECIAL; + Snow.speed = EPOMAKER_SPEED_DEFAULT; modes.push_back(Snow); mode Meteor; Meteor.name = "Meteor"; - Meteor.value = Epomaker_MODE_METEOR; + Meteor.value = EPOMAKER_MODE_METEOR; Meteor.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; Meteor.color_mode = MODE_COLORS_PER_LED | MODE_COLORS_RANDOM; - Meteor.brightness_min = Epomaker_BRIGHTNESS_MIN; - Meteor.brightness_max = Epomaker_BRIGHTNESS_MAX; - Meteor.brightness = Epomaker_BRIGHTNESS_DEFAULT; - Meteor.speed_min = Epomaker_SPEED_MIN; - Meteor.speed_max = Epomaker_SPEED_MAX_SPECIAL; - Meteor.speed = Epomaker_SPEED_DEFAULT; + Meteor.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Meteor.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Meteor.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + Meteor.speed_min = EPOMAKER_SPEED_MIN; + Meteor.speed_max = EPOMAKER_SPEED_MAX_SPECIAL; + Meteor.speed = EPOMAKER_SPEED_DEFAULT; modes.push_back(Meteor); mode Through_the_snow; Through_the_snow.name = "Through the snow (non trace)"; - Through_the_snow.value = Epomaker_MODE_THROUGH_THE_SNOW_NON_TRACE; + Through_the_snow.value = EPOMAKER_MODE_THROUGH_THE_SNOW_NON_TRACE; Through_the_snow.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; Through_the_snow.color_mode = MODE_COLORS_PER_LED | MODE_COLORS_RANDOM; - Through_the_snow.brightness_min = Epomaker_BRIGHTNESS_MIN; - Through_the_snow.brightness_max = Epomaker_BRIGHTNESS_MAX; - Through_the_snow.brightness = Epomaker_BRIGHTNESS_DEFAULT; - Through_the_snow.speed_min = Epomaker_SPEED_MIN; - Through_the_snow.speed_max = Epomaker_SPEED_MAX_SPECIAL; - Through_the_snow.speed = Epomaker_SPEED_DEFAULT; + Through_the_snow.brightness_min = EPOMAKER_BRIGHTNESS_MIN; + Through_the_snow.brightness_max = EPOMAKER_BRIGHTNESS_MAX; + Through_the_snow.brightness = EPOMAKER_BRIGHTNESS_DEFAULT; + Through_the_snow.speed_min = EPOMAKER_SPEED_MIN; + Through_the_snow.speed_max = EPOMAKER_SPEED_MAX_SPECIAL; + Through_the_snow.speed = EPOMAKER_SPEED_DEFAULT; modes.push_back(Through_the_snow); SetupZones(); @@ -287,26 +289,26 @@ void RGBController_EpomakerController::DeviceUpdateLEDs() void RGBController_EpomakerController::DeviceUpdateMode() { - if(modes[active_mode].value == Epomaker_MODE_DRIFT) + if(modes[active_mode].value == EPOMAKER_MODE_DRIFT) { if(modes[active_mode].direction == MODE_DIRECTION_LEFT) { - controller->SetOption(Epomaker_OPTION_DRIFT_LEFT); + controller->SetOption(EPOMAKER_OPTION_DRIFT_LEFT); } else if(modes[active_mode].direction == MODE_DIRECTION_RIGHT) { - controller->SetOption(Epomaker_OPTION_DRIFT_RIGHT); + controller->SetOption(EPOMAKER_OPTION_DRIFT_RIGHT); } else if(modes[active_mode].direction == MODE_DIRECTION_UP) { - controller->SetOption(Epomaker_OPTION_DRIFT_UP); + controller->SetOption(EPOMAKER_OPTION_DRIFT_UP); } else if(modes[active_mode].direction == MODE_DIRECTION_DOWN) { - controller->SetOption(Epomaker_OPTION_DRIFT_DOWN); + controller->SetOption(EPOMAKER_OPTION_DRIFT_DOWN); } } - else if(modes[active_mode].value == Epomaker_MODE_STEADY_STREAM) + else if(modes[active_mode].value == EPOMAKER_MODE_STEADY_STREAM) { /*---------------------------------------------------------*\ | TODO: These OPTIONS (zig-zag, return) should not | @@ -314,14 +316,14 @@ void RGBController_EpomakerController::DeviceUpdateMode() \*---------------------------------------------------------*/ if(modes[active_mode].direction == MODE_DIRECTION_LEFT) { - controller->SetOption(Epomaker_OPTION_STEADY_STREAM_ZIG_ZAG); + controller->SetOption(EPOMAKER_OPTION_STEADY_STREAM_ZIG_ZAG); } else if(modes[active_mode].direction == MODE_DIRECTION_RIGHT) { - controller->SetOption(Epomaker_OPTION_STEADY_STREAM_RETURN); + controller->SetOption(EPOMAKER_OPTION_STEADY_STREAM_RETURN); } } - else if(modes[active_mode].value == Epomaker_MODE_CAISPRING_SURGING) + else if(modes[active_mode].value == EPOMAKER_MODE_CAISPRING_SURGING) { /*---------------------------------------------------------*\ | TODO: These OPTIONS (in, out) should not | @@ -329,25 +331,25 @@ void RGBController_EpomakerController::DeviceUpdateMode() \*---------------------------------------------------------*/ if(modes[active_mode].direction == MODE_DIRECTION_LEFT) { - controller->SetOption(Epomaker_OPTION_CAISPRING_SURGING_OUT); + controller->SetOption(EPOMAKER_OPTION_CAISPRING_SURGING_OUT); } else if(modes[active_mode].direction == MODE_DIRECTION_RIGHT) { - controller->SetOption(Epomaker_OPTION_CAISPRING_SURGING_IN); + controller->SetOption(EPOMAKER_OPTION_CAISPRING_SURGING_IN); } } - else if(modes[active_mode].value == Epomaker_MODE_FLOWERS_BLOOMING) + else if(modes[active_mode].value == EPOMAKER_MODE_FLOWERS_BLOOMING) { if(modes[active_mode].direction == MODE_DIRECTION_LEFT) { - controller->SetOption(Epomaker_OPTION_FLOWERS_BLOOMING_LEFT); + controller->SetOption(EPOMAKER_OPTION_FLOWERS_BLOOMING_LEFT); } else if(modes[active_mode].direction == MODE_DIRECTION_RIGHT) { - controller->SetOption(Epomaker_OPTION_FLOWERS_BLOOMING_RIGHT); + controller->SetOption(EPOMAKER_OPTION_FLOWERS_BLOOMING_RIGHT); } } - else if(modes[active_mode].value == Epomaker_MODE_PEAK_TURN) + else if(modes[active_mode].value == EPOMAKER_MODE_PEAK_TURN) { /*---------------------------------------------------------*\ | TODO: These OPTIONS (clockwise, anti-clockwise) | @@ -355,16 +357,16 @@ void RGBController_EpomakerController::DeviceUpdateMode() \*---------------------------------------------------------*/ if(modes[active_mode].direction == MODE_DIRECTION_LEFT) { - controller->SetOption(Epomaker_OPTION_PEAK_TURN_ANTI_CLOCKWISE); + controller->SetOption(EPOMAKER_OPTION_PEAK_TURN_ANTI_CLOCKWISE); } else if(modes[active_mode].direction == MODE_DIRECTION_RIGHT) { - controller->SetOption(Epomaker_OPTION_PEAK_TURN_CLOCKWISE); + controller->SetOption(EPOMAKER_OPTION_PEAK_TURN_CLOCKWISE); } } else { - controller->SetOption(Epomaker_OPTION_DEFAULT); + controller->SetOption(EPOMAKER_OPTION_DEFAULT); } controller->SetDazzle(modes[active_mode].color_mode == MODE_COLORS_RANDOM); diff --git a/Controllers/EpomakerController/RGBController_EpomakerController.h b/Controllers/EpomakerController/RGBController_EpomakerController.h index c2a9cb18..05a0885e 100644 --- a/Controllers/EpomakerController/RGBController_EpomakerController.h +++ b/Controllers/EpomakerController/RGBController_EpomakerController.h @@ -1,17 +1,18 @@ -/*-------------------------------------------------------------------*\ -| RGBController_EpomakerController.h | -| | -| Driver for Epomaker Keyboard | -| | -| Alvaro Munoz (alvaromunoz) 2023-06-05 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_EpomakerController.h | +| | +| RGBController for Epomaker keyboard | +| | +| Alvaro Munoz (alvaromunoz) 05 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#ifndef RGBCONTROLLER_EpomakerCONTROLLER_H -#define RGBCONTROLLER_EpomakerCONTROLLER_H +#pragma once #include "RGBController.h" -#include "Controllers/EpomakerController/EpomakerController.h" +#include "EpomakerController.h" class RGBController_EpomakerController : public RGBController { @@ -32,5 +33,3 @@ public: private: EpomakerController* controller; }; - -#endif // RGBCONTROLLER_EpomakerCONTROLLER_H diff --git a/Controllers/EspurnaController/EspurnaController.cpp b/Controllers/EspurnaController/EspurnaController.cpp index f3a79ede..3ef062c5 100644 --- a/Controllers/EspurnaController/EspurnaController.cpp +++ b/Controllers/EspurnaController/EspurnaController.cpp @@ -1,15 +1,19 @@ /*---------------------------------------------------------*\ -| Processing Code for Espurna Interface | +| EspurnaController.cpp | | | -| Adam Honse (calcprogrammer1@gmail.com), 9/11/2020 | +| Driver for Espurna | +| | +| Adam Honse (calcprogrammer1@gmail.com) 11 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "EspurnaController.h" - #include #include #include #include +#include "EspurnaController.h" EspurnaController::EspurnaController() { @@ -26,9 +30,9 @@ void EspurnaController::Initialize(char* ledstring) LPSTR source = NULL; LPSTR udpport_baud = NULL; LPSTR next = NULL; - + source = strtok_s(ledstring, ",", &next); - + //Check for either the UDP port or the serial baud rate if (strlen(next)) { @@ -68,7 +72,7 @@ void EspurnaController::SetLEDs(std::vector colors) char get_request[1024]; snprintf(get_request, 1024, "GET /api/rgb?apikey=%s&value=%%23%02X%02X%02X HTTP/1.1\r\nHost: %s\r\n\r\n", espurna_apikey, RGBGetRValue(color), RGBGetGValue(color), RGBGetBValue(color), client_name.c_str()); tcpport->tcp_client_connect(); - tcpport->tcp_client_write(get_request, strlen(get_request)); + tcpport->tcp_client_write(get_request, (int)strlen(get_request)); tcpport->tcp_close(); } } diff --git a/Controllers/EspurnaController/EspurnaController.h b/Controllers/EspurnaController/EspurnaController.h index 3027ea63..d3a4fcf3 100644 --- a/Controllers/EspurnaController/EspurnaController.h +++ b/Controllers/EspurnaController/EspurnaController.h @@ -1,16 +1,19 @@ /*---------------------------------------------------------*\ -| Definitions for Espurna Interface | +| EspurnaController.h | | | -| Adam Honse (calcprogrammer1@gmail.com), 9/11/2020 | +| Driver for Espurna | +| | +| Adam Honse (calcprogrammer1@gmail.com) 11 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#ifndef ESPURNA_H -#define ESPURNA_H +#pragma once +#include #include "RGBController.h" #include "net_port.h" -#include - #ifndef TRUE #define TRUE true @@ -36,14 +39,9 @@ public: void SetLEDs(std::vector colors); private: - int baud_rate; - - char led_string[1024]; std::string port_name; std::string client_name; char espurna_apikey[128]; net_port *tcpport; }; - -#endif diff --git a/Controllers/EspurnaController/EspurnaControllerDetect.cpp b/Controllers/EspurnaController/EspurnaControllerDetect.cpp index 160108d9..94f14f2e 100644 --- a/Controllers/EspurnaController/EspurnaControllerDetect.cpp +++ b/Controllers/EspurnaController/EspurnaControllerDetect.cpp @@ -1,11 +1,18 @@ +/*---------------------------------------------------------*\ +| EspurnaControllerDetect.cpp | +| | +| Detctor for Espurna | +| | +| Adam Honse (calcprogrammer1@gmail.com) 11 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "EspurnaController.h" -#include "RGBController.h" #include "RGBController_Espurna.h" #include "SettingsManager.h" -#include -#include -#include /******************************************************************************************\ * * diff --git a/Controllers/EspurnaController/RGBController_Espurna.cpp b/Controllers/EspurnaController/RGBController_Espurna.cpp index b5436ef3..baeb3514 100644 --- a/Controllers/EspurnaController/RGBController_Espurna.cpp +++ b/Controllers/EspurnaController/RGBController_Espurna.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_Espurna.cpp | -| | -| Generic RGB Interface for Espurna | -| | -| Adam Honse (CalcProgrammer1) 6/20/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Espurna.cpp | +| | +| RGBController for Espurna | +| | +| Adam Honse (calcprogrammer1@gmail.com) 11 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_Espurna.h" diff --git a/Controllers/EspurnaController/RGBController_Espurna.h b/Controllers/EspurnaController/RGBController_Espurna.h index 28f5d722..853ac9e8 100644 --- a/Controllers/EspurnaController/RGBController_Espurna.h +++ b/Controllers/EspurnaController/RGBController_Espurna.h @@ -1,12 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_Espurna.h | -| | -| Generic RGB Interface for Espurna | -| | -| Adam Honse (CalcProgrammer1) 9/11/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Espurna.h | +| | +| RGBController for Espurna | +| | +| Adam Honse (calcprogrammer1@gmail.com) 11 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "EspurnaController.h" diff --git a/Controllers/FanBusController/FanBusController.cpp b/Controllers/FanBusController/FanBusController.cpp index 46704fdc..a184178a 100644 --- a/Controllers/FanBusController/FanBusController.cpp +++ b/Controllers/FanBusController/FanBusController.cpp @@ -1,7 +1,12 @@ /*---------------------------------------------------------*\ -| FanBus RGB Controller Interface | +| FanBusController.cpp | | | -| Adam Honse (calcprogrammer1@gmail.com), 1/12/2021 | +| Driver for FanBus devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ #include "FanBusController.h" @@ -41,7 +46,7 @@ void FanBusController::SetLEDs(std::vector colors) bus->write_queue(dev, 0x11 + (led_idx * 3), grn); bus->write_queue(dev, 0x12 + (led_idx * 3), blu); } - + bus->write_queue(dev, 0x0C, 0x01); bus->process_queue(); diff --git a/Controllers/FanBusController/FanBusController.h b/Controllers/FanBusController/FanBusController.h index 026cff11..894ed13d 100644 --- a/Controllers/FanBusController/FanBusController.h +++ b/Controllers/FanBusController/FanBusController.h @@ -1,16 +1,20 @@ /*---------------------------------------------------------*\ -| Definitions for FanBus RGB Controller Interface | +| FanBusController.h | | | -| Adam Honse (calcprogrammer1@gmail.com), 1/12/2021 | +| Driver for FanBus devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ #pragma once +#include #include "FanBusInterface.h" #include "RGBController.h" -#include - class FanBusController { public: diff --git a/Controllers/FanBusController/FanBusControllerDetect.cpp b/Controllers/FanBusController/FanBusControllerDetect.cpp index 1de05f24..f8ae4be3 100644 --- a/Controllers/FanBusController/FanBusControllerDetect.cpp +++ b/Controllers/FanBusController/FanBusControllerDetect.cpp @@ -1,6 +1,18 @@ +/*---------------------------------------------------------*\ +| FanBusControllerDetect.cpp | +| | +| Detector for FanBus devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "FanBusController.h" #include "RGBController_FanBus.h" +#include "SettingsManager.h" void DetectFanBusControllers() { diff --git a/Controllers/FanBusController/FanBusInterface.cpp b/Controllers/FanBusController/FanBusInterface.cpp index 2e786e63..e6b4cd6a 100644 --- a/Controllers/FanBusController/FanBusInterface.cpp +++ b/Controllers/FanBusController/FanBusInterface.cpp @@ -1,12 +1,17 @@ /*---------------------------------------------------------*\ -| FanBus Interface | +| FanBusInterface.cpp | | | -| Adam Honse (calcprogrammer1@gmail.com), 1/12/2021 | +| Interface for FanBus devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "FanBusInterface.h" - +#include #include +#include "FanBusInterface.h" using namespace std::chrono_literals; @@ -18,20 +23,20 @@ FanBusInterface::FanBusInterface(const char* portname) /*-----------------------------------------------------*\ | Flush any data in the receive queue | \*-----------------------------------------------------*/ - char read_buf[6]; + unsigned char read_buf[6]; - while(serialport->serial_read(read_buf, 6) > 0) + while(serialport->serial_read((char *)read_buf, 6) > 0) { } read_buf[0] = 0xFF; - serialport->serial_write(read_buf, 1); + serialport->serial_write((char *)read_buf, 1); std::this_thread::sleep_for(10ms); - int test = serialport->serial_read(read_buf, 1); + int test = serialport->serial_read((char *)read_buf, 1); if(test > 0) { @@ -121,10 +126,10 @@ void FanBusInterface::write_queue int FanBusInterface::process_queue() { - int return_val = serialport->serial_write((char *)&fanbus_msg_queued[0], fanbus_msg_queued.size()); + int return_val = serialport->serial_write((char *)&fanbus_msg_queued[0], (int)fanbus_msg_queued.size()); fanbus_msg_queued.clear(); - + return(return_val); } diff --git a/Controllers/FanBusController/FanBusInterface.h b/Controllers/FanBusController/FanBusInterface.h index e9bc3b90..d48a7ffb 100644 --- a/Controllers/FanBusController/FanBusInterface.h +++ b/Controllers/FanBusController/FanBusInterface.h @@ -1,13 +1,17 @@ /*---------------------------------------------------------*\ -| FanBus Interface | +| FanBusInterface.h | | | -| Adam Honse (calcprogrammer1@gmail.com), 1/12/2021 | +| Interface for FanBus devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "serial_port.h" - #include #include +#include "serial_port.h" class FanBusInterface { @@ -40,7 +44,7 @@ public: ); int process_queue(); - + private: serial_port * serialport; std::string port_name; diff --git a/Controllers/FanBusController/RGBController_FanBus.cpp b/Controllers/FanBusController/RGBController_FanBus.cpp index 732c481b..474a3afc 100644 --- a/Controllers/FanBusController/RGBController_FanBus.cpp +++ b/Controllers/FanBusController/RGBController_FanBus.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_FanBus.cpp | -| | -| Generic RGB Interface for FanBus devices | -| | -| Adam Honse (CalcProgrammer1) 1/12/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_FanBus.cpp | +| | +| RGBController for FanBus devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_FanBus.h" diff --git a/Controllers/FanBusController/RGBController_FanBus.h b/Controllers/FanBusController/RGBController_FanBus.h index ffac61a0..764dfc59 100644 --- a/Controllers/FanBusController/RGBController_FanBus.h +++ b/Controllers/FanBusController/RGBController_FanBus.h @@ -1,12 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_FanBus.h | -| | -| Generic RGB Interface for FanBus devices | -| | -| Adam Honse (CalcProgrammer1) 1/12/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_FanBus.h | +| | +| RGBController for FanBus devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "FanBusController.h" diff --git a/Controllers/FaustusController/RGBController_Faustus.cpp b/Controllers/FaustusController/RGBController_Faustus.cpp deleted file mode 100644 index 1ae028ff..00000000 --- a/Controllers/FaustusController/RGBController_Faustus.cpp +++ /dev/null @@ -1,195 +0,0 @@ -#include "RGBController_Faustus.h" -#include "Detector.h" -#include -#include - -/**------------------------------------------------------------------*\ - @name ASUS TUF Keyboard (Faustus) - @category Keyboard - @type File Stream - @save :x: - @direct :x: - @effects :white_check_mark: - @detectors DetectFaustusControllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_Faustus::RGBController_Faustus(const std::string& dev_path) -{ - name = "ASUS TUF Keyboard"; - vendor = "ASUS"; - type = DEVICE_TYPE_KEYBOARD; - description = "Faustus Device"; - - modes.resize(4); - modes[0].name = "Static"; - modes[0].value = FAUSTUS_MODE_STATIC; - modes[0].flags = MODE_FLAG_HAS_PER_LED_COLOR; - modes[0].color_mode = MODE_COLORS_PER_LED; - - modes[1].name = "Breathing"; - modes[1].value = FAUSTUS_MODE_BREATHING; - modes[1].flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR; - modes[1].speed_min = FAUSTUS_SPEED_SLOWEST; - modes[1].speed_max = FAUSTUS_SPEED_FASTEST; - modes[1].color_mode = MODE_COLORS_PER_LED; - modes[1].speed = FAUSTUS_SPEED_NORMAL; - - modes[2].name = "Color Cycle"; - modes[2].value = FAUSTUS_MODE_COLOR_CYCLE; - modes[2].flags = MODE_FLAG_HAS_SPEED; - modes[2].speed_min = FAUSTUS_SPEED_SLOWEST; - modes[2].speed_max = FAUSTUS_SPEED_FASTEST; - modes[2].color_mode = MODE_COLORS_NONE; - modes[2].speed = FAUSTUS_SPEED_NORMAL; - - modes[3].name = "Strobe"; - modes[3].value = FAUSTUS_MODE_STROBE; - modes[3].flags = MODE_FLAG_HAS_PER_LED_COLOR; - modes[3].color_mode = MODE_COLORS_PER_LED; - - SetupZones(); - - // Prepare file streams - r_path = dev_path; - g_path = dev_path; - b_path = dev_path; - mode_path = dev_path; - flags_path = dev_path; - set_path = dev_path; - - r_path.append("/kbbl_red"); - g_path.append("/kbbl_green"); - b_path.append("/kbbl_blue"); - mode_path.append("/kbbl_mode"); - flags_path.append("/kbbl_flags"); - set_path.append("/kbbl_set"); -} - -void RGBController_Faustus::SetupZones() -{ - /*---------------------------------------------------------*\ - | Set up zone | - \*---------------------------------------------------------*/ - zones.resize(1); - zones[0].type = ZONE_TYPE_SINGLE; - zones[0].name = "Keyboard Backlight zone"; - zones[0].leds_min = 1; - zones[0].leds_max = 1; - zones[0].leds_count = 1; - zones[0].matrix_map = NULL; - - /*---------------------------------------------------------*\ - | Set up LED | - \*---------------------------------------------------------*/ - leds.resize(1); - leds[0].name = "Keyboard Backlight LED"; - - SetupColors(); -} - -void RGBController_Faustus::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_Faustus::DeviceUpdateLEDs() -{ - int rv = uint8_t(RGBGetRValue(colors[0])); - int gv = uint8_t(RGBGetGValue(colors[0])); - int bv = uint8_t(RGBGetBValue(colors[0])); - - std::ofstream str_r; - std::ofstream str_g; - std::ofstream str_b; - std::ofstream str_mode; - std::ofstream str_flags; - std::ofstream str_set; - - str_r.open(r_path, std::ios::out | std::ios::trunc); - str_g.open(g_path, std::ios::out | std::ios::trunc); - str_b.open(b_path, std::ios::out | std::ios::trunc); - str_mode.open(mode_path, std::ios::out | std::ios::trunc); - str_flags.open(flags_path, std::ios::out | std::ios::trunc); - str_set.open(set_path, std::ios::out | std::ios::trunc); - - str_r << std::hex; - str_g << std::hex; - str_b << std::hex; - str_mode << std::hex; - str_flags << std::hex; - str_set << std::hex; - - str_r << rv; - str_g << gv; - str_b << bv; - str_mode << active_mode; - str_flags << 0x2a; // All of em - str_set << 2; - - // Flush everything - str_r.close(); - str_g.close(); - str_b.close(); - str_mode.close(); - str_flags.close(); - str_set.close(); -} - -void RGBController_Faustus::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_Faustus::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_Faustus::DeviceUpdateMode() -{ - DeviceUpdateLEDs(); -} - -void DetectFaustusControllers() -{ - const char* base_path = "/sys/devices/platform/faustus/kbbl"; - DIR* dir = opendir(base_path); - - if(!dir) - { - return; - } - - // Directory is present - we pretty much have a driver confirmation already, but double check for all files required just in case - struct dirent* dent = readdir(dir); - - if(!dent) - { - return; - } - - int found = 0; - while(dent) - { - const char* fname = dent->d_name; - if(!strcmp(fname, "kbbl_red") || !strcmp(fname, "kbbl_green") || !strcmp(fname, "kbbl_blue") || !strcmp(fname, "kbbl_mode") || !strcmp(fname, "kbbl_flags") || !strcmp(fname, "kbbl_set")) - { - ++found; - } - dent = readdir(dir); - } - - closedir(dir); - - if(found != 6) - { - return; - } - - ResourceManager::get()->RegisterRGBController(new RGBController_Faustus(base_path)); -} /* DetectFaustusControllers() */ - -REGISTER_DETECTOR("Faustus", DetectFaustusControllers); diff --git a/Controllers/FaustusController/RGBController_Faustus.h b/Controllers/FaustusController/RGBController_Faustus.h deleted file mode 100644 index d64681da..00000000 --- a/Controllers/FaustusController/RGBController_Faustus.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef RGBCONTROLLER_FAUSTUS_H -#define RGBCONTROLLER_FAUSTUS_H - -#include "RGBController.h" -#include - -enum -{ - FAUSTUS_MODE_STATIC = 0, - FAUSTUS_MODE_BREATHING = 1, - FAUSTUS_MODE_COLOR_CYCLE = 2, - FAUSTUS_MODE_STROBE = 3 -}; -enum -{ - FAUSTUS_SPEED_SLOWEST = 0, - FAUSTUS_SPEED_NORMAL = 1, - FAUSTUS_SPEED_FASTEST = 2, -}; - -class RGBController_Faustus : public RGBController -{ - private: - std::string r_path; - std::string g_path; - std::string b_path; - std::string mode_path; - std::string flags_path; - std::string set_path; - - public: - RGBController_Faustus(const std::string& dev_path); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); -}; - -#endif // RGBCONTROLLER_FAUSTUS_H diff --git a/Controllers/FaustusController/RGBController_Faustus_Linux.cpp b/Controllers/FaustusController/RGBController_Faustus_Linux.cpp new file mode 100644 index 00000000..4cf9e12d --- /dev/null +++ b/Controllers/FaustusController/RGBController_Faustus_Linux.cpp @@ -0,0 +1,204 @@ +/*---------------------------------------------------------*\ +| RGBController_Faustus_Linux.cpp | +| | +| RGBController for Faustus devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "RGBController_Faustus_Linux.h" +#include "Detector.h" + +/**------------------------------------------------------------------*\ + @name ASUS TUF Keyboard (Faustus) + @category Keyboard + @type File Stream + @save :x: + @direct :x: + @effects :white_check_mark: + @detectors DetectFaustusControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_Faustus::RGBController_Faustus(const std::string& dev_path) +{ + name = "ASUS TUF Laptop Keyboard"; + vendor = "ASUS"; + type = DEVICE_TYPE_LAPTOP; + description = "Faustus Device"; + + modes.resize(4); + modes[0].name = "Static"; + modes[0].value = FAUSTUS_MODE_STATIC; + modes[0].flags = MODE_FLAG_HAS_PER_LED_COLOR; + modes[0].color_mode = MODE_COLORS_PER_LED; + + modes[1].name = "Breathing"; + modes[1].value = FAUSTUS_MODE_BREATHING; + modes[1].flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR; + modes[1].speed_min = FAUSTUS_SPEED_SLOWEST; + modes[1].speed_max = FAUSTUS_SPEED_FASTEST; + modes[1].color_mode = MODE_COLORS_PER_LED; + modes[1].speed = FAUSTUS_SPEED_NORMAL; + + modes[2].name = "Color Cycle"; + modes[2].value = FAUSTUS_MODE_COLOR_CYCLE; + modes[2].flags = MODE_FLAG_HAS_SPEED; + modes[2].speed_min = FAUSTUS_SPEED_SLOWEST; + modes[2].speed_max = FAUSTUS_SPEED_FASTEST; + modes[2].color_mode = MODE_COLORS_NONE; + modes[2].speed = FAUSTUS_SPEED_NORMAL; + + modes[3].name = "Strobe"; + modes[3].value = FAUSTUS_MODE_STROBE; + modes[3].flags = MODE_FLAG_HAS_PER_LED_COLOR; + modes[3].color_mode = MODE_COLORS_PER_LED; + + SetupZones(); + + // Prepare file streams + r_path = dev_path; + g_path = dev_path; + b_path = dev_path; + mode_path = dev_path; + flags_path = dev_path; + set_path = dev_path; + + r_path.append("/kbbl_red"); + g_path.append("/kbbl_green"); + b_path.append("/kbbl_blue"); + mode_path.append("/kbbl_mode"); + flags_path.append("/kbbl_flags"); + set_path.append("/kbbl_set"); +} + +void RGBController_Faustus::SetupZones() +{ + /*---------------------------------------------------------*\ + | Set up zone | + \*---------------------------------------------------------*/ + zones.resize(1); + zones[0].type = ZONE_TYPE_SINGLE; + zones[0].name = "Keyboard Backlight zone"; + zones[0].leds_min = 1; + zones[0].leds_max = 1; + zones[0].leds_count = 1; + zones[0].matrix_map = NULL; + + /*---------------------------------------------------------*\ + | Set up LED | + \*---------------------------------------------------------*/ + leds.resize(1); + leds[0].name = "Keyboard Backlight LED"; + + SetupColors(); +} + +void RGBController_Faustus::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_Faustus::DeviceUpdateLEDs() +{ + int rv = uint8_t(RGBGetRValue(colors[0])); + int gv = uint8_t(RGBGetGValue(colors[0])); + int bv = uint8_t(RGBGetBValue(colors[0])); + + std::ofstream str_r; + std::ofstream str_g; + std::ofstream str_b; + std::ofstream str_mode; + std::ofstream str_flags; + std::ofstream str_set; + + str_r.open(r_path, std::ios::out | std::ios::trunc); + str_g.open(g_path, std::ios::out | std::ios::trunc); + str_b.open(b_path, std::ios::out | std::ios::trunc); + str_mode.open(mode_path, std::ios::out | std::ios::trunc); + str_flags.open(flags_path, std::ios::out | std::ios::trunc); + str_set.open(set_path, std::ios::out | std::ios::trunc); + + str_r << std::hex; + str_g << std::hex; + str_b << std::hex; + str_mode << std::hex; + str_flags << std::hex; + str_set << std::hex; + + str_r << rv; + str_g << gv; + str_b << bv; + str_mode << active_mode; + str_flags << 0x2a; // All of em + str_set << 2; + + // Flush everything + str_r.close(); + str_g.close(); + str_b.close(); + str_mode.close(); + str_flags.close(); + str_set.close(); +} + +void RGBController_Faustus::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_Faustus::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_Faustus::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} + +void DetectFaustusControllers() +{ + const char* base_path = "/sys/devices/platform/faustus/kbbl"; + DIR* dir = opendir(base_path); + + if(!dir) + { + return; + } + + // Directory is present - we pretty much have a driver confirmation already, but double check for all files required just in case + struct dirent* dent = readdir(dir); + + if(!dent) + { + return; + } + + int found = 0; + while(dent) + { + const char* fname = dent->d_name; + if(!strcmp(fname, "kbbl_red") || !strcmp(fname, "kbbl_green") || !strcmp(fname, "kbbl_blue") || !strcmp(fname, "kbbl_mode") || !strcmp(fname, "kbbl_flags") || !strcmp(fname, "kbbl_set")) + { + ++found; + } + dent = readdir(dir); + } + + closedir(dir); + + if(found != 6) + { + return; + } + + ResourceManager::get()->RegisterRGBController(new RGBController_Faustus(base_path)); +} /* DetectFaustusControllers() */ + +REGISTER_DETECTOR("Faustus", DetectFaustusControllers); diff --git a/Controllers/FaustusController/RGBController_Faustus_Linux.h b/Controllers/FaustusController/RGBController_Faustus_Linux.h new file mode 100644 index 00000000..9cd231e3 --- /dev/null +++ b/Controllers/FaustusController/RGBController_Faustus_Linux.h @@ -0,0 +1,51 @@ +/*---------------------------------------------------------*\ +| RGBController_Faustus_Linux.h | +| | +| RGBController for Faustus devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" + +enum +{ + FAUSTUS_MODE_STATIC = 0, + FAUSTUS_MODE_BREATHING = 1, + FAUSTUS_MODE_COLOR_CYCLE = 2, + FAUSTUS_MODE_STROBE = 3 +}; +enum +{ + FAUSTUS_SPEED_SLOWEST = 0, + FAUSTUS_SPEED_NORMAL = 1, + FAUSTUS_SPEED_FASTEST = 2, +}; + +class RGBController_Faustus : public RGBController +{ + private: + std::string r_path; + std::string g_path; + std::string b_path; + std::string mode_path; + std::string flags_path; + std::string set_path; + + public: + RGBController_Faustus(const std::string& dev_path); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); +}; diff --git a/Controllers/GaiZongGaiKeyboardController/GaiZhongGaiController.cpp b/Controllers/GaiZongGaiKeyboardController/GaiZhongGaiController.cpp index 215cd811..3028a1b3 100644 --- a/Controllers/GaiZongGaiKeyboardController/GaiZhongGaiController.cpp +++ b/Controllers/GaiZongGaiKeyboardController/GaiZhongGaiController.cpp @@ -1,23 +1,32 @@ +/*---------------------------------------------------------*\ +| GaiZhongGaiController.cpp | +| | +| Driver for GaiZhongGai keyboard | +| | +| An Yang 24 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "GaiZhongGaiController.h" +#include "StringUtils.h" + /*---------------------------------------------------------------*\ -| GaiZhongGaiController.cpp | -| | | https://oshwlab.com/yangdsada/GaiZhongGai-Keyboard-68-4PRO | | https://oshwhub.com/myng/42-jian-pan | | https://oshwhub.com/hivisme/17jian-shuo-zi-xiao-jian-pan | | https://oshwhub.com/yangzen/xing-huo-2-qi-guang-ban-qu-dong- | | https://oshwhub.com/morempty/CH552gyin-liang-xuan-niu | -| | -| An Yang 2023/6/24 | \*---------------------------------------------------------------*/ -#include -#include "GaiZhongGaiController.h" -#include - -GaiZhongGaiKeyboardController::GaiZhongGaiKeyboardController(hid_device* dev_handle, hid_device_info* info) +GaiZhongGaiKeyboardController::GaiZhongGaiKeyboardController(hid_device* dev_handle, hid_device_info* info, std::string dev_name) { dev = dev_handle; location = info->path; + name = dev_name; usb_pid = info->product_id; /*-----------------------------------------------------*\ | Obtaining the Firmware Version | @@ -155,6 +164,11 @@ std::string GaiZhongGaiKeyboardController::GetDeviceLocation() return("HID: " + location); } +std::string GaiZhongGaiKeyboardController::GetNameString() +{ + return(name); +} + std::string GaiZhongGaiKeyboardController::GetSerialString() { wchar_t serial_string[128]; @@ -165,10 +179,7 @@ std::string GaiZhongGaiKeyboardController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } std::string GaiZhongGaiKeyboardController::GetVersion() diff --git a/Controllers/GaiZongGaiKeyboardController/GaiZhongGaiController.h b/Controllers/GaiZongGaiKeyboardController/GaiZhongGaiController.h index aa990498..0dcb01a9 100644 --- a/Controllers/GaiZongGaiKeyboardController/GaiZhongGaiController.h +++ b/Controllers/GaiZongGaiKeyboardController/GaiZhongGaiController.h @@ -1,22 +1,20 @@ -/*---------------------------------------------------------------*\ -| GaiZhongGaiController.h | -| | -| https://oshwlab.com/yangdsada/GaiZhongGai-Keyboard-68-4PRO | -| https://oshwhub.com/myng/42-jian-pan | -| https://oshwhub.com/hivisme/17jian-shuo-zi-xiao-jian-pan | -| https://oshwhub.com/yangzen/xing-huo-2-qi-guang-ban-qu-dong- | -| https://oshwhub.com/morempty/CH552gyin-liang-xuan-niu | -| | -| An Yang 2023/6/24 | -\*---------------------------------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| GaiZhongGaiController.h | +| | +| Driver for GaiZhongGai keyboard | +| | +| An Yang 24 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + /*-----------------------------------------------------*\ | GaiZhongGai vendor ID | \*-----------------------------------------------------*/ @@ -42,17 +40,18 @@ class GaiZhongGaiKeyboardController { public: - GaiZhongGaiKeyboardController(hid_device* dev_handle, hid_device_info* info); + GaiZhongGaiKeyboardController(hid_device* dev_handle, hid_device_info* info, std::string dev_name); ~GaiZhongGaiKeyboardController(); std::string GetDeviceLocation(); + std::string GetNameString(); std::string GetSerialString(); std::string GetVersion(); unsigned short GetUSBPID(); uint8_t* GetDataFlash(); uint16_t GetChannelLen(uint8_t ch); void SetChannelLen(uint8_t ch , uint16_t len); - + void SendColors ( unsigned char* color_data, @@ -62,6 +61,7 @@ public: private: hid_device* dev; std::string location; + std::string name; std::string version; unsigned short usb_pid; uint8_t data_flash[128]; diff --git a/Controllers/GaiZongGaiKeyboardController/GaiZhongGaiControllerDetect.cpp b/Controllers/GaiZongGaiKeyboardController/GaiZhongGaiControllerDetect.cpp index d1f56e96..4dc7e225 100644 --- a/Controllers/GaiZongGaiKeyboardController/GaiZhongGaiControllerDetect.cpp +++ b/Controllers/GaiZongGaiKeyboardController/GaiZhongGaiControllerDetect.cpp @@ -1,20 +1,18 @@ -/*---------------------------------------------------------------*\ -| GaiZhongGaiControllerDetect.cpp | -| | -| https://oshwlab.com/yangdsada/GaiZhongGai-Keyboard-68-4PRO | -| https://oshwhub.com/myng/42-jian-pan | -| https://oshwhub.com/hivisme/17jian-shuo-zi-xiao-jian-pan | -| https://oshwhub.com/yangzen/xing-huo-2-qi-guang-ban-qu-dong- | -| https://oshwhub.com/morempty/CH552gyin-liang-xuan-niu | -| | -| An Yang 2023/6/24 | -\*---------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| GaiZhongGaiControllerDetect.cpp | +| | +| Detector for GaiZhongGai keyboard | +| | +| An Yang 24 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include "Detector.h" #include "GaiZhongGaiController.h" -#include "RGBController.h" #include "RGBController_GaiZhongGai.h" -#include /******************************************************************************************\ * * @@ -27,11 +25,12 @@ void DetectGaiZhongGaiKeyboardControllers(hid_device_info* info, const std::string& name) { hid_device* dev = hid_open_path(info->path); - if( dev ) + + if(dev) { - GaiZhongGaiKeyboardController* controller = new GaiZhongGaiKeyboardController(dev, info); + GaiZhongGaiKeyboardController* controller = new GaiZhongGaiKeyboardController(dev, info, name); RGBController_GaiZhongGaiKeyboard* rgb_controller = new RGBController_GaiZhongGaiKeyboard(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } /* DetectGaiZhongGaiKeyboardControllers() */ diff --git a/Controllers/GaiZongGaiKeyboardController/RGBController_GaiZhongGai.cpp b/Controllers/GaiZongGaiKeyboardController/RGBController_GaiZhongGai.cpp index 3619f00a..7865a885 100644 --- a/Controllers/GaiZongGaiKeyboardController/RGBController_GaiZhongGai.cpp +++ b/Controllers/GaiZongGaiKeyboardController/RGBController_GaiZhongGai.cpp @@ -1,18 +1,18 @@ -/*---------------------------------------------------------------*\ -| RGBController_GaiZhongGai.cpp | -| | -| https://oshwlab.com/yangdsada/GaiZhongGai-Keyboard-68-4PRO | -| https://oshwhub.com/myng/42-jian-pan | -| https://oshwhub.com/hivisme/17jian-shuo-zi-xiao-jian-pan | -| https://oshwhub.com/yangzen/xing-huo-2-qi-guang-ban-qu-dong- | -| https://oshwhub.com/morempty/CH552gyin-liang-xuan-niu | -| | -| An Yang 2023/6/24 | -\*---------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GaiZhongGai.cpp | +| | +| RGBController for GaiZhongGai keyboard | +| | +| An Yang 24 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include "RGBController_GaiZhongGai.h" #include "RGBControllerKeyNames.h" -#include + using namespace std; //0xFFFFFFFF indicates an unused entry in matrix @@ -259,7 +259,7 @@ void board_led_xy_self_call return; temp = p_in[*offset]; - switch (temp >> 5) + switch(temp >> 5) { case 0x07://END return; @@ -272,7 +272,7 @@ void board_led_xy_self_call break; case 0x00://transferred meaning - switch (temp >> 3) + switch(temp >> 3) { case 0x01://square led_distance = 3.54f; @@ -281,7 +281,7 @@ void board_led_xy_self_call angle_step = pi / 4.0f; break; case 0x00://transferred meaning - if (temp >> 2 == 1)//regular triangle + if(temp >> 2 == 1)//regular triangle { led_distance = 2.8f; board_distance = 2.9f; @@ -293,18 +293,23 @@ void board_led_xy_self_call break; } //New center point coordinates - new_x = x + cos(angle) * (distance + board_distance); - new_y = y + sin(angle) * (distance + board_distance); + new_x = x + cosf(angle) * (distance + board_distance); + new_y = y + sinf(angle) * (distance + board_distance); //Rotate 180 degrees - if (angle > pi) + if(angle > pi) + { new_angle = angle - pi; + } else + { new_angle = angle + pi; - for (i = 1; i < range_num; i++) + } + + for(i = 1; i < range_num; i++) { new_angle -= angle_step;//clockwise - if (i & 1)//Is led + if(i & 1)//Is led { uint8_t x_u8 = (int16_t)(((new_x + cos(new_angle) * led_distance) * p_in[120] * 0.01f + 0.5f) / 1) - @@ -320,7 +325,7 @@ void board_led_xy_self_call } else//Is COM { - if (temp & (1 << (i / 2 - 1)))//child node + if(temp & (1 << (i / 2 - 1)))//child node { (*offset)++; board_led_xy_self_call( @@ -378,85 +383,67 @@ uint16_t LightBoard_init(uint8_t* p_in) RGBController_GaiZhongGaiKeyboard::RGBController_GaiZhongGaiKeyboard(GaiZhongGaiKeyboardController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; + name = controller->GetNameString(); switch(controller->GetUSBPID()) { - case GAIZHONGGAI_68_PRO_PID: - { - name = "GaiZhongGai Keyboard Device"; - type = DEVICE_TYPE_KEYBOARD; - description = "https://oshwhub.com/yangzen/zui-gai68-/"; - } - break; - case GAIZHONGGAI_42_PRO_PID: - { - name = "GaiZhongGai Keyboard Device"; - type = DEVICE_TYPE_KEYBOARD; - description = "https://oshwhub.com/myng/42-jian-pan/"; - } - break; - case GAIZHONGGAI_17_TOUCH_PRO_PID: - { - name = "GaiZhongGai Keyboard Device"; - type = DEVICE_TYPE_KEYPAD; - description = "https://oshwhub.com/yangzen/xing-huo-ji-hua-zui-gai-17-4-chu-mo-ji-xie-jian-pan-pro/"; - } - break; - case GAIZHONGGAI_17_PRO_PID: - { - name = "GaiZhongGai Keyboard Device"; - type = DEVICE_TYPE_KEYPAD; - description = "https://oshwhub.com/hivisme/17jian-shuo-zi-xiao-jian-pan/"; - } - break; - case GAIZHONGGAI_20_PRO_PID: - { - name = "GaiZhongGai Keyboard Device"; - type = DEVICE_TYPE_KEYPAD; - description = "https://oshwhub.com/runkuny/19keys_pad_normal/"; - } - break; - case GAIZHONGGAI_LIGHT_BOARD_PID: - { - name = "GaiZhongGai Controller Device"; - type = DEVICE_TYPE_ACCESSORY; - description = "https://oshwhub.com/yangzen/xing-huo-2-qi-guang-ban-qu-dong-/"; - } - break; - case GAIZHONGGAI_RGB_HUB_GREEN_PID: - { - name = "GaiZhongGai Controller Device"; - type = DEVICE_TYPE_LEDSTRIP; - description = "https://oshwhub.com/yangzen/album/gai-zhong-gai-jian-pan-ge-ji/"; - } - break; - case GAIZHONGGAI_RGB_HUB_BLUE_PID: - { - name = "GaiZhongGai Controller Device"; - type = DEVICE_TYPE_LEDSTRIP; - description = "https://oshwhub.com/yangzen/album/gai-zhong-gai-jian-pan-ge-ji/"; - } - break; - case GAIZHONGGAI_DIAL_PID: - { - name = "GaiZhongGai DIAL Device"; - type = DEVICE_TYPE_UNKNOWN; - description = "https://oshwhub.com/morempty/CH552gyin-liang-xuan-niu/"; - } - break; + case GAIZHONGGAI_68_PRO_PID: + type = DEVICE_TYPE_KEYBOARD; + description = "https://oshwhub.com/yangzen/zui-gai68-/"; + break; + + case GAIZHONGGAI_42_PRO_PID: + type = DEVICE_TYPE_KEYBOARD; + description = "https://oshwhub.com/myng/42-jian-pan/"; + break; + + case GAIZHONGGAI_17_TOUCH_PRO_PID: + type = DEVICE_TYPE_KEYPAD; + description = "https://oshwhub.com/yangzen/xing-huo-ji-hua-zui-gai-17-4-chu-mo-ji-xie-jian-pan-pro/"; + break; + + case GAIZHONGGAI_17_PRO_PID: + type = DEVICE_TYPE_KEYPAD; + description = "https://oshwhub.com/hivisme/17jian-shuo-zi-xiao-jian-pan/"; + break; + + case GAIZHONGGAI_20_PRO_PID: + type = DEVICE_TYPE_KEYPAD; + description = "https://oshwhub.com/runkuny/19keys_pad_normal/"; + break; + + case GAIZHONGGAI_LIGHT_BOARD_PID: + type = DEVICE_TYPE_ACCESSORY; + description = "https://oshwhub.com/yangzen/xing-huo-2-qi-guang-ban-qu-dong-/"; + break; + + case GAIZHONGGAI_RGB_HUB_GREEN_PID: + type = DEVICE_TYPE_LEDSTRIP; + description = "https://oshwhub.com/yangzen/album/gai-zhong-gai-jian-pan-ge-ji/"; + break; + + case GAIZHONGGAI_RGB_HUB_BLUE_PID: + type = DEVICE_TYPE_LEDSTRIP; + description = "https://oshwhub.com/yangzen/album/gai-zhong-gai-jian-pan-ge-ji/"; + break; + + case GAIZHONGGAI_DIAL_PID: + type = DEVICE_TYPE_UNKNOWN; + description = "https://oshwhub.com/morempty/CH552gyin-liang-xuan-niu/"; + break; } - vendor = "Yang"; - version = controller->GetVersion(); - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + vendor = "Yang"; + version = controller->GetVersion(); + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0xFFFF; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); SetupZones(); @@ -688,7 +675,7 @@ void RGBController_GaiZhongGaiKeyboard::ResizeZone(int zone, int new_size) void RGBController_GaiZhongGaiKeyboard::DeviceUpdateLEDs() { unsigned char colordata[1024 * 3]; - unsigned int data_size = colors.size(); + unsigned int data_size = (unsigned int)colors.size(); for(unsigned int color_idx = 0; color_idx < data_size; color_idx++) { diff --git a/Controllers/GaiZongGaiKeyboardController/RGBController_GaiZhongGai.h b/Controllers/GaiZongGaiKeyboardController/RGBController_GaiZhongGai.h index 813b8b6f..88f2608f 100644 --- a/Controllers/GaiZongGaiKeyboardController/RGBController_GaiZhongGai.h +++ b/Controllers/GaiZongGaiKeyboardController/RGBController_GaiZhongGai.h @@ -1,14 +1,13 @@ -/*---------------------------------------------------------------*\ -| RGBController_GaiZhongGai.h | -| | -| https://oshwlab.com/yangdsada/GaiZhongGai-Keyboard-68-4PRO | -| https://oshwhub.com/myng/42-jian-pan | -| https://oshwhub.com/hivisme/17jian-shuo-zi-xiao-jian-pan | -| https://oshwhub.com/yangzen/xing-huo-2-qi-guang-ban-qu-dong- | -| https://oshwhub.com/morempty/CH552gyin-liang-xuan-niu | -| | -| An Yang 2023/6/24 | -\*---------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GaiZhongGai.h | +| | +| RGBController for GaiZhongGai keyboard | +| | +| An Yang 24 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once #include "RGBController.h" @@ -22,7 +21,7 @@ public: void SetupZones(); void ResizeZone(int zone, int new_size); - + void DeviceUpdateLEDs(); void UpdateZoneLEDs(int zone); void UpdateSingleLED(int led); diff --git a/Controllers/GainwardGPUController/GainwardGPUControllerDetect.cpp b/Controllers/GainwardGPUController/GainwardGPUControllerDetect.cpp index f0a134a1..b39a8e4a 100644 --- a/Controllers/GainwardGPUController/GainwardGPUControllerDetect.cpp +++ b/Controllers/GainwardGPUController/GainwardGPUControllerDetect.cpp @@ -1,23 +1,22 @@ -/*-----------------------------------------*\ -| GainwardGPUControllerDetect.cpp | -| | -| Driver for Gainward RGB on GPUs | -| | -| TheRogueZeta 11/05/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| GainwardGPUControllerDetect.cpp | +| | +| Detector for Gainward GPU | +| | +| TheRogueZeta 05 Nov 2020 | +| KundaPanda 04 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "Detector.h" #include "GainwardGPUv1Controller.h" #include "GainwardGPUv2Controller.h" -#include "LogManager.h" -#include "RGBController.h" #include "RGBController_GainwardGPUv1.h" #include "RGBController_GainwardGPUv2.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include /******************************************************************************************\ * * @@ -78,9 +77,8 @@ void DetectGainwardGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, co \*-----------------------------------------------------------------*/ case 0x08: { - GainwardGPUv1Controller* controller = new GainwardGPUv1Controller(bus, i2c_addr); + GainwardGPUv1Controller* controller = new GainwardGPUv1Controller(bus, i2c_addr, name); RGBController_GainwardGPUv1* rgb_controller = new RGBController_GainwardGPUv1(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -91,10 +89,9 @@ void DetectGainwardGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, co \*-----------------------------------------------------------------*/ case 0x49: { - GainwardGPUv2Controller* controller = new GainwardGPUv2Controller(bus, i2c_addr); + GainwardGPUv2Controller* controller = new GainwardGPUv2Controller(bus, i2c_addr, name); RGBController_GainwardGPUv2* rgb_controller = new RGBController_GainwardGPUv2(controller); - rgb_controller->name = name; - + ResourceManager::get()->RegisterRGBController(rgb_controller); } break; @@ -102,12 +99,15 @@ void DetectGainwardGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, co } } /* DetectGainwardGPUControllers() */ -REGISTER_I2C_PCI_DETECTOR("Gainward GTX 1080 Phoenix" , DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, GAINWARD_SUB_VEN, GAINWARD_GTX_1080_PHOENIX, 0x08); -REGISTER_I2C_PCI_DETECTOR("Gainward GTX 1080 Ti Phoenix" , DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, GAINWARD_SUB_VEN, GAINWARD_GTX_1080_TI_PHOENIX, 0x08); -REGISTER_I2C_PCI_DETECTOR("Gainward RTX 2070 Super Phantom", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX2070S_OC_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Gainward RTX 2080 Phoenix GS" , DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX2080_A_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Gainward RTX 3070 Phoenix" , DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3070_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Gainward RTX 3070 Ti Phoenix" , DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3070TI_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Gainward RTX 3080 Phoenix" , DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3080_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Gainward RTX 3080 Ti Phoenix" , DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3080TI_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Gainward RTX 3090 Phoenix" , DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3090_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Gainward GeForce GTX 1080 Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, GAINWARD_SUB_VEN, GAINWARD_GTX_1080_PHOENIX, 0x08); +REGISTER_I2C_PCI_DETECTOR("Gainward GeForce GTX 1080 Ti Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, GAINWARD_SUB_VEN, GAINWARD_GTX_1080TI_PHOENIX, 0x08); +REGISTER_I2C_PCI_DETECTOR("Gainward GeForce GTX 1660 SUPER Ghost", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660S_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1660S_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 2070 SUPER Phantom", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX2070S_OC_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 2080 Phoenix GS", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX2080_A_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3070 Phantom", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, GAINWARD_SUB_VEN, GAINWARD_RTX_3070_PHANTOM, 0x49); +REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3070 Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3070_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3070 Ti Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3070TI_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3080 Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3080_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3080 Ti Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3080TI_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3090 Phoenix", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, GAINWARD_SUB_VEN, NVIDIA_RTX3090_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Gainward GeForce RTX 3090 Ti Phantom", DetectGainwardGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, GAINWARD_SUB_VEN, GAINWARD_RTX_3090TI_PHANTOM, 0x49); diff --git a/Controllers/GainwardGPUController/GainwardGPUv1Controller.cpp b/Controllers/GainwardGPUController/GainwardGPUv1Controller.cpp deleted file mode 100644 index 38c843fe..00000000 --- a/Controllers/GainwardGPUController/GainwardGPUv1Controller.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/*-----------------------------------------*\ -| GainwardGPUv1Controller.cpp | -| | -| Driver for Gainward RGB v1 on GPUs | -| | -| TheRogueZeta 11/05/2020 | -\*-----------------------------------------*/ - -#include "GainwardGPUv1Controller.h" -#include - -GainwardGPUv1Controller::GainwardGPUv1Controller(i2c_smbus_interface* bus, gainward_gpu_dev_id dev) -{ - this->bus = bus; - this->dev = dev; -} - -GainwardGPUv1Controller::~GainwardGPUv1Controller() -{ - -} - -std::string GainwardGPUv1Controller::GetDeviceLocation() -{ - std::string return_string(bus->device_name); - char addr[5]; - snprintf(addr, 5, "0x%02X", dev); - return_string.append(", address "); - return_string.append(addr); - return("I2C: " + return_string); -} - -unsigned char GainwardGPUv1Controller::GetLEDRed() -{ - return(GainwardGPURegisterRead(GAINWARD_RED_REGISTER)); -} - -unsigned char GainwardGPUv1Controller::GetLEDGreen() -{ - return(GainwardGPURegisterRead(GAINWARD_GREEN_REGISTER)); -} - -unsigned char GainwardGPUv1Controller::GetLEDBlue() -{ - return(GainwardGPURegisterRead(GAINWARD_BLUE_REGISTER)); -} - -void GainwardGPUv1Controller::SetLEDColors(unsigned char red, unsigned char green, unsigned char blue) -{ - GainwardGPURegisterWrite(GAINWARD_RED_REGISTER, red); - GainwardGPURegisterWrite(GAINWARD_GREEN_REGISTER, green); - GainwardGPURegisterWrite(GAINWARD_BLUE_REGISTER, blue); - GainwardGPURegisterWrite(GAINWARD_06_REGISTER, 0xFF); -} - -void GainwardGPUv1Controller::SetMode() -{ - -} - -unsigned char GainwardGPUv1Controller::GainwardGPURegisterRead(unsigned char reg) -{ - return(bus->i2c_smbus_read_byte_data(dev, reg)); -} - -void GainwardGPUv1Controller::GainwardGPURegisterWrite(unsigned char reg, unsigned char val) -{ - bus->i2c_smbus_write_byte_data(dev, reg, val); -} diff --git a/Controllers/GainwardGPUController/GainwardGPUv1Controller.h b/Controllers/GainwardGPUController/GainwardGPUv1Controller.h deleted file mode 100644 index 1d380ba1..00000000 --- a/Controllers/GainwardGPUController/GainwardGPUv1Controller.h +++ /dev/null @@ -1,44 +0,0 @@ -/*-----------------------------------------*\ -| GainwardGPUController.h | -| | -| Driver for Gainward RGB v1 on GPUs | -| | -| TheRogueZeta 11/05/2020 | -\*-----------------------------------------*/ - -#include -#include "i2c_smbus.h" - -#pragma once - -typedef unsigned char gainward_gpu_dev_id; - -enum -{ - /* RGB Registers */ - GAINWARD_RED_REGISTER = 0x03, /* Red Register */ - GAINWARD_GREEN_REGISTER = 0x04, /* Green Register */ - GAINWARD_BLUE_REGISTER = 0x05, /* Blue Register */ - GAINWARD_06_REGISTER = 0x06, /* Unknown (Brightness/Mode?) Register */ -}; - -class GainwardGPUv1Controller -{ -public: - GainwardGPUv1Controller(i2c_smbus_interface* bus, gainward_gpu_dev_id); - ~GainwardGPUv1Controller(); - - std::string GetDeviceLocation(); - unsigned char GetLEDRed(); - unsigned char GetLEDGreen(); - unsigned char GetLEDBlue(); - void SetLEDColors(unsigned char red, unsigned char green, unsigned char blue); - void SetMode(); - - unsigned char GainwardGPURegisterRead(unsigned char reg); - void GainwardGPURegisterWrite(unsigned char reg, unsigned char val); - -private: - i2c_smbus_interface * bus; - gainward_gpu_dev_id dev; -}; diff --git a/Controllers/GainwardGPUController/GainwardGPUv1Controller/GainwardGPUv1Controller.cpp b/Controllers/GainwardGPUController/GainwardGPUv1Controller/GainwardGPUv1Controller.cpp new file mode 100644 index 00000000..b2e174b2 --- /dev/null +++ b/Controllers/GainwardGPUController/GainwardGPUv1Controller/GainwardGPUv1Controller.cpp @@ -0,0 +1,78 @@ +/*---------------------------------------------------------*\ +| GainwardGPUv1Controller.cpp | +| | +| Driver for Gainward v1 GPU | +| | +| TheRogueZeta 05 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "GainwardGPUv1Controller.h" + +GainwardGPUv1Controller::GainwardGPUv1Controller(i2c_smbus_interface* bus, gainward_gpu_dev_id dev, std::string dev_name) +{ + this->bus = bus; + this->dev = dev; + this->name = dev_name; +} + +GainwardGPUv1Controller::~GainwardGPUv1Controller() +{ + +} + +std::string GainwardGPUv1Controller::GetDeviceLocation() +{ + std::string return_string(bus->device_name); + char addr[5]; + snprintf(addr, 5, "0x%02X", dev); + return_string.append(", address "); + return_string.append(addr); + return("I2C: " + return_string); +} + +std::string GainwardGPUv1Controller::GetDeviceName() +{ + return(name); +} + +unsigned char GainwardGPUv1Controller::GetLEDRed() +{ + return(GainwardGPURegisterRead(GAINWARD_RED_REGISTER)); +} + +unsigned char GainwardGPUv1Controller::GetLEDGreen() +{ + return(GainwardGPURegisterRead(GAINWARD_GREEN_REGISTER)); +} + +unsigned char GainwardGPUv1Controller::GetLEDBlue() +{ + return(GainwardGPURegisterRead(GAINWARD_BLUE_REGISTER)); +} + +void GainwardGPUv1Controller::SetLEDColors(unsigned char red, unsigned char green, unsigned char blue) +{ + GainwardGPURegisterWrite(GAINWARD_RED_REGISTER, red); + GainwardGPURegisterWrite(GAINWARD_GREEN_REGISTER, green); + GainwardGPURegisterWrite(GAINWARD_BLUE_REGISTER, blue); + GainwardGPURegisterWrite(GAINWARD_06_REGISTER, 0xFF); +} + +void GainwardGPUv1Controller::SetMode() +{ + +} + +unsigned char GainwardGPUv1Controller::GainwardGPURegisterRead(unsigned char reg) +{ + return(bus->i2c_smbus_read_byte_data(dev, reg)); +} + +void GainwardGPUv1Controller::GainwardGPURegisterWrite(unsigned char reg, unsigned char val) +{ + bus->i2c_smbus_write_byte_data(dev, reg, val); +} diff --git a/Controllers/GainwardGPUController/GainwardGPUv1Controller/GainwardGPUv1Controller.h b/Controllers/GainwardGPUController/GainwardGPUv1Controller/GainwardGPUv1Controller.h new file mode 100644 index 00000000..08d92255 --- /dev/null +++ b/Controllers/GainwardGPUController/GainwardGPUv1Controller/GainwardGPUv1Controller.h @@ -0,0 +1,50 @@ +/*---------------------------------------------------------*\ +| GainwardGPUv1Controller.h | +| | +| Driver for Gainward v1 GPU | +| | +| TheRogueZeta 05 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "i2c_smbus.h" + +typedef unsigned char gainward_gpu_dev_id; + +enum +{ + /* RGB Registers */ + GAINWARD_RED_REGISTER = 0x03, /* Red Register */ + GAINWARD_GREEN_REGISTER = 0x04, /* Green Register */ + GAINWARD_BLUE_REGISTER = 0x05, /* Blue Register */ + GAINWARD_06_REGISTER = 0x06, /* Unknown (Brightness/Mode?) Register */ +}; + +class GainwardGPUv1Controller +{ +public: + GainwardGPUv1Controller(i2c_smbus_interface* bus, gainward_gpu_dev_id, std::string dev_name); + ~GainwardGPUv1Controller(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + + unsigned char GetLEDRed(); + unsigned char GetLEDGreen(); + unsigned char GetLEDBlue(); + void SetLEDColors(unsigned char red, unsigned char green, unsigned char blue); + void SetMode(); + + unsigned char GainwardGPURegisterRead(unsigned char reg); + void GainwardGPURegisterWrite(unsigned char reg, unsigned char val); + +private: + i2c_smbus_interface * bus; + gainward_gpu_dev_id dev; + std::string name; +}; diff --git a/Controllers/GainwardGPUController/RGBController_GainwardGPUv1.cpp b/Controllers/GainwardGPUController/GainwardGPUv1Controller/RGBController_GainwardGPUv1.cpp similarity index 79% rename from Controllers/GainwardGPUController/RGBController_GainwardGPUv1.cpp rename to Controllers/GainwardGPUController/GainwardGPUv1Controller/RGBController_GainwardGPUv1.cpp index 982c8ccc..f32e653f 100644 --- a/Controllers/GainwardGPUController/RGBController_GainwardGPUv1.cpp +++ b/Controllers/GainwardGPUController/GainwardGPUv1Controller/RGBController_GainwardGPUv1.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_GainwardGPUv1.cpp | -| | -| Driver for Gainward RGB v1 on GPUs | -| | -| TheRogueZeta 11/05/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GainwardGPUv1.cpp | +| | +| RGBController for Gainward v1 GPU | +| | +| TheRogueZeta 05 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_GainwardGPUv1.h" @@ -29,10 +32,10 @@ RGBController_GainwardGPUv1::RGBController_GainwardGPUv1(GainwardGPUv1Controller { controller = controller_ptr; - name = "Gainward GPU"; + name = controller->GetDeviceName(); vendor = "Gainward"; type = DEVICE_TYPE_GPU; - description = "Gainward GTX GPU"; + description = "Gainward GPU V1 Device"; location = controller->GetDeviceLocation(); mode Direct; diff --git a/Controllers/GainwardGPUController/GainwardGPUv1Controller/RGBController_GainwardGPUv1.h b/Controllers/GainwardGPUController/GainwardGPUv1Controller/RGBController_GainwardGPUv1.h new file mode 100644 index 00000000..c084be2c --- /dev/null +++ b/Controllers/GainwardGPUController/GainwardGPUv1Controller/RGBController_GainwardGPUv1.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------*\ +| RGBController_GainwardGPUv1.h | +| | +| RGBController for Gainward v1 GPU | +| | +| TheRogueZeta 05 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "GainwardGPUv1Controller.h" + +class RGBController_GainwardGPUv1 : public RGBController +{ +public: + RGBController_GainwardGPUv1(GainwardGPUv1Controller* controller_ptr); + ~RGBController_GainwardGPUv1(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + GainwardGPUv1Controller* controller; + + int GetDeviceMode(); +}; diff --git a/Controllers/GainwardGPUController/GainwardGPUv2Controller.cpp b/Controllers/GainwardGPUController/GainwardGPUv2Controller/GainwardGPUv2Controller.cpp similarity index 79% rename from Controllers/GainwardGPUController/GainwardGPUv2Controller.cpp rename to Controllers/GainwardGPUController/GainwardGPUv2Controller/GainwardGPUv2Controller.cpp index 8595a37f..22fa8ed2 100644 --- a/Controllers/GainwardGPUController/GainwardGPUv2Controller.cpp +++ b/Controllers/GainwardGPUController/GainwardGPUv2Controller/GainwardGPUv2Controller.cpp @@ -1,18 +1,22 @@ -/*-----------------------------------------*\ -| GainwardGPUv2Controller.cpp | -| | -| Driver for Gainward RGB v2 on GPUs | -| | -| KundaPanda 01/04/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| GainwardGPUv2Controller.cpp | +| | +| Driver for Gainward v2 GPU | +| | +| KundaPanda 04 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "GainwardGPUv2Controller.h" #include +#include "GainwardGPUv2Controller.h" -GainwardGPUv2Controller::GainwardGPUv2Controller(i2c_smbus_interface* bus, gainward_gpu_dev_id dev) +GainwardGPUv2Controller::GainwardGPUv2Controller(i2c_smbus_interface* bus, gainward_gpu_dev_id dev, std::string dev_name) { - this->bus = bus; - this->dev = dev; + this->bus = bus; + this->dev = dev; + this->name = dev_name; } GainwardGPUv2Controller::~GainwardGPUv2Controller() = default; @@ -27,6 +31,11 @@ std::string GainwardGPUv2Controller::GetDeviceLocation() return("I2C: " + return_string); } +std::string GainwardGPUv2Controller::GetDeviceName() +{ + return(name); +} + unsigned char GainwardGPUv2Controller::GetLEDRed() { return(bus->i2c_smbus_read_byte_data(dev, GAINWARD_V2_RED_REGISTER)); diff --git a/Controllers/GainwardGPUController/GainwardGPUv2Controller.h b/Controllers/GainwardGPUController/GainwardGPUv2Controller/GainwardGPUv2Controller.h similarity index 83% rename from Controllers/GainwardGPUController/GainwardGPUv2Controller.h rename to Controllers/GainwardGPUController/GainwardGPUv2Controller/GainwardGPUv2Controller.h index 40567112..94ab4564 100644 --- a/Controllers/GainwardGPUController/GainwardGPUv2Controller.h +++ b/Controllers/GainwardGPUController/GainwardGPUv2Controller/GainwardGPUv2Controller.h @@ -1,16 +1,19 @@ -/*-----------------------------------------*\ -| GainwardGPUv2Controller.h | -| | -| Driver for Gainward RGB v2 on GPUs | -| | -| KundaPanda 01/04/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| GainwardGPUv2Controller.h | +| | +| Driver for Gainward v2 GPU | +| | +| KundaPanda 04 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" -#pragma once - typedef unsigned char gainward_gpu_dev_id; /*---------------------------------------------------------------------------------*\ @@ -77,10 +80,12 @@ enum class GainwardGPUv2Controller { public: - GainwardGPUv2Controller(i2c_smbus_interface* bus, gainward_gpu_dev_id); + GainwardGPUv2Controller(i2c_smbus_interface* bus, gainward_gpu_dev_id, std::string dev_name); ~GainwardGPUv2Controller(); std::string GetDeviceLocation(); + std::string GetDeviceName(); + unsigned char GetLEDRed(); unsigned char GetLEDGreen(); unsigned char GetLEDBlue(); @@ -92,4 +97,5 @@ public: private: i2c_smbus_interface * bus; gainward_gpu_dev_id dev; + std::string name; }; diff --git a/Controllers/GainwardGPUController/RGBController_GainwardGPUv2.cpp b/Controllers/GainwardGPUController/GainwardGPUv2Controller/RGBController_GainwardGPUv2.cpp similarity index 87% rename from Controllers/GainwardGPUController/RGBController_GainwardGPUv2.cpp rename to Controllers/GainwardGPUController/GainwardGPUv2Controller/RGBController_GainwardGPUv2.cpp index 7ba7bf89..a2df84b8 100644 --- a/Controllers/GainwardGPUController/RGBController_GainwardGPUv2.cpp +++ b/Controllers/GainwardGPUController/GainwardGPUv2Controller/RGBController_GainwardGPUv2.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_GainwardGPUv2.cpp | -| | -| Driver for Gainward RGB v2 on GPUs | -| | -| KundaPanda 01/04/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GainwardGPUv2.cpp | +| | +| RGBController for Gainward v2 GPU | +| | +| KundaPanda 04 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_GainwardGPUv2.h" @@ -23,10 +26,10 @@ RGBController_GainwardGPUv2::RGBController_GainwardGPUv2(GainwardGPUv2Controller { controller = controller_ptr; - name = "Gainward GPU"; + name = controller->GetDeviceName(); vendor = "Gainward"; type = DEVICE_TYPE_GPU; - description = "Gainward RTX GPU"; + description = "Gainward GPU V2 Device"; location = controller->GetDeviceLocation(); mode Static; @@ -145,11 +148,6 @@ void RGBController_GainwardGPUv2::UpdateSingleLED(int /*led*/) DeviceUpdateLEDs(); } -void RGBController_GainwardGPUv2::SetCustomMode() -{ - active_mode = 0; -} - void RGBController_GainwardGPUv2::DeviceUpdateMode() { mode current_mode = modes[(unsigned int)active_mode]; diff --git a/Controllers/GainwardGPUController/GainwardGPUv2Controller/RGBController_GainwardGPUv2.h b/Controllers/GainwardGPUController/GainwardGPUv2Controller/RGBController_GainwardGPUv2.h new file mode 100644 index 00000000..5dd58b0d --- /dev/null +++ b/Controllers/GainwardGPUController/GainwardGPUv2Controller/RGBController_GainwardGPUv2.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_GainwardGPUv2.h | +| | +| RGBController for Gainward v2 GPU | +| | +| KundaPanda 04 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "GainwardGPUv2Controller.h" + +class RGBController_GainwardGPUv2 : public RGBController +{ +public: + RGBController_GainwardGPUv2(GainwardGPUv2Controller* controller_ptr); + ~RGBController_GainwardGPUv2(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + GainwardGPUv2Controller* controller; +}; diff --git a/Controllers/GainwardGPUController/RGBController_GainwardGPUv1.h b/Controllers/GainwardGPUController/RGBController_GainwardGPUv1.h deleted file mode 100644 index 09fa89e3..00000000 --- a/Controllers/GainwardGPUController/RGBController_GainwardGPUv1.h +++ /dev/null @@ -1,34 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_GainwardGPU.h | -| | -| Driver for Gainward RGB v1 on GPUs | -| | -| TheRogueZeta 11/05/2020 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "GainwardGPUv1Controller.h" - -class RGBController_GainwardGPUv1 : public RGBController -{ -public: - RGBController_GainwardGPUv1(GainwardGPUv1Controller* controller_ptr); - ~RGBController_GainwardGPUv1(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - GainwardGPUv1Controller* controller; - - int GetDeviceMode(); -}; diff --git a/Controllers/GainwardGPUController/RGBController_GainwardGPUv2.h b/Controllers/GainwardGPUController/RGBController_GainwardGPUv2.h deleted file mode 100644 index 0d1c0a00..00000000 --- a/Controllers/GainwardGPUController/RGBController_GainwardGPUv2.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_GainwardGPUv2.h | -| | -| Driver for Gainward RGB v2 on GPUs | -| | -| KundaPanda 01/04/2021 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "GainwardGPUv2Controller.h" - -class RGBController_GainwardGPUv2 : public RGBController -{ -public: - RGBController_GainwardGPUv2(GainwardGPUv2Controller* controller_ptr); - ~RGBController_GainwardGPUv2(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void SetCustomMode(); - void DeviceUpdateMode(); - -private: - GainwardGPUv2Controller* controller; -}; diff --git a/Controllers/GalaxGPUController/GalaxGPUController.cpp b/Controllers/GalaxGPUController/GalaxGPUController.cpp deleted file mode 100644 index 106e2879..00000000 --- a/Controllers/GalaxGPUController/GalaxGPUController.cpp +++ /dev/null @@ -1,106 +0,0 @@ -/*-----------------------------------------*\ -| GalaxGPUController.cpp | -| | -| Driver for Galax / KFA2 RGB on GPUs | -| | -| Niels Westphal (crashniels) 12.07.2020 | -\*-----------------------------------------*/ - -#include "GalaxGPUController.h" -#include - -GalaxGPUController::GalaxGPUController(i2c_smbus_interface* bus, galax_gpu_dev_id dev) -{ - this->bus = bus; - this->dev = dev; - - strcpy(device_name, "Galax RTX GPU"); // Would be nice to get the actual GPU name. Using this as a placeholder. -} - -GalaxGPUController::~GalaxGPUController() -{ - -} - -std::string GalaxGPUController::GetDeviceName() -{ - return(device_name); -} - -std::string GalaxGPUController::GetDeviceLocation() -{ - std::string return_string(bus->device_name); - char addr[5]; - snprintf(addr, 5, "0x%02X", dev); - return_string.append(", address "); - return_string.append(addr); - return("I2C: " + return_string); -} - -unsigned char GalaxGPUController::GetLEDRed() -{ - return(GalaxGPURegisterRead(GALAX_RED_REGISTER)); -} - -unsigned char GalaxGPUController::GetLEDGreen() -{ - return(GalaxGPURegisterRead(GALAX_GREEN_REGISTER)); -} - -unsigned char GalaxGPUController::GetLEDBlue() -{ - return(GalaxGPURegisterRead(GALAX_BLUE_REGISTER)); -} - -void GalaxGPUController::SetLEDColorsDirect(unsigned char red, unsigned char green, unsigned char blue) // Direct Mode is just Static Mode without applying color changes -{ - GalaxGPURegisterWrite(GALAX_RED_REGISTER, red); - GalaxGPURegisterWrite(GALAX_GREEN_REGISTER, green); - GalaxGPURegisterWrite(GALAX_BLUE_REGISTER, blue); -} - -void GalaxGPUController::SetLEDColorsEffect(unsigned char red, unsigned char green, unsigned char blue) -{ - GalaxGPURegisterWrite(GALAX_RED_REGISTER, red); - GalaxGPURegisterWrite(GALAX_GREEN_REGISTER, green); - GalaxGPURegisterWrite(GALAX_BLUE_REGISTER, blue); -} - -void GalaxGPUController::SetMode(unsigned char mode) -{ - switch(mode) - { - case 1: - GalaxGPURegisterWrite(GALAX_MODE_REGISTER_1, GALAX_MODE_STATIC_VALUE_1); - GalaxGPURegisterWrite(GALAX_MODE_REGISTER_2, GALAX_MODE_STATIC_VALUE_2); - break; - - case 2: - GalaxGPURegisterWrite(GALAX_MODE_REGISTER_1, GALAX_MODE_BREATHING_VALUE_1); - GalaxGPURegisterWrite(GALAX_MODE_REGISTER_2, GALAX_MODE_BREATHING_VALUE_2); - break; - - case 3: - GalaxGPURegisterWrite(GALAX_MODE_REGISTER_1, GALAX_MODE_RAINBOW_VALUE_1); - GalaxGPURegisterWrite(GALAX_MODE_REGISTER_2, GALAX_MODE_RAINBOW_VALUE_2); - break; - - case 4: - GalaxGPURegisterWrite(GALAX_MODE_REGISTER_1, GALAX_MODE_CYCLE_BREATHING_VALUE_1); - GalaxGPURegisterWrite(GALAX_MODE_REGISTER_2, GALAX_MODE_CYCLE_BREATHING_VALUE_2); - break; - - default: - break; - } -} - -unsigned char GalaxGPUController::GalaxGPURegisterRead(unsigned char reg) -{ - return(bus->i2c_smbus_read_byte_data(dev, reg)); -} - -void GalaxGPUController::GalaxGPURegisterWrite(unsigned char reg, unsigned char val) -{ - bus->i2c_smbus_write_byte_data(dev, reg, val); -} diff --git a/Controllers/GalaxGPUController/GalaxGPUController.h b/Controllers/GalaxGPUController/GalaxGPUController.h deleted file mode 100644 index 3886b66c..00000000 --- a/Controllers/GalaxGPUController/GalaxGPUController.h +++ /dev/null @@ -1,67 +0,0 @@ -/*-----------------------------------------*\ -| GalaxGPUController.h | -| | -| Driver for Galax / KFA2 RGB on GPUs | -| | -| Niels Westphal (crashniels) 12.07.2020 | -\*-----------------------------------------*/ - -#include -#include "i2c_smbus.h" - -#pragma once - -typedef unsigned char galax_gpu_dev_id; - -enum -{ - /* RGB Registers */ - GALAX_RED_REGISTER = 0x02, /* Red Register */ - GALAX_GREEN_REGISTER = 0x03, /* Green Register */ - GALAX_BLUE_REGISTER = 0x04, /* Blue Register */ - /* MODE Registers */ - GALAX_MODE_REGISTER_1 = 0x05, /* Mode Register 1 */ - GALAX_MODE_REGISTER_2 = 0x06, /* Mode Register 2 */ -}; - -enum -{ - /* Static Mode Values */ - GALAX_MODE_STATIC_VALUE_1 = 0x00, - GALAX_MODE_STATIC_VALUE_2 = 0x01, - /* Breathing Mode Values */ - GALAX_MODE_BREATHING_VALUE_1 = 0x04, - GALAX_MODE_BREATHING_VALUE_2 = 0x00, - /* Rainbow Mode Values */ - GALAX_MODE_RAINBOW_VALUE_1 = 0x84, - GALAX_MODE_RAINBOW_VALUE_2 = 0x02, - /* Cycle Breathing Mode Values */ - GALAX_MODE_CYCLE_BREATHING_VALUE_1 = 0x84, - GALAX_MODE_CYCLE_BREATHING_VALUE_2 = 0x40, -}; - -class GalaxGPUController -{ -public: - GalaxGPUController(i2c_smbus_interface* bus, galax_gpu_dev_id); - ~GalaxGPUController(); - - std::string GetDeviceName(); - std::string GetDeviceLocation(); - unsigned char GetLEDRed(); - unsigned char GetLEDGreen(); - unsigned char GetLEDBlue(); - void SetLEDColorsDirect(unsigned char red, unsigned char green, unsigned char blue); - void SetLEDColorsEffect(unsigned char red, unsigned char green, unsigned char blue); - void SetMode(unsigned char mode); - - unsigned char GalaxGPURegisterRead(unsigned char reg); - void GalaxGPURegisterWrite(unsigned char reg, unsigned char val); - - bool direct = false; // Temporary solution to check if we are in "Direct" mode - -private: - char device_name[16]; - i2c_smbus_interface * bus; - galax_gpu_dev_id dev; -}; diff --git a/Controllers/GalaxGPUController/GalaxGPUControllerDetect.cpp b/Controllers/GalaxGPUController/GalaxGPUControllerDetect.cpp index c6c2ad06..961b5b2c 100644 --- a/Controllers/GalaxGPUController/GalaxGPUControllerDetect.cpp +++ b/Controllers/GalaxGPUController/GalaxGPUControllerDetect.cpp @@ -1,21 +1,21 @@ -/*-----------------------------------------*\ -| GalaxGPUControllerDetect.cpp | -| | -| Driver for Galax / KFA2 RGB on GPUs | -| | -| Niels Westphal (crashniels) 12.07.2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| GalaxGPUControllerDetect.cpp | +| | +| Detector for Galax/KFA2 GPU | +| | +| Niels Westphal (crashniels) 12 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "Detector.h" -#include "GalaxGPUController.h" -#include "LogManager.h" -#include "RGBController.h" -#include "RGBController_GalaxGPU.h" +#include "GalaxGPUv1Controller.h" +#include "GalaxGPUv2Controller.h" +#include "RGBController_GalaxGPUv1.h" +#include "RGBController_GalaxGPUv2.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include /******************************************************************************************\ * * @@ -28,17 +28,44 @@ bool TestForGalaxGPUController(i2c_smbus_interface* bus, unsigned char address) { bool pass = false; + unsigned char res; - unsigned char res = bus->i2c_smbus_read_byte_data(address, 0x00); - unsigned char res2 = bus->i2c_smbus_read_byte_data(address, 0x01); - - if(res == 0x27 && res2 == 0x10) + switch (address) { - pass = true; + /*-----------------------------------------------------------------*\ + | V1 Controller | + \*-----------------------------------------------------------------*/ + case 0x32: + res = bus->i2c_smbus_read_byte_data(address, 0x00); + if(res == 0x27 || res == 0x26) { + res = bus->i2c_smbus_read_byte_data(address, 0x01); + if (res == 0x10 || res == 0x20) + pass = true; + } + break; + + /*-----------------------------------------------------------------*\ + | V1 Controller - RTX 3080 | + \*-----------------------------------------------------------------*/ + case 0x23: + res = bus->i2c_smbus_read_byte_data(address, 0x00); + if(res == 0x30) + { + pass = true; + } + break; + + /*-----------------------------------------------------------------*\ + | V2 Controller | + \*-----------------------------------------------------------------*/ + case 0x51: + res = bus->i2c_smbus_read_byte_data(address, 0x00); + if (res == 0x80) + pass = true; + break; } return(pass); - } /* TestForGalaxGPUController() */ @@ -54,16 +81,41 @@ void DetectGalaxGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const { if(TestForGalaxGPUController(bus, i2c_addr)) { - GalaxGPUController* controller = new GalaxGPUController(bus, i2c_addr); - RGBController_GalaxGPU* rgb_controller = new RGBController_GalaxGPU(controller); - rgb_controller->name = name; + switch(i2c_addr) + { + /*-----------------------------------------------------------------*\ + | V1 Controller | + \*-----------------------------------------------------------------*/ + case 0x32: + case 0x23: + { + GalaxGPUv1Controller* controller = new GalaxGPUv1Controller(bus, i2c_addr, name); + RGBController_GalaxGPUv1* rgb_controller = new RGBController_GalaxGPUv1(controller); - ResourceManager::get()->RegisterRGBController(rgb_controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + break; + + /*-----------------------------------------------------------------*\ + | V2 Controller | + \*-----------------------------------------------------------------*/ + case 0x51: + { + GalaxGPUv2Controller* controller = new GalaxGPUv2Controller(bus, i2c_addr, name); + RGBController_GalaxGPUv2* rgb_controller = new RGBController_GalaxGPUv2(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + break; + } } } /* DetectGalaxGPUControllers() */ -REGISTER_I2C_PCI_DETECTOR("KFA2 RTX 2070 EX", DetectGalaxGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_DEV, NVIDIA_SUB_VEN, KFA2_RTX_2070_EX_SUB_DEV, 0x23); -REGISTER_I2C_PCI_DETECTOR("GALAX RTX 2070 Super EX Gamer Black", DetectGalaxGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, NVIDIA_SUB_VEN, GALAX_RTX_2070S_EX_GAMER_BLACK_SUB_DEV, 0x23); -REGISTER_I2C_PCI_DETECTOR("KFA2 RTX 2080 EX OC", DetectGalaxGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_DEV, NVIDIA_SUB_VEN, KFA2_RTX_2080_EX_OC_SUB_DEV, 0x23); -REGISTER_I2C_PCI_DETECTOR("KFA2 RTX 2080 Super EX OC", DetectGalaxGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, NVIDIA_SUB_VEN, KFA2_RTX_2080_SUPER_EX_OC_SUB_DEV, 0x23); -REGISTER_I2C_PCI_DETECTOR("KFA2 RTX 2080 TI EX OC", DetectGalaxGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_DEV, NVIDIA_SUB_VEN, KFA2_RTX_2080_TI_EX_OC_SUB_DEV, 0x23); +REGISTER_I2C_PCI_DETECTOR("KFA2 GeForce RTX 2070 EX", DetectGalaxGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_DEV, NVIDIA_SUB_VEN, KFA2_RTX_2070_EX_SUB_DEV, 0x23); +REGISTER_I2C_PCI_DETECTOR("KFA2 GeForce RTX 2070 OC", DetectGalaxGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, NVIDIA_SUB_VEN, KFA2_RTX_2070_OC_SUB_DEV, 0x23); +REGISTER_I2C_PCI_DETECTOR("GALAX GeForce RTX 2070 SUPER EX Gamer Black", DetectGalaxGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, NVIDIA_SUB_VEN, GALAX_RTX_2070S_EX_GAMER_BLACK_SUB_DEV, 0x23); +REGISTER_I2C_PCI_DETECTOR("KFA2 GeForce RTX 2080 EX OC", DetectGalaxGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_DEV, NVIDIA_SUB_VEN, KFA2_RTX_2080_EX_OC_SUB_DEV, 0x23); +REGISTER_I2C_PCI_DETECTOR("KFA2 GeForce RTX 2080 SUPER EX OC", DetectGalaxGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, NVIDIA_SUB_VEN, KFA2_RTX_2080_SUPER_EX_OC_SUB_DEV, 0x23); +REGISTER_I2C_PCI_DETECTOR("KFA2 GeForce RTX 2080 Ti EX OC", DetectGalaxGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_DEV, NVIDIA_SUB_VEN, KFA2_RTX_2080TI_EX_OC_SUB_DEV, 0x23); +REGISTER_I2C_PCI_DETECTOR("GALAX GeForce RTX 3080 SG", DetectGalaxGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, NVIDIA_SUB_VEN, GALAX_RTX_3080_SG_SUB_DEV, 0x23); +REGISTER_I2C_PCI_DETECTOR("GALAX GeForce RTX 5070 Ti EX Gamer 1-Click OC", DetectGalaxGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, NVIDIA_SUB_VEN, GALAX_RTX_5070TI_EX_OC_SUB_DEV, 0x51); diff --git a/Controllers/GalaxGPUController/GalaxGPUv1Controller/GalaxGPUv1Controller.cpp b/Controllers/GalaxGPUController/GalaxGPUv1Controller/GalaxGPUv1Controller.cpp new file mode 100644 index 00000000..035fe605 --- /dev/null +++ b/Controllers/GalaxGPUController/GalaxGPUv1Controller/GalaxGPUv1Controller.cpp @@ -0,0 +1,108 @@ +/*---------------------------------------------------------*\ +| GalaxGPUv1Controller.cpp | +| | +| Driver for Galax/KFA2 GPU | +| | +| Niels Westphal (crashniels) 12 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "GalaxGPUv1Controller.h" + +GalaxGPUv1Controller::GalaxGPUv1Controller(i2c_smbus_interface* bus, galax_gpu_dev_id dev, std::string dev_name) +{ + this->bus = bus; + this->dev = dev; + this->name = dev_name; +} + +GalaxGPUv1Controller::~GalaxGPUv1Controller() +{ + +} + +std::string GalaxGPUv1Controller::GetDeviceLocation() +{ + std::string return_string(bus->device_name); + char addr[5]; + snprintf(addr, 5, "0x%02X", dev); + return_string.append(", address "); + return_string.append(addr); + return("I2C: " + return_string); +} + +std::string GalaxGPUv1Controller::GetDeviceName() +{ + return(name); +} + +unsigned char GalaxGPUv1Controller::GetLEDRed() +{ + return(GalaxGPURegisterRead(GALAX_V1_RED_REGISTER)); +} + +unsigned char GalaxGPUv1Controller::GetLEDGreen() +{ + return(GalaxGPURegisterRead(GALAX_V1_GREEN_REGISTER)); +} + +unsigned char GalaxGPUv1Controller::GetLEDBlue() +{ + return(GalaxGPURegisterRead(GALAX_V1_BLUE_REGISTER)); +} + +void GalaxGPUv1Controller::SetLEDColorsDirect(unsigned char red, unsigned char green, unsigned char blue) // Direct Mode is just Static Mode without applying color changes +{ + GalaxGPURegisterWrite(GALAX_V1_RED_REGISTER, red); + GalaxGPURegisterWrite(GALAX_V1_GREEN_REGISTER, green); + GalaxGPURegisterWrite(GALAX_V1_BLUE_REGISTER, blue); +} + +void GalaxGPUv1Controller::SetLEDColorsEffect(unsigned char red, unsigned char green, unsigned char blue) +{ + GalaxGPURegisterWrite(GALAX_V1_RED_REGISTER, red); + GalaxGPURegisterWrite(GALAX_V1_GREEN_REGISTER, green); + GalaxGPURegisterWrite(GALAX_V1_BLUE_REGISTER, blue); +} + +void GalaxGPUv1Controller::SetMode(unsigned char mode) +{ + switch(mode) + { + case 1: + GalaxGPURegisterWrite(GALAX_V1_MODE_REGISTER_1, GALAX_V1_MODE_STATIC_VALUE_1); + GalaxGPURegisterWrite(GALAX_V1_MODE_REGISTER_2, GALAX_V1_MODE_STATIC_VALUE_2); + break; + + case 2: + GalaxGPURegisterWrite(GALAX_V1_MODE_REGISTER_1, GALAX_V1_MODE_BREATHING_VALUE_1); + GalaxGPURegisterWrite(GALAX_V1_MODE_REGISTER_2, GALAX_V1_MODE_BREATHING_VALUE_2); + break; + + case 3: + GalaxGPURegisterWrite(GALAX_V1_MODE_REGISTER_1, GALAX_V1_MODE_RAINBOW_VALUE_1); + GalaxGPURegisterWrite(GALAX_V1_MODE_REGISTER_2, GALAX_V1_MODE_RAINBOW_VALUE_2); + break; + + case 4: + GalaxGPURegisterWrite(GALAX_V1_MODE_REGISTER_1, GALAX_V1_MODE_CYCLE_BREATHING_VALUE_1); + GalaxGPURegisterWrite(GALAX_V1_MODE_REGISTER_2, GALAX_V1_MODE_CYCLE_BREATHING_VALUE_2); + break; + + default: + break; + } +} + +unsigned char GalaxGPUv1Controller::GalaxGPURegisterRead(unsigned char reg) +{ + return(bus->i2c_smbus_read_byte_data(dev, reg)); +} + +void GalaxGPUv1Controller::GalaxGPURegisterWrite(unsigned char reg, unsigned char val) +{ + bus->i2c_smbus_write_byte_data(dev, reg, val); +} diff --git a/Controllers/GalaxGPUController/GalaxGPUv1Controller/GalaxGPUv1Controller.h b/Controllers/GalaxGPUController/GalaxGPUv1Controller/GalaxGPUv1Controller.h new file mode 100644 index 00000000..92c580d8 --- /dev/null +++ b/Controllers/GalaxGPUController/GalaxGPUv1Controller/GalaxGPUv1Controller.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------*\ +| GalaxGPUv1Controller.h | +| | +| Driver for Galax/KFA2 GPU | +| | +| Niels Westphal (crashniels) 12 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "i2c_smbus.h" + +typedef unsigned char galax_gpu_dev_id; + +enum +{ + /* RGB Registers */ + GALAX_V1_RED_REGISTER = 0x02, /* Red Register */ + GALAX_V1_GREEN_REGISTER = 0x03, /* Green Register */ + GALAX_V1_BLUE_REGISTER = 0x04, /* Blue Register */ + /* MODE Registers */ + GALAX_V1_MODE_REGISTER_1 = 0x05, /* Mode Register 1 */ + GALAX_V1_MODE_REGISTER_2 = 0x06, /* Mode Register 2 */ +}; + +enum +{ + /* Static Mode Values */ + GALAX_V1_MODE_STATIC_VALUE_1 = 0x00, + GALAX_V1_MODE_STATIC_VALUE_2 = 0x01, + /* Breathing Mode Values */ + GALAX_V1_MODE_BREATHING_VALUE_1 = 0x04, + GALAX_V1_MODE_BREATHING_VALUE_2 = 0x00, + /* Rainbow Mode Values */ + GALAX_V1_MODE_RAINBOW_VALUE_1 = 0x84, + GALAX_V1_MODE_RAINBOW_VALUE_2 = 0x02, + /* Cycle Breathing Mode Values */ + GALAX_V1_MODE_CYCLE_BREATHING_VALUE_1 = 0x84, + GALAX_V1_MODE_CYCLE_BREATHING_VALUE_2 = 0x40, +}; + +class GalaxGPUv1Controller +{ +public: + GalaxGPUv1Controller(i2c_smbus_interface* bus, galax_gpu_dev_id, std::string dev_name); + ~GalaxGPUv1Controller(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + unsigned char GetLEDRed(); + unsigned char GetLEDGreen(); + unsigned char GetLEDBlue(); + void SetLEDColorsDirect(unsigned char red, unsigned char green, unsigned char blue); + void SetLEDColorsEffect(unsigned char red, unsigned char green, unsigned char blue); + void SetMode(unsigned char mode); + + unsigned char GalaxGPURegisterRead(unsigned char reg); + void GalaxGPURegisterWrite(unsigned char reg, unsigned char val); + + bool direct = false; // Temporary solution to check if we are in "Direct" mode + +private: + i2c_smbus_interface * bus; + galax_gpu_dev_id dev; + std::string name; +}; diff --git a/Controllers/GalaxGPUController/GalaxGPUv1Controller/RGBController_GalaxGPUv1.cpp b/Controllers/GalaxGPUController/GalaxGPUv1Controller/RGBController_GalaxGPUv1.cpp new file mode 100644 index 00000000..9fb20902 --- /dev/null +++ b/Controllers/GalaxGPUController/GalaxGPUv1Controller/RGBController_GalaxGPUv1.cpp @@ -0,0 +1,179 @@ +/*---------------------------------------------------------*\ +| RGBController_GalaxGPUv1.cpp | +| | +| RGBController for Galax/KFA2 GPU | +| | +| Niels Westphal (crashniels) 12 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_GalaxGPUv1.h" + +int RGBController_GalaxGPUv1::GetDeviceMode() +{ + int modereg1 = controller->GalaxGPURegisterRead(GALAX_V1_MODE_REGISTER_1); + int modereg2 = controller->GalaxGPURegisterRead(GALAX_V1_MODE_REGISTER_2); + + if(modereg1 == GALAX_V1_MODE_STATIC_VALUE_1 && modereg2 == GALAX_V1_MODE_STATIC_VALUE_2) + { + active_mode = 1; + modes[active_mode].color_mode = MODE_COLORS_PER_LED; + } + + if(modereg1 == GALAX_V1_MODE_BREATHING_VALUE_1 && modereg2 == GALAX_V1_MODE_BREATHING_VALUE_2) + { + active_mode = 2; + modes[active_mode].color_mode = MODE_COLORS_PER_LED; + } + + if(modereg1 == GALAX_V1_MODE_RAINBOW_VALUE_1 && modereg2 == GALAX_V1_MODE_RAINBOW_VALUE_2) + { + active_mode = 3; + modes[active_mode].color_mode = MODE_COLORS_NONE; + } + + if(modereg1 == GALAX_V1_MODE_CYCLE_BREATHING_VALUE_1 && modereg2 == GALAX_V1_MODE_CYCLE_BREATHING_VALUE_2) + { + active_mode = 4; + modes[active_mode].color_mode = MODE_COLORS_NONE; + } + + return(active_mode); +} + +/**------------------------------------------------------------------*\ + @name Galax GPU v1 + @category GPU + @type I2C + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectGalaxGPUv1Controllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_GalaxGPUv1::RGBController_GalaxGPUv1(GalaxGPUv1Controller* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "GALAX"; + type = DEVICE_TYPE_GPU; + description = "GALAX / KFA2 RTX GPU"; + location = controller->GetDeviceLocation(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 1; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = 2; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Breathing.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Breathing); + + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = 3; + Rainbow.flags = 0; + Rainbow.color_mode = MODE_COLORS_NONE; + modes.push_back(Rainbow); + + mode Cycle_Breathing; + Cycle_Breathing.name = "Cycle Breathing"; + Cycle_Breathing.value = 4; + Cycle_Breathing.flags = 0; + Cycle_Breathing.color_mode = MODE_COLORS_NONE; + modes.push_back(Cycle_Breathing); + + SetupZones(); + + active_mode = GetDeviceMode(); +} + +RGBController_GalaxGPUv1::~RGBController_GalaxGPUv1() +{ + delete controller; +} + +void RGBController_GalaxGPUv1::SetupZones() +{ + /*---------------------------------------------------------*\ + | Set up zone | + \*---------------------------------------------------------*/ + zone galax_gpu_zone; + galax_gpu_zone.name = "GPU"; + galax_gpu_zone.type = ZONE_TYPE_SINGLE; + galax_gpu_zone.leds_min = 1; + galax_gpu_zone.leds_max = 1; + galax_gpu_zone.leds_count = 1; + galax_gpu_zone.matrix_map = NULL; + zones.push_back(galax_gpu_zone); + + /*---------------------------------------------------------*\ + | Set up LED | + \*---------------------------------------------------------*/ + led galax_gpu_led; + galax_gpu_led.name = "GPU"; + leds.push_back(galax_gpu_led); + + SetupColors(); + + /*---------------------------------------------------------*\ + | Initialize color | + \*---------------------------------------------------------*/ + unsigned char red = controller->GetLEDRed(); + unsigned char grn = controller->GetLEDGreen(); + unsigned char blu = controller->GetLEDBlue(); + + colors[0] = ToRGBColor(red, grn, blu); +} + +void RGBController_GalaxGPUv1::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_GalaxGPUv1::DeviceUpdateLEDs() +{ + for(std::size_t led = 0; led < colors.size(); led++) + { + unsigned char red = RGBGetRValue(colors[led]); + unsigned char grn = RGBGetGValue(colors[led]); + unsigned char blu = RGBGetBValue(colors[led]); + + if(GetMode() == 1) + { + controller->SetLEDColorsDirect(red, grn, blu); + } + else + { + controller->SetLEDColorsEffect(red, grn, blu); + } + } +} + +void RGBController_GalaxGPUv1::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_GalaxGPUv1::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_GalaxGPUv1::DeviceUpdateMode() +{ + int new_mode = modes[active_mode].value; + + controller->SetMode(new_mode); +} diff --git a/Controllers/GalaxGPUController/GalaxGPUv1Controller/RGBController_GalaxGPUv1.h b/Controllers/GalaxGPUController/GalaxGPUv1Controller/RGBController_GalaxGPUv1.h new file mode 100644 index 00000000..55c8ed9e --- /dev/null +++ b/Controllers/GalaxGPUController/GalaxGPUv1Controller/RGBController_GalaxGPUv1.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------*\ +| RGBController_GalaxGPUv1.h | +| | +| RGBController for Galax/KFA2 GPU | +| | +| Niels Westphal (crashniels) 12 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "GalaxGPUv1Controller.h" + +class RGBController_GalaxGPUv1 : public RGBController +{ +public: + RGBController_GalaxGPUv1(GalaxGPUv1Controller* controller_ptr); + ~RGBController_GalaxGPUv1(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + GalaxGPUv1Controller* controller; + + int GetDeviceMode(); +}; diff --git a/Controllers/GalaxGPUController/GalaxGPUv2Controller/GalaxGPUv2Controller.cpp b/Controllers/GalaxGPUController/GalaxGPUv2Controller/GalaxGPUv2Controller.cpp new file mode 100644 index 00000000..e078b8e3 --- /dev/null +++ b/Controllers/GalaxGPUController/GalaxGPUv2Controller/GalaxGPUv2Controller.cpp @@ -0,0 +1,119 @@ +/*---------------------------------------------------------*\ +| GalaxGPUv2Controller.cpp | +| | +| RGBController for Galax GPUs (Xtreme Tuner) | +| | +| Daniel Stuart (daniel.stuart14) 26 may 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "GalaxGPUv2Controller.h" + +GalaxGPUv2Controller::GalaxGPUv2Controller(i2c_smbus_interface* bus, galax_gpu_dev_id dev, std::string dev_name) +{ + this->bus = bus; + this->dev = dev; + this->name = dev_name; +} + +GalaxGPUv2Controller::~GalaxGPUv2Controller() +{ + +} + +std::string GalaxGPUv2Controller::GetDeviceLocation() +{ + std::string return_string(bus->device_name); + char addr[5]; + snprintf(addr, 5, "0x%02X", dev); + return_string.append(", address "); + return_string.append(addr); + return("I2C: " + return_string); +} + +std::string GalaxGPUv2Controller::GetDeviceName() +{ + return(name); +} + +unsigned char GalaxGPUv2Controller::GetLEDRed() +{ + return(GalaxGPURegisterRead(GALAX_V2_RED_REGISTER)); +} + +unsigned char GalaxGPUv2Controller::GetLEDGreen() +{ + return(GalaxGPURegisterRead(GALAX_V2_GREEN_REGISTER)); +} + +unsigned char GalaxGPUv2Controller::GetLEDBlue() +{ + return(GalaxGPURegisterRead(GALAX_V2_BLUE_REGISTER)); +} + +unsigned char GalaxGPUv2Controller::GetMode() +{ + return GalaxGPURegisterRead(GALAX_V2_MODE_REGISTER); +} + +unsigned char GalaxGPUv2Controller::GetSync() +{ + return GalaxGPURegisterRead(GALAX_V2_SYNC_REGISTER); +} + +unsigned char GalaxGPUv2Controller::GetSpeed() +{ + return GalaxGPURegisterRead(GALAX_V2_SPEED_REGISTER_A); +} + +unsigned char GalaxGPUv2Controller::GetBrightness() +{ + return GalaxGPURegisterRead(GALAX_V2_BRIGHTNESS_REGISTER); +} + +void GalaxGPUv2Controller::SetLEDColors(unsigned char red, unsigned char green, unsigned char blue) +{ + GalaxGPURegisterWrite(GALAX_V2_RED_REGISTER, red); + GalaxGPURegisterWrite(GALAX_V2_GREEN_REGISTER, green); + GalaxGPURegisterWrite(GALAX_V2_BLUE_REGISTER, blue); +} + +void GalaxGPUv2Controller::SetMode(unsigned char value) +{ + GalaxGPURegisterWrite(GALAX_V2_MODE_REGISTER, value); +} + +void GalaxGPUv2Controller::SetSync(unsigned char value) +{ + GalaxGPURegisterWrite(GALAX_V2_SYNC_REGISTER, value); +} + +void GalaxGPUv2Controller::SetSpeed(unsigned char value) +{ + // We just duplicate the value to both speed registers + GalaxGPURegisterWrite(GALAX_V2_SPEED_REGISTER_A, value); + GalaxGPURegisterWrite(GALAX_V2_SPEED_REGISTER_B, value); +} + +void GalaxGPUv2Controller::SetBrightness(unsigned char value) +{ + GalaxGPURegisterWrite(GALAX_V2_BRIGHTNESS_REGISTER, value); +} + +void GalaxGPUv2Controller::SaveMode() +{ + GalaxGPURegisterWrite(GALAX_V2_SAVE_REGISTER, GALAX_V2_SAVE_VALUE); +} + +unsigned char GalaxGPUv2Controller::GalaxGPURegisterRead(unsigned char reg) +{ + return(bus->i2c_smbus_read_byte_data(dev, reg)); +} + +void GalaxGPUv2Controller::GalaxGPURegisterWrite(unsigned char reg, unsigned char val) +{ + bus->i2c_smbus_write_byte_data(dev, reg, val); +} diff --git a/Controllers/GalaxGPUController/GalaxGPUv2Controller/GalaxGPUv2Controller.h b/Controllers/GalaxGPUController/GalaxGPUv2Controller/GalaxGPUv2Controller.h new file mode 100644 index 00000000..505a99e9 --- /dev/null +++ b/Controllers/GalaxGPUController/GalaxGPUv2Controller/GalaxGPUv2Controller.h @@ -0,0 +1,82 @@ +/*---------------------------------------------------------*\ +| GalaxGPUv2Controller.h | +| | +| RGBController for Galax GPUs (Xtreme Tuner) | +| | +| Daniel Stuart (daniel.stuart14) 26 may 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "i2c_smbus.h" + +typedef unsigned char galax_gpu_dev_id; + +enum +{ + GALAX_V2_RED_REGISTER = 0x02, /* Red Register */ + GALAX_V2_GREEN_REGISTER = 0x03, /* Green Register */ + GALAX_V2_BLUE_REGISTER = 0x04, /* Blue Register */ + GALAX_V2_SPEED_REGISTER_A = 0x21, /* Speed Register A */ + GALAX_V2_SPEED_REGISTER_B = 0x22, /* Speed Register B */ + GALAX_V2_SYNC_REGISTER = 0x27, /* Sync Register */ + GALAX_V2_BRIGHTNESS_REGISTER = 0x2D, /* Brightness Register */ + GALAX_V2_MODE_REGISTER = 0x30, /* Mode Register */ + GALAX_V2_SAVE_REGISTER = 0x40, /* Save Register */ +}; + +enum +{ + GALAX_V2_MODE_STATIC_VALUE = 0x01, /* Static Mode */ + GALAX_V2_MODE_BREATHING_VALUE = 0x02, /* Breathing Mode */ + GALAX_V2_MODE_RAINBOW_VALUE = 0x16, /* Rainbow Mode */ + GALAX_V2_MODE_OFF_VALUE = 0x19, /* Off Mode */ +}; + +enum +{ + GALAX_V2_SYNC_OFF = 0x00, /* Sync Off */ + GALAX_V2_SYNC_ON = 0x01, /* Sync On */ +}; + +enum +{ + GALAX_V2_SAVE_VALUE = 0x5A, /* Save Value */ +}; + +class GalaxGPUv2Controller +{ +public: + GalaxGPUv2Controller(i2c_smbus_interface* bus, galax_gpu_dev_id, std::string dev_name); + ~GalaxGPUv2Controller(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + unsigned char GetLEDRed(); + unsigned char GetLEDGreen(); + unsigned char GetLEDBlue(); + unsigned char GetMode(); + unsigned char GetSync(); + unsigned char GetSpeed(); + unsigned char GetBrightness(); + void SetLEDColors(unsigned char red, unsigned char green, unsigned char blue); + void SetMode(unsigned char value); + void SetSync(unsigned char value); + void SetSpeed(unsigned char value); + void SetBrightness(unsigned char value); + void SaveMode(); + + unsigned char GalaxGPURegisterRead(unsigned char reg); + void GalaxGPURegisterWrite(unsigned char reg, unsigned char val); + + bool direct = false; // Temporary solution to check if we are in "Direct" mode + +private: + i2c_smbus_interface * bus; + galax_gpu_dev_id dev; + std::string name; +}; diff --git a/Controllers/GalaxGPUController/GalaxGPUv2Controller/RGBController_GalaxGPUv2.cpp b/Controllers/GalaxGPUController/GalaxGPUv2Controller/RGBController_GalaxGPUv2.cpp new file mode 100644 index 00000000..45ceff95 --- /dev/null +++ b/Controllers/GalaxGPUController/GalaxGPUv2Controller/RGBController_GalaxGPUv2.cpp @@ -0,0 +1,221 @@ +/*---------------------------------------------------------*\ +| RGBController_GalaxGPUv2.cpp | +| | +| RGBController for Galax GPUs (Xtreme Tuner) | +| | +| Daniel Stuart (daniel.stuart14) 26 may 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_GalaxGPUv2.h" + +int RGBController_GalaxGPUv2::GetDeviceMode() +{ + int modereg = controller->GetMode(); + int syncreg = controller->GetSync(); + + int cur_mode = 0; // Static mode by default + + if (syncreg == GALAX_V2_SYNC_ON) + { + cur_mode = 3; // External Sync mode + } + else + { + switch (modereg) + { + case GALAX_V2_MODE_BREATHING_VALUE: + cur_mode = 1; + break; + + case GALAX_V2_MODE_RAINBOW_VALUE: + cur_mode = 2; + break; + + case GALAX_V2_MODE_OFF_VALUE: + cur_mode = 4; // Off mode + break; + } + } + + return(cur_mode); +} + +/**------------------------------------------------------------------*\ + @name Galax GPU v2 + @category GPU + @type I2C + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectGalaxGPUv2Controllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_GalaxGPUv2::RGBController_GalaxGPUv2(GalaxGPUv2Controller* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "GALAX"; + type = DEVICE_TYPE_GPU; + description = "GALAX RTX 40+ GPU"; + location = controller->GetDeviceLocation(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0; + Direct.brightness_min = 0x01; + Direct.brightness_max = 0x03; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = 1; + Breathing.brightness_min = 0x01; + Breathing.brightness_max = 0x03; + Breathing.speed_min = 0x00; + Breathing.speed_max = 0x09; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE; + Breathing.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Breathing); + + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = 2; + Rainbow.flags = 0; + Rainbow.brightness_min = 0x01; + Rainbow.brightness_max = 0x03; + Rainbow.speed_min = 0x00; + Rainbow.speed_max = 0x09; + Rainbow.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE; + Rainbow.color_mode = MODE_COLORS_NONE; + modes.push_back(Rainbow); + + mode Sync; + Sync.name = "External Sync"; + Sync.value = 3; + Sync.flags = MODE_FLAG_MANUAL_SAVE; + Sync.color_mode = MODE_COLORS_NONE; + modes.push_back(Sync); + + mode Off; + Off.name = "Off"; + Off.value = 4; + Off.flags = MODE_FLAG_MANUAL_SAVE; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + SetupZones(); + + active_mode = GetDeviceMode(); + modes[active_mode].brightness = controller->GetBrightness(); + modes[active_mode].speed = controller->GetSpeed(); +} + +RGBController_GalaxGPUv2::~RGBController_GalaxGPUv2() +{ + delete controller; +} + +void RGBController_GalaxGPUv2::SetupZones() +{ + /*---------------------------------------------------------*\ + | Set up zone | + \*---------------------------------------------------------*/ + zone galax_gpu_zone; + galax_gpu_zone.name = "GPU"; + galax_gpu_zone.type = ZONE_TYPE_SINGLE; + galax_gpu_zone.leds_min = 1; + galax_gpu_zone.leds_max = 1; + galax_gpu_zone.leds_count = 1; + galax_gpu_zone.matrix_map = NULL; + zones.push_back(galax_gpu_zone); + + /*---------------------------------------------------------*\ + | Set up LED | + \*---------------------------------------------------------*/ + led galax_gpu_led; + galax_gpu_led.name = "GPU"; + leds.push_back(galax_gpu_led); + + SetupColors(); + + /*---------------------------------------------------------*\ + | Initialize color | + \*---------------------------------------------------------*/ + unsigned char red = controller->GetLEDRed(); + unsigned char grn = controller->GetLEDGreen(); + unsigned char blu = controller->GetLEDBlue(); + + colors[0] = ToRGBColor(red, grn, blu); +} + +void RGBController_GalaxGPUv2::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_GalaxGPUv2::DeviceUpdateLEDs() +{ + for(std::size_t led = 0; led < colors.size(); led++) + { + unsigned char red = RGBGetRValue(colors[led]); + unsigned char grn = RGBGetGValue(colors[led]); + unsigned char blu = RGBGetBValue(colors[led]); + + controller->SetLEDColors(red, grn, blu); + } +} + +void RGBController_GalaxGPUv2::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_GalaxGPUv2::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_GalaxGPUv2::DeviceUpdateMode() +{ + unsigned char mode_value = GALAX_V2_MODE_STATIC_VALUE; // Default to static mode + unsigned char sync_value = GALAX_V2_SYNC_OFF; // Default to sync off + + switch(modes[active_mode].value) + { + case 1: + mode_value = GALAX_V2_MODE_BREATHING_VALUE; + break; + + case 2: + mode_value = GALAX_V2_MODE_RAINBOW_VALUE; + break; + + case 3: + sync_value = GALAX_V2_SYNC_ON; // Enable sync + break; + + case 4: + mode_value = GALAX_V2_MODE_OFF_VALUE; // Off mode + break; + } + + controller->SetSync(sync_value); + controller->SetMode(mode_value); + controller->SetSpeed(modes[active_mode].speed); + controller->SetBrightness(modes[active_mode].brightness); +} + +void RGBController_GalaxGPUv2::DeviceSaveMode() +{ + DeviceUpdateMode(); + controller->SaveMode(); +} diff --git a/Controllers/GalaxGPUController/GalaxGPUv2Controller/RGBController_GalaxGPUv2.h b/Controllers/GalaxGPUController/GalaxGPUv2Controller/RGBController_GalaxGPUv2.h new file mode 100644 index 00000000..9762fbcc --- /dev/null +++ b/Controllers/GalaxGPUController/GalaxGPUv2Controller/RGBController_GalaxGPUv2.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------*\ +| RGBController_GalaxGPUv2.h | +| | +| RGBController for Galax GPUs (Xtreme Tuner) | +| | +| Daniel Stuart (daniel.stuart14) 26 may 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "GalaxGPUv2Controller.h" + +class RGBController_GalaxGPUv2 : public RGBController +{ +public: + RGBController_GalaxGPUv2(GalaxGPUv2Controller* controller_ptr); + ~RGBController_GalaxGPUv2(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + GalaxGPUv2Controller* controller; + + int GetDeviceMode(); +}; diff --git a/Controllers/GalaxGPUController/RGBController_GalaxGPU.cpp b/Controllers/GalaxGPUController/RGBController_GalaxGPU.cpp deleted file mode 100644 index 9678e523..00000000 --- a/Controllers/GalaxGPUController/RGBController_GalaxGPU.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_GalaxGPU.cpp | -| | -| Driver for Galax / KFA2 RGB on GPUs | -| | -| Niels Westphal (crashniels) 12.07.2020 | -\*-----------------------------------------*/ - -#include "RGBController_GalaxGPU.h" - -int RGBController_GalaxGPU::GetDeviceMode() -{ - int modereg1 = controller->GalaxGPURegisterRead(GALAX_MODE_REGISTER_1); - int modereg2 = controller->GalaxGPURegisterRead(GALAX_MODE_REGISTER_2); - - if(modereg1 == GALAX_MODE_STATIC_VALUE_1 && modereg2 == GALAX_MODE_STATIC_VALUE_2) - { - active_mode = 1; - modes[active_mode].color_mode = MODE_COLORS_PER_LED; - } - - if(modereg1 == GALAX_MODE_BREATHING_VALUE_1 && modereg2 == GALAX_MODE_BREATHING_VALUE_2) - { - active_mode = 2; - modes[active_mode].color_mode = MODE_COLORS_PER_LED; - } - - if(modereg1 == GALAX_MODE_RAINBOW_VALUE_1 && modereg2 == GALAX_MODE_RAINBOW_VALUE_2) - { - active_mode = 3; - modes[active_mode].color_mode = MODE_COLORS_NONE; - } - - if(modereg1 == GALAX_MODE_CYCLE_BREATHING_VALUE_1 && modereg2 == GALAX_MODE_CYCLE_BREATHING_VALUE_2) - { - active_mode = 4; - modes[active_mode].color_mode = MODE_COLORS_NONE; - } - - return(active_mode); -} - -/**------------------------------------------------------------------*\ - @name Galax GPU - @category GPU - @type I2C - @save :x: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectGalaxGPUControllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_GalaxGPU::RGBController_GalaxGPU(GalaxGPUController* controller_ptr) -{ - controller = controller_ptr; - - name = controller->GetDeviceName(); - vendor = "GALAX"; - type = DEVICE_TYPE_GPU; - description = "GALAX / KFA2 RTX GPU"; - location = controller->GetDeviceLocation(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = 1; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = 2; - Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Breathing.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Breathing); - - mode Rainbow; - Rainbow.name = "Rainbow"; - Rainbow.value = 3; - Rainbow.flags = 0; - Rainbow.color_mode = MODE_COLORS_NONE; - modes.push_back(Rainbow); - - mode Cycle_Breathing; - Cycle_Breathing.name = "Cycle Breathing"; - Cycle_Breathing.value = 4; - Cycle_Breathing.flags = 0; - Cycle_Breathing.color_mode = MODE_COLORS_NONE; - modes.push_back(Cycle_Breathing); - - SetupZones(); - - active_mode = GetDeviceMode(); -} - -RGBController_GalaxGPU::~RGBController_GalaxGPU() -{ - delete controller; -} - -void RGBController_GalaxGPU::SetupZones() -{ - /*---------------------------------------------------------*\ - | Set up zone | - \*---------------------------------------------------------*/ - zone galax_gpu_zone; - galax_gpu_zone.name = "GPU"; - galax_gpu_zone.type = ZONE_TYPE_SINGLE; - galax_gpu_zone.leds_min = 1; - galax_gpu_zone.leds_max = 1; - galax_gpu_zone.leds_count = 1; - galax_gpu_zone.matrix_map = NULL; - zones.push_back(galax_gpu_zone); - - /*---------------------------------------------------------*\ - | Set up LED | - \*---------------------------------------------------------*/ - led galax_gpu_led; - galax_gpu_led.name = "GPU"; - leds.push_back(galax_gpu_led); - - SetupColors(); - - /*---------------------------------------------------------*\ - | Initialize color | - \*---------------------------------------------------------*/ - unsigned char red = controller->GetLEDRed(); - unsigned char grn = controller->GetLEDGreen(); - unsigned char blu = controller->GetLEDBlue(); - - colors[0] = ToRGBColor(red, grn, blu); -} - -void RGBController_GalaxGPU::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_GalaxGPU::DeviceUpdateLEDs() -{ - for(std::size_t led = 0; led < colors.size(); led++) - { - unsigned char red = RGBGetRValue(colors[led]); - unsigned char grn = RGBGetGValue(colors[led]); - unsigned char blu = RGBGetBValue(colors[led]); - - if(GetMode() == 1) - { - controller->SetLEDColorsDirect(red, grn, blu); - } - else - { - controller->SetLEDColorsEffect(red, grn, blu); - } - } -} - -void RGBController_GalaxGPU::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_GalaxGPU::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_GalaxGPU::DeviceUpdateMode() -{ - int new_mode = modes[active_mode].value; - - controller->SetMode(new_mode); -} diff --git a/Controllers/GalaxGPUController/RGBController_GalaxGPU.h b/Controllers/GalaxGPUController/RGBController_GalaxGPU.h deleted file mode 100644 index b699212c..00000000 --- a/Controllers/GalaxGPUController/RGBController_GalaxGPU.h +++ /dev/null @@ -1,34 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_GalaxGPU.h | -| | -| Driver for Galax / KFA2 RGB on GPUs | -| | -| Niels Westphal (crashniels) 12.07.2020 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "GalaxGPUController.h" - -class RGBController_GalaxGPU : public RGBController -{ -public: - RGBController_GalaxGPU(GalaxGPUController* controller_ptr); - ~RGBController_GalaxGPU(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - GalaxGPUController* controller; - - int GetDeviceMode(); -}; diff --git a/Controllers/GigabyteAorusCPUCoolerController/ATC800Controller.cpp b/Controllers/GigabyteAorusCPUCoolerController/ATC800Controller.cpp index a6480574..ea9fa281 100644 --- a/Controllers/GigabyteAorusCPUCoolerController/ATC800Controller.cpp +++ b/Controllers/GigabyteAorusCPUCoolerController/ATC800Controller.cpp @@ -1,20 +1,23 @@ -/*-----------------------------------------*\ -| ATC800Controller.cpp | -| | -| Driver for Aorus ATC800 CPU Cooler | -| | -| | -| Felipe Cavalcanti 08/13/2020 | -\*-----------------------------------------*/ - -#include "ATC800Controller.h" +/*---------------------------------------------------------*\ +| ATC800Controller.cpp | +| | +| Driver for Aorus ATC800 cooler | +| | +| Felipe Cavalcanti 13 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "ATC800Controller.h" +#include "StringUtils.h" -ATC800Controller::ATC800Controller(hid_device* dev_handle, const char* path) +ATC800Controller::ATC800Controller(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } ATC800Controller::~ATC800Controller() @@ -27,6 +30,11 @@ std::string ATC800Controller::GetDeviceLocation() return("HID: " + location); } +std::string ATC800Controller::GetNameString() +{ + return(name); +} + std::string ATC800Controller::GetSerialString() { wchar_t serial_string[128]; @@ -37,102 +45,243 @@ std::string ATC800Controller::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } -void ATC800Controller::SendCoolerMode - ( - unsigned char mode, - unsigned short /*speed*/, - unsigned char channel, - unsigned char red, - unsigned char green, - unsigned char blue - ) +void ATC800Controller::DisableTempRPMIndicator() { - unsigned char usb_buf[9]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, sizeof(usb_buf)); - - /*-----------------------------------------------------*\ - | Set up Lighting Control packet | - \*-----------------------------------------------------*/ - if (channel == AORUS_ATC800_TOP_ZONE) - { - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0xbe; - usb_buf[0x08] = 0xcc; - - hid_send_feature_report(dev, usb_buf, 9); - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0xc9; - usb_buf[0x02] = mode; - usb_buf[0x03] = 0x3c; - usb_buf[0x04] = 0x02; - usb_buf[0x05] = 0x00; - usb_buf[0x06] = 0x00; - - hid_send_feature_report(dev, usb_buf, 9); - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0xbc; - usb_buf[0x02] = red; - usb_buf[0x03] = green; - usb_buf[0x04] = blue; - - hid_send_feature_report(dev, usb_buf, 9); - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0xb6; - } - else if (channel == AORUS_ATC800_FANS_ZONE) - { - hid_send_feature_report(dev, usb_buf, 9); - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0xc9; - usb_buf[0x02] = mode; - usb_buf[0x03] = 0x3c; - usb_buf[0x04] = 0x02; - usb_buf[0x05] = 0x00; - usb_buf[0x06] = 0x01; - - hid_send_feature_report(dev, usb_buf, 9); - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0xb0; - usb_buf[0x02] = mode; - usb_buf[0x03] = red; - usb_buf[0x04] = green; - usb_buf[0x05] = blue; - - usb_buf[0x06] = red; - - usb_buf[0x07] = green; - usb_buf[0x08] = blue; - - for(int i = 0xb0; i <= 0xb3; i++) - { - usb_buf[0x01] = i; //zone b0->b3 - hid_send_feature_report(dev, usb_buf, 9); - } - } - - memset(usb_buf, 0x00, sizeof(usb_buf)); - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0xb6; - - hid_send_feature_report(dev, usb_buf, 9); + uint8_t usb_buf[9] = { 0x00, 0xbe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc }; + hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); +} + +void ATC800Controller::SendMode(uint8_t mode, uint8_t brightness, uint8_t speed, uint8_t mystery_flag, uint8_t zone) +{ + uint8_t usb_buf[9] = { 0x00, 0xc9, mode, brightness, speed, mystery_flag, zone, 0x00, 0x00 }; + hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); +} + +void ATC800Controller::SendOneColor(uint8_t color_flag, uint8_t red, uint8_t green, uint8_t blue) +{ + uint8_t usb_buf[9] = { 0x00, color_flag, red, green, blue, 0x00, 0x00, 0x00, 0x00 }; + hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); +} + +void ATC800Controller::SendMultiColor(uint8_t flag, uint8_t mode, uint8_t red1, uint8_t green1, uint8_t blue1, uint8_t red2, uint8_t green2, uint8_t blue2) +{ + uint8_t usb_buf[9] = { 0x00, flag, mode, red1, green1, blue1, red2, green2, blue2 }; + hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); +} + +void ATC800Controller::SendOk() +{ + uint8_t usb_buf[9] = { 0x00, 0xb6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); +} + +void ATC800Controller::SendCoolerMode(uint8_t zone, uint8_t mode, aorus_atc800_mode_config zone_config) +{ + switch (mode) + { + case AORUS_ATC800_MODE_OFF: + { + if (zone == AORUS_ATC800_TOP_ZONE) + { + DisableTempRPMIndicator(); + SendMode(0x01, 0x3c, 0x02, 0x02, 0x00); + SendOneColor(0xbc, 0x00, 0x00, 0x00); + SendOk(); + } + else if (zone == AORUS_ATC800_FANS_ZONE) + { + SendMode(0x01, 0x3c, 0x02, 0x02, 0x01); + for(int i = 0xb0; i <= 0xb3; i++) + { + SendMultiColor(i, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + } + SendOk(); + } + } + break; + + case AORUS_ATC800_MODE_CUSTOM: + { + if (zone == AORUS_ATC800_TOP_ZONE) + { + DisableTempRPMIndicator(); + SendMode(mode, (zone_config.brightness + 1) * 0x0a, 0x02, 0x00, 0x00); + SendOneColor(0xbc, RGBGetRValue(zone_config.colors[0]), RGBGetGValue(zone_config.colors[0]), RGBGetBValue(zone_config.colors[0])); + SendOk(); + } + else if (zone == AORUS_ATC800_FANS_ZONE) + { + SendMode(mode, (zone_config.brightness + 1) * 0x0a, 0x02, 0x00, 0x01); + for(int i = 0xb0; i <= 0xb3; i++) + { + SendMultiColor(i, mode, RGBGetRValue(zone_config.colors[0]), RGBGetGValue(zone_config.colors[0]), RGBGetBValue(zone_config.colors[0]), RGBGetRValue(zone_config.colors[0]), RGBGetGValue(zone_config.colors[0]), RGBGetBValue(zone_config.colors[0])); + } + SendOk(); + } + } + break; + + case AORUS_ATC800_MODE_BREATHING: + { + if (zone == AORUS_ATC800_TOP_ZONE) + { + DisableTempRPMIndicator(); + SendMode(mode, 0x3c, zone_config.speed, 0x00, 0x00); + SendOneColor(0xbc, RGBGetRValue(zone_config.colors[0]), RGBGetGValue(zone_config.colors[0]), RGBGetBValue(zone_config.colors[0])); + SendOk(); + } + else if (zone == AORUS_ATC800_FANS_ZONE) + { + SendMode(mode, 0x3c, zone_config.speed, 0x00, 0x01); + for(int i = 0xb0; i <= 0xb3; i++) + { + SendMultiColor(i, mode, RGBGetRValue(zone_config.colors[0]), RGBGetGValue(zone_config.colors[0]), RGBGetBValue(zone_config.colors[0]), RGBGetRValue(zone_config.colors[0]), RGBGetGValue(zone_config.colors[0]), RGBGetBValue(zone_config.colors[0])); + } + SendOk(); + } + } + break; + + case AORUS_ATC800_MODE_SPECTRUM_CYCLE: + { + if (zone == AORUS_ATC800_TOP_ZONE) + { + DisableTempRPMIndicator(); + SendMode(mode, (zone_config.brightness + 1) * 0x0a, zone_config.speed, 0x00, 0x00); + SendOk(); + } + else if (zone == AORUS_ATC800_FANS_ZONE) + { + SendMode(mode, (zone_config.brightness + 1) * 0x0a, zone_config.speed, 0x00, 0x01); + SendOk(); + } + } + break; + + case AORUS_ATC800_MODE_FLASHING: + case AORUS_ATC800_MODE_DOUBLE_FLASHING: + { + if (zone == AORUS_ATC800_TOP_ZONE) + { + DisableTempRPMIndicator(); + SendMode(mode, (zone_config.brightness + 1) * 0x0a, zone_config.speed, 0x00, 0x00); + SendOneColor(0xbc, RGBGetRValue(zone_config.colors[0]), RGBGetGValue(zone_config.colors[0]), RGBGetBValue(zone_config.colors[0])); + SendOk(); + } + else if (zone == AORUS_ATC800_FANS_ZONE) + { + SendMode(mode, (zone_config.brightness + 1) * 0x0a, zone_config.speed, 0x00, 0x01); + for(int i = 0xb0; i <= 0xb3; i++) + { + SendMultiColor(i, mode, RGBGetRValue(zone_config.colors[0]), RGBGetGValue(zone_config.colors[0]), RGBGetBValue(zone_config.colors[0]), RGBGetRValue(zone_config.colors[0]), RGBGetGValue(zone_config.colors[0]), RGBGetBValue(zone_config.colors[0])); + } + SendOk(); + } + } + break; + + case AORUS_ATC800_MODE_GRADIENT: + { + if (zone == AORUS_ATC800_TOP_ZONE) + { + DisableTempRPMIndicator(); + SendMode(mode, (zone_config.brightness + 1) * 0x0a, zone_config.speed, 0x00, 0x00); + SendOneColor(0xcd, RGBGetRValue(zone_config.colors[0]), RGBGetGValue(zone_config.colors[0]), RGBGetBValue(zone_config.colors[0])); + SendMode(mode, (zone_config.brightness + 1) * 0x0a, zone_config.speed, 0x0a, 0x00); + SendOk(); + } + else if (zone == AORUS_ATC800_FANS_ZONE) + { + SendMode(mode, (zone_config.brightness + 1) * 0x0a, zone_config.speed, 0x08, 0x01); + SendOneColor(0xcd, RGBGetRValue(zone_config.colors[0]), RGBGetGValue(zone_config.colors[0]), RGBGetBValue(zone_config.colors[0])); + SendMode(mode, (zone_config.brightness + 1) * 0x0a, zone_config.speed, 0x0a, 0x01); + SendOk(); + } + } + break; + + case AORUS_ATC800_MODE_COLOR_SHIFT: + { + DisableTempRPMIndicator(); + SendMode(mode, (zone_config.brightness + 1) * 0x0a, zone_config.speed, zone_config.numberOfColors, 0x02); + SendMultiColor(0xb0, mode, RGBGetRValue(zone_config.colors[0]), RGBGetGValue(zone_config.colors[0]), RGBGetBValue(zone_config.colors[0]), RGBGetRValue(zone_config.colors[1]), RGBGetGValue(zone_config.colors[1]), RGBGetBValue(zone_config.colors[1])); + SendMultiColor(0xb1, mode, RGBGetRValue(zone_config.colors[2]), RGBGetGValue(zone_config.colors[2]), RGBGetBValue(zone_config.colors[2]), RGBGetRValue(zone_config.colors[3]), RGBGetGValue(zone_config.colors[3]), RGBGetBValue(zone_config.colors[3])); + SendMultiColor(0xb2, mode, RGBGetRValue(zone_config.colors[4]), RGBGetGValue(zone_config.colors[4]), RGBGetBValue(zone_config.colors[4]), RGBGetRValue(zone_config.colors[5]), RGBGetGValue(zone_config.colors[5]), RGBGetBValue(zone_config.colors[5])); + SendMultiColor(0xb3, mode, RGBGetRValue(zone_config.colors[6]), RGBGetGValue(zone_config.colors[6]), RGBGetBValue(zone_config.colors[6]), RGBGetRValue(zone_config.colors[7]), RGBGetGValue(zone_config.colors[7]), RGBGetBValue(zone_config.colors[7])); + SendOk(); + } + break; + + case AORUS_ATC800_MODE_RAINBOW_WAVE: + { + if (zone == AORUS_ATC800_TOP_ZONE) + { + DisableTempRPMIndicator(); + SendMode(mode, (zone_config.brightness + 1) * 0x0a, zone_config.speed, 0x02, 0x00); + SendOk(); + } + else if (zone == AORUS_ATC800_FANS_ZONE) + { + SendMode(mode, (zone_config.brightness + 1) * 0x0a, zone_config.speed, 0x02, 0x01); + SendOk(); + } + } + break; + + case AORUS_ATC800_MODE_RADIATE: + { + DisableTempRPMIndicator(); + SendMode(mode, (zone_config.brightness + 1) * 0x0a, zone_config.speed, 0x02, 0x02); + SendMultiColor(0xb0, mode, RGBGetRValue(zone_config.colors[0]), RGBGetGValue(zone_config.colors[0]), RGBGetBValue(zone_config.colors[0]), RGBGetRValue(zone_config.colors[1]), RGBGetGValue(zone_config.colors[1]), RGBGetBValue(zone_config.colors[1])); + SendMultiColor(0xb1, mode, RGBGetRValue(zone_config.colors[2]), RGBGetGValue(zone_config.colors[2]), RGBGetBValue(zone_config.colors[2]), RGBGetRValue(zone_config.colors[3]), RGBGetGValue(zone_config.colors[3]), RGBGetBValue(zone_config.colors[3])); + SendMultiColor(0xb2, mode, RGBGetRValue(zone_config.colors[4]), RGBGetGValue(zone_config.colors[4]), RGBGetBValue(zone_config.colors[4]), RGBGetRValue(zone_config.colors[5]), RGBGetGValue(zone_config.colors[5]), RGBGetBValue(zone_config.colors[5])); + SendMultiColor(0xb3, mode, RGBGetRValue(zone_config.colors[6]), RGBGetGValue(zone_config.colors[6]), RGBGetBValue(zone_config.colors[6]), RGBGetRValue(zone_config.colors[7]), RGBGetGValue(zone_config.colors[7]), RGBGetBValue(zone_config.colors[7])); + SendOk(); + } + break; + + case AORUS_ATC800_MODE_RAINBOW_LOOP: + { + if (zone == AORUS_ATC800_TOP_ZONE) + { + DisableTempRPMIndicator(); + SendMode(mode, (zone_config.brightness + 1) * 0x0a, zone_config.speed, 0x00, zone); + SendOk(); + } + else if (zone == AORUS_ATC800_FANS_ZONE) + { + SendMode(mode, (zone_config.brightness + 1) * 0x0a, zone_config.speed, 0x08, zone); + SendOk(); + } + } + break; + + case AORUS_ATC800_MODE_TRICOLOR: + { + if (zone == AORUS_ATC800_TOP_ZONE) + { + DisableTempRPMIndicator(); + SendMode(mode, (zone_config.brightness + 1) * 0x0a, zone_config.speed, 0x02, 0x00); + SendMultiColor(0xb0, mode, RGBGetRValue(zone_config.colors[0]), RGBGetGValue(zone_config.colors[0]), RGBGetBValue(zone_config.colors[0]), RGBGetRValue(zone_config.colors[1]), RGBGetGValue(zone_config.colors[1]), RGBGetBValue(zone_config.colors[1])); + SendMultiColor(0xb1, mode, RGBGetRValue(zone_config.colors[2]), RGBGetGValue(zone_config.colors[2]), RGBGetBValue(zone_config.colors[2]), 0x00, 0x00, 0x00); + SendMultiColor(0xb2, mode, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + SendMultiColor(0xb3, mode, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + SendOk(); + } + else if (zone == AORUS_ATC800_FANS_ZONE) + { + SendMode(mode, (zone_config.brightness + 1) * 0x0a, zone_config.speed, 0x02, 0x01); + SendMultiColor(0xb0, mode, RGBGetRValue(zone_config.colors[0]), RGBGetGValue(zone_config.colors[0]), RGBGetBValue(zone_config.colors[0]), RGBGetRValue(zone_config.colors[1]), RGBGetGValue(zone_config.colors[1]), RGBGetBValue(zone_config.colors[1])); + SendMultiColor(0xb1, mode, RGBGetRValue(zone_config.colors[2]), RGBGetGValue(zone_config.colors[2]), RGBGetBValue(zone_config.colors[2]), 0x00, 0x00, 0x00); + SendMultiColor(0xb2, mode, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + SendMultiColor(0xb3, mode, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + SendOk(); + } + } + break; + + } } diff --git a/Controllers/GigabyteAorusCPUCoolerController/ATC800Controller.h b/Controllers/GigabyteAorusCPUCoolerController/ATC800Controller.h index 3a70bc7a..8b6746c9 100644 --- a/Controllers/GigabyteAorusCPUCoolerController/ATC800Controller.h +++ b/Controllers/GigabyteAorusCPUCoolerController/ATC800Controller.h @@ -1,35 +1,55 @@ -/*-----------------------------------------*\ -| ATC800Controller.h | -| | -| Definitions and types for ATC800 CPU | -| Cooler | -| | -| Felipe Cavalcanti 08/13/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| ATC800Controller.h | +| | +| Driver for Aorus ATC800 cooler | +| | +| Felipe Cavalcanti 13 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + +struct aorus_atc800_mode_config +{ + RGBColor colors[8]; + uint8_t numberOfColors; + uint8_t speed; + uint8_t brightness; +}; + enum { AORUS_ATC800_MODE_OFF = 0x00, - AORUS_ATC800_MODE_STATIC = 0x01, - AORUS_ATC800_MODE_PULSE = 0x02, + AORUS_ATC800_MODE_CUSTOM = 0x01, + AORUS_ATC800_MODE_BREATHING = 0x02, + AORUS_ATC800_MODE_SPECTRUM_CYCLE = 0x03, AORUS_ATC800_MODE_FLASHING = 0x04, - AORUS_ATC800_MODE_DOUBLE_FLASH = 0x05, + AORUS_ATC800_MODE_DOUBLE_FLASHING = 0x05, + AORUS_ATC800_MODE_GRADIENT = 0x06, + AORUS_ATC800_MODE_COLOR_SHIFT = 0x07, + AORUS_ATC800_MODE_RAINBOW_WAVE = 0x08, + AORUS_ATC800_MODE_RADIATE = 0x09, + AORUS_ATC800_MODE_RAINBOW_LOOP = 0x0A, + AORUS_ATC800_MODE_TRICOLOR = 0x0B, }; enum { AORUS_ATC800_SPEED_SLOWEST = 0x00, /* Slowest speed */ - AORUS_ATC800_SPEED_SLOW = 0x01, /* Slow speed */ AORUS_ATC800_SPEED_NORMAL = 0x02, /* Normal speed */ - AORUS_ATC800_SPEED_FAST = 0x03, /* Fast speed */ - AORUS_ATC800_SPEED_FASTEST = 0x04, /* Fastest speed */ + AORUS_ATC800_SPEED_FASTEST = 0x05, /* Fastest speed */ +}; + +enum +{ + AORUS_ATC800_BRIGHTNESS_MIN = 0x00, + AORUS_ATC800_BRIGHTNESS_MAX = 0x05 }; enum @@ -41,23 +61,22 @@ enum class ATC800Controller { public: - ATC800Controller(hid_device* dev_handle, const char* path); + ATC800Controller(hid_device* dev_handle, const char* path, std::string name); ~ATC800Controller(); std::string GetDeviceLocation(); + std::string GetNameString(); std::string GetSerialString(); - void SendCoolerMode - ( - unsigned char mode, - unsigned short speed, - unsigned char channel, - unsigned char red, - unsigned char green, - unsigned char blue - ); + void DisableTempRPMIndicator(); + void SendMode(uint8_t mode, uint8_t brightness, uint8_t speed, uint8_t mystery_flag, uint8_t zone); + void SendOneColor(uint8_t color_flag, uint8_t red, uint8_t green, uint8_t blue); + void SendMultiColor(uint8_t flag, uint8_t mode, uint8_t red1, uint8_t green1, uint8_t blue1, uint8_t red2, uint8_t green2, uint8_t blue2); + void SendOk(); + void SendCoolerMode(uint8_t zone, uint8_t mode, aorus_atc800_mode_config zone_config); private: - hid_device* dev; - std::string location; + hid_device* dev; + std::string location; + std::string name; }; diff --git a/Controllers/GigabyteAorusCPUCoolerController/GigabyteAorusCPUCoolerControllerDetect.cpp b/Controllers/GigabyteAorusCPUCoolerController/GigabyteAorusCPUCoolerControllerDetect.cpp index 76037f1d..559d23de 100644 --- a/Controllers/GigabyteAorusCPUCoolerController/GigabyteAorusCPUCoolerControllerDetect.cpp +++ b/Controllers/GigabyteAorusCPUCoolerController/GigabyteAorusCPUCoolerControllerDetect.cpp @@ -1,8 +1,16 @@ +/*---------------------------------------------------------*\ +| GigabyteAorusCPUCoolerControllerDetect.cpp | +| | +| Detector for Gigabyte Aorus CPU coolers | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" -#include "RGBController.h" #include "ATC800Controller.h" #include "RGBController_AorusATC800.h" -#include /*-----------------------------------------------------*\ | Vendor ID | @@ -28,12 +36,11 @@ void DetectGigabyteAorusCPUCoolerControllers(hid_device_info* info, const std::s if(dev) { - ATC800Controller* controller = new ATC800Controller(dev, info->path); + ATC800Controller* controller = new ATC800Controller(dev, info->path, name); RGBController_AorusATC800* rgb_controller = new RGBController_AorusATC800(controller); - rgb_controller->name = name; - + ResourceManager::get()->RegisterRGBController(rgb_controller); } } -REGISTER_HID_DETECTOR_IPU("Aorus CPU Coolers", DetectGigabyteAorusCPUCoolerControllers, HOLTEK_VID, ATC_800_CONTROLLER_PID, 0, 0xFF01, 1); +REGISTER_HID_DETECTOR_IPU("Gigabyte AORUS ATC800", DetectGigabyteAorusCPUCoolerControllers, HOLTEK_VID, ATC_800_CONTROLLER_PID, 0, 0xFF01, 1); diff --git a/Controllers/GigabyteAorusCPUCoolerController/RGBController_AorusATC800.cpp b/Controllers/GigabyteAorusCPUCoolerController/RGBController_AorusATC800.cpp index a624439f..a812840f 100644 --- a/Controllers/GigabyteAorusCPUCoolerController/RGBController_AorusATC800.cpp +++ b/Controllers/GigabyteAorusCPUCoolerController/RGBController_AorusATC800.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_AorusATC800.cpp | -| | -| Generic RGB Interface Aorus ATC800 CPU | -| Cooler | -| | -| Felipe Cavalcanti 08/13/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AorusATC800.cpp | +| | +| RGBController for Aorus ATC800 cooler | +| | +| Felipe Cavalcanti 13 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_AorusATC800.h" @@ -22,58 +24,170 @@ RGBController_AorusATC800::RGBController_AorusATC800(ATC800Controller* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Aorus ATC800 CPU Cooler"; - vendor = "Gigabyte"; - type = DEVICE_TYPE_COOLER; - description = "Aorus ATC800 CPU Cooler"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "Gigabyte"; + type = DEVICE_TYPE_COOLER; + description = "Aorus ATC800 CPU Cooler Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); - mode Static; - Static.name = "Static"; - Static.value = AORUS_ATC800_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Static.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Static); + mode Custom; + Custom.name = "Custom"; + Custom.value = AORUS_ATC800_MODE_CUSTOM; + Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Custom.color_mode = MODE_COLORS_PER_LED; + Custom.brightness_min = AORUS_ATC800_BRIGHTNESS_MIN; + Custom.brightness_max = AORUS_ATC800_BRIGHTNESS_MAX; + Custom.brightness = AORUS_ATC800_BRIGHTNESS_MAX; + modes.push_back(Custom); mode Off; - Off.name = "Off"; - Off.value = AORUS_ATC800_MODE_OFF; - Off.flags = 0; - Off.color_mode = MODE_COLORS_NONE; + Off.name = "Off"; + Off.value = AORUS_ATC800_MODE_OFF; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; modes.push_back(Off); mode Flashing; - Flashing.name = "Flashing"; - Flashing.value = AORUS_ATC800_MODE_FLASHING; - Flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR; - Flashing.color_mode = MODE_COLORS_PER_LED; - Flashing.speed_min = AORUS_ATC800_SPEED_SLOWEST; - Flashing.speed_max = AORUS_ATC800_SPEED_FASTEST; - Flashing.speed = AORUS_ATC800_SPEED_NORMAL; + Flashing.name = "Flashing"; + Flashing.value = AORUS_ATC800_MODE_FLASHING; + Flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Flashing.color_mode = MODE_COLORS_PER_LED; + Flashing.speed_min = AORUS_ATC800_SPEED_SLOWEST; + Flashing.speed_max = AORUS_ATC800_SPEED_FASTEST; + Flashing.speed = AORUS_ATC800_SPEED_NORMAL; + Flashing.brightness_min = AORUS_ATC800_BRIGHTNESS_MIN; + Flashing.brightness_max = AORUS_ATC800_BRIGHTNESS_MAX; + Flashing.brightness = AORUS_ATC800_BRIGHTNESS_MAX; modes.push_back(Flashing); mode DoubleFlashing; - DoubleFlashing.name = "Double Flashing"; - DoubleFlashing.value = AORUS_ATC800_MODE_DOUBLE_FLASH; - DoubleFlashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR; - DoubleFlashing.color_mode = MODE_COLORS_PER_LED; - DoubleFlashing.speed_min = AORUS_ATC800_SPEED_SLOWEST; - DoubleFlashing.speed_max = AORUS_ATC800_SPEED_FASTEST; - DoubleFlashing.speed = AORUS_ATC800_SPEED_NORMAL; + DoubleFlashing.name = "Double Flashing"; + DoubleFlashing.value = AORUS_ATC800_MODE_DOUBLE_FLASHING; + DoubleFlashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + DoubleFlashing.color_mode = MODE_COLORS_PER_LED; + DoubleFlashing.speed_min = AORUS_ATC800_SPEED_SLOWEST; + DoubleFlashing.speed_max = AORUS_ATC800_SPEED_FASTEST; + DoubleFlashing.speed = AORUS_ATC800_SPEED_NORMAL; + DoubleFlashing.brightness_min = AORUS_ATC800_BRIGHTNESS_MIN; + DoubleFlashing.brightness_max = AORUS_ATC800_BRIGHTNESS_MAX; + DoubleFlashing.brightness = AORUS_ATC800_BRIGHTNESS_MAX; modes.push_back(DoubleFlashing); - mode Pulsing; - Pulsing.name = "Pulsing"; - Pulsing.value = AORUS_ATC800_MODE_PULSE; - Pulsing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR; - Pulsing.color_mode = MODE_COLORS_PER_LED; - Pulsing.speed_min = AORUS_ATC800_SPEED_SLOWEST; - Pulsing.speed_max = AORUS_ATC800_SPEED_FASTEST; - Pulsing.speed = AORUS_ATC800_SPEED_NORMAL; - modes.push_back(Pulsing); + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = AORUS_ATC800_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.speed_min = AORUS_ATC800_SPEED_SLOWEST; + Breathing.speed_max = AORUS_ATC800_SPEED_FASTEST; + Breathing.speed = AORUS_ATC800_SPEED_NORMAL; + modes.push_back(Breathing); + + mode Gradient; + Gradient.name = "Gradient"; + Gradient.value = AORUS_ATC800_MODE_GRADIENT; + Gradient.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Gradient.color_mode = MODE_COLORS_MODE_SPECIFIC; + Gradient.colors_min = 1; + Gradient.colors_max = 1; + Gradient.colors = { 0x0000FF }; + Gradient.speed_min = AORUS_ATC800_SPEED_SLOWEST; + Gradient.speed_max = AORUS_ATC800_SPEED_FASTEST; + Gradient.speed = AORUS_ATC800_SPEED_NORMAL; + Gradient.brightness_min = AORUS_ATC800_BRIGHTNESS_MIN; + Gradient.brightness_max = AORUS_ATC800_BRIGHTNESS_MAX; + Gradient.brightness = AORUS_ATC800_BRIGHTNESS_MAX; + modes.push_back(Gradient); + + mode ColorShift; + ColorShift.name = "Color Shift"; + ColorShift.value = AORUS_ATC800_MODE_COLOR_SHIFT; + ColorShift.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + ColorShift.color_mode = MODE_COLORS_MODE_SPECIFIC; + ColorShift.colors_min = 2; + ColorShift.colors_max = 8; + ColorShift.colors = { 0x0000FF, 0x0072FF, 0x00FFFF, 0x00FF00, 0xFFFF00, 0xFF0000, 0xFF00FF, 0x8080FF }; + ColorShift.speed_min = AORUS_ATC800_SPEED_SLOWEST; + ColorShift.speed_max = AORUS_ATC800_SPEED_FASTEST; + ColorShift.speed = AORUS_ATC800_SPEED_NORMAL; + ColorShift.brightness_min = AORUS_ATC800_BRIGHTNESS_MIN; + ColorShift.brightness_max = AORUS_ATC800_BRIGHTNESS_MAX; + ColorShift.brightness = AORUS_ATC800_BRIGHTNESS_MAX; + modes.push_back(ColorShift); + + mode RainbowWave; + RainbowWave.name = "Rainbow Wave"; + RainbowWave.value = AORUS_ATC800_MODE_RAINBOW_WAVE; + RainbowWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + RainbowWave.color_mode = MODE_COLORS_NONE; + RainbowWave.speed_min = AORUS_ATC800_SPEED_SLOWEST; + RainbowWave.speed_max = AORUS_ATC800_SPEED_FASTEST; + RainbowWave.speed = AORUS_ATC800_SPEED_NORMAL; + RainbowWave.brightness_min = AORUS_ATC800_BRIGHTNESS_MIN; + RainbowWave.brightness_max = AORUS_ATC800_BRIGHTNESS_MAX; + RainbowWave.brightness = AORUS_ATC800_BRIGHTNESS_MAX; + modes.push_back(RainbowWave); + + mode Radiate; + Radiate.name = "Radiate"; + Radiate.value = AORUS_ATC800_MODE_RADIATE; + Radiate.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Radiate.color_mode = MODE_COLORS_MODE_SPECIFIC; + Radiate.colors_min = 8; + Radiate.colors_max = 8; + Radiate.colors = { 0x0000FF, 0x0072FF, 0x00FFFF, 0x00FF00, 0xFFFF00, 0xFFFF00, 0xFF00FF, 0x8080FF }; + Radiate.speed_min = AORUS_ATC800_SPEED_SLOWEST; + Radiate.speed_max = AORUS_ATC800_SPEED_FASTEST; + Radiate.speed = AORUS_ATC800_SPEED_NORMAL; + Radiate.brightness_min = AORUS_ATC800_BRIGHTNESS_MIN; + Radiate.brightness_max = AORUS_ATC800_BRIGHTNESS_MAX; + Radiate.brightness = AORUS_ATC800_BRIGHTNESS_MAX; + modes.push_back(Radiate); + + mode RainbowLoop; + RainbowLoop.name = "Rainbow Loop"; + RainbowLoop.value = AORUS_ATC800_MODE_RAINBOW_LOOP; + RainbowLoop.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + RainbowLoop.color_mode = MODE_COLORS_NONE; + RainbowLoop.speed_min = AORUS_ATC800_SPEED_SLOWEST; + RainbowLoop.speed_max = AORUS_ATC800_SPEED_FASTEST; + RainbowLoop.speed = AORUS_ATC800_SPEED_NORMAL; + RainbowLoop.brightness_min = AORUS_ATC800_BRIGHTNESS_MIN; + RainbowLoop.brightness_max = AORUS_ATC800_BRIGHTNESS_MAX; + RainbowLoop.brightness = AORUS_ATC800_BRIGHTNESS_MAX; + modes.push_back(RainbowLoop); + + mode Tricolor; + Tricolor.name = "Tricolor"; + Tricolor.value = AORUS_ATC800_MODE_TRICOLOR; + Tricolor.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Tricolor.color_mode = MODE_COLORS_MODE_SPECIFIC; + Tricolor.colors_min = 3; + Tricolor.colors_max = 3; + Tricolor.colors = { 0xFF0000, 0xFF00FF, 0xFFFF00 }; + Tricolor.speed_min = AORUS_ATC800_SPEED_SLOWEST; + Tricolor.speed_max = AORUS_ATC800_SPEED_FASTEST; + Tricolor.speed = AORUS_ATC800_SPEED_NORMAL; + Tricolor.brightness_min = AORUS_ATC800_BRIGHTNESS_MIN; + Tricolor.brightness_max = AORUS_ATC800_BRIGHTNESS_MAX; + Tricolor.brightness = AORUS_ATC800_BRIGHTNESS_MAX; + modes.push_back(Tricolor); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = AORUS_ATC800_MODE_SPECTRUM_CYCLE; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.speed_min = AORUS_ATC800_SPEED_SLOWEST; + SpectrumCycle.speed_max = AORUS_ATC800_SPEED_FASTEST; + SpectrumCycle.speed = AORUS_ATC800_SPEED_NORMAL; + SpectrumCycle.brightness_min = AORUS_ATC800_BRIGHTNESS_MIN; + SpectrumCycle.brightness_max = AORUS_ATC800_BRIGHTNESS_MAX; + SpectrumCycle.brightness = AORUS_ATC800_BRIGHTNESS_MAX; + modes.push_back(SpectrumCycle); SetupZones(); } @@ -129,20 +243,22 @@ void RGBController_AorusATC800::DeviceUpdateLEDs() void RGBController_AorusATC800::UpdateZoneLEDs(int zone) { - unsigned char mode = modes[active_mode].value; - unsigned char red = RGBGetRValue(colors[zone]); - unsigned char grn = RGBGetGValue(colors[zone]); - unsigned char blu = RGBGetBValue(colors[zone]); + aorus_atc800_mode_config zone_config; - if(mode == AORUS_ATC800_MODE_OFF) + zone_config.colors[0] = colors[zone]; + zone_config.numberOfColors = (uint8_t)modes[active_mode].colors.size(); + zone_config.speed = modes[active_mode].speed; + zone_config.brightness = modes[active_mode].brightness; + + if (modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) { - mode = 1; - red = 0; - grn = 0; - blu = 0; + for (uint8_t i = 0; i < zone_config.numberOfColors; i++) + { + zone_config.colors[i] = modes[active_mode].colors[i]; + } } - controller->SendCoolerMode(mode, modes[active_mode].speed, zone, red, grn, blu); + controller->SendCoolerMode(zone, modes[active_mode].value, zone_config); } void RGBController_AorusATC800::UpdateSingleLED(int led) diff --git a/Controllers/GigabyteAorusCPUCoolerController/RGBController_AorusATC800.h b/Controllers/GigabyteAorusCPUCoolerController/RGBController_AorusATC800.h index 7633269d..2cf7b6ba 100644 --- a/Controllers/GigabyteAorusCPUCoolerController/RGBController_AorusATC800.h +++ b/Controllers/GigabyteAorusCPUCoolerController/RGBController_AorusATC800.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_AorusATC800.h | -| | -| Generic RGB Interface for Aorus ATC 800 | -| CPU Cooler | -| | -| Felipe Cavalcanti 08/13/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_AorusATC800.h | +| | +| RGBController for Aorus ATC800 cooler | +| | +| Felipe Cavalcanti 13 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "ATC800Controller.h" diff --git a/Controllers/GigabyteAorusLaptopController/GigabyteAorusLaptopController.cpp b/Controllers/GigabyteAorusLaptopController/GigabyteAorusLaptopController.cpp new file mode 100644 index 00000000..cc869df9 --- /dev/null +++ b/Controllers/GigabyteAorusLaptopController/GigabyteAorusLaptopController.cpp @@ -0,0 +1,274 @@ +/*---------------------------------------------------------*\ +| GigabyteAorusLaptopController.cpp | +| | +| Driver for Gigabyte Aorus laptop | +| | +| Morgan Guimard (morg) 05 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "GigabyteAorusLaptopController.h" +#include "StringUtils.h" + +/*---------------------------------------------------------*\ +| Indexed colors mapping | +| blue 04 | +| green 02 | +| orange 05 | +| purple 06 | +| red 01 | +| white 07 | +| yellow 03 | +\*---------------------------------------------------------*/ +static unsigned char argb_colour_index_data[2][2][2] = + { //B0 B1 + { { 0x01, 0x04 }, //G0 R0 + { 0x02, 0x04 }, }, //G1 R0 + { { 0x01, 0x06 }, //G0 R1 + { 0x05, 0x07 }, } //G1 R1 +}; + +GigabyteAorusLaptopController::GigabyteAorusLaptopController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) +{ + dev = dev_handle; + location = info.path; + name = dev_name; +} + +GigabyteAorusLaptopController::~GigabyteAorusLaptopController() +{ + hid_close(dev); +} + +std::string GigabyteAorusLaptopController::GetNameString() +{ + return(name); +} + +std::string GigabyteAorusLaptopController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string GigabyteAorusLaptopController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void GigabyteAorusLaptopController::SetDirect(uint8_t brightness, RGBColor color) +{ + /*---------------------------------------------------------*\ + | Direct mode protocol | + | ID C R G B Br C Ch | + | 08 01 00 00 FF 32 00 C5 | + | | + | C = constant | + | RGB = color | + | Br= brightness | + | Ch = checksum: 0xFF - all bytes | + \*---------------------------------------------------------*/ + + unsigned char usb_buf[GIGABYTE_AORUS_LAPTOP_REPORT_SIZE+1]; + memset(usb_buf, 0x00, GIGABYTE_AORUS_LAPTOP_REPORT_SIZE+1); + + usb_buf[1] = GIGABYTE_AORUS_LAPTOP_REPORT_ID; + usb_buf[2] = 0x01; + usb_buf[3] = RGBGetRValue(color); + usb_buf[4] = RGBGetGValue(color); + usb_buf[5] = RGBGetBValue(color); + usb_buf[6] = brightness; + + unsigned char checksum = 0xFF; + + for(unsigned int i = 1; i < 8; i++) + { + checksum -= usb_buf[i]; + } + + usb_buf[8] = checksum; + + hid_send_feature_report(dev, usb_buf, GIGABYTE_AORUS_LAPTOP_REPORT_SIZE+1); +} + +void GigabyteAorusLaptopController::SetMode(uint8_t mode_value, uint8_t speed, uint8_t brightness, uint8_t direction, RGBColor color) +{ + /*---------------------------------------------------------*\ + | Hardware mode protocol | + | ID C M Sp Br Cl Dr Ch | + | 08 00 01 08 32 01 00 XX | + | | + | C = constant | + | M = mode | + | Sp = speed | + | Br = brightness | + | Cl = Indexed color | + | Dr = Direction | + | Ch = checksum: 0xFF - all bytes | + \*---------------------------------------------------------*/ + + unsigned char red = RGBGetRValue(color); + unsigned char grn = RGBGetGValue(color); + unsigned char blu = RGBGetBValue(color); + + unsigned char indexed_color = GetColourIndex(red,grn,blu); + + unsigned char usb_buf[GIGABYTE_AORUS_LAPTOP_REPORT_SIZE+1]; + memset(usb_buf, 0x00, GIGABYTE_AORUS_LAPTOP_REPORT_SIZE+1); + + usb_buf[1] = GIGABYTE_AORUS_LAPTOP_REPORT_ID; // report id + + usb_buf[3] = mode_value; // mode value + usb_buf[4] = speed; // speed 0x01 -> 0x09 + usb_buf[5] = brightness; // brightness 0x00 -> 0x32 + usb_buf[6] = indexed_color; // color (red, orange, yellow, green, blue, purple, white) + usb_buf[7] = direction; // direction 0x01: right, 0x02 left, 0x03 up , 0x04 down + + unsigned char checksum = 0xFF; + + for(unsigned int i = 1; i < 8; i++) + { + checksum -= usb_buf[i]; + } + + usb_buf[8] = checksum; // checksum + + hid_send_feature_report(dev, usb_buf, GIGABYTE_AORUS_LAPTOP_REPORT_SIZE+1); +} + +unsigned char GigabyteAorusLaptopController::GetColourIndex(unsigned char red, unsigned char green, unsigned char blue) +{ + /*-----------------------------------------------------*\ + | This device uses a limited colour pallette referenced | + | by an index | + | 0x01 red | + | 0x02 orange | + | 0x03 yellow | + | 0x04 green | + | 0x05 blue | + | 0x06 purple | + | 0x07 white | + \*-----------------------------------------------------*/ + unsigned int divisor = GetLargestColour( red, green, blue); + unsigned int r = (int)round( red / divisor ); + unsigned int g = (int)round( green / divisor ); + unsigned int b = (int)round( blue / divisor ); + unsigned char idx = argb_colour_index_data[r][g][b]; + return idx; +} + +unsigned int GigabyteAorusLaptopController::GetLargestColour(unsigned int red, unsigned int green, unsigned int blue) +{ + unsigned int largest; + + if ( red > green ) + { + ( red > blue ) ? largest = red : largest = blue; + } + else + { + ( green > blue ) ? largest = green : largest = blue; + } + + return (largest == 0) ? 1 : largest; +} + +void GigabyteAorusLaptopController::SetCustom(std::vector colors, std::vector positions, unsigned char brightness) +{ + /*---------------------------------------------------------*\ + | Custom mode protocol | + | ID C M Sp Br Cl Dr Ch | + | 08 00 33 01 2D 05 01 90 | + | 92 00 00 00 00 00 00 6D -> | + | GET REPORT REQUEST <- | + | read 8x64 bytes <- | + | 12 00 00 08 00 00 00 E5 -> | + | 00 RR GG BB ..... -> data (8 * 64 bytes) | + \*---------------------------------------------------------*/ + + /*---------------------------------------------------------*\ + | Sends mode packet | + \*---------------------------------------------------------*/ + unsigned char usb_buf[GIGABYTE_AORUS_LAPTOP_REPORT_SIZE+1]; + memset(usb_buf, 0x00, GIGABYTE_AORUS_LAPTOP_REPORT_SIZE+1); + + usb_buf[1] = GIGABYTE_AORUS_LAPTOP_REPORT_ID; + usb_buf[3] = GIGABYTE_AORUS_LAPTOP_CUSTOM_MODE_VALUE; + usb_buf[4] = 0x01; + usb_buf[5] = brightness; + usb_buf[6] = 0x05; + usb_buf[7] = 0x01; + + unsigned char checksum = 0xFF; + + for(unsigned int i = 1; i < 8; i++) + { + checksum -= usb_buf[i]; + } + + usb_buf[8] = checksum; + + hid_send_feature_report(dev, usb_buf, GIGABYTE_AORUS_LAPTOP_REPORT_SIZE+1); + + /*---------------------------------------------------------*\ + | Sends first packet | + \*---------------------------------------------------------*/ + unsigned char start_packet[GIGABYTE_AORUS_LAPTOP_REPORT_SIZE+1] = + { + 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D + }; + + hid_send_feature_report(dev, start_packet, GIGABYTE_AORUS_LAPTOP_REPORT_SIZE+1); + + /*---------------------------------------------------------*\ + | GET REPORT REQUEST | + \*---------------------------------------------------------*/ + unsigned char report_packet[GIGABYTE_AORUS_LAPTOP_REPORT_SIZE+1]; + memset(report_packet, 0x00, GIGABYTE_AORUS_LAPTOP_REPORT_SIZE+1); + + report_packet[1] = GIGABYTE_AORUS_LAPTOP_REPORT_ID; + hid_get_feature_report(dev, report_packet, GIGABYTE_AORUS_LAPTOP_REPORT_SIZE+1); + + /*---------------------------------------------------------*\ + | Sends 2nd packet | + \*---------------------------------------------------------*/ + unsigned char second_packet[GIGABYTE_AORUS_LAPTOP_REPORT_SIZE+1] = + { + 0x00, 0x12, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xE5 + }; + + hid_send_feature_report(dev, second_packet, GIGABYTE_AORUS_LAPTOP_REPORT_SIZE+1); + + /*---------------------------------------------------------*\ + | Creates the data packets | + \*---------------------------------------------------------*/ + unsigned char color_data[64 * 8]; + memset(color_data, 0x00, 64 * 8); + + for(unsigned int i = 0; i < positions.size(); i++) + { + color_data[positions[i] * 4 + 1] = RGBGetRValue(colors[i]); + color_data[positions[i] * 4 + 2] = RGBGetGValue(colors[i]); + color_data[positions[i] * 4 + 3] = RGBGetBValue(colors[i]); + } + + unsigned char color_buf[64 + 1]; + color_buf[0] = 0; + + for(unsigned int i = 0; i < 8; i++) + { + memcpy(&color_buf[1], &(color_data[64*i]), 64); + hid_write(dev, color_buf, 65); + } +} diff --git a/Controllers/GigabyteAorusLaptopController/GigabyteAorusLaptopController.h b/Controllers/GigabyteAorusLaptopController/GigabyteAorusLaptopController.h new file mode 100644 index 00000000..8bfc040d --- /dev/null +++ b/Controllers/GigabyteAorusLaptopController/GigabyteAorusLaptopController.h @@ -0,0 +1,73 @@ +/*---------------------------------------------------------*\ +| GigabyteAorusLaptopController.h | +| | +| Driver for Gigabyte Aorus laptop | +| | +| Morgan Guimard (morg) 05 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define GIGABYTE_AORUS_LAPTOP_REPORT_SIZE 8 +#define GIGABYTE_AORUS_LAPTOP_REPORT_ID 0x08 + +enum +{ + GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN = 0x00, + GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX = 0x32, + GIGABYTE_AORUS_LAPTOP_SPEED_MIN = 0x01, + GIGABYTE_AORUS_LAPTOP_SPEED_MAX = 0x09 +}; + +enum +{ + GIGABYTE_AORUS_LAPTOP_DIRECT_MODE_VALUE = 0x00, + GIGABYTE_AORUS_LAPTOP_STATIC_MODE_VALUE = 0x01, + GIGABYTE_AORUS_LAPTOP_PULSE_MODE_VALUE = 0x02, + GIGABYTE_AORUS_LAPTOP_WAVE_MODE_VALUE = 0x03, + GIGABYTE_AORUS_LAPTOP_REACTIVE_MODE_VALUE = 0x04, + GIGABYTE_AORUS_LAPTOP_MARQUEE_MODE_VALUE = 0x05, + GIGABYTE_AORUS_LAPTOP_RIPPLE_MODE_VALUE = 0x06, + GIGABYTE_AORUS_LAPTOP_CYCLE_MODE_VALUE = 0x08, + GIGABYTE_AORUS_LAPTOP_RAINBOW_MARQUEE_MODE_VALUE = 0x09, + GIGABYTE_AORUS_LAPTOP_DROPLET_MODE_VALUE = 0x0A, + GIGABYTE_AORUS_LAPTOP_CIRCLE_MARQUEE_MODE_VALUE = 0x0B, + GIGABYTE_AORUS_LAPTOP_HEDGE_MODE_VALUE = 0x0C, + GIGABYTE_AORUS_LAPTOP_SPIRAL_MODE_VALUE = 0x0D, + GIGABYTE_AORUS_LAPTOP_CURTAIN_MODE_VALUE = 0x40, + GIGABYTE_AORUS_LAPTOP_COMET_MODE_VALUE = 0x41, + GIGABYTE_AORUS_LAPTOP_CHASE_MODE_VALUE = 0x43, + GIGABYTE_AORUS_LAPTOP_CUSTOM_MODE_VALUE = 0x33 +}; + +class GigabyteAorusLaptopController +{ +public: + GigabyteAorusLaptopController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~GigabyteAorusLaptopController(); + + std::string GetNameString(); + std::string GetSerialString(); + std::string GetDeviceLocation(); + + void SetDirect(uint8_t brightness, RGBColor color); + void SetMode(uint8_t mode_value, uint8_t speed, uint8_t brightness, uint8_t direction, RGBColor color); + void SetCustom(std::vector colors, std::vector positions, unsigned char brightness); + +protected: + hid_device* dev; + +private: + unsigned int GetLargestColour(unsigned int red, unsigned int green, unsigned int blue); + unsigned char GetColourIndex(unsigned char red, unsigned char green, unsigned char blue); + + std::string location; + std::string name; +}; diff --git a/Controllers/GigabyteAorusLaptopController/GigabyteAorusLaptopControllerDetect.cpp b/Controllers/GigabyteAorusLaptopController/GigabyteAorusLaptopControllerDetect.cpp new file mode 100644 index 00000000..80f5b25b --- /dev/null +++ b/Controllers/GigabyteAorusLaptopController/GigabyteAorusLaptopControllerDetect.cpp @@ -0,0 +1,56 @@ +/*---------------------------------------------------------*\ +| GigabyteAorusLaptopControllerDetect.cpp | +| | +| Detector for Gigabyte Aorus laptop | +| | +| Morgan Guimard (morg) 05 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "GigabyteAorusLaptopController.h" +#include "RGBController_GigabyteAorusLaptop.h" + +/*---------------------------------------------------------*\ +| Gigabyte vendor ID | +\*---------------------------------------------------------*/ +#define GIGABYTE_AORUS_LAPTOP_VID 0x0414 + +/*---------------------------------------------------------*\ +| AORUS Laptops PID | +\*---------------------------------------------------------*/ +#define AORUS_17X_BACKLIGHT_PID 0x7A42 +#define AORUS_17X_KEYBOARD_PID 0x7A3F + +#define AORUS_15BKF_BACKLIGHT_PID 0x7A44 +#define AORUS_15BKF_KEYBOARD_PID 0x7A43 + +void DetectGigabyteAorusLaptopControllers(hid_device_info* info, const std::string& name, GIGABYTE_AORUS_LAPTOP_DEV_TYPE dev_type) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + GigabyteAorusLaptopController* controller = new GigabyteAorusLaptopController(dev, *info, name); + RGBController_GigabyteAorusLaptop* rgb_controller = new RGBController_GigabyteAorusLaptop(controller, dev_type); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectGigabyteAorusLaptopKeyboardControllers(hid_device_info* info, const std::string& name) +{ + DetectGigabyteAorusLaptopControllers(info, name, GIGABYTE_AORUS_LAPTOP_KEYBOARD_TYPE); +} + +void DetectGigabyteAorusLaptopBacklightControllers(hid_device_info* info, const std::string& name) +{ + DetectGigabyteAorusLaptopControllers(info, name, GIGABYTE_AORUS_LAPTOP_BACKLIGHT_TYPE); +} + +REGISTER_HID_DETECTOR_IPU("Gigabyte Aorus 17X Keyboard", DetectGigabyteAorusLaptopKeyboardControllers, GIGABYTE_AORUS_LAPTOP_VID, AORUS_17X_KEYBOARD_PID, 3, 0xFF01, 0x01); +REGISTER_HID_DETECTOR_IPU("Gigabyte Aorus 17X Backlight", DetectGigabyteAorusLaptopBacklightControllers, GIGABYTE_AORUS_LAPTOP_VID, AORUS_17X_BACKLIGHT_PID, 3, 0xFF01, 0x01); +REGISTER_HID_DETECTOR_IPU("Gigabyte Aorus 15BKF Keyboard", DetectGigabyteAorusLaptopKeyboardControllers, GIGABYTE_AORUS_LAPTOP_VID, AORUS_15BKF_KEYBOARD_PID, 3, 0xFF01, 0x01); +REGISTER_HID_DETECTOR_IPU("Gigabyte Aorus 15BKF Backlight", DetectGigabyteAorusLaptopBacklightControllers, GIGABYTE_AORUS_LAPTOP_VID, AORUS_15BKF_BACKLIGHT_PID, 3, 0xFF01, 0x01); diff --git a/Controllers/GigabyteAorusLaptopController/RGBController_GigabyteAorusLaptop.cpp b/Controllers/GigabyteAorusLaptopController/RGBController_GigabyteAorusLaptop.cpp new file mode 100644 index 00000000..5a9c74d3 --- /dev/null +++ b/Controllers/GigabyteAorusLaptopController/RGBController_GigabyteAorusLaptop.cpp @@ -0,0 +1,502 @@ +/*---------------------------------------------------------*\ +| RGBController_GigabyteAorusLaptop.cpp | +| | +| RGBController for Gigabyte Aorus laptop | +| | +| Morgan Guimard (morg) 05 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_GigabyteAorusLaptop.h" +#include "RGBControllerKeyNames.h" + +/**------------------------------------------------------------------*\ + @name Aorus Laptop + @category + @type USB + @save :robot: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectGigabyteAorusLaptopKeyboardControllers,DetectGigabyteAorusLaptopBacklightControllers + @comment Direct mode will only exposes the whole keyboard as one + big led, only custom mode can do real per key lightning. + This is impossible to determine if it auto saves to flash + (the battery cannot be removed) then we assume it does. + This device has 5 onboard memory profiles, we only use + the first one. +\*-------------------------------------------------------------------*/ + +#define NA 0xFFFFFFFF + +typedef struct +{ + const unsigned int width; /* matrix width */ + const unsigned int height; /* matrix height */ + std::vector> matrix_map; /* matrix map */ + std::vector led_names; /* led names */ + std::vector led_sequence_positions; /* position in buffers */ +} aorus_laptop_keyboard_layout; + +static aorus_laptop_keyboard_layout aorus_laptop_default_keyboard_layout = +{ + 19, + 6, + { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}, // 19 + { 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, NA, 32, 33, 34, 35, 36}, // 18 + { 37, NA, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54}, // 18 + { 55, NA, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, NA, 67, 68, 69, 70, NA}, // 16 + { 71, NA, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, NA, 82, 83, 84, 85, 86, 87}, // 17 + { 88, 89, 90, 91, NA, NA, NA, 92, NA, NA, 93, 94, 95, 96, 97, 98, 99, 100, NA} // 13 + }, + { + KEY_EN_ESCAPE, KEY_EN_F1, KEY_EN_F2, KEY_EN_F3, KEY_EN_F4, KEY_EN_F5, KEY_EN_F6, KEY_EN_F7, KEY_EN_F8, KEY_EN_F9, KEY_EN_F10, KEY_EN_F11, KEY_EN_F12, KEY_EN_PAUSE_BREAK, KEY_EN_DELETE, KEY_EN_HOME, KEY_EN_PAGE_UP, KEY_EN_PAGE_DOWN, KEY_EN_END, + KEY_EN_BACK_TICK, KEY_EN_1, KEY_EN_2, KEY_EN_3, KEY_EN_4, KEY_EN_5, KEY_EN_6, KEY_EN_7, KEY_EN_8, KEY_EN_9, KEY_EN_0, KEY_EN_MINUS, KEY_EN_EQUALS, KEY_EN_BACKSPACE, KEY_EN_NUMPAD_LOCK, KEY_EN_NUMPAD_DIVIDE, KEY_EN_NUMPAD_TIMES, KEY_EN_NUMPAD_MINUS, + KEY_EN_TAB, KEY_EN_Q, KEY_EN_W, KEY_EN_E, KEY_EN_R, KEY_EN_T, KEY_EN_Y, KEY_EN_U, KEY_EN_I, KEY_EN_O, KEY_EN_P, KEY_EN_LEFT_BRACKET, KEY_EN_RIGHT_BRACKET, KEY_EN_BACK_SLASH, KEY_EN_NUMPAD_7, KEY_EN_NUMPAD_8, KEY_EN_NUMPAD_9, KEY_EN_NUMPAD_PLUS, + KEY_EN_CAPS_LOCK, KEY_EN_A, KEY_EN_S, KEY_EN_D, KEY_EN_F, KEY_EN_G, KEY_EN_H, KEY_EN_J, KEY_EN_K, KEY_EN_L, KEY_EN_SEMICOLON, KEY_EN_QUOTE, KEY_EN_ISO_ENTER, KEY_EN_NUMPAD_4, KEY_EN_NUMPAD_5, KEY_EN_NUMPAD_6, + KEY_EN_LEFT_SHIFT, KEY_EN_Z, KEY_EN_X, KEY_EN_C, KEY_EN_V, KEY_EN_B, KEY_EN_N, KEY_EN_M, KEY_EN_COMMA, KEY_EN_PERIOD, KEY_EN_FORWARD_SLASH, KEY_EN_RIGHT_SHIFT, KEY_EN_UP_ARROW, KEY_EN_NUMPAD_1, KEY_EN_NUMPAD_2, KEY_EN_NUMPAD_3, KEY_EN_NUMPAD_ENTER, + KEY_EN_LEFT_CONTROL, KEY_EN_LEFT_FUNCTION, KEY_EN_LEFT_WINDOWS, KEY_EN_LEFT_ALT, KEY_EN_SPACE, KEY_EN_RIGHT_ALT, KEY_EN_MENU, KEY_EN_RIGHT_CONTROL, KEY_EN_LEFT_ARROW, KEY_EN_DOWN_ARROW, KEY_EN_RIGHT_ARROW, KEY_EN_NUMPAD_0, KEY_EN_NUMPAD_PERIOD + }, + { + 11, 17, 23, 29, 35, 41, 47, 53, 59, 65, 71, 77, 83, 89, 95, 101, 107, 113, 119, + 10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, 76, 82, 94, 100, 106, 112, 118, + 9, 15, 21, 27, 33, 39, 45, 51, 57, 63, 69, 75, 81, 87, 99, 105, 111, 116, + 8, 14, 20, 26, 32, 38, 44, 50, 56, 62, 68, 74, 92, 98, 104, 110, + 7, 19, 25, 31, 37, 43, 49, 55, 61, 67, 73, 85, 91, 97, 103, 109, 114, + 6, 12, 18, 24, 42, 60, 66, 72, 84, 90, 96, 102, 108 + } +}; + + +RGBController_GigabyteAorusLaptop::RGBController_GigabyteAorusLaptop(GigabyteAorusLaptopController* controller_ptr, GIGABYTE_AORUS_LAPTOP_DEV_TYPE dev_type) +{ + this->dev_type = dev_type; + controller = controller_ptr; + name = controller->GetNameString(); + vendor = "Gigabyte"; + type = DEVICE_TYPE_LAPTOP; + description = "Aorus Laptop"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + /*---------------------------------------------------------*\ + | Only keyboard supports Direct mode | + \*---------------------------------------------------------*/ + if(dev_type == GIGABYTE_AORUS_LAPTOP_KEYBOARD_TYPE) + { + mode Direct; + Direct.name = "Direct"; + Direct.value = GIGABYTE_AORUS_LAPTOP_DIRECT_MODE_VALUE; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + Direct.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + Direct.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + modes.push_back(Direct); + } + + /*---------------------------------------------------------*\ + | Common modes to keyboard + backlight | + \*---------------------------------------------------------*/ + mode Static; + Static.name = "Static"; + Static.value = GIGABYTE_AORUS_LAPTOP_STATIC_MODE_VALUE; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors.resize(1); + Static.colors_min = 1; + Static.colors_max = 1; + Static.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + Static.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + Static.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + modes.push_back(Static); + + mode Pulse; + Pulse.name = "Breathing"; + Pulse.value = GIGABYTE_AORUS_LAPTOP_PULSE_MODE_VALUE; + Pulse.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Pulse.color_mode = MODE_COLORS_MODE_SPECIFIC; + Pulse.colors.resize(1); + Pulse.colors_min = 1; + Pulse.colors_max = 1; + Pulse.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + Pulse.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + Pulse.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + Pulse.speed_min = GIGABYTE_AORUS_LAPTOP_SPEED_MIN; + Pulse.speed_max = GIGABYTE_AORUS_LAPTOP_SPEED_MAX; + Pulse.speed = GIGABYTE_AORUS_LAPTOP_SPEED_MAX/2; + modes.push_back(Pulse); + + mode Wave; + Wave.name = "Rainbow Wave"; + Wave.value = GIGABYTE_AORUS_LAPTOP_WAVE_MODE_VALUE; + Wave.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_AUTOMATIC_SAVE; + Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; + Wave.colors.resize(1); + Wave.colors_min = 1; + Wave.colors_max = 1; + Wave.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + Wave.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + Wave.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + Wave.speed_min = GIGABYTE_AORUS_LAPTOP_SPEED_MIN; + Wave.speed_max = GIGABYTE_AORUS_LAPTOP_SPEED_MAX; + Wave.speed = GIGABYTE_AORUS_LAPTOP_SPEED_MAX/2; + Wave.direction = MODE_DIRECTION_LEFT; + modes.push_back(Wave); + + mode Cycle; + Cycle.name = "Spectrum Cycle"; + Cycle.value = GIGABYTE_AORUS_LAPTOP_CYCLE_MODE_VALUE; + Cycle.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Cycle.color_mode = MODE_COLORS_MODE_SPECIFIC; + Cycle.colors.resize(1); + Cycle.colors_min = 1; + Cycle.colors_max = 1; + Cycle.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + Cycle.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + Cycle.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + Cycle.speed_min = GIGABYTE_AORUS_LAPTOP_SPEED_MIN; + Cycle.speed_max = GIGABYTE_AORUS_LAPTOP_SPEED_MAX; + Cycle.speed = GIGABYTE_AORUS_LAPTOP_SPEED_MAX/2; + modes.push_back(Cycle); + + mode Droplet; + Droplet.name = "Droplet"; + Droplet.value = GIGABYTE_AORUS_LAPTOP_DROPLET_MODE_VALUE; + Droplet.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Droplet.color_mode = MODE_COLORS_MODE_SPECIFIC; + Droplet.colors.resize(1); + Droplet.colors_min = 1; + Droplet.colors_max = 1; + Droplet.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + Droplet.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + Droplet.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + Droplet.speed_min = GIGABYTE_AORUS_LAPTOP_SPEED_MIN; + Droplet.speed_max = GIGABYTE_AORUS_LAPTOP_SPEED_MAX; + Droplet.speed = GIGABYTE_AORUS_LAPTOP_SPEED_MAX/2; + modes.push_back(Droplet); + + mode Spiral; + Spiral.name = "Spiral"; + Spiral.value = GIGABYTE_AORUS_LAPTOP_SPIRAL_MODE_VALUE; + Spiral.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_AUTOMATIC_SAVE; + Spiral.color_mode = MODE_COLORS_MODE_SPECIFIC; + Spiral.colors.resize(1); + Spiral.colors_min = 1; + Spiral.colors_max = 1; + Spiral.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + Spiral.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + Spiral.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + Spiral.speed_min = GIGABYTE_AORUS_LAPTOP_SPEED_MIN; + Spiral.speed_max = GIGABYTE_AORUS_LAPTOP_SPEED_MAX; + Spiral.speed = GIGABYTE_AORUS_LAPTOP_SPEED_MAX/2; + Spiral.direction = MODE_DIRECTION_LEFT; + modes.push_back(Spiral); + + /*---------------------------------------------------------*\ + | Modes for backlight only | + \*---------------------------------------------------------*/ + if(dev_type == GIGABYTE_AORUS_LAPTOP_BACKLIGHT_TYPE) + { + mode Curtain; + Curtain.name = "Curtain"; + Curtain.value = GIGABYTE_AORUS_LAPTOP_CURTAIN_MODE_VALUE; + Curtain.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Curtain.color_mode = MODE_COLORS_MODE_SPECIFIC; + Curtain.colors.resize(1); + Curtain.colors_min = 1; + Curtain.colors_max = 1; + Curtain.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + Curtain.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + Curtain.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + modes.push_back(Curtain); + + mode Comet; + Comet.name = "Comet"; + Comet.value = GIGABYTE_AORUS_LAPTOP_COMET_MODE_VALUE; + Comet.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Comet.color_mode = MODE_COLORS_MODE_SPECIFIC; + Comet.colors.resize(1); + Comet.colors_min = 1; + Comet.colors_max = 1; + Comet.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + Comet.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + Comet.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + modes.push_back(Comet); + + mode Chase; + Chase.name = "Chase"; + Chase.value = GIGABYTE_AORUS_LAPTOP_CHASE_MODE_VALUE; + Chase.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Chase.color_mode = MODE_COLORS_MODE_SPECIFIC; + Chase.colors.resize(1); + Chase.colors_min = 1; + Chase.colors_max = 1; + Chase.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + Chase.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + Chase.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + modes.push_back(Chase); + } + + /*---------------------------------------------------------*\ + | Modes for keyboard only | + \*---------------------------------------------------------*/ + if(dev_type == GIGABYTE_AORUS_LAPTOP_KEYBOARD_TYPE) + { + mode Reactive; + Reactive.name = "Reactive"; + Reactive.value = GIGABYTE_AORUS_LAPTOP_REACTIVE_MODE_VALUE; + Reactive.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Reactive.color_mode = MODE_COLORS_MODE_SPECIFIC; + Reactive.colors.resize(1); + Reactive.colors_min = 1; + Reactive.colors_max = 1; + Reactive.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + Reactive.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + Reactive.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + modes.push_back(Reactive); + + mode Marquee; + Marquee.name = "Marquee"; + Marquee.value = GIGABYTE_AORUS_LAPTOP_MARQUEE_MODE_VALUE; + Marquee.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Marquee.color_mode = MODE_COLORS_MODE_SPECIFIC; + Marquee.colors.resize(1); + Marquee.colors_min = 1; + Marquee.colors_max = 1; + Marquee.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + Marquee.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + Marquee.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + Marquee.speed_min = GIGABYTE_AORUS_LAPTOP_SPEED_MIN; + Marquee.speed_max = GIGABYTE_AORUS_LAPTOP_SPEED_MAX; + Marquee.speed = GIGABYTE_AORUS_LAPTOP_SPEED_MAX/2; + modes.push_back(Marquee); + + mode CircleMarquee; + CircleMarquee.name = "Circle Marquee"; + CircleMarquee.value = GIGABYTE_AORUS_LAPTOP_CIRCLE_MARQUEE_MODE_VALUE; + CircleMarquee.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + CircleMarquee.color_mode = MODE_COLORS_MODE_SPECIFIC; + CircleMarquee.colors.resize(1); + CircleMarquee.colors_min = 1; + CircleMarquee.colors_max = 1; + CircleMarquee.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + CircleMarquee.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + CircleMarquee.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + CircleMarquee.speed_min = GIGABYTE_AORUS_LAPTOP_SPEED_MIN; + CircleMarquee.speed_max = GIGABYTE_AORUS_LAPTOP_SPEED_MAX; + CircleMarquee.speed = GIGABYTE_AORUS_LAPTOP_SPEED_MAX/2; + modes.push_back(CircleMarquee); + + mode RainbowMarquee; + RainbowMarquee.name = "Rainbow Marquee"; + RainbowMarquee.value = GIGABYTE_AORUS_LAPTOP_RAINBOW_MARQUEE_MODE_VALUE; + RainbowMarquee.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + RainbowMarquee.color_mode = MODE_COLORS_MODE_SPECIFIC; + RainbowMarquee.colors.resize(1); + RainbowMarquee.colors_min = 1; + RainbowMarquee.colors_max = 1; + RainbowMarquee.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + RainbowMarquee.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + RainbowMarquee.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + RainbowMarquee.speed_min = GIGABYTE_AORUS_LAPTOP_SPEED_MIN; + RainbowMarquee.speed_max = GIGABYTE_AORUS_LAPTOP_SPEED_MAX; + RainbowMarquee.speed = GIGABYTE_AORUS_LAPTOP_SPEED_MAX/2; + modes.push_back(RainbowMarquee); + + mode Ripple; + Ripple.name = "Ripple"; + Ripple.value = GIGABYTE_AORUS_LAPTOP_RIPPLE_MODE_VALUE; + Ripple.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Ripple.color_mode = MODE_COLORS_MODE_SPECIFIC; + Ripple.colors.resize(1); + Ripple.colors_min = 1; + Ripple.colors_max = 1; + Ripple.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + Ripple.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + Ripple.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + Ripple.speed_min = GIGABYTE_AORUS_LAPTOP_SPEED_MIN; + Ripple.speed_max = GIGABYTE_AORUS_LAPTOP_SPEED_MAX; + Ripple.speed = GIGABYTE_AORUS_LAPTOP_SPEED_MAX/2; + modes.push_back(Ripple); + + mode Hedge; + Hedge.name = "Hedge"; + Hedge.value = GIGABYTE_AORUS_LAPTOP_HEDGE_MODE_VALUE; + Hedge.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Hedge.color_mode = MODE_COLORS_MODE_SPECIFIC; + Hedge.colors.resize(1); + Hedge.colors_min = 1; + Hedge.colors_max = 1; + Hedge.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + Hedge.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + Hedge.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + Hedge.speed_min = GIGABYTE_AORUS_LAPTOP_SPEED_MIN; + Hedge.speed_max = GIGABYTE_AORUS_LAPTOP_SPEED_MAX; + Hedge.speed = GIGABYTE_AORUS_LAPTOP_SPEED_MAX/2; + modes.push_back(Hedge); + + mode Custom; + Custom.name = "Custom"; + Custom.value = GIGABYTE_AORUS_LAPTOP_CUSTOM_MODE_VALUE; + Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Custom.color_mode = MODE_COLORS_PER_LED; + Custom.brightness_min = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MIN; + Custom.brightness_max = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX; + Custom.brightness = GIGABYTE_AORUS_LAPTOP_BRIGHTNESS_MAX/2; + modes.push_back(Custom); + } + + SetupZones(); +} + +RGBController_GigabyteAorusLaptop::~RGBController_GigabyteAorusLaptop() +{ + delete controller; +} + +void RGBController_GigabyteAorusLaptop::SetupZones() +{ + /*---------------------------------------------------------*\ + | Main zone 1 LED only | + \*---------------------------------------------------------*/ + zone new_zone; + + switch(dev_type) + { + case GIGABYTE_AORUS_LAPTOP_KEYBOARD_TYPE: + new_zone.name = "Keyboard"; + break; + case GIGABYTE_AORUS_LAPTOP_BACKLIGHT_TYPE: + new_zone.name = "Backlight"; + break; + default: + new_zone.name = "Unknonw"; + break; + } + + new_zone.type = ZONE_TYPE_SINGLE; + new_zone.leds_min = 1; + new_zone.leds_max = 1; + new_zone.leds_count = 1; + new_zone.matrix_map = nullptr; + + zones.push_back(new_zone); + + led new_led; + new_led.name = "LED"; + leds.push_back(new_led); + + /*---------------------------------------------------------*\ + | Adding an extra zone for the keyboard real layout | + \*---------------------------------------------------------*/ + if(dev_type == GIGABYTE_AORUS_LAPTOP_KEYBOARD_TYPE) + { + /*-----------------------------------------*\ + | Create the zone | + \*-----------------------------------------*/ + unsigned int zone_size = 0; + + zone keyboard_zone; + keyboard_zone.name = "Keyboard layout"; + keyboard_zone.type = ZONE_TYPE_MATRIX; + + keyboard_zone.matrix_map = new matrix_map_type; + keyboard_zone.matrix_map->height = aorus_laptop_default_keyboard_layout.height; + keyboard_zone.matrix_map->width = aorus_laptop_default_keyboard_layout.width; + + keyboard_zone.matrix_map->map = new unsigned int[aorus_laptop_default_keyboard_layout.height * aorus_laptop_default_keyboard_layout.width]; + + for(unsigned int h = 0; h < aorus_laptop_default_keyboard_layout.height; h++) + { + for(unsigned int w = 0; w < aorus_laptop_default_keyboard_layout.width; w++) + { + unsigned int key = aorus_laptop_default_keyboard_layout.matrix_map[h][w]; + keyboard_zone.matrix_map->map[h * aorus_laptop_default_keyboard_layout.width + w] = key; + + if(key != NA) + { + led new_led; + new_led.name = aorus_laptop_default_keyboard_layout.led_names[key]; + leds.push_back(new_led); + zone_size++; + } + } + } + + keyboard_zone.leds_min = zone_size; + keyboard_zone.leds_max = zone_size; + keyboard_zone.leds_count = zone_size; + + zones.push_back(keyboard_zone); + } + + SetupColors(); +} + +void RGBController_GigabyteAorusLaptop::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_GigabyteAorusLaptop::DeviceUpdateLEDs() +{ + /*---------------------------------------------------------*\ + | This device supports direct mode per LED for main zone | + | only | + \*---------------------------------------------------------*/ + if(modes[active_mode].value == GIGABYTE_AORUS_LAPTOP_DIRECT_MODE_VALUE) + { + controller->SetDirect(modes[active_mode].brightness, colors[0]); + } + + /*---------------------------------------------------------*\ + | This device supports custom mode per LED for the layout | + | zone only, this isnt a direct mode | + | Skip first color from colors array (that's the first zone | + \*---------------------------------------------------------*/ + else if(modes[active_mode].value == GIGABYTE_AORUS_LAPTOP_CUSTOM_MODE_VALUE) + { + std::vector layout_zone_colors; + + for(unsigned int i = 1; i < colors.size(); i++) + { + layout_zone_colors.push_back(colors[i]); + } + + controller->SetCustom(layout_zone_colors, aorus_laptop_default_keyboard_layout.led_sequence_positions, modes[active_mode].brightness); + } +} + +void RGBController_GigabyteAorusLaptop::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_GigabyteAorusLaptop::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_GigabyteAorusLaptop::DeviceUpdateMode() +{ + const mode& current_mode = modes[active_mode]; + + /*---------------------------------------------------------*\ + | Redirect direct and custom mode to per led handler | + \*---------------------------------------------------------*/ + if(current_mode.value == GIGABYTE_AORUS_LAPTOP_DIRECT_MODE_VALUE || current_mode.value == GIGABYTE_AORUS_LAPTOP_CUSTOM_MODE_VALUE) + { + return DeviceUpdateLEDs(); + } + + /*---------------------------------------------------------*\ + | Hardware modes update | + \*---------------------------------------------------------*/ + unsigned char brightness = current_mode.colors[0] == 0 ? 0 : current_mode.brightness; // handles black color (not indexed) + controller->SetMode(current_mode.value, current_mode.speed, brightness, current_mode.direction + 1, current_mode.colors[0]); +} diff --git a/Controllers/GigabyteAorusLaptopController/RGBController_GigabyteAorusLaptop.h b/Controllers/GigabyteAorusLaptopController/RGBController_GigabyteAorusLaptop.h new file mode 100644 index 00000000..945f219c --- /dev/null +++ b/Controllers/GigabyteAorusLaptopController/RGBController_GigabyteAorusLaptop.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------*\ +| RGBController_GigabyteAorusLaptop.h | +| | +| RGBController for Gigabyte Aorus laptop | +| | +| Morgan Guimard (morg) 05 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "GigabyteAorusLaptopController.h" + +enum GIGABYTE_AORUS_LAPTOP_DEV_TYPE +{ + GIGABYTE_AORUS_LAPTOP_KEYBOARD_TYPE, + GIGABYTE_AORUS_LAPTOP_BACKLIGHT_TYPE +}; + +class RGBController_GigabyteAorusLaptop : public RGBController +{ +public: + RGBController_GigabyteAorusLaptop(GigabyteAorusLaptopController* controller_ptr, GIGABYTE_AORUS_LAPTOP_DEV_TYPE dev_type); + ~RGBController_GigabyteAorusLaptop(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + GigabyteAorusLaptopController* controller; + GIGABYTE_AORUS_LAPTOP_DEV_TYPE dev_type; +}; diff --git a/Controllers/GigabyteAorusMouseController/GigabyteAorusMouseController.cpp b/Controllers/GigabyteAorusMouseController/GigabyteAorusMouseController.cpp index 8e1c3ce0..6d00e1fa 100644 --- a/Controllers/GigabyteAorusMouseController/GigabyteAorusMouseController.cpp +++ b/Controllers/GigabyteAorusMouseController/GigabyteAorusMouseController.cpp @@ -1,32 +1,24 @@ -/*-----------------------------------------*\ -| GigabyteAorusMouseController.cpp | -| | -| Driver for Gigabyte Aorus Mouse lighting | -| controller | -| | -| Guimard Morgan (morg) 12/29/2022 | -\*-----------------------------------------*/ -#include "GigabyteAorusMouseController.h" -#include +/*---------------------------------------------------------*\ +| GigabyteAorusMouseController.cpp | +| | +| Driver for Gigabyte Aorus mouse | +| | +| Morgan Guimard (morg) 29 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -GigabyteAorusMouseController::GigabyteAorusMouseController(hid_device* dev_handle, const hid_device_info& info) +#include +#include "GigabyteAorusMouseController.h" +#include "StringUtils.h" + +GigabyteAorusMouseController::GigabyteAorusMouseController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) { dev = dev_handle; location = info.path; + name = dev_name; version = ""; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } } GigabyteAorusMouseController::~GigabyteAorusMouseController() @@ -39,16 +31,29 @@ std::string GigabyteAorusMouseController::GetDeviceLocation() return("HID: " + location); } -std::string GigabyteAorusMouseController::GetSerialString() -{ - return(serial_number); -} - std::string GigabyteAorusMouseController::GetFirmwareVersion() { return(version); } +std::string GigabyteAorusMouseController::GetNameString() +{ + return(name); +} + +std::string GigabyteAorusMouseController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + void GigabyteAorusMouseController::SetMode(RGBColor color, uint8_t mode_value, uint8_t brightness, uint8_t speed) { uint8_t usb_buf[GIGABYTE_AORUS_MOUSE_REPORT_SIZE]; diff --git a/Controllers/GigabyteAorusMouseController/GigabyteAorusMouseController.h b/Controllers/GigabyteAorusMouseController/GigabyteAorusMouseController.h index afc59922..333c035d 100644 --- a/Controllers/GigabyteAorusMouseController/GigabyteAorusMouseController.h +++ b/Controllers/GigabyteAorusMouseController/GigabyteAorusMouseController.h @@ -1,16 +1,19 @@ -/*-----------------------------------------*\ -| GigabyteAorusMouseController.h | -| | -| Driver for Gigabyte Aorus Mouse lighting | -| controller - header file | -| | -| Guimard Morgan (morg) 12/29/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| GigabyteAorusMouseController.h | +| | +| Driver for Gigabyte Aorus mouse | +| | +| Morgan Guimard (morg) 29 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once -#include "RGBController.h" #include -#include +#include +#include "RGBController.h" #define GIGABYTE_AORUS_MOUSE_REPORT_SIZE 8 #define GIGABYTE_AORUS_MOUSE_DIRECT_CMD 0xCD @@ -37,12 +40,13 @@ enum class GigabyteAorusMouseController { public: - GigabyteAorusMouseController(hid_device* dev_handle, const hid_device_info& info); + GigabyteAorusMouseController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); ~GigabyteAorusMouseController(); - std::string GetSerialString(); std::string GetDeviceLocation(); std::string GetFirmwareVersion(); + std::string GetNameString(); + std::string GetSerialString(); void SetMode(RGBColor color, uint8_t mode_value, uint8_t brightness, uint8_t speed); void SendDirect(RGBColor color); @@ -51,6 +55,6 @@ private: hid_device* dev; std::string location; - std::string serial_number; + std::string name; std::string version; }; diff --git a/Controllers/GigabyteAorusMouseController/GigabyteAorusMouseControllerDetect.cpp b/Controllers/GigabyteAorusMouseController/GigabyteAorusMouseControllerDetect.cpp index 8f6b4b33..7eda219a 100644 --- a/Controllers/GigabyteAorusMouseController/GigabyteAorusMouseControllerDetect.cpp +++ b/Controllers/GigabyteAorusMouseController/GigabyteAorusMouseControllerDetect.cpp @@ -1,6 +1,16 @@ +/*---------------------------------------------------------*\ +| GigabyteAorusMouseControllerDetect.cpp | +| | +| Detector for Gigabyte Aorus mouse | +| | +| Morgan Guimard (morg) 29 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" -#include "RGBController.h" -#include "hidapi/hidapi.h" +#include "hidapi.h" #include "GigabyteAorusMouseController.h" #include "RGBController_GigabyteAorusMouse.h" @@ -20,9 +30,8 @@ void DetectGigabyteAorusMouseControllers(hid_device_info* info, const std::strin if(dev) { - GigabyteAorusMouseController* controller = new GigabyteAorusMouseController(dev, *info); - RGBController_GigabyteAorusMouse* rgb_controller = new RGBController_GigabyteAorusMouse(controller); - rgb_controller->name = name; + GigabyteAorusMouseController* controller = new GigabyteAorusMouseController(dev, *info, name); + RGBController_GigabyteAorusMouse* rgb_controller = new RGBController_GigabyteAorusMouse(controller); ResourceManager::get()->RegisterRGBController(rgb_controller); } diff --git a/Controllers/GigabyteAorusMouseController/RGBController_GigabyteAorusMouse.cpp b/Controllers/GigabyteAorusMouseController/RGBController_GigabyteAorusMouse.cpp index 40887535..d000d011 100644 --- a/Controllers/GigabyteAorusMouseController/RGBController_GigabyteAorusMouse.cpp +++ b/Controllers/GigabyteAorusMouseController/RGBController_GigabyteAorusMouse.cpp @@ -1,17 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_GigabyteAorusMouse.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Gigabyte Aorus Mouse lighting | -| USB Driver | -| | -| Guimard Morgan (morg) 12/29/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GigabyteAorusMouse.cpp | +| | +| RGBController for Gigabyte Aorus mouse | +| | +| Morgan Guimard (morg) 29 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_GigabyteAorusMouse.h" - -#include #include +#include +#include "RGBController_GigabyteAorusMouse.h" /**------------------------------------------------------------------*\ @name Gigabyte Aorus mouse @@ -26,10 +26,10 @@ RGBController_GigabyteAorusMouse::RGBController_GigabyteAorusMouse(GigabyteAorusMouseController* controller_ptr) { controller = controller_ptr; - name = "Gigabyte Aorus"; + name = controller->GetNameString(); vendor = "Gigabyte"; type = DEVICE_TYPE_MOUSE; - description = name; + description = "Gigabyte Mouse Device"; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); version = controller->GetFirmwareVersion(); @@ -166,7 +166,7 @@ void RGBController_GigabyteAorusMouse::UpdateSingleLED(int /*led*/) } void RGBController_GigabyteAorusMouse::DeviceUpdateMode() -{ +{ /*---------------------------------------------------------*\ | Brightness cannot be updated in the direct mode packet | \*---------------------------------------------------------*/ diff --git a/Controllers/GigabyteAorusMouseController/RGBController_GigabyteAorusMouse.h b/Controllers/GigabyteAorusMouseController/RGBController_GigabyteAorusMouse.h index 8329a9e0..81af1c39 100644 --- a/Controllers/GigabyteAorusMouseController/RGBController_GigabyteAorusMouse.h +++ b/Controllers/GigabyteAorusMouseController/RGBController_GigabyteAorusMouse.h @@ -1,12 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_GigabyteAorusMouse.h | -| | -| Generic RGB Interface for OpenRGB | -| Gigabyte Aorus Mouse lighting | -| USB Driver | -| | -| Guimard Morgan (morg) 12/29/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GigabyteAorusMouse.h | +| | +| RGBController for Gigabyte Aorus mouse | +| | +| Morgan Guimard (morg) 29 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/GigabyteAorusPCCaseController/GigabyteAorusPCCaseController.cpp b/Controllers/GigabyteAorusPCCaseController/GigabyteAorusPCCaseController.cpp new file mode 100644 index 00000000..acd9953d --- /dev/null +++ b/Controllers/GigabyteAorusPCCaseController/GigabyteAorusPCCaseController.cpp @@ -0,0 +1,111 @@ +/*---------------------------------------------------------*\ +| GigabyteAorusPCCaseController.cpp | +| | +| Driver for Gigabyte Aorus case | +| | +| Denis Nazarov (nenderus) 10 Feb 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "GigabyteAorusPCCaseController.h" +#include "StringUtils.h" + +GigabyteAorusPCCaseController::GigabyteAorusPCCaseController(hid_device *dev_handle, const char *path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; +} + +GigabyteAorusPCCaseController::~GigabyteAorusPCCaseController() +{ + hid_close(dev); +} + +std::string GigabyteAorusPCCaseController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string GigabyteAorusPCCaseController::GetNameString() +{ + return(name); +} + +std::string GigabyteAorusPCCaseController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void GigabyteAorusPCCaseController::SendColor(uint8_t red, uint8_t green, uint8_t blue) +{ + uint8_t usb_buf[9] = { 0x00, 0x01, 0xC8, red, green, blue, 0x08, 0x01, 0x00 }; + hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); +} + +void GigabyteAorusPCCaseController::SendMode(uint8_t mode, uint8_t speed, uint8_t brightness) +{ + uint8_t usb_buf[9] = { 0x00, 0x01, 0xC9, mode, brightness, speed, 0x01, 0x08, 0x00 }; + hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); +} + +void GigabyteAorusPCCaseController::SendOk() +{ + uint8_t usb_buf[9] = { 0x00, 0x01, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); +} + +void GigabyteAorusPCCaseController::SetMode(uint8_t mode, aorus_pc_case_mode_config zone_config) +{ + switch (mode) + { + case AORUS_PC_CASE_MODE_CUSTOM: + { + SendColor(RGBGetRValue(zone_config.color), RGBGetGValue(zone_config.color), RGBGetBValue(zone_config.color)); + SendMode(mode, AORUS_PC_CASE_SPEED_NORMAL, zone_config.brightness); + } + break; + + case AORUS_PC_CASE_MODE_OFF: + { + SendColor(0x00, 0x00, 0x00); + SendMode(AORUS_PC_CASE_MODE_CUSTOM, AORUS_PC_CASE_SPEED_SLOWEST, AORUS_PC_CASE_BRIGHTNESS_MAX + 0x01); + } + break; + + case AORUS_PC_CASE_MODE_BREATHING: + { + SendColor(RGBGetRValue(zone_config.color), RGBGetGValue(zone_config.color), RGBGetBValue(zone_config.color)); + SendMode(mode, zone_config.speed, AORUS_PC_CASE_BRIGHTNESS_MAX); + } + break; + + case AORUS_PC_CASE_MODE_SPECTRUM_CYCLE: + { + SendColor(0xFF, 0x00, 0x00); + SendMode(mode, zone_config.speed, AORUS_PC_CASE_BRIGHTNESS_MAX); + } + break; + + case AORUS_PC_CASE_MODE_FLASHING: + case AORUS_PC_CASE_MODE_DOUBLE_FLASHING: + { + SendColor(RGBGetRValue(zone_config.color), RGBGetGValue(zone_config.color), RGBGetBValue(zone_config.color)); + SendMode(mode, zone_config.speed, zone_config.brightness * 0x0A); + } + break; + } + + SendOk(); +} diff --git a/Controllers/GigabyteAorusPCCaseController/GigabyteAorusPCCaseController.h b/Controllers/GigabyteAorusPCCaseController/GigabyteAorusPCCaseController.h new file mode 100644 index 00000000..c8806dca --- /dev/null +++ b/Controllers/GigabyteAorusPCCaseController/GigabyteAorusPCCaseController.h @@ -0,0 +1,68 @@ +/*---------------------------------------------------------*\ +| GigabyteAorusPCCaseController.h | +| | +| Driver for Gigabyte Aorus case | +| | +| Denis Nazarov (nenderus) 10 Feb 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +struct aorus_pc_case_mode_config +{ + RGBColor color; + uint8_t speed; + uint8_t brightness; +}; + +enum +{ + AORUS_PC_CASE_MODE_OFF = 0x00, + AORUS_PC_CASE_MODE_CUSTOM = 0x01, + AORUS_PC_CASE_MODE_BREATHING = 0x02, + AORUS_PC_CASE_MODE_SPECTRUM_CYCLE = 0x03, + AORUS_PC_CASE_MODE_FLASHING = 0x04, + AORUS_PC_CASE_MODE_DOUBLE_FLASHING = 0x05, +}; + +enum +{ + AORUS_PC_CASE_SPEED_SLOWEST = 0x0A, + AORUS_PC_CASE_SPEED_NORMAL = 0x09, + AORUS_PC_CASE_SPEED_FASTEST = 0x06, +}; + +enum +{ + AORUS_PC_CASE_BRIGHTNESS_MIN = 0x00, + AORUS_PC_CASE_BRIGHTNESS_MAX = 0x09, +}; + +class GigabyteAorusPCCaseController +{ +public: + GigabyteAorusPCCaseController(hid_device* dev_handle, const char* path, std::string dev_name); + ~GigabyteAorusPCCaseController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SendColor(uint8_t red, uint8_t green, uint8_t blue); + void SendMode(uint8_t mode, uint8_t speed, uint8_t brightness); + void SendOk(); + + void SetMode(uint8_t mode, aorus_pc_case_mode_config zone_config); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/GigabyteAorusPCCaseController/GigabyteAorusPCCaseControllerDetect.cpp b/Controllers/GigabyteAorusPCCaseController/GigabyteAorusPCCaseControllerDetect.cpp new file mode 100644 index 00000000..ec6239cf --- /dev/null +++ b/Controllers/GigabyteAorusPCCaseController/GigabyteAorusPCCaseControllerDetect.cpp @@ -0,0 +1,47 @@ +/*---------------------------------------------------------*\ +| GigabyteAorusPCCaseControllerDetect.cpp | +| | +| Detector for Gigabyte Aorus case | +| | +| Denis Nazarov (nenderus) 10 Feb 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "GigabyteAorusPCCaseController.h" +#include "RGBController_GigabyteAorusPCCase.h" + +/*-----------------------------------------------------*\ +| Vendor ID | +\*-----------------------------------------------------*/ +#define HOLTEK_VID 0x1044 + +/*-----------------------------------------------------*\ +| Controller product ids | +\*-----------------------------------------------------*/ +#define C300_GLASS_PID 0x7A30 + +/******************************************************************************************\ +* * +* DetectGigabyteAorusPCCaseControllers * +* * +* Tests the USB address to see if a Gigabyte Aorus PC Case exists there. * +* * +\******************************************************************************************/ +void DetectGigabyteAorusPCCaseControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + GigabyteAorusPCCaseController* controller = new GigabyteAorusPCCaseController(dev, info->path, name); + RGBController_GigabyteAorusPCCase* rgb_controller = new RGBController_GigabyteAorusPCCase(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR_IPU("Gigabyte AORUS C300 GLASS", DetectGigabyteAorusPCCaseControllers, HOLTEK_VID, C300_GLASS_PID, 0, 0xFF01, 0x01); diff --git a/Controllers/GigabyteAorusPCCaseController/RGBController_GigabyteAorusPCCase.cpp b/Controllers/GigabyteAorusPCCaseController/RGBController_GigabyteAorusPCCase.cpp new file mode 100644 index 00000000..0f988621 --- /dev/null +++ b/Controllers/GigabyteAorusPCCaseController/RGBController_GigabyteAorusPCCase.cpp @@ -0,0 +1,178 @@ +/*---------------------------------------------------------*\ +| RGBController_GigabyteAorusPCCase.cpp | +| | +| RGBController for Gigabyte Aorus case | +| | +| Denis Nazarov (nenderus) 10 Feb 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_GigabyteAorusPCCase.h" + +/**------------------------------------------------------------------*\ + @name Gigabyte AORUS PC Case + @category Case + @type USB + @save :robot: + @direct :x: + @effects :white_check_mark: + @detectors DetectGigabyteAorusPCCaseControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_GigabyteAorusPCCase::RGBController_GigabyteAorusPCCase(GigabyteAorusPCCaseController *controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "Gigabyte"; + description = "Gigabyte AORUS PC Case Device"; + type = DEVICE_TYPE_CASE; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Custom; + Custom.name = "Custom"; + Custom.value = AORUS_PC_CASE_MODE_CUSTOM; + Custom.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Custom.color_mode = MODE_COLORS_MODE_SPECIFIC; + Custom.colors_min = 1; + Custom.colors_max = 1; + Custom.colors.resize(1); + Custom.brightness_min = AORUS_PC_CASE_BRIGHTNESS_MIN; + Custom.brightness_max = AORUS_PC_CASE_BRIGHTNESS_MAX; + Custom.brightness = AORUS_PC_CASE_BRIGHTNESS_MAX; + modes.push_back(Custom); + + mode Off; + Off.name = "Off"; + Off.value = AORUS_PC_CASE_MODE_OFF; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = AORUS_PC_CASE_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.colors.resize(1); + Breathing.speed_min = AORUS_PC_CASE_SPEED_SLOWEST; + Breathing.speed_max = AORUS_PC_CASE_SPEED_FASTEST; + Breathing.speed = AORUS_PC_CASE_SPEED_NORMAL; + modes.push_back(Breathing); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = AORUS_PC_CASE_MODE_SPECTRUM_CYCLE; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.speed_min = AORUS_PC_CASE_SPEED_SLOWEST; + SpectrumCycle.speed_max = AORUS_PC_CASE_SPEED_FASTEST; + SpectrumCycle.speed = AORUS_PC_CASE_SPEED_NORMAL; + modes.push_back(SpectrumCycle); + + mode Flashing; + Flashing.name = "Flashing"; + Flashing.value = AORUS_PC_CASE_MODE_FLASHING; + Flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Flashing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Flashing.colors_min = 1; + Flashing.colors_max = 1; + Flashing.colors.resize(1); + Flashing.speed_min = AORUS_PC_CASE_SPEED_SLOWEST; + Flashing.speed_max = AORUS_PC_CASE_SPEED_FASTEST; + Flashing.speed = AORUS_PC_CASE_SPEED_NORMAL; + Flashing.brightness_min = AORUS_PC_CASE_BRIGHTNESS_MIN; + Flashing.brightness_max = AORUS_PC_CASE_BRIGHTNESS_MAX; + Flashing.brightness = AORUS_PC_CASE_BRIGHTNESS_MAX; + modes.push_back(Flashing); + + mode DoubleFlashing; + DoubleFlashing.name = "Double Flashing"; + DoubleFlashing.value = AORUS_PC_CASE_MODE_DOUBLE_FLASHING; + DoubleFlashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + DoubleFlashing.color_mode = MODE_COLORS_MODE_SPECIFIC; + DoubleFlashing.colors_min = 1; + DoubleFlashing.colors_max = 1; + DoubleFlashing.colors.resize(1); + DoubleFlashing.speed_min = AORUS_PC_CASE_SPEED_SLOWEST; + DoubleFlashing.speed_max = AORUS_PC_CASE_SPEED_FASTEST; + DoubleFlashing.speed = AORUS_PC_CASE_SPEED_NORMAL; + DoubleFlashing.brightness_min = AORUS_PC_CASE_BRIGHTNESS_MIN; + DoubleFlashing.brightness_max = AORUS_PC_CASE_BRIGHTNESS_MAX; + DoubleFlashing.brightness = AORUS_PC_CASE_BRIGHTNESS_MAX; + modes.push_back(DoubleFlashing); + + SetupZones(); +} + +RGBController_GigabyteAorusPCCase::~RGBController_GigabyteAorusPCCase() +{ + delete controller; +} + +void RGBController_GigabyteAorusPCCase::SetupZones() +{ + zone case_zone; + case_zone.name = "Case"; + case_zone.type = ZONE_TYPE_SINGLE; + case_zone.leds_min = 1; + case_zone.leds_max = 1; + case_zone.leds_count = 1; + case_zone.matrix_map = NULL; + zones.push_back(case_zone); + + led case_led; + case_led.name = "Case"; + leds.push_back(case_led); + + SetupColors(); +} + +void RGBController_GigabyteAorusPCCase::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_GigabyteAorusPCCase::DeviceUpdateLEDs() +{ + /*---------------------------------------------------------*\ + | This device does not need update leds | + \*---------------------------------------------------------*/ +} + +void RGBController_GigabyteAorusPCCase::UpdateZoneLEDs(int /*zone*/) +{ + /*---------------------------------------------------------*\ + | This device does not need update zone leds | + \*---------------------------------------------------------*/ +} + +void RGBController_GigabyteAorusPCCase::UpdateSingleLED(int /*led*/) +{ + /*---------------------------------------------------------*\ + | This device does not need update single led | + \*---------------------------------------------------------*/ +} + +void RGBController_GigabyteAorusPCCase::DeviceUpdateMode() +{ + aorus_pc_case_mode_config zone_config; + zone_config.color = 0x000000; + zone_config.speed = modes[active_mode].speed; + zone_config.brightness = modes[active_mode].brightness; + + if (modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + zone_config.color = modes[active_mode].colors[0]; + } + + controller->SetMode(modes[active_mode].value, zone_config); +} diff --git a/Controllers/GigabyteAorusPCCaseController/RGBController_GigabyteAorusPCCase.h b/Controllers/GigabyteAorusPCCaseController/RGBController_GigabyteAorusPCCase.h new file mode 100644 index 00000000..129aaf15 --- /dev/null +++ b/Controllers/GigabyteAorusPCCaseController/RGBController_GigabyteAorusPCCase.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_GigabyteAorusPCCase.h | +| | +| RGBController for Gigabyte Aorus case | +| | +| Denis Nazarov (nenderus) 10 Feb 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "GigabyteAorusPCCaseController.h" + +class RGBController_GigabyteAorusPCCase : public RGBController +{ +public: + RGBController_GigabyteAorusPCCase(GigabyteAorusPCCaseController* controller_ptr); + ~RGBController_GigabyteAorusPCCase(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + GigabyteAorusPCCaseController* controller; +}; diff --git a/Controllers/GigabyteRGBFusion2BlackwellGPUController/GigabyteRGBFusion2BlackwellGPUController.cpp b/Controllers/GigabyteRGBFusion2BlackwellGPUController/GigabyteRGBFusion2BlackwellGPUController.cpp new file mode 100644 index 00000000..303a5666 --- /dev/null +++ b/Controllers/GigabyteRGBFusion2BlackwellGPUController/GigabyteRGBFusion2BlackwellGPUController.cpp @@ -0,0 +1,92 @@ +/*---------------------------------------------------------*\ +| GigabyteRGBFusion2BlackwellGPUController.cpp | +| | +| Driver for Gigabyte RGB Fusion 2 Blackwell GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "GigabyteRGBFusion2BlackwellGPUController.h" +#include "GigabyteRGBFusion2BlackwellGPUDefinitions.h" +#include "LogManager.h" + +using namespace std::chrono_literals; + +RGBFusion2BlackwellGPUController::RGBFusion2BlackwellGPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev, std::string dev_name) +{ + this->bus = bus; + this->dev = dev; + this->name = dev_name; +} + +RGBFusion2BlackwellGPUController::~RGBFusion2BlackwellGPUController() +{ + +} + +std::string RGBFusion2BlackwellGPUController::GetDeviceLocation() +{ + std::string return_string(bus->device_name); + char addr[5]; + snprintf(addr, 5, "0x%02X", dev); + return_string.append(", address "); + return_string.append(addr); + return("I2C: " + return_string); +} + +std::string RGBFusion2BlackwellGPUController::GetDeviceName() +{ + return(name); +} + +void RGBFusion2BlackwellGPUController::SaveConfig() +{ + uint8_t data_pkt[64] = { 0x13, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + bus->i2c_write_block(dev, sizeof(data_pkt), data_pkt); +} + +void RGBFusion2BlackwellGPUController::SetMode(uint8_t type, uint8_t zone, uint8_t mode, fusion2_config zone_config) +{ + if(zone_config.numberOfColors == 0 && zone < RGB_FUSION_2_BLACKWELL_GPU_NUMBER_OF_ZONES) + this->zone_color[zone] = zone_config.colors[zone]; + + /************************************************************************************\ + * * + * Packet (total size = 64 bytes) * + * TYPE MODE SPD BRT R G B 0 ZONE SZ0-8 * + * 0x12 0x01 0x08 0x06 0x0A 0xFF 0xFF 0x00 0x00 0x00 0x08 [R] [G] [B] [R] [G] [B] ... * + * * + * SZ is the amount of colors that will be sent in the format of 3 bytes RGB * + * * + \************************************************************************************/ + uint8_t zone_pkt[64] = {type, 0x01, mode, zone_config.speed, zone_config.brightness, (uint8_t)RGBGetRValue(this->zone_color[zone]), (uint8_t)RGBGetGValue(this->zone_color[zone]), (uint8_t)RGBGetBValue(this->zone_color[zone]), 0x00, zone, zone_config.numberOfColors, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + if(zone_config.numberOfColors > 0) + { + int currentPos = 12; + for(uint8_t i = 0; i < zone_config.numberOfColors; i++) + { + zone_pkt[currentPos + 0] = RGBGetRValue(zone_config.colors[i]); + zone_pkt[currentPos + 1] = RGBGetGValue(zone_config.colors[i]); + zone_pkt[currentPos + 2] = RGBGetBValue(zone_config.colors[i]); + currentPos += 3; + } + } + + bus->i2c_write_block(dev, sizeof(zone_pkt), zone_pkt); +} + +void RGBFusion2BlackwellGPUController::SetZone(uint8_t zone, uint8_t mode, fusion2_config zone_config) +{ + if(mode == RGB_FUSION2_BLACKWELL_GPU_MODE_BREATHING) + zone_config.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + + uint8_t type = RGB_FUSION2_BLACKWELL_GPU_REG_COLOR; + if(mode != RGB_FUSION2_BLACKWELL_GPU_MODE_DIRECT) + type = RGB_FUSION2_BLACKWELL_GPU_REG_MODE; + + SetMode(type, zone, mode, zone_config); +} diff --git a/Controllers/GigabyteRGBFusion2BlackwellGPUController/GigabyteRGBFusion2BlackwellGPUController.h b/Controllers/GigabyteRGBFusion2BlackwellGPUController/GigabyteRGBFusion2BlackwellGPUController.h new file mode 100644 index 00000000..b32ca28b --- /dev/null +++ b/Controllers/GigabyteRGBFusion2BlackwellGPUController/GigabyteRGBFusion2BlackwellGPUController.h @@ -0,0 +1,89 @@ +/*---------------------------------------------------------*\ +| GigabyteRGBFusion2BlackwellGPUController.h | +| | +| Driver for Gigabyte RGB Fusion 2 Blackwell GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "i2c_smbus.h" +#include "RGBController.h" +#include "GigabyteRGBFusion2BlackwellGPUDefinitions.h" + +typedef unsigned char rgb_fusion_dev_id; + +struct fusion2_config +{ + uint8_t brightness; + RGBColor colors[8]; + uint8_t numberOfColors; + uint8_t speed; + uint8_t direction; +}; + +enum +{ + RGB_FUSION2_BLACKWELL_GPU_REG_MODE = 0x12, // Limits updates to at most 9 per second + RGB_FUSION2_BLACKWELL_GPU_REG_COLOR = 0x16, // Used for 'Intelligent' mode, faster updates (used for direct mode) +}; + +enum +{ + RGB_FUSION2_BLACKWELL_GPU_MODE_DIRECT = 0x00, // Used for Intelligent mode (0x16) and Off (0x12) + RGB_FUSION2_BLACKWELL_GPU_MODE_STATIC = 0x01, + RGB_FUSION2_BLACKWELL_GPU_MODE_BREATHING = 0x02, + RGB_FUSION2_BLACKWELL_GPU_MODE_FLASHING = 0x03, + RGB_FUSION2_BLACKWELL_GPU_MODE_DUAL_FLASHING = 0x04, + RGB_FUSION2_BLACKWELL_GPU_MODE_COLOR_CYCLE = 0x05, + RGB_FUSION2_BLACKWELL_GPU_MODE_WAVE = 0x06, // Not available to Eagle/Aero + RGB_FUSION2_BLACKWELL_GPU_MODE_GRADIENT = 0x07, // Not available to Eagle/Aero + RGB_FUSION2_BLACKWELL_GPU_MODE_COLOR_SHIFT = 0x08, // Not available to Eagle/Aero + RGB_FUSION2_BLACKWELL_GPU_MODE_TRICOLOR = 0x09, // Available to Waterforce + RGB_FUSION2_BLACKWELL_GPU_MODE_DAZZLE = 0x0A, // Not available to Eagle/Aero/Waterforce +}; + +enum +{ + RGB_FUSION2_BLACKWELL_GPU_SPEED_SLOWEST = 0x01, + RGB_FUSION2_BLACKWELL_GPU_SPEED_NORMAL = 0x03, + RGB_FUSION2_BLACKWELL_GPU_SPEED_FASTEST = 0x06 +}; + +enum +{ + RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MIN = 0x01, + RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX = 0x0A +}; + +enum +{ + RGB_FUSION2_BLACKWELL_GPU_SINGLE_ZONE = 0, + RGB_FUSION2_BLACKWELL_GPU_GAMING_LAYOUT = 1, + RGB_FUSION2_BLACKWELL_GPU_WATERFORCE_LAYOUT = 2, +}; + +class RGBFusion2BlackwellGPUController +{ +public: + RGBFusion2BlackwellGPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev, std::string dev_name); + ~RGBFusion2BlackwellGPUController(); + + RGBColor zone_color[RGB_FUSION_2_BLACKWELL_GPU_NUMBER_OF_ZONES]; + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + + void SaveConfig(); + + void SetZone(uint8_t zone, uint8_t mode, fusion2_config zone_config); + void SetMode(uint8_t type, uint8_t zone, uint8_t mode, fusion2_config zone_config); + +private: + i2c_smbus_interface* bus; + rgb_fusion_dev_id dev; + std::string name; +}; diff --git a/Controllers/GigabyteRGBFusion2BlackwellGPUController/GigabyteRGBFusion2BlackwellGPUControllerDetect.cpp b/Controllers/GigabyteRGBFusion2BlackwellGPUController/GigabyteRGBFusion2BlackwellGPUControllerDetect.cpp new file mode 100644 index 00000000..8d675cd2 --- /dev/null +++ b/Controllers/GigabyteRGBFusion2BlackwellGPUController/GigabyteRGBFusion2BlackwellGPUControllerDetect.cpp @@ -0,0 +1,169 @@ +/*---------------------------------------------------------*\ +| GigabyteRGBFusion2BlackwellGPUControllerDetect.cpp | +| | +| Detector for Gigabyte RGB Fusion 2 Blackwell GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "GigabyteRGBFusion2BlackwellGPUController.h" +#include "LogManager.h" +#include "RGBController_GigabyteRGBFusion2BlackwellGPU.h" +#include "i2c_smbus.h" +#include "pci_ids.h" + +#define GIGABYTEGPU_CONTROLLER_NAME3 "Gigabyte RGB Fusion2 Blackwell GPU" + +/******************************************************************************************\ +* * +* TestForGigabyteRGBFusion2BlackwellGPUController * +* * +* Tests the given address to see if an RGB Fusion2 controller exists there. First * +* does a quick write to test for a response * +* * +\******************************************************************************************/ + +bool TestForGigabyteRGBFusion2BlackwellGPUController(i2c_smbus_interface* bus, unsigned char address) +{ + bool pass = false; + int res, pktsz; + const int read_sz = 4; + const int write_sz = 64; //0x40 + uint8_t data_pkt[write_sz] = { 0x10, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t data_readpkt[read_sz] = {}; + + res = bus->i2c_write_block(address, write_sz, data_pkt); + + pass = true; + + pktsz = read_sz; + res = bus->i2c_read_block(address, &pktsz, data_readpkt); + + //What we have seen returned so far... + //GeForce RTX 5070 Ti Eagle OC 16G 0x01 0x01 0x01 0x00 + //GeForce RTX 5070 Ti Gaming OC 16G 0x01 0x01 0x01 0x00 + //GeForce RTX 5070 Gaming OC 12G 0x01 0x01 0x01 0x00 + + if(res < 0 || data_readpkt[0] != 0x01 || data_readpkt[1] != 0x01 || data_readpkt[2] != 0x01) + { + // Assemble C-string with respons for debugging + std::string text = ""; + + for(int idx = 0; idx < read_sz; ++idx) + { + char str[6]; + snprintf(str, 6, " 0x%02X", data_readpkt[idx]); + text.append(str); + } + + LOG_DEBUG("[%s] at address 0x%02X invalid. Expected 0x01 0x01 0x01 [0x*] but received:%s", GIGABYTEGPU_CONTROLLER_NAME3, address, text.c_str()); + pass = false; + } + + return(pass); +} /* TestForRGBFusion2BlackwellGPUController() */ + +/*******************************************************************************************\ +* * +* DetectGigabyteRGBFusion2BlackwellGPUControllers * +* * +* Detect GigabyteRGB Fusion2 controllers with a specified layout on the enumerated * +* I2C busses. * +* * +* bus - pointer to i2c_smbus_interface where RGB Fusion2 device is connected * +* dev - I2C address of RGB Fusion2 device * +* * +\*******************************************************************************************/ + +void DetectGigabyteRGBFusion2BlackwellGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name, uint8_t led_zones) +{ + // Check for RGB Fusion2 controller + if(TestForGigabyteRGBFusion2BlackwellGPUController(bus, i2c_addr)) + { + RGBFusion2BlackwellGPUController* controller = new RGBFusion2BlackwellGPUController(bus, i2c_addr, name); + RGBController_RGBFusion2BlackwellGPU* rgb_controller = new RGBController_RGBFusion2BlackwellGPU(controller, led_zones); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} /* DetectGigabyteRGBFusion2BlackwellGPUControllers() */ + +/*******************************************************************************************\ +* * +* DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers * +* * +* Detect GigabyteRGB Fusion2 controllers with one zone on the enumerated I2C busses. * +* * +* bus - pointer to i2c_smbus_interface where RGB Fusion2 device is connected * +* dev - I2C address of RGB Fusion2 device * +* * +\*******************************************************************************************/ + +void DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name) +{ + DetectGigabyteRGBFusion2BlackwellGPUControllers(bus, i2c_addr, name, RGB_FUSION2_BLACKWELL_GPU_SINGLE_ZONE); +} /* DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers() */ + +/*******************************************************************************************\ +* * +* DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers * +* * +* Detect GigabyteRGB Fusion2 controllers with gaming layouts on the enumerated I2C * +* busses. * +* * +* bus - pointer to i2c_smbus_interface where RGB Fusion2 device is connected * +* dev - I2C address of RGB Fusion2 device * +* * +\*******************************************************************************************/ + +void DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name) +{ + DetectGigabyteRGBFusion2BlackwellGPUControllers(bus, i2c_addr, name, RGB_FUSION2_BLACKWELL_GPU_GAMING_LAYOUT); +} /* DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers() */ + +/*******************************************************************************************\ +* * +* DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers * +* * +* Detect GigabyteRGB Fusion2 controllers with waterforce layouts on the enumerated * +* I2C busses. * +* * +* bus - pointer to i2c_smbus_interface where RGB Fusion2 device is connected * +* dev - I2C address of RGB Fusion2 device * +* * +\*******************************************************************************************/ + +void DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name) +{ + DetectGigabyteRGBFusion2BlackwellGPUControllers(bus, i2c_addr, name, RGB_FUSION2_BLACKWELL_GPU_WATERFORCE_LAYOUT); +} /* DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers() */ + +/*-----------------------------------------*\ +| Nvidia GPUs | +\*-----------------------------------------*/ + +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5060 Ti Gaming OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5060TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5060TI_GAMING_OC_16G_SUB_DEV, 0x75); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Eagle OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070_EAGLE_OC_12G_SUB_DEV, 0x75); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Gaming OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070_GAMING_OC_12G_SUB_DEV, 0x75); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Ti Eagle OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070TI_EAGLE_OC_16G_SUB_DEV, 0x75); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Ti Eagle OC ICE", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070TI_EAGLE_OC_ICE_16G_SUB_DEV, 0x75); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Ti Aero OC", DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070TI_AERO_OC_16G_SUB_DEV, 0x75); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5070 Ti Gaming OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5070TI_GAMING_OC_16G_SUB_DEV, 0x75); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5080 Gaming OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5080_GAMING_OC_16G_SUB_DEV, 0x75); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5080 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5080_XTREME_WATERFORCE_16G_SUB_DEV, 0x75); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5090 Gaming OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5090_GAMING_OC_32G_SUB_DEV, 0x75); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5090 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5090_XTREME_WATERFORCE_32G_SUB_DEV1, 0x75); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5090 XTREME WATERFORCE", DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5090_XTREME_WATERFORCE_32G_SUB_DEV2, 0x75); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5090 MASTER", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5090_MASTER_32G_SUB_DEV, 0x75); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5090 MASTER ICE", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5090_MASTER_ICE_32G_SUB_DEV, 0x75); + +/*-----------------------------------------*\ +| AMD GPUs | +\*-----------------------------------------*/ + +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS Radeon RX 9070 XT Elite", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RX9070XT_ELITE_16G_SUB_DEV, 0x75); +REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9070 XT GAMING OC", DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9070XT_GAMING_OC_16G_SUB_DEV, 0x75); + + diff --git a/Controllers/GigabyteRGBFusion2BlackwellGPUController/GigabyteRGBFusion2BlackwellGPUDefinitions.h b/Controllers/GigabyteRGBFusion2BlackwellGPUController/GigabyteRGBFusion2BlackwellGPUDefinitions.h new file mode 100644 index 00000000..d0cac908 --- /dev/null +++ b/Controllers/GigabyteRGBFusion2BlackwellGPUController/GigabyteRGBFusion2BlackwellGPUDefinitions.h @@ -0,0 +1,12 @@ +/*---------------------------------------------------------*\ +| GigabyteRGBFusion2BlackwellGPUDefinitions.h | +| | +| Definitions for Gigabyte RGB Fusion 2 Blackwell GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#define RGB_FUSION_2_BLACKWELL_GPU_NUMBER_OF_ZONES 6 diff --git a/Controllers/GigabyteRGBFusion2BlackwellGPUController/RGBController_GigabyteRGBFusion2BlackwellGPU.cpp b/Controllers/GigabyteRGBFusion2BlackwellGPUController/RGBController_GigabyteRGBFusion2BlackwellGPU.cpp new file mode 100644 index 00000000..3b30d2d3 --- /dev/null +++ b/Controllers/GigabyteRGBFusion2BlackwellGPUController/RGBController_GigabyteRGBFusion2BlackwellGPU.cpp @@ -0,0 +1,363 @@ +/*---------------------------------------------------------*\ +| RGBController_GigabyteRGBFusion2BlackwellGPU.cpp | +| | +| RGBController for Gigabyte RGB Fusion 2 Blackwell GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_GigabyteRGBFusion2BlackwellGPU.h" +#include "LogManager.h" +#include "GigabyteRGBFusion2BlackwellGPUDefinitions.h" + +/**------------------------------------------------------------------*\ + @name Gigabyte Fusion 2 Blackwell GPU + @category GPU + @type I2C + @save :white_check_mark: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectGigabyteRGBFusion2BlackwellSingleZoneGPUControllers,DetectGigabyteRGBFusion2BlackwellGamingLayoutGPUControllers,DetectGigabyteRGBFusion2BlackwellWaterforceLayoutGPUControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_RGBFusion2BlackwellGPU::RGBController_RGBFusion2BlackwellGPU(RGBFusion2BlackwellGPUController* controller_ptr, uint8_t led_layout) +{ + controller = controller_ptr; + gpu_layout = led_layout; + + name = controller->GetDeviceName(); + vendor = "Gigabyte"; + description = "Gigabyte RGB Fusion 2 Blackwell GPU Device"; + location = controller->GetDeviceLocation(); + type = DEVICE_TYPE_GPU; + + mode Static; + Static.name = "Static"; + Static.value = RGB_FUSION2_BLACKWELL_GPU_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Static.color_mode = MODE_COLORS_PER_LED; + Static.brightness_min = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MIN; + Static.brightness_max = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + Static.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + modes.push_back(Static); + + // Some GPU models (Gaming) dont maintain the colors but it has faster updates, useful for Effects (and the reason it has to be named Direct) + mode Direct; + Direct.name = "Direct"; + Direct.value = RGB_FUSION2_BLACKWELL_GPU_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MIN; + Direct.brightness_max = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + Direct.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + modes.push_back(Direct); + + mode Breathing; + Breathing.name = "Pulse"; + Breathing.value = RGB_FUSION2_BLACKWELL_GPU_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + Breathing.speed_min = RGB_FUSION2_BLACKWELL_GPU_SPEED_SLOWEST; + Breathing.speed_max = RGB_FUSION2_BLACKWELL_GPU_SPEED_FASTEST; + Breathing.speed = RGB_FUSION2_BLACKWELL_GPU_SPEED_NORMAL; + Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.brightness_min = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MIN; + Breathing.brightness_max = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + Breathing.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + modes.push_back(Breathing); + + mode Flashing; + Flashing.name = "Flash"; + Flashing.value = RGB_FUSION2_BLACKWELL_GPU_MODE_FLASHING; + Flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Flashing.speed_min = RGB_FUSION2_BLACKWELL_GPU_SPEED_SLOWEST; + Flashing.speed_max = RGB_FUSION2_BLACKWELL_GPU_SPEED_FASTEST; + Flashing.speed = RGB_FUSION2_BLACKWELL_GPU_SPEED_NORMAL; + Flashing.color_mode = MODE_COLORS_PER_LED; + Flashing.brightness_min = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MIN; + Flashing.brightness_max = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + Flashing.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + modes.push_back(Flashing); + + mode DualFlashing; + DualFlashing.name = "Double Flash"; + DualFlashing.value = RGB_FUSION2_BLACKWELL_GPU_MODE_DUAL_FLASHING; + DualFlashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + DualFlashing.speed_min = RGB_FUSION2_BLACKWELL_GPU_SPEED_SLOWEST; + DualFlashing.speed_max = RGB_FUSION2_BLACKWELL_GPU_SPEED_FASTEST; + DualFlashing.speed = RGB_FUSION2_BLACKWELL_GPU_SPEED_NORMAL; + DualFlashing.color_mode = MODE_COLORS_PER_LED; + DualFlashing.brightness_min = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MIN; + DualFlashing.brightness_max = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + DualFlashing.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + modes.push_back(DualFlashing); + + mode SpectrumCycle; + SpectrumCycle.name = "Color Cycle"; + SpectrumCycle.value = RGB_FUSION2_BLACKWELL_GPU_MODE_COLOR_CYCLE; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + SpectrumCycle.speed_min = RGB_FUSION2_BLACKWELL_GPU_SPEED_SLOWEST; + SpectrumCycle.speed_max = RGB_FUSION2_BLACKWELL_GPU_SPEED_FASTEST; + SpectrumCycle.speed = RGB_FUSION2_BLACKWELL_GPU_SPEED_NORMAL; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.brightness_min = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MIN; + SpectrumCycle.brightness_max = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + SpectrumCycle.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + modes.push_back(SpectrumCycle); + + if(led_layout == RGB_FUSION2_BLACKWELL_GPU_GAMING_LAYOUT || led_layout == RGB_FUSION2_BLACKWELL_GPU_WATERFORCE_LAYOUT) + { + mode Wave; + Wave.name = "Wave"; + Wave.value = RGB_FUSION2_BLACKWELL_GPU_MODE_WAVE; + Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Wave.speed_min = RGB_FUSION2_BLACKWELL_GPU_SPEED_SLOWEST; + Wave.speed_max = RGB_FUSION2_BLACKWELL_GPU_SPEED_FASTEST; + Wave.speed = RGB_FUSION2_BLACKWELL_GPU_SPEED_NORMAL; + Wave.color_mode = MODE_COLORS_NONE; + Wave.brightness_min = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MIN; + Wave.brightness_max = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + Wave.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + modes.push_back(Wave); + + mode Gradient; + Gradient.name = "Gradient"; + Gradient.value = RGB_FUSION2_BLACKWELL_GPU_MODE_GRADIENT; + Gradient.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Gradient.speed_min = RGB_FUSION2_BLACKWELL_GPU_SPEED_SLOWEST; + Gradient.speed_max = RGB_FUSION2_BLACKWELL_GPU_SPEED_FASTEST; + Gradient.speed = RGB_FUSION2_BLACKWELL_GPU_SPEED_NORMAL; + Gradient.color_mode = MODE_COLORS_PER_LED; + Gradient.brightness_min = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MIN; + Gradient.brightness_max = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + Gradient.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + modes.push_back(Gradient); + + mode ColorShift; + ColorShift.name = "Color Shift"; + ColorShift.value = RGB_FUSION2_BLACKWELL_GPU_MODE_COLOR_SHIFT; + ColorShift.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + ColorShift.speed_min = RGB_FUSION2_BLACKWELL_GPU_SPEED_SLOWEST; + ColorShift.speed_max = RGB_FUSION2_BLACKWELL_GPU_SPEED_FASTEST; + ColorShift.speed = RGB_FUSION2_BLACKWELL_GPU_SPEED_NORMAL; + ColorShift.color_mode = MODE_COLORS_MODE_SPECIFIC; + ColorShift.colors_min = 1; + ColorShift.colors_max = 8; + ColorShift.colors.resize(8); + ColorShift.brightness_min = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MIN; + ColorShift.brightness_max = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + ColorShift.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + modes.push_back(ColorShift); + + /* Disabled Dazzle as it seems to only execute once, would need to loop it maybe? + * Not for Waterforce + mode Dazzle; + Dazzle.name = "Dazzle"; + Dazzle.value = RGB_FUSION2_BLACKWELL_GPU_MODE_DAZZLE; + Dazzle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Dazzle.speed_min = RGB_FUSION2_BLACKWELL_GPU_SPEED_SLOWEST; + Dazzle.speed_max = RGB_FUSION2_BLACKWELL_GPU_SPEED_FASTEST; + Dazzle.speed = RGB_FUSION2_BLACKWELL_GPU_SPEED_NORMAL; + Dazzle.color_mode = MODE_COLORS_MODE_SPECIFIC; + Dazzle.colors_min = 1; + Dazzle.colors_max = 8; + Dazzle.colors.resize(8); + Dazzle.brightness_min = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MIN; + Dazzle.brightness_max = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + Dazzle.brightness = RGB_FUSION2_BLACKWELL_GPU_BRIGHTNESS_MAX; + modes.push_back(Dazzle);*/ + } + + SetupZones(); +} + +RGBController_RGBFusion2BlackwellGPU::~RGBController_RGBFusion2BlackwellGPU() +{ + delete controller; +} + +void RGBController_RGBFusion2BlackwellGPU::SetupZones() +{ + /*---------------------------------------------------------*\ + | This device only allows setting the entire zone for all | + | LED's in the zone and does not allow per LED control. | + \*---------------------------------------------------------*/ + if(gpu_layout == RGB_FUSION2_BLACKWELL_GPU_SINGLE_ZONE) + { + zone new_zone; + led new_led; + + new_zone.name = "Side"; + new_zone.type = ZONE_TYPE_SINGLE; + new_zone.leds_min = 1; + new_zone.leds_max = 1; + new_zone.leds_count = 1; + new_zone.matrix_map = NULL; + + new_led.name = new_zone.name; + + /*---------------------------------------------------------*\ + | Push the zone and LED on to device vectors | + \*---------------------------------------------------------*/ + leds.push_back(new_led); + zones.push_back(new_zone); + } + else if(gpu_layout == RGB_FUSION2_BLACKWELL_GPU_GAMING_LAYOUT) + { + for(uint8_t zone_idx = 0; zone_idx < 4; zone_idx++) + { + zone new_zone; + led new_led; + + switch(zone_idx) + { + case 0: + new_zone.name = "Right fan"; + break; + + case 1: + new_zone.name = "Left fan"; + break; + + case 2: + new_zone.name = "Center fan"; + break; + + case 3: + new_zone.name = "Side"; + break; + } + + new_zone.type = ZONE_TYPE_SINGLE; + new_zone.leds_min = 1; + new_zone.leds_max = 1; + new_zone.leds_count = 1; + new_zone.matrix_map = NULL; + + new_led.name = new_zone.name; + + /*---------------------------------------------------------*\ + | Push the zone and LED on to device vectors | + \*---------------------------------------------------------*/ + leds.push_back(new_led); + zones.push_back(new_zone); + } + } + else if(gpu_layout == RGB_FUSION2_BLACKWELL_GPU_WATERFORCE_LAYOUT) + { + for(uint8_t zone_idx = 0; zone_idx < 2; zone_idx++) + { + zone new_zone; + led new_led; + + switch(zone_idx) + { + case 0: + new_zone.name = "Waterblock"; + break; + + case 1: + new_zone.name = "Backplate"; + break; + } + + new_zone.type = ZONE_TYPE_SINGLE; + new_zone.leds_min = 1; + new_zone.leds_max = 1; + new_zone.leds_count = 1; + new_zone.matrix_map = NULL; + + new_led.name = new_zone.name; + + /*---------------------------------------------------------*\ + | Push the zone and LED on to device vectors | + \*---------------------------------------------------------*/ + leds.push_back(new_led); + zones.push_back(new_zone); + } + } + + SetupColors(); +} + +void RGBController_RGBFusion2BlackwellGPU::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_RGBFusion2BlackwellGPU::DeviceUpdateLEDs() +{ + fusion2_config zone_config; + + zone_config.brightness = modes[active_mode].brightness; + zone_config.speed = modes[active_mode].speed; + zone_config.direction = modes[active_mode].direction; + zone_config.numberOfColors = 0; + + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + zone_config.numberOfColors = (uint8_t)modes[active_mode].colors.size(); + } + + uint8_t gpu_zones; + switch(gpu_layout) // replicating GCC that sends more packets even when there is less zones + { + case RGB_FUSION2_BLACKWELL_GPU_SINGLE_ZONE: + gpu_zones = 1; + break; + + case RGB_FUSION2_BLACKWELL_GPU_GAMING_LAYOUT: + gpu_zones = 6; + break; + + case RGB_FUSION2_BLACKWELL_GPU_WATERFORCE_LAYOUT: + gpu_zones = 3; + break; + + default: + LOG_TRACE("[%s] Invalid GPU layout (%d) when updating LEDs.", name.c_str(), gpu_layout); + return; // should not happen + } + + for(uint8_t zone_idx = 0; zone_idx < gpu_zones; zone_idx++) + { + if(zone_idx >= zones.size()) + { + zone_config.colors[zone_idx] = colors.back(); + } + else + { + zone_config.colors[zone_idx] = colors[zone_idx]; + } + + for(uint8_t i = 0; i < zone_config.numberOfColors; i++) // specific for MODE_COLORS_MODE_SPECIFIC + { + zone_config.colors[i] = modes[active_mode].colors[i]; + } + + controller->SetZone(zone_idx, modes[active_mode].value, zone_config); + } +} + +void RGBController_RGBFusion2BlackwellGPU::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RGBFusion2BlackwellGPU::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RGBFusion2BlackwellGPU::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} + +void RGBController_RGBFusion2BlackwellGPU::DeviceSaveMode() +{ + controller->SaveConfig(); +} diff --git a/Controllers/GigabyteRGBFusion2BlackwellGPUController/RGBController_GigabyteRGBFusion2BlackwellGPU.h b/Controllers/GigabyteRGBFusion2BlackwellGPUController/RGBController_GigabyteRGBFusion2BlackwellGPU.h new file mode 100644 index 00000000..edf3e08f --- /dev/null +++ b/Controllers/GigabyteRGBFusion2BlackwellGPUController/RGBController_GigabyteRGBFusion2BlackwellGPU.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_GigabyteRGBFusion2BlackwellGPU.h | +| | +| RGBController for Gigabyte RGB Fusion 2 Blackwell GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "GigabyteRGBFusion2BlackwellGPUController.h" + +class RGBController_RGBFusion2BlackwellGPU : public RGBController +{ +public: + RGBController_RGBFusion2BlackwellGPU(RGBFusion2BlackwellGPUController* controller_ptr, uint8_t led_layout); + ~RGBController_RGBFusion2BlackwellGPU(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + RGBFusion2BlackwellGPUController* controller; + uint8_t gpu_layout; +}; diff --git a/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.cpp b/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.cpp index 32a3bf69..0bb10b40 100644 --- a/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.cpp +++ b/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.cpp @@ -1,17 +1,18 @@ -/*-----------------------------------------*\ -| GigabyteRGBFusion2DRAMController.cpp | -| | -| Driver for Gigabyte Aorus RGB Fusion 2 | -| DRAM lighting controller | -| | -| Adam Honse (CalcProgrammer1) 6/7/2020 | -\*-----------------------------------------*/ - -#include "GigabyteRGBFusion2DRAMController.h" +/*---------------------------------------------------------*\ +| GigabyteRGBFusion2DRAMController.cpp | +| | +| Driver for Gigabyte Aorus RGB Fusion 2 RAM | +| | +| Adam Honse (CalcProgrammer1) 07 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include #include #include +#include "GigabyteRGBFusion2DRAMController.h" RGBFusion2DRAMController::RGBFusion2DRAMController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev) { diff --git a/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.h b/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.h index 8e6d0a5c..7a8f1883 100644 --- a/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.h +++ b/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.h @@ -1,17 +1,19 @@ -/*-----------------------------------------*\ -| GigabyteRGBFusion2DRAMController.h | -| | -| Definitions and types for Gigabyte Aorus | -| RGB Fusion 2 DRAM lighting controller | -| | -| Adam Honse (CalcProgrammer1) 6/7/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| GigabyteRGBFusion2DRAMController.cpp | +| | +| Driver for Gigabyte Aorus RGB Fusion 2 RAM | +| | +| Adam Honse (CalcProgrammer1) 07 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" -#pragma once - typedef unsigned char rgb_fusion_dev_id; enum @@ -61,7 +63,7 @@ public: std::string GetDeviceLocation(); unsigned int GetLEDCount(); void Apply(); - + void SetLEDEffect ( unsigned int led, diff --git a/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMControllerDetect.cpp b/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMControllerDetect.cpp index 5ad3ee7d..dd5155d0 100644 --- a/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMControllerDetect.cpp +++ b/Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMControllerDetect.cpp @@ -1,14 +1,22 @@ +/*---------------------------------------------------------*\ +| GigabyteRGBFusion2DRAMControllerDetect.cpp | +| | +| Detector for Gigabyte Aorus RGB Fusion 2 RAM | +| | +| Adam Honse (CalcProgrammer1) 07 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include #include "Detector.h" #include "LogManager.h" #include "GigabyteRGBFusion2DRAMController.h" -#include "RGBController.h" #include "RGBController_GigabyteRGBFusion2DRAM.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include -#include /******************************************************************************************\ * * @@ -54,7 +62,7 @@ bool TestForGigabyteRGBFusion2DRAMController(i2c_smbus_interface* bus, unsigned * * * DetectGigabyteRGBFusion2DRAMControllers * * * -* Detect Gigabyte RGB Fusion 2 controllers on the enumerated I2C buses at address 0x67. * +* Detect Gigabyte RGB Fusion 2 controllers on the enumerated I2C buses at address 0x67. * * * * bus - pointer to i2c_smbus_interface where RGB Fusion device is connected * * dev - I2C address of RGB Fusion device * diff --git a/Controllers/GigabyteRGBFusion2DRAMController/RGBController_GigabyteRGBFusion2DRAM.cpp b/Controllers/GigabyteRGBFusion2DRAMController/RGBController_GigabyteRGBFusion2DRAM.cpp index 80d8a8d4..5db7427a 100644 --- a/Controllers/GigabyteRGBFusion2DRAMController/RGBController_GigabyteRGBFusion2DRAM.cpp +++ b/Controllers/GigabyteRGBFusion2DRAMController/RGBController_GigabyteRGBFusion2DRAM.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| GigabyteRGBController_RGBFusion2DRAM.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Gigabyte RGB Fusion 2 DRAM Driver | -| | -| Adam Honse (CalcProgrammer1) 6/7/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| GigabyteRGBController_RGBFusion2DRAM.cpp | +| | +| RGBController for Gigabyte Aorus RGB Fusion 2 RAM | +| | +| Adam Honse (CalcProgrammer1) 07 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_GigabyteRGBFusion2DRAM.h" diff --git a/Controllers/GigabyteRGBFusion2DRAMController/RGBController_GigabyteRGBFusion2DRAM.h b/Controllers/GigabyteRGBFusion2DRAMController/RGBController_GigabyteRGBFusion2DRAM.h index 492e01b1..91747c72 100644 --- a/Controllers/GigabyteRGBFusion2DRAMController/RGBController_GigabyteRGBFusion2DRAM.h +++ b/Controllers/GigabyteRGBFusion2DRAMController/RGBController_GigabyteRGBFusion2DRAM.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_GigabyteRGBFusion2DRAM.h | -| | -| Generic RGB Interface for OpenRGB | -| Gigabyte RGB Fusion 2 DRAM Driver | -| | -| Adam Honse (CalcProgrammer1) 6/7/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| GigabyteRGBController_RGBFusion2DRAM.h | +| | +| RGBController for Gigabyte Aorus RGB Fusion 2 RAM | +| | +| Adam Honse (CalcProgrammer1) 07 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUController.cpp b/Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUController.cpp index e27a55e3..9f6f3946 100644 --- a/Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUController.cpp +++ b/Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUController.cpp @@ -1,12 +1,11 @@ -/*-----------------------------------------*\ -| GigabyteRGBFusion2GPUController.cpp | -| | -| Driver for Gigabyte Aorus RGB Fusion2 GPU| -| lighting controller | -| | -| based on original by | -| Adam Honse (CalcProgrammer1) | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| GigabyteRGBFusion2GPUController.cpp | +| | +| Driver for Gigabyte Aorus RGB Fusion 2 GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include #include @@ -15,15 +14,11 @@ using namespace std::chrono_literals; -RGBFusion2GPUController::RGBFusion2GPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev) +RGBFusion2GPUController::RGBFusion2GPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev, std::string dev_name) { - this->bus = bus; - this->dev = dev; - - for(uint8_t i = 0; i < 4; i++) - { - zone_led_count[i] = 1; - } + this->bus = bus; + this->dev = dev; + this->name = dev_name; } RGBFusion2GPUController::~RGBFusion2GPUController() @@ -41,6 +36,11 @@ std::string RGBFusion2GPUController::GetDeviceLocation() return("I2C: " + return_string); } +std::string RGBFusion2GPUController::GetDeviceName() +{ + return(name); +} + void RGBFusion2GPUController::SaveConfig() { uint8_t data_pkt[8] = { 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -49,10 +49,43 @@ void RGBFusion2GPUController::SaveConfig() void RGBFusion2GPUController::SetMode(uint8_t zone, uint8_t mode, fusion2_config zone_config, uint8_t mystery_flag) { + if(zone < 4) + { + this->zone_color[zone] = zone_config.colors[0]; + } + uint8_t zone_pkt[8] = { RGB_FUSION2_GPU_REG_MODE, mode, zone_config.speed, zone_config.brightness, mystery_flag, (uint8_t)(zone + 1), 0x00, 0x00 }; bus->i2c_write_block(dev, sizeof(zone_pkt), zone_pkt); - uint8_t zone_pkt2[8] = { RGB_FUSION2_GPU_REG_COLOR, (uint8_t)RGBGetRValue(zone_config.colors[0]), (uint8_t)RGBGetGValue(zone_config.colors[0]), (uint8_t)RGBGetBValue(zone_config.colors[0]), (uint8_t)(zone + 1), 0x00, 0x00, 0x00 }; + uint8_t zone_pkt2[8] = { 0 }; + switch(zone) + { + case 0: + case 1: + zone_pkt2[0] = RGB_FUSION2_GPU_REG_COLOR_LEFT_MID; + zone_pkt2[1] = mode; + zone_pkt2[2] = (uint8_t)RGBGetRValue(this->zone_color[0]); + zone_pkt2[3] = (uint8_t)RGBGetGValue(this->zone_color[0]); + zone_pkt2[4] = (uint8_t)RGBGetBValue(this->zone_color[0]); + zone_pkt2[5] = (uint8_t)RGBGetRValue(this->zone_color[1]); + zone_pkt2[6] = (uint8_t)RGBGetGValue(this->zone_color[1]); + zone_pkt2[7] = (uint8_t)RGBGetBValue(this->zone_color[1]); + break; + case 2: + zone_pkt2[0] = RGB_FUSION2_GPU_REG_COLOR_RIGHT; + zone_pkt2[1] = mode; + zone_pkt2[2] = (uint8_t)RGBGetRValue(this->zone_color[2]); + zone_pkt2[3] = (uint8_t)RGBGetGValue(this->zone_color[2]); + zone_pkt2[4] = (uint8_t)RGBGetBValue(this->zone_color[2]); + break; + default: + zone_pkt2[0] = RGB_FUSION2_GPU_REG_COLOR; + zone_pkt2[1] = (uint8_t)RGBGetRValue(zone_config.colors[0]); + zone_pkt2[2] = (uint8_t)RGBGetGValue(zone_config.colors[0]); + zone_pkt2[3] = (uint8_t)RGBGetBValue(zone_config.colors[0]); + zone_pkt2[4] = (uint8_t)(zone + 1); + break; + } bus->i2c_write_block(dev, sizeof(zone_pkt2), zone_pkt2); } @@ -71,6 +104,7 @@ void RGBFusion2GPUController::SetZone(uint8_t zone, uint8_t mode, fusion2_config case RGB_FUSION2_GPU_MODE_BREATHING: { + zone_config.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; SetMode(zone, mode, zone_config, mystery_flag); } break; @@ -79,7 +113,7 @@ void RGBFusion2GPUController::SetZone(uint8_t zone, uint8_t mode, fusion2_config { uint8_t zone_pkt[8] = { RGB_FUSION2_GPU_REG_MODE, mode, zone_config.speed, zone_config.brightness, mystery_flag, (uint8_t)(zone + 1), 0x00, 0x00 }; bus->i2c_write_block(dev, sizeof(zone_pkt), zone_pkt); - } + } break; case RGB_FUSION2_GPU_MODE_GRADIENT: @@ -107,7 +141,7 @@ void RGBFusion2GPUController::SetZone(uint8_t zone, uint8_t mode, fusion2_config } break; - case RGB_FUSION2_GPU_MODE_COLOR_SHIFT: + case RGB_FUSION2_GPU_MODE_COLOR_SHIFT: { mystery_flag = zone_config.numberOfColors; uint8_t zone_pkt[8] = { RGB_FUSION2_GPU_REG_MODE, mode, zone_config.speed, zone_config.brightness, mystery_flag, (uint8_t)(zone + 1), 0x00, 0x00 }; @@ -142,7 +176,7 @@ void RGBFusion2GPUController::SetZone(uint8_t zone, uint8_t mode, fusion2_config bus->i2c_write_block(dev, sizeof(zone_pktD), zone_pktD); } break; - + default: { LOG_TRACE("[%s] Mode %02d not found", "fusion2 gpu", mode); diff --git a/Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUController.h b/Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUController.h index 8a2ee9dc..90595c7e 100644 --- a/Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUController.h +++ b/Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUController.h @@ -1,19 +1,18 @@ -/*------------------------------------------*\ -| GigabyteRGBFusion2GPUController.h | -| | -| Definitions and types for Gigabyte Aorus | -| RGB Fusion2 GPU lighting controller | -| | -| based on original by | -| Adam Honse (CalcProgrammer1) 2/20/2020 | -\*------------------------------------------*/ +/*---------------------------------------------------------*\ +| GigabyteRGBFusion2GPUController.h | +| | +| Driver for Gigabyte Aorus RGB Fusion 2 GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" #include "RGBController.h" -#pragma once - typedef unsigned char rgb_fusion_dev_id; struct fusion2_config @@ -28,7 +27,9 @@ struct fusion2_config enum { RGB_FUSION2_GPU_REG_COLOR = 0x40, - RGB_FUSION2_GPU_REG_MODE = 0x88 + RGB_FUSION2_GPU_REG_MODE = 0x88, + RGB_FUSION2_GPU_REG_COLOR_LEFT_MID = 0xB0, + RGB_FUSION2_GPU_REG_COLOR_RIGHT = 0xB1 }; enum @@ -60,17 +61,14 @@ enum class RGBFusion2GPUController { public: - RGBFusion2GPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev); + RGBFusion2GPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev, std::string dev_name); ~RGBFusion2GPUController(); - uint8_t zone_led_count[4]; - uint8_t zone_modes[4]; + RGBColor zone_color[4]; std::string GetDeviceLocation(); + std::string GetDeviceName(); - void GetDeviceModes(); - uint8_t GetZoneMode(uint8_t zone); - fusion2_config GetZoneConfig(uint8_t zone, uint8_t mode); void SaveConfig(); void SetZone(uint8_t zone, uint8_t mode, fusion2_config zone_config); @@ -79,5 +77,5 @@ public: private: i2c_smbus_interface* bus; rgb_fusion_dev_id dev; - + std::string name; }; diff --git a/Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUControllerDetect.cpp b/Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUControllerDetect.cpp index d07251b1..1f4ec983 100644 --- a/Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUControllerDetect.cpp +++ b/Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUControllerDetect.cpp @@ -1,13 +1,19 @@ +/*---------------------------------------------------------*\ +| GigabyteRGBFusion2GPUControllerDetect.cpp | +| | +| Detector for Gigabyte Aorus RGB Fusion 2 GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "GigabyteRGBFusion2GPUController.h" #include "LogManager.h" -#include "RGBController.h" #include "RGBController_GigabyteRGBFusion2GPU.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include #define GIGABYTEGPU_CONTROLLER_NAME2 "Gigabyte RGB Fusion2 GPU" @@ -46,17 +52,23 @@ bool TestForGigabyteRGBFusion2GPUController(i2c_smbus_interface* bus, unsigned c //GeForce RTX 4080 Gigabyte AORUS MASTER 16G 0xAB 0x10 0x52 0x07 //Note that GeForce RTX 3080 Ti AORUS XTREME WATERFORCE 12G LHS exposes three i2c buses but only one returns a 0xAB //response and controls the RGB lighting. The other buses return 0x00 0x00 0x00 0x00. - //Note that GeForce RTX 4080 Gigabyte AORUS MASTER 16G exposes two i2c bus with writable address 0x71 but on respond + //Note that GeForce RTX 4080 Gigabyte AORUS MASTER 16G exposes two i2c bus with writable address 0x71 but one respond //0x00 0x00 0x00 0x00 so it should be the one controlling the LCD screen. So we skip this bus //All seen responses start with 0xAB, so we check for this. if(res < 0 || data_readpkt[0] != 0xAB) { // Assemble C-string with respons for debugging - char str[32]; + std::string text = ""; + for(int idx = 0; idx < read_sz; ++idx) - snprintf(&str[5*idx], 32, " 0x%02X", data_readpkt[idx]); - LOG_DEBUG("[%s] at address 0x%02X invalid. Expected 0xAB [0x*] but received:%s", GIGABYTEGPU_CONTROLLER_NAME2, address, str); + { + char str[6]; + snprintf(str, 6, " 0x%02X", data_readpkt[idx]); + text.append(str); + } + + LOG_DEBUG("[%s] at address 0x%02X invalid. Expected 0xAB [0x*] but received:%s", GIGABYTEGPU_CONTROLLER_NAME2, address, text.c_str()); pass = false; } @@ -79,51 +91,91 @@ void DetectGigabyteRGBFusion2GPUControllers(i2c_smbus_interface* bus, uint8_t i2 // Check for RGB Fusion2 controller if(TestForGigabyteRGBFusion2GPUController(bus, i2c_addr)) { - RGBFusion2GPUController* controller = new RGBFusion2GPUController(bus, i2c_addr); + RGBFusion2GPUController* controller = new RGBFusion2GPUController(bus, i2c_addr, name); RGBController_RGBFusion2GPU* rgb_controller = new RGBController_RGBFusion2GPU(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } /* DetectGigabyteRGBFusion2GPUControllers() */ -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX2060 SUPER 8G V1", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2060S_V1_SUB_DEV, 0x50); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX2070 XTREME 8G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2070_XTREME_SUB_DEV, 0x50); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX2070 XTREME 8G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2070_XTREME_SUB_DEV2, 0x50); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX2070 SUPER 8G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070S_GAMING_OC_SUB_DEV2, 0x50); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX2070 SUPER 8G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2070S_8G_SUB_DEV, 0x50); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX2080 8G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080_SUB_DEV, 0x50); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX2080 XTREME 8G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080_XTREME_SUB_DEV, 0x50); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX2080 SUPER 8G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080S_SUB_DEV, 0x50); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX2080 SUPER 8G Rev 1.0", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080S_SUB_DEV_V1, 0x50); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX2080 SUPER Waterforce WB 8G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080S_WATERFORCE_WB_SUB_DEV, 0x51); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX2080 SUPER Waterforce WB 8G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080S_WATERFORCE_WB_SUB_DEV2, 0x08); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX2080 Ti XTREME 11G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080TI_EXTREME_SUB_DEV, 0x50); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX3060 ELITE 12G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_ELITE_12GB_SUB_DEV, 0x70); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX3060 ELITE 12G Rev a1", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA106_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_ELITE_12GB_SUB_DEV, 0x70); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX3060 ELITE 12G LHR", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_ELITE_12GB_SUB_DEV, 0x70); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX3060 Ti ELITE 8G LHR", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_ELITE_8GB_SUB_DEV, 0x70); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 Ti GAMING OC 8G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_GDDR6X_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_GAMING_OC_8G_SUB_DEV, 0x62); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 Ti GAMING OC 8G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_GAMING_OC_SUB_DEV, 0x62); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 Ti GAMING OC LHR 8G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_GAMING_OC_SUB_DEV, 0x62); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 Ti GAMING OC PRO 8G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_GAMING_OC_PRO_SUB_DEV, 0x62); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 Ti Gaming OC PRO 8G LHR", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_GAMING_OC_PRO_SUB_DEV, 0x62); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3070 MASTER 8G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_MASTER_OC_SUB_DEV, 0x66); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3070 MASTER 8G LHR", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_MASTER_OC_SUB_DEV, 0x66); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX3070 Ti MASTER 8G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX3070TI_MASTER_8G_SUB_DEV, 0x70); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX3080 XTREME WATERFORCE WB 10G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_XTREME_WATERFORCE_SUB_DEV, 0x64); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX3080 XTREME WATERFORCE WB 10G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_XTREME_WATERFORCE_SUB_DEV, 0x64); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX3080 XTREME WATERFORCE WB 12G LHR", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_XTREME_WATERFORCE_12G_SUB_DEV, 0x64); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX3080 XTREME WATERFORCE 10G Rev 2.0", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_XTREME_WATERFORCE_V2_SUB_DEV, 0x65); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3080 Ti Vision OC 12G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080TI_VISION_OC_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX3080 Ti XTREME WATERFORCE 12G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080TI_XTREME_WATERFORCE_SUB_DEV, 0x65); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3090 VISION OC 24G ", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3090_VISION_OC_24G_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX3090 XTREME WATERFORCE 24G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3090_XTREME_WATERFORCE_SUB_DEV, 0x65); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX3090 XTREME WATERFORCE WB 24G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3090_XTREME_WATERFORCE_WB_SUB_DEV, 0x64); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX4070Ti Gaming OC 12G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070TI_GAMING_OC_12G, 0x71); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX4080 AERO OC 16G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4080_AERO_OC_SUB_DEV, 0x71); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX4080 Eagle OC 16G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4080_EAGLE_OC_SUB_DEV, 0x71); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX4080 Gaming OC 16G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4080_GAMING_OC_SUB_DEV, 0x71); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX4080 MASTER 16G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX4080_MASTER_16G_SUB_DEV, 0x71); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX4090 GAMING OC 24G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4090_GAMING_OC_24G_SUB_DEV, 0x71); -REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RTX4090 MASTER 24G", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX4090_MASTER_24G_SUB_DEV, 0x71); +/*-----------------------------------------*\ +| Nvidia GPUs | +\*-----------------------------------------*/ + +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2060 SUPER", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2060S_V1_SUB_DEV_H, 0x50); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2060 SUPER", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2060S_V1_SUB_DEV_P, 0x50); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2070", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2070_SUB_DEV, 0x50); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2070 XTREME", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2070_XTREME_SUB_DEV_H, 0x50); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2070 XTREME", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2070_XTREME_SUB_DEV_P, 0x50); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2070 SUPER", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2070S_8G_SUB_DEV_H, 0x50); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2070 SUPER", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2070S_8G_SUB_DEV_P, 0x50); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2080", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080_SUB_DEV_H, 0x50); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2080", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080_SUB_DEV_P, 0x50); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2080 XTREME", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080_XTREME_SUB_DEV_H, 0x50); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2080 XTREME", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080_XTREME_SUB_DEV_P, 0x50); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2080 SUPER", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080S_SUB_DEV_H, 0x50); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2080 SUPER", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080S_SUB_DEV_P, 0x50); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2080 SUPER Waterforce WB", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080S_WATERFORCE_WB_SUB_DEV_H,0x51); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2080 SUPER Waterforce WB", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080S_WATERFORCE_WB_SUB_DEV_P,0x51); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2080 SUPER Waterforce", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080S_WATERFORCE_SUB_DEV_H, 0x08); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2080 SUPER Waterforce", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080S_WATERFORCE_SUB_DEV_P, 0x08); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2080 Ti XTREME", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080TI_EXTREME_SUB_DEV_H, 0x50); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 2080 Ti XTREME", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX2080TI_EXTREME_SUB_DEV_P, 0x50); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 3060 ELITE", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_ELITE_12GB_SUB_DEV, 0x70); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 3060 ELITE Rev A1", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA106_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_ELITE_12GB_SUB_DEV, 0x70); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 3060 ELITE LHR", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_ELITE_12GB_SUB_DEV, 0x70); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 3060 Ti ELITE LHR", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_ELITE_8GB_SUB_DEV, 0x70); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 Ti GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_GDDR6X_DEV,GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_GAMING_OC_8G_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 Ti GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_GAMING_OC_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 Ti GAMING OC LHR", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_GAMING_OC_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 Ti GAMING OC PRO", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_GAMING_OC_PRO_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 Ti Gaming OC PRO LHR", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_GAMING_OC_PRO_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3070 MASTER", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_MASTER_OC_SUB_DEV, 0x66); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3070 MASTER LHR", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_MASTER_OC_SUB_DEV, 0x66); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 3070 Ti MASTER", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX3070TI_MASTER_8G_SUB_DEV, 0x70); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 3080 XTREME WATERFORCE WB", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_XTREME_WATERFORCE_SUB_DEV, 0x64); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 3080 XTREME WATERFORCE WB", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_XTREME_WATERFORCE_SUB_DEV, 0x64); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 3080 XTREME WATERFORCE V2", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_XTREME_WATERFORCE_V2_SUB_DEV, 0x65); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 3080 12G XTREME WATERFORCE WB", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_XTREME_WATERFORCE_12G_SUB_DEV, 0x64); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3080 Ti Vision OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080TI_VISION_OC_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 3080 Ti XTREME WATERFORCE", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080TI_XTREME_WATERFORCE_SUB_DEV, 0x65); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 3080 Ti XTREME WATERFORCE", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080TI_XTREME_WATERFORCE_SUB_DEV2, 0x64); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3090 VISION OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3090_VISION_OC_24G_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 3090 XTREME WATERFORCE", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3090_XTREME_WATERFORCE_SUB_DEV, 0x65); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 3090 XTREME WATERFORCE WB", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3090_XTREME_WATERFORCE_WB_SUB_DEV, 0x64); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070_GAMING_OC_12G, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070_GAMING_OC_12G_V2, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 SUPER GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070S_GAMING_OC_12G, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 SUPER Aero OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070S_AERO_OC_12G, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 SUPER Eagle OC Ice", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070S_EAGLE_OC_ICE_12G, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 Ti GAMING", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070TI_GAMING_12G, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 Ti GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070TI_GAMING_OC_12G, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 Ti GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070TI_GAMING_OC_12G_SUB_DEV2, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 Ti Eagle OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070TI_EAGLE_OC_SUB_DEV, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 Eagle OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070_EAGLE_OC_SUB_DEV, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 Ti Eagle OC Rev 2", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070TI_EAGLE_OC_V2_SUB_DEV, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 Ti Master", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070TI_MASTER_12G, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 4070 Ti ELITE", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070TI_ELITE_12G, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 Ti SUPER GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070TIS_GAMING_OC_16G_SUB_DEV, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4080 AERO OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4080_AERO_OC_SUB_DEV, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4080 Eagle OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4080_EAGLE_OC_SUB_DEV, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4080 SUPER GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4080S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4080S_GAMING_OC_16GB_SUB_DEV, 0x72); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4080 SUPER AERO OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4080S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4080S_AERO_OC_16GB_SUB_DEV, 0x72); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4080 GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4080_GAMING_OC_SUB_DEV, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 4080 MASTER", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX4080_MASTER_16G_SUB_DEV, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4090 AERO OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4090_AERO_OC_24G_SUB_DEV, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4090 GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4090_GAMING_OC_24G_SUB_DEV, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 4090 MASTER", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX4090_MASTER_24G_SUB_DEV, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS GeForce RTX 5090 D MASTER", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX5090D_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RTX5090D_MASTER_32G_SUB_DEV, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 5090 GAMING OC", DetectGigabyteRGBFusion2GPUControllers, NVIDIA_VEN, NVIDIA_RTX5090D_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX5090_GAMING_OC_32G_SUB_DEV, 0x71); + +/*-----------------------------------------*\ +| AMD GPUs | +\*-----------------------------------------*/ + +REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7800 XT GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI32_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7800XT_GAMING_OC_16G_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7900 GRE GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7900GRE_GAMING_OC_16G_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 7900 XT GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX7900XT_GAMING_OC_20G_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS RX 6750 XT ELITE 12G", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RX_6750_XT_ELITE_12G_SUB_DEV, 0x70); +REGISTER_I2C_PCI_DETECTOR("Gigabyte AORUS Radeon RX 9070 XT Elite", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_AORUS_RX9070XT_ELITE_16G_SUB_DEV, 0x73); +REGISTER_I2C_PCI_DETECTOR("Gigabyte Radeon RX 9070 XT GAMING OC", DetectGigabyteRGBFusion2GPUControllers, AMD_GPU_VEN, AMD_NAVI48_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RX9070XT_GAMING_OC_16G_SUB_DEV, 0x73); diff --git a/Controllers/GigabyteRGBFusion2GPUController/RGBController_GigabyteRGBFusion2GPU.cpp b/Controllers/GigabyteRGBFusion2GPUController/RGBController_GigabyteRGBFusion2GPU.cpp index 240e5922..788979f6 100644 --- a/Controllers/GigabyteRGBFusion2GPUController/RGBController_GigabyteRGBFusion2GPU.cpp +++ b/Controllers/GigabyteRGBFusion2GPUController/RGBController_GigabyteRGBFusion2GPU.cpp @@ -1,22 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_GigabyteRGBFusion2GPU.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Gigabyte RGB Fusion2 GPU Driver | -| | -| based on original by | -| Adam Honse (CalcProgrammer1) | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GigabyteRGBFusion2GPU.cpp | +| | +| RGBController for Gigabyte Aorus RGB Fusion 2 GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_GigabyteRGBFusion2GPU.h" - -static const char* gigabyte_fusion2_gpu_zone[] = -{ - "gpu zone 1", - "gpu zone 2", - "gpu zone 3", - "gpu zone 4" -}; +#include "LogManager.h" /**------------------------------------------------------------------*\ @name Gigabyte Fusion 2 GPU @@ -31,62 +23,61 @@ static const char* gigabyte_fusion2_gpu_zone[] = RGBController_RGBFusion2GPU::RGBController_RGBFusion2GPU(RGBFusion2GPUController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Gigabyte GPU"; - vendor = "Gigabyte"; - description = "Gigabyte RGB Fusion 2 GPU"; - location = controller->GetDeviceLocation(); - - type = DEVICE_TYPE_GPU; + name = controller->GetDeviceName(); + vendor = "Gigabyte"; + description = "Gigabyte RGB Fusion 2 GPU Device"; + location = controller->GetDeviceLocation(); + type = DEVICE_TYPE_GPU; mode Direct; - Direct.name = "Direct"; - Direct.value = RGB_FUSION2_GPU_MODE_STATIC; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Direct.color_mode = MODE_COLORS_PER_LED; - Direct.brightness_min = RGB_FUSION2_GPU_BRIGHTNESS_MIN; - Direct.brightness_max = RGB_FUSION2_GPU_BRIGHTNESS_MAX; - Direct.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; + Direct.name = "Direct"; + Direct.value = RGB_FUSION2_GPU_MODE_STATIC; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = RGB_FUSION2_GPU_BRIGHTNESS_MIN; + Direct.brightness_max = RGB_FUSION2_GPU_BRIGHTNESS_MAX; + Direct.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; modes.push_back(Direct); mode Breathing; - Breathing.name = "Pulse"; - Breathing.value = RGB_FUSION2_GPU_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; - Breathing.speed_min = RGB_FUSION2_GPU_SPEED_SLOWEST; - Breathing.speed_max = RGB_FUSION2_GPU_SPEED_FASTEST; - Breathing.speed = RGB_FUSION2_GPU_SPEED_NORMAL; - Breathing.color_mode = MODE_COLORS_PER_LED; - Breathing.brightness_min = RGB_FUSION2_GPU_BRIGHTNESS_MIN; - Breathing.brightness_max = RGB_FUSION2_GPU_BRIGHTNESS_MAX; - Breathing.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; + Breathing.name = "Pulse"; + Breathing.value = RGB_FUSION2_GPU_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + Breathing.speed_min = RGB_FUSION2_GPU_SPEED_SLOWEST; + Breathing.speed_max = RGB_FUSION2_GPU_SPEED_FASTEST; + Breathing.speed = RGB_FUSION2_GPU_SPEED_NORMAL; + Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.brightness_min = RGB_FUSION2_GPU_BRIGHTNESS_MIN; + Breathing.brightness_max = RGB_FUSION2_GPU_BRIGHTNESS_MAX; + Breathing.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; modes.push_back(Breathing); mode Flashing; - Flashing.name = "Flash"; - Flashing.value = RGB_FUSION2_GPU_MODE_FLASHING; - Flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Flashing.speed_min = RGB_FUSION2_GPU_SPEED_SLOWEST; - Flashing.speed_max = RGB_FUSION2_GPU_SPEED_FASTEST; - Flashing.speed = RGB_FUSION2_GPU_SPEED_NORMAL; - Flashing.color_mode = MODE_COLORS_PER_LED; - Flashing.brightness_min = RGB_FUSION2_GPU_BRIGHTNESS_MIN; - Flashing.brightness_max = RGB_FUSION2_GPU_BRIGHTNESS_MAX; - Flashing.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; + Flashing.name = "Flash"; + Flashing.value = RGB_FUSION2_GPU_MODE_FLASHING; + Flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Flashing.speed_min = RGB_FUSION2_GPU_SPEED_SLOWEST; + Flashing.speed_max = RGB_FUSION2_GPU_SPEED_FASTEST; + Flashing.speed = RGB_FUSION2_GPU_SPEED_NORMAL; + Flashing.color_mode = MODE_COLORS_PER_LED; + Flashing.brightness_min = RGB_FUSION2_GPU_BRIGHTNESS_MIN; + Flashing.brightness_max = RGB_FUSION2_GPU_BRIGHTNESS_MAX; + Flashing.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; modes.push_back(Flashing); mode DualFlashing; - DualFlashing.name = "Double Flash"; - DualFlashing.value = RGB_FUSION2_GPU_MODE_DUAL_FLASHING; - DualFlashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - DualFlashing.speed_min = RGB_FUSION2_GPU_SPEED_SLOWEST; - DualFlashing.speed_max = RGB_FUSION2_GPU_SPEED_FASTEST; - DualFlashing.speed = RGB_FUSION2_GPU_SPEED_NORMAL; - DualFlashing.color_mode = MODE_COLORS_PER_LED; - DualFlashing.brightness_min = RGB_FUSION2_GPU_BRIGHTNESS_MIN; - DualFlashing.brightness_max = RGB_FUSION2_GPU_BRIGHTNESS_MAX; - DualFlashing.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; + DualFlashing.name = "Double Flash"; + DualFlashing.value = RGB_FUSION2_GPU_MODE_DUAL_FLASHING; + DualFlashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + DualFlashing.speed_min = RGB_FUSION2_GPU_SPEED_SLOWEST; + DualFlashing.speed_max = RGB_FUSION2_GPU_SPEED_FASTEST; + DualFlashing.speed = RGB_FUSION2_GPU_SPEED_NORMAL; + DualFlashing.color_mode = MODE_COLORS_PER_LED; + DualFlashing.brightness_min = RGB_FUSION2_GPU_BRIGHTNESS_MIN; + DualFlashing.brightness_max = RGB_FUSION2_GPU_BRIGHTNESS_MAX; + DualFlashing.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; modes.push_back(DualFlashing); mode SpectrumCycle; @@ -103,60 +94,63 @@ RGBController_RGBFusion2GPU::RGBController_RGBFusion2GPU(RGBFusion2GPUController modes.push_back(SpectrumCycle); mode Gradient; - Gradient.name = "Gradient"; - Gradient.value = RGB_FUSION2_GPU_MODE_GRADIENT; - Gradient.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Gradient.speed_min = RGB_FUSION2_GPU_SPEED_SLOWEST; - Gradient.speed_max = RGB_FUSION2_GPU_SPEED_FASTEST; - Gradient.speed = RGB_FUSION2_GPU_SPEED_NORMAL; - Gradient.color_mode = MODE_COLORS_PER_LED; - Gradient.brightness_min = RGB_FUSION2_GPU_BRIGHTNESS_MIN; - Gradient.brightness_max = RGB_FUSION2_GPU_BRIGHTNESS_MAX; - Gradient.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; + Gradient.name = "Gradient"; + Gradient.value = RGB_FUSION2_GPU_MODE_GRADIENT; + Gradient.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Gradient.speed_min = RGB_FUSION2_GPU_SPEED_SLOWEST; + Gradient.speed_max = RGB_FUSION2_GPU_SPEED_FASTEST; + Gradient.speed = RGB_FUSION2_GPU_SPEED_NORMAL; + Gradient.color_mode = MODE_COLORS_PER_LED; + Gradient.brightness_min = RGB_FUSION2_GPU_BRIGHTNESS_MIN; + Gradient.brightness_max = RGB_FUSION2_GPU_BRIGHTNESS_MAX; + Gradient.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; modes.push_back(Gradient); mode Wave; - Wave.name = "Wave"; - Wave.value = RGB_FUSION2_GPU_MODE_WAVE; - Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Wave.speed_min = RGB_FUSION2_GPU_SPEED_SLOWEST; - Wave.speed_max = RGB_FUSION2_GPU_SPEED_FASTEST; - Wave.speed = RGB_FUSION2_GPU_SPEED_NORMAL; - Wave.color_mode = MODE_COLORS_NONE; - Wave.brightness_min = RGB_FUSION2_GPU_BRIGHTNESS_MIN; - Wave.brightness_max = RGB_FUSION2_GPU_BRIGHTNESS_MAX; - Wave.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; + Wave.name = "Wave"; + Wave.value = RGB_FUSION2_GPU_MODE_WAVE; + Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Wave.speed_min = RGB_FUSION2_GPU_SPEED_SLOWEST; + Wave.speed_max = RGB_FUSION2_GPU_SPEED_FASTEST; + Wave.speed = RGB_FUSION2_GPU_SPEED_NORMAL; + Wave.color_mode = MODE_COLORS_NONE; + Wave.brightness_min = RGB_FUSION2_GPU_BRIGHTNESS_MIN; + Wave.brightness_max = RGB_FUSION2_GPU_BRIGHTNESS_MAX; + Wave.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; modes.push_back(Wave); mode Shift; - Shift.name = "Color Shift"; - Shift.value = RGB_FUSION2_GPU_MODE_COLOR_SHIFT; - Shift.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Shift.speed_min = RGB_FUSION2_GPU_SPEED_SLOWEST; - Shift.speed_max = RGB_FUSION2_GPU_SPEED_FASTEST; - Shift.speed = RGB_FUSION2_GPU_SPEED_NORMAL; - Shift.color_mode = MODE_COLORS_MODE_SPECIFIC; - Shift.colors_min = 1; - Shift.colors_max = 8; + Shift.name = "Color Shift"; + Shift.value = RGB_FUSION2_GPU_MODE_COLOR_SHIFT; + Shift.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Shift.speed_min = RGB_FUSION2_GPU_SPEED_SLOWEST; + Shift.speed_max = RGB_FUSION2_GPU_SPEED_FASTEST; + Shift.speed = RGB_FUSION2_GPU_SPEED_NORMAL; + Shift.color_mode = MODE_COLORS_MODE_SPECIFIC; + Shift.colors_min = 1; + Shift.colors_max = 8; Shift.colors.resize(8); - Shift.brightness_min = RGB_FUSION2_GPU_BRIGHTNESS_MIN; - Shift.brightness_max = RGB_FUSION2_GPU_BRIGHTNESS_MAX; - Shift.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; + Shift.brightness_min = RGB_FUSION2_GPU_BRIGHTNESS_MIN; + Shift.brightness_max = RGB_FUSION2_GPU_BRIGHTNESS_MAX; + Shift.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; modes.push_back(Shift); mode Tricolor; - Tricolor.name = "Tricolor"; - Tricolor.value = RGB_FUSION2_GPU_MODE_TRICOLOR; - Tricolor.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Tricolor.speed_min = RGB_FUSION2_GPU_SPEED_SLOWEST; - Tricolor.speed_max = RGB_FUSION2_GPU_SPEED_FASTEST; - Tricolor.speed = RGB_FUSION2_GPU_SPEED_NORMAL; - Tricolor.color_mode = MODE_COLORS_MODE_SPECIFIC; + Tricolor.name = "Tricolor"; + Tricolor.value = RGB_FUSION2_GPU_MODE_TRICOLOR; + Tricolor.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Tricolor.speed_min = RGB_FUSION2_GPU_SPEED_SLOWEST; + Tricolor.speed_max = RGB_FUSION2_GPU_SPEED_FASTEST; + Tricolor.speed = RGB_FUSION2_GPU_SPEED_NORMAL; + Tricolor.color_mode = MODE_COLORS_MODE_SPECIFIC; + Tricolor.colors_min = 1; + Tricolor.colors_max = 3; Tricolor.colors.resize(3); - Tricolor.brightness_min = RGB_FUSION2_GPU_BRIGHTNESS_MIN; - Tricolor.brightness_max = RGB_FUSION2_GPU_BRIGHTNESS_MAX; - Tricolor.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; + Tricolor.brightness_min = RGB_FUSION2_GPU_BRIGHTNESS_MIN; + Tricolor.brightness_max = RGB_FUSION2_GPU_BRIGHTNESS_MAX; + Tricolor.brightness = RGB_FUSION2_GPU_BRIGHTNESS_MAX; modes.push_back(Tricolor); + SetupZones(); } @@ -165,18 +159,6 @@ RGBController_RGBFusion2GPU::~RGBController_RGBFusion2GPU() delete controller; } -uint8_t RGBController_RGBFusion2GPU::getModeIndex(uint8_t mode_value) -{ - for (uint8_t mode_index = 0; mode_index < modes.size(); mode_index++) - { - if (modes[mode_index].value == mode_value) - { - return mode_index; - } - } - return 0; -} - void RGBController_RGBFusion2GPU::SetupZones() { /*---------------------------------------------------------*\ @@ -184,31 +166,27 @@ void RGBController_RGBFusion2GPU::SetupZones() | LED's in the zone and does not allow per LED control. | \*---------------------------------------------------------*/ - //controller->GetDeviceModes(); - - for(uint8_t zone_idx = 0; zone_idx < 4; zone_idx++) + for(uint8_t zone_idx = 0; zone_idx < RGB_FUSION_2_GPU_NUMBER_OF_ZONES; zone_idx++) { - if(controller->zone_led_count[zone_idx] > 0) - { - zone* new_zone = new zone(); - led* new_led = new led(); + zone new_zone; + led new_led; - new_zone->name = gigabyte_fusion2_gpu_zone[zone_idx]; - new_zone->type = ZONE_TYPE_SINGLE; - new_zone->leds_min = controller->zone_led_count[zone_idx]; - new_zone->leds_max = new_zone->leds_min; - new_zone->leds_count = new_zone->leds_min; - new_zone->matrix_map = NULL; + new_zone.name = "GPU zone " + std::to_string(zone_idx + 1); + new_zone.type = ZONE_TYPE_SINGLE; + new_zone.leds_min = 1; + new_zone.leds_max = 1; + new_zone.leds_count = 1; + new_zone.matrix_map = NULL; - new_led->name = gigabyte_fusion2_gpu_zone[zone_idx]; - /*---------------------------------------------------------*\ - | Push the zone and LED on to device vectors | - \*---------------------------------------------------------*/ - leds.push_back(*new_led); - zones.push_back(*new_zone); - zoneIndexMap.push_back(zone_idx); - } + new_led.name = new_zone.name; + + /*---------------------------------------------------------*\ + | Push the zone and LED on to device vectors | + \*---------------------------------------------------------*/ + leds.push_back(new_led); + zones.push_back(new_zone); } + SetupColors(); } @@ -223,12 +201,12 @@ void RGBController_RGBFusion2GPU::DeviceUpdateLEDs() { fusion2_config zone_config; - zone_config.brightness = modes[active_mode].brightness; - zone_config.speed = modes[active_mode].speed; - zone_config.direction = modes[active_mode].direction; - zone_config.numberOfColors = (uint8_t)modes[active_mode].colors.size(); + zone_config.brightness = modes[active_mode].brightness; + zone_config.speed = modes[active_mode].speed; + zone_config.direction = modes[active_mode].direction; + zone_config.numberOfColors = (uint8_t)modes[active_mode].colors.size(); - for (uint8_t zone_idx = 0; zone_idx < zoneIndexMap.size(); zone_idx++) + for(uint8_t zone_idx = 0; zone_idx < RGB_FUSION_2_GPU_NUMBER_OF_ZONES; zone_idx++) { zone_config.colors[0] = colors[zone_idx]; @@ -240,22 +218,25 @@ void RGBController_RGBFusion2GPU::DeviceUpdateLEDs() } } - controller->SetZone(zoneIndexMap[zone_idx], modes[active_mode].value, zone_config); + controller->SetZone(zone_idx, modes[active_mode].value, zone_config); } } -void RGBController_RGBFusion2GPU::UpdateZoneLEDs(int /*zone*/) +void RGBController_RGBFusion2GPU::UpdateZoneLEDs(int zone) { + LOG_TRACE("[%s] Update zone #%d", name.c_str(), zone); DeviceUpdateLEDs(); } -void RGBController_RGBFusion2GPU::UpdateSingleLED(int /*led*/) +void RGBController_RGBFusion2GPU::UpdateSingleLED(int led) { + LOG_TRACE("[%s] Update single led : %d", name.c_str(), led); DeviceUpdateLEDs(); } void RGBController_RGBFusion2GPU::DeviceUpdateMode() { + LOG_TRACE("[%s] Switching to mode %s @ brightness %d and speed %d", name.c_str(), modes[active_mode].name.c_str(), modes[active_mode].brightness, modes[active_mode].speed); DeviceUpdateLEDs(); } diff --git a/Controllers/GigabyteRGBFusion2GPUController/RGBController_GigabyteRGBFusion2GPU.h b/Controllers/GigabyteRGBFusion2GPUController/RGBController_GigabyteRGBFusion2GPU.h index 895c821f..81a405d7 100644 --- a/Controllers/GigabyteRGBFusion2GPUController/RGBController_GigabyteRGBFusion2GPU.h +++ b/Controllers/GigabyteRGBFusion2GPUController/RGBController_GigabyteRGBFusion2GPU.h @@ -1,18 +1,19 @@ -/*-----------------------------------------*\ -| RGBController_GigabyteRGBFusion2GPU.h | -| | -| Generic RGB Interface for OpenRGB | -| Gigabyte RGB Fusion2 GPU Driver | -| | -| based on original by | -| Adam Honse (CalcProgrammer1) 2/23/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GigabyteRGBFusion2GPU.h | +| | +| RGBController for Gigabyte Aorus RGB Fusion 2 GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once #include "RGBController.h" #include "GigabyteRGBFusion2GPUController.h" +#define RGB_FUSION_2_GPU_NUMBER_OF_ZONES 5 + class RGBController_RGBFusion2GPU : public RGBController { public: @@ -31,8 +32,5 @@ public: void DeviceSaveMode(); private: - uint8_t getModeIndex(uint8_t mode_value); - RGBFusion2GPUController* controller; - std::vector zoneIndexMap; }; diff --git a/Controllers/GigabyteRGBFusion2SMBusController/GigabyteRGBFusion2SMBusController.cpp b/Controllers/GigabyteRGBFusion2SMBusController/GigabyteRGBFusion2SMBusController.cpp index b683bc04..fe88e004 100644 --- a/Controllers/GigabyteRGBFusion2SMBusController/GigabyteRGBFusion2SMBusController.cpp +++ b/Controllers/GigabyteRGBFusion2SMBusController/GigabyteRGBFusion2SMBusController.cpp @@ -1,22 +1,20 @@ -/*-----------------------------------------*\ -| GigabyteRGBFusion2SMBusController.cpp | -| | -| Driver for Gigabyte Aorus RGB Fusion 2 | -| SMBus lighting controller | -| | -| Adam Honse (CalcProgrammer1) 3/12/2020 | -| Matt Harper 5/5/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| GigabyteRGBFusion2SMBusController.cpp | +| | +| Driver for Gigabyte Aorus RGB Fusion 2 SMBus | +| motherboard | +| | +| Adam Honse (CalcProgrammer1) 12 Mar 2020 | +| Matt Harper 05 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "GigabyteRGBFusion2SMBusController.h" #include #include #include - -#ifdef DEBUG -#include -#include -#endif +#include "GigabyteRGBFusion2SMBusController.h" RGBFusion2SMBusController::RGBFusion2SMBusController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev, std::string mb_name) { @@ -71,20 +69,7 @@ void RGBFusion2SMBusController::WriteLED(int led) led -= 1; } - #ifdef DEBUG - std::cout << std::hex << write_register << "\t"; - for(int i = 0; i < 2; i++) - { - for(int j = 0; j < 16; j++) - { - std::cout << std::setw(2) << std::setfill('0') << std::hex << (int)led_data[led+i][j] << " "; - } - std::cout << " "; - } - std::cout << std::endl; - #endif - - bus->i2c_smbus_write_block_data(RGB_FUSION_2_SMBUS_ADDR, write_register, 32, led_data[led]); + bus->i2c_smbus_write_block_data(RGB_FUSION_2_SMBUS_ADDR, (u8)write_register, 32, led_data[led]); } void RGBFusion2SMBusController::Apply() diff --git a/Controllers/GigabyteRGBFusion2SMBusController/GigabyteRGBFusion2SMBusController.h b/Controllers/GigabyteRGBFusion2SMBusController/GigabyteRGBFusion2SMBusController.h index 9403d79b..2bdd868e 100644 --- a/Controllers/GigabyteRGBFusion2SMBusController/GigabyteRGBFusion2SMBusController.h +++ b/Controllers/GigabyteRGBFusion2SMBusController/GigabyteRGBFusion2SMBusController.h @@ -1,17 +1,21 @@ -/*-----------------------------------------*\ -| GigabyteRGBFusion2SMBusController.h | -| | -| Definitions and types for Gigabyte Aorus | -| RGB Fusion 2 SMBus lighting controller | -| | -| Adam Honse (CalcProgrammer1) 3/12/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| GigabyteRGBFusion2SMBusController.h | +| | +| Driver for Gigabyte Aorus RGB Fusion 2 SMBus | +| motherboard | +| | +| Adam Honse (CalcProgrammer1) 12 Mar 2020 | +| Matt Harper 05 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" -#pragma once - typedef unsigned char rgb_fusion_dev_id; enum @@ -92,7 +96,7 @@ public: std::string GetDeviceLocation(); unsigned int GetLEDCount(); void Apply(); - + void SetLEDEffect ( unsigned int led, diff --git a/Controllers/GigabyteRGBFusion2SMBusController/GigabyteRGBFusion2SMBusControllerDetect.cpp b/Controllers/GigabyteRGBFusion2SMBusController/GigabyteRGBFusion2SMBusControllerDetect.cpp index 6fc6df94..6c12f6cf 100644 --- a/Controllers/GigabyteRGBFusion2SMBusController/GigabyteRGBFusion2SMBusControllerDetect.cpp +++ b/Controllers/GigabyteRGBFusion2SMBusController/GigabyteRGBFusion2SMBusControllerDetect.cpp @@ -1,15 +1,25 @@ +/*---------------------------------------------------------*\ +| GigabyteRGBFusion2SMBusControllerDetect.cpp | +| | +| Detector for Gigabyte Aorus RGB Fusion 2 SMBus | +| motherboard | +| | +| Matt Harper 05 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include #include "Detector.h" #include "GigabyteRGBFusion2SMBusController.h" #include "LogManager.h" -#include "RGBController.h" #include "RGBController_GigabyteRGBFusion2SMBus.h" +#include "SettingsManager.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include -#include -#include "dependencies/dmiinfo.h" +#include "dmiinfo.h" #define DETECTOR_NAME "Gigabyte RGB Fusion 2 SMBus" #define VENDOR_NAME "Gigabyte Technology Co., Ltd." diff --git a/Controllers/GigabyteRGBFusion2SMBusController/RGBController_GigabyteRGBFusion2SMBus.cpp b/Controllers/GigabyteRGBFusion2SMBusController/RGBController_GigabyteRGBFusion2SMBus.cpp index 07733d71..dfa10e15 100644 --- a/Controllers/GigabyteRGBFusion2SMBusController/RGBController_GigabyteRGBFusion2SMBus.cpp +++ b/Controllers/GigabyteRGBFusion2SMBusController/RGBController_GigabyteRGBFusion2SMBus.cpp @@ -1,11 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_GigabyteRGBFusion2SMBus.cpp| -| | -| Generic RGB Interface for OpenRGB | -| Gigabyte RGB Fusion 2 SMBUS Driver | -| | -| Matt Harper (5/5/2020) | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GigabyteRGBFusion2SMBus.cpp | +| | +| RGBController for Gigabyte Aorus RGB Fusion 2 SMBus | +| motherboard | +| | +| Matt Harper 05 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_GigabyteRGBFusion2SMBus.h" @@ -246,7 +249,7 @@ void RGBController_RGBFusion2SMBus::ResizeZone(int /*zone*/, int /*new_size*/) void RGBController_RGBFusion2SMBus::DeviceUpdateLEDs() { - for (std::size_t led = 0; led < colors.size(); led++) + for(unsigned int led = 0; led < (unsigned int)colors.size(); led++) { RGBColor color = colors[led]; unsigned char red = RGBGetRValue(color); @@ -292,4 +295,4 @@ void RGBController_RGBFusion2SMBus::DeviceUpdateMode() int RGBController_RGBFusion2SMBus::GetDeviceMode() { return(0); -} \ No newline at end of file +} diff --git a/Controllers/GigabyteRGBFusion2SMBusController/RGBController_GigabyteRGBFusion2SMBus.h b/Controllers/GigabyteRGBFusion2SMBusController/RGBController_GigabyteRGBFusion2SMBus.h index 96f52f56..37b33166 100644 --- a/Controllers/GigabyteRGBFusion2SMBusController/RGBController_GigabyteRGBFusion2SMBus.h +++ b/Controllers/GigabyteRGBFusion2SMBusController/RGBController_GigabyteRGBFusion2SMBus.h @@ -1,12 +1,14 @@ - -/*-----------------------------------------*\ -| RGBController_GigabyteRGBFusion2SMBus.h | -| | -| Generic RGB Interface for OpenRGB | -| Gigabyte RGB Fusion 2 SMBUS Driver | -| | -| Matt Harper (5/5/2020) | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GigabyteRGBFusion2SMBus.h | +| | +| RGBController for Gigabyte Aorus RGB Fusion 2 SMBus | +| motherboard | +| | +| Matt Harper 05 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/GigabyteRGBFusion2USBController/GigabyteRGBFusion2USBController.cpp b/Controllers/GigabyteRGBFusion2USBController/GigabyteRGBFusion2USBController.cpp index 16ee7613..08c5dfb0 100644 --- a/Controllers/GigabyteRGBFusion2USBController/GigabyteRGBFusion2USBController.cpp +++ b/Controllers/GigabyteRGBFusion2USBController/GigabyteRGBFusion2USBController.cpp @@ -1,40 +1,36 @@ -/*-----------------------------------------*\ -| GigabyteRGBFusion2USBController.cpp | -| | -| Driver for Gigabyte Aorus RGB Fusion 2.0 | -| USB lighting controller | -| | -| Author: jackun 1/8/2020 | -| Maintainer: Chris M (Dr_No) | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| GigabyteRGBFusion2USBController.cpp | +| | +| Driver for Gigabyte Aorus RGB Fusion 2 USB motherboard | +| | +| jackun 08 Jan 2020 | +| megadjc 31 Jul 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "GigabyteRGBFusion2USBController.h" -#include "ResourceManager.h" -#include "SettingsManager.h" /*-------------------------------------------------------------------------*\ +| Low level RGB value conversion table | | This is stored as a uint32_t in the chip so is trasmitted LSB to MSB | | Therefore the numbers represent the index where the controller will find | | respective colour in a regular packet | \*-------------------------------------------------------------------------*/ static RGBCalibration GigabyteCalibrationsLookup { - { "BGR", { 0x00, 0x01, 0x02, 0x00} }, - { "BRG", { 0x01, 0x00, 0x02, 0x00} }, - { "GRB", { 0x02, 0x00, 0x01, 0x00} }, - { "GBR", { 0x00, 0x02, 0x01, 0x00} }, - { "RGB", { 0x02, 0x01, 0x00, 0x00} }, - { "RBG", { 0x01, 0x02, 0x00, 0x00} } -}; - -static calibration GigabyteBoardCalibration -{ - { "D_LED1", "GRB" }, - { "D_LED2", "GRB" }, - { "Mainboard", "BGR" }, - { "Spare", "BGR" } + { "BGR", {{{0x00, 0x01, 0x02, 0x00}}}}, + { "BRG", {{{0x01, 0x00, 0x02, 0x00}}}}, + { "GRB", {{{0x02, 0x00, 0x01, 0x00}}}}, + { "GBR", {{{0x00, 0x02, 0x01, 0x00}}}}, + { "RGB", {{{0x02, 0x01, 0x00, 0x00}}}}, + { "RBG", {{{0x01, 0x02, 0x00, 0x00}}}} }; +/*---------------------------------------------------------*\ +| Converts LED counts to divisions in hardware | +\*---------------------------------------------------------*/ static LEDCount LedCountToEnum(unsigned int c) { if(c <= 32) @@ -59,47 +55,21 @@ static LEDCount LedCountToEnum(unsigned int c) } } -RGBFusion2USBController::RGBFusion2USBController(hid_device* handle, const char *path, std::string mb_name) : dev(handle) +RGBFusion2USBController::RGBFusion2USBController(hid_device* handle, const char* path, std::string mb_name, uint16_t pid): dev(handle), product_id(pid) { - int res = 0; - char text[64] = { 0x00 }; - unsigned char buffer[64] = { 0x00 }; - - if(dev) + name = mb_name; + location = path; + + if(!RefreshHardwareInfo()) { - SetCalibration(); - - name = mb_name; - - /*---------------------------------------------------------*\ - | HID report read needs 0x60 packet or it gives IO error | - \*---------------------------------------------------------*/ - SendPacket(0x60, 0x00); - - buffer[0] = report_id; - res = hid_get_feature_report(dev, buffer, 64); - - if(res > 0) - { - report = *reinterpret_cast(buffer); - - description = std::string(report.str_product, 32); - description.erase(std::find(description.begin(), description.end(), '\0'), description.end()); - - snprintf(text, 11, "0x%08X", report.fw_ver); - version = text; - - snprintf(text, 11, "0x%08X", report.chip_id); - chip_id = text; - - D_LED1_count = LedCountToEnum(report.total_leds & 0x0F); - D_LED2_count = LedCountToEnum(report.total_leds & 0xF0); - } - - location = path; - - EnableBeat(false); + return; } + if(report.support_cmd_flag >= 0x02) + { + EnableLampArray(false); + } + ResetController(); + EnableBeat(false); } RGBFusion2USBController::~RGBFusion2USBController() @@ -107,130 +77,382 @@ RGBFusion2USBController::~RGBFusion2USBController() hid_close(dev); } +/*---------------------------------------------------------*\ +| Read configuration data from hardware. | +| Returns false if read fails. | +\*---------------------------------------------------------*/ +bool RGBFusion2USBController::RefreshHardwareInfo() +{ + unsigned char buffer[FUSION2_USB_BUFFER_SIZE] = {0}; + + SendPacket(0x60, 0x00); + buffer[0] = report_id; + int res = hid_get_feature_report(dev, buffer, sizeof(buffer)); + + if(res < static_cast(sizeof(IT8297Report))) + { + report_loaded = false; + return false; + } + + std::memcpy(&report, buffer, sizeof(IT8297Report)); + report_loaded = true; + + description = std::string(report.str_product, 28); + if(std::string::iterator nul = std::find(description.begin(), description.end(), '\0'); + nul != description.end()) + { + description.erase(nul, description.end()); + } + + { + char text[32]{}; + + uint32_t fw_ver = ((report.fw_ver & 0x000000FFu) << 24) + | ((report.fw_ver & 0x0000FF00u) << 8) + | ((report.fw_ver & 0x00FF0000u) >> 8) + | ((report.fw_ver & 0xFF000000u) >> 24); + + uint8_t b0 = static_cast((fw_ver >> 24) & 0xFFu); + uint8_t b1 = static_cast((fw_ver >> 16) & 0xFFu); + uint8_t b2 = static_cast((fw_ver >> 8) & 0xFFu); + uint8_t b3 = static_cast( fw_ver & 0xFFu); + + std::snprintf(text, sizeof(text), "%u.%u.%u.%u", b0, b1, b2, b3); + version = text; + std::snprintf(text, sizeof(text), "0x%08X", report.chip_id); + chip_id = text; + } + + D_LED1_count = LedCountToEnum(report.curr_led_count_low & 0x0F); + D_LED2_count = LedCountToEnum((report.curr_led_count_low >> 4) & 0x0F); + D_LED3_count = LedCountToEnum(report.curr_led_count_high & 0x0F); + D_LED4_count = LedCountToEnum((report.curr_led_count_high >> 4) & 0x0F); + + cal_data.dled[0] = report.cal_strip0; + cal_data.dled[1] = report.cal_strip1; + cal_data.mainboard = report.rgb_cali; + cal_data.spare[0] = report.cal_spare0; + cal_data.spare[1] = report.cal_spare1; + + cali_loaded = false; + if(product_id == 0x5711) + { + unsigned char buffer2[FUSION2_USB_BUFFER_SIZE] = {0}; + SendPacket(0x61, 0x00); + buffer2[0] = report_id; + int res2 = hid_get_feature_report(dev, buffer2, sizeof(buffer2)); + + if(res2 >= static_cast(sizeof(IT5711Calibration))) + { + std::memcpy(&cali, buffer2, sizeof(IT5711Calibration)); + cali_loaded = true; + + cal_data.dled[2] = cali.cal_strip2; + cal_data.dled[3] = cali.cal_strip3; + cal_data.spare[2] = cali.cal_spare2; + cal_data.spare[3] = cali.cal_spare3; + } + else + { + cal_data.dled[2] = 0; + cal_data.dled[3] = 0; + cal_data.spare[2] = 0; + cal_data.spare[3] = 0; + cali_loaded = false; + } + } + else + { + cal_data.dled[2] = 0; + cal_data.dled[3] = 0; + cal_data.spare[2] = 0; + cal_data.spare[3] = 0; + } + + return report_loaded; +} + void RGBFusion2USBController::SetMode(int m) { mode = m; } -RGBA RGBFusion2USBController::GetCalibration(std::string rgb_order) +std::string RGBFusion2USBController::DecodeCalibrationBuffer(uint32_t value) const { - /*-------------------------------------------------*\ - | Check for RGB order string in calibration table | - | If not found return the "BGR" calibration | - \*-------------------------------------------------*/ - if(GigabyteCalibrationsLookup.count(rgb_order)) + if(value==0) return "OFF"; + + uint8_t bo_b = value & 0xFF; + uint8_t bo_g = (value >> 8) & 0xFF; + uint8_t bo_r = (value >> 16) & 0xFF; + + bool in_range = (bo_r<3 && bo_g<3 && bo_b<3); + bool distinct = (bo_r!=bo_g && bo_r!=bo_b && bo_g!=bo_b); + + if(in_range && distinct) { - return GigabyteCalibrationsLookup.find(rgb_order)->second; + std::string out(3, '?'); + out[bo_r] = 'R'; + out[bo_g] = 'G'; + out[bo_b] = 'B'; + return out; + } + + return "BAD"; +} + +uint32_t RGBFusion2USBController::EncodeCalibrationBuffer(const std::string& rgb_order) +{ + if(rgb_order.empty()) + { + return 0u; + } + + std::string key = rgb_order; + std::transform(key.begin(), key.end(), key.begin(), + [](unsigned char c){ return char(std::toupper(c)); }); + + if(key=="OFF" || key=="0") + { + return 0u; + } + + RGBCalibration::const_iterator it = GigabyteCalibrationsLookup.find(key); + if(it == GigabyteCalibrationsLookup.end()) + { + return 0u; + } + + const RGBA &rgb_cal = it->second; + return (uint32_t(rgb_cal.raw[0])) + | (uint32_t(rgb_cal.raw[1]) << 8) + | (uint32_t(rgb_cal.raw[2]) << 16) + | (uint32_t(rgb_cal.raw[3]) << 24); +} + + +EncodedCalibration RGBFusion2USBController::GetCalibration(bool refresh_from_hw) +{ + if(refresh_from_hw || !report_loaded || (product_id == 0x5711 && !cali_loaded)) + { + if(!RefreshHardwareInfo()) + { + return EncodedCalibration{}; + } + } + + EncodedCalibration out{}; + out.dled[0] = DecodeCalibrationBuffer(cal_data.dled[0]); + out.dled[1] = DecodeCalibrationBuffer(cal_data.dled[1]); + out.spare[0] = DecodeCalibrationBuffer(cal_data.spare[0]); + out.spare[1] = DecodeCalibrationBuffer(cal_data.spare[1]); + out.mainboard = DecodeCalibrationBuffer(cal_data.mainboard); + + if(product_id == 0x5711) + { + out.dled[2] = DecodeCalibrationBuffer(cal_data.dled[2]); + out.dled[3] = DecodeCalibrationBuffer(cal_data.dled[3]); + out.spare[2] = DecodeCalibrationBuffer(cal_data.spare[2]); + out.spare[3] = DecodeCalibrationBuffer(cal_data.spare[3]); } else { - return GigabyteCalibrationsLookup.find("BGR")->second; + out.dled[2] = "OFF"; + out.dled[3] = "OFF"; + out.spare[2] = "OFF"; + out.spare[3] = "OFF"; } + + return out; } -void RGBFusion2USBController::SetCalibrationBuffer(std::string rgb_order, uint8_t* buffer, uint8_t offset) +bool RGBFusion2USBController::SetCalibration(const EncodedCalibration& cal, bool refresh_from_hw) { - RGBA rgb_cal; - int raw_size = sizeof(rgb_cal.raw) / sizeof(rgb_cal.raw[0]); - - rgb_cal = GetCalibration(rgb_order); - - for(int i = 0; i < raw_size; i++) + if(refresh_from_hw) { - buffer[offset + i] = rgb_cal.raw[i]; + if(!RefreshHardwareInfo()) + { + return false; + } } -} -/*---------------------------------------------------------------------------------------------*\ -| Sets RGB color mapping to LED pins. | -| "Custom" RGB packets don't seem to get remapped so use report.byteorderN and do it manually. | -| Of course it all depends how we send data to the controller, but bios/rgb fusion 2 itself | -| set it up like this. | -\*---------------------------------------------------------------------------------------------*/ -void RGBFusion2USBController::SetCalibration() -{ - const std::string detector_name = "Gigabyte RGB Fusion 2 USB"; - const std::string json_cal = "Calibration"; - SettingsManager* settings_manager = ResourceManager::get()->GetSettingsManager(); - json device_settings = settings_manager->GetSettings(detector_name); - - /*---------------------------------------------------------*\ - | Get Layouts from the settings manager | - | If Calibration settings are not found then write them out | - | Calibration will only be executed if it is explicitly | - | enabled by the user | - \*---------------------------------------------------------*/ - if(!device_settings.contains(json_cal)) + if(EncodeCalibrationBuffer(cal.dled[0]) == cal_data.dled[0] + && EncodeCalibrationBuffer(cal.dled[1]) == cal_data.dled[1] + && EncodeCalibrationBuffer(cal.mainboard) == cal_data.mainboard + && EncodeCalibrationBuffer(cal.spare[0]) == cal_data.spare[0] + && EncodeCalibrationBuffer(cal.spare[1]) == cal_data.spare[1] + && (product_id != 0x5711 + || (EncodeCalibrationBuffer(cal.dled[2]) == cal_data.dled[2] + && EncodeCalibrationBuffer(cal.dled[3]) == cal_data.dled[3] + && EncodeCalibrationBuffer(cal.spare[2]) == cal_data.spare[2] + && EncodeCalibrationBuffer(cal.spare[3]) == cal_data.spare[3]))) { - device_settings[json_cal]["Enabled"] = false; - device_settings[json_cal]["Data"] = GigabyteBoardCalibration; - - settings_manager->SetSettings(detector_name, device_settings); - settings_manager->SaveSettings(); + return true; } - else if(device_settings[json_cal]["Enabled"]) + + CMD_0x33 desired{}; + std::memset(&desired, 0, sizeof(desired)); + desired.report_id = report_id; + desired.command_id = 0x33; + + desired.d_strip_c0 = EncodeCalibrationBuffer(cal.dled[0]); + desired.d_strip_c1 = EncodeCalibrationBuffer(cal.dled[1]); + desired.rgb_cali = EncodeCalibrationBuffer(cal.mainboard); + desired.c_spare0 = EncodeCalibrationBuffer(cal.spare[0]); + desired.c_spare1 = EncodeCalibrationBuffer(cal.spare[1]); + + if(product_id == 0x5711) { - GigabyteBoardCalibration["D_LED1"] = device_settings[json_cal]["Data"]["D_LED1"]; - GigabyteBoardCalibration["D_LED2"] = device_settings[json_cal]["Data"]["D_LED2"]; - GigabyteBoardCalibration["Mainboard"] = device_settings[json_cal]["Data"]["Mainboard"]; - GigabyteBoardCalibration["Spare"] = device_settings[json_cal]["Data"]["Spare"]; - - uint8_t buffer[64] = { 0x00 }; - buffer[0] = report_id; - buffer[1] = 0x33; - - SetCalibrationBuffer( GigabyteBoardCalibration.find("D_LED1")->second, buffer, 2); - SetCalibrationBuffer( GigabyteBoardCalibration.find("D_LED2")->second, buffer, 6); - SetCalibrationBuffer( GigabyteBoardCalibration.find("Mainboard")->second, buffer, 10); - SetCalibrationBuffer( GigabyteBoardCalibration.find("Spare")->second, buffer, 14); - - SendPacket(buffer); + desired.d_strip_c2 = EncodeCalibrationBuffer(cal.dled[2]); + desired.d_strip_c3 = EncodeCalibrationBuffer(cal.dled[3]); + desired.c_spare2 = EncodeCalibrationBuffer(cal.spare[2]); + desired.c_spare3 = EncodeCalibrationBuffer(cal.spare[3]); } -} -void RGBFusion2USBController::SetLedCount(unsigned int led, unsigned int count) -{ - /*-----------------------------------------------------------------*\ - | Check which Digital LED we're setting then send the value of both | - \*-----------------------------------------------------------------*/ - if(led == HDR_D_LED1) + std::memset(desired.reserved, 0, sizeof(desired.reserved)); + int rc = SendPacket(reinterpret_cast(&desired)); + if(rc < 0) { - D_LED1_count = LedCountToEnum(count); + return false; + } + + ResetController(); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + SaveCalState(); + std::this_thread::sleep_for(std::chrono::milliseconds(20)); + + cal_data.dled[0] = desired.d_strip_c0; + cal_data.dled[1] = desired.d_strip_c1; + cal_data.mainboard = desired.rgb_cali; + cal_data.spare[0] = desired.c_spare0; + cal_data.spare[1] = desired.c_spare1; + + if(product_id == 0x5711) + { + cal_data.dled[2] = desired.d_strip_c2; + cal_data.dled[3] = desired.d_strip_c3; + cal_data.spare[2] = desired.c_spare2; + cal_data.spare[3] = desired.c_spare3; } else { - D_LED2_count = LedCountToEnum(count); + cal_data.dled[2] = 0u; + cal_data.dled[3] = 0u; + cal_data.spare[2] = 0u; + cal_data.spare[3] = 0u; } - SendPacket(0x34, D_LED1_count | (D_LED2_count << 4)); + return true; } -bool RGBFusion2USBController::DisableBuiltinEffect(int enable_bit, int mask) +void RGBFusion2USBController::SetLedCount(unsigned int c0, unsigned int c1, unsigned int c2, unsigned int c3) { - if(effect_disabled & enable_bit) + new_d1 = LedCountToEnum(c0); + new_d2 = LedCountToEnum(c1); + new_d3 = LedCountToEnum(c2); + new_d4 = LedCountToEnum(c3); + + if(new_d1 == D_LED1_count && new_d2 == D_LED2_count && new_d3 == D_LED3_count && new_d4 == D_LED4_count) { - return(true); + return; } - effect_disabled &= ~mask; - effect_disabled |= enable_bit; + D_LED1_count = new_d1; + D_LED2_count = new_d2; + D_LED3_count = new_d3; + D_LED4_count = new_d4; + unsigned char buffer[FUSION2_USB_BUFFER_SIZE] = { 0 }; + buffer[0] = report_id; + buffer[1] = 0x34; + buffer[2] = (new_d2 << 4) | new_d1; + buffer[3] = (new_d4 << 4) | new_d3; + SendPacket(buffer); +} + +/*---------------------------------------------------------*\ +| Switch ARGB header mode (single/addressable) | +\*---------------------------------------------------------*/ +bool RGBFusion2USBController::SetStripBuiltinEffectState(int hdr, bool enable) +{ + static bool first_call = true; + int bitmask = 0; + + if(hdr == -1) + { + bitmask = 0x01 | 0x02 | 0x08 | 0x10; + } + else + { + switch(hdr) + { + case LED4: + case HDR_D_LED2: + case HDR_D_LED2_RGB: + bitmask = 0x02; + break; + case HDR_D_LED3: + case HDR_D_LED3_RGB: + bitmask = 0x08; + break; + case HDR_D_LED4: + case HDR_D_LED4_RGB: + bitmask = 0x10; + break; + default: + bitmask = 0x01; + break; + } + } + + int new_effect_disabled = enable + ? (effect_disabled & ~bitmask) + : (effect_disabled | bitmask); + + if(!first_call && new_effect_disabled == effect_disabled) + { + return true; + } + + first_call = false; + effect_disabled = new_effect_disabled; int res = SendPacket(0x32, effect_disabled); - - /*-----------------------------------------------------------------*\ - | Sometimes effect doesn't apply at first, delay a little and let | - | MCU react, if this packet is the cause | - \*-----------------------------------------------------------------*/ std::this_thread::sleep_for(std::chrono::milliseconds(50)); - return res; } +/*---------------------------------------------------------*\ +| Persist LED config data | +\*---------------------------------------------------------*/ +bool RGBFusion2USBController::SaveLEDState(bool e) +{ + return SendPacket(0x47, e ? 1 : 0); +} + +/*---------------------------------------------------------*\ +| Persist calibration | +\*---------------------------------------------------------*/ +bool RGBFusion2USBController::SaveCalState() +{ + return SendPacket(0x5E, 0); +} + +/*---------------------------------------------------------*\ +| Set beat mode (hardware audio sync mode) | +\*---------------------------------------------------------*/ bool RGBFusion2USBController::EnableBeat(bool e) { return SendPacket(0x31, e ? 1 : 0); } +/*---------------------------------------------------------*\ +| Set Lamp Array mode (MSDL) | +\*---------------------------------------------------------*/ +bool RGBFusion2USBController::EnableLampArray(bool enable) +{ + return SendPacket(0x48, enable ? 1 : 0); +} + std::string RGBFusion2USBController::GetDeviceName() { return(name); @@ -256,29 +478,45 @@ std::string RGBFusion2USBController::GetSerial() return(chip_id); } -void RGBFusion2USBController::SetStripColors - ( - unsigned int hdr, - RGBColor * colors, - unsigned int num_colors, - int single_led - ) +/*---------------------------------------------------------*\ +| PID (controller feature support) | +\*---------------------------------------------------------*/ +uint16_t RGBFusion2USBController::GetProductID() +{ + return (product_id); +} + +/*---------------------------------------------------------*\ +| Low level controller number (multi-controller) | +\*---------------------------------------------------------*/ +uint8_t RGBFusion2USBController::GetDeviceNum() +{ + return (device_num); +} + +/*---------------------------------------------------------*\ +| Set ARGB strips (addressable) | +\*---------------------------------------------------------*/ +void RGBFusion2USBController::SetStripColors(unsigned int hdr, RGBColor* colors, unsigned int num_colors, int single_led) { PktRGB pkt; pkt.Init(hdr, report_id); - - /*-------------------------------------------------------------------------*\ - | FIXME assuming that LED strips ports are 0x58/0x59 for all boards | - \*-------------------------------------------------------------------------*/ uint32_t byteorder; - - if(hdr == HDR_D_LED1_RGB) + + switch(pkt.s.header) { - byteorder = report.byteorder0; - } - else - { - byteorder = report.byteorder1; + case HDR_D_LED2_RGB: + byteorder = cal_data.dled[1]; + break; + case HDR_D_LED3_RGB: + byteorder = cal_data.dled[2]; + break; + case HDR_D_LED4_RGB: + byteorder = cal_data.dled[3]; + break; + default: + byteorder = cal_data.dled[0]; + break; } unsigned char bo_r = byteorder >> 16; @@ -291,10 +529,6 @@ void RGBFusion2USBController::SetStripColors int k = 0; int leds_in_pkt = sizeof(pkt.s.leds) / sizeof(*pkt.s.leds); /* 19 */ - /*-------------------------------------------------------------------------*\ - | Other leds stay at whatever the builtin effect was doing at that moment | - | if breathing/pulse effect faded out then they stay dark | - \*-------------------------------------------------------------------------*/ if(single_led > -1) { leds_left = 1; @@ -314,14 +548,12 @@ void RGBFusion2USBController::SetStripColors for(int i = 0; i < leds_in_pkt; i++) { - RGBColor color = colors[k]; - unsigned char red = RGBGetRValue(color); - unsigned char grn = RGBGetGValue(color); - unsigned char blu = RGBGetBValue(color); + RGBColor color = colors[k]; + uint8_t offset = (i * 3) + 5; - pkt.buffer[5 + i * 3 + bo_r] = red; - pkt.buffer[5 + i * 3 + bo_g] = grn; - pkt.buffer[5 + i * 3 + bo_b] = blu; + pkt.buffer[offset + bo_r] = RGBGetRValue(color); + pkt.buffer[offset + bo_g] = RGBGetGValue(color); + pkt.buffer[offset + bo_b] = RGBGetBValue(color); k++; } @@ -332,98 +564,149 @@ void RGBFusion2USBController::SetStripColors return; } } - - if(hdr == HDR_D_LED1_RGB) - { - DisableBuiltinEffect(0x01, 0x01); - } - else - { - DisableBuiltinEffect(0x02, 0x02); - } } -static const std::array< std::array, 5> speeds = -{ - { - {1600, 1600, 200}, - {1200, 1200, 200}, - {800, 800, 200}, - {400, 400, 200}, - {200, 200, 200}, - }, -}; - -void RGBFusion2USBController::SetLEDEffect(unsigned int led, int mode, unsigned int speed, unsigned char brightness, bool random, unsigned char r, unsigned char g, unsigned char b) +/*---------------------------------------------------------*\ +| Set hardware effects (single) | +| Note: Effects paramters match that of gigabyte software. | +| -(2)Gigabyte breathe ranges are 400-1000ms in 100ms steps | +| and 1000-1600ms in 200ms steps | +| -(3)Gigabyte flash ranges are 600-2400ms in 200ms steps | +| -(4)Gigabyte color cycle ranges are 300-2400ms for period0| +| and 100-2200ms for period1 in 100ms steps. | +| the follow this trend between 300-1100/100-1000ms | +| then jump to 2400ms and 2200ms respective on speed 9. | +| -(6)Gigabyte Wave ranges are 30-300ms in steps following | +| the following formula. 2.5(s+1)^2 + 2.5(s+1) + 25. | +| -(15)Gigabyte dflash ranges are 800-2600ms in 200ms steps | +| -(3)(15)flash and dflash parameters were combined. | +\*---------------------------------------------------------*/ +void RGBFusion2USBController::SetLEDEffect(int led, int mode, unsigned int speed, unsigned char brightness, bool random, uint32_t* color) { PktEffect pkt; - - pkt.Init(led, report_id); - pkt.e.effect_type = mode; - pkt.e.color0 = r << 16 | g << 8 | b; - - pkt.e.max_brightness = brightness; + pkt.Init(led, report_id, product_id); + if(led == -1) + { + effect_zone_mask = pkt.e.zone0; + } + else if((effect_zone_mask & pkt.e.zone0) == 0) + { + effect_zone_mask |= pkt.e.zone0; + } + pkt.e.max_brightness = brightness; + pkt.e.effect_type = mode; + pkt.e.effect_param0 = random ? 7 : 0; + pkt.e.color0 = RGBToBGRColor(*color); switch(mode) { - case 0: // Direct - case 1: // Static + case EFFECT_PULSE: + pkt.e.period0 = (speed <= 6) ? (400 + speed * 100) : (1000 + (speed - 6) * 200); + pkt.e.period1 = pkt.e.period0; + pkt.e.period2 = 200; break; - - case 2: //Breathing - case 3: //Blink - case 4: // Color Cycle - if(speed < speeds.size()) - { - const std::array& s = speeds[speed]; - - pkt.e.period0 = s[0]; - pkt.e.period1 = s[1]; - pkt.e.period2 = s[2]; - } - - if(random) - { - pkt.e.effect_param0 = 7; // cycle through up to 7 (max?) colors - } + case EFFECT_DFLASH: + pkt.e.effect_type = 3; + pkt.e.effect_param1 = 1; + pkt.e.effect_param2 = 2; + case EFFECT_BLINKING: + pkt.e.period0 = 100; + pkt.e.period1 = 100; + pkt.e.period2 = (speed * 200) + 700; break; - - // "Fake" effects - case 10: // flashing, flashing color cycle - pkt.e.period0 = 200; - pkt.e.period1 = 200; - pkt.e.period2 = 5000 - 1000 * speed; // time between flashing, doesn't seem to be affected by period0/period1 - pkt.e.effect_type = 3; - pkt.e.effect_param2 = 2; // flash twice - - if (random) - { - pkt.e.effect_param0 = 7; - } + case EFFECT_COLORCYCLE: + pkt.e.period0 = (speed * 100 + 300) + (speed > 8 ? 1300 * (speed - 8) : 0); + pkt.e.period1 = pkt.e.period0 -200; + pkt.e.effect_param0 = 7; + break; + case EFFECT_WAVE: + pkt.e.period0 = (((speed + 1)^2) + (speed + 1) + 10) * 5 / 2; + pkt.e.effect_param0 = 7; + pkt.e.effect_param1 = 1; + break; + case EFFECT_RANDOM: + pkt.e.period0 = 100; + pkt.e.effect_param0 = 1; + pkt.e.effect_param1 = 5; + break; + case EFFECT_WAVE1: + pkt.e.period0 = 1200; + pkt.e.period1 = 100; + pkt.e.period2 = 360; + pkt.e.period3 = 1200; + break; + case EFFECT_WAVE2: + case EFFECT_WAVE4: + pkt.e.period0 = 200; + pkt.e.effect_param0 = 7; + break; + case EFFECT_WAVE3: + pkt.e.period0 = 840; + pkt.e.period1 = 20; + pkt.e.period2 = 200; + pkt.e.period3 = 840; break; } - SendPacket(pkt.buffer); } -bool RGBFusion2USBController::ApplyEffect() +/*---------------------------------------------------------*\ +| Apply hardware effects (single) | +\*---------------------------------------------------------*/ +bool RGBFusion2USBController::ApplyEffect(bool fast_apply) { - return SendPacket(0x28, 0xFF); + if(fast_apply) + { + if(product_id == 0x5711) + { + return SendPacket(0x28, 0xFF, 0x07); + } + else + { + return SendPacket(0x28, 0xFF, 0x00); + } + } + + PktEffectApply pkt = {}; + pkt.a.zone_sel0 = effect_zone_mask; + + effect_zone_mask = 0; + return SendPacket(pkt.buffer); } bool RGBFusion2USBController::SendPacket(uint8_t a, uint8_t b, uint8_t c) { - unsigned char buffer[64] {}; + unsigned char buffer[FUSION2_USB_BUFFER_SIZE] {}; buffer[0] = report_id; buffer[1] = a; buffer[2] = b; buffer[3] = c; - return(SendPacket(buffer) == 64); + return(SendPacket(buffer) == FUSION2_USB_BUFFER_SIZE); } int RGBFusion2USBController::SendPacket(unsigned char* packet) { - return hid_send_feature_report(dev, packet, 64); + return hid_send_feature_report(dev, packet, FUSION2_USB_BUFFER_SIZE); +} + +/*---------------------------------------------------------*\ +| Reset controller parameters | +\*---------------------------------------------------------*/ +void RGBFusion2USBController::ResetController() +{ + for(uint8_t reg = 0x20; reg <= 0x27; ++reg) + { + SendPacket(reg, 0x00, 0x00); + } + + if(product_id == 0x5711) + { + for(uint8_t reg = 0x90; reg <= 0x92; ++reg) + { + SendPacket(reg, 0x00, 0x00); + } + } + ApplyEffect(true); } diff --git a/Controllers/GigabyteRGBFusion2USBController/GigabyteRGBFusion2USBController.h b/Controllers/GigabyteRGBFusion2USBController/GigabyteRGBFusion2USBController.h index 14e1bf77..e989307a 100644 --- a/Controllers/GigabyteRGBFusion2USBController/GigabyteRGBFusion2USBController.h +++ b/Controllers/GigabyteRGBFusion2USBController/GigabyteRGBFusion2USBController.h @@ -1,76 +1,95 @@ -/*-----------------------------------------*\ -| GigabyteRGBFusion2USBController.h | -| | -| Definitions and types for Gigabyte Aorus | -| RGB Fusion 2.0 USB lighting controller | -| | -| Author: jackun 1/8/2020 | -| Maintainer: Chris M (Dr_No) | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include -#include -#include -#include -#include -#include +/*---------------------------------------------------------*\ +| GigabyteRGBFusion2USBController.h | +| | +| Driver for Gigabyte Aorus RGB Fusion 2 USB motherboard | +| | +| jackun 08 Jan 2020 | +| megadjc 31 Jul 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#define GB_CALIBRATION_SIZE (sizeof(GB_Calibrations) / sizeof(GB_Calibrations[0])) +#include +#include +#include +#include +#include "RGBController.h" -/*-------------------------------------------------------------*\ -| Standardising LED naming for external config layout | -\*-------------------------------------------------------------*/ -const uint8_t LED1 = 0x20; -const uint8_t LED2 = 0x21; -const uint8_t LED3 = 0x22; -const uint8_t LED4 = 0x23; -const uint8_t LED5 = 0x24; -const uint8_t LED6 = 0x25; -const uint8_t LED7 = 0x26; -const uint8_t LED8 = 0x27; +#define FUSION2_USB_BUFFER_SIZE 64 -/*-------------------------------------------------------------*\ -| LED "headers" 0x20..0x27, As seen on Gigabyte X570 Elite board| -| Internal legacy shorthand naming and possibly deprecated | -\*-------------------------------------------------------------*/ -const uint8_t HDR_BACK_IO = LED1; -const uint8_t HDR_CPU = LED2; -const uint8_t HDR_LED_2 = LED3; -const uint8_t HDR_PCIE = LED4; -const uint8_t HDR_LED_C1C2 = LED5; -const uint8_t HDR_D_LED1 = LED6; -const uint8_t HDR_D_LED2 = LED7; -const uint8_t HDR_LED_7 = LED8; +/*--------------------------------------------------------*\ +| Base LED mappings found on all controllers. | +\*--------------------------------------------------------*/ +const uint8_t LED1 = 0; +const uint8_t LED2 = 1; +const uint8_t LED3 = 2; +const uint8_t LED4 = 3; +const uint8_t LED5 = 4; +const uint8_t LED6 = 5; +const uint8_t LED7 = 6; +const uint8_t LED8 = 7; -/*-------------------------------------------------------------*\ -| FIXME assuming that it is 0x58 for all boards | -\*-------------------------------------------------------------*/ -const uint8_t HDR_D_LED1_RGB = 0x58; -const uint8_t HDR_D_LED2_RGB = 0x59; +/*--------------------------------------------------------*\ +| IT8297/IT5701/IT5702 ARGB Headers | +\*--------------------------------------------------------*/ +const uint8_t HDR_D_LED1 = LED6; +const uint8_t HDR_D_LED2 = LED7; +const uint8_t HDR_D_LED1_RGB = 0x58; +const uint8_t HDR_D_LED2_RGB = 0x59; +/*--------------------------------------------------------*\ +| Additional LED mappings found on IT5711 controllers. | +\*--------------------------------------------------------*/ +const uint8_t LED9 = 8; +const uint8_t LED10 = 9; +const uint8_t LED11 = 10; + +/*--------------------------------------------------------*\ +| IT5711 additional ARGB Headers. | +\*--------------------------------------------------------*/ +const uint8_t HDR_D_LED3 = LED8; +const uint8_t HDR_D_LED4 = LED9; +const uint8_t HDR_D_LED3_RGB = 0x62; +const uint8_t HDR_D_LED4_RGB = 0x63; + +/*---------------------------------------------------------*\ +| Effects mode list | +\*---------------------------------------------------------*/ enum EffectType { - EFFECT_NONE = 0, - EFFECT_STATIC = 1, - EFFECT_PULSE = 2, - EFFECT_BLINKING = 3, - EFFECT_COLORCYCLE = 4, + EFFECT_NONE = 0, + EFFECT_STATIC = 1, + EFFECT_PULSE = 2, + EFFECT_BLINKING = 3, + EFFECT_COLORCYCLE = 4, + EFFECT_WAVE = 6, + EFFECT_RANDOM = 8, + EFFECT_WAVE1 = 9, + EFFECT_WAVE2 = 10, + EFFECT_WAVE3 = 11, + EFFECT_WAVE4 = 12, + EFFECT_DFLASH = 15, // to be continued... }; +/*---------------------------------------------------------*\ +| Low level strip length divisions | +\*---------------------------------------------------------*/ enum LEDCount { - LEDS_32 = 0, + LEDS_32 = 0, LEDS_64, LEDS_256, LEDS_512, LEDS_1024, }; +/*---------------------------------------------------------*\ +| Defines the RGB led data structure. | +\*---------------------------------------------------------*/ struct LEDs { uint8_t r; @@ -78,8 +97,52 @@ struct LEDs uint8_t b; }; +/*---------------------------------------------------------*\ +| Defines structure for low level calibration data. | +\*---------------------------------------------------------*/ +struct CalibrationData +{ + uint32_t dled[4] = {0}; + uint32_t spare[4] = {0}; + uint32_t mainboard = 0; +}; + +/*---------------------------------------------------------*\ +| Defines structure for high level calibration data. | +\*---------------------------------------------------------*/ +struct EncodedCalibration +{ + std::string dled[4]; + std::string spare[4]; + std::string mainboard; +}; + #pragma pack(push, 1) +/*---------------------------------------------------------*\ +| Packet structure for applying effects | +\*---------------------------------------------------------*/ +union PktEffectApply +{ + unsigned char buffer[FUSION2_USB_BUFFER_SIZE]; + struct apply_data + { + uint8_t report_id = 0xCC; + uint8_t command_id = 0x28; + uint32_t zone_sel0 = 0; + uint32_t zone_sel1 = 0; + uint8_t padding[54]; + } a; + + PktEffectApply() : a {} + { + std::memset(a.padding, 0, sizeof(a.padding)); + } +}; + +/*---------------------------------------------------------*\ +| Single LED Calibration struct | +\*---------------------------------------------------------*/ struct RGBA { union @@ -98,14 +161,17 @@ struct RGBA typedef std::map< std::string, RGBA > RGBCalibration; typedef std::map< std::string, std::string> calibration; +/*---------------------------------------------------------*\ +| Packet structure for ARGB headers (addressable) | +\*---------------------------------------------------------*/ union PktRGB { - unsigned char buffer[64]; + unsigned char buffer[FUSION2_USB_BUFFER_SIZE]; struct RGBData { uint8_t report_id; uint8_t header; - uint16_t boffset; // In bytes, absolute + uint16_t boffset; uint8_t bcount; LEDs leds[19]; uint16_t padding0; @@ -117,6 +183,22 @@ union PktRGB void Init(uint8_t header, uint8_t report_id) { + switch(header) + { + case LED4: + case HDR_D_LED2: + header = HDR_D_LED2_RGB; + break; + case HDR_D_LED3: + header = HDR_D_LED3_RGB; + break; + case HDR_D_LED4: + header = HDR_D_LED4_RGB; + break; + default: + header = HDR_D_LED1_RGB; + break; + } s.report_id = report_id; s.header = header; s.boffset = 0; @@ -125,29 +207,40 @@ union PktRGB } }; +/*---------------------------------------------------------*\ +| Packet structure for hardware effects | +| Default values for Hardware Effects mode. | +| Old init values. | +| (All values 0 unless otherwise noted below) | +| e.color0 = 0x00FF2100; //orange | +| e.period1 = 1200; | +| e.period2 = 200; | +| e.period3 = 200; | +| e.effect_param2 = 1; | +\*---------------------------------------------------------*/ union PktEffect { - unsigned char buffer[64]; + unsigned char buffer[FUSION2_USB_BUFFER_SIZE]; struct Effect { - uint8_t report_id; - uint8_t header; - uint32_t zone0; // RGB Fusion seems to set it to pow(2, header - 0x20) - uint32_t zone1; - uint8_t reserved0; - uint8_t effect_type; - uint8_t max_brightness; - uint8_t min_brightness; - uint32_t color0; - uint32_t color1; - uint16_t period0; // Fade in - uint16_t period1; // Fade out - uint16_t period2; // Hold - uint16_t period3; - uint8_t effect_param0; - uint8_t effect_param1; - uint8_t effect_param2; - uint8_t effect_param3; + uint8_t report_id = 0; + uint8_t header = 0; + uint32_t zone0 = 0; // RGB Fusion sets it to pow(2, led) + uint32_t zone1 = 0; + uint8_t reserved0 = 0; + uint8_t effect_type = EFFECT_STATIC; + uint8_t max_brightness = 255; + uint8_t min_brightness = 0; + uint32_t color0 = 0; + uint32_t color1 = 0; + uint16_t period0 = 0; // Fade in - Rising Timer - Needs to be 0 for "Direct" + uint16_t period1 = 0; // Fade out + uint16_t period2 = 0; // Hold + uint16_t period3 = 0; + uint8_t effect_param0 = 0; // ex color count to cycle through (max seems to be 7) + uint8_t effect_param1 = 0; + uint8_t effect_param2 = 0; // ex flash repeat count + uint8_t effect_param3 = 0; uint8_t padding0[30]; } e; @@ -155,52 +248,88 @@ union PktEffect { } - void Init(int header, uint8_t report_id) + void Init(int led, uint8_t report_id, uint16_t pid) { - memset(buffer, 0, sizeof(buffer)); + memset(e.padding0, 0, sizeof(e.padding0)); e.report_id = report_id; - - if(header < 8) + if(led == -1) { - e.header = 32 + header; // Set as default + e.zone0 = (pid == 0x5711) ? 0x07FF : 0xFF; + e.header = 0x20; + } + else if(led < 8) + { + e.zone0 = 1U << led; + e.header = 0x20 + led; + } + else if(led < 11) + { + e.zone0 = 1U << led; + e.header = 0x90 + (led - 8); } else { - e.header = header; + e.zone0 = 0; + e.header = 0; } - - e.zone0 = (uint32_t)(1 << (e.header - 32)); - e.effect_type = EFFECT_STATIC; - e.max_brightness = 100; - e.min_brightness = 0; - e.color0 = 0x00FF2100; //orange - e.period0 = 0; //Rising Timer - Needs to be 0 for "Direct" - e.period1 = 1200; - e.period2 = 200; - e.period3 = 200; - e.effect_param0 = 0; // ex color count to cycle through (max seems to be 7) - e.effect_param1 = 0; - e.effect_param2 = 1; // ex flash repeat count - e.effect_param3 = 0; } }; +/*---------------------------------------------------------*\ +| Basic Controller Init Struct | +\*---------------------------------------------------------*/ struct IT8297Report { - uint8_t report_id; - uint8_t product; - uint8_t device_num; - uint8_t total_leds; + uint8_t report_id; + uint8_t product; + uint8_t device_num; + uint8_t strip_detect; uint32_t fw_ver; - uint16_t curr_led_count; - uint16_t reserved0; - char str_product[32]; // might be 28 and an extra byteorder3 - uint32_t byteorder0; // is little-endian 0x00RRGGBB ? - uint32_t byteorder1; - uint32_t byteorder2; + uint8_t curr_led_count_high; + uint8_t curr_led_count_low; + uint8_t strip_ctrl_length1; + uint8_t support_cmd_flag; + char str_product[28]; + uint32_t cal_spare0; + uint32_t cal_strip0; + uint32_t cal_strip1; + uint32_t rgb_cali; uint32_t chip_id; - uint32_t reserved1; + uint32_t cal_spare1; +}; + +/*---------------------------------------------------------*\ +| CC61 Calibration Struct (For IT5711) | +\*---------------------------------------------------------*/ +struct IT5711Calibration +{ + uint8_t report_id; + uint8_t reserved[3]; + uint32_t cal_strip2; + uint32_t cal_strip3; + uint32_t cal_spare2; + uint32_t cal_spare3; + uint8_t padding[44]; +}; + +/*---------------------------------------------------------*\ +| CC33 Set Calibration Struct | +\*---------------------------------------------------------*/ +struct CMD_0x33 +{ + uint8_t report_id; + uint8_t command_id; + uint32_t d_strip_c0; + uint32_t d_strip_c1; + uint32_t rgb_cali; + uint32_t c_spare0; + uint32_t c_spare1; + uint32_t d_strip_c2; + uint32_t d_strip_c3; + uint32_t c_spare2; + uint32_t c_spare3; + uint8_t reserved[25]; }; #pragma pack(pop) @@ -208,39 +337,44 @@ struct IT8297Report class RGBFusion2USBController { public: - RGBFusion2USBController(hid_device* handle, const char *path, std::string mb_name); + RGBFusion2USBController(hid_device* handle, const char *path, std::string mb_name, uint16_t pid); ~RGBFusion2USBController(); - void SetStripColors - ( - unsigned int hdr, - RGBColor * colors, - unsigned int num_colors, - int single_led = -1 - ); - - void SetLEDEffect(unsigned int led, int mode, unsigned int speed, unsigned char brightness, bool random, unsigned char red, unsigned char green, unsigned char blue); - void SetLedCount(unsigned int led, unsigned int count); - void SetMode(int mode); - bool ApplyEffect(); - bool DisableBuiltinEffect(int enable_bit, int mask); - void SetCalibration(); - std::string GetDeviceName(); - std::string GetDeviceDescription(); - std::string GetDeviceLocation(); - std::string GetFWVersion(); - std::string GetSerial(); + bool RefreshHardwareInfo(); + void ResetController(); + uint16_t GetProductID(); + uint8_t GetDeviceNum(); + void SetStripColors(unsigned int hdr, RGBColor * colors, unsigned int num_colors, int single_led = -1); + void SetLEDEffect(int led, int mode, unsigned int speed, unsigned char brightness, bool random, uint32_t* color); + void SetLedCount(unsigned int c0, unsigned int c1, unsigned int c2, unsigned int c3); + void SetMode(int mode); + bool ApplyEffect(bool batch_commit = false); + bool SetStripBuiltinEffectState(int hdr, bool enable); + EncodedCalibration GetCalibration(bool refresh_from_hw = false); + bool SetCalibration(const EncodedCalibration& cal, bool refresh_from_hw); + std::string GetDeviceName(); + std::string GetDeviceDescription(); + std::string GetDeviceLocation(); + std::string GetFWVersion(); + std::string GetSerial(); private: - bool EnableBeat(bool enable); - bool SendPacket(uint8_t a, uint8_t b, uint8_t c = 0); - int SendPacket(unsigned char* packet); - RGBA GetCalibration( std::string rgb_order); - void SetCalibrationBuffer(std::string rgb_order, uint8_t* buffer, uint8_t offset); - + bool SaveLEDState(bool enable); + bool SaveCalState(); + bool EnableLampArray(bool enable); + bool EnableBeat(bool enable); + bool SendPacket(uint8_t a, uint8_t b, uint8_t c = 0); + int SendPacket(unsigned char* packet); + uint32_t EncodeCalibrationBuffer(const std::string& rgb_order); + std::string DecodeCalibrationBuffer(uint32_t value) const; hid_device* dev; + int device_num; + uint16_t product_id; + uint32_t effect_zone_mask = 0; int mode; IT8297Report report; + IT5711Calibration cali; + CalibrationData cal_data; std::string name; std::string description; std::string location; @@ -248,6 +382,14 @@ private: std::string chip_id; int effect_disabled = 0; int report_id = 0xCC; + bool report_loaded = false; + bool cali_loaded = false; + LEDCount new_d1; + LEDCount new_d2; + LEDCount new_d3; + LEDCount new_d4; LEDCount D_LED1_count; LEDCount D_LED2_count; + LEDCount D_LED3_count; + LEDCount D_LED4_count; }; diff --git a/Controllers/GigabyteRGBFusion2USBController/GigabyteRGBFusion2USBControllerDetect.cpp b/Controllers/GigabyteRGBFusion2USBController/GigabyteRGBFusion2USBControllerDetect.cpp index 5eaba8a7..f0c3ecf3 100644 --- a/Controllers/GigabyteRGBFusion2USBController/GigabyteRGBFusion2USBControllerDetect.cpp +++ b/Controllers/GigabyteRGBFusion2USBController/GigabyteRGBFusion2USBControllerDetect.cpp @@ -1,7 +1,21 @@ +/*---------------------------------------------------------*\ +| GigabyteRGBFusion2USBControllerDetect.cpp | +| | +| Detector for Gigabyte Aorus RGB Fusion 2 USB | +| motherboard | +| | +| jackun 08 Jan 2020 | +| megadjc 31 Jul 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "GigabyteRGBFusion2USBController.h" #include "RGBController_GigabyteRGBFusion2USB.h" -#include "dependencies/dmiinfo.h" +#include "dmiinfo.h" + #define DETECTOR_NAME "Gigabyte RGB Fusion 2 USB" #define IT8297_VID 0x048D @@ -9,14 +23,9 @@ #define IT8297_U 0xCC #define IT8297_UPG 0xFF89 -/******************************************************************************************\ -* * -* DetectGigabyteRGBFusion2USBControllers * -* * -* Detect GigabyteRGB Fusion 2 devices that use IT8297 RGB controller * -* * -\******************************************************************************************/ - +/*---------------------------------------------------------*\ +| Detector for Gigabyte RGB Fusion USB controllers | +\*---------------------------------------------------------*/ void DetectGigabyteRGBFusion2USBControllers(hid_device_info* info, const std::string&) { DMIInfo MB_info; @@ -24,18 +33,22 @@ void DetectGigabyteRGBFusion2USBControllers(hid_device_info* info, const std::st if(dev) { - RGBFusion2USBController* controller = new RGBFusion2USBController(dev, info->path, MB_info.getMainboard()); + RGBFusion2USBController* controller = new RGBFusion2USBController(dev, info->path, MB_info.getMainboard(), info->product_id); RGBController_RGBFusion2USB* rgb_controller = new RGBController_RGBFusion2USB(controller, DETECTOR_NAME); // Constructor sets the name ResourceManager::get()->RegisterRGBController(rgb_controller); } -} /* DetectRGBFusion2USBControllers() */ +} #ifdef USE_HID_USAGE REGISTER_HID_DETECTOR_PU(DETECTOR_NAME, DetectGigabyteRGBFusion2USBControllers, IT8297_VID, 0x8297, IT8297_UPG, IT8297_U); +REGISTER_HID_DETECTOR_PU(DETECTOR_NAME, DetectGigabyteRGBFusion2USBControllers, IT8297_VID, 0x8950, IT8297_UPG, IT8297_U); REGISTER_HID_DETECTOR_PU(DETECTOR_NAME, DetectGigabyteRGBFusion2USBControllers, IT8297_VID, 0x5702, IT8297_UPG, IT8297_U); +REGISTER_HID_DETECTOR_PU(DETECTOR_NAME, DetectGigabyteRGBFusion2USBControllers, IT8297_VID, 0x5711, IT8297_UPG, IT8297_U); #else REGISTER_HID_DETECTOR_I(DETECTOR_NAME, DetectGigabyteRGBFusion2USBControllers, IT8297_VID, 0x8297, IT8297_IFC); +REGISTER_HID_DETECTOR_I(DETECTOR_NAME, DetectGigabyteRGBFusion2USBControllers, IT8297_VID, 0x8950, IT8297_IFC); REGISTER_HID_DETECTOR_I(DETECTOR_NAME, DetectGigabyteRGBFusion2USBControllers, IT8297_VID, 0x5702, IT8297_IFC); +REGISTER_HID_DETECTOR_I(DETECTOR_NAME, DetectGigabyteRGBFusion2USBControllers, IT8297_VID, 0x5711, IT8297_IFC); #endif diff --git a/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USB.cpp b/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USB.cpp index 7a366dcc..d4577a52 100644 --- a/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USB.cpp +++ b/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USB.cpp @@ -1,245 +1,21 @@ -/*-----------------------------------------*\ -| RGBController_GigabyteRGBFusion2USB.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Gigabyte RGB Fusion 2.0 USB Driver | -| | -| Author: jackun 1/8/2020 | -| Maintainer: Chris M (Dr_No) | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GigabyteRGBFusion2USB.cpp | +| | +| RGBController for Gigabyte Aorus RGB Fusion 2 USB | +| motherboard | +| | +| jackun 08 Jan 2020 | +| megadjc 31 Jul 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_GigabyteRGBFusion2USB.h" +#include "RGBController_GigabyteRGBFusion2USBBoards.h" +#include "RGBController_GigabyteRGBFusion2USBLayouts.h" #include "ResourceManager.h" #include "SettingsManager.h" -#include -#include - -/*-------------------------------------------------*\ -| LedHeaders is a map of the led header addresses | -\*-------------------------------------------------*/ -static FwdLedHeaders LedLookup -{ - {"LED1", 0x20}, {"LED2", 0x21}, {"LED3", 0x22}, {"LED4", 0x23}, - {"LED5", 0x24}, {"LED6", 0x25}, {"LED7", 0x26}, {"LED8", 0x27}, - {"D_LED1", 0x58}, {"D_LED2", 0x59}, -}; - -/*-------------------------------------------------*\ -| This is the default knownLayouts structure and | -| will be written into config if it doesn't exist | -\*-------------------------------------------------*/ -static MBName MBName2LayoutLookup -{ - {"B550 AORUS ELITE", "STD_ATX" }, - {"B550 AORUS PRO", "STD_ATX" }, - {"B550I AORUS PRO AX", "ITX" }, - {"X570 AORUS ELITE", "STD_ATX" }, - {"X570 AORUS MASTER", "MSTR_ATX_3"}, - {"X570 AORUS ELITE WIFI", "STD_ATX" }, - {"X570 AORUS PRO WIFI", "STD_ATX" }, - {"X570 AORUS ULTRA", "STD_ATX" }, - {"X570 I AORUS PRO WIFI", "ITX" }, - {"X670E AORUS MASTER", "MSTR_ATX_2"}, - {"Z390 AORUS MASTER-CF", "MSTR_ATX" }, -}; - -/*-------------------------------------------------*\ -| This is the default Custom layout that will be | -| written into config if it doesn't exist | -\*-------------------------------------------------*/ -static const KnownLayout HardcodedCustom -{ - { - "Custom", - { - { - "Motherboard", - { - { "Name for Led 1", LED1, 1 }, - { "Name for Led 2", LED2, 1 }, - { "Name for Led 3", LED3, 1 }, - { "Name for Led 4", LED4, 1 }, - { "Name for Led 5", LED5, 1 }, - { "Name for Led 8", LED8, 1 }, - } - }, - { - "D_LED1 Bottom", - { - { "Name for LED Strip 1", HDR_D_LED1, 0 }, - } - }, - { - "D_LED2 Top", - { - { "Name for LED Strip 2", HDR_D_LED2, 0 }, - } - } - } - } -}; - -/*-------------------------------------------------*\ -| KnownLayoutsLookup now needs to be variable to | -| allow for a custom addition from config | -\*-------------------------------------------------*/ -static KnownLayout knownLayoutsLookup -{ - { - "IT8297BX-GBX570", //Left as a catch all - { - { - "Motherboard", - { - { "Name for Led 1", LED1, 1 }, - { "Name for Led 2", LED2, 1 }, - { "Name for Led 3", LED3, 1 }, - { "Name for Led 4", LED4, 1 }, - { "Name for Led 5", LED5, 1 }, - { "Name for Led 6", LED6, 1 }, - { "Name for Led 7", LED7, 1 }, - { "Name for Led 8", LED8, 1 }, - } - }, - { - "D_LED1 Bottom", - { - { "Name for LED Strip 1", HDR_D_LED1, 0 }, - } - }, - { - "D_LED2 Top", - { - { "Name for LED Strip 2", HDR_D_LED2, 0 }, - } - } - } - }, - { - "STD_ATX", - { - { - "Motherboard", - { - { "Back I/O", HDR_BACK_IO, 1 }, - { "CPU Header", HDR_CPU, 1 }, - { "PCIe", HDR_PCIE, 1}, - { "LED C1/C2", HDR_LED_C1C2, 1 }, // 12VGRB headers seem to be connected - } - }, - { - "D_LED1 Bottom", - { - { "D_LED1 Bottom", HDR_D_LED1, 0 }, - } - }, - { - "D_LED2 Top", - { - { "D_LED2 Top", HDR_D_LED2, 0 }, - } - } - } - }, - { - "ITX", - { - { - "Motherboard", - { - { "LED Group0", HDR_BACK_IO, 1 }, - { "LED Group1", HDR_CPU, 1 }, - { "LED Group2", HDR_LED_2, 1 }, - { "LED Group3", HDR_PCIE, 1 }, - { "LED C1/C2", HDR_LED_C1C2, 1 }, // 12VGRB headers seem to be connected - } - }, - { - "D_LED1", - { - { "D_LED1", HDR_D_LED1, 0 }, - } - } - } - }, - { - "MSTR_ATX", - { - { - "Digital Headers", - { - { "D_LED1 / D_LED2", LED6, 0}, - } - }, - { - "ARGB Strip", - { - { "Back IO / VRM", LED7, 0}, - } - }, - { - "Motherboard", - { - { "XMP Logo", LED2, 1}, - { "Chipset Logo", LED3, 1}, - { "PCIe", LED4, 1}, - { "LED C1/C2", LED5, 1}, - } - } - } - }, - { - "MSTR_ATX_2", - { - { - "D_LED1 Bottom", - { - { "D_LED1 Bottom", HDR_D_LED2, 0}, - } - }, - { - "D_LED2 Top", - { - { "D_LED2 Top", HDR_D_LED1, 0}, - } - }, - { - "Motherboard", - { - { "LED C1", LED2, 1}, - { "LED C2", LED5, 1}, - { "CPU Header", LED3, 1}, - { "Cover Left", LED4, 1}, - { "Cover Right", LED1, 1}, - } - } - } - }, - { - "MSTR_ATX_3", - { - { - "Digital Headers", - { - { "D_LED1 / D_LED2", HDR_D_LED1, 0}, - } - }, - { - "ARGB Strip", - { - { "LED C1/C2", LED5, 1}, - } - }, - { - "Motherboard", - { - { "Aorus Logo", LED7, 1}, - { "ESS Logo", LED4, 1}, - } - } - } - }, -}; /**------------------------------------------------------------------*\ @name Gigabyte RGB Fusion 2 USB @@ -253,27 +29,160 @@ static KnownLayout knownLayoutsLookup Intel mainboards from the x570 and z390 chipsets onwards. \*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| Convert calibration data to JSON | +\*---------------------------------------------------------*/ +static nlohmann::json WriteCalJsonFrom(const EncodedCalibration& src, uint16_t pid) +{ + nlohmann::json calib_json; + calib_json["HDR_D_LED1"] = src.dled[0]; + calib_json["HDR_D_LED2"] = src.dled[1]; + + if(pid == 0x5711) + { + calib_json["HDR_D_LED3"] = src.dled[2]; + calib_json["HDR_D_LED4"] = src.dled[3]; + } + calib_json["Mainboard"] = src.mainboard; + calib_json["Spare0"] = src.spare[0]; + calib_json["Spare1"] = src.spare[1]; + + if(pid == 0x5711) + { + calib_json["Spare2"] = src.spare[2]; + calib_json["Spare3"] = src.spare[3]; + } + return calib_json; +} + +/*---------------------------------------------------------*\ +| Fill missing JSON calibration keys | +\*---------------------------------------------------------*/ +static void FillMissingWith(nlohmann::json& dst, const EncodedCalibration& fb, uint16_t pid) +{ + struct SetIfMissing + { + nlohmann::json& dst; + + void operator()(const char* key, const std::string& val) const + { + if(!dst.contains(key)) + { + dst[key] = val; + } + } + }; + + SetIfMissing set_if_missing{dst}; + + set_if_missing("HDR_D_LED1", fb.dled[0]); + set_if_missing("HDR_D_LED2", fb.dled[1]); + if(pid==0x5711) + { + set_if_missing("HDR_D_LED3", fb.dled[2]); + set_if_missing("HDR_D_LED4", fb.dled[3]); + } + set_if_missing("Mainboard", fb.mainboard); + set_if_missing("Spare0", fb.spare[0]); + set_if_missing("Spare1", fb.spare[1]); + if(pid==0x5711) + { + set_if_missing("Spare2", fb.spare[2]); + set_if_missing("Spare3", fb.spare[3]); + } +} + +/*---------------------------------------------------------*\ +| JSON safe string fetch (calibration) | +\*---------------------------------------------------------*/ +static std::string GetOrOff(const nlohmann::json& obj, const char* key) +{ + return obj.contains(key) ? obj.at(key).get() : std::string("OFF"); +} + +/*---------------------------------------------------------*\ +| Build custom layout in JSON | +\*---------------------------------------------------------*/ +static nlohmann::json BuildCustomLayoutJson(const ZoneLeds& src_layout, const RvrseLedHeaders& reverseLookup) +{ + nlohmann::json json_HCL; + for(ZoneLeds::const_iterator zl = src_layout.begin(); zl != src_layout.end(); ++zl) + { + const std::string& zone_name = zl->first; + const std::vector& v_lp = zl->second; + + nlohmann::json json_zl; + for(std::vector::const_iterator it = v_lp.begin(); it != v_lp.end(); ++it) + { + const LedPort& lp = *it; + nlohmann::json json_lp; + json_lp["name"] = lp.name; + json_lp["header"] = reverseLookup.at(lp.header); + json_lp["count"] = lp.count; + json_zl.push_back(json_lp); + } + json_HCL.emplace(zone_name, json_zl); + } + return json_HCL; +} + +/*---------------------------------------------------------*\ +| Build custom layout from JSON | +\*---------------------------------------------------------*/ +static void LoadCustomLayoutFromJson(const nlohmann::json& json_HCL, const FwdLedHeaders& forwardLookup, ZoneLeds& out_layout) +{ + out_layout.clear(); + + for(nlohmann::json::const_iterator json_layout_it = json_HCL.begin(); + json_layout_it != json_HCL.end(); + ++json_layout_it) + { + const std::string& zone_name = json_layout_it.key(); + const nlohmann::json& json_zl = json_layout_it.value(); + + std::vector v_lp; + + for(nlohmann::json::const_iterator zl_it = json_zl.begin(); + zl_it != json_zl.end(); + ++zl_it) + { + const nlohmann::json& zl = *zl_it; + nlohmann::json jv = zl; + LedPort lp; + + lp.name = jv["name"].get(); + lp.header = forwardLookup.at(jv["header"].get()); + lp.count = jv.contains("count") ? jv["count"].get() : 1; + + v_lp.push_back(lp); + } + + out_layout.insert(std::pair>(zone_name, v_lp)); + } +} + RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController* controller_ptr, std::string detector) { - controller = controller_ptr; - - name = controller->GetDeviceName(); - detector_name = detector; - vendor = "Gigabyte"; - type = DEVICE_TYPE_MOTHERBOARD; - description = controller->GetDeviceDescription(); - version = controller->GetFWVersion(); - location = controller->GetDeviceLocation(); - serial = controller->GetSerial(); + controller = controller_ptr; + name = controller->GetDeviceName(); + detector_name = detector; + vendor = "Gigabyte"; + type = DEVICE_TYPE_MOTHERBOARD; + description = controller->GetDeviceDescription(); + version = controller->GetFWVersion(); + location = controller->GetDeviceLocation(); + serial = controller->GetSerial(); + pid = controller->GetProductID(); + device_num = controller->GetDeviceNum(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0xFFFF; - Direct.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR; - Direct.brightness_min = RGBFUSION2_BRIGHTNESS_MIN; - Direct.brightness_max = RGBFUSION2_BRIGHTNESS_MAX; - Direct.brightness = RGBFUSION2_BRIGHTNESS_MAX; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR; + Direct.brightness_min = RGBFUSION2_BRIGHTNESS_MIN; + Direct.brightness_max = RGBFUSION2_BRIGHTNESS_MAX; + Direct.brightness = RGBFUSION2_BRIGHTNESS_MAX; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); mode Static; @@ -294,31 +203,31 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController Breathing.value = EFFECT_PULSE; Breathing.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; Breathing.brightness_min = RGBFUSION2_BRIGHTNESS_MIN; - Breathing.brightness_max = RGBFUSION2_BRIGHTNESS_MAX; - Breathing.brightness = RGBFUSION2_BRIGHTNESS_MAX; - Breathing.speed_min = 0; - Breathing.speed_max = 4; + Breathing.brightness_max = 100; // Set 100 max due to controller quirks + Breathing.brightness = Breathing.brightness_max; + Breathing.speed_min = RGBFUSION2_SPEED_MIN; + Breathing.speed_max = RGBFUSION2_SPEED_MAX; + Breathing.speed = RGBFUSION2_SPEED_MID; Breathing.colors_min = 1; Breathing.colors_max = 1; Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; Breathing.colors.resize(1); - Breathing.speed = 2; modes.push_back(Breathing); mode Blinking; - Blinking.name = "Blinking"; + Blinking.name = "Flashing"; Blinking.value = EFFECT_BLINKING; Blinking.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; Blinking.brightness_min = RGBFUSION2_BRIGHTNESS_MIN; Blinking.brightness_max = RGBFUSION2_BRIGHTNESS_MAX; Blinking.brightness = RGBFUSION2_BRIGHTNESS_MAX; - Blinking.speed_min = 0; - Blinking.speed_max = 4; + Blinking.speed_min = RGBFUSION2_SPEED_MIN; + Blinking.speed_max = RGBFUSION2_SPEED_MAX; + Blinking.speed = RGBFUSION2_SPEED_MID; Blinking.colors_min = 1; Blinking.colors_max = 1; Blinking.color_mode = MODE_COLORS_MODE_SPECIFIC; Blinking.colors.resize(1); - Blinking.speed = 2; modes.push_back(Blinking); mode ColorCycle; @@ -328,28 +237,103 @@ RGBController_RGBFusion2USB::RGBController_RGBFusion2USB(RGBFusion2USBController ColorCycle.brightness_min = RGBFUSION2_BRIGHTNESS_MIN; ColorCycle.brightness_max = RGBFUSION2_BRIGHTNESS_MAX; ColorCycle.brightness = RGBFUSION2_BRIGHTNESS_MAX; - ColorCycle.speed_min = 0; - ColorCycle.speed_max = 4; + ColorCycle.speed_min = RGBFUSION2_SPEED_MIN; + ColorCycle.speed_max = RGBFUSION2_SPEED_MAX; + ColorCycle.speed = RGBFUSION2_SPEED_MID; ColorCycle.color_mode = MODE_COLORS_NONE; - ColorCycle.speed = 2; modes.push_back(ColorCycle); mode Flashing; - Flashing.name = "Flashing"; - Flashing.value = 10; + Flashing.name = "Double Flash"; + Flashing.value = EFFECT_DFLASH; Flashing.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; Flashing.brightness_min = RGBFUSION2_BRIGHTNESS_MIN; Flashing.brightness_max = RGBFUSION2_BRIGHTNESS_MAX; Flashing.brightness = RGBFUSION2_BRIGHTNESS_MAX; - Flashing.speed_min = 0; - Flashing.speed_max = 4; + Flashing.speed_min = RGBFUSION2_SPEED_MIN; + Flashing.speed_max = RGBFUSION2_SPEED_MAX; + Flashing.speed = RGBFUSION2_SPEED_MID; Flashing.colors_min = 1; Flashing.colors_max = 1; Flashing.color_mode = MODE_COLORS_MODE_SPECIFIC; Flashing.colors.resize(1); - Flashing.speed = 2; modes.push_back(Flashing); + mode Wave; + Wave.name = "Wave"; + Wave.value = EFFECT_WAVE; + Wave.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Wave.brightness_min = RGBFUSION2_BRIGHTNESS_MIN; + Wave.brightness_max = RGBFUSION2_BRIGHTNESS_MAX; + Wave.brightness = RGBFUSION2_BRIGHTNESS_MAX; + Wave.speed_min = RGBFUSION2_SPEED_MIN; + Wave.speed_max = RGBFUSION2_SPEED_MAX; + Wave.speed = RGBFUSION2_SPEED_MID; + Wave.colors_min = 0; + Wave.colors_max = 0; + Wave.color_mode = MODE_COLORS_NONE; + modes.push_back(Wave); + + mode Random; + Random.name = "Random"; + Random.value = EFFECT_RANDOM; + Random.flags = MODE_FLAG_HAS_BRIGHTNESS; + Random.brightness_min = RGBFUSION2_BRIGHTNESS_MIN; + Random.brightness_max = RGBFUSION2_BRIGHTNESS_MAX; + Random.brightness = RGBFUSION2_BRIGHTNESS_MAX; + Random.colors_min = 0; + Random.colors_max = 0; + Random.color_mode = MODE_COLORS_NONE; + modes.push_back(Random); + + mode Wave1; + Wave1.name = "Wave 1"; + Wave1.value = EFFECT_WAVE1; + Wave1.flags = MODE_FLAG_HAS_BRIGHTNESS; + Wave1.brightness_min = RGBFUSION2_BRIGHTNESS_MIN; + Wave1.brightness_max = RGBFUSION2_BRIGHTNESS_MAX; + Wave1.brightness = RGBFUSION2_BRIGHTNESS_MAX; + Wave1.colors_min = 0; + Wave1.colors_max = 0; + Wave1.color_mode = MODE_COLORS_NONE; + modes.push_back(Wave1); + + mode Wave2; + Wave2.name = "Wave 2"; + Wave2.value = EFFECT_WAVE2; + Wave2.flags = MODE_FLAG_HAS_BRIGHTNESS; + Wave2.brightness_min = RGBFUSION2_BRIGHTNESS_MIN; + Wave2.brightness_max = RGBFUSION2_BRIGHTNESS_MAX; + Wave2.brightness = RGBFUSION2_BRIGHTNESS_MAX; + Wave2.colors_min = 0; + Wave2.colors_max = 0; + Wave2.color_mode = MODE_COLORS_NONE; + modes.push_back(Wave2); + + mode Wave3; + Wave3.name = "Wave 3"; + Wave3.value = EFFECT_WAVE3; + Wave3.flags = MODE_FLAG_HAS_BRIGHTNESS; + Wave3.brightness_min = RGBFUSION2_BRIGHTNESS_MIN; + Wave3.brightness_max = RGBFUSION2_BRIGHTNESS_MAX; + Wave3.brightness = RGBFUSION2_BRIGHTNESS_MAX; + Wave3.colors_min = 0; + Wave3.colors_max = 0; + Wave3.color_mode = MODE_COLORS_NONE; + modes.push_back(Wave3); + + mode Wave4; + Wave4.name = "Wave 4"; + Wave4.value = EFFECT_WAVE4; + Wave4.flags = MODE_FLAG_HAS_BRIGHTNESS; + Wave4.brightness_min = RGBFUSION2_BRIGHTNESS_MIN; + Wave4.brightness_max = RGBFUSION2_BRIGHTNESS_MAX; + Wave4.brightness = RGBFUSION2_BRIGHTNESS_MAX; + Wave4.colors_min = 0; + Wave4.colors_max = 0; + Wave4.color_mode = MODE_COLORS_NONE; + modes.push_back(Wave4); + Load_Device_Config(); Init_Controller(); SetupZones(); @@ -360,126 +344,186 @@ RGBController_RGBFusion2USB::~RGBController_RGBFusion2USB() delete controller; } +/*---------------------------------------------------------*\ +| Loads JSON config data | +\*---------------------------------------------------------*/ void RGBController_RGBFusion2USB::Load_Device_Config() { - const std::string SectionLayout = "MotherboardLayouts"; - const std::string SectionCustom = "CustomLayout"; - SettingsManager* settings_manager = ResourceManager::get()->GetSettingsManager(); - json device_settings = settings_manager->GetSettings(detector_name); - RvrseLedHeaders ReverseLedLookup = reverse_map(LedLookup); + const std::string SectionCustom = "CustomLayout"; + const std::string SectionCalibration = "Calibration"; + RvrseLedHeaders ReverseLedLookup = reverse_map(LedLookup); + SettingsManager* settings_manager = ResourceManager::get()->GetSettingsManager(); + nlohmann::json device_settings = settings_manager->GetSettings(detector_name); - /*-------------------------------------------------*\ - | Get Layouts from the settings manager | - | If MotherboardLayouts is not found then write it | - | to settings | - \*-------------------------------------------------*/ - if(!device_settings.contains(SectionLayout)) + if(pid == 0x5711) { - device_settings[SectionLayout] = MBName2LayoutLookup; - settings_manager->SetSettings(detector_name, device_settings); - settings_manager->SaveSettings(); - MBName2Layout = MBName2LayoutLookup; + layout = HardcodedCustom_Gen2.find("Custom")->second; } else { - for(const nlohmann::detail::iteration_proxy_value>& it : device_settings[SectionLayout].items()) - { - MBName2Layout.insert( std::pair(it.key(), it.value() )); - } + layout = HardcodedCustom_Gen1.find("Custom")->second; } - /*-------------------------------------------------*\ - | Get Custom Layout from the settings manager | - \*-------------------------------------------------*/ - layout = HardcodedCustom.find("Custom")->second; - if (!device_settings.contains(SectionCustom)) + /*---------------------------------------------------------*\ + | Remove legacy top-level "MotherboardLayouts" | + \*---------------------------------------------------------*/ + if(device_settings.contains("MotherboardLayouts")) { - /*---------------------------------------------*\ - | If the Custom layout is not found then write | - | it to settings | - \*---------------------------------------------*/ - json json_HCL; - - for(ZoneLeds::iterator zl = layout.begin(); zl != layout.end(); zl++) - { - std::vector v_lp = zl->second; - json json_zl; - - for(std::vector::iterator lp_it = v_lp.begin(); lp_it != v_lp.end(); lp_it++) - { - json json_lp; - json_lp["name"] = lp_it[0].name; - json_lp["header"] = ReverseLedLookup.find(lp_it[0].header)->second; - json_zl.push_back(json_lp); - } - json_HCL.emplace(zl->first, json_zl); - } + device_settings.erase("MotherboardLayouts"); + settings_manager->SetSettings(detector_name, device_settings); + settings_manager->SaveSettings(); + } + if(!device_settings.contains(SectionCustom)) + { + nlohmann::json json_HCL = BuildCustomLayoutJson(layout, ReverseLedLookup); device_settings[SectionCustom]["Enabled"] = false; - device_settings[SectionCustom]["Data"] = json_HCL; + device_settings[SectionCustom]["Data"] = BuildCustomLayoutJson(layout, ReverseLedLookup); + settings_manager->SetSettings(detector_name, device_settings); + settings_manager->SaveSettings(); + } + + custom_layout = device_settings[SectionCustom]["Enabled"]; + + if(custom_layout) + { + const nlohmann::json json_HCL = device_settings[SectionCustom]["Data"]; + LoadCustomLayoutFromJson(json_HCL, LedLookup, layout); + } + + EncodedCalibration hw_cal = controller->GetCalibration(false); + + if(!device_settings.contains(SectionCalibration)) + { + device_settings[SectionCalibration]["Enabled"] = false; + device_settings[SectionCalibration]["Data"] = WriteCalJsonFrom(hw_cal, pid); settings_manager->SetSettings(detector_name, device_settings); settings_manager->SaveSettings(); } else { - custom_layout = device_settings[SectionCustom]["Enabled"]; + nlohmann::json& cal_sec = device_settings[SectionCalibration]; + bool cal_enable = cal_sec.value("Enabled", false); - /*---------------------------------------------*\ - | If the Custom layout is found and enabled | - | then read it in from config | - \*---------------------------------------------*/ - if(custom_layout) + if(!cal_sec.contains("Data") || !cal_sec["Data"].is_object()) { - json json_HCL = device_settings[SectionCustom]["Data"]; - layout.clear(); + cal_sec["Data"] = WriteCalJsonFrom(hw_cal, pid); + settings_manager->SetSettings(detector_name, device_settings); + settings_manager->SaveSettings(); + } + else + { + nlohmann::json& cdata = cal_sec["Data"]; + FillMissingWith(cdata, hw_cal, pid); - for(const nlohmann::detail::iteration_proxy_value>& json_layout_it : json_HCL.items()) + if(!cal_enable) { - json json_zl = json_layout_it.value(); - std::vector v_lp; - - for(json& zl : json_zl) - { - json json_vlp = zl; - - LedPort lp; - - /*---------------------------------*\ - | Initialize the name, header, and | - | count values. Set the D_LED | - | headers LED count to 0 | - \*---------------------------------*/ - lp.name = json_vlp["name"].get(); - lp.header = LedLookup.find(json_vlp["header"].get())->second; - lp.count = ((lp.header == LED6) || (lp.header == LED7)) ? 0 : 1; - v_lp.push_back(lp); - } - - layout.insert(std::pair>(json_layout_it.key(),v_lp)); + cal_sec["Data"] = WriteCalJsonFrom(hw_cal, pid); + settings_manager->SetSettings(detector_name, device_settings); + settings_manager->SaveSettings(); } } + + if(cal_enable) + { + const nlohmann::json& cdata = cal_sec["Data"]; + + EncodedCalibration desired; + desired.dled[0] = GetOrOff(cdata, "HDR_D_LED1"); + desired.dled[1] = GetOrOff(cdata, "HDR_D_LED2"); + desired.mainboard = GetOrOff(cdata, "Mainboard"); + desired.spare[0] = GetOrOff(cdata, "Spare0"); + desired.spare[1] = GetOrOff(cdata, "Spare1"); + + if(pid == 0x5711) + { + desired.dled[2] = GetOrOff(cdata, "HDR_D_LED3"); + desired.dled[3] = GetOrOff(cdata, "HDR_D_LED4"); + desired.spare[2] = GetOrOff(cdata, "Spare2"); + desired.spare[3] = GetOrOff(cdata, "Spare3"); + } + else + { + desired.dled[2] = "OFF"; + desired.dled[3] = "OFF"; + desired.spare[2] = "OFF"; + desired.spare[3] = "OFF"; + } + controller->SetCalibration(desired, false); + } } } +/*---------------------------------------------------------*\ +| Loads layout and zone data for controller | +\*---------------------------------------------------------*/ void RGBController_RGBFusion2USB::Init_Controller() { /*---------------------------------------------------------*\ | Look up channel map based on device name | \*---------------------------------------------------------*/ - if (!custom_layout) + if(!custom_layout) { - /*-----------------------------------------------------*\ - | If the layout is custom then it's loaded and ready, | - | otherwise get known layouts | - | This check is a quick way to get a boolean on find() | - \*-----------------------------------------------------*/ - if(MBName2Layout.count(controller->GetDeviceName())) + std::string layout_key; + + bool found = false; + + switch(pid) { - layout = knownLayoutsLookup.find(MBName2Layout.find(controller->GetDeviceName())->second )->second; + case 0x5711: + if(MBName2LayoutLookup5711.count(name)) + { + layout_key = MBName2LayoutLookup5711.at(name); + found = true; + } + break; + + case 0x5702: + if(MBName2LayoutLookup5702.count(name)) + { + layout_key = MBName2LayoutLookup5702.at(name); + found = true; + } + break; + + case 0x8950: + if(MBName2LayoutLookup8950.count(name)) + { + layout_key = MBName2LayoutLookup8950.at(name); + found = true; + } + break; + + case 0x8297: + if(MBName2LayoutLookup8297.count(name)) + { + layout_key = MBName2LayoutLookup8297.at(name); + found = true; + } + break; + + default: + break; + } + + if(found) + { + layout = knownLayoutsLookup.at(layout_key); } else { - layout = knownLayoutsLookup.find("IT8297BX-GBX570")->second; + switch(pid) + { + case 0x8297: + case 0x8950: + case 0x5702: + layout = knownLayoutsLookup.at("STD_ATX"); + break; + + default: + layout = knownLayoutsLookup.at("IT5711-Generic"); + break; + } } } @@ -500,17 +544,14 @@ void RGBController_RGBFusion2USB::Init_Controller() for(std::size_t lp_idx = 0; lp_idx < lp.size(); lp_idx++) { - /*-------------------------------------------------*\ - | Get LED count and check if it is a single LED zone| - \*-------------------------------------------------*/ int lp_count = lp[lp_idx].count; single_zone = single_zone && (lp_count == 1); LED_count += lp_count; } zones[zone_idx].name = zl->first; - zones[zone_idx].leds_min = (single_zone) ? LED_count : RGBFusion2_Digital_LEDS_Min; - zones[zone_idx].leds_max = (single_zone) ? LED_count : RGBFusion2_Digital_LEDS_Max; + zones[zone_idx].leds_min = (single_zone) ? LED_count : RGBFUSION2_DIGITAL_LEDS_MIN; + zones[zone_idx].leds_max = (single_zone) ? LED_count : RGBFUSION2_DIGITAL_LEDS_MAX; zones[zone_idx].leds_count = (single_zone) ? LED_count : 0; zones[zone_idx].type = (single_zone) ? ZONE_TYPE_SINGLE : ZONE_TYPE_LINEAR; zones[zone_idx].matrix_map = NULL; @@ -520,31 +561,49 @@ void RGBController_RGBFusion2USB::Init_Controller() void RGBController_RGBFusion2USB::SetupZones() { - /*-------------------------------------------------*\ - | Clear any existing color/LED configuration | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Clear any existing color/LED configuration | + \*---------------------------------------------------------*/ leds.clear(); colors.clear(); + unsigned int d1 = 0, d2 = 0, d3 = 0, d4 = 0; + /*---------------------------------------------------------*\ - | Set up zones | + | Set up zones (Fixed so as to not spam the controller) | \*---------------------------------------------------------*/ int zone_idx = 0; - for(ZoneLeds::iterator zl = layout.begin(); zl != layout.end(); zl++) + for (ZoneLeds::iterator zl = layout.begin(); zl != layout.end(); zl++) { bool single_zone = (zones[zone_idx].type == ZONE_TYPE_SINGLE); - if(!single_zone) + if (!single_zone) { - controller->SetLedCount(zl->second.at(0).header, zones[zone_idx].leds_count); - controller->DisableBuiltinEffect(0, 0x3); + unsigned char hdr = zl->second.at(0).header; + + switch (hdr) + { + case LED4: + case HDR_D_LED2: + d2 = zones[zone_idx].leds_count; + break; + case HDR_D_LED3: + d3 = zones[zone_idx].leds_count; + break; + case HDR_D_LED4: + d4 = zones[zone_idx].leds_count; + break; + default: + d1 = zones[zone_idx].leds_count; + break; + } } - for(unsigned int lp_idx = 0; lp_idx < zones[zone_idx].leds_count; lp_idx++) + for (unsigned int lp_idx = 0; lp_idx < zones[zone_idx].leds_count; lp_idx++) { led new_led; - if(single_zone) + if (single_zone) { new_led.name = zl->second.at(lp_idx).name; new_led.value = zl->second.at(lp_idx).header; @@ -562,6 +621,8 @@ void RGBController_RGBFusion2USB::SetupZones() zone_idx++; } + controller->SetLedCount(d1, d2, d3, d4); + controller->SetStripBuiltinEffectState(-1, false); SetupColors(); } @@ -582,10 +643,93 @@ void RGBController_RGBFusion2USB::ResizeZone(int zone, int new_size) void RGBController_RGBFusion2USB::DeviceUpdateLEDs() { - for(size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + int mode_value = (modes[active_mode].value); + bool random = (modes[active_mode].color_mode == MODE_COLORS_RANDOM); + uint32_t* color = &null_color; + + /*---------------------------------------------------------*\ + | If Wave 1-4 then use special sequence. | + \*---------------------------------------------------------*/ + if(mode_value == 6 || (mode_value >= 9 && mode_value <= 12)) { - UpdateZoneLEDs(zone_idx); + controller->SetStripBuiltinEffectState(-1, true); + controller->SetLEDEffect(-1, 1, 0, 0xFF, 0, color); + controller->ApplyEffect(); + controller->SetLEDEffect( 2, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color); + controller->ApplyEffect(); + return; } + + for(int zone_idx = 0; zone_idx < (int)zones.size(); zone_idx++) + { + if(zones[zone_idx].type == ZONE_TYPE_SINGLE) + { + for(std::size_t led_idx = 0; led_idx < zones[zone_idx].leds_count; led_idx++) + { + /*---------------------------------------------------------*\ + | Motherboard LEDs always use effect mode, so use static for| + | direct mode but get colors from zone | + \*---------------------------------------------------------*/ + if(modes[active_mode].value == 0xFFFF) + { + color = &zones[zone_idx].colors[led_idx]; + mode_value = EFFECT_STATIC; + } + /*---------------------------------------------------------*\ + | If the mode uses mode-specific color, get color from mode | + \*---------------------------------------------------------*/ + else if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + color = &modes[active_mode].colors[0]; + } + + /*---------------------------------------------------------*\ + | Apply the mode and color to the zone | + \*---------------------------------------------------------*/ + controller->SetLEDEffect(zones[zone_idx].leds[led_idx].value, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color); + } + } + /*---------------------------------------------------------*\ + | Set strip LEDs | + \*---------------------------------------------------------*/ + else + { + if(zones[zone_idx].leds && zones[zone_idx].leds_count) + { + unsigned char hdr = zones[zone_idx].leds->value; + + /*---------------------------------------------------------*\ + | Direct mode addresses a different register | + \*---------------------------------------------------------*/ + if(modes[active_mode].value == 0xFFFF) + { + controller->SetStripBuiltinEffectState(hdr, false); + controller->SetStripColors(hdr, zones[zone_idx].colors, zones[zone_idx].leds_count); + } + + /*---------------------------------------------------------*\ + | Effect mode | + \*---------------------------------------------------------*/ + else + { + /*---------------------------------------------------------*\ + | If mode has mode specific color, load color from mode | + \*---------------------------------------------------------*/ + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + color = &modes[active_mode].colors[0]; + } + + /*---------------------------------------------------------*\ + | Apply hardware effects to LED strips | + \*---------------------------------------------------------*/ + controller->SetStripBuiltinEffectState(hdr, true); + controller->SetLEDEffect(hdr, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color); + } + } + } + } + controller->ApplyEffect(); } void RGBController_RGBFusion2USB::UpdateZoneLEDs(int zone) @@ -593,61 +737,62 @@ void RGBController_RGBFusion2USB::UpdateZoneLEDs(int zone) /*---------------------------------------------------------*\ | Get mode parameters | \*---------------------------------------------------------*/ - int mode_value = (modes[active_mode].value); - bool random = (modes[active_mode].color_mode == MODE_COLORS_RANDOM || mode_value == EFFECT_COLORCYCLE); + int mode_value = (modes[active_mode].value); + bool random = (modes[active_mode].color_mode == MODE_COLORS_RANDOM); + uint32_t* color = &null_color; + + /*---------------------------------------------------------*\ + | If Wave 1-4 then use special sequence. | + \*---------------------------------------------------------*/ + if(mode_value == 6 || (mode_value >= 9 && mode_value <= 12)) + { + controller->SetStripBuiltinEffectState(-1, true); + controller->SetLEDEffect(-1, 1, 0, 0xFF, 0, color); + controller->ApplyEffect(); + controller->SetLEDEffect( 2, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color); + controller->ApplyEffect(); + return; + } /*---------------------------------------------------------*\ | Set motherboard LEDs | \*---------------------------------------------------------*/ if(zones[zone].type == ZONE_TYPE_SINGLE) { - unsigned char red = 0; - unsigned char grn = 0; - unsigned char blu = 0; - for(std::size_t led_idx = 0; led_idx < zones[zone].leds_count; led_idx++) { - /*---------------------------------------------------------*\ - | Initialize mode value | - \*---------------------------------------------------------*/ - mode_value = modes[active_mode].value; - - /*---------------------------------------------------------*\ - | Motherboard LEDs always use effect mode, so use static for| - | direct mode but get colors from zone | - \*---------------------------------------------------------*/ + /*------------------------------------------------------------*\ + | Motherboard LEDs always use effect mode, so use static for | + | direct mode but get colors from zone | + \*------------------------------------------------------------*/ if(mode_value == 0xFFFF) { - red = RGBGetRValue(zones[zone].colors[led_idx]); - grn = RGBGetGValue(zones[zone].colors[led_idx]); - blu = RGBGetBValue(zones[zone].colors[led_idx]); - - mode_value = EFFECT_STATIC; + color = &zones[zone].colors[led_idx]; + mode_value = EFFECT_STATIC; } + /*---------------------------------------------------------*\ | If the mode uses mode-specific color, get color from mode | \*---------------------------------------------------------*/ else if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) { - red = RGBGetRValue(modes[active_mode].colors[0]); - grn = RGBGetGValue(modes[active_mode].colors[0]); - blu = RGBGetBValue(modes[active_mode].colors[0]); + color = &modes[active_mode].colors[0]; } /*---------------------------------------------------------*\ | Apply the mode and color to the zone | \*---------------------------------------------------------*/ - controller->SetLEDEffect(zones[zone].leds[led_idx].value, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, red, grn, blu); + controller->SetLEDEffect(zones[zone].leds[led_idx].value, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color); + controller->ApplyEffect(); } - - controller->ApplyEffect(); } + /*---------------------------------------------------------*\ | Set strip LEDs | \*---------------------------------------------------------*/ else { - if(zones[zone].leds_count) + if(zones[zone].leds && zones[zone].leds_count) { unsigned char hdr = zones[zone].leds->value; @@ -656,34 +801,28 @@ void RGBController_RGBFusion2USB::UpdateZoneLEDs(int zone) \*---------------------------------------------------------*/ if(mode_value == 0xFFFF) { - hdr += RGBFusion2_Digital_Direct_Offset; - controller->DisableBuiltinEffect(1, ((hdr == HDR_D_LED1_RGB) ? 0x01 : 0x02)); + controller->SetStripBuiltinEffectState(hdr, false); controller->SetStripColors(hdr, zones[zone].colors, zones[zone].leds_count); } + /*---------------------------------------------------------*\ | Effect mode | \*---------------------------------------------------------*/ else { - unsigned char red = 0; - unsigned char grn = 0; - unsigned char blu = 0; - /*---------------------------------------------------------*\ | If mode has mode specific color, load color from mode | \*---------------------------------------------------------*/ if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) { - red = RGBGetRValue(modes[active_mode].colors[0]); - grn = RGBGetGValue(modes[active_mode].colors[0]); - blu = RGBGetBValue(modes[active_mode].colors[0]); + color = &modes[active_mode].colors[0]; } /*---------------------------------------------------------*\ | Apply built-in effects to LED strips | \*---------------------------------------------------------*/ - controller->DisableBuiltinEffect(0, hdr == HDR_D_LED1 ? 0x01 : 0x02); - controller->SetLEDEffect(hdr, modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, random, red, grn, blu); + controller->SetStripBuiltinEffectState(hdr, true); + controller->SetLEDEffect(hdr, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color); controller->ApplyEffect(); } } @@ -695,8 +834,22 @@ void RGBController_RGBFusion2USB::UpdateSingleLED(int led) /*---------------------------------------------------------*\ | Get mode parameters | \*---------------------------------------------------------*/ - bool random = (modes[active_mode].color_mode == MODE_COLORS_RANDOM); - int mode_value = (modes[active_mode].value); + int mode_value = (modes[active_mode].value); + bool random = (modes[active_mode].color_mode == MODE_COLORS_RANDOM); + uint32_t* color = &null_color; + + /*---------------------------------------------------------*\ + | If Wave 1-4 then use special sequence. | + \*---------------------------------------------------------*/ + if(mode_value == 6 || (mode_value >= 9 && mode_value <= 12)) + { + controller->SetStripBuiltinEffectState(-1, true); + controller->SetLEDEffect(-1, 1, 0, 0xFF, 0, color); + controller->ApplyEffect(); + controller->SetLEDEffect( 2, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color); + controller->ApplyEffect(); + return; + } unsigned int zone_idx = GetLED_Zone(led); /*---------------------------------------------------------*\ @@ -704,35 +857,28 @@ void RGBController_RGBFusion2USB::UpdateSingleLED(int led) \*---------------------------------------------------------*/ if(zones[zone_idx].type == ZONE_TYPE_SINGLE) { - unsigned char red = 0; - unsigned char grn = 0; - unsigned char blu = 0; - /*---------------------------------------------------------*\ | Motherboard LEDs always use effect mode, so use static for| | direct mode but get colors from zone | \*---------------------------------------------------------*/ if(mode_value == 0xFFFF) { - red = RGBGetRValue(colors[led]); - grn = RGBGetGValue(colors[led]); - blu = RGBGetBValue(colors[led]); - - mode_value = EFFECT_STATIC; + color = &colors[led]; + mode_value = EFFECT_STATIC; } + /*---------------------------------------------------------*\ | If the mode uses mode-specific color, get color from mode | \*---------------------------------------------------------*/ else if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) { - red = RGBGetRValue(modes[active_mode].colors[0]); - grn = RGBGetGValue(modes[active_mode].colors[0]); - blu = RGBGetBValue(modes[active_mode].colors[0]); + color = &modes[active_mode].colors[0]; } - controller->SetLEDEffect(leds[led].value, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, red, grn, blu); + controller->SetLEDEffect(leds[led].value, mode_value, modes[active_mode].speed, modes[active_mode].brightness, random, color); controller->ApplyEffect(); } + /*---------------------------------------------------------*\ | Set strip LEDs | \*---------------------------------------------------------*/ @@ -749,7 +895,7 @@ void RGBController_RGBFusion2USB::DeviceUpdateMode() int RGBController_RGBFusion2USB::GetLED_Zone(int led_idx) { - for(size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + for(int zone_idx = 0; zone_idx < (int)zones.size(); zone_idx++) { int zone_start = zones[zone_idx].start_idx; int zone_end = zone_start + zones[zone_idx].leds_count - 1; @@ -760,8 +906,8 @@ int RGBController_RGBFusion2USB::GetLED_Zone(int led_idx) } } - /*---------------------------------*\ - | If zone is not found, return -1 | - \*---------------------------------*/ + /*---------------------------------------------------------*\ + | If zone is not found, return -1 | + \*---------------------------------------------------------*/ return(-1); } diff --git a/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USB.h b/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USB.h index f38be3b1..b197f4d1 100644 --- a/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USB.h +++ b/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USB.h @@ -1,24 +1,31 @@ -/*-----------------------------------------*\ -| RGBController_GigabyteRGBFusion2USB.h | -| | -| Generic RGB Interface for OpenRGB | -| Gigabyte RGB Fusion 2.0 USB Driver | -| | -| Author: jackun 1/8/2020 | -| Maintainer: Chris M (Dr_No) | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GigabyteRGBFusion2USB.h | +| | +| RGBController for Gigabyte Aorus RGB Fusion 2 USB | +| motherboard | +| | +| jackun 08 Jan 2020 | +| megadjc 31 Jul 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + +#include #include "RGBController.h" #include "GigabyteRGBFusion2USBController.h" -#include -#include +#include "RGBController_GigabyteRGBFusion2USBBoards.h" +#include "RGBController_GigabyteRGBFusion2USBLayouts.h" -#define RGBFusion2_Digital_LEDS_Min 0; -#define RGBFusion2_Digital_LEDS_Max 1024; -#define RGBFUSION2_BRIGHTNESS_MIN 0; -#define RGBFUSION2_BRIGHTNESS_MAX 100; -#define RGBFusion2_Digital_Direct_Offset (HDR_D_LED1_RGB - HDR_D_LED1); +#define RGBFUSION2_DIGITAL_LEDS_MIN 0 +#define RGBFUSION2_DIGITAL_LEDS_MAX 1024 +#define RGBFUSION2_BRIGHTNESS_MIN 0 +#define RGBFUSION2_BRIGHTNESS_MAX 255 +#define RGBFUSION2_SPEED_MIN 9 +#define RGBFUSION2_SPEED_MID 4 +#define RGBFUSION2_SPEED_MAX 0 template static std::map reverse_map(const std::map& map) @@ -33,20 +40,6 @@ static std::map reverse_map(const std::map& map) return reversed_map; } -typedef std::map< std::string, int > FwdLedHeaders; -typedef std::map< int, std::string > RvrseLedHeaders; - -struct LedPort -{ - std::string name; - int header; - int count; -}; - -typedef std::map< std::string, std::string > MBName; -typedef std::map< std::string, std::vector > ZoneLeds; -typedef std::map< std::string, ZoneLeds> KnownLayout; - class RGBController_RGBFusion2USB: public RGBController { public: @@ -69,8 +62,10 @@ private: std::string detector_name; RGBFusion2USBController* controller; - IT8297Report report; + int device_num; ZoneLeds layout; + RGBColor null_color = 0; + uint16_t pid; void Load_Device_Config(); void Init_Controller(); diff --git a/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USBBoards.cpp b/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USBBoards.cpp new file mode 100644 index 00000000..f21a0bd8 --- /dev/null +++ b/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USBBoards.cpp @@ -0,0 +1,314 @@ + +/*---------------------------------------------------------*\ +| RGBController_GigabyteRGBFusion2USBBoards.cpp | +| | +| RGBController for Gigabyte Aorus RGB Fusion 2 USB | +| motherboard | +| | +| megadjc 31 Jul 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_GigabyteRGBFusion2USBBoards.h" + +/*---------------------------------------------------------*\ +| This is a list of known layouts listed by controller | +\*---------------------------------------------------------*/ + +const MBName MBName2LayoutLookup8297 = +{ + {"X570 AORUS ELITE", "STD_ATX" }, + {"X570 AORUS ELITE WIFI", "STD_ATX" }, + {"X570 AORUS MASTER", "MSTR_ATX_3" }, + {"X570 AORUS PRO", "STD_ATX" }, + {"X570 AORUS PRO WIFI", "STD_ATX" }, + {"X570 AORUS ULTRA", "STD_ATX" }, + {"X570 I AORUS PRO WIFI", "B550I-AORUS-PRO-AX" }, + {"Z390 AORUS MASTER-CF", "MSTR_ATX" }, +}; + +const MBName MBName2LayoutLookup8950 = +{ + {"H810M GAMING WIFI6", "H810M" }, + {"H810M H", "H810M" }, + {"H810M S2H", "H810M" }, +}; + +const MBName MBName2LayoutLookup5702 = +{ + {"A620I AX", "B650-C-V2" }, + {"A620M C", "B650-D2H" }, + {"A620M D2H", "B650-D2H" }, + {"A620M DS3H", "A620M-H" }, + {"A620M GAMING X", "A620M-H" }, + {"A620M GAMING X AX", "A620M-H" }, + {"A620M H", "A620M-H" }, + {"A620M S2H", "B650-C-V2" }, + {"B550 AORUS ELITE", "STD_ATX" }, + {"B550 AORUS PRO", "STD_ATX" }, + {"B550I AORUS PRO AX", "B550I-AORUS-PRO-AX" }, + {"B650 AERO G", "X670-ELITE" }, + {"B650 AORUS ELITE", "B650-ELITE" }, + {"B650 AORUS ELITE AX", "B650-ELITE" }, + {"B650 AORUS ELITE AX ICE", "B650-ELITE-V2" }, + {"B650 AORUS ELITE AX V2", "B650-ELITE-V2" }, + {"B650 AORUS ELITE V2", "B650-ELITE-V2" }, + {"B650 AORUS PRO AX", "B650-PRO" }, + {"B650 EAGLE", "B650-Eagle-AX" }, + {"B650 EAGLE AX", "B650-Eagle-AX" }, + {"B650 GAMING X", "B650-PRO" }, + {"B650 GAMING X AX", "B650-PRO" }, + {"B650 GAMING X AX V2", "B650-PRO" }, + {"B650 GAMING X V2", "B650-PRO" }, + {"B650 UD AC", "B650-UD" }, + {"B650 UD AX", "B650-UD" }, + {"B650E AORUS ELITE X AX ICE", "B650-ELITE-V2" }, + {"B650E AORUS MASTER", "MSTR_ATX_2" }, + {"B650E AORUS PRO X USB4", "B650-USB4" }, + {"B650E AORUS TACHYON", "B650-TACH" }, + {"B650I AORUS ULTRA", "B650-D2H" }, + {"B650I AX", "B650-C-V2" }, + {"B650M AORUS ELITE", "B650-ELITE" }, + {"B650M AORUS ELITE AX", "B650-ELITE" }, + {"B650M AORUS ELITE AX ICE", "B650-ELITE" }, + {"B650M AORUS PRO", "B650-ELITE" }, + {"B650M AORUS PRO AX", "B650-ELITE" }, + {"B650M C V2", "B650-C-V2" }, + {"B650M C V3", "B650-C-V2" }, + {"B650M D2H", "B650-D2H" }, + {"B650M D2HP", "B650M-DS3H" }, + {"B650M D3HP", "B650M-DS3H" }, + {"B650M D3HP AX", "B650M-DS3H" }, + {"B650M DS3H", "B650M-DS3H" }, + {"B650M GAMING PLUS WIFI", "B650M-DS3H" }, + {"B650M GAMING WIFI", "B650M-DS3H" }, + {"B650M GAMING WIFI6", "B650M-DS3H" }, + {"B650M GAMING X AX", "B650M-DS3H" }, + {"B650M H", "B650-D2H" }, + {"B650M K", "B650M-DS3H" }, + {"B650M S2H", "B650-D2H" }, + {"B760 AORUS ELITE", "Z790-S-DDR4" }, + {"B760 AORUS ELITE AX", "Z790-S-DDR4" }, + {"B760 AORUS MASTER DDR4", "Z690-ELITE" }, + {"B760 DS3H", "Z790-S-DDR4" }, + {"B760 DS3H AC", "Z790-S-DDR4" }, + {"B760 DS3H AC DDR4", "Z790-S-DDR4" }, + {"B760 DS3H AX", "Z790-S-DDR4" }, + {"B760 DS3H AX DDR4", "Z790-S-DDR4" }, + {"B760 DS3H AX V2", "Z790-S-DDR4" }, + {"B760 DS3H DDR4", "Z790-S-DDR4" }, + {"B760 GAMING X", "Z790-S-DDR4" }, + {"B760 GAMING X AX", "Z790-S-DDR4" }, + {"B760 GAMING X AX DDR4", "Z790-S-DDR4" }, + {"B760 GAMING X DDR4", "Z790-S-DDR4" }, + {"B760I AORUS PRO", "B550I-AORUS-PRO-AX" }, + {"B760I AORUS PRO DDR4", "B550I-AORUS-PRO-AX" }, + {"B760M AORUS ELITE", "Z790-XTRM" }, + {"B760M AORUS ELITE AX", "Z790-XTRM" }, + {"B760M AORUS ELITE AX DDR4", "Z790-XTRM" }, + {"B760M AORUS ELITE DDR4", "Z790-XTRM" }, + {"B760M AORUS ELITE X AX", "B760M-EXAX" }, + {"B760M AORUS PRO", "Z790-XTRM" }, + {"B760M AORUS PRO AX", "Z790-XTRM" }, + {"B760M AORUS PRO AX DDR4", "Z790-XTRM" }, + {"B760M AORUS PRO DDR4", "Z790-XTRM" }, + {"B760M C", "Z790-S-DDR4" }, + {"B760M C V2", "Z790-S-DDR4" }, + {"B760M D2H", "B760M-D2H" }, + {"B760M D2H DDR4", "B760M-D2H" }, + {"B760M D3H", "B760M-D2H" }, + {"B760M D3H DDR4", "B760M-D2H" }, + {"B760M D3HP", "B760M-D2H" }, + {"B760M D3HP DDR4", "B760M-D2H" }, + {"B760M D3HP WIFI6", "B760M-D2H" }, + {"B760M DS3H", "B760M-D2H" }, + {"B760M DS3H AX", "B760M-D2H" }, + {"B760M DS3H AX DDR4", "B760M-D2H" }, + {"B760M DS3H DDR4", "B760M-D2H" }, + {"B760M DS3H GEN 5", "B760M-DS3H-DR-G5" }, + {"B760M G AX", "B760M-GAX" }, + {"B760M GAMING", "B760M-GAX" }, + {"B760M GAMING AC", "B760M-GAX" }, + {"B760M GAMING AC DDR4", "B760M-D2H" }, + {"B760M GAMING DDR4", "B760M-D2H" }, + {"B760M GAMING PLUS WIFI DDR4", "B760M-D2H" }, + {"B760M GAMING WIFI", "B760M-GAX" }, + {"B760M GAMING WIFI PLUS", "B760M-GAX" }, + {"B760M GAMING X", "Z790-S-DDR4" }, + {"B760M GAMING X AX", "Z790-S-DDR4" }, + {"B760M GAMING X AX DDR4", "Z790-S-DDR4" }, + {"B760M GAMING X DDR4", "Z790-S-DDR4" }, + {"B760M POWER", "B760M-D2H" }, + {"B760M POWER DDR4", "B760M-D2H" }, + {"H610M D3H DDR4", "B860I-Pro" }, + {"H610M D3H WIFI DDR4", "B860I-Pro" }, + {"H610M GAMING WIFI DDR4", "B860I-Pro" }, + {"TRX50 AERO D", "TRX50-AERO-D" }, + {"X570S AERO G", "X670-ELITE" }, + {"X570S AORUS ELITE", "X570S-ELITE" }, + {"X570S AORUS ELITE AX", "X570S-ELITE" }, + {"X570S AORUS MASTER", "X570S-A-MSTR" }, + {"X570S AORUS PRO AX", "X570S-PRO-AX" }, + {"X570S GAMING X", "X570S-ELITE" }, + {"X570S UD", "X670-ELITE" }, + {"X570SI AORUS PRO AX", "B550I-AORUS-PRO-AX" }, + {"X670 AORUS ELITE AX", "X670-ELITE" }, + {"X670 GAMING X AX", "X670-ELITE" }, + {"X670 GAMING X AX V2", "B650-Eagle-AX" }, + {"X670E AORUS MASTER", "MSTR_ATX_2" }, + {"X670E AORUS PRO X", "X670-A-PRO-X" }, + {"X670E AORUS XTREME", "MSTR_ATX_2" }, + {"Z690 AORUS ELITE", "Z690-ELITE" }, + {"Z690 AORUS ELITE AX", "Z690-ELITE" }, + {"Z690 AORUS ELITE AX DDR4", "Z690-ELITE" }, + {"Z690 AORUS ELITE DDR4", "Z690-ELITE" }, + {"Z790 AERO G", "Z790-S-DDR4" }, + {"Z790 AORUS ELITE", "Z790-ELITE" }, + {"Z790 AORUS ELITE AX", "Z790-ELITE" }, + {"Z790 AORUS ELITE AX DDR4", "Z790-ELITE" }, + {"Z790 AORUS ELITE AX ICE", "Z790-ELITE" }, + {"Z790 AORUS ELITE AX-W", "Z790-ELITE" }, + {"Z790 AORUS ELITE DDR4", "Z790-ELITE" }, + {"Z790 AORUS ELITE X", "TRX50-AERO-D" }, + {"Z790 AORUS ELITE X AX", "TRX50-AERO-D" }, + {"Z790 AORUS ELITE X WIFI7", "TRX50-AERO-D" }, + {"Z790 AORUS MASTER", "Z790-MSTR" }, + {"Z790 AORUS MASTER X", "Z790-MSTR-X" }, + {"Z790 AORUS PRO X", "Z790-PRO-X" }, + {"Z790 AORUS PRO X WIFI7", "Z790-PRO-X" }, + {"Z790 AORUS TACHYON", "Z790-XTRM" }, + {"Z790 AORUS TACHYON X", "Z790-MSTR-X" }, + {"Z790 AORUS XTREME", "Z790-XTRM" }, + {"Z790 AORUS XTREME X", "Z790-XTRM-X" }, + {"Z790 AORUS XTREME X ICE", "Z790-XTRM-X" }, + {"Z790 D", "Z790-D" }, + {"Z790 D AC", "Z790-D" }, + {"Z790 D AX", "Z790-D" }, + {"Z790 D WIFI", "Z790-D" }, + {"Z790 EAGLE", "Z790-D" }, + {"Z790 EAGLE AX", "Z790-D" }, + {"Z790 GAMING PLUS AX", "Z790-S-DDR4" }, + {"Z790 GAMING X", "Z790-S-DDR4" }, + {"Z790 GAMING X AX", "Z790-S-DDR4" }, + {"Z790 S DDR4", "Z790-S-DDR4" }, + {"Z790 S WIFI DDR4", "Z790-S-DDR4" }, + {"Z790 UD", "Z790-D" }, + {"Z790 UD AC", "Z790-D" }, + {"Z790 UD AX", "Z790-D" }, + {"Z790I AORUS ULTRA", "B550I-AORUS-PRO-AX" }, + {"Z790M AORUS ELITE", "Z790-ELITE" }, + {"Z790M AORUS ELITE AX", "Z790-ELITE" }, + {"Z790M AORUS ELITE AX ICE", "Z790-ELITE" }, +}; + +const MBName MBName2LayoutLookup5711 = +{ + {"A620I AX", "B650-D2H" }, + {"A620M DS3H", "B650M-DS3H" }, + {"A620M GAMING X", "B650M-DS3H" }, + {"A620M GAMING X AX", "B650M-DS3H" }, + {"A620M H", "B650M-DS3H" }, + {"A620M S2H", "B650M-DS3H" }, + {"B650E AORUS STEALTH ICE", "B650E-AORUS-STEALTH" }, + {"B760 DS3H GEN5", "B840M-DS3H" }, + {"B760 DS3H WIFI6E GEN5", "B840M-DS3H" }, + {"B760 GAMING X DDR4 GEN5", "B840M-DS3H" }, + {"B760 GAMING X GEN5", "B840M-DS3H" }, + {"B760 GAMING X WIFI6 GEN5", "B840M-DS3H" }, + {"B760M AORUS ELITE DDR4 GEN5", "X870-WIFI7" }, + {"B760M AORUS ELITE GEN5", "X870-WIFI7" }, + {"B760M AORUS ELITE WIFI6 DDR4 GEN5", "X870-WIFI7" }, + {"B760M AORUS ELITE WIFI6 GEN5", "X870-WIFI7" }, + {"B760M C V3", "B850-EGL-WIFI6" }, + {"B760M DS3H DDR4 GEN 5", "B760M-DS3H-DR-G5" }, + {"B760M DS3H WIFI6E DDR4 GEN 5", "B760M-DS3H-DR-G5" }, + {"B760M GAMING WIFI6 PLUS GEN5", "B760M-DS3H-DR-G5" }, + {"B760M GAMING WIFI6E GEN 5", "B760M-DS3H-DR-G5" }, + {"B760M GAMING X DDR4 GEN5", "B850-AI-TOP" }, + {"B760M GAMING X GEN5", "B850-AI-TOP" }, + {"B760M GAMING X WIFI6E DDR4 GEN5", "B850-AI-TOP" }, + {"B760M GAMING X WIFI6E GEN5", "B850-AI-TOP" }, + {"B840M AORUS ELITE WIFI6E", "B840M-WIFI6E" }, + {"B840M D2H", "B840M-DS3H" }, + {"B840M DS3H", "B840M-DS3H" }, + {"B840M EAGLE WIFI6", "B840M-DS3H" }, + {"B850 AI Top", "B850-AI-TOP" }, + {"B850 AORUS ELITE WIFI7", "X870-WIFI7" }, + {"B850 AORUS ELITE WIFI7 ICE", "X870-WIFI7" }, + {"B850 EAGLE ICE", "B850-EGL-WIFI6" }, + {"B850 EAGLE WIFI6E", "B850-EGL-WIFI6" }, + {"B850 EAGLE WIFI7 ICE", "B850-EGL-WIFI6" }, + {"B850 GAMING WIFI6", "B850-EGL-WIFI6" }, + {"B850 GAMING X WIFI6E", "B850-GMX-WIFI6" }, + {"B850I AORUS PRO", "X870I-PRO" }, + {"B850M AORUS ELITE", "B850-GMX-WIFI6" }, + {"B850M AORUS ELITE WIFI6E", "B850-GMX-WIFI6" }, + {"B850M AORUS ELITE WIFI6E ICE", "B850-GMX-WIFI6" }, + {"B850M AORUS PRO WIFI7", "Z890-WIFI7" }, + {"B850M D3HP", "X870I-PRO" }, + {"B850M DS3H", "B850-EGL-WIFI6" }, + {"B850M DS3H ICE", "B850-EGL-WIFI6" }, + {"B850M EAGLE WIFI6E", "B850-EGL-WIFI6" }, + {"B850M EAGLE WIFI6E ICE", "B850-EGL-WIFI6" }, + {"B850M FORCE", "B850-EGL-WIFI6" }, + {"B850M FORCE WIFI6E", "B850-EGL-WIFI6" }, + {"B850M GAMING X WIFI6E", "B850-GMX-WIFI6" }, + {"B860 AORUS ELITE WIFI7 ICE", "B860-WIFI7" }, + {"B860 DS3H", "B860-DS3H" }, + {"B860 DS3H WIFI6E", "B860-DS3H" }, + {"B860 EAGLE WIFI6E", "B860-EGL-WIFI6" }, + {"B860 GAMING X WIFI6E", "B860-DS3H" }, + {"B860I AORUS PRO ICE", "B860I-Pro" }, + {"B860M AORUS ELITE", "B860-WIFI7" }, + {"B860M AORUS ELITE WIFI6E", "B860-WIFI7" }, + {"B860M AORUS ELITE WIFI6E ICE", "B860-WIFI7" }, + {"B860M AORUS PRO WIFI7", "B860-WIFI7" }, + {"B860M D2H", "B860M-D2H" }, + {"B860M EAGLE", "B860-EGL-P-WIFI6" }, + {"B860M EAGLE DS3H", "B860-EGL-P-WIFI6" }, + {"B860M EAGLE DS3H WIFI6E", "B860-EGL-P-WIFI6" }, + {"B860M EAGLE PLUS WIFI6E", "B860-EGL-P-WIFI6" }, + {"B860M EAGLE WIFI6", "B860-EGL-P-WIFI6" }, + {"B860M EAGLE WIFI6 V2", "B860-EGL-P-WIFI6" }, + {"B860M GAMING WIFI6", "B860M-D2H" }, + {"B860M GAMING X", "B860-EGL-P-WIFI6" }, + {"B860M GAMING X WIFI6E", "B860-EGL-P-WIFI6" }, + {"B860M POWER", "B860-EGL-P-WIFI6" }, + {"TRX50 AI TOP", "TRX50-A-TP" }, + {"W790 AI TOP", "B850-AI-TOP" }, + {"W880 AI TOP", "B850-AI-TOP" }, + {"X870 AORUS ELITE WIFI7", "X870-WIFI7" }, + {"X870 AORUS ELITE WIFI7 ICE", "X870-WIFI7" }, + {"X870 EAGLE WIFI7", "X870-WIFI7" }, + {"X870 GAMING WIFI6", "X870-WIFI7" }, + {"X870 GAMING X WIFI", "X870-WIFI7" }, + {"X870E AORUS ELITE WIFI7", "X870E-WIFI7" }, + {"X870E AORUS ELITE WIFI7 ICE", "X870E-WIFI7" }, + {"X870E AORUS MASTER", "X870E-MSTR" }, + {"X870E AORUS PRO", "X870E-PRO" }, + {"X870E AORUS PRO ICE", "X870E-PRO" }, + {"X870E AORUS XTREME AI TOP", "X870E-XTRM-AI-TOP" }, + {"X870I AORUS PRO", "X870I-PRO" }, + {"X870I AORUS PRO ICE", "X870I-PRO" }, + {"Z890 AERO D", "B850-AI-TOP" }, + {"Z890 AERO G", "B850-AI-TOP" }, + {"Z890 AI TOP", "B850-AI-TOP" }, + {"Z890 AORUS ELITE WIFI7", "Z890-WIFI7" }, + {"Z890 AORUS ELITE WIFI7 ICE", "Z890-WIFI7" }, + {"Z890 AORUS ELITE X ICE", "Z890-WIFI7" }, + {"Z890 AORUS MASTER", "Z890-MSTR" }, + {"Z890 AORUS MASTER AI TOP", "Z890-MSTR-AI-TOP" }, + {"Z890 AORUS PRO ICE", "Z890-WIFI7" }, + {"Z890 AORUS TACHYON ICE", "B850-AI-TOP" }, + {"Z890 AORUS XTREME AI TOP", "Z890-XTRM-AI-TOP" }, + {"Z890 EAGLE", "Z890-WIFI7" }, + {"Z890 EAGLE WIFI7", "Z890-WIFI7" }, + {"Z890 GAMING X WIFI7", "Z890-WIFI7" }, + {"Z890 UD WIFI6E", "B850-AI-TOP" }, + {"Z890I AORUS ULTRA", "Z890-A-ULTRA" }, + {"Z890M AORUS ELITE WIFI7", "Z890-WIFI7" }, + {"Z890M AORUS ELITE WIFI7 ICE", "Z890-WIFI7" }, + {"Z890M GAMING X", "X870I-PRO" }, +}; diff --git a/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USBBoards.h b/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USBBoards.h new file mode 100644 index 00000000..243cbe28 --- /dev/null +++ b/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USBBoards.h @@ -0,0 +1,25 @@ +/*---------------------------------------------------------*\ +| RGBController_GigabyteRGBFusion2USBBoards.h | +| | +| RGBController for Gigabyte Aorus RGB Fusion 2 USB | +| motherboard | +| | +| megadjc 31 Jul 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include + +using MBName = std::map; + +extern const MBName MBName2LayoutLookup8297; +extern const MBName MBName2LayoutLookup8950; +extern const MBName MBName2LayoutLookup5702; +extern const MBName MBName2LayoutLookup5711; + + diff --git a/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USBLayouts.cpp b/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USBLayouts.cpp new file mode 100644 index 00000000..bf4aa96d --- /dev/null +++ b/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USBLayouts.cpp @@ -0,0 +1,1935 @@ +/*---------------------------------------------------------*\ +| RGBController_GigabyteRGBFusion2USBLayouts.cpp | +| | +| RGBController for Gigabyte Aorus RGB Fusion 2 USB | +| motherboard | +| | +| megadjc 31 Jul 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_GigabyteRGBFusion2USBLayouts.h" +#include "GigabyteRGBFusion2USBController.h" + +/*-------------------------------------------------*\ +| LedHeaders is a map of the led header addresses | +\*-------------------------------------------------*/ +const FwdLedHeaders LedLookup = +{ + {"LED1", 0}, + {"LED2", 1}, + {"LED3", 2}, + {"LED4", 3}, + {"LED5", 4}, + {"LED6", 5}, + {"LED7", 6}, + {"LED8", 7}, + {"LED9", 8}, + {"LED10", 9}, + {"LED11", 10}, + {"HDR_D_LED1", 5}, + {"HDR_D_LED2", 6}, + {"HDR_D_LED3", 7}, + {"HDR_D_LED4", 8}, + {"HDR_D_LED1_RGB", 0x58}, + {"HDR_D_LED2_RGB", 0x59}, + {"HDR_D_LED3_RGB", 0x62}, + {"HDR_D_LED4_RGB", 0x63}, +}; + +/*-------------------------------------------------*\ +| These are the default Custom layouts that will | +| be written into config if they doesn't exist | +\*-------------------------------------------------*/ +const KnownLayout HardcodedCustom_Gen1 = +{ + { + "Custom", + { + { + "D_LED2 Top", + { + { "Name for LED Strip 2", HDR_D_LED2, 0 }, + } + }, + { + "D_LED1 Bottom", + { + { "Name for LED Strip 1", HDR_D_LED1, 0 }, + } + }, + { + "Motherboard", + { + { "Name for Led 1", LED1, 1 }, + { "Name for Led 2", LED2, 1 }, + { "Name for Led 3", LED3, 1 }, + { "Name for Led 4", LED4, 1 }, + { "Name for Led 5", LED5, 1 }, + { "Name for Led 8", LED8, 1 }, + } + } + } + } +}; + +const KnownLayout HardcodedCustom_Gen2 = +{ + { + "Custom", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "ARGB_V2_4", + { + { "ARGB_V2_4", HDR_D_LED4, 0 }, + } + }, + { + "Motherboard", + { + { "0x20", LED1, 1 }, + { "0x21", LED2, 1 }, + { "0x22", LED3, 1 }, + { "0x23", LED4, 1 }, + { "0x90", LED9, 1 }, + { "0x91", LED10, 1 }, + { "0x92", LED11, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, +}; + + +/*-------------------------------------------------*\ +| KnownLayoutsLookup contains zone mapping data | +| for each motherboard. | +\*-------------------------------------------------*/ +const KnownLayout knownLayoutsLookup = +{ + { + "STD_ATX", + { + { + "D_LED1 Bottom", + { + { "D_LED1 Bottom", HDR_D_LED1, 0 }, + } + }, + { + "D_LED2 Top", + { + { "D_LED2 Top", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Back I/O", LED1, 1 }, + { "PCIe", LED4, 1 }, + } + }, + { + "12V RGB Strips", + { + { "CPU Header", LED2, 1 }, + { "LED_C1/C2", LED5, 1 }, + } + } + } + }, + { + "A620M-H", + { + { + "D_LED1", + { + { "D_LED1", HDR_D_LED1, 0 }, + } + }, + { + "D_LED2", + { + { "D_LED2", HDR_D_LED2, 0 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED2, 1 }, + } + } + } + }, + { + "B550I-AORUS-PRO-AX", + { + { + "D_LED", + { + { "D_LED", HDR_D_LED1, 0 }, + } + }, + { + "Motherboard", + { + { "Top LED", LED1, 1 }, + { "Top Middle LED", LED2, 1 }, + { "Bottom Middle LED", LED3, 1 }, + { "Bottom LED", LED4, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B650-C-V2", + { + { + "D_LED", + { + { "D_LED", HDR_D_LED1, 0 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED2, 1 }, + } + } + } + }, + { + "B650-D2H", + { + { + "D_LED", + { + { "D_LED", HDR_D_LED1, 0 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B650-Eagle-AX", + { + { + "ARGB_V2_1/V2.3", + { + { "ARGB_V2_1/V2.3", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B650-ELITE", + { + { + "D_LED2 Top", + { + { "D_LED2 Top", HDR_D_LED1, 0 }, + } + }, + { + "D_LED1 Bottom", + { + { "D_LED1 Bottom", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED4, 1 }, + } + }, + { + "12V RGB Strips", + { + { "CPU Header", LED3, 1 }, + { "LED_C1", LED2, 1 }, + { "LED_C2", LED5, 1 }, + } + } + } + }, + { + "B650-ELITE-V2", + { + { + "D_LED2 Top", + { + { "D_LED2 Top", HDR_D_LED1, 0 }, + } + }, + { + "D_LED1 Bottom", + { + { "D_LED1 Bottom", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED4, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B650-PRO", + { + { + "D_LED2 Top", + { + { "D_LED2 Top", HDR_D_LED1, 0 }, + } + }, + { + "D_LED1 Bottom", + { + { "D_LED1 Bottom", HDR_D_LED2, 0 }, + } + }, + { + "12V RGB Strips", + { + { "CPU Header", LED3, 1 }, + { "LED_C1", LED2, 1 }, + { "LED_C2", LED5, 1 }, + } + } + } + }, + { + "B650-UD", + { + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED1, 0 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B650E-AORUS-STEALTH", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED11, 1 }, + { "Logo", LED10, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B650-TACH", + { + { + "D_LED", + { + { "D_LED", HDR_D_LED1, 0 }, + } + }, + { + "12V RGB Strips", + { + { "CPU Header", LED3, 1 }, + { "LED_C", LED2, 1 }, + } + } + } + }, + { + "B650-USB4", + { + { + "ARGB_V2_1/V2.3", + { + { "ARGB_V2_1/V2.3", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED3, 1 }, + { "Cover Left", LED4, 1 }, + { "Cover Right", LED1, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B650M-DS3H", + { + { + "D_LED1", + { + { "D_LED1", HDR_D_LED1, 0 }, + } + }, + { + "D_LED2", + { + { "D_LED2", HDR_D_LED2, 0 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B760M-D2H", + { + { + "D_LED", + { + { "D_LED", HDR_D_LED1, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED4, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED2, 1 }, + } + } + } + }, + { + "B760M-EXAX", + { + { + "ARGB_V2_1/V2.3", + { + { "ARGB_V2_1/V2.3", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Top Logo", LED4, 1 }, + { "Top Middle Logo", LED3, 1 }, + { "Bottom Middle Logo", LED2, 1 }, + { "Bottom Logo", LED1, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B760M-GAX", + { + { + "D_LED1", + { + { "D_LED1", HDR_D_LED1, 0 }, + } + }, + { + "D_LED2", + { + { "D_LED2", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED2, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED2, 1 }, + } + } + } + }, + { + "B760M-DS3H-DR-G5", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED1, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B840M-WIFI6E", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED3, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B840M-DS3H", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B850-AI-TOP", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B850-EGL-WIFI6", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B850-GMX-WIFI6", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED3, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B860-DS3H", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED3, 1 }, + { "Logo", LED10, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B860-EGL-WIFI6", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B860-EGL-P-WIFI6", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED1, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B860-WIFI7", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED3, 1 }, + { "Logo", LED10, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "B860I-Pro", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + } + } + }, + { + "H810M", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", LED3, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", LED4, 0 }, + } + }, + } + }, + { + "MSTR_ATX", + { + { + "D_LED1 Bottom", + { + { "D_LED1 Bottom", HDR_D_LED1, 0 }, + } + }, + { + "D_LED2 Top", + { + { "D_LED2 Top", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Back IO / VRM", LED7, 0 }, + { "Chipset Logo", LED3, 1 }, + { "PCIe", LED4, 1 }, + { "XMP Logo", LED2, 1 }, + } + }, + { + "12V RGB Strips", + { + { "LED_C1/C2", LED5, 1 }, + } + } + } + }, + { + "MSTR_ATX_2", + { + { + "D_LED2 Top", + { + { "D_LED2 Top", HDR_D_LED1, 0 }, + } + }, + { + "D_LED1 Bottom", + { + { "D_LED1 Bottom", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Cover Left", LED4, 1 }, + { "Cover Right", LED1, 1 }, + } + }, + { + "12V RGB Strips", + { + { "CPU Header", LED3, 1 }, + { "LED_C1", LED2, 1 }, + { "LED_C2", LED5, 1 }, + } + } + } + }, + { + "MSTR_ATX_3", + { + { + "D_LED2 Top", + { + { "D_LED2 Top", HDR_D_LED1, 0 }, + } + }, + { + "D_LED1 Bottom", + { + { "D_LED1 Bottom", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Aorus Logo", LED7, 1 }, + { "ESS Logo", LED4, 1 }, + } + }, + { + "12V RGB Strips", + { + { "LED_C1/C2", LED5, 1 }, + } + } + } + }, + { + "TRX50-AERO-D", + { + { + "ARGB_V2_1/V2.3", + { + { "ARGB_V2_1/V2.3", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED3, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "TRX50-A-TP", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "X570S-ELITE", + { + { + "D_LED2 Top", + { + { "D_LED2 Top", HDR_D_LED1, 0 }, + } + }, + { + "D_LED1 Bottom", + { + { "D_LED1 Bottom", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Top Right Accents", LED4, 1 }, + } + }, + { + "12V RGB Strips", + { + { "CPU Header", LED3, 1 }, + { "LED_C1", LED2, 1 }, + { "LED_C2", LED5, 1 }, + } + } + } + }, + { + "X570S-A-MSTR", + { + { + "D_LED2 Top", + { + { "D_LED2 Top", HDR_D_LED1, 0 }, + } + }, + { + "D_LED1 Bottom", + { + { "D_LED1 Bottom", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Logo", LED1, 1 }, + } + }, + { + "12V RGB Strips", + { + { "CPU Header", LED3, 1 }, + { "LED_C1", LED2, 1 }, + { "LED_C2", LED5, 1 }, + } + } + } + }, + { + "X570S-PRO-AX", + { + { + "D_LED2 Top", + { + { "D_LED2 Top", HDR_D_LED1, 0 }, + } + }, + { + "D_LED1 Bottom", + { + { "D_LED1 Bottom", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Logo", LED1, 1 }, + { "ESS Logo", LED4, 1 }, + } + }, + { + "12V RGB Strips", + { + { "CPU Header", LED3, 1 }, + { "LED_C1", LED2, 1 }, + { "LED_C2", LED5, 1 }, + } + } + } + }, + { + "X670-ELITE", + { + { + "D_LED2 Top", + { + { "D_LED2 Top", HDR_D_LED1, 0 }, + } + }, + { + "D_LED1 Bottom", + { + { "D_LED1 Bottom", HDR_D_LED2, 0 }, + } + }, + { + "12V RGB Strips", + { + { "CPU Header", LED3, 1 }, + { "LED_C1", LED2, 1 }, + { "LED_C2", LED5, 1 }, + } + } + } + }, + { + "X670-A-PRO-X", + { + { + "D_LED2 Top", + { + { "D_LED2 Top", HDR_D_LED1, 0 }, + } + }, + { + "D_LED1 Bottom", + { + { "D_LED1 Bottom", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Cover Left", LED4, 1 }, + { "Cover Right", LED1, 1 }, + } + }, + { + "12V RGB Strips", + { + { "LED_C1", LED2, 1 }, + { "LED_C2", LED5, 1 }, + } + } + } + }, + { + "X870-WIFI7", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED3, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "X870E-WIFI7", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED11, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + }, + } + }, + { + "X870E-PRO", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED11, 1 }, + { "Logo", LED10, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "X870E-MSTR", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "ARGB_V2_4", + { + { "ARGB_V2_4", HDR_D_LED4, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED11, 1 }, + { "Logo", LED10, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "X870E-XTRM-AI-TOP", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED11, 1 }, + { "Logo", LED10, 1 }, + { "Wifi Antenna Accent", LED9, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "X870I-PRO", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "Z690-ELITE", + { + { + "D_LED1", + { + { "D_LED1", HDR_D_LED1, 0 }, + } + }, + { + "D_LED2", + { + { "D_LED2", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Top Right Accent", LED3, 1 }, + { "Middle Right Accent", LED4, 1 }, + { "Logo", LED1, 1 }, + } + }, + { + "12V RGB Strips", + { + { "LED_C1", LED2, 1 }, + { "LED_C2", LED5, 1 }, + } + } + } + }, + { + "Z790-D", + { + { + "D_LED1", + { + { "D_LED1", HDR_D_LED1, 0 }, + } + }, + { + "D_LED2", + { + { "D_LED2", HDR_D_LED2, 0 }, + } + } + } + }, + { + "Z790-PRO-X", + { + { + "ARGB_V2_1/ARGB V 2.3", + { + { "ARGB_V2_1/ARGB V 2.3", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Logo", LED1, 1 }, + { "Logo 2", LED4, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "Z790-MSTR", + { + { + "D_LED1", + { + { "D_LED1", HDR_D_LED1, 0 }, + } + }, + { + "D_LED2", + { + { "D_LED2", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Logo", LED1, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "Z790-MSTR-X", + { + { + "ARGB_V2_1/V2.3", + { + { "ARGB_V2_1/V2.3", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Logo", LED1, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "Z790-ELITE", + { + { + "D_LED1", + { + { "D_LED1", HDR_D_LED1, 0 }, + } + }, + { + "D_LED2", + { + { "D_LED2", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Logo", LED3, 1 }, + } + }, + { + "12V RGB Strips", + { + { "LED_C1", LED2, 1 }, + { "LED_C2", LED5, 1 }, + } + } + } + }, + { + "Z790-S-DDR4", + { + { + "D_LED1", + { + { "D_LED1", HDR_D_LED1, 0 }, + } + }, + { + "D_LED2", + { + { "D_LED2", HDR_D_LED2, 0 }, + } + }, + { + "12V RGB Strips", + { + { "LED_C1", LED2, 1 }, + { "LED_C2", LED5, 1 }, + } + } + } + }, + { + "Z790-XTRM", + { + { + "D_LED1", + { + { "D_LED1", HDR_D_LED1, 0 }, + } + }, + { + "D_LED2", + { + { "D_LED2", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED3, 1 }, + } + }, + { + "12V RGB Strips", + { + { "LED_C1", LED2, 1 }, + { "LED_C2", LED5, 1 }, + } + } + } + }, + { + "Z790-XTRM-X", + { + { + "ARGB_V2_1/V2.3", + { + { "ARGB_V2_1/V2.3", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED3, 1 }, + } + }, + { + "12V RGB Strips", + { + { "LED_C1", LED5, 1 }, + { "LED_C2", LED4, 1 }, + { "LED_C3", LED2, 1 }, + } + } + } + }, + { + "Z890-WIFI7", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED3, 1 }, + { "Logo", LED10, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "Z890-MSTR", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "ARGB_V2_4", + { + { "ARGB_V2_4", HDR_D_LED4, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED3, 1 }, + { "Logo", LED10, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "Z890-MSTR-AI-TOP", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "ARGB_V2_4", + { + { "ARGB_V2_4", HDR_D_LED4, 0 }, + } + }, + { + "Motherboard", + { + { "Accent", LED11, 1 }, + { "Logo", LED10, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "Z890-XTRM-AI-TOP", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "ARGB_V2_4", + { + { "ARGB_V2_4", HDR_D_LED4, 0 }, + } + }, + { + "Motherboard", + { + { "Logo", LED10, 1 }, + { "WIFI Antenna Accent", LED11, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "Z890-A-ULTRA", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "Motherboard", + { + { "Logo", LED10, 1 }, + } + } + } + }, + { + "IT5711-Generic", + { + { + "ARGB_V2_1", + { + { "ARGB_V2_1", HDR_D_LED1, 0 }, + } + }, + { + "ARGB_V2_2", + { + { "ARGB_V2_2", HDR_D_LED2, 0 }, + } + }, + { + "ARGB_V2_3", + { + { "ARGB_V2_3", HDR_D_LED3, 0 }, + } + }, + { + "ARGB_V2_4", + { + { "ARGB_V2_4", HDR_D_LED4, 0 }, + } + }, + { + "Motherboard", + { + { "0x20", LED1, 1 }, + { "Ox21", LED2, 1 }, + { "0x22", LED3, 1 }, + { "0x23", LED4, 1 }, + { "0x90", LED9, 1 }, + { "0x91", LED10, 1 }, + { "0x92", LED11, 1 }, + } + }, + { + "12V RGB Strip", + { + { "LED_C", LED5, 1 }, + } + } + } + }, + { + "IT8297BX-GBX570", + { + { + "D_LED2 Top", + { + { "Name for LED Strip 2", HDR_D_LED2, 0 }, + } + }, + { + "D_LED1 Bottom", + { + { "Name for LED Strip 1", HDR_D_LED1, 0 }, + } + }, + { + "Motherboard", + { + { "Name for Led 1", LED1, 1 }, + { "Name for Led 2", LED2, 1 }, + { "Name for Led 3", LED3, 1 }, + { "Name for Led 4", LED4, 1 }, + { "Name for Led 5", LED5, 1 }, + { "Name for Led 6", LED6, 1 }, + { "Name for Led 7", LED7, 1 }, + { "Name for Led 8", LED8, 1 }, + } + } + } + } +}; diff --git a/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USBLayouts.h b/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USBLayouts.h new file mode 100644 index 00000000..19607598 --- /dev/null +++ b/Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USBLayouts.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_GigabyteRGBFusion2USBLayouts.h | +| | +| RGBController for Gigabyte Aorus RGB Fusion 2 USB | +| motherboard | +| | +| megadjc 31 Jul 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include + +/* LED port definition */ +struct LedPort +{ + std::string name; + int header; + int count; +}; + +/* Type aliases */ +using FwdLedHeaders = std::map; +using RvrseLedHeaders = std::map; +using ZoneLeds = std::map>; +using KnownLayout = std::map; + +extern const KnownLayout HardcodedCustom_Gen1; +extern const KnownLayout HardcodedCustom_Gen2; +extern const KnownLayout knownLayoutsLookup; +extern const FwdLedHeaders LedLookup; \ No newline at end of file diff --git a/Controllers/GigabyteRGBFusionController/GigabyteRGBFusionController.cpp b/Controllers/GigabyteRGBFusionController/GigabyteRGBFusionController.cpp index e4c24248..155c4ecb 100644 --- a/Controllers/GigabyteRGBFusionController/GigabyteRGBFusionController.cpp +++ b/Controllers/GigabyteRGBFusionController/GigabyteRGBFusionController.cpp @@ -1,16 +1,18 @@ -/*-----------------------------------------*\ -| GigabyteRGBFusionController.cpp | -| | -| Driver for Gigabyte Aorus RGB Fusion | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 12/10/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| GigabyteRGBFusionController.cpp | +| | +| Driver for Gigabyte Aorus RGB Fusion SMBus motherboard | +| | +| Adam Honse (CalcProgrammer1) 10 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "GigabyteRGBFusionController.h" #include #include #include +#include "GigabyteRGBFusionController.h" RGBFusionController::RGBFusionController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev) { @@ -63,7 +65,7 @@ void RGBFusionController::SetAllColors(unsigned char red, unsigned char green, u { unsigned char mode_ch_0; unsigned char mode_ch_1; - + switch_bank(1); set_color_ch_0(red, green, blue); set_color_ch_1(red, green, blue); diff --git a/Controllers/GigabyteRGBFusionController/GigabyteRGBFusionController.h b/Controllers/GigabyteRGBFusionController/GigabyteRGBFusionController.h index 9effbcbe..f42c76f0 100644 --- a/Controllers/GigabyteRGBFusionController/GigabyteRGBFusionController.h +++ b/Controllers/GigabyteRGBFusionController/GigabyteRGBFusionController.h @@ -1,17 +1,19 @@ -/*-----------------------------------------*\ -| GigabyteRGBFusionController.h | -| | -| Definitions and types for Gigabyte Aorus | -| RGB Fusion lighting controller | -| | -| Adam Honse (CalcProgrammer1) 12/10/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| GigabyteRGBFusionController.h | +| | +| Driver for Gigabyte Aorus RGB Fusion SMBus motherboard | +| | +| Adam Honse (CalcProgrammer1) 10 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" -#pragma once - typedef unsigned char rgb_fusion_dev_id; enum diff --git a/Controllers/GigabyteRGBFusionController/GigabyteRGBFusionControllerDetect.cpp b/Controllers/GigabyteRGBFusionController/GigabyteRGBFusionControllerDetect.cpp index 3b18b62d..2711da3f 100644 --- a/Controllers/GigabyteRGBFusionController/GigabyteRGBFusionControllerDetect.cpp +++ b/Controllers/GigabyteRGBFusionController/GigabyteRGBFusionControllerDetect.cpp @@ -1,13 +1,22 @@ +/*---------------------------------------------------------*\ +| GigabyteRGBFusionControllerDetect.cpp | +| | +| Detector for Gigabyte Aorus RGB Fusion SMBus | +| motherboard | +| | +| Adam Honse (CalcProgrammer1) 10 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "GigabyteRGBFusionController.h" #include "LogManager.h" -#include "RGBController.h" #include "RGBController_GigabyteRGBFusion.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include #define DETECTOR_NAME "Gigabyte RGB Fusion SMBus" #define VENDOR_NAME "Gigabyte Technology Co., Ltd." diff --git a/Controllers/GigabyteRGBFusionController/RGBController_GigabyteRGBFusion.cpp b/Controllers/GigabyteRGBFusionController/RGBController_GigabyteRGBFusion.cpp index 04bbc051..bd13434f 100644 --- a/Controllers/GigabyteRGBFusionController/RGBController_GigabyteRGBFusion.cpp +++ b/Controllers/GigabyteRGBFusionController/RGBController_GigabyteRGBFusion.cpp @@ -1,11 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_GigabyteRGBFusion.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Gigabyte RGB Fusion Driver | -| | -| Adam Honse (CalcProgrammer1) 12/11/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GigabyteRGBFusion.cpp | +| | +| RGBController for Gigabyte Aorus RGB Fusion SMBus | +| motherboard | +| | +| Adam Honse (CalcProgrammer1) 11 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_GigabyteRGBFusion.h" @@ -126,7 +129,7 @@ void RGBController_RGBFusion::ResizeZone(int /*zone*/, int /*new_size*/) void RGBController_RGBFusion::DeviceUpdateLEDs() { - for (std::size_t led = 0; led < colors.size(); led++) + for(unsigned int led = 0; led < (unsigned int)colors.size(); led++) { RGBColor color = colors[led]; unsigned char red = RGBGetRValue(color); @@ -156,7 +159,7 @@ int RGBController_RGBFusion::GetDeviceMode() { int dev_mode = controller->GetMode(); - for(std::size_t mode = 0; mode < modes.size(); mode++) + for(int mode = 0; mode < (int)modes.size(); mode++) { if(modes[mode].value == dev_mode) { diff --git a/Controllers/GigabyteRGBFusionController/RGBController_GigabyteRGBFusion.h b/Controllers/GigabyteRGBFusionController/RGBController_GigabyteRGBFusion.h index c0eecc73..ac8853f9 100644 --- a/Controllers/GigabyteRGBFusionController/RGBController_GigabyteRGBFusion.h +++ b/Controllers/GigabyteRGBFusionController/RGBController_GigabyteRGBFusion.h @@ -1,11 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_GigabyteRGBFusion.h | -| | -| Generic RGB Interface for OpenRGB | -| Gigabyte RGB Fusion Driver | -| | -| Adam Honse (CalcProgrammer1) 12/11/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GigabyteRGBFusion.h | +| | +| RGBController for Gigabyte Aorus RGB Fusion SMBus | +| motherboard | +| | +| Adam Honse (CalcProgrammer1) 11 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/GigabyteRGBFusionGPUController/GigabyteRGBFusionGPUController.cpp b/Controllers/GigabyteRGBFusionGPUController/GigabyteRGBFusionGPUController.cpp index 62f1b52f..39852bcb 100644 --- a/Controllers/GigabyteRGBFusionGPUController/GigabyteRGBFusionGPUController.cpp +++ b/Controllers/GigabyteRGBFusionGPUController/GigabyteRGBFusionGPUController.cpp @@ -1,18 +1,21 @@ -/*-----------------------------------------*\ -| GigabyteRGBFusionGPUController.cpp | -| | -| Driver for Gigabyte Aorus RGB Fusion GPU | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 2/20/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| GigabyteRGBFusionGPUController.cpp | +| | +| Driver for Gigabyte Aorus RGB Fusion GPU | +| | +| Adam Honse (CalcProgrammer1) 20 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "GigabyteRGBFusionGPUController.h" -RGBFusionGPUController::RGBFusionGPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev) +RGBFusionGPUController::RGBFusionGPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev, std::string dev_name) { - this->bus = bus; - this->dev = dev; + this->bus = bus; + this->dev = dev; + this->name = dev_name; } RGBFusionGPUController::~RGBFusionGPUController() @@ -30,6 +33,11 @@ std::string RGBFusionGPUController::GetDeviceLocation() return("I2C: " + return_string); } +std::string RGBFusionGPUController::GetDeviceName() +{ + return(name); +} + void RGBFusionGPUController::SetColor(unsigned char red, unsigned char green, unsigned char blue) { bus->i2c_smbus_write_byte(dev, RGB_FUSION_GPU_REG_COLOR); @@ -37,8 +45,10 @@ void RGBFusionGPUController::SetColor(unsigned char red, unsigned char green, un 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) + /*-----------------------------------------------------*\ + | 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); @@ -54,8 +64,10 @@ void RGBFusionGPUController::SetMode(unsigned char mode, unsigned char speed, un bus->i2c_smbus_write_byte(dev, speed); bus->i2c_smbus_write_byte(dev, brightness); - // Pad commands with 4 zero-bytes for NVIDIA_RTX3060_DEV - if (dev == 0x62) + /*-----------------------------------------------------*\ + | 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); @@ -71,12 +83,14 @@ void RGBFusionGPUController::Save() bus->i2c_smbus_write_byte(dev, 0x00); bus->i2c_smbus_write_byte(dev, 0x00); - // Pad commands with 4 zero-bytes for NVIDIA_RTX3060_DEV - if (dev == 0x62) + /*-----------------------------------------------------*\ + | 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); } -} \ No newline at end of file +} diff --git a/Controllers/GigabyteRGBFusionGPUController/GigabyteRGBFusionGPUController.h b/Controllers/GigabyteRGBFusionGPUController/GigabyteRGBFusionGPUController.h index a43f4a6c..02de5a61 100644 --- a/Controllers/GigabyteRGBFusionGPUController/GigabyteRGBFusionGPUController.h +++ b/Controllers/GigabyteRGBFusionGPUController/GigabyteRGBFusionGPUController.h @@ -1,17 +1,19 @@ -/*-----------------------------------------*\ -| GigabyteRGBFusionGPUController.h | -| | -| Definitions and types for Gigabyte Aorus | -| RGB Fusion GPU lighting controller | -| | -| Adam Honse (CalcProgrammer1) 2/20/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| GigabyteRGBFusionGPUController.h | +| | +| Driver for Gigabyte Aorus RGB Fusion GPU | +| | +| Adam Honse (CalcProgrammer1) 20 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" -#pragma once - typedef unsigned char rgb_fusion_dev_id; enum @@ -47,10 +49,11 @@ enum class RGBFusionGPUController { public: - RGBFusionGPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev); + RGBFusionGPUController(i2c_smbus_interface* bus, rgb_fusion_dev_id dev, std::string dev_name); ~RGBFusionGPUController(); std::string GetDeviceLocation(); + std::string GetDeviceName(); void SetColor(unsigned char red, unsigned char green, unsigned char blue); void SetMode(unsigned char mode, unsigned char speed, unsigned char brightness); @@ -59,5 +62,5 @@ public: private: i2c_smbus_interface* bus; rgb_fusion_dev_id dev; - + std::string name; }; diff --git a/Controllers/GigabyteRGBFusionGPUController/GigabyteRGBFusionGPUControllerDetect.cpp b/Controllers/GigabyteRGBFusionGPUController/GigabyteRGBFusionGPUControllerDetect.cpp index 4b801825..72a9491a 100644 --- a/Controllers/GigabyteRGBFusionGPUController/GigabyteRGBFusionGPUControllerDetect.cpp +++ b/Controllers/GigabyteRGBFusionGPUController/GigabyteRGBFusionGPUControllerDetect.cpp @@ -1,13 +1,20 @@ +/*---------------------------------------------------------*\ +| GigabyteRGBFusionGPUControllerDetect.cpp | +| | +| Detector for Gigabyte Aorus RGB Fusion GPU | +| | +| Adam Honse (CalcProgrammer1) 20 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "GigabyteRGBFusionGPUController.h" #include "LogManager.h" -#include "RGBController.h" #include "RGBController_GigabyteRGBFusionGPU.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include #define GIGABYTEGPU_CONTROLLER_NAME "Gigabyte RGB Fusion GPU" @@ -91,82 +98,93 @@ void DetectGigabyteRGBFusionGPUControllers(i2c_smbus_interface* bus, uint8_t i2c // Check for RGB Fusion controller if(TestForGigabyteRGBFusionGPUController(bus, i2c_addr)) { - RGBFusionGPUController* controller = new RGBFusionGPUController(bus, i2c_addr); + RGBFusionGPUController* controller = new RGBFusionGPUController(bus, i2c_addr, name); RGBController_RGBFusionGPU* rgb_controller = new RGBController_RGBFusionGPU(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } /* DetectGigabyteRGBFusionGPUControllers() */ -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1050 Ti G1 Gaming (rev A1)", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1050TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1050TI_G1_GAMING_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1050 Ti G1 Gaming", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1050TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1050TI_G1_GAMING_SUB_DEV, 0x48); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1060 G1 Gaming 6G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1060_G1_GAMING_SUB_DEV, 0x48); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1060 G1 Gaming 6G OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1060_G1_GAMING_OC_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1060 Xtreme Gaming V1", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1060_XTREME_V1_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1060 Xtreme Gaming v2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1060_XTREME_V2_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1070 Xtreme Gaming", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1070_XTREME_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1070 G1 Gaming 8G V1", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1070_G1_GAMING_8G_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1070 Ti 8G Gaming", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1070TI_GAMING_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1080 G1 Gaming", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1080_G1_GAMING_SUB_DEV, 0x48); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1080 Ti 11G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1080TI_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1080 Ti Gaming OC 11G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1080TI_GAMING_OC_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1080 Ti Gaming OC BLACK 11G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1080TI_GAMING_OC_BLACK_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1080 Ti Xtreme Edition", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1080TI_XTREME_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1080 Ti Xtreme Waterforce Edition", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1080TI_XTREME_WATERFORCE_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1650 Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1650_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1650_GAMING_OC_SUB_DEV, 0x55); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1660 Gaming OC 6G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1660_GAMING_OC_6G_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte GTX1660 SUPER Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1660S_GAMING_OC_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2060 Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060_GAMING_OC_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2060 Gaming OC PRO", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060_GAMING_OC_PRO_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2060 Gaming OC PRO V2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060_GAMING_OC_PRO_SUB_DEV2, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2060 Gaming OC PRO White", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060_GAMING_OC_PRO_WHITE_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2060 SUPER Gaming", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060S_GAMING_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2060 SUPER Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060S_GAMING_OC_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2060 SUPER Gaming OC 3X White 8G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060S_GAMING_OC_WHITE_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2060 SUPER Gaming OC 3X 8G V2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060S_GAMING_OC_3X_V2_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2070 Gaming OC 8G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070_GAMING_OC_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2070 Gaming OC 8GC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070_GAMING_OC_8GC_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2070 Windforce 8G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070_WINDFORCE_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2070S Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070S_GAMING_OC_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2070S Gaming OC 3X", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070S_GAMING_OC_3X_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2070S Gaming OC 3X", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070S_GAMING_OC_3X_SUB_DEV, 0x55); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2070S Gaming OC 3X White", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070S_GAMING_OC_3X_WHITE_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2080 Gaming OC 8G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2080_GAMING_OC_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2080 Gaming OC 8G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2080_A_GAMING_OC_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2080 Ti GAMING OC 11G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2080_TI_GAMING_OC_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX2080S Gaming OC 8G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2080S_GAMING_OC_SUB_DEV, 0x47); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3050 Gaming OC 8G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3050_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3050_GAMING_OC_8GB_SUB_DEV, 0x62); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 EAGLE OC 12G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_EAGLE_OC_12GB_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 EAGLE OC 12G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_EAGLE_OC_12GB_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 EAGLE OC 12G V2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_EAGLE_OC_12GB_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 EAGLE 12G LHR V2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_EAGLE_12GB_V2_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 Vision OC 12G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_VISION_OC_12GB_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 Vision OC 12G LHR", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_VISION_OC_12GB_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 Vision OC 12G v3.0", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_VISION_OC_12GB_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 Gaming OC 12G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_GAMING_OC_12GB_SUB_DEV, 0x62); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 Gaming OC 12G (rev. 2.0)", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_GAMING_OC_12GB_SUB_DEV, 0x62); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 Gaming OC 12G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_GAMING_OC_12GB_SUB_DEV, 0x62); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 Ti EAGLE OC 8G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_EAGLE_OC_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 Ti EAGLE OC 8G V2.0 LHR", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_EAGLE_OC_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 Ti EAGLE OC 8G V2.0 LHR", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_EAGLE_OC_LHR_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3060 Ti Vision OC 8G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_VISION_OC_8G_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3070 Gaming OC 8G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_GAMING_OC_SUB_DEV, 0x62); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3070 Gaming OC 8G v3.0 LHR", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_GAMING_OC_SUB_DEV, 0x62); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3070 Vision 8G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_VISION_OC_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3070 Vision 8G V2.0 LHR", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_VISION_OC_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3070 Eagle OC 8G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_EAGLE_OC_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3070 Eagle OC 8G V2.0 LHR", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_EAGLE_OC_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3070 Ti Gaming OC 8G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070TI_GAMING_OC_SUB_DEV, 0x62); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3070 Ti EAGLE 8G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070TI_EAGLE_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3070 Ti Vision OC 8G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070TI_VISION_OC_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3080 Gaming OC 10G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_GAMING_OC_SUB_DEV, 0x62); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3080 Gaming OC 12G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_GAMING_OC_12G_SUB_DEV, 0x62); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3080 Gaming OC 10G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_GAMING_OC_SUB_DEV, 0x62); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3080 Vision OC 10G (REV 2.0)", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_VISION_OC_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3080 Vision OC 10G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_VISION_OC_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3080 EAGLE OC 10G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_EAGLE_OC_10G_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3080 Ti Gaming OC 12G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080TI_GAMING_OC_SUB_DEV, 0x62); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3080 Ti EAGLE 12G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080TI_EAGLE_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3080 Ti EAGLE OC 12G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080TI_EAGLE_OC_SUB_DEV, 0x63); -REGISTER_I2C_PCI_DETECTOR("Gigabyte RTX3090 Gaming OC 24G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3090_GAMING_OC_24GB_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1050 Ti G1 Gaming Rev A1", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1050TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1050TI_G1_GAMING_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1050 Ti G1 Gaming", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1050TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1050TI_G1_GAMING_SUB_DEV, 0x48); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1060 G1 Gaming", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1060_G1_GAMING_SUB_DEV, 0x48); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1060 G1 Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1060_G1_GAMING_OC_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1060 Xtreme Gaming V1", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1060_XTREME_V1_SUB_DEV_D, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1060 Xtreme Gaming V1", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1060_XTREME_V1_SUB_DEV_H, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1060 Xtreme Gaming V2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1060_XTREME_V2_SUB_DEV_D, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1060 Xtreme Gaming V2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1060_XTREME_V2_SUB_DEV_H, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1070 Xtreme Gaming", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1070_XTREME_SUB_DEV_D, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1070 Xtreme Gaming", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1070_XTREME_SUB_DEV_H, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1070 G1 Gaming V1", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1070_G1_GAMING_8G_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1070 Ti Gaming", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1070TI_GAMING_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1080 G1 Gaming", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1080_G1_GAMING_SUB_DEV, 0x48); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1080 Ti Gaming", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1080TI_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1080 Ti Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1080TI_GAMING_OC_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1080 Ti Gaming OC BLACK", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1080TI_GAMING_OC_BLACK_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1080 Ti Xtreme Edition", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1080TI_XTREME_SUB_DEV_D, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1080 Ti Xtreme Edition", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1080TI_XTREME_SUB_DEV_H, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1080 Ti Xtreme Waterforce Edition", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1080TI_XTREME_WATERFORCE_SUB_DEV_D, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1080 Ti Xtreme Waterforce Edition", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1080TI_XTREME_WATERFORCE_SUB_DEV_H, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1650 Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1650_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1650_GAMING_OC_SUB_DEV, 0x55); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1660 Gaming OC 6G", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1660_GAMING_OC_6G_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1660 SUPER Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1660S_GAMING_OC_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce GTX 1660 Ti Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_GTX1660TI_GAMING_OC_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2060 Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060_GAMING_OC_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2060 Gaming OC PRO", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060_GAMING_OC_PRO_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2060 Gaming OC PRO V2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU104_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060_GAMING_OC_PRO_SUB_DEV2, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2060 Gaming OC PRO V3", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060_GAMING_OC_PRO_SUB_DEV2, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2060 Gaming OC PRO White", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060_GAMING_OC_PRO_WHITE_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2060 SUPER Gaming", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060S_GAMING_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2060 SUPER Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060S_GAMING_OC_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2060 SUPER Gaming OC 3X White", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060S_GAMING_OC_WHITE_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2060 SUPER Gaming OC 3X V2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2060S_GAMING_OC_3X_V2_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2070 Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070_GAMING_OC_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2070 Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070_GAMING_OC_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2070 Gaming OC 8GC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070_GAMING_OC_8GC_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2070 Windforce", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070_WINDFORCE_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2070 SUPER Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070S_GAMING_OC_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2070 SUPER Gaming OC 3X", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070S_GAMING_OC_3X_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2070 SUPER Gaming OC 3X", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070S_GAMING_OC_3X_SUB_DEV, 0x55); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2070 SUPER Gaming OC 3X White", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2070S_GAMING_OC_3X_WHITE_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2080 Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2080_GAMING_OC_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2080 Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2080_A_GAMING_OC_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2080 Ti GAMING OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2080TI_GAMING_OC_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 2080 SUPER Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX2080S_GAMING_OC_SUB_DEV, 0x47); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3050 Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3050_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3050_GAMING_OC_8GB_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 EAGLE OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_EAGLE_OC_12GB_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 EAGLE OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_EAGLE_OC_12GB_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 EAGLE OC V2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_EAGLE_OC_12GB_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 EAGLE LHR V2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_EAGLE_12GB_V2_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 Vision OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_VISION_OC_12GB_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 Vision OC LHR", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_VISION_OC_12GB_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 Vision OC V3", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_VISION_OC_12GB_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_GAMING_OC_12GB_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 Gaming OC V2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_GAMING_OC_12GB_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060_GAMING_OC_12GB_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 Ti EAGLE OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_EAGLE_OC_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 Ti EAGLE OC LHR V2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_EAGLE_OC_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 Ti EAGLE OC LHR V2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_EAGLE_OC_LHR_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3060 Ti Vision OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3060TI_VISION_OC_8G_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3070 Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_GAMING_OC_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3070 Gaming OC LHR V3", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_GAMING_OC_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3070 Vision", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_VISION_OC_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3070 Vision LHR V2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_VISION_OC_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3070 Eagle OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_EAGLE_OC_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3070 Eagle OC LHR V2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070_EAGLE_OC_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3070 Ti Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070TI_GAMING_OC_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3070 Ti EAGLE", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070TI_EAGLE_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3070 Ti Vision OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3070TI_VISION_OC_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3080 Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_GAMING_OC_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3080 Vision OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_VISION_OC_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3080 EAGLE OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_EAGLE_OC_10G_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3080 Gaming OC LHR", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_GAMING_OC_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3080 Vision OC LHR V2", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_VISION_OC_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3080 12G Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080_GAMING_OC_12G_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3080 Ti Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080TI_GAMING_OC_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3080 Ti EAGLE", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080TI_EAGLE_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3080 Ti EAGLE OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3080TI_EAGLE_OC_SUB_DEV, 0x63); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 3090 Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX3090_GAMING_OC_24GB_SUB_DEV, 0x62); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4060 Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX4060_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4060_GAMING_OC_8G_SUB_DEV, 0x55); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4060 Ti Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX4060TI_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4060TI_GAMING_OC_8G_SUB_DEV, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4060 Ti Gaming OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX4060TI_16G_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4060TI_GAMING_OC_16G_SUB_DEV, 0x71); +REGISTER_I2C_PCI_DETECTOR("Gigabyte GeForce RTX 4070 Ti SUPER EAGLE OC", DetectGigabyteRGBFusionGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, GIGABYTE_SUB_VEN, GIGABYTE_RTX4070TIS_EAGLE_OC_16G_SUB_DEV, 0x71); diff --git a/Controllers/GigabyteRGBFusionGPUController/RGBController_GigabyteRGBFusionGPU.cpp b/Controllers/GigabyteRGBFusionGPUController/RGBController_GigabyteRGBFusionGPU.cpp index b985ce06..57f745eb 100644 --- a/Controllers/GigabyteRGBFusionGPUController/RGBController_GigabyteRGBFusionGPU.cpp +++ b/Controllers/GigabyteRGBFusionGPUController/RGBController_GigabyteRGBFusionGPU.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_GigabyteRGBFusionGPU.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Gigabyte RGB Fusion GPU Driver | -| | -| Adam Honse (CalcProgrammer1) 2/23/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GigabyteRGBFusionGPU.cpp | +| | +| RGBController for Gigabyte Aorus RGB Fusion GPU | +| | +| Adam Honse (CalcProgrammer1) 23 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_GigabyteRGBFusionGPU.h" @@ -22,84 +24,84 @@ RGBController_RGBFusionGPU::RGBController_RGBFusionGPU(RGBFusionGPUController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Gigabyte GPU"; - vendor = "Gigabyte"; - description = "RGB Fusion GPU"; - location = controller->GetDeviceLocation(); - type = DEVICE_TYPE_GPU; + name = controller->GetDeviceName(); + vendor = "Gigabyte"; + description = "RGB Fusion GPU Device"; + location = controller->GetDeviceLocation(); + type = DEVICE_TYPE_GPU; mode Direct; - Direct.name = "Direct"; - Direct.value = RGB_FUSION_GPU_MODE_STATIC; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Direct.color_mode = MODE_COLORS_PER_LED; - Direct.brightness_min = RGB_FUSION_GPU_BRIGHTNESS_MIN; - Direct.brightness_max = RGB_FUSION_GPU_BRIGHTNESS_MAX; - Direct.brightness = RGB_FUSION_GPU_BRIGHTNESS_MAX; + Direct.name = "Direct"; + Direct.value = RGB_FUSION_GPU_MODE_STATIC; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = RGB_FUSION_GPU_BRIGHTNESS_MIN; + Direct.brightness_max = RGB_FUSION_GPU_BRIGHTNESS_MAX; + Direct.brightness = RGB_FUSION_GPU_BRIGHTNESS_MAX; modes.push_back(Direct); mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = RGB_FUSION_GPU_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Breathing.speed_min = RGB_FUSION_GPU_SPEED_SLOWEST; - Breathing.speed_max = RGB_FUSION_GPU_SPEED_FASTEST; - Breathing.speed = RGB_FUSION_GPU_SPEED_NORMAL; - Breathing.color_mode = MODE_COLORS_PER_LED; - Breathing.brightness_min = RGB_FUSION_GPU_BRIGHTNESS_MIN; - Breathing.brightness_max = RGB_FUSION_GPU_BRIGHTNESS_MAX; - Breathing.brightness = RGB_FUSION_GPU_BRIGHTNESS_MAX; + Breathing.name = "Breathing"; + Breathing.value = RGB_FUSION_GPU_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Breathing.speed_min = RGB_FUSION_GPU_SPEED_SLOWEST; + Breathing.speed_max = RGB_FUSION_GPU_SPEED_FASTEST; + Breathing.speed = RGB_FUSION_GPU_SPEED_NORMAL; + Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.brightness_min = RGB_FUSION_GPU_BRIGHTNESS_MIN; + Breathing.brightness_max = RGB_FUSION_GPU_BRIGHTNESS_MAX; + Breathing.brightness = RGB_FUSION_GPU_BRIGHTNESS_MAX; modes.push_back(Breathing); mode Flashing; - Flashing.name = "Flashing"; - Flashing.value = RGB_FUSION_GPU_MODE_FLASHING; - Flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Flashing.speed_min = RGB_FUSION_GPU_SPEED_SLOWEST; - Flashing.speed_max = RGB_FUSION_GPU_SPEED_FASTEST; - Flashing.speed = RGB_FUSION_GPU_SPEED_NORMAL; - Flashing.color_mode = MODE_COLORS_PER_LED; - Flashing.brightness_min = RGB_FUSION_GPU_BRIGHTNESS_MIN; - Flashing.brightness_max = RGB_FUSION_GPU_BRIGHTNESS_MAX; - Flashing.brightness = RGB_FUSION_GPU_BRIGHTNESS_MAX; + Flashing.name = "Flashing"; + Flashing.value = RGB_FUSION_GPU_MODE_FLASHING; + Flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Flashing.speed_min = RGB_FUSION_GPU_SPEED_SLOWEST; + Flashing.speed_max = RGB_FUSION_GPU_SPEED_FASTEST; + Flashing.speed = RGB_FUSION_GPU_SPEED_NORMAL; + Flashing.color_mode = MODE_COLORS_PER_LED; + Flashing.brightness_min = RGB_FUSION_GPU_BRIGHTNESS_MIN; + Flashing.brightness_max = RGB_FUSION_GPU_BRIGHTNESS_MAX; + Flashing.brightness = RGB_FUSION_GPU_BRIGHTNESS_MAX; modes.push_back(Flashing); mode DualFlashing; - DualFlashing.name = "Dual Flashing"; - DualFlashing.value = RGB_FUSION_GPU_MODE_DUAL_FLASHING; - DualFlashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - DualFlashing.speed_min = RGB_FUSION_GPU_SPEED_SLOWEST; - DualFlashing.speed_max = RGB_FUSION_GPU_SPEED_FASTEST; - DualFlashing.speed = RGB_FUSION_GPU_SPEED_NORMAL; - DualFlashing.color_mode = MODE_COLORS_PER_LED; - DualFlashing.brightness_min = RGB_FUSION_GPU_BRIGHTNESS_MIN; - DualFlashing.brightness_max = RGB_FUSION_GPU_BRIGHTNESS_MAX; - DualFlashing.brightness = RGB_FUSION_GPU_BRIGHTNESS_MAX; + DualFlashing.name = "Dual Flashing"; + DualFlashing.value = RGB_FUSION_GPU_MODE_DUAL_FLASHING; + DualFlashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + DualFlashing.speed_min = RGB_FUSION_GPU_SPEED_SLOWEST; + DualFlashing.speed_max = RGB_FUSION_GPU_SPEED_FASTEST; + DualFlashing.speed = RGB_FUSION_GPU_SPEED_NORMAL; + DualFlashing.color_mode = MODE_COLORS_PER_LED; + DualFlashing.brightness_min = RGB_FUSION_GPU_BRIGHTNESS_MIN; + DualFlashing.brightness_max = RGB_FUSION_GPU_BRIGHTNESS_MAX; + DualFlashing.brightness = RGB_FUSION_GPU_BRIGHTNESS_MAX; modes.push_back(DualFlashing); mode ColorCycle; - ColorCycle.name = "Color Cycle"; - ColorCycle.value = RGB_FUSION_GPU_MODE_COLOR_CYCLE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - ColorCycle.flags = MODE_FLAG_HAS_SPEED; - ColorCycle.speed_min = RGB_FUSION_GPU_SPEED_SLOWEST; - ColorCycle.speed_max = RGB_FUSION_GPU_SPEED_FASTEST; - ColorCycle.speed = RGB_FUSION_GPU_SPEED_NORMAL; - ColorCycle.color_mode = MODE_COLORS_NONE; + ColorCycle.name = "Color Cycle"; + ColorCycle.value = RGB_FUSION_GPU_MODE_COLOR_CYCLE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + ColorCycle.flags = MODE_FLAG_HAS_SPEED; + ColorCycle.speed_min = RGB_FUSION_GPU_SPEED_SLOWEST; + ColorCycle.speed_max = RGB_FUSION_GPU_SPEED_FASTEST; + ColorCycle.speed = RGB_FUSION_GPU_SPEED_NORMAL; + ColorCycle.color_mode = MODE_COLORS_NONE; modes.push_back(ColorCycle); mode SpectrumCycle; - SpectrumCycle.name = "Spectrum Cycle"; - SpectrumCycle.value = RGB_FUSION_GPU_MODE_SPECTRUM_CYCLE; - SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - SpectrumCycle.speed_min = RGB_FUSION_GPU_SPEED_SLOWEST; - SpectrumCycle.speed_max = RGB_FUSION_GPU_SPEED_FASTEST; - SpectrumCycle.speed = RGB_FUSION_GPU_SPEED_NORMAL; - SpectrumCycle.color_mode = MODE_COLORS_NONE; - SpectrumCycle.brightness_min = RGB_FUSION_GPU_BRIGHTNESS_MIN; - SpectrumCycle.brightness_max = RGB_FUSION_GPU_BRIGHTNESS_MAX; - SpectrumCycle.brightness = RGB_FUSION_GPU_BRIGHTNESS_MAX; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = RGB_FUSION_GPU_MODE_SPECTRUM_CYCLE; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + SpectrumCycle.speed_min = RGB_FUSION_GPU_SPEED_SLOWEST; + SpectrumCycle.speed_max = RGB_FUSION_GPU_SPEED_FASTEST; + SpectrumCycle.speed = RGB_FUSION_GPU_SPEED_NORMAL; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.brightness_min = RGB_FUSION_GPU_BRIGHTNESS_MIN; + SpectrumCycle.brightness_max = RGB_FUSION_GPU_BRIGHTNESS_MAX; + SpectrumCycle.brightness = RGB_FUSION_GPU_BRIGHTNESS_MAX; modes.push_back(SpectrumCycle); SetupZones(); diff --git a/Controllers/GigabyteRGBFusionGPUController/RGBController_GigabyteRGBFusionGPU.h b/Controllers/GigabyteRGBFusionGPUController/RGBController_GigabyteRGBFusionGPU.h index d32a40c8..1de9bf11 100644 --- a/Controllers/GigabyteRGBFusionGPUController/RGBController_GigabyteRGBFusionGPU.h +++ b/Controllers/GigabyteRGBFusionGPUController/RGBController_GigabyteRGBFusionGPU.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_GigabyteRGBFusionGPU.h | -| | -| Generic RGB Interface for OpenRGB | -| Gigabyte RGB Fusion GPU Driver | -| | -| Adam Honse (CalcProgrammer1) 2/23/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GigabyteRGBFusionGPU.h | +| | +| RGBController for Gigabyte Aorus RGB Fusion GPU | +| | +| Adam Honse (CalcProgrammer1) 23 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once @@ -28,7 +30,7 @@ public: void DeviceUpdateMode(); void DeviceSaveMode(); - + private: RGBFusionGPUController* controller; }; diff --git a/Controllers/GigabyteSuperIORGBController/GigabyteSuperIORGBController.cpp b/Controllers/GigabyteSuperIORGBController/GigabyteSuperIORGBController.cpp index 1ac8370c..68c6e588 100644 --- a/Controllers/GigabyteSuperIORGBController/GigabyteSuperIORGBController.cpp +++ b/Controllers/GigabyteSuperIORGBController/GigabyteSuperIORGBController.cpp @@ -1,21 +1,40 @@ -/*------------------------------------------*\ -| GigabyteSuperIORGBController.cpp | -| | -| Ryan Frankcombe (422gRdHuX5uk) 2/11/2020 | -\*------------------------------------------*/ +/*---------------------------------------------------------*\ +| GigabyteSuperIORGBController.cpp | +| | +| Driver for Gigabyte Aorus Super IO motherboard | +| | +| Ryan Frankcombe (422gRdHuX5uk) 11 Sep 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "GigabyteSuperIORGBController.h" #include "super_io.h" -GigabyteSuperIORGBController::GigabyteSuperIORGBController(int sioaddr) +GigabyteSuperIORGBController::GigabyteSuperIORGBController(int sioaddr, std::string dev_name) { gig_sioaddr = sioaddr; + name = dev_name; } GigabyteSuperIORGBController::~GigabyteSuperIORGBController() { } + +std::string GigabyteSuperIORGBController::GetDeviceLocation() +{ + char hex[12]; + snprintf(hex, sizeof(hex), "0x%X", gig_sioaddr); + return("SIO: " + std::string(hex)); +} + +std::string GigabyteSuperIORGBController::GetDeviceName() +{ + return(name); +} + void GigabyteSuperIORGBController::ChipEntry() { /*--------------------------------*\ @@ -31,6 +50,7 @@ void GigabyteSuperIORGBController::ChipEntry() \*_-------------------------------*/ superio_outb(gig_sioaddr, GIGABYTE_SUPERIO_CHIPSELECT_REGISTER_1, GIGABYTE_SUPERIO_CHIPSELECT_VALUE_1); } + void GigabyteSuperIORGBController::ChipExit() { /*-----------------------------------------------------------------------------------*\ @@ -39,6 +59,7 @@ void GigabyteSuperIORGBController::ChipExit() \*_----------------------------------------------------------------------------------*/ superio_outb(gig_sioaddr, GIGABYTE_SUPERIO_CHIPEXIT_REGISTER_1, GIGABYTE_SUPERIO_CHIPEXIT_VALUE_1); } + void GigabyteSuperIORGBController::SetColor(unsigned int red, unsigned int green, unsigned int blue) { /*--------------------------------*\ @@ -70,11 +91,11 @@ void GigabyteSuperIORGBController::SetMode(int new_mode) ChipEntry(); } - /*-----------------------------------------------------*\ + /*-----------------------------------------------------*\ | Write the colors to the color sequence registers | \*-----------------------------------------------------*/ switch (new_mode) - { + { case GIGABYTE_MODE1_STATIC: superio_outb(gig_sioaddr, GIGABYTE_SUPERIO_STATIC_REGISTER_1, GIGABYTE_SUPERIO_STATIC_VALUE_1); superio_outb(gig_sioaddr, GIGABYTE_SUPERIO_STATIC_REGISTER_2, GIGABYTE_SUPERIO_STATIC_VALUE_2); @@ -112,7 +133,8 @@ void GigabyteSuperIORGBController::SetMode(int new_mode) superio_outb(gig_sioaddr, GIGABYTE_SUPERIO_FLASHING_REGISTER_5, GIGABYTE_SUPERIO_FLASHING_VALUE_5); superio_outb(gig_sioaddr, GIGABYTE_SUPERIO_FLASHING_REGISTER_6, GIGABYTE_SUPERIO_FLASHING_VALUE_6); break; - } + } + if(new_mode>=GIGABYTE_MODE1_STATIC && new_mode<=GIGABYTE_MODE1_FLASHING) { ChipExit(); diff --git a/Controllers/GigabyteSuperIORGBController/GigabyteSuperIORGBController.h b/Controllers/GigabyteSuperIORGBController/GigabyteSuperIORGBController.h index 8598e4e8..fe1f875d 100644 --- a/Controllers/GigabyteSuperIORGBController/GigabyteSuperIORGBController.h +++ b/Controllers/GigabyteSuperIORGBController/GigabyteSuperIORGBController.h @@ -1,14 +1,17 @@ -/*-----------------------------------------------*\ -| GigabyteSuperIORGBController.h | -| | -| Definitions and types for Gigabyte SuperIO RGB | -| lighting controller | -| | -| Ryan Frankcombe (422gRdHuX5uk) 9/11/2022 | -\*-----------------------------------------------*/ +/*---------------------------------------------------------*\ +| GigabyteSuperIORGBController.h | +| | +| Driver for Gigabyte Aorus Super IO motherboard | +| | +| Ryan Frankcombe (422gRdHuX5uk) 11 Sep 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include -#pragma once enum { @@ -129,11 +132,11 @@ enum class GigabyteSuperIORGBController { public: - GigabyteSuperIORGBController(int sioaddr); + GigabyteSuperIORGBController(int sioaddr, std::string dev_name); ~GigabyteSuperIORGBController(); - std::string GetDeviceName(); std::string GetDeviceLocation(); + std::string GetDeviceName(); unsigned int GetMode(); void SetMode(int new_mode); @@ -142,5 +145,6 @@ public: void ChipEntry(); void ChipExit(); private: - int gig_sioaddr; + int gig_sioaddr; + std::string name; }; diff --git a/Controllers/GigabyteSuperIORGBController/GigabyteSuperIORGBControllerDetect.cpp b/Controllers/GigabyteSuperIORGBController/GigabyteSuperIORGBControllerDetect.cpp index 0ca0e77c..0092424e 100644 --- a/Controllers/GigabyteSuperIORGBController/GigabyteSuperIORGBControllerDetect.cpp +++ b/Controllers/GigabyteSuperIORGBController/GigabyteSuperIORGBControllerDetect.cpp @@ -1,20 +1,19 @@ -/*-----------------------------------------------*\ -| RGBController_GigabyteSuperIORGB.cpp | -| | -| Detect Gigabyte RGB compatible Super-IO chips | -| | -| Ryan Frankcombe (422gRdHuX5uk ) 9/11/2022 | -\*-----------------------------------------------*/ +/*---------------------------------------------------------*\ +| GigabyteSuperIORGBControllerDetect.cpp | +| | +| Detector for Gigabyte Aorus Super IO motherboard | +| | +| Ryan Frankcombe (422gRdHuX5uk) 11 Sep 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "GigabyteSuperIORGBController.h" -#include "RGBController.h" #include "RGBController_GigabyteSuperIORGB.h" #include "super_io.h" -#include "dependencies/dmiinfo.h" -#include -#include -#include -#include +#include "dmiinfo.h" #define NUM_COMPATIBLE_DEVICES (sizeof(compatible_devices) / sizeof(compatible_devices[0])) @@ -30,13 +29,13 @@ static gig_device compatible_devices[] = void DetectGigabyteSuperIORGBControllers() { - int sio_addrs[2] = {0x2E, 0x4E}; + int sio_addrs[2] = {0x2E, 0x4E}; DMIInfo board; - std::string board_dmi = board.getMainboard(); - std::string manufacturer = board.getManufacturer(); + std::string board_dmi = board.getMainboard(); + std::string manufacturer = board.getManufacturer(); - if (manufacturer != "Gigabyte Technology Co., Ltd.") + if(manufacturer != "Gigabyte Technology Co., Ltd.") { return; } @@ -51,14 +50,13 @@ void DetectGigabyteSuperIORGBControllers() switch(val & SIO_ID_MASK) { - case SIO_ITE688_ID: + case SIO_ITE8688_ID: for(unsigned int i = 0; i < NUM_COMPATIBLE_DEVICES; i++) { - if (board_dmi.find(std::string(compatible_devices[i].name)) != std::string::npos) + if(board_dmi.find(std::string(compatible_devices[i].name)) != std::string::npos) { - GigabyteSuperIORGBController* controller = new GigabyteSuperIORGBController(sioaddr); + GigabyteSuperIORGBController* controller = new GigabyteSuperIORGBController(sioaddr, "Gigabyte " + board_dmi); RGBController_GigabyteSuperIORGB* rgb_controller = new RGBController_GigabyteSuperIORGB(controller); - rgb_controller->name = "Gigabyte " + board_dmi; ResourceManager::get()->RegisterRGBController(rgb_controller); break; diff --git a/Controllers/GigabyteSuperIORGBController/RGBController_GigabyteSuperIORGB.cpp b/Controllers/GigabyteSuperIORGBController/RGBController_GigabyteSuperIORGB.cpp index 8e34bc4a..2f6d0c3c 100644 --- a/Controllers/GigabyteSuperIORGBController/RGBController_GigabyteSuperIORGB.cpp +++ b/Controllers/GigabyteSuperIORGBController/RGBController_GigabyteSuperIORGB.cpp @@ -1,10 +1,13 @@ -/*-------------------------------------------*\ -| RGBController_GigabyteSuperIORGB.cpp | -| | -| Generic RGB Interface for Gigabyte RGB | -| | -| Ryan Frankcombe (422gRdHuX5uk ) 9/11/2022 | -\*-------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GigabyteSuperIORGB.cpp | +| | +| RGBController for Gigabyte Aorus Super IO motherboard | +| | +| Ryan Frankcombe (422gRdHuX5uk) 11 Sep 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_GigabyteSuperIORGB.h" @@ -67,7 +70,7 @@ To add this chipset you will need to first add it to the SuperIO definitions file, which is named super_io.h like below ```c++ - #define SIO_ITE688_ID 0x8688 // Device ID for ITE8688 (8688) + #define SIO_ITE8688_ID 0x8688 // Device ID for ITE8688 (8688) #define SIO_NEWCHIPSETMODEL_ID 0xFOUNDHEXIDECIMALVALUE // Device ID for NEWCHIPSETMODEL (FOUNDHEXIDECIMALVALUE) ``` @@ -77,53 +80,54 @@ ```c++ switch (val & SIO_ID_MASK) { - case SIO_ITE688_ID: + case SIO_ITE8688_ID: case SIO_NEWCHIPSETMODEL_ID: ``` \*-------------------------------------------------------------------*/ RGBController_GigabyteSuperIORGB::RGBController_GigabyteSuperIORGB(GigabyteSuperIORGBController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Gigabyte SuperIO Compatible Motherboard"; - vendor = "Gigabyte"; - type = DEVICE_TYPE_MOTHERBOARD; - description = "Gigabyte SuperIO RGB Device"; + name = controller->GetDeviceName(); + vendor = "Gigabyte"; + type = DEVICE_TYPE_MOTHERBOARD; + description = "Gigabyte SuperIO RGB Device"; + location = controller->GetDeviceLocation(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + 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); mode Static; - Static.name = "Static"; - Static.value = GIGABYTE_MODE1_STATIC; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Static.name = "Static"; + Static.value = GIGABYTE_MODE1_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Static.color_mode = MODE_COLORS_PER_LED; modes.push_back(Static); mode Rainbow; - Rainbow.name = "Rainbow"; - Rainbow.value = GIGABYTE_MODE1_RAINBOW; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Rainbow.name = "Rainbow"; + Rainbow.value = GIGABYTE_MODE1_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Rainbow.color_mode = MODE_COLORS_PER_LED; modes.push_back(Rainbow); mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = GIGABYTE_MODE1_BREATHING; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Breathing.name = "Breathing"; + Breathing.value = GIGABYTE_MODE1_BREATHING; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Breathing.color_mode = MODE_COLORS_PER_LED; modes.push_back(Breathing); mode Flashing; - Flashing.name = "Flashing"; - Flashing.value = GIGABYTE_MODE1_FLASHING; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Flashing.name = "Flashing"; + Flashing.value = GIGABYTE_MODE1_FLASHING; + Flashing.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Flashing.color_mode = MODE_COLORS_PER_LED; modes.push_back(Flashing); SetupZones(); @@ -146,7 +150,7 @@ void RGBController_GigabyteSuperIORGB::SetupZones() zones.push_back(gig_zone); led gig_led; - gig_led.name = "LED_C1"; + gig_led.name = "LED_C1"; leds.push_back(gig_led); SetupColors(); diff --git a/Controllers/GigabyteSuperIORGBController/RGBController_GigabyteSuperIORGB.h b/Controllers/GigabyteSuperIORGBController/RGBController_GigabyteSuperIORGB.h index 328bf534..8bb79535 100644 --- a/Controllers/GigabyteSuperIORGBController/RGBController_GigabyteSuperIORGB.h +++ b/Controllers/GigabyteSuperIORGBController/RGBController_GigabyteSuperIORGB.h @@ -1,12 +1,16 @@ -/*------------------------------------------*\ -| RGBController_GigabyteSuperIORGB.h | -| | -| Generic RGB Interface for Gigabyte RGB | -| | -| Ryan Frankcombe (422gRdHuX5uk) 9/11/2022 | -\*------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_GigabyteSuperIORGB.h | +| | +| RGBController for Gigabyte Aorus Super IO motherboard | +| | +| Ryan Frankcombe (422gRdHuX5uk) 11 Sep 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "GigabyteSuperIORGBController.h" diff --git a/Controllers/GoveeController/GoveeController.cpp b/Controllers/GoveeController/GoveeController.cpp new file mode 100644 index 00000000..287da302 --- /dev/null +++ b/Controllers/GoveeController/GoveeController.cpp @@ -0,0 +1,321 @@ +/*---------------------------------------------------------*\ +| GoveeController.cpp | +| | +| Driver for Govee wireless lighting devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 01 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "base64.hpp" +#include "GoveeController.h" + +using json = nlohmann::json; +using namespace std::chrono_literals; + +base64::byte CalculateXorChecksum(std::vector packet) +{ + base64::byte checksum = 0; + + for(unsigned int i = 0; i < packet.size(); i++) + { + checksum ^= packet[i]; + } + + return(checksum); +} + +GoveeController::GoveeController(std::string ip) +{ + /*-----------------------------------------------------*\ + | Fill in location string with device's IP address | + \*-----------------------------------------------------*/ + ip_address = ip; + + /*-----------------------------------------------------*\ + | Register callback for receiving broadcasts | + \*-----------------------------------------------------*/ + RegisterReceiveBroadcastCallback(this); + + broadcast_received = false; + + /*-----------------------------------------------------*\ + | Request device information | + \*-----------------------------------------------------*/ + SendScan(); + + /*-----------------------------------------------------*\ + | Wait up to 5s for device information to be received | + \*-----------------------------------------------------*/ + for(unsigned int wait_count = 0; wait_count < 500; wait_count++) + { + if(broadcast_received) + { + break; + } + + std::this_thread::sleep_for(10ms); + } + + /*-----------------------------------------------------*\ + | Open a UDP client sending to the Govee device IP, | + | port 4003 | + \*-----------------------------------------------------*/ + port.udp_client(ip_address.c_str(), "4003"); +} + +GoveeController::~GoveeController() +{ + UnregisterReceiveBroadcastCallback(this); +} + +std::string GoveeController::GetLocation() +{ + return("IP: " + ip_address); +} + +std::string GoveeController::GetSku() +{ + return(sku); +} + +std::string GoveeController::GetVersion() +{ + return("BLE Hardware Version: " + bleVersionHard + "\r\n" + + "BLE Software Version: " + bleVersionSoft + "\r\n" + + "WiFi Hardware Version: " + wifiVersionHard + "\r\n" + + "WiFI Software Version: " + wifiVersionSoft + "\r\n"); +} + +void GoveeController::ReceiveBroadcast(char* recv_buf, int size) +{ + if(broadcast_received) + { + return; + } + + /*-----------------------------------------------------*\ + | Responses are not null-terminated, so add termination | + \*-----------------------------------------------------*/ + recv_buf[size] = '\0'; + + /*-----------------------------------------------------*\ + | Convert null-terminated response to JSON | + \*-----------------------------------------------------*/ + json response = json::parse(recv_buf); + + /*-----------------------------------------------------*\ + | Check if the response contains the method name | + \*-----------------------------------------------------*/ + if(response.contains("msg")) + { + /*-------------------------------------------------*\ + | Handle responses for scan command | + | This command's response should contain a msg | + | object containing a data member with ip, device, | + | sku, among others. | + \*-------------------------------------------------*/ + if(response["msg"].contains("cmd")) + { + if(response["msg"]["cmd"] == "scan") + { + if(response["msg"].contains("data")) + { + if(response["msg"]["data"].contains("ip")) + { + if(response["msg"]["data"]["ip"] == ip_address) + { + if(response["msg"]["data"].contains("sku")) + { + sku = response["msg"]["data"]["sku"]; + } + + if(response["msg"]["data"].contains("bleVersionHard")) + { + bleVersionHard = response["msg"]["data"]["bleVersionHard"]; + } + + if(response["msg"]["data"].contains("bleVersionSoft")) + { + bleVersionSoft = response["msg"]["data"]["bleVersionSoft"]; + } + + if(response["msg"]["data"].contains("wifiVersionHard")) + { + wifiVersionHard = response["msg"]["data"]["wifiVersionHard"]; + } + + if(response["msg"]["data"].contains("wifiVersionSoft")) + { + wifiVersionSoft = response["msg"]["data"]["wifiVersionSoft"]; + } + + broadcast_received = true; + } + } + } + } + } + } +} + +void GoveeController::SetColor(unsigned char red, unsigned char green, unsigned char blue) +{ + json command; + + command["msg"]["cmd"] = "colorwc"; + command["msg"]["data"]["color"]["r"] = red; + command["msg"]["data"]["color"]["g"] = green; + command["msg"]["data"]["color"]["b"] = blue; + command["msg"]["data"]["colorTemInKelvin"] = "0"; + + /*-----------------------------------------------------*\ + | Convert the JSON object to a string and write it | + \*-----------------------------------------------------*/ + std::string command_str = command.dump(); + + port.udp_write((char *)command_str.c_str(), (int)command_str.length() + 1); +} + +void GoveeController::SendRazerData(RGBColor* colors, unsigned int size) +{ + std::vector pkt = { 0xBB, 0x00, 0x00, 0xB0, 0x00, 0x00 }; + json command; + + pkt[2] = 2 + (3 * size); + pkt[5] = size; + pkt.resize(6 + (3 * size)); + + for(std::size_t led_idx = 0; led_idx < size; led_idx++) + { + pkt[6 + (led_idx * 3)] = RGBGetRValue(colors[led_idx]); + pkt[7 + (led_idx * 3)] = RGBGetGValue(colors[led_idx]); + pkt[8 + (led_idx * 3)] = RGBGetBValue(colors[led_idx]); + } + + pkt.push_back(CalculateXorChecksum(pkt)); + + command["msg"]["cmd"] = "razer"; + command["msg"]["data"]["pt"] = base64::encode(pkt); + + /*-----------------------------------------------------*\ + | Convert the JSON object to a string and write it | + \*-----------------------------------------------------*/ + std::string command_str = command.dump(); + + port.udp_write((char *)command_str.c_str(), (int)command_str.length() + 1); +} + +void GoveeController::SendRazerDisable() +{ + const std::vector pkt = { 0xBB, 0x00, 0x01, 0xB1, 0x00, 0x0B }; + json command; + + command["msg"]["cmd"] = "razer"; + command["msg"]["data"]["pt"] = base64::encode(pkt); + + /*-----------------------------------------------------*\ + | Convert the JSON object to a string and write it | + \*-----------------------------------------------------*/ + std::string command_str = command.dump(); + + port.udp_write((char *)command_str.c_str(), (int)command_str.length() + 1); +} + +void GoveeController::SendRazerEnable() +{ + const std::vector pkt = { 0xBB, 0x00, 0x01, 0xB1, 0x01, 0x0A }; + json command; + + command["msg"]["cmd"] = "razer"; + command["msg"]["data"]["pt"] = base64::encode(pkt); + + /*-----------------------------------------------------*\ + | Convert the JSON object to a string and write it | + \*-----------------------------------------------------*/ + std::string command_str = command.dump(); + + port.udp_write((char *)command_str.c_str(), (int)command_str.length() + 1); +} + +void GoveeController::SendScan() +{ + json command; + + command["msg"]["cmd"] = "scan"; + command["msg"]["data"]["account_topic"] = "GA/123456789"; + + /*-----------------------------------------------------*\ + | Convert the JSON object to a string and write it | + \*-----------------------------------------------------*/ + std::string command_str = command.dump(); + + broadcast_port.udp_write((char *)command_str.c_str(), (int)command_str.length() + 1); +} + +/*---------------------------------------------------------*\ +| Static class members for shared broadcast receiver | +\*---------------------------------------------------------*/ +net_port GoveeController::broadcast_port; +std::vector GoveeController::callbacks; +std::thread* GoveeController::ReceiveThread; +std::atomic GoveeController::ReceiveThreadRun; + +void GoveeController::ReceiveBroadcastThreadFunction() +{ + char recv_buf[1024]; + + broadcast_port.set_receive_timeout(1, 0); + + while(ReceiveThreadRun.load()) + { + /*-------------------------------------------------*\ + | Receive up to 1024 bytes from the device with a | + | 1s timeout | + \*-------------------------------------------------*/ + int size = broadcast_port.udp_listen(recv_buf, 1024); + + /*-------------------------------------------------*\ + | If data was received, loop through registered | + | callback controllers and call the | + | ReceiveBroadcast function for the controller | + | matching the received data | + | | + | NOTE: As implemented, it doesn't actually match | + | the intended controller and just calls all | + | registered controllers. As they are all called | + | sequence, this should work, but if parallel calls | + | are ever needed, receives should be filtered by | + | IP address | + \*-------------------------------------------------*/ + if(size > 0) + { + for(std::size_t callback_idx = 0; callback_idx < callbacks.size(); callback_idx++) + { + GoveeController* controller = callbacks[callback_idx]; + + controller->ReceiveBroadcast(recv_buf, size); + } + } + } +} + +void GoveeController::RegisterReceiveBroadcastCallback(GoveeController* controller_ptr) +{ + callbacks.push_back(controller_ptr); +} + +void GoveeController::UnregisterReceiveBroadcastCallback(GoveeController* controller_ptr) +{ + for(std::size_t callback_idx = 0; callback_idx < callbacks.size(); callback_idx++) + { + if(callbacks[callback_idx] == controller_ptr) + { + callbacks.erase(callbacks.begin() + callback_idx); + break; + } + } +} diff --git a/Controllers/GoveeController/GoveeController.h b/Controllers/GoveeController/GoveeController.h new file mode 100644 index 00000000..3f552104 --- /dev/null +++ b/Controllers/GoveeController/GoveeController.h @@ -0,0 +1,71 @@ +/*---------------------------------------------------------*\ +| GoveeController.h | +| | +| Driver for Govee wireless lighting devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 01 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" +#include "net_port.h" + +class GoveeController +{ +public: + GoveeController(std::string ip); + ~GoveeController(); + + std::string GetLocation(); + std::string GetSku(); + std::string GetVersion(); + + void ReceiveBroadcast(char* recv_buf, int size); + + void SendRazerData(RGBColor* colors, unsigned int size); + void SendRazerDisable(); + void SendRazerEnable(); + + void SendScan(); + + void SetColor(unsigned char red, unsigned char green, unsigned char blue); + +private: + std::string firmware_version; + std::string ip_address; + std::string module_name; + std::string module_mac; + + std::string sku; + std::string bleVersionHard; + std::string bleVersionSoft; + std::string wifiVersionHard; + std::string wifiVersionSoft; + + bool broadcast_received; + + net_port port; + +public: + /*-----------------------------------------------------*\ + | One receive thread is shared among all instances of | + | GoveeController, so the receive thread function is | + | static and the thread is initialized in the detector | + | if any GoveeControllers are created. | + \*-----------------------------------------------------*/ + static net_port broadcast_port; + static std::vector callbacks; + static std::thread* ReceiveThread; + static std::atomic ReceiveThreadRun; + + static void ReceiveBroadcastThreadFunction(); + static void RegisterReceiveBroadcastCallback(GoveeController* controller_ptr); + static void UnregisterReceiveBroadcastCallback(GoveeController* controller_ptr); +}; diff --git a/Controllers/GoveeController/GoveeControllerDetect.cpp b/Controllers/GoveeController/GoveeControllerDetect.cpp new file mode 100644 index 00000000..e949b99a --- /dev/null +++ b/Controllers/GoveeController/GoveeControllerDetect.cpp @@ -0,0 +1,92 @@ +/*---------------------------------------------------------*\ +| GoveeControllerDetect.cpp | +| | +| Detector for Govee wireless lighting devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 01 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include "Detector.h" +#include "GoveeController.h" +#include "RGBController.h" +#include "RGBController_Govee.h" +#include "SettingsManager.h" + +/******************************************************************************************\ +* * +* DetectGoveeControllers * +* * +* Detect Govee devices * +* * +\******************************************************************************************/ + +void DetectGoveeControllers() +{ + json govee_settings; + + /*-----------------------------------------------------*\ + | Get Govee settings from settings manager | + \*-----------------------------------------------------*/ + govee_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("GoveeDevices"); + + /*-----------------------------------------------------*\ + | If the Govee settings contains devices, process | + \*-----------------------------------------------------*/ + if(govee_settings.contains("devices")) + { + GoveeController::ReceiveThreadRun = false; + + if(govee_settings["devices"].size() > 0) + { + /*---------------------------------------------*\ + | Open a UDP client sending to and receiving | + | from the Govee Multicast IP, send port 4001 | + | and receive port 4002 | + \*---------------------------------------------*/ + GoveeController::broadcast_port.udp_client("239.255.255.250", "4001", "4002"); + GoveeController::broadcast_port.udp_join_multicast_group("239.255.255.250"); + + /*---------------------------------------------*\ + | Start a thread to handle responses received | + | from the Govee device | + \*---------------------------------------------*/ + GoveeController::ReceiveThreadRun = true; + GoveeController::ReceiveThread = new std::thread(&GoveeController::ReceiveBroadcastThreadFunction); + } + + for(unsigned int device_idx = 0; device_idx < govee_settings["devices"].size(); device_idx++) + { + if(govee_settings["devices"][device_idx].contains("ip")) + { + std::string govee_ip = govee_settings["devices"][device_idx]["ip"]; + + GoveeController* controller = new GoveeController(govee_ip); + RGBController_Govee* rgb_controller = new RGBController_Govee(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + } + + /*-------------------------------------------------*\ + | All controllers have been created, the broadcast | + | receiver thread is no longer needed and can be | + | shut down | + \*-------------------------------------------------*/ + if(GoveeController::ReceiveThreadRun) + { + GoveeController::ReceiveThreadRun = false; + GoveeController::ReceiveThread->join(); + delete GoveeController::ReceiveThread; + GoveeController::broadcast_port.tcp_close(); + } + } + +} /* DetectGoveeControllers() */ + +REGISTER_DETECTOR("Govee", DetectGoveeControllers); diff --git a/Controllers/GoveeController/RGBController_Govee.cpp b/Controllers/GoveeController/RGBController_Govee.cpp new file mode 100644 index 00000000..0ab0456a --- /dev/null +++ b/Controllers/GoveeController/RGBController_Govee.cpp @@ -0,0 +1,142 @@ +/*---------------------------------------------------------*\ +| RGBController_Govee.cpp | +| | +| RGBController for Govee wireless lighting devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 27 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RGBController_Govee.h" + +using namespace std::chrono_literals; + +static std::map govee_led_counts +{ + { "H619A", 20 }, + { "H70B1", 20 }, +}; + +RGBController_Govee::RGBController_Govee(GoveeController* controller_ptr) +{ + controller = controller_ptr; + + name = "Govee " + controller->GetSku(); + vendor = "Govee"; + type = DEVICE_TYPE_LIGHT; + description = "Govee Device"; + location = controller->GetLocation(); + version = controller->GetVersion(); + + mode Static; + Static.name = "Static"; + Static.value = 1; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.resize(1); + modes.push_back(Static); + + 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(); + + keepalive_thread_run = 1; + keepalive_thread = new std::thread(&RGBController_Govee::KeepaliveThread, this); +} + +RGBController_Govee::~RGBController_Govee() +{ + keepalive_thread_run = 0; + keepalive_thread->join(); + delete keepalive_thread; + + delete controller; +} + +void RGBController_Govee::SetupZones() +{ + unsigned int led_count = govee_led_counts[controller->GetSku()]; + + zone strip; + strip.name = "Govee Strip"; + strip.type = ZONE_TYPE_LINEAR; + strip.leds_count = led_count; + strip.leds_min = led_count; + strip.leds_max = led_count; + strip.matrix_map = NULL; + zones.push_back(strip); + + for(std::size_t led_idx = 0; led_idx < strip.leds_count; led_idx++) + { + led strip_led; + strip_led.name = "Govee LED"; + leds.push_back(strip_led); + } + + SetupColors(); +} + +void RGBController_Govee::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_Govee::DeviceUpdateLEDs() +{ + last_update_time = std::chrono::steady_clock::now(); + + if(modes[active_mode].color_mode == MODE_COLORS_PER_LED) + { + controller->SendRazerData(&colors[0], (unsigned int)colors.size()); + } +} + +void RGBController_Govee::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_Govee::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_Govee::DeviceUpdateMode() +{ + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + unsigned char red = RGBGetRValue(modes[active_mode].colors[0]); + unsigned char grn = RGBGetGValue(modes[active_mode].colors[0]); + unsigned char blu = RGBGetBValue(modes[active_mode].colors[0]); + controller->SetColor(red, grn, blu); + } + else + { + controller->SendRazerEnable(); + DeviceUpdateLEDs(); + } +} + +void RGBController_Govee::KeepaliveThread() +{ + while(keepalive_thread_run.load()) + { + if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::seconds(30)) + { + DeviceUpdateLEDs(); + } + std::this_thread::sleep_for(10s); + } +} diff --git a/Controllers/GoveeController/RGBController_Govee.h b/Controllers/GoveeController/RGBController_Govee.h new file mode 100644 index 00000000..6c1809ba --- /dev/null +++ b/Controllers/GoveeController/RGBController_Govee.h @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| RGBController_Govee.h | +| | +| RGBController for Govee wireless lighting devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 01 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "GoveeController.h" + +class RGBController_Govee : public RGBController +{ +public: + RGBController_Govee(GoveeController* controller_ptr); + ~RGBController_Govee(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + void KeepaliveThread(); + +private: + GoveeController* controller; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::chrono::time_point last_update_time; +}; diff --git a/Controllers/GoveeController/base64.hpp b/Controllers/GoveeController/base64.hpp new file mode 100644 index 00000000..ffffae17 --- /dev/null +++ b/Controllers/GoveeController/base64.hpp @@ -0,0 +1,111 @@ +#pragma once + +#include +#include +#include +#include + +namespace base64 +{ + inline static const char kEncodeLookup[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + inline static const char kPadCharacter = '='; + + using byte = std::uint8_t; + + inline std::string encode(const std::vector& input) + { + std::string encoded; + encoded.reserve(((input.size() / 3) + (input.size() % 3 > 0)) * 4); + + std::uint32_t temp{}; + auto it = input.begin(); + + for(std::size_t i = 0; i < input.size() / 3; ++i) + { + temp = (*it++) << 16; + temp += (*it++) << 8; + temp += (*it++); + encoded.append(1, kEncodeLookup[(temp & 0x00FC0000) >> 18]); + encoded.append(1, kEncodeLookup[(temp & 0x0003F000) >> 12]); + encoded.append(1, kEncodeLookup[(temp & 0x00000FC0) >> 6 ]); + encoded.append(1, kEncodeLookup[(temp & 0x0000003F) ]); + } + + switch(input.size() % 3) + { + case 1: + temp = (*it++) << 16; + encoded.append(1, kEncodeLookup[(temp & 0x00FC0000) >> 18]); + encoded.append(1, kEncodeLookup[(temp & 0x0003F000) >> 12]); + encoded.append(2, kPadCharacter); + break; + case 2: + temp = (*it++) << 16; + temp += (*it++) << 8; + encoded.append(1, kEncodeLookup[(temp & 0x00FC0000) >> 18]); + encoded.append(1, kEncodeLookup[(temp & 0x0003F000) >> 12]); + encoded.append(1, kEncodeLookup[(temp & 0x00000FC0) >> 6 ]); + encoded.append(1, kPadCharacter); + break; + } + + return encoded; + } + + inline std::vector decode(const std::string& input) + { + if(input.length() % 4) + throw std::runtime_error("Invalid base64 length!"); + + std::size_t padding{}; + + if(input.length()) + { + if(input[input.length() - 1] == kPadCharacter) padding++; + if(input[input.length() - 2] == kPadCharacter) padding++; + } + + std::vector decoded; + decoded.reserve(((input.length() / 4) * 3) - padding); + + std::uint32_t temp{}; + auto it = input.begin(); + + while(it < input.end()) + { + for(std::size_t i = 0; i < 4; ++i) + { + temp <<= 6; + if (*it >= 0x41 && *it <= 0x5A) temp |= *it - 0x41; + else if(*it >= 0x61 && *it <= 0x7A) temp |= *it - 0x47; + else if(*it >= 0x30 && *it <= 0x39) temp |= *it + 0x04; + else if(*it == 0x2B) temp |= 0x3E; + else if(*it == 0x2F) temp |= 0x3F; + else if(*it == kPadCharacter) + { + switch(input.end() - it) + { + case 1: + decoded.push_back((temp >> 16) & 0x000000FF); + decoded.push_back((temp >> 8 ) & 0x000000FF); + return decoded; + case 2: + decoded.push_back((temp >> 10) & 0x000000FF); + return decoded; + default: + throw std::runtime_error("Invalid padding in base64!"); + } + } + else throw std::runtime_error("Invalid character in base64!"); + + ++it; + } + + decoded.push_back((temp >> 16) & 0x000000FF); + decoded.push_back((temp >> 8 ) & 0x000000FF); + decoded.push_back((temp ) & 0x000000FF); + } + + return decoded; + } +} diff --git a/Controllers/HPOmen30LController/HPOmen30LController.cpp b/Controllers/HPOmen30LController/HPOmen30LController.cpp index b3b088b8..6b2dcf6c 100644 --- a/Controllers/HPOmen30LController/HPOmen30LController.cpp +++ b/Controllers/HPOmen30LController/HPOmen30LController.cpp @@ -1,14 +1,20 @@ -/*-----------------------------------------*\ -| HPOmen30LController.cpp | -| | -| Driver for HP Omen 30L RGB lighting | -| controller | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| HPOmen30LController.cpp | +| | +| Driver for HP Omen 30L | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "HPOmen30LController.h" #include #include #include +#include "HPOmen30LController.h" + +#define HP_OMEN_30L_BUFFER_SIZE 58 +#define HP_OMEN_30L_VERSION_ID 0x12 +#define HP_OMEN_30L_MAX_BRIGHTNESS 0x64 HPOmen30LController::HPOmen30LController(hid_device* dev_handle, const char* path) { @@ -21,30 +27,50 @@ HPOmen30LController::HPOmen30LController(hid_device* dev_handle, const char* pat logo.value = HP_OMEN_30L_LOGO_ZONE; logo.mode = HP_OMEN_30L_DIRECT; logo.speed = HP_OMEN_30L_SPEED_MED; - logo.brightness = 0x64; + logo.brightness = HP_OMEN_30L_MAX_BRIGHTNESS; hp_zones.push_back(logo); hp_zone bar; bar.value = HP_OMEN_30L_BAR_ZONE; bar.mode = HP_OMEN_30L_DIRECT; bar.speed = HP_OMEN_30L_SPEED_MED; - bar.brightness = 0x64; + bar.brightness = HP_OMEN_30L_MAX_BRIGHTNESS; hp_zones.push_back(bar); hp_zone fan; fan.value = HP_OMEN_30L_FAN_ZONE; fan.mode = HP_OMEN_30L_DIRECT; fan.speed = HP_OMEN_30L_SPEED_MED; - fan.brightness = 0x64; + fan.brightness = HP_OMEN_30L_MAX_BRIGHTNESS; hp_zones.push_back(fan); hp_zone cpu; cpu.value = HP_OMEN_30L_CPU_ZONE; cpu.mode = HP_OMEN_30L_DIRECT; cpu.speed = HP_OMEN_30L_SPEED_MED; - cpu.brightness = 0x64; + cpu.brightness = HP_OMEN_30L_MAX_BRIGHTNESS; hp_zones.push_back(cpu); + hp_zone botFan; + botFan.value = HP_OMEN_30L_BOT_FAN_ZONE; + botFan.mode = HP_OMEN_30L_DIRECT; + botFan.speed = HP_OMEN_30L_SPEED_MED; + botFan.brightness = HP_OMEN_30L_MAX_BRIGHTNESS; + hp_zones.push_back(botFan); + + hp_zone midFan; + midFan.value = HP_OMEN_30L_MID_FAN_ZONE; + midFan.mode = HP_OMEN_30L_DIRECT; + midFan.speed = HP_OMEN_30L_SPEED_MED; + midFan.brightness = HP_OMEN_30L_MAX_BRIGHTNESS; + hp_zones.push_back(midFan); + + hp_zone topFan; + topFan.value = HP_OMEN_30L_TOP_FAN_ZONE; + topFan.mode = HP_OMEN_30L_DIRECT; + topFan.speed = HP_OMEN_30L_SPEED_MED; + topFan.brightness = HP_OMEN_30L_MAX_BRIGHTNESS; + hp_zones.push_back(topFan); } HPOmen30LController::~HPOmen30LController() @@ -95,77 +121,88 @@ void HPOmen30LController::SetZoneColor(int zone, std::vector colors) void HPOmen30LController::SendZoneUpdate(int zone, std::vector colors) { - unsigned char usb_buf[] = - { - 0x00, 0x00, // [0x00-0x01] - 0x12, 0x05, 0x00, 0x00, // [0x02-0x05] - 0x00, 0x00, 0x00, 0x00, // [0x06-0x09] - 0x00, 0x00, 0x00, 0x00, // [0x0A-0x0D] - 0x00, 0x00, 0x00, 0x00, // [0x0E-0x11] - 0x00, 0x00, 0x00, 0x00, // [0x12-0x15] - 0x00, 0x00, 0x00, 0x00, // [0x16-0x19] - 0x00, 0x00, 0x00, 0x00, // [0x1A-0x1D] - 0x00, 0x00, 0x00, 0x00, // [0x1E-0x21] - 0x00, 0x00, 0x00, 0x00, // [0x22-0x25] - 0x00, 0x00, 0x00, 0x00, // [0x26-0x29] - 0x00, 0x00, 0x00, 0x00, // [0x2A-0x2D] - 0x00, 0x00, 0x00, 0x00, // [0x2E-0x31] - 0x00, 0x00, 0x00, 0x00, // [0x32-0x35] Always 0x00*4 - 0x00, 0x00, 0x00, 0x00 // [0x36-0x39] zone / 0x01 / theme / speed - }; + unsigned char usb_buf[HP_OMEN_30L_BUFFER_SIZE] = {}; // zero-initialize array + // 0x00 - 0x01: Unknown + // 0x02: Version ID (HP_OMEN_30L_VERSION_ID) + // 0x03: Lighting mode (static, direct, off, breathing, cycle, blinking, ...) + // 0x04: Total color count (only different from 1 in modes with changing colors) + // 0x05: Current color number (see above, used to set the different colors, one at a time, starting at 1) + // 0x06 - 0x07: Unknown + // 0x08 - 0x23: Used to control the RGB (static) or RGBA (direct) of the first seven LED zones + // 0x24 - 0x2f: Unknown, probably also used for RGB/RGBA control if there's support up to 10 zones + // 0x30: Brightness + // 0x31: Type (static=0x02, direct=0x04, changing colors=0x0A) + // 0x32 - 0x35: Unknown + // 0x36: Zone to update (can only update one at a time) + // 0x37: Power mode to update (on, suspend) + // 0x38: Theme (either 0 to use the colors set in 0x04/0x05, or the ID of a predefined theme) + // 0x39: Color change speed (only relevant for modes with changing colors) + usb_buf[0x02] = HP_OMEN_30L_VERSION_ID; usb_buf[0x36] = hp_zones[zone].value; - if(hp_zones[zone].mode != HP_OMEN_30L_DIRECT) - { - hid_write(dev, usb_buf, 58); - } - - usb_buf[0x37] = 0x01; - usb_buf[0x39] = hp_zones[zone].speed; + // The Omen controller allows setting different modes for when the computer is powered on + // vs when the computer is suspended. + // Because the OpenRGB UI does not allow such a choice, we're only changing the powered on mode. + // If this ever changes, we need to take the user choice into consideration (HP_OMEN_30L_POWER_SUSPEND) + usb_buf[0x37] = HP_OMEN_30L_POWER_ON; usb_buf[0x03] = hp_zones[zone].mode; + + if (hp_zones[zone].mode == HP_OMEN_30L_OFF) + { + hid_write(dev, usb_buf, HP_OMEN_30L_BUFFER_SIZE); + return; + } + usb_buf[0x30] = hp_zones[zone].brightness; - + int index = hp_zones[zone].value - 1; if(hp_zones[zone].mode == HP_OMEN_30L_DIRECT) { - usb_buf[0x31] = HP_OMEN_30L_DIRECT; - usb_buf[0x04] = 0x01; - } - else - { - usb_buf[0x31] = 0x0A; - } + usb_buf[0x31] = HP_OMEN_30L_DIRECT; + usb_buf[0x04] = 0x01; + usb_buf[0x05] = 0x01; + usb_buf[0x08 + index * 4] = HP_OMEN_30L_MAX_BRIGHTNESS; + usb_buf[0x09 + index * 4] = RGBGetRValue(colors[zone]); + usb_buf[0x0A + index * 4] = RGBGetGValue(colors[zone]); + usb_buf[0x0B + index * 4] = RGBGetBValue(colors[zone]); - if(hp_zones[zone].mode == HP_OMEN_30L_DIRECT) - { - usb_buf[0x08] = usb_buf[0x0C] = usb_buf[0x10] = usb_buf[0x14] = 0x64; - usb_buf[0x09] = usb_buf[0x0D] = usb_buf[0x11] = usb_buf[0x15] = RGBGetRValue(colors[zone]); - usb_buf[0x0A] = usb_buf[0x0E] = usb_buf[0x12] = usb_buf[0x16] = RGBGetGValue(colors[zone]); - usb_buf[0x0B] = usb_buf[0x0F] = usb_buf[0x13] = usb_buf[0x17] = RGBGetBValue(colors[zone]); - - hid_write(dev, usb_buf, 58); + hid_write(dev, usb_buf, HP_OMEN_30L_BUFFER_SIZE); } else if(hp_zones[zone].mode == HP_OMEN_30L_STATIC) { - usb_buf[0x08] = usb_buf[0x0B] = usb_buf[0x0E] = usb_buf[0x11] = RGBGetRValue(colors[zone]); - usb_buf[0x09] = usb_buf[0x0C] = usb_buf[0x0F] = usb_buf[0x12] = RGBGetGValue(colors[zone]); - usb_buf[0x0A] = usb_buf[0x0D] = usb_buf[0x10] = usb_buf[0x13] = RGBGetBValue(colors[zone]); + usb_buf[0x31] = 0x02; + usb_buf[0x04] = 0x01; + usb_buf[0x05] = 0x01; + usb_buf[0x08 + index * 3] = RGBGetRValue(colors[zone]); + usb_buf[0x09 + index * 3] = RGBGetGValue(colors[zone]); + usb_buf[0x0A + index * 3] = RGBGetBValue(colors[zone]); - hid_write(dev, usb_buf, 58); + hid_write(dev, usb_buf, HP_OMEN_30L_BUFFER_SIZE); } else { - usb_buf[0x04] = colors.size(); + usb_buf[0x31] = 0x0A; + usb_buf[0x39] = hp_zones[zone].speed; - for(unsigned int i = 0; i < colors.size(); i++) + // Theme is custom by default, but if we could select a theme through the UI, + // we would set it in usb_buf[0x38] here and ignore the custom colors vector + unsigned char theme = HP_OMEN_30L_THEME_CUSTOM; + usb_buf[0x38] = theme; + if (theme == HP_OMEN_30L_THEME_CUSTOM) { - usb_buf[0x05] = i + 1; - - usb_buf[0x08] = usb_buf[0x0B] = usb_buf[0x0E] = usb_buf[0x11] = RGBGetRValue(colors[i]); - usb_buf[0x09] = usb_buf[0x0C] = usb_buf[0x0F] = usb_buf[0x12] = RGBGetGValue(colors[i]); - usb_buf[0x0A] = usb_buf[0x0D] = usb_buf[0x10] = usb_buf[0x13] = RGBGetBValue(colors[i]); - - hid_write(dev, usb_buf, 58); + usb_buf[0x04] = (unsigned char)colors.size(); + for(unsigned int i = 0; i < (unsigned int)colors.size(); i++) + { + usb_buf[0x05] = i + 1; + usb_buf[0x08 + index * 3] = RGBGetRValue(colors[i]); + usb_buf[0x09 + index * 3] = RGBGetGValue(colors[i]); + usb_buf[0x0A + index * 3] = RGBGetBValue(colors[i]); + hid_write(dev, usb_buf, HP_OMEN_30L_BUFFER_SIZE); + } + } + else + { + hid_write(dev, usb_buf, HP_OMEN_30L_BUFFER_SIZE); } } } diff --git a/Controllers/HPOmen30LController/HPOmen30LController.h b/Controllers/HPOmen30LController/HPOmen30LController.h index ae397952..5cddd6b2 100644 --- a/Controllers/HPOmen30LController/HPOmen30LController.h +++ b/Controllers/HPOmen30LController/HPOmen30LController.h @@ -1,17 +1,19 @@ -/*-----------------------------------------*\ -| HPOmen30LController.h | -| | -| Driver for HP Omen 30L RGB lighting | -| controller | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include -#include +/*---------------------------------------------------------*\ +| HPOmen30LController.h | +| | +| Driver for HP Omen 30L | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include +#include "RGBController.h" + typedef struct { unsigned char value; @@ -24,10 +26,12 @@ enum { HP_OMEN_30L_STATIC = 0x01, /* Static effect channel */ HP_OMEN_30L_DIRECT = 0x04, /* Direct for effects plugin */ + HP_OMEN_30L_OFF = 0x05, /* Turns off the led */ HP_OMEN_30L_BREATHING = 0x06, /* Breathing effect channel */ HP_OMEN_30L_COLOR_CYCLE = 0x07, /* Color cycle effect channel */ - HP_OMEN_30L_BLINKING = 0x08, /* Led blink */ - + HP_OMEN_30L_BLINKING = 0x08, /* Blinking effect channel */ + HP_OMEN_30L_WAVE = 0x09, /* Wave effect channel */ + HP_OMEN_30L_RADIAL = 0x0A, /* Radial effect channel */ }; enum @@ -39,10 +43,29 @@ enum enum { - HP_OMEN_30L_LOGO_ZONE = 0x01, - HP_OMEN_30L_BAR_ZONE = 0x02, - HP_OMEN_30L_FAN_ZONE = 0x03, - HP_OMEN_30L_CPU_ZONE = 0x04, + HP_OMEN_30L_LOGO_ZONE = 0x01, + HP_OMEN_30L_BAR_ZONE = 0x02, + HP_OMEN_30L_FAN_ZONE = 0x03, + HP_OMEN_30L_CPU_ZONE = 0x04, + HP_OMEN_30L_BOT_FAN_ZONE = 0x05, + HP_OMEN_30L_MID_FAN_ZONE = 0x06, + HP_OMEN_30L_TOP_FAN_ZONE = 0x07, +}; + +enum +{ + HP_OMEN_30L_POWER_ON = 0x01, /* Settings for powered on */ + HP_OMEN_30L_POWER_SUSPEND = 0x02, /* Settings for suspended */ +}; + +enum +{ + HP_OMEN_30L_THEME_CUSTOM = 0x00, + HP_OMEN_30L_THEME_GALAXY = 0x01, + HP_OMEN_30L_THEME_VOLCANO = 0x02, + HP_OMEN_30L_THEME_JUNGLE = 0x03, + HP_OMEN_30L_THEME_OCEAN = 0x04, + HP_OMEN_30L_THEME_UNICORN = 0x05, }; class HPOmen30LController @@ -58,7 +81,6 @@ public: std::string GetLocationString(); std::string GetSerialString(); - void SetRingEffectChannel(unsigned char channel); void SetZoneMode(int zone,unsigned char mode, unsigned char speed, unsigned char brightness); void SetZoneColor(int zone, std::vector colors); @@ -70,5 +92,4 @@ private: std::vector hp_zones; void SendZoneUpdate(int zone, std::vector colors); - }; diff --git a/Controllers/HPOmen30LController/HPOmen30LControllerDetect.cpp b/Controllers/HPOmen30LController/HPOmen30LControllerDetect.cpp index a940bce5..af075bf2 100644 --- a/Controllers/HPOmen30LController/HPOmen30LControllerDetect.cpp +++ b/Controllers/HPOmen30LController/HPOmen30LControllerDetect.cpp @@ -1,8 +1,16 @@ +/*---------------------------------------------------------*\ +| HPOmen30LControllerDetect.cpp | +| | +| Detector for HP Omen 30L | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "HPOmen30LController.h" -#include "RGBController.h" #include "RGBController_HPOmen30L.h" -#include #define HP_OMEN_30L_VID 0x103C #define HP_OMEN_30L_PID 0x84FD diff --git a/Controllers/HPOmen30LController/RGBController_HPOmen30L.cpp b/Controllers/HPOmen30LController/RGBController_HPOmen30L.cpp index 28980332..b52510e6 100644 --- a/Controllers/HPOmen30LController/RGBController_HPOmen30L.cpp +++ b/Controllers/HPOmen30LController/RGBController_HPOmen30L.cpp @@ -1,8 +1,11 @@ -/*-----------------------------------------*\ -| RGBController_HPOmen30L.cpp | -| | -| Generic RGB Interface for HP Omen 30L | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_HPOmen30L.cpp | +| | +| RGBController for HP Omen 30L | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_HPOmen30L.h" @@ -47,6 +50,13 @@ RGBController_HPOmen30L::RGBController_HPOmen30L(HPOmen30LController* controller Static.brightness = 100; modes.push_back(Static); + mode Off; + Off.name = "Off"; + Off.value = HP_OMEN_30L_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + mode Breathing; Breathing.name = "Breathing"; Breathing.value = HP_OMEN_30L_BREATHING; @@ -95,6 +105,38 @@ RGBController_HPOmen30L::RGBController_HPOmen30L(HPOmen30LController* controller Blinking.brightness = 100; modes.push_back(Blinking); + mode Wave; + Wave.name = "Wave"; + Wave.value = HP_OMEN_30L_WAVE; + Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Wave.speed_min = HP_OMEN_30L_SPEED_SLOW; + Wave.speed_max = HP_OMEN_30L_SPEED_FAST; + Wave.speed = HP_OMEN_30L_SPEED_MED; + Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; + Wave.colors_min = 6; + Wave.colors_max = 6; + Wave.colors.resize(6); + Wave.brightness_min = 0; + Wave.brightness_max = 100; + Wave.brightness = 100; + modes.push_back(Wave); + + mode Radial; + Radial.name = "Radial"; + Radial.value = HP_OMEN_30L_RADIAL; + Radial.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Radial.speed_min = HP_OMEN_30L_SPEED_SLOW; + Radial.speed_max = HP_OMEN_30L_SPEED_FAST; + Radial.speed = HP_OMEN_30L_SPEED_MED; + Radial.color_mode = MODE_COLORS_MODE_SPECIFIC; + Radial.colors_min = 1; + Radial.colors_max = 6; + Radial.colors.resize(4); + Radial.brightness_min = 0; + Radial.brightness_max = 100; + Radial.brightness = 100; + modes.push_back(Radial); + SetupZones(); } @@ -144,6 +186,33 @@ void RGBController_HPOmen30L::SetupZones() cpu_zone.matrix_map = NULL; zones.push_back(cpu_zone); + zone bot_fan; + bot_fan.name = "Front Bottom Fan"; + bot_fan.type = ZONE_TYPE_SINGLE; + bot_fan.leds_min = 1; + bot_fan.leds_max = 1; + bot_fan.leds_count = 1; + bot_fan.matrix_map = NULL; + zones.push_back(bot_fan); + + zone mid_fan; + mid_fan.name = "Front Middle Fan"; + mid_fan.type = ZONE_TYPE_SINGLE; + mid_fan.leds_min = 1; + mid_fan.leds_max = 1; + mid_fan.leds_count = 1; + mid_fan.matrix_map = NULL; + zones.push_back(mid_fan); + + zone top_fan; + top_fan.name = "Front Top Fan"; + top_fan.type = ZONE_TYPE_SINGLE; + top_fan.leds_min = 1; + top_fan.leds_max = 1; + top_fan.leds_count = 1; + top_fan.matrix_map = NULL; + zones.push_back(top_fan); + /*---------------------------------------------------------*\ | Set up LEDs | \*---------------------------------------------------------*/ @@ -163,6 +232,18 @@ void RGBController_HPOmen30L::SetupZones() cpu_led.name = "CPU LED"; leds.push_back(cpu_led); + led bot_fan_led; + bot_fan_led.name = "Bottom Fan LED"; + leds.push_back(bot_fan_led); + + led mid_fan_led; + bot_fan_led.name = "Middle Fan LED"; + leds.push_back(bot_fan_led); + + led top_fan_led; + bot_fan_led.name = "Top Fan LED"; + leds.push_back(bot_fan_led); + SetupColors(); } @@ -177,7 +258,9 @@ void RGBController_HPOmen30L::DeviceUpdateLEDs() { for(unsigned int i = 0; i < zones.size(); i++) { - if(modes[active_mode].value == HP_OMEN_30L_STATIC || modes[active_mode].value == HP_OMEN_30L_DIRECT) + if(modes[active_mode].value == HP_OMEN_30L_STATIC || + modes[active_mode].value == HP_OMEN_30L_DIRECT || + modes[active_mode].value == HP_OMEN_30L_OFF) { controller->SetZoneColor(i, colors); } diff --git a/Controllers/HPOmen30LController/RGBController_HPOmen30L.h b/Controllers/HPOmen30LController/RGBController_HPOmen30L.h index 74493403..c1463232 100644 --- a/Controllers/HPOmen30LController/RGBController_HPOmen30L.h +++ b/Controllers/HPOmen30LController/RGBController_HPOmen30L.h @@ -1,11 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_HPOmen30L.h | -| | -| Generic RGB Interface for HP Omen 30L | -| | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_HPOmen30L.h | +| | +| RGBController for HP Omen 30L | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "HPOmen30LController.h" diff --git a/Controllers/HYTEKeyboardController/HYTEKeyboardController.cpp b/Controllers/HYTEKeyboardController/HYTEKeyboardController.cpp new file mode 100644 index 00000000..71837a48 --- /dev/null +++ b/Controllers/HYTEKeyboardController/HYTEKeyboardController.cpp @@ -0,0 +1,202 @@ +/*---------------------------------------------------------*\ +| HYTEKeyboardController.cpp | +| | +| Driver for HYTE keyboard | +| | +| Adam Honse (calcprogrammer1@gmail.com) 30 Oct 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "HYTEKeyboardController.h" + +HYTEKeyboardController::HYTEKeyboardController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; +} + +HYTEKeyboardController::~HYTEKeyboardController() +{ + +} + +std::string HYTEKeyboardController::GetDeviceLocation() +{ + return("HID " + location); +} + +std::string HYTEKeyboardController::GetDeviceName() +{ + return(name); +} + +void HYTEKeyboardController::LEDStreaming(unsigned int zone, RGBColor* colors) +{ + /*-----------------------------------------------------*\ + | Call the appropriate LEDStreaming function for the | + | given zone | + \*-----------------------------------------------------*/ + switch(zone) + { + case HYTE_KEYBOARD_ZONE_KEYBOARD: + LEDStreaming_Keyboard(colors); + break; + + case HYTE_KEYBOARD_ZONE_SURROUND: + LEDStreaming_Surround(colors); + break; + } +} + +void HYTEKeyboardController::LEDStreaming_Keyboard(RGBColor* colors) +{ + /*-----------------------------------------------------*\ + | LED Streaming - Keyboard RGB | + | | + | Set Feature (9 bytes, the first byte is 0x00) | + | 0x04 0xF0 0x00 0x00 0x00 0x00 0x00 0x00 | + | | + | EP6 Write (6 pages, 65 bytes/page) | + | 0xRR 0xGG 0xBB 0xRR 0xGG 0xBB ... | + \*-----------------------------------------------------*/ + unsigned char usb_feature_buf[9]; + unsigned char usb_buf[6][65]; + + /*-----------------------------------------------------*\ + | Set up feature report | + \*-----------------------------------------------------*/ + memset(usb_feature_buf, 0, sizeof(usb_feature_buf)); + + usb_feature_buf[0] = 0x00; + usb_feature_buf[1] = 0x04; + usb_feature_buf[2] = 0xF0; + + /*-----------------------------------------------------*\ + | Set up data packets | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0][0] = 0x00; + usb_buf[1][0] = 0x00; + usb_buf[2][0] = 0x00; + usb_buf[3][0] = 0x00; + usb_buf[4][0] = 0x00; + usb_buf[5][0] = 0x00; + + /*-----------------------------------------------------*\ + | Fill in color data | + \*-----------------------------------------------------*/ + unsigned int color_idx = 0; + unsigned int channel_idx = 0; + + for(unsigned int pkt_idx = 0; pkt_idx < 6; pkt_idx++) + { + for(unsigned int byte_idx = 0; byte_idx < 64; byte_idx++) + { + switch(channel_idx) + { + case 0: + usb_buf[pkt_idx][1 + byte_idx] = RGBGetRValue(colors[color_idx]); + break; + + case 1: + usb_buf[pkt_idx][1 + byte_idx] = RGBGetGValue(colors[color_idx]); + break; + + case 2: + usb_buf[pkt_idx][1 + byte_idx] = RGBGetBValue(colors[color_idx]); + color_idx++; + break; + } + + channel_idx = ( channel_idx + 1 ) % 3; + } + } + + /*-----------------------------------------------------*\ + | Send the data | + \*-----------------------------------------------------*/ + hid_send_feature_report(dev, usb_feature_buf, sizeof(usb_feature_buf)); + hid_write(dev, usb_buf[0], sizeof(usb_buf[0])); + hid_write(dev, usb_buf[1], sizeof(usb_buf[1])); + hid_write(dev, usb_buf[2], sizeof(usb_buf[2])); + hid_write(dev, usb_buf[3], sizeof(usb_buf[3])); + hid_write(dev, usb_buf[4], sizeof(usb_buf[4])); + hid_write(dev, usb_buf[5], sizeof(usb_buf[5])); +} + +void HYTEKeyboardController::LEDStreaming_Surround(RGBColor* colors) +{ + /*-----------------------------------------------------*\ + | LED Streaming - Surround RGB | + | | + | Set Feature (9 bytes, the first byte is 0x00) | + | 0x04 0xF1 0x00 0x00 0x00 0x00 0x00 0x00 | + | | + | EP6 Write (3 pages, 65 bytes/page) | + | 0xRR 0xGG 0xBB 0xRR 0xGG 0xBB ... | + \*-----------------------------------------------------*/ + unsigned char usb_feature_buf[9]; + unsigned char usb_buf[3][65]; + + /*-----------------------------------------------------*\ + | Set up feature report | + \*-----------------------------------------------------*/ + memset(usb_feature_buf, 0, sizeof(usb_feature_buf)); + + usb_feature_buf[0] = 0x00; + usb_feature_buf[1] = 0x04; + usb_feature_buf[2] = 0xF1; + + /*-----------------------------------------------------*\ + | Set up data packets | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0][0] = 0x00; + usb_buf[1][0] = 0x00; + usb_buf[2][0] = 0x00; + + /*-----------------------------------------------------*\ + | Fill in color data | + \*-----------------------------------------------------*/ + unsigned int color_idx = 0; + unsigned int channel_idx = 0; + + for(unsigned int pkt_idx = 0; pkt_idx < 3; pkt_idx++) + { + for(unsigned int byte_idx = 0; byte_idx < 64; byte_idx++) + { + switch(channel_idx) + { + case 0: + usb_buf[pkt_idx][1 + byte_idx] = RGBGetRValue(colors[color_idx]); + break; + + case 1: + usb_buf[pkt_idx][1 + byte_idx] = RGBGetGValue(colors[color_idx]); + break; + + case 2: + usb_buf[pkt_idx][1 + byte_idx] = RGBGetBValue(colors[color_idx]); + color_idx++; + break; + } + + channel_idx = ( channel_idx + 1 ) % 3; + } + } + + /*-----------------------------------------------------*\ + | Send the data | + \*-----------------------------------------------------*/ + hid_send_feature_report(dev, usb_feature_buf, sizeof(usb_feature_buf)); + hid_write(dev, usb_buf[0], sizeof(usb_buf[0])); + hid_write(dev, usb_buf[1], sizeof(usb_buf[1])); + hid_write(dev, usb_buf[2], sizeof(usb_buf[2])); +} + diff --git a/Controllers/HYTEKeyboardController/HYTEKeyboardController.h b/Controllers/HYTEKeyboardController/HYTEKeyboardController.h new file mode 100644 index 00000000..a1953154 --- /dev/null +++ b/Controllers/HYTEKeyboardController/HYTEKeyboardController.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------*\ +| HYTEKeyboardController.h | +| | +| Driver for HYTE keyboard | +| | +| Adam Honse (calcprogrammer1@gmail.com) 30 Oct 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +enum +{ + HYTE_KEYBOARD_ZONE_KEYBOARD, + HYTE_KEYBOARD_ZONE_SURROUND +}; + +class HYTEKeyboardController +{ +public: + HYTEKeyboardController(hid_device* dev_handle, const char* path, std::string dev_name); + ~HYTEKeyboardController(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + + void LEDStreaming(unsigned int zone, RGBColor* colors); + +private: + hid_device* dev; + std::string location; + std::string name; + + void LEDStreaming_Keyboard(RGBColor* colors); + void LEDStreaming_Surround(RGBColor* colors); +}; diff --git a/Controllers/HYTEKeyboardController/HYTEKeyboardControllerDetect.cpp b/Controllers/HYTEKeyboardController/HYTEKeyboardControllerDetect.cpp new file mode 100644 index 00000000..2fd9863e --- /dev/null +++ b/Controllers/HYTEKeyboardController/HYTEKeyboardControllerDetect.cpp @@ -0,0 +1,40 @@ +/*---------------------------------------------------------*\ +| HYTEKeyboardControllerDetect.cpp | +| | +| Detector for HYTE keyboard | +| | +| Adam Honse (calcprogrammer1@gmail.com) 30 Oct 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "HYTEKeyboardController.h" +#include "RGBController_HYTEKeyboard.h" + +/*---------------------------------------------------------*\ +| HYTE vendor ID | +\*---------------------------------------------------------*/ +#define HYTE_VID 0x3402 + +/*---------------------------------------------------------*\ +| HYTE keyboard product IDs | +\*---------------------------------------------------------*/ +#define HYTE_KEEB_TKL_PID 0x0300 + +void DetectHYTEKeyboard(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + HYTEKeyboardController* controller = new HYTEKeyboardController(dev, info->path, name); + RGBController_HYTEKeyboard* rgb_controller = new RGBController_HYTEKeyboard(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR_PU("HYTE Keeb TKL", DetectHYTEKeyboard, HYTE_VID, HYTE_KEEB_TKL_PID, 0xFF11, 0xF0); diff --git a/Controllers/HYTEKeyboardController/RGBController_HYTEKeyboard.cpp b/Controllers/HYTEKeyboardController/RGBController_HYTEKeyboard.cpp new file mode 100644 index 00000000..144ee028 --- /dev/null +++ b/Controllers/HYTEKeyboardController/RGBController_HYTEKeyboard.cpp @@ -0,0 +1,200 @@ +/*---------------------------------------------------------*\ +| RGBController_HYTEKeyboard.cpp | +| | +| RGBController for HYTE keyboard | +| | +| Adam Honse (calcprogrammer1@gmail.com) 30 Oct 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "KeyboardLayoutManager.h" +#include "RGBController_HYTEKeyboard.h" + +/*---------------------------------------------------------------------*\ +| HYTE Keeb TKL KLM Layout | +\*---------------------------------------------------------------------*/ +const std::vector hyte_keeb_tkl_values = +{ + /* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK */ + 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + /* BKTK 1 2 3 4 5 6 7 8 9 0 - = BSPC INS HOME PGUP */ + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, + /* TAB Q W E R T Y U I O P [ ] \ DEL END PGDN */ + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + /* CPLK A S D F G H J K L ; " # ENTR */ + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, + /* LSFT \ Z X C V B N M , . / RSFT ARWU */ + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 97, 99, + /* LCTL LWIN LALT SPC RALT RFNC RMNU RCTL ARWL ARWD ARWR */ + 105, 106, 107, 111, 115, 116, 117, 118, 119, 120, 121, +}; + +keyboard_keymap_overlay_values hyte_keeb_tkl_layout = +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_TKL, + { + hyte_keeb_tkl_values, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys - Add additional LEDs for space bar underglow and media keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 5, 4, 109, KEY_EN_SPACE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 5, 5, 110, KEY_EN_SPACE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 5, 7, 112, KEY_EN_SPACE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 5, 8, 113, KEY_EN_SPACE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 0, 0, 77, KEY_EN_MEDIA_STOP, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_ROW, }, + { 0, 0, 1, 78, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 0, 2, 79, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 0, 3, 98, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 0, 4, 100, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + } +}; + +RGBController_HYTEKeyboard::RGBController_HYTEKeyboard(HYTEKeyboardController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "HYTE"; + type = DEVICE_TYPE_KEYBOARD; + description = "HYTE Keyboard Device"; + location = controller->GetDeviceLocation(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + SetupZones(); +} + +RGBController_HYTEKeyboard::~RGBController_HYTEKeyboard() +{ + delete controller; +} + +void RGBController_HYTEKeyboard::SetupZones() +{ + KeyboardLayoutManager new_kb(KEYBOARD_LAYOUT_DEFAULT, hyte_keeb_tkl_layout.base_size, hyte_keeb_tkl_layout.key_values); + new_kb.ChangeKeys(hyte_keeb_tkl_layout.edit_keys); + + zone keyboard_zone; + + keyboard_zone.name = "Keyboard"; + keyboard_zone.type = ZONE_TYPE_MATRIX; + + matrix_map_type * keyboard_map = new matrix_map_type; + keyboard_zone.matrix_map = keyboard_map; + keyboard_zone.matrix_map->height = new_kb.GetRowCount(); + keyboard_zone.matrix_map->width = new_kb.GetColumnCount(); + + keyboard_zone.matrix_map->map = new unsigned int[keyboard_map->height * keyboard_map->width]; + keyboard_zone.leds_count = new_kb.GetKeyCount(); + keyboard_zone.leds_min = keyboard_zone.leds_count; + keyboard_zone.leds_max = keyboard_zone.leds_count; + + zones.push_back(keyboard_zone); + + /*---------------------------------------------------------*\ + | Matrix map still uses declared zone rows and columns | + | as the packet structure depends on the matrix map | + \*---------------------------------------------------------*/ + new_kb.GetKeyMap(keyboard_map->map, KEYBOARD_MAP_FILL_TYPE_COUNT, keyboard_map->height, keyboard_map->width); + + /*---------------------------------------------------------*\ + | Create LEDs for the Matrix zone | + | Place keys in the layout to populate the matrix | + \*---------------------------------------------------------*/ + for(unsigned int led_idx = 0; led_idx < keyboard_zone.leds_count; led_idx++) + { + led new_led; + + new_led.name = new_kb.GetKeyNameAt(led_idx); + new_led.value = new_kb.GetKeyValueAt(led_idx); + + leds.push_back(new_led); + } + + zone surround_zone; + + surround_zone.name = "Underglow"; + surround_zone.type = ZONE_TYPE_LINEAR; + surround_zone.leds_min = 63; + surround_zone.leds_max = 63; + surround_zone.leds_count = 63; + surround_zone.matrix_map = NULL; + + zones.push_back(surround_zone); + + for(unsigned int led_idx = 0; led_idx < surround_zone.leds_count; led_idx++) + { + led new_led; + + new_led.name = surround_zone.name; + + leds.push_back(new_led); + } + + + SetupColors(); +} + +void RGBController_HYTEKeyboard::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_HYTEKeyboard::DeviceUpdateLEDs() +{ + for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + UpdateZoneLEDs(zone_idx); + } +} + +void RGBController_HYTEKeyboard::UpdateZoneLEDs(int zone) +{ + if(zone == HYTE_KEYBOARD_ZONE_KEYBOARD) + { + RGBColor color_buf[127]; + + for(unsigned int led_idx = 0; led_idx < zones[HYTE_KEYBOARD_ZONE_KEYBOARD].leds_count; led_idx++) + { + color_buf[leds[led_idx].value] = colors[led_idx]; + } + + controller->LEDStreaming(zone, &color_buf[0]); + } + else + { + controller->LEDStreaming(zone, zones[zone].colors); + } +} + +void RGBController_HYTEKeyboard::UpdateSingleLED(int led) +{ + if(led < (int)zones[0].leds_count) + { + UpdateZoneLEDs(0); + } + else + { + UpdateZoneLEDs(1); + } +} + +void RGBController_HYTEKeyboard::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} diff --git a/Controllers/HYTEKeyboardController/RGBController_HYTEKeyboard.h b/Controllers/HYTEKeyboardController/RGBController_HYTEKeyboard.h new file mode 100644 index 00000000..cbf3abba --- /dev/null +++ b/Controllers/HYTEKeyboardController/RGBController_HYTEKeyboard.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_HYTEKeyboard.h | +| | +| RGBController for HYTE keyboard | +| | +| Adam Honse (calcprogrammer1@gmail.com) 30 Oct 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "HYTEKeyboardController.h" +#include "RGBController.h" + +class RGBController_HYTEKeyboard : public RGBController +{ +public: + RGBController_HYTEKeyboard(HYTEKeyboardController* controller_ptr); + ~RGBController_HYTEKeyboard(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + HYTEKeyboardController* controller; +}; diff --git a/Controllers/HYTEMousematController/HYTEMousematController_Linux/HYTEMousematControllerDetect_Linux.cpp b/Controllers/HYTEMousematController/HYTEMousematController_Linux/HYTEMousematControllerDetect_Linux.cpp new file mode 100644 index 00000000..42c2f85e --- /dev/null +++ b/Controllers/HYTEMousematController/HYTEMousematController_Linux/HYTEMousematControllerDetect_Linux.cpp @@ -0,0 +1,88 @@ +/*---------------------------------------------------------*\ +| HYTEMousematControllerDetect_Linux.cpp | +| | +| Detector for HYTE mousemat (libusb implementation for | +| Linux) | +| | +| Adam Honse (calcprogrammer1@gmail.com) 18 Jul 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "RGBController_HYTEMousemat.h" + +/*-----------------------------------------------------*\ +| HYTE vendor ID | +\*-----------------------------------------------------*/ +#define HYTE_VID 0x3402 + +/*-----------------------------------------------------*\ +| HYTE CNVS product IDs | +\*-----------------------------------------------------*/ +#define HYTE_CNVS_HW_VER_1_PID 0x0B00 +#define HYTE_CNVS_HW_VER_2_PID 0x0B01 + +typedef struct +{ + unsigned short usb_vid; + unsigned short usb_pid; + unsigned char usb_interface; + const char * name; +} hyte_mousemat_device; + +#define HYTE_MOUSEMAT_NUM_DEVICES (sizeof(device_list) / sizeof(device_list[ 0 ])) + +static const hyte_mousemat_device device_list[] = +{ + /*-----------------------------------------------------------------------------------------------------*\ + | Mousemats | + \*-----------------------------------------------------------------------------------------------------*/ + { HYTE_VID, HYTE_CNVS_HW_VER_1_PID, 0, "HYTE CNVS" }, + { HYTE_VID, HYTE_CNVS_HW_VER_2_PID, 0, "HYTE CNVS" }, +}; + +/******************************************************************************************\ +* * +* DetectHYTEMousematControllers * +* * +* Detect devices supported by the HyteMousemat driver * +* * +\******************************************************************************************/ + +void DetectHYTEMousematControllers() +{ + libusb_init(NULL); + + #ifdef _WIN32 + libusb_set_option(NULL, LIBUSB_OPTION_USE_USBDK); + #endif + + for(std::size_t device_idx = 0; device_idx < HYTE_MOUSEMAT_NUM_DEVICES; device_idx++) + { + libusb_device_handle * dev = libusb_open_device_with_vid_pid(NULL, device_list[device_idx].usb_vid, device_list[device_idx].usb_pid); + + //Look for HYTE CNVS + if(dev) + { + libusb_detach_kernel_driver(dev, 0); + libusb_claim_interface(dev, 0); + + HYTEMousematController * controller = new HYTEMousematController(dev, device_list[device_idx].name); + RGBController_HYTEMousemat * rgb_controller = new RGBController_HYTEMousemat(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + } + +} /* DetectHYTEMousematControllers() */ + +REGISTER_DETECTOR("HYTE Mousemat", DetectHYTEMousematControllers); +/*---------------------------------------------------------------------------------------------------------*\ +| Entries for dynamic UDEV rules | +| | +| DUMMY_DEVICE_DETECTOR("HYTE Mousemat", DetectHYTEMousematControllers, 0x3402, 0x0B00 ) | +| DUMMY_DEVICE_DETECTOR("HYTE Mousemat", DetectHYTEMousematControllers, 0x3402, 0x0B01 ) | +\*---------------------------------------------------------------------------------------------------------*/ diff --git a/Controllers/HYTEMousematController/HYTEMousematController_Linux/HYTEMousematController_Linux.cpp b/Controllers/HYTEMousematController/HYTEMousematController_Linux/HYTEMousematController_Linux.cpp new file mode 100644 index 00000000..6efdb56e --- /dev/null +++ b/Controllers/HYTEMousematController/HYTEMousematController_Linux/HYTEMousematController_Linux.cpp @@ -0,0 +1,109 @@ +/*---------------------------------------------------------*\ +| HYTEMousematController_Linux.cpp | +| | +| Driver for HYTE mousemat (libusb implementation for | +| Linux) | +| | +| Adam Honse (calcprogrammer1@gmail.com) 18 Jul 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include "HYTEMousematController_Linux.h" + +HYTEMousematController::HYTEMousematController(libusb_device_handle* dev_handle, std::string dev_name) +{ + dev = dev_handle; + name = dev_name; + + /*-----------------------------------------------------*\ + | Fill in location string with USB ID | + \*-----------------------------------------------------*/ + libusb_device_descriptor descriptor; + libusb_get_device_descriptor(libusb_get_device(dev_handle), &descriptor); + + std::stringstream location_stream; + location_stream << std::hex << std::setfill('0') << std::setw(4) << descriptor.idVendor << ":" << std::hex << std::setfill('0') << std::setw(4) << descriptor.idProduct; + location = location_stream.str(); +} + +HYTEMousematController::~HYTEMousematController() +{ + libusb_release_interface(dev, 0); + libusb_attach_kernel_driver(dev, 0); + libusb_close(dev); +} + +std::string HYTEMousematController::GetLocation() +{ + return(location); +} + +std::string HYTEMousematController::GetName() +{ + return(name); +} + +void HYTEMousematController::FirmwareAnimationControl(bool enabled) +{ + unsigned char serial_buf[4]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(serial_buf, 0, sizeof(serial_buf)); + + /*-----------------------------------------------------*\ + | Set up Firmware Animation Control packet | + \*-----------------------------------------------------*/ + serial_buf[0] = 0xFF; + serial_buf[1] = 0xDC; + serial_buf[2] = 0x05; + serial_buf[3] = enabled; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + libusb_bulk_transfer(dev, HYTE_CNVS_EP_OUT, serial_buf, sizeof(serial_buf), NULL, 1000); +} + +void HYTEMousematController::StreamingCommand(RGBColor* colors) +{ + unsigned char serial_buf[157]; + unsigned int max_brightness = 72; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(serial_buf, 0, sizeof(serial_buf)); + + /*-----------------------------------------------------*\ + | Set up Streaming packet | + \*-----------------------------------------------------*/ + serial_buf[0] = 0xFF; + serial_buf[1] = 0xEE; + serial_buf[2] = 0x02; + serial_buf[3] = 0x01; + serial_buf[4] = 0x00; + serial_buf[5] = 0x32; + serial_buf[6] = 0x00; + + /*-----------------------------------------------------*\ + | Copy in colors | + \*-----------------------------------------------------*/ + for(unsigned int color_idx = 0; color_idx < 50; color_idx++) + { + serial_buf[7 + (color_idx * 3)] = ( max_brightness * RGBGetGValue(colors[color_idx]) ) / 100; + serial_buf[8 + (color_idx * 3)] = ( max_brightness * RGBGetRValue(colors[color_idx]) ) / 100; + serial_buf[9 + (color_idx * 3)] = ( max_brightness * RGBGetBValue(colors[color_idx]) ) / 100; + } + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + libusb_bulk_transfer(dev, HYTE_CNVS_EP_OUT, serial_buf, sizeof(serial_buf), NULL, 1000); +} diff --git a/Controllers/HYTEMousematController/HYTEMousematController_Linux/HYTEMousematController_Linux.h b/Controllers/HYTEMousematController/HYTEMousematController_Linux/HYTEMousematController_Linux.h new file mode 100644 index 00000000..a69868a3 --- /dev/null +++ b/Controllers/HYTEMousematController/HYTEMousematController_Linux/HYTEMousematController_Linux.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------*\ +| HYTEMousematController_Linux.h | +| | +| Driver for HYTE mousemat (libusb implementation for | +| Linux) | +| | +| Adam Honse (calcprogrammer1@gmail.com) 18 Jul 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" + +/*---------------------------------------------------------*\ +| HYTE CNVS endpoint values | +\*---------------------------------------------------------*/ +#define HYTE_CNVS_EP_IN 0x81 +#define HYTE_CNVS_EP_OUT 0x01 + +class HYTEMousematController +{ +public: + HYTEMousematController(libusb_device_handle* dev_handle, std::string dev_name); + ~HYTEMousematController(); + + std::string GetLocation(); + std::string GetName(); + + void FirmwareAnimationControl(bool enabled); + void StreamingCommand(RGBColor* colors); + +private: + libusb_device_handle* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematControllerDetect_Windows_MacOS.cpp b/Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematControllerDetect_Windows_MacOS.cpp new file mode 100644 index 00000000..49fd2e7f --- /dev/null +++ b/Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematControllerDetect_Windows_MacOS.cpp @@ -0,0 +1,72 @@ +/*---------------------------------------------------------*\ +| HYTEMousematControllerDetect_Windows_MacOS.cpp | +| | +| Detector for HYTE mousemat (Serial implementation for | +| Windows and MacOS) | +| | +| Adam Honse (calcprogrammer1@gmail.com) 18 Jul 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "HYTEMousematController_Windows_MacOS.h" +#include "RGBController_HYTEMousemat.h" +#include "find_usb_serial_port.h" + +#define HYTE_VID 0x3402 + +#define HYTE_CNVS_HW_VER_1_PID 0x0B00 +#define HYTE_CNVS_HW_VER_2_PID 0x0B01 + +struct hyte_mousemat_type +{ + unsigned short vid; + unsigned short pid; + const char * name; +}; + +#define HYTE_MOUSEMAT_NUM_DEVICES 2 + +static const hyte_mousemat_type hyte_mousemat_devices[] = +{ + { HYTE_VID, HYTE_CNVS_HW_VER_1_PID, "HYTE CNVS" }, + { HYTE_VID, HYTE_CNVS_HW_VER_2_PID, "HYTE CNVS" }, +}; + +/******************************************************************************************\ +* * +* DetectHYTEMousematControllers * +* * +* Detect devices supported by the HyteMousemat driver * +* * +\******************************************************************************************/ + +void DetectHYTEMousematControllers() +{ + for(unsigned int device_id = 0; device_id < HYTE_MOUSEMAT_NUM_DEVICES; device_id++) + { + std::vector ports = find_usb_serial_port(hyte_mousemat_devices[device_id].vid, hyte_mousemat_devices[device_id].pid); + + for(unsigned int i = 0; i < ports.size(); i++) + { + if(*ports[i] != "") + { + HYTEMousematController * controller = new HYTEMousematController((char *)ports[i]->c_str(), hyte_mousemat_devices[device_id].name); + RGBController_HYTEMousemat * rgb_controller = new RGBController_HYTEMousemat(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + } + } +} /* DetectHYTEMousematControllers() */ + +REGISTER_DETECTOR("HYTE Mousemat", DetectHYTEMousematControllers); +/*---------------------------------------------------------------------------------------------------------*\ +| Entries for dynamic UDEV rules | +| | +| DUMMY_DEVICE_DETECTOR("HYTE Mousemat", DetectHYTEMousematControllers, 0x3402, 0x0B00 ) | +| DUMMY_DEVICE_DETECTOR("HYTE Mousemat", DetectHYTEMousematControllers, 0x3402, 0x0B01 ) | +\*---------------------------------------------------------------------------------------------------------*/ diff --git a/Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematController_Windows_MacOS.cpp b/Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematController_Windows_MacOS.cpp new file mode 100644 index 00000000..23446b4e --- /dev/null +++ b/Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematController_Windows_MacOS.cpp @@ -0,0 +1,100 @@ +/*---------------------------------------------------------*\ +| HYTEMousematController_Windows_MacOS.cpp | +| | +| Driver for HYTE mousemat (Serial implementation for | +| Windows and MacOS) | +| | +| Adam Honse (calcprogrammer1@gmail.com) 18 Jul 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "HYTEMousematController_Windows_MacOS.h" + +HYTEMousematController::HYTEMousematController(char* port, std::string dev_name) +{ + name = dev_name; + port_name = port; + + /*-----------------------------------------------------*\ + | Open the port | + | Baud rate doesn't matter for ACM device | + \*-----------------------------------------------------*/ + serialport = new serial_port(port_name.c_str(), 2000000); +} + +HYTEMousematController::~HYTEMousematController() +{ + serialport->serial_close(); +} + +std::string HYTEMousematController::GetLocation() +{ + return(port_name); +} + +std::string HYTEMousematController::GetName() +{ + return(name); +} + +void HYTEMousematController::FirmwareAnimationControl(bool enabled) +{ + unsigned char serial_buf[4]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(serial_buf, 0, sizeof(serial_buf)); + + /*-----------------------------------------------------*\ + | Set up Firmware Animation Control packet | + \*-----------------------------------------------------*/ + serial_buf[0] = 0xFF; + serial_buf[1] = 0xDC; + serial_buf[2] = 0x05; + serial_buf[3] = enabled; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + serialport->serial_write((char *)serial_buf, sizeof(serial_buf)); +} + +void HYTEMousematController::StreamingCommand(RGBColor* colors) +{ + unsigned char serial_buf[157]; + unsigned int max_brightness = 72; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(serial_buf, 0, sizeof(serial_buf)); + + /*-----------------------------------------------------*\ + | Set up Streaming packet | + \*-----------------------------------------------------*/ + serial_buf[0] = 0xFF; + serial_buf[1] = 0xEE; + serial_buf[2] = 0x02; + serial_buf[3] = 0x01; + serial_buf[4] = 0x00; + serial_buf[5] = 0x32; + serial_buf[6] = 0x00; + + /*-----------------------------------------------------*\ + | Copy in colors | + \*-----------------------------------------------------*/ + for(unsigned int color_idx = 0; color_idx < 50; color_idx++) + { + serial_buf[7 + (color_idx * 3)] = ( max_brightness * RGBGetGValue(colors[color_idx]) ) / 100; + serial_buf[8 + (color_idx * 3)] = ( max_brightness * RGBGetRValue(colors[color_idx]) ) / 100; + serial_buf[9 + (color_idx * 3)] = ( max_brightness * RGBGetBValue(colors[color_idx]) ) / 100; + } + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + serialport->serial_write((char *)serial_buf, sizeof(serial_buf)); +} diff --git a/Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematController_Windows_MacOS.h b/Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematController_Windows_MacOS.h new file mode 100644 index 00000000..3ac606e0 --- /dev/null +++ b/Controllers/HYTEMousematController/HYTEMousematController_Windows_MacOS/HYTEMousematController_Windows_MacOS.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| HYTEMousematController_Windows_MacOS.h | +| | +| Driver for HYTE mousemat (Serial implementation for | +| Windows and MacOS) | +| | +| Adam Honse (calcprogrammer1@gmail.com) 18 Jul 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "serial_port.h" + +class HYTEMousematController +{ +public: + HYTEMousematController(char* port, std::string dev_name); + ~HYTEMousematController(); + + std::string GetLocation(); + std::string GetName(); + + void FirmwareAnimationControl(bool enabled); + void StreamingCommand(RGBColor* colors); + +private: + std::string name; + std::string port_name; + serial_port * serialport = nullptr; +}; diff --git a/Controllers/HYTEMousematController/RGBController_HYTEMousemat.cpp b/Controllers/HYTEMousematController/RGBController_HYTEMousemat.cpp new file mode 100644 index 00000000..4503ad68 --- /dev/null +++ b/Controllers/HYTEMousematController/RGBController_HYTEMousemat.cpp @@ -0,0 +1,117 @@ +/*---------------------------------------------------------*\ +| RGBController_HYTEMousemat.cpp | +| | +| RGBController for HYTE mousemat | +| | +| Adam Honse (calcprogrammer1@gmail.com) 18 Jul 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_HYTEMousemat.h" + +/**------------------------------------------------------------------*\ + @name HYTE Mousemat + @category Mousemat + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectHYTEMousematControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_HYTEMousemat::RGBController_HYTEMousemat(HYTEMousematController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = "HYTE"; + description = "HYTE Mousemat Device"; + type = DEVICE_TYPE_MOUSEMAT; + location = controller->GetLocation(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = HYTE_CNVS_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + // HYTE CNVS does not seem to be able to transfer back into firmware animation + // after streaming command has been used + //mode Rainbow; + //Rainbow.name = "Rainbow Wave"; + //Rainbow.value = HYTE_CNVS_MODE_RAINBOW; + //Rainbow.flags = MODE_FLAG_HAS_RANDOM_COLOR; + //Rainbow.color_mode = MODE_COLORS_RANDOM; + //modes.push_back(Rainbow); + + SetupZones(); +} + +RGBController_HYTEMousemat::~RGBController_HYTEMousemat() +{ + delete controller; +} + +void RGBController_HYTEMousemat::SetupZones() +{ + zone mousemat_zone; + + mousemat_zone.name = "Mousemat"; + mousemat_zone.type = ZONE_TYPE_LINEAR; + mousemat_zone.leds_min = 50; + mousemat_zone.leds_max = 50; + mousemat_zone.leds_count = 50; + mousemat_zone.matrix_map = NULL; + + zones.push_back(mousemat_zone); + + for(unsigned int led_idx = 0; led_idx < zones[0].leds_count; led_idx++) + { + led mousemat_led; + + mousemat_led.name = "Mousemat LED "; + mousemat_led.name.append(std::to_string(led_idx)); + + leds.push_back(mousemat_led); + } + + SetupColors(); +} + +void RGBController_HYTEMousemat::ResizeZone(int /*zone*/, int /*new_size*/) +{ + +} + +void RGBController_HYTEMousemat::DeviceUpdateLEDs() +{ + controller->StreamingCommand(&colors[0]); +} + +void RGBController_HYTEMousemat::UpdateZoneLEDs(int /*zone*/) +{ + +} + +void RGBController_HYTEMousemat::UpdateSingleLED(int /*led*/) +{ + +} + +void RGBController_HYTEMousemat::DeviceUpdateMode() +{ + switch(modes[active_mode].value) + { + case HYTE_CNVS_MODE_DIRECT: + controller->FirmwareAnimationControl(false); + break; + + case HYTE_CNVS_MODE_RAINBOW: + controller->FirmwareAnimationControl(true); + break; + } +} diff --git a/Controllers/HYTEMousematController/RGBController_HYTEMousemat.h b/Controllers/HYTEMousematController/RGBController_HYTEMousemat.h new file mode 100644 index 00000000..c4c58a00 --- /dev/null +++ b/Controllers/HYTEMousematController/RGBController_HYTEMousemat.h @@ -0,0 +1,48 @@ +/*---------------------------------------------------------*\ +| RGBController_HYTEMousemat.h | +| | +| RGBController for HYTE mousemat | +| | +| Adam Honse (calcprogrammer1@gmail.com) 18 Jul 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" + +#if defined(_WIN32) || defined(__APPLE__) +#include "HYTEMousematController_Windows_MacOS.h" +#endif + +#ifdef __linux__ +#include "HYTEMousematController_Linux.h" +#endif + + +enum +{ + HYTE_CNVS_MODE_DIRECT = 0, /* Direct (streaming) mode */ + HYTE_CNVS_MODE_RAINBOW = 1, /* Rainbow wave (firmware animation) mode */ +}; + +class RGBController_HYTEMousemat : public RGBController +{ +public: + RGBController_HYTEMousemat(HYTEMousematController* controller_ptr); + ~RGBController_HYTEMousemat(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + HYTEMousematController* controller; +}; diff --git a/Controllers/HYTENexusController/HYTENexusController.cpp b/Controllers/HYTENexusController/HYTENexusController.cpp new file mode 100644 index 00000000..b19b598d --- /dev/null +++ b/Controllers/HYTENexusController/HYTENexusController.cpp @@ -0,0 +1,407 @@ +/*---------------------------------------------------------*\ +| HYTENexusController.cpp | +| | +| Driver for HYTE Nexus | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "HYTENexusController.h" +#include "LogManager.h" + +using namespace std::chrono_literals; + +/*---------------------------------------------------------*\ +| The protocol for the HYTE NP50 and Q60 are documented | +| on hackmd.io: | +| NP50: https://hackmd.io/3X_ojT77Sr-sLt5Fo2CYMQ | +| Q60: https://hackmd.io/7qUhUQfIQReQYNhdGLqO6g | +| | +| More information on the HYTE Nexus Playground site: | +| https://hyte.com/nexus/nexus-playground | +\*---------------------------------------------------------*/ + +HYTENexusController::HYTENexusController(char* port, unsigned short pid, std::string dev_name) +{ + port_name = port; + device_pid = pid; + name = dev_name; + + /*-----------------------------------------------------*\ + | Initialize channels based on PID | + \*-----------------------------------------------------*/ + memset(channels, 0, sizeof(channels)); + + switch(pid) + { + case HYTE_NEXUS_PORTAL_NP50_PID: + num_channels = 3; + + channels[0].is_nexus_channel = true; + channels[1].is_nexus_channel = true; + channels[2].is_nexus_channel = true; + + channels[0].has_6_led_logo = true; + break; + + case HYTE_THICC_Q60_PID: + num_channels = 4; + + channels[0].is_nexus_channel = true; + channels[1].is_nexus_channel = true; + channels[2].is_nexus_channel = false; + channels[3].is_nexus_channel = false; + + channels[2].has_lcd_leds = true; + channels[3].has_4_led_logo = true; + break; + + default: + num_channels = 0; + break; + } + + /*-----------------------------------------------------*\ + | Open the port | + | Baud rate doesn't matter for ACM device | + \*-----------------------------------------------------*/ + serialport = new serial_port(port_name.c_str(), 2000000); + + /*-----------------------------------------------------*\ + | Get controller information and firmware version | + \*-----------------------------------------------------*/ + ReadDeviceInfo(); + ReadFirmwareVersion(); + + /*-----------------------------------------------------*\ + | Get attached device information for all channels | + \*-----------------------------------------------------*/ + for(unsigned int channel = 0; channel < num_channels; channel++) + { + if(channels[channel].is_nexus_channel) + { + ReadChannelInfo(channel); + } + } + + keepalive_thread_run = true; + keepalive_thread = std::thread(&HYTENexusController::KeepaliveThreadFunction, this); +} + +HYTENexusController::~HYTENexusController() +{ + keepalive_thread_run = false; + keepalive_thread.join(); + + serialport->serial_close(); +} + +std::string HYTENexusController::GetFirmwareVersion() +{ + return(firmware_version); +} + +std::string HYTENexusController::GetLocation() +{ + return(port_name); +} + +std::string HYTENexusController::GetName() +{ + return(name); +} + +void HYTENexusController::KeepaliveThreadFunction() +{ + while(keepalive_thread_run.load()) + { + if((std::chrono::steady_clock::now() - last_update_time) > 2500ms) + { + ReadDeviceInfo(); + } + std::this_thread::sleep_for(1s); + } +} + +std::string HYTENexusController::GetDeviceName(unsigned int device_type) +{ + std::string device_name = ""; + + switch(device_type) + { + case HYTE_NEXUS_DEVICE_TYPE_LS10: + device_name = "LS10"; + break; + + case HYTE_NEXUS_DEVICE_TYPE_LS30: + device_name = "LS30"; + break; + + case HYTE_NEXUS_DEVICE_TYPE_FP12: + device_name = "FP12"; + break; + + case HYTE_NEXUS_DEVICE_TYPE_FP12_DUO: + device_name = "FP12 Duo"; + break; + + case HYTE_NEXUS_DEVICE_TYPE_FP12_TRIO: + device_name = "FP12 Trio"; + break; + + case HYTE_NEXUS_DEVICE_TYPE_LN4060: + device_name = "LN4060"; + break; + + case HYTE_NEXUS_DEVICE_TYPE_LN70: + device_name = "LN70"; + break; + } + + return(device_name); +} + +void HYTENexusController::LEDStreaming(unsigned char channel, unsigned short led_count, RGBColor* colors) +{ + /*-----------------------------------------------------*\ + | Send LED Streaming command | + | Byte 0: FF | + | Byte 1: EE | + | Byte 2: 01 | + | Byte 3: Channel (Port1, Port2, or Port3) | + | Byte 4: LEDCount_H | + | Byte 5: LEDCount_L | + | Byte 6: Reserved | + | Byte 7: G | + | Byte 8: R | + | Byte 9: B | + | Repeat GRB pattern for remaining bytes | + \*-----------------------------------------------------*/ + unsigned char command_buf[750]; + + memset(command_buf, 0, sizeof(command_buf)); + + command_buf[0] = 0xFF; + command_buf[1] = 0xEE; + command_buf[2] = 0x01; + command_buf[3] = (channel + 1); + command_buf[4] = (led_count >> 8); + command_buf[5] = (led_count & 0xFF); + + for(unsigned int led_idx = 0; led_idx < led_count; led_idx++) + { + unsigned int offset = (led_idx * 3); + + command_buf[7 + offset] = RGBGetGValue(colors[led_idx]); + command_buf[8 + offset] = RGBGetRValue(colors[led_idx]); + command_buf[9 + offset] = RGBGetBValue(colors[led_idx]); + } + + /*-----------------------------------------------------*\ + | The default data length is (led_count * 3) + 7 | + \*-----------------------------------------------------*/ + unsigned int bytes_to_send = ((led_count * 3) + 7); + + /*-----------------------------------------------------*\ + | The HYTE THICC Q60 requires 90 bytes to be sent for | + | the 4th channel (logo) even though it only has 4 LEDs | + \*-----------------------------------------------------*/ + if((device_pid == HYTE_THICC_Q60_PID) + && (channel == 3) + && (bytes_to_send < 90)) + { + bytes_to_send = 90; + } + + /*-----------------------------------------------------*\ + | The HYTE Nexus Portal NP50 requires 750 bytes to be | + | sent for the 3rd channel, no matter how many LEDs it | + | has connected | + \*-----------------------------------------------------*/ + if((device_pid == HYTE_NEXUS_PORTAL_NP50_PID) + && (channel == 2) + && (bytes_to_send < 750)) + { + bytes_to_send = 750; + } + + port_mutex.lock(); + serialport->serial_write((char *)command_buf, bytes_to_send); + serialport->serial_flush_tx(); + serialport->serial_flush_rx(); + port_mutex.unlock(); +} + +void HYTENexusController::ReadChannelInfo(unsigned char channel) +{ + /*-----------------------------------------------------*\ + | Send Get Channel Info command | + | Byte 0: FF | + | Byte 1: CC | + | Byte 2: 01 (Get Status) | + | Byte 3: Channel (Port1, Port2, or Port3) | + \*-----------------------------------------------------*/ + unsigned char command_buf[4]; + + command_buf[0] = 0xFF; + command_buf[1] = 0xCC; + command_buf[2] = 0x01; + command_buf[3] = (channel + 1); + + port_mutex.lock(); + serialport->serial_write((char *)command_buf, sizeof(command_buf)); + serialport->serial_flush_tx(); + + /*-----------------------------------------------------*\ + | Wait 50ms for device to send response | + \*-----------------------------------------------------*/ + std::this_thread::sleep_for(50ms); + + /*-----------------------------------------------------*\ + | Receive Channel Info | + | First Device Additional Devices | + | Byte 0: FF 00 | + | Byte 1: CC 00 | + | Byte 2: Device Count | + | Byte 3: Device Type | + | Byte 4: Hardware Version | + | Byte 5: LED Count | + | Byte 6: Fan Temp_H | + | Byte 7: Fan Temp_L | + | Byte 8: Fan RPM_H | + | Byte 9: Fan RPM_L | + | Byte 10: Fan Orientation | + | Byte 11: Touch | + | | + | Format repeats with offset of 12 * n for nth device | + | in the list, except for the first two bytes being | + | zero. | + \*-----------------------------------------------------*/ + unsigned char receive_buf[240]; + + serialport->serial_read((char *)receive_buf, sizeof(receive_buf)); + serialport->serial_flush_rx(); + port_mutex.unlock(); + + channels[channel].num_devices = 0; + memset(&channels[channel].devices, 0, sizeof(channels[channel].devices)); + + for(unsigned int device = 0; device < 19; device++) + { + unsigned int offset = 12 * device; + + if(receive_buf[offset + 2] > 0) + { + channels[channel].num_devices++; + + channels[channel].devices[device].device_type = receive_buf[offset + 3]; + channels[channel].devices[device].hardware_version = receive_buf[offset + 4]; + channels[channel].devices[device].led_count = receive_buf[offset + 5]; + } + } +} + +void HYTENexusController::ReadDeviceInfo() +{ + /*-----------------------------------------------------*\ + | Send Get Device Info command | + | Byte 0: FF | + | Byte 1: CC | + | Byte 2: 01 (Get Status) | + | Byte 3: 00 (NP50/Pump) | + \*-----------------------------------------------------*/ + unsigned char command_buf[4]; + + command_buf[0] = 0xFF; + command_buf[1] = 0xCC; + command_buf[2] = 0x01; + command_buf[3] = 0x00; + + port_mutex.lock(); + serialport->serial_write((char *)command_buf, sizeof(command_buf)); + serialport->serial_flush_tx(); + + /*-----------------------------------------------------*\ + | Wait 50ms for device to send response | + \*-----------------------------------------------------*/ + std::this_thread::sleep_for(50ms); + + /*-----------------------------------------------------*\ + | Receive Device Info | + | NP50 Q60 | + | Byte 0: FF FF | + | Byte 1: CC CC | + | Byte 2: 00 00 | + | Byte 3: Noise_H Reserve | + | Byte 4: Noise_L Reserve | + | Byte 5: Reserve In Liquid Temp_H | + | Byte 6: Reserve In Liquid Temp_L | + | Byte 7: Temp_H Out Liquid Temp_H | + | Byte 8: Temp_L Out Liquid Temp_L | + | Byte 9: RPM_H Pump RPM_H | + | Byte 10: RPM_L Pump RPM_L | + | Byte 11: Reserve Fan Exhaust/Intake | + | Byte 12: Current Cooling Mode Current Cooling Mode| + | Byte 13: Warning Warnings | + \*-----------------------------------------------------*/ + unsigned char receive_buf[14]; + + serialport->serial_read((char *)receive_buf, sizeof(receive_buf)); + serialport->serial_flush_rx(); + port_mutex.unlock(); + + /*-----------------------------------------------------*\ + | Update last update time | + \*-----------------------------------------------------*/ + last_update_time = std::chrono::steady_clock::now(); +} + +void HYTENexusController::ReadFirmwareVersion() +{ + /*-----------------------------------------------------*\ + | Send Get Firmware Version command | + | Byte 0: FF | + | Byte 1: DD | + | Byte 2: 02 | + | Byte 3: 00 (Reserve) | + \*-----------------------------------------------------*/ + unsigned char command_buf[4]; + + command_buf[0] = 0xFF; + command_buf[1] = 0xDD; + command_buf[2] = 0x02; + command_buf[3] = 0x00; + + port_mutex.lock(); + serialport->serial_write((char *)command_buf, sizeof(command_buf)); + serialport->serial_flush_tx(); + + /*-----------------------------------------------------*\ + | Wait 50ms for device to send response | + \*-----------------------------------------------------*/ + std::this_thread::sleep_for(50ms); + + /*-----------------------------------------------------*\ + | Receive Firmware Version | + | Byte 0: FF | + | Byte 1: DD | + | Byte 2: 02 | + | Byte 3: Large Version | + | Byte 4: Mid Version | + | Byte 5: Small Version | + | Byte 6: Hardware Version | + \*-----------------------------------------------------*/ + unsigned char receive_buf[7]; + + serialport->serial_read((char *)receive_buf, sizeof(receive_buf)); + serialport->serial_flush_rx(); + port_mutex.unlock(); + + /*-----------------------------------------------------*\ + | Format Firmware Version string | + \*-----------------------------------------------------*/ + firmware_version = "FW: " + std::to_string(receive_buf[3]) + "." + std::to_string(receive_buf[4]) + "." + std::to_string(receive_buf[5]) + ", HW: " + std::to_string(receive_buf[6]); +} diff --git a/Controllers/HYTENexusController/HYTENexusController.h b/Controllers/HYTENexusController/HYTENexusController.h new file mode 100644 index 00000000..f590068d --- /dev/null +++ b/Controllers/HYTENexusController/HYTENexusController.h @@ -0,0 +1,87 @@ +/*---------------------------------------------------------*\ +| HYTENexusController.h | +| | +| Driver for HYTE Nexus | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include +#include +#include "RGBController.h" +#include "serial_port.h" + +#define HYTE_THICC_Q60_PID 0x0400 +#define HYTE_NEXUS_PORTAL_NP50_PID 0x0901 + +typedef struct +{ + unsigned int device_type; + unsigned int hardware_version; + unsigned char led_count; +} hyte_nexus_device; + +typedef struct +{ + bool is_nexus_channel; + bool has_4_led_logo; + bool has_6_led_logo; + bool has_lcd_leds; + unsigned int num_devices; + hyte_nexus_device devices[19]; +} hyte_nexus_channel; + +enum +{ + HYTE_NEXUS_DEVICE_TYPE_LS10 = 0x01, + HYTE_NEXUS_DEVICE_TYPE_LS30 = 0x02, + HYTE_NEXUS_DEVICE_TYPE_FP12 = 0x03, + HYTE_NEXUS_DEVICE_TYPE_FP12_DUO = 0x04, + HYTE_NEXUS_DEVICE_TYPE_FP12_TRIO = 0x05, + HYTE_NEXUS_DEVICE_TYPE_LN4060 = 0x06, + HYTE_NEXUS_DEVICE_TYPE_LN70 = 0x07, +}; + +class HYTENexusController +{ +public: + HYTENexusController(char* port, unsigned short pid, std::string dev_name); + ~HYTENexusController(); + + std::string GetFirmwareVersion(); + std::string GetLocation(); + std::string GetName(); + std::string GetDeviceName(unsigned int device_type); + + void LEDStreaming(unsigned char channel, unsigned short num_leds, RGBColor* colors); + + hyte_nexus_channel channels[4]; + unsigned int num_channels; + unsigned short device_pid; + +private: + std::string firmware_version; + std::string name; + std::string port_name; + std::mutex port_mutex; + serial_port * serialport = nullptr; + std::chrono::time_point last_update_time; + std::atomic keepalive_thread_run; + std::thread keepalive_thread; + + void KeepaliveThreadFunction(); + + void ReadChannelInfo(unsigned char channel); + void ReadDeviceInfo(); + void ReadFirmwareVersion(); + + void SetStartupAnimation(bool enable); +}; diff --git a/Controllers/HYTENexusController/HYTENexusControllerDetect.cpp b/Controllers/HYTENexusController/HYTENexusControllerDetect.cpp new file mode 100644 index 00000000..3462c6d4 --- /dev/null +++ b/Controllers/HYTENexusController/HYTENexusControllerDetect.cpp @@ -0,0 +1,68 @@ +/*---------------------------------------------------------*\ +| HYTENexusControllerDetect.cpp | +| | +| Detector for HYTE Nexus | +| | +| Adam Honse (calcprogrammer1@gmail.com) 19 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "HYTENexusController.h" +#include "RGBController_HYTENexus.h" +#include "find_usb_serial_port.h" + +#define HYTE_VID 0x3402 + +struct hyte_nexus_type +{ + unsigned short vid; + unsigned short pid; + const char * name; +}; + +#define HYTE_NEXUS_NUM_DEVICES 2 + +static const hyte_nexus_type hyte_nexus_devices[] = +{ + { HYTE_VID, HYTE_THICC_Q60_PID, "HYTE THICC Q60", }, + { HYTE_VID, HYTE_NEXUS_PORTAL_NP50_PID, "HYTE Nexus Portal NP50" }, +}; + +/******************************************************************************************\ +* * +* DetectHYTENexusControllers * +* * +* Detect devices supported by the HYTENexus driver * +* * +\******************************************************************************************/ + +void DetectHYTENexusControllers() +{ + for(unsigned int device_id = 0; device_id < HYTE_NEXUS_NUM_DEVICES; device_id++) + { + std::vector ports = find_usb_serial_port(hyte_nexus_devices[device_id].vid, hyte_nexus_devices[device_id].pid); + + for(unsigned int i = 0; i < ports.size(); i++) + { + if(*ports[i] != "") + { + HYTENexusController * controller = new HYTENexusController((char *)ports[i]->c_str(), hyte_nexus_devices[device_id].pid, hyte_nexus_devices[device_id].name); + RGBController_HYTENexus * rgb_controller = new RGBController_HYTENexus(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + } + } +} /* DetectHYTENexusControllers() */ + +REGISTER_DETECTOR("HYTE Nexus", DetectHYTENexusControllers); +/*---------------------------------------------------------------------------------------------------------*\ +| Entries for dynamic UDEV rules | +| | +| DUMMY_DEVICE_DETECTOR("HYTE THICC Q60", DetectHYTENexusControllers, 0x3402, 0x0400 ) | +| DUMMY_DEVICE_DETECTOR("HYTE Nexus Portal NP50", DetectHYTENexusControllers, 0x3402, 0x0901 ) | +\*---------------------------------------------------------------------------------------------------------*/ diff --git a/Controllers/HYTENexusController/RGBController_HYTENexus.cpp b/Controllers/HYTENexusController/RGBController_HYTENexus.cpp new file mode 100644 index 00000000..fd5f0477 --- /dev/null +++ b/Controllers/HYTENexusController/RGBController_HYTENexus.cpp @@ -0,0 +1,195 @@ +/*---------------------------------------------------------*\ +| RGBController_HYTENexus.cpp | +| | +| RGBController for HYTE Nexus | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_HYTENexus.h" + +using namespace std::chrono_literals; + +//0xFFFFFFFF indicates an unused entry in matrix +#define NA 0xFFFFFFFF + +static unsigned int thicc_q60_matrix_map[9][5] = +{ + { 33, 32, NA, 17, 0 }, + { 34, 31, NA, 16, 1 }, + { 35, 30, NA, 15, 2 }, + { 36, 29, 18, 14, 3 }, + { 37, 28, 19, 13, 4 }, + { 38, 27, 20, 12, 5 }, + { 39, 26, 21, 11, 6 }, + { 40, 25, 22, 10, 7 }, + { 41, 24, 23, 9, 8 }, +}; + +RGBController_HYTENexus::RGBController_HYTENexus(HYTENexusController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = "HYTE"; + description = "HYTE Nexus Device"; + type = DEVICE_TYPE_LEDSTRIP; + location = controller->GetLocation(); + version = controller->GetFirmwareVersion(); + + 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(); +} + +RGBController_HYTENexus::~RGBController_HYTENexus() +{ + delete controller; +} + +void RGBController_HYTENexus::SetupZones() +{ + for(unsigned int channel = 0; channel < controller->num_channels; channel++) + { + unsigned int channel_leds = 0; + unsigned int logo_leds = 0; + + for(unsigned int device = 0; device < controller->channels[channel].num_devices; device++) + { + channel_leds += controller->channels[channel].devices[device].led_count; + } + + if(controller->channels[channel].has_4_led_logo == true || controller->channels[channel].has_6_led_logo == true) + { + if(controller->channels[channel].has_4_led_logo == true) + { + logo_leds = 4; + } + else if(controller->channels[channel].has_6_led_logo == true) + { + logo_leds = 6; + } + + channel_leds += logo_leds; + } + + if(controller->channels[channel].has_lcd_leds == true) + { + channel_leds += 42; + } + + zone channel_zone; + + channel_zone.name = "Channel " + std::to_string(channel); + channel_zone.type = ZONE_TYPE_LINEAR; + channel_zone.leds_min = channel_leds; + channel_zone.leds_max = channel_leds; + channel_zone.leds_count = channel_leds; + channel_zone.matrix_map = NULL; + + for(unsigned int led_idx = 0; led_idx < channel_leds; led_idx++) + { + led channel_led; + + channel_led.name = "Channel " + std::to_string(channel) + " LED " + std::to_string(led_idx); + channel_led.value = channel; + + leds.push_back(channel_led); + } + + unsigned int start_idx = 0; + + if(controller->channels[channel].has_4_led_logo == true || controller->channels[channel].has_6_led_logo == true) + { + segment logo_segment; + + logo_segment.name = "Logo"; + logo_segment.leds_count = logo_leds; + logo_segment.start_idx = start_idx; + logo_segment.type = ZONE_TYPE_SINGLE; + + channel_zone.segments.push_back(logo_segment); + + start_idx += logo_segment.leds_count; + } + + if(controller->channels[channel].has_lcd_leds == true) + { + segment lcd_leds_segment; + + lcd_leds_segment.name = "LCD LED Matrix"; + lcd_leds_segment.leds_count = 42; + lcd_leds_segment.start_idx = start_idx; + lcd_leds_segment.type = ZONE_TYPE_MATRIX; + + channel_zone.type = ZONE_TYPE_MATRIX; + channel_zone.matrix_map = new matrix_map_type; + channel_zone.matrix_map->height = 9; + channel_zone.matrix_map->width = 5; + channel_zone.matrix_map->map = (unsigned int *)&thicc_q60_matrix_map; + + channel_zone.segments.push_back(lcd_leds_segment); + + start_idx += lcd_leds_segment.leds_count; + } + + for(unsigned int device = 0; device < controller->channels[channel].num_devices; device++) + { + if(controller->channels[channel].devices[device].led_count > 0) + { + segment device_segment; + + device_segment.name = controller->GetDeviceName(controller->channels[channel].devices[device].device_type); + device_segment.leds_count = controller->channels[channel].devices[device].led_count; + device_segment.start_idx = start_idx; + device_segment.type = ZONE_TYPE_LINEAR; + + channel_zone.segments.push_back(device_segment); + + start_idx += device_segment.leds_count; + } + } + + zones.push_back(channel_zone); + } + + SetupColors(); +} + +void RGBController_HYTENexus::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_HYTENexus::DeviceUpdateLEDs() +{ + for(unsigned int zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + UpdateZoneLEDs(zone_idx); + } +} + +void RGBController_HYTENexus::UpdateZoneLEDs(int zone) +{ + controller->LEDStreaming(zone, zones[zone].leds_count, zones[zone].colors); +} + +void RGBController_HYTENexus::UpdateSingleLED(int led) +{ + UpdateZoneLEDs(leds[led].value); +} + +void RGBController_HYTENexus::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} diff --git a/Controllers/HYTENexusController/RGBController_HYTENexus.h b/Controllers/HYTENexusController/RGBController_HYTENexus.h new file mode 100644 index 00000000..aa1670af --- /dev/null +++ b/Controllers/HYTENexusController/RGBController_HYTENexus.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_HYTENexus.h | +| | +| RGBController for HYTE Nexus | +| | +| Adam Honse (calcprogrammer1@gmail.com) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "HYTENexusController.h" +#include "RGBController.h" + +class RGBController_HYTENexus : public RGBController +{ +public: + RGBController_HYTENexus(HYTENexusController* controller_ptr); + ~RGBController_HYTENexus(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + HYTENexusController* controller; +}; diff --git a/Controllers/HoltekController/HoltekA070Controller.h b/Controllers/HoltekController/HoltekA070Controller.h deleted file mode 100644 index 7005339d..00000000 --- a/Controllers/HoltekController/HoltekA070Controller.h +++ /dev/null @@ -1,48 +0,0 @@ -/*---------------------------------------------------------------*\ -| HoltekA070Controller.h | -| | -| Definitions and types for Holtek USB Gaming Mouse [04d9:a070] | -| | -| Santeri Pikarinen (santeri3700) 8/01/2020 | -\*---------------------------------------------------------------*/ - -#include "RGBController.h" - -#include -#include - -#pragma once - -enum -{ - HOLTEK_A070_MODE_STATIC = 0x01, - HOLTEK_A070_MODE_BREATHING_SLOW = 0x02, - HOLTEK_A070_MODE_BREATHING_MEDIUM = 0x03, - HOLTEK_A070_MODE_BREATHING_FAST = 0x04 -}; - -class HoltekA070Controller -{ -public: - HoltekA070Controller(hid_device* dev_handle, const char* path); - ~HoltekA070Controller(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - - void SendCustomColor - ( - unsigned char red, - unsigned char green, - unsigned char blue - ); - - void SendMode - ( - unsigned char mode - ); - -private: - hid_device* dev; - std::string location; -}; diff --git a/Controllers/HoltekController/HoltekA070Controller.cpp b/Controllers/HoltekController/HoltekA070Controller/HoltekA070Controller.cpp similarity index 80% rename from Controllers/HoltekController/HoltekA070Controller.cpp rename to Controllers/HoltekController/HoltekA070Controller/HoltekA070Controller.cpp index 6bc14141..7a9ba50f 100644 --- a/Controllers/HoltekController/HoltekA070Controller.cpp +++ b/Controllers/HoltekController/HoltekA070Controller/HoltekA070Controller.cpp @@ -1,19 +1,23 @@ -/*-----------------------------------------------*\ -| HoltekA070Controller.cpp | -| | -| Driver for Holtek USB Gaming Mouse [04d9:a070] | -| | -| Santeri Pikarinen (santeri3700) 8/01/2020 | -\*-----------------------------------------------*/ - -#include "HoltekA070Controller.h" +/*---------------------------------------------------------*\ +| HoltekA070Controller.cpp | +| | +| Driver for Holtek mouse | +| | +| Santeri Pikarinen (santeri3700) 01 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "HoltekA070Controller.h" +#include "StringUtils.h" -HoltekA070Controller::HoltekA070Controller(hid_device* dev_handle, const char* path) +HoltekA070Controller::HoltekA070Controller(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } HoltekA070Controller::~HoltekA070Controller() @@ -26,6 +30,11 @@ std::string HoltekA070Controller::GetDeviceLocation() return("HID: " + location); } +std::string HoltekA070Controller::GetNameString() +{ + return(name); +} + std::string HoltekA070Controller::GetSerialString() { wchar_t serial_string[128]; @@ -36,10 +45,7 @@ std::string HoltekA070Controller::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } /*-------------------------------------------------------------------------------------------------*\ diff --git a/Controllers/HoltekController/HoltekA070Controller/HoltekA070Controller.h b/Controllers/HoltekController/HoltekA070Controller/HoltekA070Controller.h new file mode 100644 index 00000000..37c55423 --- /dev/null +++ b/Controllers/HoltekController/HoltekA070Controller/HoltekA070Controller.h @@ -0,0 +1,51 @@ +/*---------------------------------------------------------*\ +| HoltekA070Controller.h | +| | +| Driver for Holtek mouse | +| | +| Santeri Pikarinen (santeri3700) 01 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include + +enum +{ + HOLTEK_A070_MODE_STATIC = 0x01, + HOLTEK_A070_MODE_BREATHING_SLOW = 0x02, + HOLTEK_A070_MODE_BREATHING_MEDIUM = 0x03, + HOLTEK_A070_MODE_BREATHING_FAST = 0x04 +}; + +class HoltekA070Controller +{ +public: + HoltekA070Controller(hid_device* dev_handle, const char* path, std::string dev_name); + ~HoltekA070Controller(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SendCustomColor + ( + unsigned char red, + unsigned char green, + unsigned char blue + ); + + void SendMode + ( + unsigned char mode + ); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/HoltekController/HoltekA070Controller/RGBController_HoltekA070.cpp b/Controllers/HoltekController/HoltekA070Controller/RGBController_HoltekA070.cpp new file mode 100644 index 00000000..67cdf9ee --- /dev/null +++ b/Controllers/HoltekController/HoltekA070Controller/RGBController_HoltekA070.cpp @@ -0,0 +1,107 @@ +/*---------------------------------------------------------*\ +| RGBController_HoltekA070.cpp | +| | +| RGBController for Holtek mouse | +| | +| Santeri Pikarinen (santeri3700) 01 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_HoltekA070.h" + +/**------------------------------------------------------------------*\ + @name Holtek A070 + @category Mouse + @type USB + @save :x: + @direct :x: + @effects :white_check_mark: + @detectors DetectHoltekControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_HoltekA070::RGBController_HoltekA070(HoltekA070Controller* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "Holtek"; + type = DEVICE_TYPE_MOUSE; + description = "Holtek USB Gaming Mouse Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Static; + Static.name = "Static"; + Static.speed = HOLTEK_A070_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Static.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Static); + + mode Breathing; + Breathing.name = "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 = HOLTEK_A070_MODE_BREATHING_SLOW; + Breathing.speed_max = HOLTEK_A070_MODE_BREATHING_FAST; + Breathing.speed = HOLTEK_A070_MODE_BREATHING_MEDIUM; + modes.push_back(Breathing); + + SetupZones(); +} + +RGBController_HoltekA070::~RGBController_HoltekA070() +{ + delete controller; +} + +void RGBController_HoltekA070::SetupZones() +{ + zone mouse_zone; + mouse_zone.name = "Mouse"; + mouse_zone.type = ZONE_TYPE_SINGLE; + mouse_zone.leds_min = 1; + mouse_zone.leds_max = 1; + mouse_zone.leds_count = 1; + mouse_zone.matrix_map = NULL; + zones.push_back(mouse_zone); + + led mouse_led; + mouse_led.name = "Mouse"; + leds.push_back(mouse_led); + + SetupColors(); +} + +void RGBController_HoltekA070::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_HoltekA070::DeviceUpdateLEDs() +{ + unsigned char red = RGBGetRValue(colors[0]); + unsigned char green = RGBGetGValue(colors[0]); + unsigned char blue = RGBGetBValue(colors[0]); + + controller->SendCustomColor(red, green, blue); +} + +void RGBController_HoltekA070::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_HoltekA070::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_HoltekA070::DeviceUpdateMode() +{ + controller->SendMode(modes[active_mode].speed); +} diff --git a/Controllers/HoltekController/HoltekA070Controller/RGBController_HoltekA070.h b/Controllers/HoltekController/HoltekA070Controller/RGBController_HoltekA070.h new file mode 100644 index 00000000..34f436c6 --- /dev/null +++ b/Controllers/HoltekController/HoltekA070Controller/RGBController_HoltekA070.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_HoltekA070.h | +| | +| RGBController for Holtek mouse | +| | +| Santeri Pikarinen (santeri3700) 01 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "HoltekA070Controller.h" + +class RGBController_HoltekA070 : public RGBController +{ +public: + RGBController_HoltekA070(HoltekA070Controller* controller_ptr); + ~RGBController_HoltekA070(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + HoltekA070Controller* controller; +}; diff --git a/Controllers/HoltekController/HoltekA1FAController.cpp b/Controllers/HoltekController/HoltekA1FAController.cpp deleted file mode 100644 index ae52f70d..00000000 --- a/Controllers/HoltekController/HoltekA1FAController.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/*-----------------------------------------------*\ -| HoltekA1FAController.cpp | -| | -| Driver for Holtek based Mousemat [04d9:a1fa] | -| | -| Edoardo Ridolfi (edo2313) 26/12/2020 | -\*-----------------------------------------------*/ - -#include "HoltekA1FAController.h" - -#include - -HoltekA1FAController::HoltekA1FAController(hid_device *dev_handle, const char *path) -{ - dev = dev_handle; - location = path; -} - -HoltekA1FAController::~HoltekA1FAController() -{ - hid_close(dev); -} - - -std::string HoltekA1FAController::GetDeviceLocation() -{ - return ("HID: " + location); -} - -std::string HoltekA1FAController::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); -} - -/*-------------------------------------------------------------------------------------------------*\ -| Private packet sending functions. | -\*-------------------------------------------------------------------------------------------------*/ - -void HoltekA1FAController::SendData(unsigned char mode, unsigned char brightness, unsigned char speed, unsigned char preset, unsigned char red, unsigned char green, unsigned char blue) -{ - char usb_buf[9] = {0x00}; - - /*-----------------------------------------------------*\ - | Set up RGB Control packet | - \*-----------------------------------------------------*/ - usb_buf[HOLTEK_A1FA_BYTE_COMMAND] = 0x08; - usb_buf[HOLTEK_A1FA_BYTE_MODE] = mode; - usb_buf[HOLTEK_A1FA_BYTE_BRIGHTNESS] = brightness; - usb_buf[HOLTEK_A1FA_BYTE_SPEED] = speed; - usb_buf[HOLTEK_A1FA_BYTE_PRESET] = preset; - usb_buf[HOLTEK_A1FA_BYTE_RED] = red; - usb_buf[HOLTEK_A1FA_BYTE_GREEN] = green; - usb_buf[HOLTEK_A1FA_BYTE_BLUE] = blue; - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_send_feature_report(dev, (unsigned char *)usb_buf, sizeof(usb_buf)); -} diff --git a/Controllers/HoltekController/HoltekA1FAController.h b/Controllers/HoltekController/HoltekA1FAController.h deleted file mode 100644 index e2b78585..00000000 --- a/Controllers/HoltekController/HoltekA1FAController.h +++ /dev/null @@ -1,61 +0,0 @@ -/*---------------------------------------------------------------*\ -| HoltekA1FAController.h | -| | -| Definitions and types for Holtek based Mousemat [04d9:a1fa] | -| | -| Edoardo Ridolfi (edo2313) 26/12/2020 | -\*---------------------------------------------------------------*/ - -#include "RGBController.h" - -#include -#include - -#pragma once - -enum -{ - HOLTEK_A1FA_BYTE_COMMAND = 1, - HOLTEK_A1FA_BYTE_MODE = 2, - HOLTEK_A1FA_BYTE_BRIGHTNESS = 3, - HOLTEK_A1FA_BYTE_SPEED = 4, - HOLTEK_A1FA_BYTE_PRESET = 5, - HOLTEK_A1FA_BYTE_RED = 6, - HOLTEK_A1FA_BYTE_GREEN = 7, - HOLTEK_A1FA_BYTE_BLUE = 8 - -}; - -enum -{ - HOLTEK_A1FA_MODE_STATIC = 0x00, - HOLTEK_A1FA_MODE_BREATHING = 0x01, - HOLTEK_A1FA_MODE_NEON = 0x02, - HOLTEK_A1FA_MODE_RAINBOW = 0x03 -}; - -enum -{ - HOLTEK_A1FA_SPEED_SLOWEST = 0x00, /* Slowest speed */ - HOLTEK_A1FA_SPEED_SLOWER = 0x01, /* Slower speed */ - HOLTEK_A1FA_SPEED_SLOW = 0x02, /* Slow speed */ - HOLTEK_A1FA_SPEED_NORMAL = 0x03, /* Normal speed */ - HOLTEK_A1FA_SPEED_FAST = 0x04, /* Fast speed */ - HOLTEK_A1FA_SPEED_FASTEST = 0x05 /* Fastest speed */ -}; - -class HoltekA1FAController -{ -public: - HoltekA1FAController(hid_device *dev_handle, const char *path); - ~HoltekA1FAController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - - void SendData(unsigned char mode, unsigned char brightness, unsigned char speed, unsigned char preset, unsigned char red, unsigned char green, unsigned char blue); - -private: - hid_device *dev; - std::string location; -}; diff --git a/Controllers/HoltekController/HoltekA1FAController/HoltekA1FAController.cpp b/Controllers/HoltekController/HoltekA1FAController/HoltekA1FAController.cpp new file mode 100644 index 00000000..66765b84 --- /dev/null +++ b/Controllers/HoltekController/HoltekA1FAController/HoltekA1FAController.cpp @@ -0,0 +1,75 @@ +/*---------------------------------------------------------*\ +| HoltekA1FAController.cpp | +| | +| Driver for Holtek mousemat | +| | +| Edoardo Ridolfi (edo2313) 26 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "HoltekA1FAController.h" +#include "StringUtils.h" + +HoltekA1FAController::HoltekA1FAController(hid_device *dev_handle, const char *path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; +} + +HoltekA1FAController::~HoltekA1FAController() +{ + hid_close(dev); +} + +std::string HoltekA1FAController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string HoltekA1FAController::GetNameString() +{ + return(name); +} + +std::string HoltekA1FAController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +/*-------------------------------------------------------------------------------------------------*\ +| Private packet sending functions. | +\*-------------------------------------------------------------------------------------------------*/ + +void HoltekA1FAController::SendData(unsigned char mode, unsigned char brightness, unsigned char speed, unsigned char preset, unsigned char red, unsigned char green, unsigned char blue) +{ + char usb_buf[9] = {0x00}; + + /*-----------------------------------------------------*\ + | Set up RGB Control packet | + \*-----------------------------------------------------*/ + usb_buf[HOLTEK_A1FA_BYTE_COMMAND] = 0x08; + usb_buf[HOLTEK_A1FA_BYTE_MODE] = mode; + usb_buf[HOLTEK_A1FA_BYTE_BRIGHTNESS] = brightness; + usb_buf[HOLTEK_A1FA_BYTE_SPEED] = speed; + usb_buf[HOLTEK_A1FA_BYTE_PRESET] = preset; + usb_buf[HOLTEK_A1FA_BYTE_RED] = red; + usb_buf[HOLTEK_A1FA_BYTE_GREEN] = green; + usb_buf[HOLTEK_A1FA_BYTE_BLUE] = blue; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_send_feature_report(dev, (unsigned char *)usb_buf, sizeof(usb_buf)); +} diff --git a/Controllers/HoltekController/HoltekA1FAController/HoltekA1FAController.h b/Controllers/HoltekController/HoltekA1FAController/HoltekA1FAController.h new file mode 100644 index 00000000..2d7004e9 --- /dev/null +++ b/Controllers/HoltekController/HoltekA1FAController/HoltekA1FAController.h @@ -0,0 +1,65 @@ +/*---------------------------------------------------------*\ +| HoltekA1FAController.h | +| | +| Driver for Holtek mousemat | +| | +| Edoardo Ridolfi (edo2313) 26 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +enum +{ + HOLTEK_A1FA_BYTE_COMMAND = 1, + HOLTEK_A1FA_BYTE_MODE = 2, + HOLTEK_A1FA_BYTE_BRIGHTNESS = 3, + HOLTEK_A1FA_BYTE_SPEED = 4, + HOLTEK_A1FA_BYTE_PRESET = 5, + HOLTEK_A1FA_BYTE_RED = 6, + HOLTEK_A1FA_BYTE_GREEN = 7, + HOLTEK_A1FA_BYTE_BLUE = 8 + +}; + +enum +{ + HOLTEK_A1FA_MODE_STATIC = 0x00, + HOLTEK_A1FA_MODE_BREATHING = 0x01, + HOLTEK_A1FA_MODE_NEON = 0x02, + HOLTEK_A1FA_MODE_RAINBOW = 0x03 +}; + +enum +{ + HOLTEK_A1FA_SPEED_SLOWEST = 0x00, /* Slowest speed */ + HOLTEK_A1FA_SPEED_SLOWER = 0x01, /* Slower speed */ + HOLTEK_A1FA_SPEED_SLOW = 0x02, /* Slow speed */ + HOLTEK_A1FA_SPEED_NORMAL = 0x03, /* Normal speed */ + HOLTEK_A1FA_SPEED_FAST = 0x04, /* Fast speed */ + HOLTEK_A1FA_SPEED_FASTEST = 0x05 /* Fastest speed */ +}; + +class HoltekA1FAController +{ +public: + HoltekA1FAController(hid_device *dev_handle, const char *path, std::string dev_name); + ~HoltekA1FAController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SendData(unsigned char mode, unsigned char brightness, unsigned char speed, unsigned char preset, unsigned char red, unsigned char green, unsigned char blue); + +private: + hid_device *dev; + std::string location; + std::string name; +}; diff --git a/Controllers/HoltekController/HoltekA1FAController/RGBController_HoltekA1FA.cpp b/Controllers/HoltekController/HoltekA1FAController/RGBController_HoltekA1FA.cpp new file mode 100644 index 00000000..e2078ba7 --- /dev/null +++ b/Controllers/HoltekController/HoltekA1FAController/RGBController_HoltekA1FA.cpp @@ -0,0 +1,150 @@ +/*---------------------------------------------------------*\ +| RGBController_HoltekA1FA.cpp | +| | +| RGBController for Holtek mousemat | +| | +| Edoardo Ridolfi (edo2313) 26 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_HoltekA1FA.h" + +/**------------------------------------------------------------------*\ + @name Holtek A1FA + @category Mouse + @type USB + @save :x: + @direct :x: + @effects :white_check_mark: + @detectors DetectHoltekMousemats + @comment +\*-------------------------------------------------------------------*/ + +RGBController_HoltekA1FA::RGBController_HoltekA1FA(HoltekA1FAController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "Holtek"; + type = DEVICE_TYPE_MOUSEMAT; + description = "Holtek Mousemat Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Static; + Static.name = "Static"; + Static.value = HOLTEK_A1FA_MODE_STATIC; + Static.speed = HOLTEK_A1FA_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Static.color_mode = MODE_COLORS_PER_LED; + Static.colors_min = 1; + Static.colors_max = 7; + Static.colors.resize(7); + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = HOLTEK_A1FA_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_RANDOM_COLOR; + Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.speed_min = HOLTEK_A1FA_SPEED_SLOWEST; + Breathing.speed_max = HOLTEK_A1FA_SPEED_FASTEST; + Breathing.speed = HOLTEK_A1FA_SPEED_NORMAL; + Breathing.colors_min = 1; + Breathing.colors_max = 7; + Breathing.colors.resize(7); + modes.push_back(Breathing); + + mode Neon; + Neon.name = "Neon"; + Neon.value = HOLTEK_A1FA_MODE_NEON; + Neon.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Neon.color_mode = MODE_COLORS_NONE; + Neon.speed_min = HOLTEK_A1FA_SPEED_SLOWEST; + Neon.speed_max = HOLTEK_A1FA_SPEED_FASTEST; + Neon.speed = HOLTEK_A1FA_SPEED_NORMAL; + modes.push_back(Neon); + + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = HOLTEK_A1FA_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.speed_min = HOLTEK_A1FA_SPEED_SLOWEST; + Rainbow.speed_max = HOLTEK_A1FA_SPEED_FASTEST; + Rainbow.speed = HOLTEK_A1FA_SPEED_NORMAL; + modes.push_back(Rainbow); + + SetupZones(); +} + +RGBController_HoltekA1FA::~RGBController_HoltekA1FA() +{ + delete controller; +} + +void RGBController_HoltekA1FA::SetupZones() +{ + zone mouse_zone; + mouse_zone.name = "Mousemat"; + mouse_zone.type = ZONE_TYPE_SINGLE; + mouse_zone.leds_min = 1; + mouse_zone.leds_max = 1; + mouse_zone.leds_count = 1; + mouse_zone.matrix_map = NULL; + zones.push_back(mouse_zone); + + led mouse_led; + mouse_led.name = "Mousemat"; + leds.push_back(mouse_led); + + SetupColors(); +} + +void RGBController_HoltekA1FA::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_HoltekA1FA::DeviceUpdateLEDs() +{ + unsigned char mode = modes[active_mode].value; + unsigned char brightness = 0x20; /*When brightness support is added, change this */ + unsigned char speed = modes[active_mode].speed; + unsigned char preset = (modes[active_mode].color_mode == MODE_COLORS_RANDOM) ? 0x70 : 0x00; + unsigned char red = RGBGetRValue(colors[0]); + unsigned char green = RGBGetGValue(colors[0]); + unsigned char blue = RGBGetBValue(colors[0]); + + controller->SendData(mode, brightness, speed, preset, red, green, blue); +} + +void RGBController_HoltekA1FA::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_HoltekA1FA::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_HoltekA1FA::DeviceUpdateMode() +{ + if((active_mode < HOLTEK_A1FA_MODE_NEON) && (previous_mode < HOLTEK_A1FA_MODE_NEON)) + { + //If we're switching from and to static and breathing then sync the mode colors + for(unsigned int i = 0; i < modes[active_mode].colors_max; i++) + { + modes[active_mode].colors[i] = modes[previous_mode].colors[i]; + } + } + + previous_mode = active_mode; + + DeviceUpdateLEDs(); +} diff --git a/Controllers/HoltekController/HoltekA1FAController/RGBController_HoltekA1FA.h b/Controllers/HoltekController/HoltekA1FAController/RGBController_HoltekA1FA.h new file mode 100644 index 00000000..d08a8781 --- /dev/null +++ b/Controllers/HoltekController/HoltekA1FAController/RGBController_HoltekA1FA.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_HoltekA1FA.h | +| | +| RGBController for Holtek mousemat | +| | +| Edoardo Ridolfi (edo2313) 26 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "HoltekA1FAController.h" + +class RGBController_HoltekA1FA : public RGBController +{ +public: + RGBController_HoltekA1FA(HoltekA1FAController* controller_ptr); + ~RGBController_HoltekA1FA(); + + int previous_mode = 0; /* previous mode */ + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + HoltekA1FAController* controller; +}; diff --git a/Controllers/HoltekController/HoltekControllerDetect.cpp b/Controllers/HoltekController/HoltekControllerDetect.cpp index 8d3032ba..b18e48b1 100644 --- a/Controllers/HoltekController/HoltekControllerDetect.cpp +++ b/Controllers/HoltekController/HoltekControllerDetect.cpp @@ -1,11 +1,18 @@ +/*---------------------------------------------------------*\ +| HoltekControllerDetect.cpp | +| | +| Detector for Holtek devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "HoltekA070Controller.h" -#include "RGBController.h" #include "RGBController_HoltekA070.h" #include "HoltekA1FAController.h" #include "RGBController_HoltekA1FA.h" -#include -#include /*-----------------------------------------------------*\ | Holtek Semiconductor Inc. vendor ID | @@ -26,9 +33,8 @@ void DetectHoltekControllers(hid_device_info* info, const std::string& name) if(dev) { - HoltekA070Controller* controller = new HoltekA070Controller(dev, info->path); + HoltekA070Controller* controller = new HoltekA070Controller(dev, info->path, name); RGBController_HoltekA070* rgb_controller = new RGBController_HoltekA070(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -40,9 +46,8 @@ void DetectHoltekMousemats(hid_device_info *info, const std::string &name) if(dev) { - HoltekA1FAController* controller = new HoltekA1FAController(dev, info->path); + HoltekA1FAController* controller = new HoltekA1FAController(dev, info->path, name); RGBController_HoltekA1FA* rgb_controller = new RGBController_HoltekA1FA(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } diff --git a/Controllers/HoltekController/RGBController_HoltekA070.cpp b/Controllers/HoltekController/RGBController_HoltekA070.cpp deleted file mode 100644 index a083d3cb..00000000 --- a/Controllers/HoltekController/RGBController_HoltekA070.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/*--------------------------------------------------------------*\ -| RGBController_HoltekA070.cpp | -| | -| Generic RGB Interface for Holtek USB Gaming Mouse [04d9:a070] | -| | -| Santeri Pikarinen (santeri3700) 8/01/2020 | -\*--------------------------------------------------------------*/ - -#include "RGBController_HoltekA070.h" - -/**------------------------------------------------------------------*\ - @name Holtek A070 - @category Mouse - @type USB - @save :x: - @direct :x: - @effects :white_check_mark: - @detectors DetectHoltekControllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_HoltekA070::RGBController_HoltekA070(HoltekA070Controller* controller_ptr) -{ - controller = controller_ptr; - - name = "Holtek USB Gaming Mouse Device"; - vendor = "Holtek"; - type = DEVICE_TYPE_MOUSE; - description = "Holtek USB Gaming Mouse Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - mode Static; - Static.name = "Static"; - Static.speed = HOLTEK_A070_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Static.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Static); - - mode Breathing; - Breathing.name = "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 = HOLTEK_A070_MODE_BREATHING_SLOW; - Breathing.speed_max = HOLTEK_A070_MODE_BREATHING_FAST; - Breathing.speed = HOLTEK_A070_MODE_BREATHING_MEDIUM; - modes.push_back(Breathing); - - SetupZones(); -} - -RGBController_HoltekA070::~RGBController_HoltekA070() -{ - delete controller; -} - -void RGBController_HoltekA070::SetupZones() -{ - zone mouse_zone; - mouse_zone.name = "Mouse"; - mouse_zone.type = ZONE_TYPE_SINGLE; - mouse_zone.leds_min = 1; - mouse_zone.leds_max = 1; - mouse_zone.leds_count = 1; - mouse_zone.matrix_map = NULL; - zones.push_back(mouse_zone); - - led mouse_led; - mouse_led.name = "Mouse"; - leds.push_back(mouse_led); - - SetupColors(); -} - -void RGBController_HoltekA070::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_HoltekA070::DeviceUpdateLEDs() -{ - unsigned char red = RGBGetRValue(colors[0]); - unsigned char green = RGBGetGValue(colors[0]); - unsigned char blue = RGBGetBValue(colors[0]); - - controller->SendCustomColor(red, green, blue); -} - -void RGBController_HoltekA070::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_HoltekA070::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_HoltekA070::DeviceUpdateMode() -{ - controller->SendMode(modes[active_mode].speed); -} diff --git a/Controllers/HoltekController/RGBController_HoltekA070.h b/Controllers/HoltekController/RGBController_HoltekA070.h deleted file mode 100644 index 45c07119..00000000 --- a/Controllers/HoltekController/RGBController_HoltekA070.h +++ /dev/null @@ -1,30 +0,0 @@ -/*--------------------------------------------------------------*\ -| RGBController_HoltekA070.h | -| | -| Generic RGB Interface for Holtek USB Gaming Mouse [04d9:a070] | -| | -| Santeri Pikarinen (santeri3700) 8/01/2020 | -\*--------------------------------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "HoltekA070Controller.h" - -class RGBController_HoltekA070 : public RGBController -{ -public: - RGBController_HoltekA070(HoltekA070Controller* controller_ptr); - ~RGBController_HoltekA070(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - HoltekA070Controller* controller; -}; diff --git a/Controllers/HoltekController/RGBController_HoltekA1FA.cpp b/Controllers/HoltekController/RGBController_HoltekA1FA.cpp deleted file mode 100644 index ef96fd51..00000000 --- a/Controllers/HoltekController/RGBController_HoltekA1FA.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/*--------------------------------------------------------------*\ -| RGBController_HoltekA1FA.cpp | -| | -| Generic RGB Interface for Holtek based Mousemat [04d9:a1fa] | -| | -| Edoardo Ridolfi (edo2313) 26/12/2020 | -\*--------------------------------------------------------------*/ - -#include "RGBController_HoltekA1FA.h" - -/**------------------------------------------------------------------*\ - @name Holtek A1FA - @category Mouse - @type USB - @save :x: - @direct :x: - @effects :white_check_mark: - @detectors DetectHoltekMousemats - @comment -\*-------------------------------------------------------------------*/ - -RGBController_HoltekA1FA::RGBController_HoltekA1FA(HoltekA1FAController* controller_ptr) -{ - controller = controller_ptr; - - name = "Holtek Mousemat Device"; - vendor = "Holtek"; - type = DEVICE_TYPE_MOUSEMAT; - description = "Holtek Mousemat Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - mode Static; - Static.name = "Static"; - Static.value = HOLTEK_A1FA_MODE_STATIC; - Static.speed = HOLTEK_A1FA_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Static.color_mode = MODE_COLORS_PER_LED; - Static.colors_min = 1; - Static.colors_max = 7; - Static.colors.resize(7); - modes.push_back(Static); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = HOLTEK_A1FA_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_RANDOM_COLOR; - Breathing.color_mode = MODE_COLORS_PER_LED; - Breathing.speed_min = HOLTEK_A1FA_SPEED_SLOWEST; - Breathing.speed_max = HOLTEK_A1FA_SPEED_FASTEST; - Breathing.speed = HOLTEK_A1FA_SPEED_NORMAL; - Breathing.colors_min = 1; - Breathing.colors_max = 7; - Breathing.colors.resize(7); - modes.push_back(Breathing); - - mode Neon; - Neon.name = "Neon"; - Neon.value = HOLTEK_A1FA_MODE_NEON; - Neon.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; - Neon.color_mode = MODE_COLORS_NONE; - Neon.speed_min = HOLTEK_A1FA_SPEED_SLOWEST; - Neon.speed_max = HOLTEK_A1FA_SPEED_FASTEST; - Neon.speed = HOLTEK_A1FA_SPEED_NORMAL; - modes.push_back(Neon); - - mode Rainbow; - Rainbow.name = "Rainbow"; - Rainbow.value = HOLTEK_A1FA_MODE_RAINBOW; - Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; - Rainbow.color_mode = MODE_COLORS_NONE; - Rainbow.speed_min = HOLTEK_A1FA_SPEED_SLOWEST; - Rainbow.speed_max = HOLTEK_A1FA_SPEED_FASTEST; - Rainbow.speed = HOLTEK_A1FA_SPEED_NORMAL; - modes.push_back(Rainbow); - - SetupZones(); -} - -RGBController_HoltekA1FA::~RGBController_HoltekA1FA() -{ - delete controller; -} - -void RGBController_HoltekA1FA::SetupZones() -{ - zone mouse_zone; - mouse_zone.name = "Mousemat"; - mouse_zone.type = ZONE_TYPE_SINGLE; - mouse_zone.leds_min = 1; - mouse_zone.leds_max = 1; - mouse_zone.leds_count = 1; - mouse_zone.matrix_map = NULL; - zones.push_back(mouse_zone); - - led mouse_led; - mouse_led.name = "Mousemat"; - leds.push_back(mouse_led); - - SetupColors(); -} - -void RGBController_HoltekA1FA::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_HoltekA1FA::DeviceUpdateLEDs() -{ - unsigned char mode = modes[active_mode].value; - unsigned char brightness = 0x20; /*When brightness support is added, change this */ - unsigned char speed = modes[active_mode].speed; - unsigned char preset = (modes[active_mode].color_mode == MODE_COLORS_RANDOM) ? 0x70 : 0x00; - unsigned char red = RGBGetRValue(colors[0]); - unsigned char green = RGBGetGValue(colors[0]); - unsigned char blue = RGBGetBValue(colors[0]); - - controller->SendData(mode, brightness, speed, preset, red, green, blue); -} - -void RGBController_HoltekA1FA::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_HoltekA1FA::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_HoltekA1FA::DeviceUpdateMode() -{ - if((active_mode < HOLTEK_A1FA_MODE_NEON) && (previous_mode < HOLTEK_A1FA_MODE_NEON)) - { - //If we're switching from and to static and breathing then sync the mode colors - for(unsigned int i = 0; i < modes[active_mode].colors_max; i++) - { - modes[active_mode].colors[i] = modes[previous_mode].colors[i]; - } - } - - previous_mode = active_mode; - - DeviceUpdateLEDs(); -} diff --git a/Controllers/HoltekController/RGBController_HoltekA1FA.h b/Controllers/HoltekController/RGBController_HoltekA1FA.h deleted file mode 100644 index b79ab80e..00000000 --- a/Controllers/HoltekController/RGBController_HoltekA1FA.h +++ /dev/null @@ -1,32 +0,0 @@ -/*--------------------------------------------------------------*\ -| RGBController_HoltekA1FA.h | -| | -| Generic RGB Interface for Holtek based Mousemat [04d9:a1fa] | -| | -| Edoardo Ridolfi (edo2313) 26/12/2020 | -\*--------------------------------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "HoltekA1FAController.h" - -class RGBController_HoltekA1FA : public RGBController -{ -public: - RGBController_HoltekA1FA(HoltekA1FAController* controller_ptr); - ~RGBController_HoltekA1FA(); - - int previous_mode = 0; /* previous mode */ - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - HoltekA1FAController* controller; -}; diff --git a/Controllers/HyperXDRAMController/HyperXDRAMController.cpp b/Controllers/HyperXDRAMController/HyperXDRAMController.cpp index 74283b40..8253c87d 100644 --- a/Controllers/HyperXDRAMController/HyperXDRAMController.cpp +++ b/Controllers/HyperXDRAMController/HyperXDRAMController.cpp @@ -1,19 +1,22 @@ -/*-----------------------------------------*\ -| HyperXDRAMController.cpp | -| | -| Definitions and types for HyperX Predator| -| and Fury RGB RAM lighting controller | -| | -| Adam Honse (CalcProgrammer1) 6/29/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| HyperXDRAMController.cpp | +| | +| Driver for HyperX/Kingston Fury RAM | +| | +| Adam Honse (CalcProgrammer1) 19 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "HyperXDRAMController.h" #include +#include "HyperXDRAMController.h" -HyperXDRAMController::HyperXDRAMController(i2c_smbus_interface* bus, hyperx_dev_id dev, unsigned char slots) +HyperXDRAMController::HyperXDRAMController(i2c_smbus_interface* bus, hyperx_dev_id dev, unsigned char slots, std::string dev_name) { this->bus = bus; this->dev = dev; + this->name = dev_name; slots_valid = slots; led_count = 0; @@ -45,6 +48,11 @@ std::string HyperXDRAMController::GetDeviceLocation() return("I2C: " + return_string); } +std::string HyperXDRAMController::GetDeviceName() +{ + return(name); +} + unsigned int HyperXDRAMController::GetLEDCount() { return(led_count); @@ -188,7 +196,7 @@ void HyperXDRAMController::SetMode(unsigned char new_mode, bool random, unsigned { mode = new_mode; speed = new_speed; - + bus->i2c_smbus_write_byte_data(dev, HYPERX_REG_APPLY, 0x01); /*-----------------------------------------------------*\ @@ -206,7 +214,7 @@ void HyperXDRAMController::SetMode(unsigned char new_mode, bool random, unsigned { mode_reg = HYPERX_REG_MODE_CUSTOM; } - + switch (mode) { case HYPERX_MODE_DIRECT: diff --git a/Controllers/HyperXDRAMController/HyperXDRAMController.h b/Controllers/HyperXDRAMController/HyperXDRAMController.h index f640232c..574eb804 100644 --- a/Controllers/HyperXDRAMController/HyperXDRAMController.h +++ b/Controllers/HyperXDRAMController/HyperXDRAMController.h @@ -1,17 +1,19 @@ -/*-----------------------------------------*\ -| HyperXDRAMController.h | -| | -| Definitions and types for HyperX Predator| -| and Fury RGB RAM lighting controller | -| | -| Adam Honse (CalcProgrammer1) 6/29/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| HyperXDRAMController.h | +| | +| Driver for HyperX/Kingston Fury RAM | +| | +| Adam Honse (CalcProgrammer1) 19 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" -#pragma once - typedef unsigned char hyperx_dev_id; typedef unsigned short hyperx_register; @@ -204,10 +206,12 @@ static const unsigned char slot_map[4] = class HyperXDRAMController { public: - HyperXDRAMController(i2c_smbus_interface* bus, hyperx_dev_id dev, unsigned char slots); + HyperXDRAMController(i2c_smbus_interface* bus, hyperx_dev_id dev, unsigned char slots, std::string dev_name); ~HyperXDRAMController(); std::string GetDeviceLocation(); + std::string GetDeviceName(); + unsigned int GetLEDCount(); unsigned int GetSlotCount(); unsigned int GetMode(); @@ -228,4 +232,5 @@ private: hyperx_dev_id dev; unsigned int mode; unsigned short speed; + std::string name; }; diff --git a/Controllers/HyperXDRAMController/HyperXDRAMControllerDetect.cpp b/Controllers/HyperXDRAMController/HyperXDRAMControllerDetect.cpp index 922d2a5f..1abde868 100644 --- a/Controllers/HyperXDRAMController/HyperXDRAMControllerDetect.cpp +++ b/Controllers/HyperXDRAMController/HyperXDRAMControllerDetect.cpp @@ -1,13 +1,21 @@ +/*---------------------------------------------------------*\ +| HyperXDRAMControllerDetect.cpp | +| | +| Driver for HyperX/Kingston Fury RAM | +| | +| Adam Honse (CalcProgrammer1) 19 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "HyperXDRAMController.h" #include "LogManager.h" -#include "RGBController.h" #include "RGBController_HyperXDRAM.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include using namespace std::chrono_literals; @@ -55,92 +63,61 @@ bool TestForHyperXDRAMController(i2c_smbus_interface* bus, unsigned char address * Detect HyperX DRAM controllers on the enumerated I2C busses. * * * * bus - pointer to i2c_smbus_interface where Aura device is connected * -* dev - I2C address of Aura device * +* slots - accessors to SPD information of the occupied slots * * * \******************************************************************************************/ -void DetectHyperXDRAMControllers(std::vector &busses) +void DetectHyperXDRAMControllers(i2c_smbus_interface* bus, std::vector &slots, const std::string &/*name*/) { - for(unsigned int bus = 0; bus < busses.size(); bus++) + unsigned char slots_valid = 0x00; + bool fury_detected = false; + bool pred_detected = false; + + // Check for HyperX controller at 0x27 + LOG_DEBUG("[%s] Testing bus %d at address 0x27", HYPERX_CONTROLLER_NAME, bus->port_id); + + if(TestForHyperXDRAMController(bus, 0x27)) { - unsigned char slots_valid = 0x00; - bool fury_detected = false; - bool pred_detected = false; - - LOG_DEBUG("[%s] Checking VID/PID on bus %d...", HYPERX_CONTROLLER_NAME, bus); - - IF_DRAM_SMBUS(busses[bus]->pci_vendor, busses[bus]->pci_device) + for(SPDWrapper *slot : slots) { - // Check for HyperX controller at 0x27 - LOG_DEBUG("[%s] Testing bus %d at address 0x27", HYPERX_CONTROLLER_NAME, bus); + LOG_DEBUG("[%s] SPD check success", HYPERX_CONTROLLER_NAME); - if(TestForHyperXDRAMController(busses[bus], 0x27)) + slots_valid |= (1 << (slot->index())); + + if(slot->manufacturer_data(0x06) == 0x01) { - busses[bus]->i2c_smbus_write_byte_data(0x37, 0x00, 0xFF); - - std::this_thread::sleep_for(1ms); - - for(int slot_addr = 0x50; slot_addr <= 0x57; slot_addr++) - { - // Test for HyperX SPD at slot_addr - // This test was copied from NGENUITY software - // Tests SPD addresses in order: 0x40, 0x41 - int read_0x40 = busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x40); - int read_0x41 = busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x41); - - LOG_DEBUG("[%s] SPD check: 0x40 => %02X, 0x41 => %02X, ", - HYPERX_CONTROLLER_NAME, read_0x40, read_0x41); - - if((read_0x40 == 0x01) && (read_0x41 == 0x98)) - { - LOG_DEBUG("[%s] SPD check success", HYPERX_CONTROLLER_NAME); - - slots_valid |= (1 << (slot_addr - 0x50)); - - if(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x67) == 0x01) - { - fury_detected = true; - } - else - { - pred_detected = true; - } - } - else - { - LOG_DEBUG("[%s] SPD check failed", HYPERX_CONTROLLER_NAME); - } - - std::this_thread::sleep_for(1ms); - } - - LOG_DEBUG("[%s] slots_valid=%d fury_detected=%d pred_detected=%d", - HYPERX_CONTROLLER_NAME, slots_valid, fury_detected, pred_detected); - - if(slots_valid != 0) - { - HyperXDRAMController* controller = new HyperXDRAMController(busses[bus], 0x27, slots_valid); - RGBController_HyperXDRAM* rgb_controller = new RGBController_HyperXDRAM(controller); - - if(fury_detected && !pred_detected) - { - rgb_controller->name = "HyperX Fury RGB"; - } - else if(!fury_detected && pred_detected) - { - rgb_controller->name = "HyperX Predator RGB"; - } - - ResourceManager::get()->RegisterRGBController(rgb_controller); - } + fury_detected = true; } + else + { + pred_detected = true; + } + + std::this_thread::sleep_for(1ms); } - else + + LOG_DEBUG("[%s] slots_valid=%d fury_detected=%d pred_detected=%d", + HYPERX_CONTROLLER_NAME, slots_valid, fury_detected, pred_detected); + + if(slots_valid != 0) { - LOG_DEBUG("[%s] IF_DRAM_SMBUS was false for %04X %04X", HYPERX_CONTROLLER_NAME, busses[bus]->pci_vendor, busses[bus]->pci_device); + std::string name = "HyperX DRAM"; + + if(fury_detected && !pred_detected) + { + name = "HyperX Fury RGB"; + } + else if(!fury_detected && pred_detected) + { + name = "HyperX Predator RGB"; + } + + HyperXDRAMController* controller = new HyperXDRAMController(bus, 0x27, slots_valid, name); + RGBController_HyperXDRAM* rgb_controller = new RGBController_HyperXDRAM(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); } } - } /* DetectHyperXDRAMControllers() */ -REGISTER_I2C_DETECTOR("HyperX DRAM", DetectHyperXDRAMControllers); +REGISTER_I2C_DIMM_DETECTOR("HyperX DRAM", DetectHyperXDRAMControllers, JEDEC_KINGSTON, SPD_DDR4_SDRAM); diff --git a/Controllers/HyperXDRAMController/RGBController_HyperXDRAM.cpp b/Controllers/HyperXDRAMController/RGBController_HyperXDRAM.cpp index a8843adf..72ee7a63 100644 --- a/Controllers/HyperXDRAMController/RGBController_HyperXDRAM.cpp +++ b/Controllers/HyperXDRAMController/RGBController_HyperXDRAM.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_HyperXDRAM.cpp | -| | -| Generic RGB Interface for OpenAuraSDK | -| HyperX Predator and Fury RGB interface | -| | -| Adam Honse (CalcProgrammer1) 6/29/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_HyperXDRAM.cpp | +| | +| RGBController for HyperX/Kingston Fury RAM | +| | +| Adam Honse (CalcProgrammer1) 29 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_HyperXDRAM.h" @@ -22,113 +24,113 @@ RGBController_HyperXDRAM::RGBController_HyperXDRAM(HyperXDRAMController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "HyperX DRAM"; - vendor = "HyperX"; - type = DEVICE_TYPE_DRAM; - description = "HyperX DRAM Device"; - location = controller->GetDeviceLocation(); + name = controller->GetDeviceName(); + vendor = "HyperX"; + type = DEVICE_TYPE_DRAM; + description = "HyperX DRAM Device"; + location = controller->GetDeviceLocation(); mode Direct; - Direct.name = "Direct"; - Direct.value = HYPERX_MODE_DIRECT; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = HYPERX_MODE_DIRECT; + 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 = HYPERX_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Static.colors_min = 1; - Static.colors_max = 1; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.name = "Static"; + Static.value = HYPERX_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Static.colors_min = 1; + Static.colors_max = 1; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; Static.colors.resize(1); modes.push_back(Static); mode Rainbow; - Rainbow.name = "Rainbow"; - Rainbow.value = HYPERX_MODE_RAINBOW; - Rainbow.flags = MODE_FLAG_HAS_SPEED; - Rainbow.speed_min = HYPERX_SPEED_RAINBOW_SLOW; - Rainbow.speed_max = HYPERX_SPEED_RAINBOW_FAST; - Rainbow.speed = HYPERX_SPEED_RAINBOW_NORMAL; - Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.name = "Rainbow"; + Rainbow.value = HYPERX_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_SPEED; + Rainbow.speed_min = HYPERX_SPEED_RAINBOW_SLOW; + Rainbow.speed_max = HYPERX_SPEED_RAINBOW_FAST; + Rainbow.speed = HYPERX_SPEED_RAINBOW_NORMAL; + Rainbow.color_mode = MODE_COLORS_NONE; modes.push_back(Rainbow); mode Comet; - Comet.name = "Comet"; - Comet.value = HYPERX_MODE_COMET; - Comet.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; - Comet.speed_min = HYPERX_SPEED_COMET_SLOW; - Comet.speed_max = HYPERX_SPEED_COMET_FAST; - Comet.colors_min = 1; - Comet.colors_max = 1; - Comet.speed = HYPERX_SPEED_COMET_NORMAL; - Comet.color_mode = MODE_COLORS_MODE_SPECIFIC; + Comet.name = "Comet"; + Comet.value = HYPERX_MODE_COMET; + Comet.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + Comet.speed_min = HYPERX_SPEED_COMET_SLOW; + Comet.speed_max = HYPERX_SPEED_COMET_FAST; + Comet.colors_min = 1; + Comet.colors_max = 1; + Comet.speed = HYPERX_SPEED_COMET_NORMAL; + Comet.color_mode = MODE_COLORS_MODE_SPECIFIC; Comet.colors.resize(1); modes.push_back(Comet); mode Heartbeat; - Heartbeat.name = "Heartbeat"; - Heartbeat.value = HYPERX_MODE_HEARTBEAT; - Heartbeat.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; - Heartbeat.speed_min = HYPERX_SPEED_COMET_SLOW; - Heartbeat.speed_max = HYPERX_SPEED_COMET_FAST; - Heartbeat.colors_min = 1; - Heartbeat.colors_max = 1; - Heartbeat.speed = HYPERX_SPEED_COMET_NORMAL; - Heartbeat.color_mode = MODE_COLORS_MODE_SPECIFIC; + Heartbeat.name = "Heartbeat"; + Heartbeat.value = HYPERX_MODE_HEARTBEAT; + Heartbeat.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + Heartbeat.speed_min = HYPERX_SPEED_COMET_SLOW; + Heartbeat.speed_max = HYPERX_SPEED_COMET_FAST; + Heartbeat.colors_min = 1; + Heartbeat.colors_max = 1; + Heartbeat.speed = HYPERX_SPEED_COMET_NORMAL; + Heartbeat.color_mode = MODE_COLORS_MODE_SPECIFIC; Heartbeat.colors.resize(1); modes.push_back(Heartbeat); mode SpectrumCycle; - SpectrumCycle.name = "Spectrum Cycle"; - SpectrumCycle.value = HYPERX_MODE_CYCLE; - SpectrumCycle.flags = MODE_FLAG_HAS_SPEED; - SpectrumCycle.speed_min = HYPERX_SPEED_CYCLE_SLOW; - SpectrumCycle.speed_max = HYPERX_SPEED_CYCLE_FAST; - SpectrumCycle.speed = HYPERX_SPEED_CYCLE_NORMAL; - SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = HYPERX_MODE_CYCLE; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED; + SpectrumCycle.speed_min = HYPERX_SPEED_CYCLE_SLOW; + SpectrumCycle.speed_max = HYPERX_SPEED_CYCLE_FAST; + SpectrumCycle.speed = HYPERX_SPEED_CYCLE_NORMAL; + SpectrumCycle.color_mode = MODE_COLORS_NONE; modes.push_back(SpectrumCycle); mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = HYPERX_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; - Breathing.speed_min = HYPERX_SPEED_BREATHING_SLOW; - Breathing.speed_max = HYPERX_SPEED_BREATHING_FAST; - Breathing.colors_min = 1; - Breathing.colors_max = 1; - Breathing.speed = HYPERX_SPEED_BREATHING_NORMAL; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.name = "Breathing"; + Breathing.value = HYPERX_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + Breathing.speed_min = HYPERX_SPEED_BREATHING_SLOW; + Breathing.speed_max = HYPERX_SPEED_BREATHING_FAST; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.speed = HYPERX_SPEED_BREATHING_NORMAL; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; Breathing.colors.resize(1); modes.push_back(Breathing); mode Bounce; - Bounce.name = "Bounce"; - Bounce.value = HYPERX_MODE_BOUNCE; - Bounce.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; - Bounce.speed_min = HYPERX_SPEED_BOUNCE_SLOW; - Bounce.speed_max = HYPERX_SPEED_BOUNCE_FAST; - Bounce.colors_min = 1; - Bounce.colors_max = 1; - Bounce.speed = HYPERX_SPEED_BOUNCE_NORMAL; - Bounce.color_mode = MODE_COLORS_MODE_SPECIFIC; + Bounce.name = "Bounce"; + Bounce.value = HYPERX_MODE_BOUNCE; + Bounce.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + Bounce.speed_min = HYPERX_SPEED_BOUNCE_SLOW; + Bounce.speed_max = HYPERX_SPEED_BOUNCE_FAST; + Bounce.colors_min = 1; + Bounce.colors_max = 1; + Bounce.speed = HYPERX_SPEED_BOUNCE_NORMAL; + Bounce.color_mode = MODE_COLORS_MODE_SPECIFIC; Bounce.colors.resize(1); modes.push_back(Bounce); mode Blink; - Blink.name = "Blink"; - Blink.value = HYPERX_MODE_BLINK; - Blink.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; - Blink.speed_min = HYPERX_SPEED_BLINK_SLOW; - Blink.speed_max = HYPERX_SPEED_BLINK_FAST; - Blink.colors_min = 1; - Blink.colors_max = 1; - Blink.speed = HYPERX_SPEED_BLINK_NORMAL; - Blink.color_mode = MODE_COLORS_MODE_SPECIFIC; + Blink.name = "Blink"; + Blink.value = HYPERX_MODE_BLINK; + Blink.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + Blink.speed_min = HYPERX_SPEED_BLINK_SLOW; + Blink.speed_max = HYPERX_SPEED_BLINK_FAST; + Blink.colors_min = 1; + Blink.colors_max = 1; + Blink.speed = HYPERX_SPEED_BLINK_NORMAL; + Blink.color_mode = MODE_COLORS_MODE_SPECIFIC; Blink.colors.resize(1); modes.push_back(Blink); @@ -168,7 +170,7 @@ void RGBController_HyperXDRAM::SetupZones() new_led->name.append(", LED "); new_led->name.append(std::to_string(led_idx + 1)); - new_led->value = leds.size(); + new_led->value = (unsigned int)leds.size(); leds.push_back(*new_led); } @@ -188,7 +190,7 @@ void RGBController_HyperXDRAM::DeviceUpdateLEDs() { if(controller->GetMode() == HYPERX_MODE_DIRECT) { - for (std::size_t led_idx = 0; led_idx < colors.size(); led_idx++ ) + for(unsigned int led_idx = 0; led_idx < (unsigned int)colors.size(); led_idx++ ) { RGBColor color = colors[led_idx]; unsigned char red = RGBGetRValue(color); @@ -213,7 +215,7 @@ void RGBController_HyperXDRAM::UpdateZoneLEDs(int zone) { if(controller->GetMode() == HYPERX_MODE_DIRECT) { - for (std::size_t led_idx = 0; led_idx < zones[zone].leds_count; led_idx++ ) + for(std::size_t led_idx = 0; led_idx < zones[zone].leds_count; led_idx++ ) { unsigned int led = zones[zone].leds[led_idx].value; RGBColor color = colors[led]; diff --git a/Controllers/HyperXDRAMController/RGBController_HyperXDRAM.h b/Controllers/HyperXDRAMController/RGBController_HyperXDRAM.h index 855e6679..4071507c 100644 --- a/Controllers/HyperXDRAMController/RGBController_HyperXDRAM.h +++ b/Controllers/HyperXDRAMController/RGBController_HyperXDRAM.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_HyperXDRAM.h | -| | -| Generic RGB Interface for OpenAuraSDK | -| HyperX Predator and Fury RGB interface | -| | -| Adam Honse (CalcProgrammer1) 6/29/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_HyperXDRAM.h | +| | +| RGBController for HyperX/Kingston Fury RAM | +| | +| Adam Honse (CalcProgrammer1) 29 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller.h b/Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller.h deleted file mode 100644 index cf69ac74..00000000 --- a/Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| HyperXAlloyElite2Controller.h | -| | -| Definitions and types for HyperX Alloy | -| Elite2 RGB Keyboard lighting controller | -| | -| KundaPanda (vojdo) 02/04/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include - -#pragma once - -class HyperXAlloyElite2Controller -{ -public: - HyperXAlloyElite2Controller(hid_device* dev_handle, const char* path); - ~HyperXAlloyElite2Controller(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - - void SetLEDsDirect(const std::vector& colors); - -private: - hid_device* dev; - std::string location; - - void SendDirectInitialization(); -}; diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller.cpp b/Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller/HyperXAlloyElite2Controller.cpp similarity index 87% rename from Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller.cpp rename to Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller/HyperXAlloyElite2Controller.cpp index 380a5960..c4796642 100644 --- a/Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller.cpp +++ b/Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller/HyperXAlloyElite2Controller.cpp @@ -1,25 +1,28 @@ -/*-----------------------------------------*\ -| HyperXAlloyElite2Controller.cpp | -| | -| Driver for HyperX Alloy Elite2 RGB | -| Keyboard lighting controller | -| | -| KundaPanda (vojdo) 02/04/2021 | -\*-----------------------------------------*/ - -#include "HyperXAlloyElite2Controller.h" +/*---------------------------------------------------------*\ +| HyperXAlloyElite2Controller.cpp | +| | +| Driver for HyperX Alloy Elite 2 keyboard | +| | +| KundaPanda (vojdo) 02 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "HyperXAlloyElite2Controller.h" +#include "StringUtils.h" /*-----------------------------------------*\ | Skip these indices in the color output | \*-----------------------------------------*/ static const unsigned int SKIP_INDICES[] = { 23, 29, 41, 47, 70, 71, 76, 77, 87, 88, 93, 99, 100, 102, 108, 113 }; -HyperXAlloyElite2Controller::HyperXAlloyElite2Controller(hid_device* dev_handle, const char* path) +HyperXAlloyElite2Controller::HyperXAlloyElite2Controller(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } HyperXAlloyElite2Controller::~HyperXAlloyElite2Controller() @@ -32,6 +35,11 @@ std::string HyperXAlloyElite2Controller::GetDeviceLocation() return("HID " + location); } +std::string HyperXAlloyElite2Controller::GetNameString() +{ + return(name); +} + std::string HyperXAlloyElite2Controller::GetSerialString() { wchar_t serial_string[128]; @@ -42,10 +50,7 @@ std::string HyperXAlloyElite2Controller::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void HyperXAlloyElite2Controller::SetLEDsDirect(const std::vector& colors) @@ -131,7 +136,7 @@ void HyperXAlloyElite2Controller::SetLEDsDirect(const std::vector& col | Send packet | \*---------------------------------------------*/ hid_send_feature_report(dev, buf, sizeof(buf)); - + /*---------------------------------------------*\ | Zero out buffer and reset index | \*---------------------------------------------*/ diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller/HyperXAlloyElite2Controller.h b/Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller/HyperXAlloyElite2Controller.h new file mode 100644 index 00000000..d1c47f8f --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller/HyperXAlloyElite2Controller.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| HyperXAlloyElite2Controller.h | +| | +| Driver for HyperX Alloy Elite 2 keyboard | +| | +| KundaPanda (vojdo) 02 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +class HyperXAlloyElite2Controller +{ +public: + HyperXAlloyElite2Controller(hid_device* dev_handle, const char* path, std::string dev_name); + ~HyperXAlloyElite2Controller(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SetLEDsDirect(const std::vector& colors); + +private: + hid_device* dev; + std::string location; + std::string name; + + void SendDirectInitialization(); +}; diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite2.cpp b/Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller/RGBController_HyperXAlloyElite2.cpp similarity index 87% rename from Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite2.cpp rename to Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller/RGBController_HyperXAlloyElite2.cpp index 3d06f44d..c6447cbe 100644 --- a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite2.cpp +++ b/Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller/RGBController_HyperXAlloyElite2.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_HyperXAlloyElite2.cpp | -| | -| Generic RGB Interface for HyperX Alloy | -| Elite2 RGB Keyboard | -| | -| KundaPanda (vojdo) 02/04/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_HyperXAlloyElite2.cpp | +| | +| RGBController for HyperX Alloy Elite 2 keyboard | +| | +| KundaPanda (vojdo) 02 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_HyperXAlloyElite2.h" @@ -206,20 +208,20 @@ static const char *led_names[] = RGBController_HyperXAlloyElite2::RGBController_HyperXAlloyElite2(HyperXAlloyElite2Controller* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "HyperX Alloy Elite 2 Keyboard Device"; - vendor = "HyperX"; - type = DEVICE_TYPE_KEYBOARD; - description = "HyperX Alloy Elite 2 Keyboard Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "HyperX"; + type = DEVICE_TYPE_KEYBOARD; + description = "HyperX Alloy Elite 2 Keyboard Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0xFFFF; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); SetupZones(); diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller/RGBController_HyperXAlloyElite2.h b/Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller/RGBController_HyperXAlloyElite2.h new file mode 100644 index 00000000..425fbf9f --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller/RGBController_HyperXAlloyElite2.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------*\ +| RGBController_HyperXAlloyElite2.h | +| | +| RGBController for HyperX Alloy Elite 2 keyboard | +| | +| KundaPanda (vojdo) 02 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" +#include "HyperXAlloyElite2Controller.h" + +class RGBController_HyperXAlloyElite2 : public RGBController +{ +public: + RGBController_HyperXAlloyElite2(HyperXAlloyElite2Controller* controller_ptr); + ~RGBController_HyperXAlloyElite2(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + void KeepaliveThreadFunction(); + +private: + HyperXAlloyElite2Controller* controller; + std::atomic keepalive_thread_run; + std::thread* keepalive_thread; + std::chrono::time_point last_update_time; +}; diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyEliteController.cpp b/Controllers/HyperXKeyboardController/HyperXAlloyEliteController/HyperXAlloyEliteController.cpp similarity index 94% rename from Controllers/HyperXKeyboardController/HyperXAlloyEliteController.cpp rename to Controllers/HyperXKeyboardController/HyperXAlloyEliteController/HyperXAlloyEliteController.cpp index 703f75c3..204aa459 100644 --- a/Controllers/HyperXKeyboardController/HyperXAlloyEliteController.cpp +++ b/Controllers/HyperXKeyboardController/HyperXAlloyEliteController/HyperXAlloyEliteController.cpp @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| HyperXAlloyEliteController.cpp | -| | -| Driver for HyperX Alloy Elite Keyboard | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 1/30/2020 | -\*-----------------------------------------*/ - -#include "HyperXAlloyEliteController.h" +/*---------------------------------------------------------*\ +| HyperXAlloyEliteController.cpp | +| | +| Driver for HyperX Alloy Elite keyboard | +| | +| Adam Honse (CalcProgrammer1) 30 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "HyperXAlloyEliteController.h" +#include "StringUtils.h" using namespace std::chrono_literals; @@ -27,10 +29,11 @@ static unsigned int extended_red[] = {0x08, 0x48, 0x88, 0x09, 0x89, 0x0A, 0x8A, static unsigned int extended_grn[] = {0x29, 0x28, 0x78, 0x19, 0x79, 0x1A, 0x7A, 0x1B, 0x7B, 0x1C, 0x7C, 0x1D, 0x7D, 0x1E, 0x6E, 0x7E, 0x1F, 0x6F, 0x82, 0x23, 0x83, 0x22 }; static unsigned int extended_blu[] = {0x39, 0x38, 0x68, 0x3A, 0x69, 0x2A, 0x6A, 0x2B, 0x6B, 0x2C, 0x6C, 0x2D, 0x6D, 0x2E, 0x5E, 0x5D, 0x2F, 0x5F, 0x72, 0x33, 0x73, 0x32 }; -HyperXAlloyEliteController::HyperXAlloyEliteController(hid_device* dev_handle, const char* path) +HyperXAlloyEliteController::HyperXAlloyEliteController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } HyperXAlloyEliteController::~HyperXAlloyEliteController() @@ -43,6 +46,11 @@ std::string HyperXAlloyEliteController::GetDeviceLocation() return("HID: " + location); } +std::string HyperXAlloyEliteController::GetNameString() +{ + return(name); +} + std::string HyperXAlloyEliteController::GetSerialString() { wchar_t serial_string[128]; @@ -53,10 +61,7 @@ std::string HyperXAlloyEliteController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void HyperXAlloyEliteController::SetMode @@ -221,7 +226,7 @@ void HyperXAlloyEliteController::SetLEDs(std::vector colors) ); std::this_thread::sleep_for(5ms); - + SendExtendedColor ( 0x01, diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyEliteController.h b/Controllers/HyperXKeyboardController/HyperXAlloyEliteController/HyperXAlloyEliteController.h similarity index 83% rename from Controllers/HyperXKeyboardController/HyperXAlloyEliteController.h rename to Controllers/HyperXKeyboardController/HyperXAlloyEliteController/HyperXAlloyEliteController.h index fd23c984..a1aa846e 100644 --- a/Controllers/HyperXKeyboardController/HyperXAlloyEliteController.h +++ b/Controllers/HyperXKeyboardController/HyperXAlloyEliteController/HyperXAlloyEliteController.h @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| HyperXAlloyEliteController.h | -| | -| Definitions and types for HyperX Alloy | -| Elite Keyboard lighting controller | -| | -| Adam Honse (CalcProgrammer1) 1/30/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| HyperXAlloyEliteController.h | +| | +| Driver for HyperX Alloy Elite keyboard | +| | +| Adam Honse (CalcProgrammer1) 30 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + enum { HYPERX_ALLOY_ELITE_PACKET_ID_SET_EFFECT = 0x02, /* Set profile effect packet */ @@ -65,10 +66,11 @@ enum class HyperXAlloyEliteController { public: - HyperXAlloyEliteController(hid_device* dev_handle, const char* path); + HyperXAlloyEliteController(hid_device* dev_handle, const char* path, std::string dev_name); ~HyperXAlloyEliteController(); std::string GetDeviceLocation(); + std::string GetNameString(); std::string GetSerialString(); void SetMode @@ -88,6 +90,7 @@ private: unsigned char active_direction; unsigned char active_speed; std::string location; + std::string name; void SelectProfile ( diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite.cpp b/Controllers/HyperXKeyboardController/HyperXAlloyEliteController/RGBController_HyperXAlloyElite.cpp similarity index 78% rename from Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite.cpp rename to Controllers/HyperXKeyboardController/HyperXAlloyEliteController/RGBController_HyperXAlloyElite.cpp index 4da9f97b..eab80c3e 100644 --- a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite.cpp +++ b/Controllers/HyperXKeyboardController/HyperXAlloyEliteController/RGBController_HyperXAlloyElite.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_HyperXAlloyElite.cpp | -| | -| Generic RGB Interface for HyperX Alloy | -| Elite Keyboard | -| | -| Adam Honse (CalcProgrammer1) 2/2/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_HyperXAlloyElite.cpp | +| | +| RGBController for HyperX Alloy Elite keyboard | +| | +| Adam Honse (CalcProgrammer1) 02 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_HyperXAlloyElite.h" @@ -189,50 +191,50 @@ static const char *led_names[] = RGBController_HyperXAlloyElite::RGBController_HyperXAlloyElite(HyperXAlloyEliteController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "HyperX Alloy Elite"; - vendor = "HyperX"; - type = DEVICE_TYPE_KEYBOARD; - description = "HyperX Alloy Elite Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "HyperX"; + type = DEVICE_TYPE_KEYBOARD; + description = "HyperX Alloy Elite Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = HYPERX_ALLOY_ELITE_MODE_STATIC; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = HYPERX_ALLOY_ELITE_MODE_STATIC; + 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 = HYPERX_ALLOY_ELITE_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Static.color_mode = MODE_COLORS_PER_LED; + Static.name = "Static"; + Static.value = HYPERX_ALLOY_ELITE_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Static.color_mode = MODE_COLORS_PER_LED; modes.push_back(Static); mode Wave; - Wave.name = "Wave"; - Wave.value = HYPERX_ALLOY_ELITE_MODE_WAVE; - Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_AUTOMATIC_SAVE; - Wave.speed_min = 0x00; - Wave.speed_max = 0x09; - Wave.color_mode = MODE_COLORS_NONE; - Wave.speed = 0x09; - Wave.direction = MODE_DIRECTION_LEFT; + Wave.name = "Wave"; + Wave.value = HYPERX_ALLOY_ELITE_MODE_WAVE; + Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_AUTOMATIC_SAVE; + Wave.speed_min = 0x00; + Wave.speed_max = 0x09; + Wave.color_mode = MODE_COLORS_NONE; + Wave.speed = 0x09; + Wave.direction = MODE_DIRECTION_LEFT; modes.push_back(Wave); mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = HYPERX_ALLOY_ELITE_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Breathing.speed_min = 0x00; - Breathing.speed_max = 0x09; - Breathing.colors_min = 1; - Breathing.colors_max = 2; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.speed = 0x09; + Breathing.name = "Breathing"; + Breathing.value = HYPERX_ALLOY_ELITE_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.speed_min = 0x00; + Breathing.speed_max = 0x09; + Breathing.colors_min = 1; + Breathing.colors_max = 2; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.speed = 0x09; Breathing.colors.resize(2); modes.push_back(Breathing); diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyEliteController/RGBController_HyperXAlloyElite.h b/Controllers/HyperXKeyboardController/HyperXAlloyEliteController/RGBController_HyperXAlloyElite.h new file mode 100644 index 00000000..b5227b4f --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyEliteController/RGBController_HyperXAlloyElite.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------*\ +| RGBController_HyperXAlloyElite.h | +| | +| RGBController for HyperX Alloy Elite keyboard | +| | +| Adam Honse (CalcProgrammer1) 02 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" +#include "HyperXAlloyEliteController.h" + +class RGBController_HyperXAlloyElite : public RGBController +{ +public: + RGBController_HyperXAlloyElite(HyperXAlloyEliteController* controller_ptr); + ~RGBController_HyperXAlloyElite(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + void KeepaliveThreadFunction(); + +private: + HyperXAlloyEliteController* controller; + std::atomic keepalive_thread_run; + std::thread* keepalive_thread; + std::chrono::time_point last_update_time; +}; diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyFPSController.h b/Controllers/HyperXKeyboardController/HyperXAlloyFPSController.h deleted file mode 100644 index 800f8c65..00000000 --- a/Controllers/HyperXKeyboardController/HyperXAlloyFPSController.h +++ /dev/null @@ -1,49 +0,0 @@ -/*-----------------------------------------*\ -| HyperXAlloyFPSController.h | -| | -| Definitions and types for HyperX Alloy | -| Elite Keyboard lighting controller | -| | -| Adam Honse (CalcProgrammer1) 1/30/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include - -#pragma once - -enum -{ - HYPERX_ALLOY_FPS_PACKET_ID_DIRECT = 0x16, /* Direct control packet */ -}; - -enum -{ - HYPERX_ALLOY_FPS_COLOR_CHANNEL_RED = 0x01, - HYPERX_ALLOY_FPS_COLOR_CHANNEL_GREEN = 0x02, - HYPERX_ALLOY_FPS_COLOR_CHANNEL_BLUE = 0x03 -}; - -class HyperXAlloyFPSController -{ -public: - HyperXAlloyFPSController(hid_device* dev_handle, const char* path); - ~HyperXAlloyFPSController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - - void SetLEDsDirect(std::vector colors); - -private: - hid_device* dev; - std::string location; - - void SendDirect - ( - unsigned char color_channel, - unsigned char* color_data - ); -}; diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyFPSController.cpp b/Controllers/HyperXKeyboardController/HyperXAlloyFPSController/HyperXAlloyFPSController.cpp similarity index 81% rename from Controllers/HyperXKeyboardController/HyperXAlloyFPSController.cpp rename to Controllers/HyperXKeyboardController/HyperXAlloyFPSController/HyperXAlloyFPSController.cpp index 3edb5597..779e34af 100644 --- a/Controllers/HyperXKeyboardController/HyperXAlloyFPSController.cpp +++ b/Controllers/HyperXKeyboardController/HyperXAlloyFPSController/HyperXAlloyFPSController.cpp @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| HyperXAlloyFPSController.cpp | -| | -| Driver for HyperX Alloy FPS Keyboard | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 1/30/2020 | -\*-----------------------------------------*/ - -#include "HyperXAlloyFPSController.h" +/*---------------------------------------------------------*\ +| HyperXAlloyFPSController.cpp | +| | +| Driver for HyperX Alloy FPS keyboard | +| | +| Adam Honse (CalcProgrammer1) 30 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "HyperXAlloyFPSController.h" +#include "StringUtils.h" using namespace std::chrono_literals; @@ -23,10 +25,11 @@ static unsigned int keys[] = {0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x 0x7F, 0x81, 0x84, 0x85, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F, 0x91, 0x94, 0x95 }; -HyperXAlloyFPSController::HyperXAlloyFPSController(hid_device* dev_handle, const char* path) +HyperXAlloyFPSController::HyperXAlloyFPSController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } HyperXAlloyFPSController::~HyperXAlloyFPSController() @@ -39,6 +42,11 @@ std::string HyperXAlloyFPSController::GetDeviceLocation() return("HID: " + location); } +std::string HyperXAlloyFPSController::GetNameString() +{ + return(name); +} + std::string HyperXAlloyFPSController::GetSerialString() { wchar_t serial_string[128]; @@ -49,10 +57,7 @@ std::string HyperXAlloyFPSController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void HyperXAlloyFPSController::SetLEDsDirect(std::vector colors) diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyFPSController/HyperXAlloyFPSController.h b/Controllers/HyperXKeyboardController/HyperXAlloyFPSController/HyperXAlloyFPSController.h new file mode 100644 index 00000000..96187dce --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyFPSController/HyperXAlloyFPSController.h @@ -0,0 +1,52 @@ +/*---------------------------------------------------------*\ +| HyperXAlloyFPSController.h | +| | +| Driver for HyperX Alloy FPS keyboard | +| | +| Adam Honse (CalcProgrammer1) 30 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +enum +{ + HYPERX_ALLOY_FPS_PACKET_ID_DIRECT = 0x16, /* Direct control packet */ +}; + +enum +{ + HYPERX_ALLOY_FPS_COLOR_CHANNEL_RED = 0x01, + HYPERX_ALLOY_FPS_COLOR_CHANNEL_GREEN = 0x02, + HYPERX_ALLOY_FPS_COLOR_CHANNEL_BLUE = 0x03 +}; + +class HyperXAlloyFPSController +{ +public: + HyperXAlloyFPSController(hid_device* dev_handle, const char* path, std::string dev_name); + ~HyperXAlloyFPSController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SetLEDsDirect(std::vector colors); + +private: + hid_device* dev; + std::string location; + std::string name; + + void SendDirect + ( + unsigned char color_channel, + unsigned char* color_data + ); +}; diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyFPS.cpp b/Controllers/HyperXKeyboardController/HyperXAlloyFPSController/RGBController_HyperXAlloyFPS.cpp similarity index 86% rename from Controllers/HyperXKeyboardController/RGBController_HyperXAlloyFPS.cpp rename to Controllers/HyperXKeyboardController/HyperXAlloyFPSController/RGBController_HyperXAlloyFPS.cpp index 2030c7aa..dc152b13 100644 --- a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyFPS.cpp +++ b/Controllers/HyperXKeyboardController/HyperXAlloyFPSController/RGBController_HyperXAlloyFPS.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_HyperXAlloyFPS.cpp | -| | -| Generic RGB Interface for HyperX Alloy | -| FPS Keyboard | -| | -| Adam Honse (CalcProgrammer1) 2/2/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_HyperXAlloyFPS.cpp | +| | +| RGBController for HyperX Alloy FPS keyboard | +| | +| Adam Honse (CalcProgrammer1) 02 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_HyperXAlloyFPS.h" @@ -161,20 +163,20 @@ static const char *led_names[] = RGBController_HyperXAlloyFPS::RGBController_HyperXAlloyFPS(HyperXAlloyFPSController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "HyperX Alloy FPS"; - vendor = "HyperX"; - type = DEVICE_TYPE_KEYBOARD; - description = "HyperX Alloy FPS Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "HyperX"; + type = DEVICE_TYPE_KEYBOARD; + description = "HyperX Alloy FPS Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + 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(); diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyFPSController/RGBController_HyperXAlloyFPS.h b/Controllers/HyperXKeyboardController/HyperXAlloyFPSController/RGBController_HyperXAlloyFPS.h new file mode 100644 index 00000000..3e2ca76f --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyFPSController/RGBController_HyperXAlloyFPS.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------*\ +| RGBController_HyperXAlloyFPS.h | +| | +| RGBController for HyperX Alloy FPS keyboard | +| | +| Adam Honse (CalcProgrammer1) 02 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" +#include "HyperXAlloyFPSController.h" + +class RGBController_HyperXAlloyFPS : public RGBController +{ +public: + RGBController_HyperXAlloyFPS(HyperXAlloyFPSController* controller_ptr); + ~RGBController_HyperXAlloyFPS(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + void KeepaliveThreadFunction(); + +private: + HyperXAlloyFPSController* controller; + std::atomic keepalive_thread_run; + std::thread* keepalive_thread; + std::chrono::time_point last_update_time; +}; diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller.h b/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller.h deleted file mode 100644 index af058522..00000000 --- a/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller.h +++ /dev/null @@ -1,39 +0,0 @@ -/*---------------------------------------*\ -| HyperXAlloyOrigins60and65Controller.h | -| | -| Definitions and types for HyperX | -| Alloy Origins 60 and 65 RGB Keyboards | -| lighting controller | -| | -| Derek Huber 03/18/2023 | -\*---------------------------------------*/ - -#include "RGBController.h" - -#include -#include - -#pragma once - -class HyperXAlloyOrigins60and65Controller -{ -public: - HyperXAlloyOrigins60and65Controller(hid_device* dev_handle, const char* path); - ~HyperXAlloyOrigins60and65Controller(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - - void SetLEDsDirect(std::vector colors); - -private: - hid_device* dev; - std::string location; - - void SendDirectInitialization(); - void SendDirectColorPacket - ( - RGBColor* color_data, - unsigned int color_count - ); -}; diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller.cpp b/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller/HyperXAlloyOrigins60and65Controller.cpp similarity index 81% rename from Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller.cpp rename to Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller/HyperXAlloyOrigins60and65Controller.cpp index 666fce95..00b944cd 100644 --- a/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller.cpp +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller/HyperXAlloyOrigins60and65Controller.cpp @@ -1,20 +1,23 @@ -/*-----------------------------------------*\ -| HyperXAlloyOrigins60and65Controller.cpp | -| | -| Driver for HyperX Alloy Origins 60 and | -| 65 RGB Keyboards lighting controller | -| | -| Derek Huber 03/18/2023 | -\*-----------------------------------------*/ - -#include "HyperXAlloyOrigins60and65Controller.h" +/*---------------------------------------------------------*\ +| HyperXAlloyOrigins60and65Controller.cpp | +| | +| Driver for HyperX Alloy Origins 60 and 65 keyboard | +| | +| Derek Huber 18 Mar 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "HyperXAlloyOrigins60and65Controller.h" +#include "StringUtils.h" -HyperXAlloyOrigins60and65Controller::HyperXAlloyOrigins60and65Controller(hid_device* dev_handle, const char* path) +HyperXAlloyOrigins60and65Controller::HyperXAlloyOrigins60and65Controller(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + dev_name = name; } HyperXAlloyOrigins60and65Controller::~HyperXAlloyOrigins60and65Controller() @@ -27,6 +30,11 @@ std::string HyperXAlloyOrigins60and65Controller::GetDeviceLocation() return("HID " + location); } +std::string HyperXAlloyOrigins60and65Controller::GetNameString() +{ + return(name); +} + std::string HyperXAlloyOrigins60and65Controller::GetSerialString() { wchar_t serial_string[128]; @@ -37,10 +45,7 @@ std::string HyperXAlloyOrigins60and65Controller::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void HyperXAlloyOrigins60and65Controller::SetLEDsDirect(std::vector colors) @@ -49,7 +54,7 @@ void HyperXAlloyOrigins60and65Controller::SetLEDsDirect(std::vector co | Set up variables to track progress of color transmit | | Do this after inserting blanks | \*-----------------------------------------------------*/ - int colors_to_send = colors.size(); + int colors_to_send = (int)colors.size(); int colors_sent = 0; SendDirectInitialization(); diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller/HyperXAlloyOrigins60and65Controller.h b/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller/HyperXAlloyOrigins60and65Controller.h new file mode 100644 index 00000000..43dd52a5 --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller/HyperXAlloyOrigins60and65Controller.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------*\ +| HyperXAlloyOrigins60and65Controller.h | +| | +| Driver for HyperX Alloy Origins 60 and 65 keyboard | +| | +| Derek Huber 18 Mar 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +class HyperXAlloyOrigins60and65Controller +{ +public: + HyperXAlloyOrigins60and65Controller(hid_device* dev_handle, const char* path, std::string dev_name); + ~HyperXAlloyOrigins60and65Controller(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SetLEDsDirect(std::vector colors); + +private: + hid_device* dev; + std::string location; + std::string name; + + void SendDirectInitialization(); + void SendDirectColorPacket + ( + RGBColor* color_data, + unsigned int color_count + ); +}; diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60and65.cpp b/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller/RGBController_HyperXAlloyOrigins60and65.cpp similarity index 86% rename from Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60and65.cpp rename to Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller/RGBController_HyperXAlloyOrigins60and65.cpp index c2c3662c..142183e5 100644 --- a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60and65.cpp +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller/RGBController_HyperXAlloyOrigins60and65.cpp @@ -1,11 +1,14 @@ -/*---------------------------------------------*\ -| RGBController_HyperXAlloyOrigins60and65.cpp | -| | -| Generic RGB Interface for HyperX Alloy | -| Origins 60 and 65 RGB Keyboards | -| | -| Derek Huber 03/18/2023 | -\*---------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_HyperXAlloyOrigins60and65.cpp | +| | +| RGBController for HyperX Alloy Origins 60 and 65 | +| keyboard | +| | +| Derek Huber 18 Mar 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_HyperXAlloyOrigins60and65.h" @@ -194,11 +197,6 @@ static const char *led_names_65[] = KEY_EN_RIGHT_ARROW }; -static const char* zone_names[] = -{ - ZONE_EN_KEYBOARD -}; - /**------------------------------------------------------------------*\ @name HyperX Alloy Origins 60 and 65 @category Keyboard @@ -212,29 +210,31 @@ static const char* zone_names[] = RGBController_HyperXAlloyOrigins60and65::RGBController_HyperXAlloyOrigins60and65(HyperXAlloyOrigins60and65Controller* controller_ptr, AlloyOrigins60and65MappingLayoutType keyboard_layout) { - controller = controller_ptr; - layout = keyboard_layout; + controller = controller_ptr; + layout = keyboard_layout; switch(layout) { case ALLOY_ORIGINS_60_LAYOUT: - name = "HyperX Alloy Origins 60 Keyboard Device"; + description = "HyperX Alloy Origins 60 Keyboard Device"; break; + case ALLOY_ORIGINS_65_LAYOUT: - name = "HyperX Alloy Origins 65 Keyboard Device"; + description = "HyperX Alloy Origins 65 Keyboard Device"; + break; } - description = name; - vendor = "HyperX"; - type = DEVICE_TYPE_KEYBOARD; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "HyperX"; + type = DEVICE_TYPE_KEYBOARD; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0xFFFF; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); SetupZones(); diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller/RGBController_HyperXAlloyOrigins60and65.h b/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller/RGBController_HyperXAlloyOrigins60and65.h new file mode 100644 index 00000000..cd4b9190 --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller/RGBController_HyperXAlloyOrigins60and65.h @@ -0,0 +1,57 @@ +/*---------------------------------------------------------*\ +| RGBController_HyperXAlloyOrigins60and65.h | +| | +| RGBController for HyperX Alloy Origins 60 and 65 | +| keyboard | +| | +| Derek Huber 18 Mar 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "HyperXAlloyOrigins60and65Controller.h" + +enum AlloyOrigins60and65MappingLayoutType +{ + ALLOY_ORIGINS_60_LAYOUT, + ALLOY_ORIGINS_65_LAYOUT +}; + +typedef struct +{ + const char* name; + const zone_type type; + const unsigned int size; + matrix_map_type* matrix; +} led_zone; + +class RGBController_HyperXAlloyOrigins60and65 : public RGBController +{ +public: + RGBController_HyperXAlloyOrigins60and65(HyperXAlloyOrigins60and65Controller* controller_ptr, AlloyOrigins60and65MappingLayoutType keyboard_layout); + ~RGBController_HyperXAlloyOrigins60and65(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + void KeepaliveThread(); + +private: + HyperXAlloyOrigins60and65Controller* controller; + AlloyOrigins60and65MappingLayoutType layout; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::chrono::time_point last_update_time; +}; diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsController.h b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsController.h deleted file mode 100644 index 4a111482..00000000 --- a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsController.h +++ /dev/null @@ -1,38 +0,0 @@ -/*-----------------------------------------*\ -| HyperXAlloyOriginsController.h | -| | -| Definitions and types for HyperX Alloy | -| Origins RGB Keyboard lighting controller | -| | -| Adam Honse (CalcProgrammer1) 7/11/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include - -#pragma once - -class HyperXAlloyOriginsController -{ -public: - HyperXAlloyOriginsController(hid_device* dev_handle, const char* path); - ~HyperXAlloyOriginsController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - - void SetLEDsDirect(std::vector colors); - -private: - hid_device* dev; - std::string location; - - void SendDirectInitialization(); - void SendDirectColorPacket - ( - RGBColor* color_data, - unsigned int color_count - ); -}; diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsController.cpp b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsController/HyperXAlloyOriginsController.cpp similarity index 83% rename from Controllers/HyperXKeyboardController/HyperXAlloyOriginsController.cpp rename to Controllers/HyperXKeyboardController/HyperXAlloyOriginsController/HyperXAlloyOriginsController.cpp index 0ae5005d..4942f8c4 100644 --- a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsController.cpp +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsController/HyperXAlloyOriginsController.cpp @@ -1,23 +1,26 @@ -/*-----------------------------------------*\ -| HyperXAlloyOriginsController.cpp | -| | -| Driver for HyperX Alloy Origins RGB | -| Keyboard lighting controller | -| | -| Adam Honse (CalcProgrammer1) 7/11/2020 | -\*-----------------------------------------*/ - -#include "HyperXAlloyOriginsController.h" +/*---------------------------------------------------------*\ +| HyperXAlloyOriginsController.cpp | +| | +| Driver for HyperX Alloy Origins keyboard | +| | +| Adam Honse (CalcProgrammer1) 11 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "HyperXAlloyOriginsController.h" +#include "StringUtils.h" // Skip these indices in the color output static unsigned int skip_idx[] = { 23, 29, 41, 47, 59, 70, 71, 87, 88, 93, 99, 100, 102, 108, 113, 114, 120, 123, 124 }; -HyperXAlloyOriginsController::HyperXAlloyOriginsController(hid_device* dev_handle, const char* path) +HyperXAlloyOriginsController::HyperXAlloyOriginsController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } HyperXAlloyOriginsController::~HyperXAlloyOriginsController() @@ -30,6 +33,11 @@ std::string HyperXAlloyOriginsController::GetDeviceLocation() return("HID " + location); } +std::string HyperXAlloyOriginsController::GetNameString() +{ + return(name); +} + std::string HyperXAlloyOriginsController::GetSerialString() { wchar_t serial_string[128]; @@ -40,10 +48,7 @@ std::string HyperXAlloyOriginsController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void HyperXAlloyOriginsController::SetLEDsDirect(std::vector colors) @@ -60,7 +65,7 @@ void HyperXAlloyOriginsController::SetLEDsDirect(std::vector colors) | Set up variables to track progress of color transmit | | Do this after inserting blanks | \*-----------------------------------------------------*/ - int colors_to_send = colors.size(); + int colors_to_send = (int)colors.size(); int colors_sent = 0; SendDirectInitialization(); diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsController/HyperXAlloyOriginsController.h b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsController/HyperXAlloyOriginsController.h new file mode 100644 index 00000000..10680199 --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsController/HyperXAlloyOriginsController.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------*\ +| HyperXAlloyOriginsController.h | +| | +| Driver for HyperX Alloy Origins keyboard | +| | +| Adam Honse (CalcProgrammer1) 11 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +class HyperXAlloyOriginsController +{ +public: + HyperXAlloyOriginsController(hid_device* dev_handle, const char* path, std::string dev_name); + ~HyperXAlloyOriginsController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SetLEDsDirect(std::vector colors); + +private: + hid_device* dev; + std::string location; + std::string name; + + void SendDirectInitialization(); + void SendDirectColorPacket + ( + RGBColor* color_data, + unsigned int color_count + ); +}; diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins.cpp b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsController/RGBController_HyperXAlloyOrigins.cpp similarity index 86% rename from Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins.cpp rename to Controllers/HyperXKeyboardController/HyperXAlloyOriginsController/RGBController_HyperXAlloyOrigins.cpp index d87ed146..69691677 100644 --- a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins.cpp +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsController/RGBController_HyperXAlloyOrigins.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_HyperXAlloyOrigins.cpp | -| | -| Generic RGB Interface for HyperX Alloy | -| Origins RGB Keyboard | -| | -| Adam Honse (CalcProgrammer1) 7/11/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_HyperXAlloyOrigins.cpp | +| | +| RGBController for HyperX Alloy Origins keyboard | +| | +| Adam Honse (CalcProgrammer1) 11 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_HyperXAlloyOrigins.h" @@ -181,20 +183,20 @@ static const char *led_names[] = RGBController_HyperXAlloyOrigins::RGBController_HyperXAlloyOrigins(HyperXAlloyOriginsController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "HyperX Alloy Origins Keyboard Device"; - vendor = "HyperX"; - type = DEVICE_TYPE_KEYBOARD; - description = "HyperX Alloy Origins Keyboard Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "HyperX"; + type = DEVICE_TYPE_KEYBOARD; + description = "HyperX Alloy Origins Keyboard Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0xFFFF; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); SetupZones(); diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsController/RGBController_HyperXAlloyOrigins.h b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsController/RGBController_HyperXAlloyOrigins.h new file mode 100644 index 00000000..b2d78454 --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsController/RGBController_HyperXAlloyOrigins.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------*\ +| RGBController_HyperXAlloyOrigins.h | +| | +| RGBController for HyperX Alloy Origins keyboard | +| | +| Adam Honse (CalcProgrammer1) 11 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "HyperXAlloyOriginsController.h" + +class RGBController_HyperXAlloyOrigins : public RGBController +{ +public: + RGBController_HyperXAlloyOrigins(HyperXAlloyOriginsController* controller_ptr); + ~RGBController_HyperXAlloyOrigins(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + void KeepaliveThread(); + +private: + HyperXAlloyOriginsController* controller; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::chrono::time_point last_update_time; +}; diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.cpp b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.cpp deleted file mode 100644 index 2cb47232..00000000 --- a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/*------------------------------------------*\ -| HyperXAlloyOriginsCoreController.cpp | -| | -| Driver for HyperX Alloy Origins Core | -| RGB Keyboard lighting controller | -| | -| Volodymyr Nazarchuk (Vavooon) 4/28/2021 | -| mike white (kamaaina) 6/9/2021 | -\*------------------------------------------*/ - -#include "HyperXAlloyOriginsCoreController.h" - -#include - -// Skip these indices in the color output -static unsigned int skip_idx[] = {6, 7, 14, 15, 22, 23, 30, 31, 38, 39, 44, 46, 47, 54, 55, 58, 60, 61, 62, 63, 70, 71, 78, 79, 86, 87, 94, 95, 101, 102, 103, 109, 110, 111, 118, 119}; - -HyperXAlloyOriginsCoreController::HyperXAlloyOriginsCoreController(hid_device* dev_handle, hid_device_info* dev_info) -{ - dev = dev_handle; - location = dev_info->path; - - /*-----------------------------------------------------*\ - | Get the firmware version from the device info | - \*-----------------------------------------------------*/ - char fw_version_buf[8]; - memset(fw_version_buf, '\0', sizeof(fw_version_buf)); - - unsigned short version = dev_info->release_number; - snprintf(fw_version_buf, 8, "%.2X.%.2X", (version & 0xFF00) >> 8, version & 0x00FF); - - firmware_version = fw_version_buf; -} - -HyperXAlloyOriginsCoreController::~HyperXAlloyOriginsCoreController() -{ - hid_close(dev); -} - -std::string HyperXAlloyOriginsCoreController::GetDeviceLocation() -{ - return("HID " + location); -} - -std::string HyperXAlloyOriginsCoreController::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); -} - -std::string HyperXAlloyOriginsCoreController::GetFirmwareVersion() -{ - return(firmware_version); -} - -void HyperXAlloyOriginsCoreController::SetBrightness(unsigned int brightness) -{ - unsigned char packet[65]; - memset(packet, 0x00, sizeof(packet)); - - packet[1] = 0xA7; - packet[4] = 0x01; - packet[5] = brightness; - - hid_write(dev, packet, 65); -} - - -void HyperXAlloyOriginsCoreController::SetLEDsDirect(std::vector colors) -{ - for(unsigned int skip_cnt = 0; skip_cnt < (sizeof(skip_idx) / sizeof(skip_idx[0])); skip_cnt++) - { - colors.insert(colors.begin() + skip_idx[skip_cnt], 0x00000000); - } - - unsigned char buf[380]; - memset(buf, 0x00, sizeof(buf)); - - int offset = 0; - int rowPos = 0; - - for(unsigned int color_idx = 0; color_idx < colors.size(); color_idx++) - { - if (color_idx > 0 && color_idx % 16 == 0) - { - offset += 48; - rowPos = 0; - } - - buf[rowPos + offset] = RGBGetGValue(colors[color_idx]); - buf[rowPos + offset + 16] = RGBGetRValue(colors[color_idx]); - buf[rowPos + offset + 32] = RGBGetBValue(colors[color_idx]); - - rowPos++; - } - - unsigned int sentBytes = 0; - unsigned int bytesToSend = sizeof(buf); - unsigned int payloadSize = 60; - unsigned int seq = 0; - - while(sentBytes < bytesToSend) - { - if (bytesToSend - sentBytes < payloadSize) - { - payloadSize = bytesToSend - sentBytes; - } - - unsigned char packet[65]; - memset(packet, 0x00, sizeof(packet)); - - packet[1] = 0xA2; - packet[2] = seq++; - packet[4] = payloadSize; - - memcpy(&packet[5], &buf[sentBytes], payloadSize); - hid_write(dev, packet, 65); - - sentBytes += payloadSize; - } -} diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.h b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.h deleted file mode 100644 index 483088b2..00000000 --- a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.h +++ /dev/null @@ -1,35 +0,0 @@ -/*------------------------------------------*\ -| HyperXAlloyOriginsCoreController.h | -| | -| Definitions and types for HyperX Alloy | -| Origins Core RGB Keyboard lighting | -| controller | -| | -| Volodymyr Nazarchuk (Vavooon) 4/28/2021 | -\*------------------------------------------*/ - -#include "RGBController.h" - -#include -#include - -#pragma once - -class HyperXAlloyOriginsCoreController -{ -public: - HyperXAlloyOriginsCoreController(hid_device* dev_handle, hid_device_info* dev_info); - ~HyperXAlloyOriginsCoreController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - std::string GetFirmwareVersion(); - - void SetLEDsDirect(std::vector colors); - void SetBrightness(unsigned int brightness); - -private: - hid_device* dev; - std::string location; - std::string firmware_version; -}; diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController/HyperXAlloyOriginsCoreController.cpp b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController/HyperXAlloyOriginsCoreController.cpp new file mode 100644 index 00000000..24841b33 --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController/HyperXAlloyOriginsCoreController.cpp @@ -0,0 +1,188 @@ +/*---------------------------------------------------------*\ +| HyperXAlloyOriginsCoreController.cpp | +| | +| Driver for HyperX Alloy Origins Core keyboard | +| | +| Volodymyr Nazarchuk (Vavooon) 28 Apr 2021 | +| Mike White (kamaaina) 09 Jun 2021 | +| carlos jordao 15 Mar 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "HyperXAlloyOriginsCoreController.h" +#include "StringUtils.h" +#include "LogManager.h" + + +HyperXAlloyOriginsCoreController::HyperXAlloyOriginsCoreController(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name) +{ + dev = dev_handle; + location = dev_info->path; + name = dev_name; + + /*-----------------------------------------------------*\ + | Get the firmware version from the device info | + \*-----------------------------------------------------*/ + char fw_version_buf[8]; + memset(fw_version_buf, '\0', sizeof(fw_version_buf)); + + unsigned short version = dev_info->release_number; + snprintf(fw_version_buf, 8, "%.2X.%.2X", (version & 0xFF00) >> 8, version & 0x00FF); + + firmware_version = fw_version_buf; +} + +HyperXAlloyOriginsCoreController::~HyperXAlloyOriginsCoreController() +{ + hid_close(dev); +} + +std::string HyperXAlloyOriginsCoreController::GetDeviceLocation() +{ + return("HID " + location); +} + +std::string HyperXAlloyOriginsCoreController::GetNameString() +{ + return(name); +} + +std::string HyperXAlloyOriginsCoreController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string HyperXAlloyOriginsCoreController::GetFirmwareVersion() +{ + return(firmware_version); +} + +unsigned int HyperXAlloyOriginsCoreController::GetVariant() +{ + unsigned char packet[65]; + unsigned int variant = 0; + int actual = 0; + + memset(packet, 0x00, sizeof(packet)); + + /*---------------------------------------*\ + | Command 10 asks some data from keyboard | + | The answer looks like: | + | * command answer header (bytes 0-4) | + | * data length: byte 4 | + | * version (bytes 5-6) | + | * Product string (bytes 9-33) | + | * Layout variant (byte 56) | + \*---------------------------------------*/ + packet[1] = 0x10; + hid_write(dev, packet, 65); + memset(packet, 0x00, sizeof(packet)); + actual = hid_read(dev, packet, 65); + + if(actual > 0) + variant = packet[56]; + else + variant = 0x09; + + LOG_DEBUG("[HyperX Alloy Origins Core] variant: 0x%02X", variant); + return variant; +} + + +void HyperXAlloyOriginsCoreController::SetBrightness(unsigned int brightness) +{ + unsigned char packet[65]; + memset(packet, 0x00, sizeof(packet)); + + packet[1] = 0xA7; + packet[4] = 0x01; + packet[5] = brightness; + + hid_write(dev, packet, 65); +} + + +void HyperXAlloyOriginsCoreController::SetLEDsDirect(std::vector colors) +{ + /*------------------------------------------------------------------------------*\ + | * Always send 380 bytes to the keyboard and a total of 94 led indexes. | + | The colors are grouped into segments of 48 bytes. | + | Each one is divided into: | + | 6 Green + 2 zeroes + 6 Green + 2 zeroes + | + | 6 Red + 2 zeroes + 6 Red + 2 zeroes + | + | 6 Blue + 2 zeroes + 6 Blue + 2 zeroes | + | \=---> sector 0 \=--> sector 1 | + | Every 6 colors form a sector. The names are arbitrary, just to make clear how | + | to set the colors into the buffer. | + | So each segment has 2 sectors and 12 colors. | + | The last 10 colors don't fill completely the last segment. | + | * All 94 colors can be sent even if some of them aren't used by the physical | + | keyboard. This allows to lit every key, even if not mapped directly. | + \*------------------------------------------------------------------------------*/ + unsigned int segment = 0, sector = 0, sequence = 0; + unsigned int total_colors = 0; + unsigned char buf[380]; + memset(buf, 0x00, sizeof(buf)); + + /*---------------------------------------------------------------------------*\ + | transfer the colors to the buffer. Max 94 colors to avoid buffer overflow. | + \*---------------------------------------------------------------------------*/ + if(colors.size() > 94) + { + total_colors = 94; + } + else + { + total_colors = (unsigned int)colors.size(); + } + + for(unsigned int color_idx = 0; color_idx < total_colors; color_idx++) + { + unsigned int pos = 0; + segment = (color_idx / 12) * 48; + sector = ((color_idx / 6) & 1) * 8; + sequence = color_idx % 6; + + pos = segment + sector + sequence; + + buf[pos ] = RGBGetGValue(colors[color_idx]); + buf[pos + 16] = RGBGetRValue(colors[color_idx]); + buf[pos + 32] = RGBGetBValue(colors[color_idx]); + } + + unsigned int sentBytes = 0; + unsigned int bytesToSend = sizeof(buf); + unsigned int payloadSize = 60; + unsigned int seq = 0; + + while(sentBytes < bytesToSend) + { + if (bytesToSend - sentBytes < payloadSize) + { + payloadSize = bytesToSend - sentBytes; + } + + unsigned char packet[65]; + memset(packet, 0x00, sizeof(packet)); + + packet[1] = 0xA2; + packet[2] = seq++; + packet[4] = payloadSize; + + memcpy(&packet[5], &buf[sentBytes], payloadSize); + hid_write(dev, packet, payloadSize + 5); + + sentBytes += payloadSize; + } +} diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController/HyperXAlloyOriginsCoreController.h b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController/HyperXAlloyOriginsCoreController.h new file mode 100644 index 00000000..7e332607 --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController/HyperXAlloyOriginsCoreController.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------*\ +| HyperXAlloyOriginsCoreController.h | +| | +| Driver for HyperX Alloy Origins Core keyboard | +| | +| Volodymyr Nazarchuk (Vavooon) 28 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +class HyperXAlloyOriginsCoreController +{ +public: + HyperXAlloyOriginsCoreController(hid_device* dev_handle, hid_device_info* dev_info, std::string dev_name); + ~HyperXAlloyOriginsCoreController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + std::string GetFirmwareVersion(); + unsigned int GetVariant(); + + void SetLEDsDirect(std::vector colors); + void SetBrightness(unsigned int brightness); + +private: + hid_device* dev; + std::string location; + std::string firmware_version; + std::string name; +}; diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController/RGBController_HyperXAlloyOriginsCore.cpp b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController/RGBController_HyperXAlloyOriginsCore.cpp new file mode 100644 index 00000000..27c48393 --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController/RGBController_HyperXAlloyOriginsCore.cpp @@ -0,0 +1,347 @@ +/*---------------------------------------------------------*\ +| RGBController_HyperXAlloyOriginsCore.cpp | +| | +| RGBController for HyperX Alloy Origins Core keyboard | +| | +| Volodymyr Nazarchuk (Vavooon) 28 Apr 2021 | +| carlos jordao 15 Mar 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBControllerKeyNames.h" +#include "RGBController_HyperXAlloyOriginsCore.h" + +using namespace std::chrono_literals; + +#define HYPERX_MIN_BRIGHTNESS 0 +#define HYPERX_MAX_BRIGHTNESS 255 + +#define NA 0xFFFFFFFF + +/*----------------------------------*\ +| Maps LED position number to keys | +| * based on ANSI QWERTY | +\*----------------------------------*/ +static unsigned int matrix_map[6][19] = +{ + { 0, NA, 1, 2, 3, 4, 5, 6, 7, 48, NA, 49, 50, 51, 52, NA, 53, 54, 55 }, + { 8, 9, 10, 11, 12, 13, 14, 15, 16, 56, 57, 58, 59, 60, NA, NA, 61, 62, 63 }, + { 17, NA, 18, 19, 20, 21, 22, 23, 24, 64, 65, 66, 67, 68, 69, NA, 70, 71, 72 }, + { 25, NA, 26, 27, 28, 29, 30, 31, 32, 73, 74, 75, 76, 78, NA, NA, NA, NA, NA }, + { 33, NA, 35, 36, 37, 38, 39, 40, 79, 80, 81, NA, 83, 84, NA, NA, NA, 85, NA }, + { 41, 42, 43, NA, NA, NA, 45, NA, NA, NA, NA, 86, 87, 88, 89, NA, 90, 91, 92 } +}; + +static const char* zone_names[] = +{ + ZONE_EN_KEYBOARD, +}; + +static zone_type zone_types[] = +{ + ZONE_TYPE_MATRIX, +}; + + +/*--------------------------------------------------------------------------------*\ +| This keyboard (TKL) always receives 93 led colors. | +| * Some indexes are just blank (unused). | +| * Regional layouts have a few different enabled or disabled led indexes. | +| * All indexes need to be sent anyway. Declaring all of them makes it easier to | +| add new layouts without creating a new matrix map. | +| * led_names contains the indexes used by the HyperX keyboard | +\*--------------------------------------------------------------------------------*/ +struct led_index +{ + const char *name; + unsigned int index; +}; + +static led_index led_names[] = +{ + {KEY_EN_ESCAPE, 0}, + {KEY_EN_F1, 1}, + {KEY_EN_F2, 2}, + {KEY_EN_F3, 3}, + {KEY_EN_F4, 4}, + {KEY_EN_F5, 5}, + {KEY_EN_F6, 6}, + {KEY_EN_F7, 7}, + + {KEY_EN_BACK_TICK, 8}, + {KEY_EN_1, 9}, + {KEY_EN_2, 10}, + {KEY_EN_3, 11}, + {KEY_EN_4, 12}, + {KEY_EN_5, 13}, + {KEY_EN_6, 14}, + {KEY_EN_7, 15}, + {KEY_EN_8, 16}, + + {KEY_EN_TAB, 17}, + {KEY_EN_Q, 18}, + {KEY_EN_W, 19}, + {KEY_EN_E, 20}, + {KEY_EN_R, 21}, + {KEY_EN_T, 22}, + {KEY_EN_Y, 23}, + {KEY_EN_U, 24}, + + {KEY_EN_CAPS_LOCK, 25}, + {KEY_EN_A, 26}, + {KEY_EN_S, 27}, + {KEY_EN_D, 28}, + {KEY_EN_F, 29}, + {KEY_EN_G, 30}, + {KEY_EN_H, 31}, + {KEY_EN_J, 32}, + + {KEY_EN_LEFT_SHIFT, 33}, + {KEY_EN_UNUSED, 34}, + {KEY_EN_Z, 35}, + {KEY_EN_X, 36}, + {KEY_EN_C, 37}, + {KEY_EN_V, 38}, + {KEY_EN_B, 39}, + {KEY_EN_N, 40}, + + {KEY_EN_LEFT_CONTROL, 41}, + {KEY_EN_LEFT_WINDOWS, 42}, + {KEY_EN_LEFT_ALT, 43}, + + {KEY_EN_UNUSED, 44}, + {KEY_EN_SPACE, 45}, + {KEY_EN_UNUSED, 46}, + {KEY_EN_UNUSED, 47}, + + // End of first section + + {KEY_EN_F8, 48}, + {KEY_EN_F9, 49}, + {KEY_EN_F10, 50}, + {KEY_EN_F11, 51}, + {KEY_EN_F12, 52}, + {KEY_EN_PRINT_SCREEN, 53}, + {KEY_EN_SCROLL_LOCK, 54}, + {KEY_EN_PAUSE_BREAK, 55}, + + {KEY_EN_9, 56}, + {KEY_EN_0, 57}, + {KEY_EN_MINUS, 58}, + {KEY_EN_EQUALS, 59}, + {KEY_EN_BACKSPACE, 60}, + {KEY_EN_INSERT, 61}, + {KEY_EN_HOME, 62}, + {KEY_EN_PAGE_UP, 63}, + + {KEY_EN_I, 64}, + {KEY_EN_O, 65}, + {KEY_EN_P, 66}, + {KEY_EN_LEFT_BRACKET, 67}, + {KEY_EN_RIGHT_BRACKET, 68}, + {KEY_EN_ANSI_BACK_SLASH, 69}, + + {KEY_EN_DELETE, 70}, + {KEY_EN_END, 71}, + {KEY_EN_PAGE_DOWN, 72}, + + {KEY_EN_K, 73}, + {KEY_EN_L, 74}, + {KEY_EN_SEMICOLON, 75}, + {KEY_EN_QUOTE, 76}, + {KEY_EN_POUND, 77}, + {KEY_EN_ANSI_ENTER, 78}, + + {KEY_EN_M, 79}, + {KEY_EN_COMMA, 80}, + {KEY_EN_PERIOD, 81}, + {KEY_EN_UNUSED, 82}, + {KEY_EN_FORWARD_SLASH, 83}, + {KEY_EN_RIGHT_SHIFT, 84}, + + {KEY_EN_UP_ARROW, 85}, + + {KEY_EN_RIGHT_ALT, 86}, + {KEY_EN_RIGHT_FUNCTION, 87}, + {KEY_EN_MENU, 88}, + {KEY_EN_RIGHT_CONTROL, 89}, + + {KEY_EN_LEFT_ARROW, 90}, + {KEY_EN_DOWN_ARROW, 91}, + {KEY_EN_RIGHT_ARROW, 92} +}; + +/**------------------------------------------------------------------*\ + @name HyperX Alloy Origins Core + @category Keyboard + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectHyperXAlloyOriginsCore + @comment +\*-------------------------------------------------------------------*/ + +RGBController_HyperXAlloyOriginsCore::RGBController_HyperXAlloyOriginsCore(HyperXAlloyOriginsCoreController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "HyperX"; + type = DEVICE_TYPE_KEYBOARD; + description = "HyperX Alloy Origins Core Keyboard Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + version = controller->GetFirmwareVersion(); + variant = controller->GetVariant(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.brightness_min = HYPERX_MIN_BRIGHTNESS; + Direct.brightness_max = HYPERX_MAX_BRIGHTNESS; + Direct.brightness = HYPERX_MAX_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + SetupZones(); + + /*-----------------------------------------------------*\ + | The HyperX Origins Core requires a packet within few | + | seconds of sending the lighting change in order to | + | not revert back into current profile. Start a thread | + | to continuously send color values each 10ms | + \*-----------------------------------------------------*/ + keepalive_thread_run = 1; + keepalive_thread = new std::thread(&RGBController_HyperXAlloyOriginsCore::KeepaliveThread, this); +} + +RGBController_HyperXAlloyOriginsCore::~RGBController_HyperXAlloyOriginsCore() +{ + keepalive_thread_run = 0; + keepalive_thread->join(); + delete keepalive_thread; + + /*---------------------------------------------------------*\ + | Delete the matrix map | + \*---------------------------------------------------------*/ + 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; + } + } + + delete controller; +} + +void RGBController_HyperXAlloyOriginsCore::SetupZones() +{ + const unsigned int total_leds = sizeof(led_names) / sizeof(led_names[0]); + zone new_zone; + + for(unsigned int zone_idx = 0; zone_idx < 1; zone_idx++) + { + new_zone.name = zone_names[zone_idx]; + new_zone.type = zone_types[zone_idx]; + + /*-----------------------------------------------------*\ + | Regional configuration can be done by setting | + | the relevant keys based on the led map. | + \*-----------------------------------------------------*/ + if(variant == HYPERX_ALLOY_ORIGINS_CORE_ABNT2) + { + // Sets the led indexes of this variant + matrix_map[2][14] = NA; + matrix_map[3][13] = 77; // ] + matrix_map[3][14] = 78; // enter + matrix_map[4][ 1] = 34; // backslash + matrix_map[4][11] = 82; // ; + + // corrects the visual representantion + led_names[ 8].name = KEY_EN_QUOTE; + led_names[34].name = KEY_EN_ISO_BACK_SLASH; + led_names[67].name = KEY_NORD_ACUTE_GRAVE; + led_names[68].name = KEY_EN_LEFT_BRACKET; + led_names[69].name = KEY_EN_UNUSED; + led_names[75].name = KEY_FR_CEDILLA_C; + led_names[76].name = KEY_BR_TILDE; + led_names[77].name = KEY_EN_RIGHT_BRACKET; + led_names[78].name = KEY_EN_ISO_ENTER; + led_names[82].name = KEY_EN_SEMICOLON; + } + + for(unsigned int led_idx = 0; led_idx < total_leds; led_idx++) + { + led new_led; + new_led.name = led_names[led_idx].name; + new_led.value = led_names[led_idx].index; + leds.push_back(new_led); + } + + matrix_map_type * keyboard_map = new matrix_map_type; + new_zone.leds_count = total_leds; + new_zone.leds_min = new_zone.leds_count; + new_zone.leds_max = new_zone.leds_count; + + if(zone_types[zone_idx] == ZONE_TYPE_MATRIX) + { + new_zone.matrix_map = keyboard_map; + new_zone.matrix_map->height = 6; + new_zone.matrix_map->width = 19; + new_zone.matrix_map->map = (unsigned int *)&matrix_map; + } + else + { + new_zone.matrix_map = NULL; + } + zones.push_back(new_zone); + } + SetupColors(); +} + +void RGBController_HyperXAlloyOriginsCore::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_HyperXAlloyOriginsCore::DeviceUpdateLEDs() +{ + controller->SetLEDsDirect(colors); +} + +void RGBController_HyperXAlloyOriginsCore::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_HyperXAlloyOriginsCore::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_HyperXAlloyOriginsCore::DeviceUpdateMode() +{ + controller->SetBrightness(modes[active_mode].brightness); +} + +void RGBController_HyperXAlloyOriginsCore::KeepaliveThread() +{ + while(keepalive_thread_run.load()) + { + if(active_mode == 0) + { + if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50)) + { + UpdateLEDs(); + } + } + std::this_thread::sleep_for(10ms); + } +} diff --git a/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController/RGBController_HyperXAlloyOriginsCore.h b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController/RGBController_HyperXAlloyOriginsCore.h new file mode 100644 index 00000000..f1341c23 --- /dev/null +++ b/Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController/RGBController_HyperXAlloyOriginsCore.h @@ -0,0 +1,45 @@ +/*---------------------------------------------------------*\ +| RGBController_HyperXAlloyOriginsCore.h | +| | +| RGBController for HyperX Alloy Origins Core keyboard | +| | +| Volodymyr Nazarchuk (Vavooon) 28 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "HyperXAlloyOriginsCoreController.h" + +#define HYPERX_ALLOY_ORIGINS_CORE_ANSI 0x09 +#define HYPERX_ALLOY_ORIGINS_CORE_ABNT2 0x10 + +class RGBController_HyperXAlloyOriginsCore : public RGBController +{ +public: + RGBController_HyperXAlloyOriginsCore(HyperXAlloyOriginsCoreController* controller_ptr); + ~RGBController_HyperXAlloyOriginsCore(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + void KeepaliveThread(); + +private: + HyperXAlloyOriginsCoreController* controller; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::chrono::time_point last_update_time; + unsigned int variant; +}; diff --git a/Controllers/HyperXKeyboardController/HyperXKeyboardControllerDetect.cpp b/Controllers/HyperXKeyboardController/HyperXKeyboardControllerDetect.cpp index 8c5667a6..2bbec9d8 100644 --- a/Controllers/HyperXKeyboardController/HyperXKeyboardControllerDetect.cpp +++ b/Controllers/HyperXKeyboardController/HyperXKeyboardControllerDetect.cpp @@ -1,3 +1,13 @@ +/*---------------------------------------------------------*\ +| HyperXKeyboardControllerDetect.cpp | +| | +| Driver for HyperX keyboards | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "HyperXAlloyEliteController.h" #include "HyperXAlloyElite2Controller.h" @@ -5,14 +15,12 @@ #include "HyperXAlloyOriginsController.h" #include "HyperXAlloyOriginsCoreController.h" #include "HyperXAlloyOrigins60and65Controller.h" -#include "RGBController.h" #include "RGBController_HyperXAlloyElite.h" #include "RGBController_HyperXAlloyElite2.h" #include "RGBController_HyperXAlloyFPS.h" #include "RGBController_HyperXAlloyOrigins.h" #include "RGBController_HyperXAlloyOriginsCore.h" #include "RGBController_HyperXAlloyOrigins60and65.h" -#include /*-----------------------------------------------------*\ | HyperX keyboard vendor and product IDs | @@ -59,9 +67,8 @@ void DetectHyperXAlloyElite(hid_device_info* info, const std::string& name) if(dev) { - HyperXAlloyEliteController* controller = new HyperXAlloyEliteController(dev, info->path); + HyperXAlloyEliteController* controller = new HyperXAlloyEliteController(dev, info->path, name); RGBController_HyperXAlloyElite* rgb_controller = new RGBController_HyperXAlloyElite(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -73,9 +80,8 @@ void DetectHyperXAlloyElite2(hid_device_info* info, const std::string& name) if(dev) { - HyperXAlloyElite2Controller* controller = new HyperXAlloyElite2Controller(dev, info->path); + HyperXAlloyElite2Controller* controller = new HyperXAlloyElite2Controller(dev, info->path, name); RGBController_HyperXAlloyElite2* rgb_controller = new RGBController_HyperXAlloyElite2(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -87,9 +93,8 @@ void DetectHyperXAlloyFPS(hid_device_info* info, const std::string& name) if(dev) { - HyperXAlloyFPSController* controller = new HyperXAlloyFPSController(dev, info->path); + HyperXAlloyFPSController* controller = new HyperXAlloyFPSController(dev, info->path, name); RGBController_HyperXAlloyFPS* rgb_controller = new RGBController_HyperXAlloyFPS(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -101,9 +106,8 @@ void DetectHyperXAlloyOrigins(hid_device_info* info, const std::string& name) if(dev) { - HyperXAlloyOriginsController* controller = new HyperXAlloyOriginsController(dev, info->path); + HyperXAlloyOriginsController* controller = new HyperXAlloyOriginsController(dev, info->path, name); RGBController_HyperXAlloyOrigins* rgb_controller = new RGBController_HyperXAlloyOrigins(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -115,9 +119,8 @@ void DetectHyperXAlloyOriginsCore(hid_device_info* info, const std::string& name if(dev) { - HyperXAlloyOriginsCoreController* controller = new HyperXAlloyOriginsCoreController(dev, info); + HyperXAlloyOriginsCoreController* controller = new HyperXAlloyOriginsCoreController(dev, info, name); RGBController_HyperXAlloyOriginsCore* rgb_controller = new RGBController_HyperXAlloyOriginsCore(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -129,10 +132,9 @@ void DetectHyperXAlloyOrigins60and65(hid_device_info* info, const std::string& n if(dev) { - HyperXAlloyOrigins60and65Controller* controller = new HyperXAlloyOrigins60and65Controller(dev, info->path); + HyperXAlloyOrigins60and65Controller* controller = new HyperXAlloyOrigins60and65Controller(dev, info->path, name); AlloyOrigins60and65MappingLayoutType layout = GetAlloyOrigins60and65MappingLayoutType(info->product_id); RGBController_HyperXAlloyOrigins60and65* rgb_controller = new RGBController_HyperXAlloyOrigins60and65(controller, layout); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite.h b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite.h deleted file mode 100644 index 89831b4e..00000000 --- a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite.h +++ /dev/null @@ -1,41 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_HyperXAlloyElite.h | -| | -| Generic RGB Interface for HyperX Alloy | -| Elite Keyboard | -| | -| Adam Honse (CalcProgrammer1) 2/2/2020 | -\*-----------------------------------------*/ - -#pragma once -#include -#include -#include - -#include "RGBController.h" -#include "HyperXAlloyEliteController.h" - -class RGBController_HyperXAlloyElite : public RGBController -{ -public: - RGBController_HyperXAlloyElite(HyperXAlloyEliteController* controller_ptr); - ~RGBController_HyperXAlloyElite(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - void KeepaliveThreadFunction(); - -private: - HyperXAlloyEliteController* controller; - std::atomic keepalive_thread_run; - std::thread* keepalive_thread; - std::chrono::time_point last_update_time; -}; diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite2.h b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite2.h deleted file mode 100644 index e637db95..00000000 --- a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite2.h +++ /dev/null @@ -1,41 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_HyperXAlloyElite2.h | -| | -| Generic RGB Interface for HyperX Alloy | -| Elite2 RGB Keyboard | -| | -| KundaPanda (vojdo) 02/04/2021 | -\*-----------------------------------------*/ - -#pragma once -#include -#include -#include - -#include "RGBController.h" -#include "HyperXAlloyElite2Controller.h" - -class RGBController_HyperXAlloyElite2 : public RGBController -{ -public: - RGBController_HyperXAlloyElite2(HyperXAlloyElite2Controller* controller_ptr); - ~RGBController_HyperXAlloyElite2(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - void KeepaliveThreadFunction(); - -private: - HyperXAlloyElite2Controller* controller; - std::atomic keepalive_thread_run; - std::thread* keepalive_thread; - std::chrono::time_point last_update_time; -}; diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyFPS.h b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyFPS.h deleted file mode 100644 index fa2d5c86..00000000 --- a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyFPS.h +++ /dev/null @@ -1,41 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_HyperXAlloyFPS.h | -| | -| Generic RGB Interface for HyperX Alloy | -| FPS Keyboard | -| | -| Adam Honse (CalcProgrammer1) 2/2/2020 | -\*-----------------------------------------*/ - -#pragma once -#include -#include -#include - -#include "RGBController.h" -#include "HyperXAlloyFPSController.h" - -class RGBController_HyperXAlloyFPS : public RGBController -{ -public: - RGBController_HyperXAlloyFPS(HyperXAlloyFPSController* controller_ptr); - ~RGBController_HyperXAlloyFPS(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - void KeepaliveThreadFunction(); - -private: - HyperXAlloyFPSController* controller; - std::atomic keepalive_thread_run; - std::thread* keepalive_thread; - std::chrono::time_point last_update_time; -}; diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins.h b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins.h deleted file mode 100644 index ca51fe81..00000000 --- a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins.h +++ /dev/null @@ -1,39 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_HyperXAlloyOrigins.h | -| | -| Generic RGB Interface for HyperX Alloy | -| Origins RGB Keyboard | -| | -| Adam Honse (CalcProgrammer1) 7/11/2020 | -\*-----------------------------------------*/ - -#pragma once -#include - -#include "RGBController.h" -#include "HyperXAlloyOriginsController.h" - -class RGBController_HyperXAlloyOrigins : public RGBController -{ -public: - RGBController_HyperXAlloyOrigins(HyperXAlloyOriginsController* controller_ptr); - ~RGBController_HyperXAlloyOrigins(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - void KeepaliveThread(); - -private: - HyperXAlloyOriginsController* controller; - std::thread* keepalive_thread; - std::atomic keepalive_thread_run; - std::chrono::time_point last_update_time; -}; diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60and65.h b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60and65.h deleted file mode 100644 index f28b7935..00000000 --- a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60and65.h +++ /dev/null @@ -1,54 +0,0 @@ -/*-------------------------------------------*\ -| RGBController_HyperXAlloyOrigins60and65.h | -| | -| Generic RGB Interface for HyperX Alloy | -| Origins 60 and 65 RGB Keyboards | -| | -| Derek Huber 03/18/2023 | -\*-------------------------------------------*/ - -#pragma once -#include - -#include "RGBController.h" -#include "HyperXAlloyOrigins60and65Controller.h" - -enum AlloyOrigins60and65MappingLayoutType -{ - ALLOY_ORIGINS_60_LAYOUT, - ALLOY_ORIGINS_65_LAYOUT -}; - -typedef struct -{ - const char* name; - const zone_type type; - const unsigned int size; - matrix_map_type* matrix; -} led_zone; - -class RGBController_HyperXAlloyOrigins60and65 : public RGBController -{ -public: - RGBController_HyperXAlloyOrigins60and65(HyperXAlloyOrigins60and65Controller* controller_ptr, AlloyOrigins60and65MappingLayoutType keyboard_layout); - ~RGBController_HyperXAlloyOrigins60and65(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - void KeepaliveThread(); - -private: - HyperXAlloyOrigins60and65Controller* controller; - AlloyOrigins60and65MappingLayoutType layout; - std::thread* keepalive_thread; - std::atomic keepalive_thread_run; - std::chrono::time_point last_update_time; -}; diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.cpp b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.cpp deleted file mode 100644 index 9e076dc7..00000000 --- a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/*------------------------------------------*\ -| RGBController_HyperXAlloyOriginsCore.cpp | -| | -| Generic RGB Interface for HyperX Alloy | -| Origins Core RGB Keyboard | -| | -| Volodymyr Nazarchuk (Vavooon) 4/28/2021 | -\*------------------------------------------*/ - -#include "RGBControllerKeyNames.h" -#include "RGBController_HyperXAlloyOriginsCore.h" - -using namespace std::chrono_literals; - - -#define HYPERX_MIN_BRIGHTNESS 0 -#define HYPERX_MAX_BRIGHTNESS 255 - -//0xFFFFFFFF indicates an unused entry in matrix -#define NA 0xFFFFFFFF - -static unsigned int matrix_map[6][19] = -{ - { 0, NA, 1, 2, 3, 4, 5, 6, 7, 44, NA, 45, 46, 47, 48, NA, 49, 50, 51 }, - { 8, 9, 10, 11, 12, 13, 14, 15, 16, 52, 53, 54, 55, 56, NA, NA, 57, 58, 59 }, - { 17, NA, 18, 19, 20, 21, 22, 23, 24, 60, 61, 62, 63, 64, 65, NA, 66, 67, 68 }, - { 25, NA, 26, 27, 28, 29, 30, 31, 32, 69, 70, 71, 72, 73, NA, NA, NA, NA, NA }, - { 33, NA, 34, 35, 36, 37, 38, NA, 39, 74, 75, 76, 77, 78, NA, NA, NA, 79, NA }, - { 40, 41, 42, NA, NA, NA, 43, NA, NA, NA, NA, 80, 81, 82, 83, NA, 84, 85, 86 } -}; - -static const char* zone_names[] = -{ - ZONE_EN_KEYBOARD, -}; - -static zone_type zone_types[] = -{ - ZONE_TYPE_MATRIX, -}; - -static const unsigned int zone_sizes[] = -{ - 87, -}; - -static const char *led_names[] = -{ - KEY_EN_ESCAPE, - KEY_EN_F1, - KEY_EN_F2, - KEY_EN_F3, - KEY_EN_F4, - KEY_EN_F5, - KEY_EN_F6, - KEY_EN_F7, - - KEY_EN_BACK_TICK, - KEY_EN_1, - KEY_EN_2, - KEY_EN_3, - KEY_EN_4, - KEY_EN_5, - KEY_EN_6, - KEY_EN_7, - KEY_EN_8, - - KEY_EN_TAB, - KEY_EN_Q, - KEY_EN_W, - KEY_EN_E, - KEY_EN_R, - KEY_EN_T, - KEY_EN_Y, - KEY_EN_U, - - KEY_EN_CAPS_LOCK, - KEY_EN_A, - KEY_EN_S, - KEY_EN_D, - KEY_EN_F, - KEY_EN_G, - KEY_EN_H, - KEY_EN_J, - - KEY_EN_LEFT_SHIFT, - KEY_EN_Z, - KEY_EN_X, - KEY_EN_C, - KEY_EN_V, - KEY_EN_B, - KEY_EN_N, - - KEY_EN_LEFT_CONTROL, - KEY_EN_LEFT_WINDOWS, - KEY_EN_LEFT_ALT, - KEY_EN_SPACE, - - // End of first section - - KEY_EN_F8, - KEY_EN_F9, - KEY_EN_F10, - KEY_EN_F11, - KEY_EN_F12, - KEY_EN_PRINT_SCREEN, - KEY_EN_SCROLL_LOCK, - KEY_EN_PAUSE_BREAK, - - KEY_EN_9, - KEY_EN_0, - KEY_EN_MINUS, - KEY_EN_EQUALS, - KEY_EN_BACKSPACE, - KEY_EN_INSERT, - KEY_EN_HOME, - KEY_EN_PAGE_UP, - - - KEY_EN_I, - KEY_EN_O, - KEY_EN_P, - KEY_EN_LEFT_BRACKET, - KEY_EN_RIGHT_BRACKET, - KEY_EN_ANSI_BACK_SLASH, - KEY_EN_DELETE, - KEY_EN_END, - KEY_EN_PAGE_DOWN, - - - KEY_EN_K, - KEY_EN_L, - KEY_EN_SEMICOLON, - KEY_EN_QUOTE, - KEY_EN_ANSI_ENTER, - - - KEY_EN_M, - KEY_EN_COMMA, - KEY_EN_PERIOD, - KEY_EN_FORWARD_SLASH, - KEY_EN_RIGHT_SHIFT, - KEY_EN_UP_ARROW, - KEY_EN_RIGHT_ALT, - KEY_EN_RIGHT_FUNCTION, - KEY_EN_MENU, - KEY_EN_RIGHT_CONTROL, - KEY_EN_LEFT_ARROW, - KEY_EN_DOWN_ARROW, - KEY_EN_RIGHT_ARROW -}; - -/**------------------------------------------------------------------*\ - @name HyperX Alloy Origins Core - @category Keyboard - @type USB - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectHyperXAlloyOriginsCore - @comment -\*-------------------------------------------------------------------*/ - -RGBController_HyperXAlloyOriginsCore::RGBController_HyperXAlloyOriginsCore(HyperXAlloyOriginsCoreController* controller_ptr) -{ - controller = controller_ptr; - - name = "HyperX Alloy Origins Core Keyboard Device"; - vendor = "HyperX"; - type = DEVICE_TYPE_KEYBOARD; - description = "HyperX Alloy Origins Core Keyboard Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = 0xFFFF; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Direct.brightness_min = HYPERX_MIN_BRIGHTNESS; - Direct.brightness_max = HYPERX_MAX_BRIGHTNESS; - Direct.brightness = HYPERX_MAX_BRIGHTNESS; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - - SetupZones(); - - /*-----------------------------------------------------*\ - | The HyperX Origins Core requires a packet within few | - | seconds of sending the lighting change in order to | - | not revert back into current profile. Start a thread | - | to continuously send color values each 10ms | - \*-----------------------------------------------------*/ - keepalive_thread_run = 1; - keepalive_thread = new std::thread(&RGBController_HyperXAlloyOriginsCore::KeepaliveThread, this); -} - -RGBController_HyperXAlloyOriginsCore::~RGBController_HyperXAlloyOriginsCore() -{ - keepalive_thread_run = 0; - keepalive_thread->join(); - delete keepalive_thread; - - /*---------------------------------------------------------*\ - | Delete the matrix map | - \*---------------------------------------------------------*/ - 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; - } - } - - delete controller; -} - -void RGBController_HyperXAlloyOriginsCore::SetupZones() -{ - unsigned int total_led_count = 0; - for(unsigned int zone_idx = 0; zone_idx < 1; zone_idx++) - { - zone new_zone; - new_zone.name = zone_names[zone_idx]; - new_zone.type = zone_types[zone_idx]; - new_zone.leds_min = zone_sizes[zone_idx]; - new_zone.leds_max = zone_sizes[zone_idx]; - new_zone.leds_count = zone_sizes[zone_idx]; - - if(zone_types[zone_idx] == ZONE_TYPE_MATRIX) - { - new_zone.matrix_map = new matrix_map_type; - new_zone.matrix_map->height = 6; - new_zone.matrix_map->width = 19; - new_zone.matrix_map->map = (unsigned int *)&matrix_map; - } - else - { - new_zone.matrix_map = NULL; - } - - zones.push_back(new_zone); - - total_led_count += zone_sizes[zone_idx]; - } - - for(unsigned int led_idx = 0; led_idx < total_led_count; led_idx++) - { - led new_led; - new_led.name = led_names[led_idx]; - leds.push_back(new_led); - } - - SetupColors(); -} - -void RGBController_HyperXAlloyOriginsCore::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_HyperXAlloyOriginsCore::DeviceUpdateLEDs() -{ - controller->SetLEDsDirect(colors); -} - -void RGBController_HyperXAlloyOriginsCore::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_HyperXAlloyOriginsCore::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_HyperXAlloyOriginsCore::DeviceUpdateMode() -{ - controller->SetBrightness(modes[active_mode].brightness); -} - -void RGBController_HyperXAlloyOriginsCore::KeepaliveThread() -{ - while(keepalive_thread_run.load()) - { - if(active_mode == 0) - { - if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50)) - { - UpdateLEDs(); - } - } - std::this_thread::sleep_for(10ms); - } -} diff --git a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.h b/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.h deleted file mode 100644 index 5479c1f1..00000000 --- a/Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.h +++ /dev/null @@ -1,39 +0,0 @@ -/*------------------------------------------*\ -| RGBController_HyperXAlloyOriginsCore.h | -| | -| Generic RGB Interface for HyperX Alloy | -| Origins Core RGB Keyboard | -| | -| Volodymyr Nazarchuk (Vavooon) 4/28/2021 | -\*------------------------------------------*/ - -#pragma once -#include - -#include "RGBController.h" -#include "HyperXAlloyOriginsCoreController.h" - -class RGBController_HyperXAlloyOriginsCore : public RGBController -{ -public: - RGBController_HyperXAlloyOriginsCore(HyperXAlloyOriginsCoreController* controller_ptr); - ~RGBController_HyperXAlloyOriginsCore(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - void KeepaliveThread(); - -private: - HyperXAlloyOriginsCoreController* controller; - std::thread* keepalive_thread; - std::atomic keepalive_thread_run; - std::chrono::time_point last_update_time; -}; diff --git a/Controllers/HyperXMicrophoneController/HyperXMicrophoneController.cpp b/Controllers/HyperXMicrophoneController/HyperXMicrophoneController.cpp index 6d2e24b3..a0a8345e 100644 --- a/Controllers/HyperXMicrophoneController/HyperXMicrophoneController.cpp +++ b/Controllers/HyperXMicrophoneController/HyperXMicrophoneController.cpp @@ -1,53 +1,61 @@ -/*-----------------------------------------*\ -| HyperXMicrophoneController.cpp | -| | -| Implementation for the HyperX | -| Quadcast S RGB microphone | -| | -| Matt Silva (thesilvanator) 2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| HyperXMicrophoneController.cpp | +| | +| Driver for HyperX microphone | +| | +| Matt Silva (thesilvanator) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "HyperXMicrophoneController.h" #include +#include "HyperXMicrophoneController.h" +#include "StringUtils.h" using namespace std::chrono_literals; -HyperXMicrophoneController::HyperXMicrophoneController(hidapi_wrapper hid_wrapper, hid_device* dev_handle, std::string path) +HyperXMicrophoneController::HyperXMicrophoneController(hidapi_wrapper hid_wrapper, hid_device* dev_handle, std::string path, std::string dev_name) { wrapper = hid_wrapper; dev = dev_handle; location = path; + name = dev_name; +} +HyperXMicrophoneController::~HyperXMicrophoneController() +{ + lock.lock(); + + if(dev) + { + wrapper.hid_close(dev); + } + + lock.unlock(); +} + +std::string HyperXMicrophoneController::GetDeviceLocation() +{ + return(location); +} + +std::string HyperXMicrophoneController::GetNameString() +{ + return(name); +} + +std::string HyperXMicrophoneController::GetSerialString() +{ wchar_t serial_string[128]; int ret = wrapper.hid_get_serial_number_string(dev, serial_string, 128); if(ret != 0) { - serial_number = ""; + return(""); } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } -} -HyperXMicrophoneController::~HyperXMicrophoneController() -{ - if(dev) - { - wrapper.hid_close(dev); - } -} - -std::string HyperXMicrophoneController::GetDeviceLocation() -{ - return location; -} - -std::string HyperXMicrophoneController::GetSerialString() -{ - return serial_number; + return(StringUtils::wstring_to_string(serial_string)); } void HyperXMicrophoneController::SaveColors(std::vector colors, unsigned int num_frames) diff --git a/Controllers/HyperXMicrophoneController/HyperXMicrophoneController.h b/Controllers/HyperXMicrophoneController/HyperXMicrophoneController.h index 3a695d4d..22c4abb5 100644 --- a/Controllers/HyperXMicrophoneController/HyperXMicrophoneController.h +++ b/Controllers/HyperXMicrophoneController/HyperXMicrophoneController.h @@ -1,11 +1,14 @@ -/*-----------------------------------------*\ -| HyperXMicrophoneController.h | -| | -| Implementation for the HyperX | -| Quadcast S RGB microphone | -| | -| Matt Silva (thesilvanator) 2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| HyperXMicrophoneController.cpp | +| | +| Driver for HyperX microphone | +| | +| Matt Silva (thesilvanator) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include @@ -18,10 +21,11 @@ class HyperXMicrophoneController { public: - HyperXMicrophoneController(hidapi_wrapper hid_wrapper, hid_device* dev, std::string path); + HyperXMicrophoneController(hidapi_wrapper hid_wrapper, hid_device* dev, std::string path, std::string dev_name); ~HyperXMicrophoneController(); std::string GetDeviceLocation(); + std::string GetNameString(); std::string GetSerialString(); void SendDirect(std::vector color_data); @@ -31,8 +35,8 @@ private: hidapi_wrapper wrapper; hid_device* dev; std::string location; - std::string serial_number; std::mutex lock; + std::string name; void SendEOT(uint8_t frame_count); void SendToRegister(uint8_t reg, uint8_t param1, uint8_t param2); diff --git a/Controllers/HyperXMicrophoneController/HyperXMicrophoneControllerDetect.cpp b/Controllers/HyperXMicrophoneController/HyperXMicrophoneControllerDetect.cpp index 9d1ad2fc..34f65332 100644 --- a/Controllers/HyperXMicrophoneController/HyperXMicrophoneControllerDetect.cpp +++ b/Controllers/HyperXMicrophoneController/HyperXMicrophoneControllerDetect.cpp @@ -1,19 +1,17 @@ -/*-----------------------------------------*\ -| HyperXMicrophoneControllerDetect.cpp | -| | -| Implementation for the HyperX | -| Quadcast S RGB microphone | -| | -| Matt Silva (thesilvanator) 2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| HyperXMicrophoneControllerDetect.cpp | +| | +| Detector for HyperX microphone | +| | +| Matt Silva (thesilvanator) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "Detector.h" #include "HyperXMicrophoneController.h" -#include "RGBController.h" #include "RGBController_HyperXMicrophone.h" -#include -#include - #include "hidapi_wrapper.h" /*-----------------------------------------------------*\ @@ -28,6 +26,8 @@ #define HYPERX_QS_PID_HP_2 0x068C #define HYPERX_QS_PID_HP_3 0x0294 #define HYPERX_QS_PID_HP_4 0x028C +#define HYPERX_QS_PID_HP_5 0x048C +#define HYPERX_QS_PID_HP_6 0x0D8B #define HYPERX_DUOCAST_PID 0x098C @@ -37,9 +37,8 @@ void DetectHyperXMicrophoneControllers(hidapi_wrapper wrapper, hid_device_info* if(dev) { - HyperXMicrophoneController* controller = new HyperXMicrophoneController(wrapper, dev, info->path); + HyperXMicrophoneController* controller = new HyperXMicrophoneController(wrapper, dev, info->path, name); RGBController_HyperXMicrophone *rgb_controller = new RGBController_HyperXMicrophone(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -50,4 +49,6 @@ REGISTER_HID_WRAPPED_DETECTOR_I("HyperX Quadcast S", DetectHyperXMicrophoneContr REGISTER_HID_WRAPPED_DETECTOR_I("HyperX Quadcast S", DetectHyperXMicrophoneControllers, HYPERX_HP_VID, HYPERX_QS_PID_HP_2, 0);//, 0xFF90, 0xFF00); REGISTER_HID_WRAPPED_DETECTOR_I("HyperX Quadcast S", DetectHyperXMicrophoneControllers, HYPERX_HP_VID, HYPERX_QS_PID_HP_3, 0);//, 0xFF90, 0xFF00); REGISTER_HID_WRAPPED_DETECTOR_I("HyperX Quadcast S", DetectHyperXMicrophoneControllers, HYPERX_HP_VID, HYPERX_QS_PID_HP_4, 0);//, 0xFF90, 0xFF00); +REGISTER_HID_WRAPPED_DETECTOR_I("HyperX Quadcast S", DetectHyperXMicrophoneControllers, HYPERX_HP_VID, HYPERX_QS_PID_HP_5, 0);//, 0xFF90, 0xFF00); +REGISTER_HID_WRAPPED_DETECTOR_I("HyperX Quadcast S", DetectHyperXMicrophoneControllers, HYPERX_HP_VID, HYPERX_QS_PID_HP_6, 0);//, 0xFF90, 0xFF00); REGISTER_HID_WRAPPED_DETECTOR_I("HyperX DuoCast", DetectHyperXMicrophoneControllers, HYPERX_HP_VID, HYPERX_DUOCAST_PID, 0);//, 0xFF90, 0xFF00); diff --git a/Controllers/HyperXMicrophoneController/RGBController_HyperXMicrophone.cpp b/Controllers/HyperXMicrophoneController/RGBController_HyperXMicrophone.cpp index c622bb5d..40a51fef 100644 --- a/Controllers/HyperXMicrophoneController/RGBController_HyperXMicrophone.cpp +++ b/Controllers/HyperXMicrophoneController/RGBController_HyperXMicrophone.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_HyperXMicrophone.cpp | -| | -| Implementation for the HyperX | -| Quadcast S RGB microphone | -| | -| Matt Silva (thesilvanator) 2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_HyperXMicrophone.cpp | +| | +| RGBController for HyperX microphone | +| | +| Matt Silva (thesilvanator) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ /**------------------------------------------------------------------*\ @name HyperX Quadcast S @@ -55,6 +57,7 @@ RGBController_HyperXMicrophone::RGBController_HyperXMicrophone(HyperXMicrophoneC { controller = controller_ptr; + name = controller->GetNameString(); vendor = "HyperX"; type = DEVICE_TYPE_MICROPHONE; description = "HyperX Microphone Device"; @@ -97,7 +100,7 @@ void RGBController_HyperXMicrophone::SetupZones() zone Mic; Mic.name = "Microphone"; - Mic.type = ZONE_TYPE_LINEAR; + Mic.type = ZONE_TYPE_SINGLE; Mic.leds_min = 2; Mic.leds_max = 2; Mic.leds_count = 2; diff --git a/Controllers/HyperXMicrophoneController/RGBController_HyperXMicrophone.h b/Controllers/HyperXMicrophoneController/RGBController_HyperXMicrophone.h index 8b28fc67..ae61c100 100644 --- a/Controllers/HyperXMicrophoneController/RGBController_HyperXMicrophone.h +++ b/Controllers/HyperXMicrophoneController/RGBController_HyperXMicrophone.h @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_HyperXMicrophone.h | -| | -| Implementation for the HyperX | -| Quadcast S RGB microphone | -| | -| Matt Silva (thesilvanator) 2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_HyperXMicrophone.h | +| | +| RGBController for HyperX microphone | +| | +| Matt Silva (thesilvanator) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include +#include #include "RGBController.h" #include "HyperXMicrophoneController.h" diff --git a/Controllers/HyperXMouseController/HyperXMouseControllerDetect.cpp b/Controllers/HyperXMouseController/HyperXMouseControllerDetect.cpp index fde37d97..20fe7313 100644 --- a/Controllers/HyperXMouseController/HyperXMouseControllerDetect.cpp +++ b/Controllers/HyperXMouseController/HyperXMouseControllerDetect.cpp @@ -1,24 +1,34 @@ +/*---------------------------------------------------------*\ +| HyperXMouseControllerDetect.cpp | +| | +| Detector for HyperX mouse | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "HyperXPulsefireFPSProController.h" #include "HyperXPulsefireSurgeController.h" #include "HyperXPulsefireDartController.h" #include "HyperXPulsefireRaidController.h" -#include "RGBController.h" #include "RGBController_HyperXPulsefireFPSPro.h" #include "RGBController_HyperXPulsefireHaste.h" #include "RGBController_HyperXPulsefireSurge.h" #include "RGBController_HyperXPulsefireDart.h" #include "RGBController_HyperXPulsefireRaid.h" -#include /*-----------------------------------------------------*\ | HyperX mouse vendor IDs | \*-----------------------------------------------------*/ -#define HYPERX_VID 0x0951 -#define HYPERX_VID_2 0x03F0 +#define HYPERX_VID 0x0951 //Kingston Technology +#define HYPERX_VID_2 0x03F0 //HP, Hewlett-Packard Company #define HYPERX_PULSEFIRE_SURGE_PID 0x16D3 +#define HYPERX_PULSEFIRE_SURGE_PID_2 0x0490 #define HYPERX_PULSEFIRE_FPS_PRO_PID 0x16D7 #define HYPERX_PULSEFIRE_CORE_PID 0x16DE +#define HYPERX_PULSEFIRE_CORE_PID_2 0x0D8F #define HYPERX_PULSEFIRE_DART_WIRELESS_PID 0x16E1 #define HYPERX_PULSEFIRE_DART_WIRELESS_PID_2 0x068E #define HYPERX_PULSEFIRE_DART_WIRED_PID 0x16E2 @@ -33,9 +43,8 @@ void DetectHyperXPulsefireSurgeControllers(hid_device_info* info, const std::str if(dev) { - HyperXPulsefireSurgeController* controller = new HyperXPulsefireSurgeController(dev, info->path); + HyperXPulsefireSurgeController* controller = new HyperXPulsefireSurgeController(dev, info->path, name); RGBController_HyperXPulsefireSurge* rgb_controller = new RGBController_HyperXPulsefireSurge(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -47,9 +56,8 @@ void DetectHyperXPulsefireFPSProControllers(hid_device_info* info, const std::st if(dev) { - HyperXPulsefireFPSProController* controller = new HyperXPulsefireFPSProController(dev, info->path); + HyperXPulsefireFPSProController* controller = new HyperXPulsefireFPSProController(dev, info->path, name); RGBController_HyperXPulsefireFPSPro* rgb_controller = new RGBController_HyperXPulsefireFPSPro(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -61,9 +69,8 @@ void DetectHyperXPulsefireHasteControllers(hid_device_info* info, const std::str if(dev) { - HyperXPulsefireHasteController* controller = new HyperXPulsefireHasteController(dev, info->path); + HyperXPulsefireHasteController* controller = new HyperXPulsefireHasteController(dev, info->path, name); RGBController_HyperXPulsefireHaste* rgb_controller = new RGBController_HyperXPulsefireHaste(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -75,9 +82,8 @@ void DetectHyperXPulsefireDartControllers(hid_device_info* info, const std::stri if(dev) { - HyperXPulsefireDartController* controller = new HyperXPulsefireDartController(dev, info->path); + HyperXPulsefireDartController* controller = new HyperXPulsefireDartController(dev, info->path, name); RGBController_HyperXPulsefireDart* rgb_controller = new RGBController_HyperXPulsefireDart(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -89,17 +95,18 @@ void DetectHyperXPulsefireRaidControllers(hid_device_info* info, const std::stri if(dev) { - HyperXPulsefireRaidController* controller = new HyperXPulsefireRaidController(dev, *info); + HyperXPulsefireRaidController* controller = new HyperXPulsefireRaidController(dev, *info, name); RGBController_HyperXPulsefireRaid* rgb_controller = new RGBController_HyperXPulsefireRaid(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } /* DetectHyperXPulsefireRaidControllers() */ REGISTER_HID_DETECTOR_IP("HyperX Pulsefire Surge", DetectHyperXPulsefireSurgeControllers, HYPERX_VID, HYPERX_PULSEFIRE_SURGE_PID, 1, 0xFF01); +REGISTER_HID_DETECTOR_IP("HyperX Pulsefire Surge (HP)", DetectHyperXPulsefireSurgeControllers, HYPERX_VID_2, HYPERX_PULSEFIRE_SURGE_PID_2, 1, 0xFF01); REGISTER_HID_DETECTOR_IP("HyperX Pulsefire FPS Pro", DetectHyperXPulsefireFPSProControllers, HYPERX_VID, HYPERX_PULSEFIRE_FPS_PRO_PID, 1, 0xFF01); REGISTER_HID_DETECTOR_IP("HyperX Pulsefire Core", DetectHyperXPulsefireFPSProControllers, HYPERX_VID, HYPERX_PULSEFIRE_CORE_PID, 1, 0xFF01); +REGISTER_HID_DETECTOR_IP("HyperX Pulsefire Core (HP)", DetectHyperXPulsefireFPSProControllers, HYPERX_VID_2, HYPERX_PULSEFIRE_CORE_PID_2, 1, 0xFF01); REGISTER_HID_DETECTOR_IP("HyperX Pulsefire Dart (Wireless)", DetectHyperXPulsefireDartControllers, HYPERX_VID, HYPERX_PULSEFIRE_DART_WIRELESS_PID, 2, 0xFF00); REGISTER_HID_DETECTOR_IP("HyperX Pulsefire Dart (Wireless)", DetectHyperXPulsefireDartControllers, HYPERX_VID_2, HYPERX_PULSEFIRE_DART_WIRELESS_PID_2, 2, 0xFF00); REGISTER_HID_DETECTOR_IP("HyperX Pulsefire Dart (Wired)", DetectHyperXPulsefireDartControllers, HYPERX_VID, HYPERX_PULSEFIRE_DART_WIRED_PID, 1, 0xFF13); diff --git a/Controllers/HyperXMouseController/HyperXPulsefireDartController.h b/Controllers/HyperXMouseController/HyperXPulsefireDartController.h deleted file mode 100644 index d70538a1..00000000 --- a/Controllers/HyperXMouseController/HyperXPulsefireDartController.h +++ /dev/null @@ -1,63 +0,0 @@ -/*-------------------------------------------*\ -| HyperXPulsefireDartController.h | -| | -| Definitions and types for HyperX | -| Pulsefire Dart lighting controller | -| | -| Santeri Pikarinen (santeri3700) 12/26/2020 | -\*-------------------------------------------*/ - -#include "RGBController.h" - -#include -#include - -#pragma once - -enum -{ - HYPERX_PULSEFIRE_DART_PACKET_ID_DIRECT = 0xd2, /* Direct control packet */ - HYPERX_PULSEFIRE_DART_PACKET_SIZE = 65, /* Report ID padding + 64 byte payload */ - - HYPERX_PULSEFIRE_DART_MODE_STATIC = 0x00, /* Static color mode */ - HYPERX_PULSEFIRE_DART_MODE_CYCLE = 0x12, /* Spectrum cycle mode */ - HYPERX_PULSEFIRE_DART_MODE_BREATHING = 0x20, /* Single color breathing mode */ - HYPERX_PULSEFIRE_DART_MODE_REACTIVE = 0x30, /* Reactive/Trigger fade mode */ - - HYPERX_PULSEFIRE_DART_SPEED_MIN = 0x64, - HYPERX_PULSEFIRE_DART_SPEED_MAX = 0x00, - HYPERX_PULSEFIRE_DART_SPEED_MED = 0x32, - HYPERX_PULSEFIRE_DART_SPEED_NONE = 0x00, /* For static color mode */ - - HYPERX_PULSEFIRE_DART_BRIGHTNESS_MIN = 0x00, - HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX = 0x64, - - HYPERX_PULSEFIRE_DART_LED_LOGO = 0x00, - HYPERX_PULSEFIRE_DART_LED_SCROLL = 0x10, - HYPERX_PULSEFIRE_DART_LED_ALL = 0x20 -}; - -class HyperXPulsefireDartController -{ -public: - HyperXPulsefireDartController(hid_device* dev_handle, const char* path); - ~HyperXPulsefireDartController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - - void SendDirect - ( - RGBColor color_data, - int led, - int mode, - int brightness, - int speed - ); - - void Save(); - -private: - hid_device* dev; - std::string location; -}; diff --git a/Controllers/HyperXMouseController/HyperXPulsefireDartController.cpp b/Controllers/HyperXMouseController/HyperXPulsefireDartController/HyperXPulsefireDartController.cpp similarity index 79% rename from Controllers/HyperXMouseController/HyperXPulsefireDartController.cpp rename to Controllers/HyperXMouseController/HyperXPulsefireDartController/HyperXPulsefireDartController.cpp index 62e523f5..7f3bb62b 100644 --- a/Controllers/HyperXMouseController/HyperXPulsefireDartController.cpp +++ b/Controllers/HyperXMouseController/HyperXPulsefireDartController/HyperXPulsefireDartController.cpp @@ -1,20 +1,23 @@ -/*-------------------------------------------*\ -| HyperXPulsefireDartController.cpp | -| | -| Driver for HyperX Pulsefire Dart | -| lighting controller | -| | -| Santeri Pikarinen (santeri3700) 12/26/2020 | -\*-------------------------------------------*/ - -#include "HyperXPulsefireDartController.h" +/*---------------------------------------------------------*\ +| HyperXPulsefireDartController.cpp | +| | +| Driver for HyperX Pulsefire Dart | +| | +| Santeri Pikarinen (santeri3700) 26 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "HyperXPulsefireDartController.h" +#include "StringUtils.h" -HyperXPulsefireDartController::HyperXPulsefireDartController(hid_device* dev_handle, const char* path) +HyperXPulsefireDartController::HyperXPulsefireDartController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } HyperXPulsefireDartController::~HyperXPulsefireDartController() @@ -27,6 +30,11 @@ std::string HyperXPulsefireDartController::GetDeviceLocation() return("HID: " + location); } +std::string HyperXPulsefireDartController::GetNameString() +{ + return(name); +} + std::string HyperXPulsefireDartController::GetSerialString() { wchar_t serial_string[128]; @@ -37,10 +45,7 @@ std::string HyperXPulsefireDartController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } /*-------------------------------------------------------------------------------------------------*\ @@ -71,7 +76,7 @@ void HyperXPulsefireDartController::SendDirect buf[0x02] = led; buf[0x03] = mode; buf[0x04] = 0x08; // 8 bytes after buffer index 0x04 - + buf[0x05] = RGBGetRValue(color); buf[0x06] = RGBGetGValue(color); buf[0x07] = RGBGetBValue(color); @@ -82,7 +87,7 @@ void HyperXPulsefireDartController::SendDirect buf[0x0b] = brightness; buf[0x0c] = speed; - + /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ diff --git a/Controllers/HyperXMouseController/HyperXPulsefireDartController/HyperXPulsefireDartController.h b/Controllers/HyperXMouseController/HyperXPulsefireDartController/HyperXPulsefireDartController.h new file mode 100644 index 00000000..32310776 --- /dev/null +++ b/Controllers/HyperXMouseController/HyperXPulsefireDartController/HyperXPulsefireDartController.h @@ -0,0 +1,66 @@ +/*---------------------------------------------------------*\ +| HyperXPulsefireDartController.h | +| | +| Driver for HyperX Pulsefire Dart | +| | +| Santeri Pikarinen (santeri3700) 26 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +enum +{ + HYPERX_PULSEFIRE_DART_PACKET_ID_DIRECT = 0xd2, /* Direct control packet */ + HYPERX_PULSEFIRE_DART_PACKET_SIZE = 65, /* Report ID padding + 64 byte payload */ + + HYPERX_PULSEFIRE_DART_MODE_STATIC = 0x00, /* Static color mode */ + HYPERX_PULSEFIRE_DART_MODE_CYCLE = 0x12, /* Spectrum cycle mode */ + HYPERX_PULSEFIRE_DART_MODE_BREATHING = 0x20, /* Single color breathing mode */ + HYPERX_PULSEFIRE_DART_MODE_REACTIVE = 0x30, /* Reactive/Trigger fade mode */ + + HYPERX_PULSEFIRE_DART_SPEED_MIN = 0x64, + HYPERX_PULSEFIRE_DART_SPEED_MAX = 0x00, + HYPERX_PULSEFIRE_DART_SPEED_MED = 0x32, + HYPERX_PULSEFIRE_DART_SPEED_NONE = 0x00, /* For static color mode */ + + HYPERX_PULSEFIRE_DART_BRIGHTNESS_MIN = 0x00, + HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX = 0x64, + + HYPERX_PULSEFIRE_DART_LED_LOGO = 0x00, + HYPERX_PULSEFIRE_DART_LED_SCROLL = 0x10, + HYPERX_PULSEFIRE_DART_LED_ALL = 0x20 +}; + +class HyperXPulsefireDartController +{ +public: + HyperXPulsefireDartController(hid_device* dev_handle, const char* path, std::string dev_name); + ~HyperXPulsefireDartController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SendDirect + ( + RGBColor color_data, + int led, + int mode, + int brightness, + int speed + ); + + void Save(); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/HyperXMouseController/HyperXPulsefireDartController/RGBController_HyperXPulsefireDart.cpp b/Controllers/HyperXMouseController/HyperXPulsefireDartController/RGBController_HyperXPulsefireDart.cpp new file mode 100644 index 00000000..0e0a6576 --- /dev/null +++ b/Controllers/HyperXMouseController/HyperXPulsefireDartController/RGBController_HyperXPulsefireDart.cpp @@ -0,0 +1,170 @@ +/*---------------------------------------------------------*\ +| RGBController_HyperXPulsefireDart.cpp | +| | +| RGBController for HyperX Pulsefire Dart | +| | +| Santeri Pikarinen (santeri3700) 26 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_HyperXPulsefireDart.h" + +/**------------------------------------------------------------------*\ + @name HyperX Pulsefire Dart + @category Mouse + @type USB + @save :white_check_mark: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectHyperXPulsefireDartControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_HyperXPulsefireDart::RGBController_HyperXPulsefireDart(HyperXPulsefireDartController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "HyperX"; + type = DEVICE_TYPE_MOUSE; + description = "HyperX Pulsefire Dart Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = HYPERX_PULSEFIRE_DART_MODE_STATIC; + Direct.speed = HYPERX_PULSEFIRE_DART_SPEED_NONE; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MIN; + Direct.brightness_max = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX; + Direct.brightness = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX; + modes.push_back(Direct); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = HYPERX_PULSEFIRE_DART_MODE_BREATHING; + Breathing.speed = HYPERX_PULSEFIRE_DART_SPEED_MED; + Breathing.speed_min = HYPERX_PULSEFIRE_DART_SPEED_MIN; + Breathing.speed_max = HYPERX_PULSEFIRE_DART_SPEED_MAX; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.brightness_min = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MIN; + Breathing.brightness_max = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX; + Breathing.brightness = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX; + modes.push_back(Breathing); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = HYPERX_PULSEFIRE_DART_MODE_CYCLE; + SpectrumCycle.speed = HYPERX_PULSEFIRE_DART_SPEED_MED; + SpectrumCycle.speed_min = HYPERX_PULSEFIRE_DART_SPEED_MIN; + SpectrumCycle.speed_max = HYPERX_PULSEFIRE_DART_SPEED_MAX; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.brightness_min = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MIN; + SpectrumCycle.brightness_max = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX; + SpectrumCycle.brightness = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX; + modes.push_back(SpectrumCycle); + + mode Reactive; + Reactive.name = "Reactive"; + Reactive.value = HYPERX_PULSEFIRE_DART_MODE_REACTIVE; + Reactive.speed = HYPERX_PULSEFIRE_DART_SPEED_MED; + Reactive.speed_min = HYPERX_PULSEFIRE_DART_SPEED_MIN; + Reactive.speed_max = HYPERX_PULSEFIRE_DART_SPEED_MAX; + Reactive.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Reactive.color_mode = MODE_COLORS_PER_LED; + Reactive.brightness_min = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MIN; + Reactive.brightness_max = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX; + Reactive.brightness = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX; + modes.push_back(Reactive); + + SetupZones(); +} + +RGBController_HyperXPulsefireDart::~RGBController_HyperXPulsefireDart() +{ + +} + +void RGBController_HyperXPulsefireDart::SetupZones() +{ + zone scroll_zone; + scroll_zone.name = "Scroll Wheel"; + scroll_zone.type = ZONE_TYPE_SINGLE; + scroll_zone.leds_min = 1; + scroll_zone.leds_max = 1; + scroll_zone.leds_count = 1; + scroll_zone.matrix_map = NULL; + zones.push_back(scroll_zone); + + led scroll_led; + scroll_led.name = "Scroll Wheel"; + scroll_led.value = HYPERX_PULSEFIRE_DART_LED_SCROLL; + leds.push_back(scroll_led); + + zone logo_zone; + logo_zone.name = "Logo"; + logo_zone.type = ZONE_TYPE_SINGLE; + logo_zone.leds_min = 1; + logo_zone.leds_max = 1; + logo_zone.leds_count = 1; + logo_zone.matrix_map = NULL; + zones.push_back(logo_zone); + + led logo_led; + logo_led.name = "Logo"; + logo_led.value = HYPERX_PULSEFIRE_DART_LED_LOGO; + leds.push_back(logo_led); + + SetupColors(); +} + +void RGBController_HyperXPulsefireDart::ResizeZone(int /*zone*/, int /*new_size*/) +{ + +} + +void RGBController_HyperXPulsefireDart::DeviceUpdateLEDs() +{ + DeviceUpdateMode(); +} + +void RGBController_HyperXPulsefireDart::UpdateZoneLEDs(int zone) +{ + UpdateSingleLED(zone); +} + +void RGBController_HyperXPulsefireDart::UpdateSingleLED(int led) +{ + if(modes[active_mode].color_mode == MODE_COLORS_PER_LED) + { + controller->SendDirect(colors[led], leds[led].value, modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed); + } + else + { + controller->SendDirect(colors[led], HYPERX_PULSEFIRE_DART_LED_ALL, modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed); + } +} + +void RGBController_HyperXPulsefireDart::DeviceUpdateMode() +{ + if(modes[active_mode].color_mode == MODE_COLORS_PER_LED) + { + controller->SendDirect(colors[0], HYPERX_PULSEFIRE_DART_LED_SCROLL, modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed); + controller->SendDirect(colors[1], HYPERX_PULSEFIRE_DART_LED_LOGO, modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed); + } + else + { + controller->SendDirect(colors[0], HYPERX_PULSEFIRE_DART_LED_ALL, modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed); + } +} + +void RGBController_HyperXPulsefireDart::DeviceSaveMode() +{ + controller->Save(); +} diff --git a/Controllers/HyperXMouseController/HyperXPulsefireDartController/RGBController_HyperXPulsefireDart.h b/Controllers/HyperXMouseController/HyperXPulsefireDartController/RGBController_HyperXPulsefireDart.h new file mode 100644 index 00000000..0d6be3b8 --- /dev/null +++ b/Controllers/HyperXMouseController/HyperXPulsefireDartController/RGBController_HyperXPulsefireDart.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------*\ +| RGBController_HyperXPulsefireDart.h | +| | +| RGBController for HyperX Pulsefire Dart | +| | +| Santeri Pikarinen (santeri3700) 26 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "HyperXPulsefireDartController.h" + +class RGBController_HyperXPulsefireDart : public RGBController +{ +public: + RGBController_HyperXPulsefireDart(HyperXPulsefireDartController* controller_ptr); + ~RGBController_HyperXPulsefireDart(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + HyperXPulsefireDartController* controller; +}; diff --git a/Controllers/HyperXMouseController/HyperXPulsefireFPSProController.cpp b/Controllers/HyperXMouseController/HyperXPulsefireFPSProController.cpp deleted file mode 100644 index 6d53ac37..00000000 --- a/Controllers/HyperXMouseController/HyperXPulsefireFPSProController.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/*-----------------------------------------*\ -| HyperXPulsefireFPSProController.cpp | -| | -| Driver for HyperX Pulsefire FPS Pro | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 12/26/2020 | -\*-----------------------------------------*/ - -#include "HyperXPulsefireFPSProController.h" - -#include - -HyperXPulsefireFPSProController::HyperXPulsefireFPSProController(hid_device* dev_handle, const char* path) -{ - dev = dev_handle; - location = path; -} - -HyperXPulsefireFPSProController::~HyperXPulsefireFPSProController() -{ - hid_close(dev); -} - -std::string HyperXPulsefireFPSProController::GetDeviceLocation() -{ - return("HID " + location); -} - -std::string HyperXPulsefireFPSProController::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); -} - -/*-------------------------------------------------------------------------------------------------*\ -| Private packet sending functions. | -\*-------------------------------------------------------------------------------------------------*/ - -void HyperXPulsefireFPSProController::SendDirect - ( - RGBColor* color_data - ) -{ - unsigned char buf[264]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(buf, 0x00, sizeof(buf)); - - /*-----------------------------------------------------*\ - | Set up Direct Mode packet | - \*-----------------------------------------------------*/ - buf[0x00] = 0x07; - buf[0x01] = HYPERX_PULSEFIRE_FPS_PRO_PACKET_ID_DIRECT; - - buf[0x02] = RGBGetRValue(color_data[0]); - buf[0x03] = RGBGetGValue(color_data[0]); - buf[0x04] = RGBGetBValue(color_data[0]); - - buf[0x08] = 0xA0; - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_send_feature_report(dev, buf, 264); -} diff --git a/Controllers/HyperXMouseController/HyperXPulsefireFPSProController.h b/Controllers/HyperXMouseController/HyperXPulsefireFPSProController.h deleted file mode 100644 index 5b7ee6ca..00000000 --- a/Controllers/HyperXMouseController/HyperXPulsefireFPSProController.h +++ /dev/null @@ -1,39 +0,0 @@ -/*-----------------------------------------*\ -| HyperXPulsefireFPSProController.h | -| | -| Definitions and types for HyperX | -| Pulsefire FPS Pro lighting controller | -| | -| Adam Honse (CalcProgrammer1) 12/26/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include - -#pragma once - -enum -{ - HYPERX_PULSEFIRE_FPS_PRO_PACKET_ID_DIRECT = 0x0A, /* Direct control packet */ -}; - -class HyperXPulsefireFPSProController -{ -public: - HyperXPulsefireFPSProController(hid_device* dev_handle, const char* path); - ~HyperXPulsefireFPSProController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - - void SendDirect - ( - RGBColor* color_data - ); - -private: - hid_device* dev; - std::string location; -}; diff --git a/Controllers/HyperXMouseController/HyperXPulsefireFPSProController/HyperXPulsefireFPSProController.cpp b/Controllers/HyperXMouseController/HyperXPulsefireFPSProController/HyperXPulsefireFPSProController.cpp new file mode 100644 index 00000000..4e711c2d --- /dev/null +++ b/Controllers/HyperXMouseController/HyperXPulsefireFPSProController/HyperXPulsefireFPSProController.cpp @@ -0,0 +1,83 @@ +/*---------------------------------------------------------*\ +| HyperXPulsefireFPSProController.cpp | +| | +| Driver for HyperX Pulsefire FPS Pro | +| | +| Adam Honse (CalcProgrammer1) 26 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "HyperXPulsefireFPSProController.h" +#include "StringUtils.h" + +HyperXPulsefireFPSProController::HyperXPulsefireFPSProController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; +} + +HyperXPulsefireFPSProController::~HyperXPulsefireFPSProController() +{ + hid_close(dev); +} + +std::string HyperXPulsefireFPSProController::GetDeviceLocation() +{ + return("HID " + location); +} + +std::string HyperXPulsefireFPSProController::GetNameString() +{ + return(name); +} + +std::string HyperXPulsefireFPSProController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +/*-------------------------------------------------------------------------------------------------*\ +| Private packet sending functions. | +\*-------------------------------------------------------------------------------------------------*/ + +void HyperXPulsefireFPSProController::SendDirect + ( + RGBColor* color_data + ) +{ + unsigned char buf[264]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(buf, 0x00, sizeof(buf)); + + /*-----------------------------------------------------*\ + | Set up Direct Mode packet | + \*-----------------------------------------------------*/ + buf[0x00] = 0x07; + buf[0x01] = HYPERX_PULSEFIRE_FPS_PRO_PACKET_ID_DIRECT; + + buf[0x02] = RGBGetRValue(color_data[0]); + buf[0x03] = RGBGetGValue(color_data[0]); + buf[0x04] = RGBGetBValue(color_data[0]); + + buf[0x08] = 0xA0; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_send_feature_report(dev, buf, 264); +} diff --git a/Controllers/HyperXMouseController/HyperXPulsefireFPSProController/HyperXPulsefireFPSProController.h b/Controllers/HyperXMouseController/HyperXPulsefireFPSProController/HyperXPulsefireFPSProController.h new file mode 100644 index 00000000..0050be03 --- /dev/null +++ b/Controllers/HyperXMouseController/HyperXPulsefireFPSProController/HyperXPulsefireFPSProController.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------*\ +| HyperXPulsefireFPSProController.h | +| | +| Driver for HyperX Pulsefire FPS Pro | +| | +| Adam Honse (CalcProgrammer1) 26 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +enum +{ + HYPERX_PULSEFIRE_FPS_PRO_PACKET_ID_DIRECT = 0x0A, /* Direct control packet */ +}; + +class HyperXPulsefireFPSProController +{ +public: + HyperXPulsefireFPSProController(hid_device* dev_handle, const char* path, std::string dev_name); + ~HyperXPulsefireFPSProController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SendDirect + ( + RGBColor* color_data + ); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/HyperXMouseController/HyperXPulsefireFPSProController/RGBController_HyperXPulsefireFPSPro.cpp b/Controllers/HyperXMouseController/HyperXPulsefireFPSProController/RGBController_HyperXPulsefireFPSPro.cpp new file mode 100644 index 00000000..7973222a --- /dev/null +++ b/Controllers/HyperXMouseController/HyperXPulsefireFPSProController/RGBController_HyperXPulsefireFPSPro.cpp @@ -0,0 +1,147 @@ +/*---------------------------------------------------------*\ +| RGBController_HyperXPulsefireFPSPro.cpp | +| | +| RGBController for HyperX Pulsefire FPS Pro | +| | +| Adam Honse (CalcProgrammer1) 26 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_HyperXPulsefireFPSPro.h" + +using namespace std::chrono_literals; + +/**------------------------------------------------------------------*\ + @name HyperX Pulsefire FPS + @category Mouse + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectHyperXPulsefireFPSProControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_HyperXPulsefireFPSPro::RGBController_HyperXPulsefireFPSPro(HyperXPulsefireFPSProController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "HyperX"; + type = DEVICE_TYPE_MOUSE; + description = "HyperX Pulsefire FPS Pro Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + SetupZones(); + + /*-----------------------------------------------------*\ + | The Corsair Lighting Node Pro requires a packet within| + | 20 seconds of sending the lighting change in order | + | to not revert back into rainbow mode. Start a thread | + | to continuously send a keepalive packet every 5s | + \*-----------------------------------------------------*/ + keepalive_thread_run = 1; + keepalive_thread = new std::thread(&RGBController_HyperXPulsefireFPSPro::KeepaliveThread, this); +}; + +RGBController_HyperXPulsefireFPSPro::~RGBController_HyperXPulsefireFPSPro() +{ + keepalive_thread_run = 0; + keepalive_thread->join(); + delete keepalive_thread; + + delete controller; +} + +void RGBController_HyperXPulsefireFPSPro::SetupZones() +{ + zone logo; + logo.name = "Logo"; + logo.type = ZONE_TYPE_SINGLE; + logo.leds_min = 1; + logo.leds_max = 1; + logo.leds_count = 1; + logo.matrix_map = NULL; + zones.push_back(logo); + + 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; + + if(zones[zone_idx].leds_count > 1) + { + new_led.name.append(" LED "); + new_led.name.append(std::to_string(led_idx + 1)); + } + + leds.push_back(new_led); + } + } + + SetupColors(); +} + +void RGBController_HyperXPulsefireFPSPro::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_HyperXPulsefireFPSPro::DeviceUpdateLEDs() +{ + last_update_time = std::chrono::steady_clock::now(); + + if(active_mode == 0) + { + controller->SendDirect(&colors[0]); + } + else + { + } + +} + +void RGBController_HyperXPulsefireFPSPro::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_HyperXPulsefireFPSPro::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_HyperXPulsefireFPSPro::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} + +void RGBController_HyperXPulsefireFPSPro::KeepaliveThread() +{ + while(keepalive_thread_run.load()) + { + if(active_mode == 0) + { + if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50)) + { + UpdateLEDs(); + } + } + std::this_thread::sleep_for(10ms); + } +} diff --git a/Controllers/HyperXMouseController/HyperXPulsefireFPSProController/RGBController_HyperXPulsefireFPSPro.h b/Controllers/HyperXMouseController/HyperXPulsefireFPSProController/RGBController_HyperXPulsefireFPSPro.h new file mode 100644 index 00000000..dec5a625 --- /dev/null +++ b/Controllers/HyperXMouseController/HyperXPulsefireFPSProController/RGBController_HyperXPulsefireFPSPro.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------*\ +| RGBController_HyperXPulsefireFPSPro.h | +| | +| RGBController for HyperX Pulsefire FPS Pro | +| | +| Adam Honse (CalcProgrammer1) 26 Dec 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "HyperXPulsefireFPSProController.h" + +class RGBController_HyperXPulsefireFPSPro : public RGBController +{ +public: + RGBController_HyperXPulsefireFPSPro(HyperXPulsefireFPSProController* controller_ptr); + ~RGBController_HyperXPulsefireFPSPro(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + void KeepaliveThread(); + +private: + HyperXPulsefireFPSProController* controller; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::chrono::time_point last_update_time; +}; diff --git a/Controllers/HyperXMouseController/HyperXPulsefireHasteController.h b/Controllers/HyperXMouseController/HyperXPulsefireHasteController.h deleted file mode 100644 index 5c6992af..00000000 --- a/Controllers/HyperXMouseController/HyperXPulsefireHasteController.h +++ /dev/null @@ -1,46 +0,0 @@ -/*-----------------------------------------*\ -| HyperXPulsefireHasteController.h | -| | -| Definitions and types for HyperX | -| Pulsefire FPS Pro lighting controller | -| | -| Adam Honse (CalcProgrammer1) 8/19/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include - -#pragma once - -enum -{ - HYPERX_PULSEFIRE_HASTE_PACKET_ID_SETUP = 0x04, /* Direct setup packet */ - HYPERX_PULSEFIRE_HASTE_PACKET_ID_COLOR = 0x81, /* Direct color packet */ -}; - -class HyperXPulsefireHasteController -{ -public: - HyperXPulsefireHasteController(hid_device* dev_handle, const char* path); - ~HyperXPulsefireHasteController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - - void SendDirect - ( - RGBColor* color_data - ); - -private: - hid_device* dev; - std::string location; - - void SendDirectSetup(); - void SendDirectColor - ( - RGBColor* color_data - ); -}; diff --git a/Controllers/HyperXMouseController/HyperXPulsefireHasteController.cpp b/Controllers/HyperXMouseController/HyperXPulsefireHasteController/HyperXPulsefireHasteController.cpp similarity index 76% rename from Controllers/HyperXMouseController/HyperXPulsefireHasteController.cpp rename to Controllers/HyperXMouseController/HyperXPulsefireHasteController/HyperXPulsefireHasteController.cpp index 1539f968..ddcd4337 100644 --- a/Controllers/HyperXMouseController/HyperXPulsefireHasteController.cpp +++ b/Controllers/HyperXMouseController/HyperXPulsefireHasteController/HyperXPulsefireHasteController.cpp @@ -1,20 +1,23 @@ -/*-----------------------------------------*\ -| HyperXPulsefireHasteController.cpp | -| | -| Driver for HyperX Pulsefire Haste | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 8/19/2021 | -\*-----------------------------------------*/ - -#include "HyperXPulsefireHasteController.h" +/*---------------------------------------------------------*\ +| HyperXPulsefireHasteController.cpp | +| | +| Driver for HyperX Pulsefire Haste | +| | +| Adam Honse (CalcProgrammer1) 19 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "HyperXPulsefireHasteController.h" +#include "StringUtils.h" -HyperXPulsefireHasteController::HyperXPulsefireHasteController(hid_device* dev_handle, const char* path) +HyperXPulsefireHasteController::HyperXPulsefireHasteController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } HyperXPulsefireHasteController::~HyperXPulsefireHasteController() @@ -27,6 +30,11 @@ std::string HyperXPulsefireHasteController::GetDeviceLocation() return("HID " + location); } +std::string HyperXPulsefireHasteController::GetNameString() +{ + return(name); +} + std::string HyperXPulsefireHasteController::GetSerialString() { wchar_t serial_string[128]; @@ -37,10 +45,7 @@ std::string HyperXPulsefireHasteController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void HyperXPulsefireHasteController::SendDirect @@ -97,13 +102,13 @@ void HyperXPulsefireHasteController::SendDirectColor \*-----------------------------------------------------*/ buf[0x00] = 0x00; buf[0x01] = HYPERX_PULSEFIRE_HASTE_PACKET_ID_COLOR; - + buf[0x02] = RGBGetRValue(color_data[0]); buf[0x03] = RGBGetGValue(color_data[0]); buf[0x04] = RGBGetBValue(color_data[0]); buf[0x08] = 0x02; - + /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ diff --git a/Controllers/HyperXMouseController/HyperXPulsefireHasteController/HyperXPulsefireHasteController.h b/Controllers/HyperXMouseController/HyperXPulsefireHasteController/HyperXPulsefireHasteController.h new file mode 100644 index 00000000..0a257761 --- /dev/null +++ b/Controllers/HyperXMouseController/HyperXPulsefireHasteController/HyperXPulsefireHasteController.h @@ -0,0 +1,49 @@ +/*---------------------------------------------------------*\ +| HyperXPulsefireHasteController.h | +| | +| Driver for HyperX Pulsefire Haste | +| | +| Adam Honse (CalcProgrammer1) 19 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +enum +{ + HYPERX_PULSEFIRE_HASTE_PACKET_ID_SETUP = 0x04, /* Direct setup packet */ + HYPERX_PULSEFIRE_HASTE_PACKET_ID_COLOR = 0x81, /* Direct color packet */ +}; + +class HyperXPulsefireHasteController +{ +public: + HyperXPulsefireHasteController(hid_device* dev_handle, const char* path, std::string dev_name); + ~HyperXPulsefireHasteController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SendDirect + ( + RGBColor* color_data + ); + +private: + hid_device* dev; + std::string location; + std::string name; + + void SendDirectSetup(); + void SendDirectColor + ( + RGBColor* color_data + ); +}; diff --git a/Controllers/HyperXMouseController/HyperXPulsefireHasteController/RGBController_HyperXPulsefireHaste.cpp b/Controllers/HyperXMouseController/HyperXPulsefireHasteController/RGBController_HyperXPulsefireHaste.cpp new file mode 100644 index 00000000..ad8d0f24 --- /dev/null +++ b/Controllers/HyperXMouseController/HyperXPulsefireHasteController/RGBController_HyperXPulsefireHaste.cpp @@ -0,0 +1,147 @@ +/*---------------------------------------------------------*\ +| RGBController_HyperXPulsefireHaste.cpp | +| | +| RGBController for HyperX Pulsefire Haste | +| | +| Adam Honse (CalcProgrammer1) 19 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_HyperXPulsefireHaste.h" + +using namespace std::chrono_literals; + +/**------------------------------------------------------------------*\ + @name HyperX Pulsefire Haste + @category Mouse + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectHyperXPulsefireHasteControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_HyperXPulsefireHaste::RGBController_HyperXPulsefireHaste(HyperXPulsefireHasteController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "HyperX"; + type = DEVICE_TYPE_MOUSE; + description = "HyperX Pulsefire Haste Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + SetupZones(); + + /*-----------------------------------------------------*\ + | The Corsair Lighting Node Pro requires a packet within| + | 20 seconds of sending the lighting change in order | + | to not revert back into rainbow mode. Start a thread | + | to continuously send a keepalive packet every 5s | + \*-----------------------------------------------------*/ + keepalive_thread_run = 1; + keepalive_thread = new std::thread(&RGBController_HyperXPulsefireHaste::KeepaliveThread, this); +}; + +RGBController_HyperXPulsefireHaste::~RGBController_HyperXPulsefireHaste() +{ + keepalive_thread_run = 0; + keepalive_thread->join(); + delete keepalive_thread; + + delete controller; +} + +void RGBController_HyperXPulsefireHaste::SetupZones() +{ + zone logo; + logo.name = "Logo"; + logo.type = ZONE_TYPE_SINGLE; + logo.leds_min = 1; + logo.leds_max = 1; + logo.leds_count = 1; + logo.matrix_map = NULL; + zones.push_back(logo); + + 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; + + if(zones[zone_idx].leds_count > 1) + { + new_led.name.append(" LED "); + new_led.name.append(std::to_string(led_idx + 1)); + } + + leds.push_back(new_led); + } + } + + SetupColors(); +} + +void RGBController_HyperXPulsefireHaste::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_HyperXPulsefireHaste::DeviceUpdateLEDs() +{ + last_update_time = std::chrono::steady_clock::now(); + + if(active_mode == 0) + { + controller->SendDirect(&colors[0]); + } + else + { + } + +} + +void RGBController_HyperXPulsefireHaste::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_HyperXPulsefireHaste::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_HyperXPulsefireHaste::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} + +void RGBController_HyperXPulsefireHaste::KeepaliveThread() +{ + while(keepalive_thread_run.load()) + { + if(active_mode == 0) + { + if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50)) + { + UpdateLEDs(); + } + } + std::this_thread::sleep_for(10ms); + } +} diff --git a/Controllers/HyperXMouseController/HyperXPulsefireHasteController/RGBController_HyperXPulsefireHaste.h b/Controllers/HyperXMouseController/HyperXPulsefireHasteController/RGBController_HyperXPulsefireHaste.h new file mode 100644 index 00000000..6941b85a --- /dev/null +++ b/Controllers/HyperXMouseController/HyperXPulsefireHasteController/RGBController_HyperXPulsefireHaste.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------*\ +| RGBController_HyperXPulsefireHaste.h | +| | +| RGBController for HyperX Pulsefire Haste | +| | +| Adam Honse (CalcProgrammer1) 19 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "HyperXPulsefireHasteController.h" + +class RGBController_HyperXPulsefireHaste : public RGBController +{ +public: + RGBController_HyperXPulsefireHaste(HyperXPulsefireHasteController* controller_ptr); + ~RGBController_HyperXPulsefireHaste(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + void KeepaliveThread(); + +private: + HyperXPulsefireHasteController* controller; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::chrono::time_point last_update_time; +}; diff --git a/Controllers/HyperXMouseController/HyperXPulsefireRaidController.cpp b/Controllers/HyperXMouseController/HyperXPulsefireRaidController.cpp deleted file mode 100644 index 693de1af..00000000 --- a/Controllers/HyperXMouseController/HyperXPulsefireRaidController.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/*-------------------------------------------*\ -| HyperXPulsefireRaidController.cpp | -| | -| Driver for HyperX Pulsefire Raid | -| lighting controller | -| | -| Morgan Guimard (morg) 04/06/2022 | -\*-------------------------------------------*/ - -#include "HyperXPulsefireRaidController.h" -#include - -using namespace std::chrono_literals; - -HyperXPulsefireRaidController::HyperXPulsefireRaidController(hid_device* dev_handle, const hid_device_info& info) -{ - dev = dev_handle; - location = info.path; - version = ""; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } - -} - -HyperXPulsefireRaidController::~HyperXPulsefireRaidController() -{ - hid_close(dev); -} - -std::string HyperXPulsefireRaidController::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string HyperXPulsefireRaidController::GetSerialString() -{ - return(serial_number); -} - -std::string HyperXPulsefireRaidController::GetFirmwareVersion() -{ - return(version); -} - -void HyperXPulsefireRaidController::SendColors(std::vector colors) -{ - unsigned char usb_buf[HYPERX_PULSFIRE_RAID_PACKET_DATA_LENGTH]; - memset(usb_buf, 0x00, HYPERX_PULSFIRE_RAID_PACKET_DATA_LENGTH); - - usb_buf[0] = HYPERX_PULSFIRE_RAID_REPORT_ID; - usb_buf[1] = HYPERX_PULSFIRE_RAID_DIRECT_MODE_START_PACKET; - - for(unsigned int i = 0; i < 2; i++) - { - usb_buf[3 * i + 2] = RGBGetRValue(colors[i]); - usb_buf[3 * i + 3] = RGBGetGValue(colors[i]); - usb_buf[3 * i + 4] = RGBGetBValue(colors[i]); - } - - usb_buf[8] = HYPERX_PULSFIRE_RAID_DIRECT_MODE_END_PACKET; - - Send(usb_buf); -} - - -void HyperXPulsefireRaidController::Send(unsigned char* packet) -{ - hid_send_feature_report(dev, packet, HYPERX_PULSFIRE_RAID_PACKET_DATA_LENGTH); - std::this_thread::sleep_for(10ms); -} diff --git a/Controllers/HyperXMouseController/HyperXPulsefireRaidController.h b/Controllers/HyperXMouseController/HyperXPulsefireRaidController.h deleted file mode 100644 index 4717620c..00000000 --- a/Controllers/HyperXMouseController/HyperXPulsefireRaidController.h +++ /dev/null @@ -1,50 +0,0 @@ -/*-------------------------------------------*\ -| HyperXPulsefireRaidController.h | -| | -| Definitions and types for HyperX | -| Pulsefire Raid lighting controller | -| | -| Morgan Guimard (morg) 04/06/2022 | -\*-------------------------------------------*/ - -#include "RGBController.h" - -#include -#include - -#pragma once - -#define HYPERX_PULSFIRE_RAID_PACKET_DATA_LENGTH 264 -#define HYPERX_PULSFIRE_RAID_REPORT_ID 0x07 -#define HYPERX_PULSFIRE_RAID_LEDS_COUNT 2 -#define HYPERX_PULSFIRE_RAID_DIRECT_MODE_START_PACKET 0x0A -#define HYPERX_PULSFIRE_RAID_DIRECT_MODE_END_PACKET 0xA0 - -enum -{ - HYPERX_PULSFIRE_RAID_BRIGHTNESS_MIN = 0x00, - HYPERX_PULSFIRE_RAID_BRIGHTNESS_MAX = 0x64 -}; - -class HyperXPulsefireRaidController -{ -public: - HyperXPulsefireRaidController(hid_device* dev_handle, const hid_device_info& info); - ~HyperXPulsefireRaidController(); - - std::string GetSerialString(); - std::string GetDeviceLocation(); - std::string GetFirmwareVersion(); - void SendColors(std::vector colors); - void SetBrightness(unsigned char brightness); - -protected: - hid_device* dev; - -private: - std::string location; - std::string serial_number; - std::string version; - - void Send(unsigned char* packet); -}; diff --git a/Controllers/HyperXMouseController/HyperXPulsefireRaidController/HyperXPulsefireRaidController.cpp b/Controllers/HyperXMouseController/HyperXPulsefireRaidController/HyperXPulsefireRaidController.cpp new file mode 100644 index 00000000..acf670e9 --- /dev/null +++ b/Controllers/HyperXMouseController/HyperXPulsefireRaidController/HyperXPulsefireRaidController.cpp @@ -0,0 +1,78 @@ +/*---------------------------------------------------------*\ +| HyperXPulsefireRaidController.cpp | +| | +| Driver for HyperX Pulsefire Raid | +| | +| Morgan Guimard (morg) 06 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "HyperXPulsefireRaidController.h" +#include "StringUtils.h" + +using namespace std::chrono_literals; + +HyperXPulsefireRaidController::HyperXPulsefireRaidController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) +{ + dev = dev_handle; + location = info.path; + name = dev_name; +} + +HyperXPulsefireRaidController::~HyperXPulsefireRaidController() +{ + hid_close(dev); +} + +std::string HyperXPulsefireRaidController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string HyperXPulsefireRaidController::GetNameString() +{ + return(name); +} + +std::string HyperXPulsefireRaidController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void HyperXPulsefireRaidController::SendColors(std::vector colors) +{ + unsigned char usb_buf[HYPERX_PULSFIRE_RAID_PACKET_DATA_LENGTH]; + memset(usb_buf, 0x00, HYPERX_PULSFIRE_RAID_PACKET_DATA_LENGTH); + + usb_buf[0] = HYPERX_PULSFIRE_RAID_REPORT_ID; + usb_buf[1] = HYPERX_PULSFIRE_RAID_DIRECT_MODE_START_PACKET; + + for(unsigned int i = 0; i < 2; i++) + { + usb_buf[3 * i + 2] = RGBGetRValue(colors[i]); + usb_buf[3 * i + 3] = RGBGetGValue(colors[i]); + usb_buf[3 * i + 4] = RGBGetBValue(colors[i]); + } + + usb_buf[8] = HYPERX_PULSFIRE_RAID_DIRECT_MODE_END_PACKET; + + Send(usb_buf); +} + + +void HyperXPulsefireRaidController::Send(unsigned char* packet) +{ + hid_send_feature_report(dev, packet, HYPERX_PULSFIRE_RAID_PACKET_DATA_LENGTH); + std::this_thread::sleep_for(10ms); +} diff --git a/Controllers/HyperXMouseController/HyperXPulsefireRaidController/HyperXPulsefireRaidController.h b/Controllers/HyperXMouseController/HyperXPulsefireRaidController/HyperXPulsefireRaidController.h new file mode 100644 index 00000000..885aec77 --- /dev/null +++ b/Controllers/HyperXMouseController/HyperXPulsefireRaidController/HyperXPulsefireRaidController.h @@ -0,0 +1,51 @@ +/*---------------------------------------------------------*\ +| HyperXPulsefireRaidController.h | +| | +| Driver for HyperX Pulsefire Raid | +| | +| Morgan Guimard (morg) 06 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define HYPERX_PULSFIRE_RAID_PACKET_DATA_LENGTH 264 +#define HYPERX_PULSFIRE_RAID_REPORT_ID 0x07 +#define HYPERX_PULSFIRE_RAID_LEDS_COUNT 2 +#define HYPERX_PULSFIRE_RAID_DIRECT_MODE_START_PACKET 0x0A +#define HYPERX_PULSFIRE_RAID_DIRECT_MODE_END_PACKET 0xA0 + +enum +{ + HYPERX_PULSFIRE_RAID_BRIGHTNESS_MIN = 0x00, + HYPERX_PULSFIRE_RAID_BRIGHTNESS_MAX = 0x64 +}; + +class HyperXPulsefireRaidController +{ +public: + HyperXPulsefireRaidController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~HyperXPulsefireRaidController(); + + std::string GetNameString(); + std::string GetSerialString(); + std::string GetDeviceLocation(); + + void SendColors(std::vector colors); + void SetBrightness(unsigned char brightness); + +protected: + hid_device* dev; + +private: + std::string location; + std::string name; + + void Send(unsigned char* packet); +}; diff --git a/Controllers/HyperXMouseController/HyperXPulsefireRaidController/RGBController_HyperXPulsefireRaid.cpp b/Controllers/HyperXMouseController/HyperXPulsefireRaidController/RGBController_HyperXPulsefireRaid.cpp new file mode 100644 index 00000000..49b570b0 --- /dev/null +++ b/Controllers/HyperXMouseController/HyperXPulsefireRaidController/RGBController_HyperXPulsefireRaid.cpp @@ -0,0 +1,135 @@ +/*---------------------------------------------------------*\ +| RGBController_HyperXPulsefireRaid.cpp | +| | +| RGBController for HyperX Pulsefire Raid | +| | +| Morgan Guimard (morg) 06 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_HyperXPulsefireRaid.h" + +/**------------------------------------------------------------------*\ + @name HyperX Pulsefire Raid + @category Mouse + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectHyperXPulsefireRaidControllers + @comment +\*-------------------------------------------------------------------*/ + +using namespace std::chrono_literals; + +RGBController_HyperXPulsefireRaid::RGBController_HyperXPulsefireRaid(HyperXPulsefireRaidController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "HyperX"; + type = DEVICE_TYPE_MOUSE; + description = "HyperX Pulsefire Raid Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0x00; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness = HYPERX_PULSFIRE_RAID_BRIGHTNESS_MAX; + Direct.brightness_min = HYPERX_PULSFIRE_RAID_BRIGHTNESS_MIN; + Direct.brightness_max = HYPERX_PULSFIRE_RAID_BRIGHTNESS_MAX; + + modes.push_back(Direct); + + SetupZones(); + + /*-----------------------------------------------------*\ + | This devices requires a keepalive thread or it will | + | reset to default (flash) | + \*-----------------------------------------------------*/ + keepalive_thread_run = 1; + keepalive_thread = new std::thread(&RGBController_HyperXPulsefireRaid::KeepaliveThread, this); +} + +RGBController_HyperXPulsefireRaid::~RGBController_HyperXPulsefireRaid() +{ + +} + +void RGBController_HyperXPulsefireRaid::SetupZones() +{ + std::string led_names[HYPERX_PULSFIRE_RAID_LEDS_COUNT] = + { + "Scroll Wheel", "Logo" + }; + + for(unsigned int i = 0; i < HYPERX_PULSFIRE_RAID_LEDS_COUNT; i++) + { + zone new_zone; + new_zone.name = led_names[i]; + new_zone.type = ZONE_TYPE_SINGLE; + new_zone.leds_min = 1; + new_zone.leds_max = 1; + new_zone.leds_count = 1; + new_zone.matrix_map = NULL; + zones.push_back(new_zone); + + led new_led; + new_led.name = led_names[i]; + leds.push_back(new_led); + } + + SetupColors(); +} + +void RGBController_HyperXPulsefireRaid::ResizeZone(int /*zone*/, int /*new_size*/) +{ + +} + +void RGBController_HyperXPulsefireRaid::DeviceUpdateLEDs() +{ + UpdateSingleLED(0); +} + +void RGBController_HyperXPulsefireRaid::UpdateZoneLEDs(int zone) +{ + UpdateSingleLED(zone); +} + +void RGBController_HyperXPulsefireRaid::UpdateSingleLED(int /*led*/) +{ + last_update_time = std::chrono::steady_clock::now(); + controller->SendColors(colors); +} + +void RGBController_HyperXPulsefireRaid::DeviceUpdateMode() +{ + +} + +void RGBController_HyperXPulsefireRaid::DeviceSaveMode() +{ + +} + +void RGBController_HyperXPulsefireRaid::KeepaliveThread() +{ + while(keepalive_thread_run.load()) + { + if(active_mode == 0) + { + if((std::chrono::steady_clock::now() - last_update_time) > 1s) + { + UpdateLEDs(); + } + } + + std::this_thread::sleep_for(10ms); + } +} diff --git a/Controllers/HyperXMouseController/HyperXPulsefireRaidController/RGBController_HyperXPulsefireRaid.h b/Controllers/HyperXMouseController/HyperXPulsefireRaidController/RGBController_HyperXPulsefireRaid.h new file mode 100644 index 00000000..a1667cfa --- /dev/null +++ b/Controllers/HyperXMouseController/HyperXPulsefireRaidController/RGBController_HyperXPulsefireRaid.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------*\ +| RGBController_HyperXPulsefireRaid.h | +| | +| RGBController for HyperX Pulsefire Raid | +| | +| Morgan Guimard (morg) 06 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "HyperXPulsefireRaidController.h" + +class RGBController_HyperXPulsefireRaid : public RGBController +{ +public: + RGBController_HyperXPulsefireRaid(HyperXPulsefireRaidController* controller_ptr); + ~RGBController_HyperXPulsefireRaid(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + HyperXPulsefireRaidController* controller; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::chrono::time_point last_update_time; + void KeepaliveThread(); +}; diff --git a/Controllers/HyperXMouseController/HyperXPulsefireSurgeController.h b/Controllers/HyperXMouseController/HyperXPulsefireSurgeController.h deleted file mode 100644 index d2fcb405..00000000 --- a/Controllers/HyperXMouseController/HyperXPulsefireSurgeController.h +++ /dev/null @@ -1,62 +0,0 @@ -/*-----------------------------------------*\ -| HyperXPulsefireSurgeController.h | -| | -| Definitions and types for HyperX | -| Pulsefire Surge lighting controller | -| | -| Adam Honse (CalcProgrammer1) 7/25/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include - -#pragma once - -enum -{ - HYPERX_PULSEFIRE_SURGE_PACKET_ID_SET_CONFIGURATION = 0x01, /* Set profile configuration packet */ - HYPERX_PULSEFIRE_SURGE_PACKET_ID_SET_BRIGHTNESS = 0x03, /* Set profile settings and brightness */ - HYPERX_PULSEFIRE_SURGE_PACKET_ID_SELECT_PROFILE = 0x07, /* Select profile */ - HYPERX_PULSEFIRE_SURGE_PACKET_ID_DIRECT = 0x14, /* Direct control packet */ -}; - -enum -{ - HYPERX_PULSEFIRE_SURGE_MODE_SOLID = 0x00, /* Solid color mode */ - HYPERX_PULSEFIRE_SURGE_MODE_CYCLE = 0x01, /* Spectrum cycle mode */ - HYPERX_PULSEFIRE_SURGE_MODE_BREATHING = 0x02, /* Breathing mode */ - HYPERX_PULSEFIRE_SURGE_MODE_WAVE = 0x03, /* Wave mode */ - HYPERX_PULSEFIRE_SURGE_MODE_TRIGGER = 0x04, /* Trigger mode */ -}; - -class HyperXPulsefireSurgeController -{ -public: - HyperXPulsefireSurgeController(hid_device* dev_handle, const char* path); - ~HyperXPulsefireSurgeController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - - void SelectProfile - ( - unsigned char profile - ); - - void SetProfileBrightness - ( - unsigned char profile, - unsigned char brightness - ); - - void SendDirect - ( - RGBColor* color_data - ); - -private: - hid_device* dev; - std::string location; -}; diff --git a/Controllers/HyperXMouseController/HyperXPulsefireSurgeController.cpp b/Controllers/HyperXMouseController/HyperXPulsefireSurgeController/HyperXPulsefireSurgeController.cpp similarity index 82% rename from Controllers/HyperXMouseController/HyperXPulsefireSurgeController.cpp rename to Controllers/HyperXMouseController/HyperXPulsefireSurgeController/HyperXPulsefireSurgeController.cpp index 9a1b4925..e00756e9 100644 --- a/Controllers/HyperXMouseController/HyperXPulsefireSurgeController.cpp +++ b/Controllers/HyperXMouseController/HyperXPulsefireSurgeController/HyperXPulsefireSurgeController.cpp @@ -1,20 +1,23 @@ -/*-----------------------------------------*\ -| HyperXPulsefireSurgeController.cpp | -| | -| Driver for HyperX Pulsefire Surge | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 7/25/2020 | -\*-----------------------------------------*/ - -#include "HyperXPulsefireSurgeController.h" +/*---------------------------------------------------------*\ +| HyperXPulsefireSurgeController.cpp | +| | +| Driver for HyperX Pulsefire Surge | +| | +| Adam Honse (CalcProgrammer1) 25 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "HyperXPulsefireSurgeController.h" +#include "StringUtils.h" -HyperXPulsefireSurgeController::HyperXPulsefireSurgeController(hid_device* dev_handle, const char* path) +HyperXPulsefireSurgeController::HyperXPulsefireSurgeController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } HyperXPulsefireSurgeController::~HyperXPulsefireSurgeController() @@ -27,6 +30,11 @@ std::string HyperXPulsefireSurgeController::GetDeviceLocation() return("HID " + location); } +std::string HyperXPulsefireSurgeController::GetNameString() +{ + return(name); +} + std::string HyperXPulsefireSurgeController::GetSerialString() { wchar_t serial_string[128]; @@ -37,10 +45,7 @@ std::string HyperXPulsefireSurgeController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } /*-------------------------------------------------------------------------------------------------*\ diff --git a/Controllers/HyperXMouseController/HyperXPulsefireSurgeController/HyperXPulsefireSurgeController.h b/Controllers/HyperXMouseController/HyperXPulsefireSurgeController/HyperXPulsefireSurgeController.h new file mode 100644 index 00000000..6baa8e72 --- /dev/null +++ b/Controllers/HyperXMouseController/HyperXPulsefireSurgeController/HyperXPulsefireSurgeController.h @@ -0,0 +1,65 @@ +/*---------------------------------------------------------*\ +| HyperXPulsefireSurgeController.h | +| | +| Driver for HyperX Pulsefire Surge | +| | +| Adam Honse (CalcProgrammer1) 25 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +enum +{ + HYPERX_PULSEFIRE_SURGE_PACKET_ID_SET_CONFIGURATION = 0x01, /* Set profile configuration packet */ + HYPERX_PULSEFIRE_SURGE_PACKET_ID_SET_BRIGHTNESS = 0x03, /* Set profile settings and brightness */ + HYPERX_PULSEFIRE_SURGE_PACKET_ID_SELECT_PROFILE = 0x07, /* Select profile */ + HYPERX_PULSEFIRE_SURGE_PACKET_ID_DIRECT = 0x14, /* Direct control packet */ +}; + +enum +{ + HYPERX_PULSEFIRE_SURGE_MODE_SOLID = 0x00, /* Solid color mode */ + HYPERX_PULSEFIRE_SURGE_MODE_CYCLE = 0x01, /* Spectrum cycle mode */ + HYPERX_PULSEFIRE_SURGE_MODE_BREATHING = 0x02, /* Breathing mode */ + HYPERX_PULSEFIRE_SURGE_MODE_WAVE = 0x03, /* Wave mode */ + HYPERX_PULSEFIRE_SURGE_MODE_TRIGGER = 0x04, /* Trigger mode */ +}; + +class HyperXPulsefireSurgeController +{ +public: + HyperXPulsefireSurgeController(hid_device* dev_handle, const char* path, std::string dev_name); + ~HyperXPulsefireSurgeController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SelectProfile + ( + unsigned char profile + ); + + void SetProfileBrightness + ( + unsigned char profile, + unsigned char brightness + ); + + void SendDirect + ( + RGBColor* color_data + ); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireSurge.cpp b/Controllers/HyperXMouseController/HyperXPulsefireSurgeController/RGBController_HyperXPulsefireSurge.cpp similarity index 75% rename from Controllers/HyperXMouseController/RGBController_HyperXPulsefireSurge.cpp rename to Controllers/HyperXMouseController/HyperXPulsefireSurgeController/RGBController_HyperXPulsefireSurge.cpp index c6c3a7ac..bc841d7e 100644 --- a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireSurge.cpp +++ b/Controllers/HyperXMouseController/HyperXPulsefireSurgeController/RGBController_HyperXPulsefireSurge.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_HyperXPulsefireSurge.cpp | -| | -| Generic RGB Interface for HyperX | -| Pulsefire Surge | -| | -| Adam Honse (CalcProgrammer1) 2/2/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_HyperXPulsefireSurge.cpp | +| | +| RGBController for HyperX Pulsefire Surge | +| | +| Adam Honse (CalcProgrammer1) 25 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_HyperXPulsefireSurge.h" @@ -24,20 +26,20 @@ using namespace std::chrono_literals; RGBController_HyperXPulsefireSurge::RGBController_HyperXPulsefireSurge(HyperXPulsefireSurgeController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "HyperX Pulsefire Surge Device"; - vendor = "HyperX"; - type = DEVICE_TYPE_MOUSE; - description = "HyperX Pulsefire Surge Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "HyperX"; + type = DEVICE_TYPE_MOUSE; + description = "HyperX Pulsefire Surge Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0xFFFF; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); SetupZones(); diff --git a/Controllers/HyperXMouseController/HyperXPulsefireSurgeController/RGBController_HyperXPulsefireSurge.h b/Controllers/HyperXMouseController/HyperXPulsefireSurgeController/RGBController_HyperXPulsefireSurge.h new file mode 100644 index 00000000..0df965b2 --- /dev/null +++ b/Controllers/HyperXMouseController/HyperXPulsefireSurgeController/RGBController_HyperXPulsefireSurge.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------*\ +| RGBController_HyperXPulsefireSurge.h | +| | +| RGBController for HyperX Pulsefire Surge | +| | +| Adam Honse (CalcProgrammer1) 25 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "HyperXPulsefireSurgeController.h" + +class RGBController_HyperXPulsefireSurge : public RGBController +{ +public: + RGBController_HyperXPulsefireSurge(HyperXPulsefireSurgeController* controller_ptr); + ~RGBController_HyperXPulsefireSurge(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + void KeepaliveThread(); + +private: + HyperXPulsefireSurgeController* controller; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::chrono::time_point last_update_time; +}; diff --git a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireDart.cpp b/Controllers/HyperXMouseController/RGBController_HyperXPulsefireDart.cpp deleted file mode 100644 index 938aca5c..00000000 --- a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireDart.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/*-------------------------------------------*\ -| RGBController_HyperXPulsefireDart.cpp | -| | -| Generic RGB Interface for HyperX | -| Pulsefire Dart | -| | -| Santeri Pikarinen (santeri3700) 12/26/2020 | -\*-------------------------------------------*/ - -#include "RGBController_HyperXPulsefireDart.h" - -/**------------------------------------------------------------------*\ - @name HyperX Pulsefire Dart - @category Mouse - @type USB - @save :white_check_mark: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectHyperXPulsefireDartControllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_HyperXPulsefireDart::RGBController_HyperXPulsefireDart(HyperXPulsefireDartController* controller_ptr) -{ - controller = controller_ptr; - - name = "HyperX Pulsefire Dart Device"; - vendor = "HyperX"; - type = DEVICE_TYPE_MOUSE; - description = "HyperX Pulsefire Dart Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = HYPERX_PULSEFIRE_DART_MODE_STATIC; - Direct.speed = HYPERX_PULSEFIRE_DART_SPEED_NONE; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Direct.color_mode = MODE_COLORS_PER_LED; - Direct.brightness_min = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MIN; - Direct.brightness_max = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX; - Direct.brightness = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX; - modes.push_back(Direct); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = HYPERX_PULSEFIRE_DART_MODE_BREATHING; - Breathing.speed = HYPERX_PULSEFIRE_DART_SPEED_MED; - Breathing.speed_min = HYPERX_PULSEFIRE_DART_SPEED_MIN; - Breathing.speed_max = HYPERX_PULSEFIRE_DART_SPEED_MAX; - Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Breathing.color_mode = MODE_COLORS_PER_LED; - Breathing.brightness_min = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MIN; - Breathing.brightness_max = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX; - Breathing.brightness = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX; - modes.push_back(Breathing); - - mode SpectrumCycle; - SpectrumCycle.name = "Spectrum Cycle"; - SpectrumCycle.value = HYPERX_PULSEFIRE_DART_MODE_CYCLE; - SpectrumCycle.speed = HYPERX_PULSEFIRE_DART_SPEED_MED; - SpectrumCycle.speed_min = HYPERX_PULSEFIRE_DART_SPEED_MIN; - SpectrumCycle.speed_max = HYPERX_PULSEFIRE_DART_SPEED_MAX; - SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - SpectrumCycle.color_mode = MODE_COLORS_NONE; - SpectrumCycle.brightness_min = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MIN; - SpectrumCycle.brightness_max = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX; - SpectrumCycle.brightness = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX; - modes.push_back(SpectrumCycle); - - mode Reactive; - Reactive.name = "Reactive"; - Reactive.value = HYPERX_PULSEFIRE_DART_MODE_REACTIVE; - Reactive.speed = HYPERX_PULSEFIRE_DART_SPEED_MED; - Reactive.speed_min = HYPERX_PULSEFIRE_DART_SPEED_MIN; - Reactive.speed_max = HYPERX_PULSEFIRE_DART_SPEED_MAX; - Reactive.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Reactive.color_mode = MODE_COLORS_PER_LED; - Reactive.brightness_min = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MIN; - Reactive.brightness_max = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX; - Reactive.brightness = HYPERX_PULSEFIRE_DART_BRIGHTNESS_MAX; - modes.push_back(Reactive); - - SetupZones(); -} - -RGBController_HyperXPulsefireDart::~RGBController_HyperXPulsefireDart() -{ - -} - -void RGBController_HyperXPulsefireDart::SetupZones() -{ - zone scroll_zone; - scroll_zone.name = "Scroll Wheel"; - scroll_zone.type = ZONE_TYPE_SINGLE; - scroll_zone.leds_min = 1; - scroll_zone.leds_max = 1; - scroll_zone.leds_count = 1; - scroll_zone.matrix_map = NULL; - zones.push_back(scroll_zone); - - led scroll_led; - scroll_led.name = "Scroll Wheel"; - scroll_led.value = HYPERX_PULSEFIRE_DART_LED_SCROLL; - leds.push_back(scroll_led); - - zone logo_zone; - logo_zone.name = "Logo"; - logo_zone.type = ZONE_TYPE_SINGLE; - logo_zone.leds_min = 1; - logo_zone.leds_max = 1; - logo_zone.leds_count = 1; - logo_zone.matrix_map = NULL; - zones.push_back(logo_zone); - - led logo_led; - logo_led.name = "Logo"; - logo_led.value = HYPERX_PULSEFIRE_DART_LED_LOGO; - leds.push_back(logo_led); - - SetupColors(); -} - -void RGBController_HyperXPulsefireDart::ResizeZone(int /*zone*/, int /*new_size*/) -{ - -} - -void RGBController_HyperXPulsefireDart::DeviceUpdateLEDs() -{ - DeviceUpdateMode(); -} - -void RGBController_HyperXPulsefireDart::UpdateZoneLEDs(int zone) -{ - UpdateSingleLED(zone); -} - -void RGBController_HyperXPulsefireDart::UpdateSingleLED(int led) -{ - if(modes[active_mode].color_mode == MODE_COLORS_PER_LED) - { - controller->SendDirect(colors[led], leds[led].value, modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed); - } - else - { - controller->SendDirect(colors[led], HYPERX_PULSEFIRE_DART_LED_ALL, modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed); - } -} - -void RGBController_HyperXPulsefireDart::DeviceUpdateMode() -{ - if(modes[active_mode].color_mode == MODE_COLORS_PER_LED) - { - controller->SendDirect(colors[0], HYPERX_PULSEFIRE_DART_LED_SCROLL, modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed); - controller->SendDirect(colors[1], HYPERX_PULSEFIRE_DART_LED_LOGO, modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed); - } - else - { - controller->SendDirect(colors[0], HYPERX_PULSEFIRE_DART_LED_ALL, modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed); - } -} - -void RGBController_HyperXPulsefireDart::DeviceSaveMode() -{ - controller->Save(); -} diff --git a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireDart.h b/Controllers/HyperXMouseController/RGBController_HyperXPulsefireDart.h deleted file mode 100644 index 503f063b..00000000 --- a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireDart.h +++ /dev/null @@ -1,35 +0,0 @@ -/*-------------------------------------------*\ -| RGBController_HyperXPulsefireDart.h | -| | -| Generic RGB Interface for HyperX | -| Pulsefire Dart | -| | -| Santeri Pikarinen (santeri3700) 12/26/2020 | -\*-------------------------------------------*/ - -#pragma once -#include - -#include "RGBController.h" -#include "HyperXPulsefireDartController.h" - -class RGBController_HyperXPulsefireDart : public RGBController -{ -public: - RGBController_HyperXPulsefireDart(HyperXPulsefireDartController* controller_ptr); - ~RGBController_HyperXPulsefireDart(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - HyperXPulsefireDartController* controller; -}; diff --git a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireFPSPro.cpp b/Controllers/HyperXMouseController/RGBController_HyperXPulsefireFPSPro.cpp deleted file mode 100644 index 787f2122..00000000 --- a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireFPSPro.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_HyperXPulsefireFPSPro.cpp | -| | -| Generic RGB Interface for HyperX | -| Pulsefire Surge | -| | -| Adam Honse (CalcProgrammer1) 2/2/2020 | -\*-----------------------------------------*/ - -#include "RGBController_HyperXPulsefireFPSPro.h" - -using namespace std::chrono_literals; - -/**------------------------------------------------------------------*\ - @name HyperX Pulsefire FPS - @category Mouse - @type USB - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectHyperXPulsefireFPSProControllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_HyperXPulsefireFPSPro::RGBController_HyperXPulsefireFPSPro(HyperXPulsefireFPSProController* controller_ptr) -{ - controller = controller_ptr; - - name = "HyperX Pulsefire FPS Pro Device"; - vendor = "HyperX"; - type = DEVICE_TYPE_MOUSE; - description = "HyperX Pulsefire FPS Pro Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = 0xFFFF; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - - SetupZones(); - - /*-----------------------------------------------------*\ - | The Corsair Lighting Node Pro requires a packet within| - | 20 seconds of sending the lighting change in order | - | to not revert back into rainbow mode. Start a thread | - | to continuously send a keepalive packet every 5s | - \*-----------------------------------------------------*/ - keepalive_thread_run = 1; - keepalive_thread = new std::thread(&RGBController_HyperXPulsefireFPSPro::KeepaliveThread, this); -}; - -RGBController_HyperXPulsefireFPSPro::~RGBController_HyperXPulsefireFPSPro() -{ - keepalive_thread_run = 0; - keepalive_thread->join(); - delete keepalive_thread; - - delete controller; -} - -void RGBController_HyperXPulsefireFPSPro::SetupZones() -{ - zone logo; - logo.name = "Logo"; - logo.type = ZONE_TYPE_SINGLE; - logo.leds_min = 1; - logo.leds_max = 1; - logo.leds_count = 1; - logo.matrix_map = NULL; - zones.push_back(logo); - - 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; - - if(zones[zone_idx].leds_count > 1) - { - new_led.name.append(" LED "); - new_led.name.append(std::to_string(led_idx + 1)); - } - - leds.push_back(new_led); - } - } - - SetupColors(); -} - -void RGBController_HyperXPulsefireFPSPro::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_HyperXPulsefireFPSPro::DeviceUpdateLEDs() -{ - last_update_time = std::chrono::steady_clock::now(); - - if(active_mode == 0) - { - controller->SendDirect(&colors[0]); - } - else - { - } - -} - -void RGBController_HyperXPulsefireFPSPro::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_HyperXPulsefireFPSPro::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_HyperXPulsefireFPSPro::DeviceUpdateMode() -{ - DeviceUpdateLEDs(); -} - -void RGBController_HyperXPulsefireFPSPro::KeepaliveThread() -{ - while(keepalive_thread_run.load()) - { - if(active_mode == 0) - { - if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50)) - { - UpdateLEDs(); - } - } - std::this_thread::sleep_for(10ms); - } -} diff --git a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireFPSPro.h b/Controllers/HyperXMouseController/RGBController_HyperXPulsefireFPSPro.h deleted file mode 100644 index 4ef9e6e1..00000000 --- a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireFPSPro.h +++ /dev/null @@ -1,39 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_HyperXPulsefireFPSPro.h | -| | -| Generic RGB Interface for HyperX | -| Pulsefire FPS Pro | -| | -| Adam Honse (CalcProgrammer1) 12/26/2020 | -\*-----------------------------------------*/ - -#pragma once -#include - -#include "RGBController.h" -#include "HyperXPulsefireFPSProController.h" - -class RGBController_HyperXPulsefireFPSPro : public RGBController -{ -public: - RGBController_HyperXPulsefireFPSPro(HyperXPulsefireFPSProController* controller_ptr); - ~RGBController_HyperXPulsefireFPSPro(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - void KeepaliveThread(); - -private: - HyperXPulsefireFPSProController* controller; - std::thread* keepalive_thread; - std::atomic keepalive_thread_run; - std::chrono::time_point last_update_time; -}; diff --git a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireHaste.cpp b/Controllers/HyperXMouseController/RGBController_HyperXPulsefireHaste.cpp deleted file mode 100644 index d77b0e50..00000000 --- a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireHaste.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_HyperXPulsefireHaste.cpp | -| | -| Generic RGB Interface for HyperX | -| Pulsefire Haste | -| | -| Adam Honse (CalcProgrammer1) 8/19/2021 | -\*-----------------------------------------*/ - -#include "RGBController_HyperXPulsefireHaste.h" - -using namespace std::chrono_literals; - -/**------------------------------------------------------------------*\ - @name HyperX Pulsefire Haste - @category Mouse - @type USB - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectHyperXPulsefireHasteControllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_HyperXPulsefireHaste::RGBController_HyperXPulsefireHaste(HyperXPulsefireHasteController* controller_ptr) -{ - controller = controller_ptr; - - name = "HyperX Pulsefire Haste Device"; - vendor = "HyperX"; - type = DEVICE_TYPE_MOUSE; - description = "HyperX Pulsefire Haste Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = 0xFFFF; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - - SetupZones(); - - /*-----------------------------------------------------*\ - | The Corsair Lighting Node Pro requires a packet within| - | 20 seconds of sending the lighting change in order | - | to not revert back into rainbow mode. Start a thread | - | to continuously send a keepalive packet every 5s | - \*-----------------------------------------------------*/ - keepalive_thread_run = 1; - keepalive_thread = new std::thread(&RGBController_HyperXPulsefireHaste::KeepaliveThread, this); -}; - -RGBController_HyperXPulsefireHaste::~RGBController_HyperXPulsefireHaste() -{ - keepalive_thread_run = 0; - keepalive_thread->join(); - delete keepalive_thread; - - delete controller; -} - -void RGBController_HyperXPulsefireHaste::SetupZones() -{ - zone logo; - logo.name = "Logo"; - logo.type = ZONE_TYPE_SINGLE; - logo.leds_min = 1; - logo.leds_max = 1; - logo.leds_count = 1; - logo.matrix_map = NULL; - zones.push_back(logo); - - 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; - - if(zones[zone_idx].leds_count > 1) - { - new_led.name.append(" LED "); - new_led.name.append(std::to_string(led_idx + 1)); - } - - leds.push_back(new_led); - } - } - - SetupColors(); -} - -void RGBController_HyperXPulsefireHaste::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_HyperXPulsefireHaste::DeviceUpdateLEDs() -{ - last_update_time = std::chrono::steady_clock::now(); - - if(active_mode == 0) - { - controller->SendDirect(&colors[0]); - } - else - { - } - -} - -void RGBController_HyperXPulsefireHaste::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_HyperXPulsefireHaste::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_HyperXPulsefireHaste::DeviceUpdateMode() -{ - DeviceUpdateLEDs(); -} - -void RGBController_HyperXPulsefireHaste::KeepaliveThread() -{ - while(keepalive_thread_run.load()) - { - if(active_mode == 0) - { - if((std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(50)) - { - UpdateLEDs(); - } - } - std::this_thread::sleep_for(10ms); - } -} diff --git a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireHaste.h b/Controllers/HyperXMouseController/RGBController_HyperXPulsefireHaste.h deleted file mode 100644 index 84c395d6..00000000 --- a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireHaste.h +++ /dev/null @@ -1,39 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_HyperXPulsefireHaste.h | -| | -| Generic RGB Interface for HyperX | -| Pulsefire Haste | -| | -| Adam Honse (CalcProgrammer1) 8/19/2021 | -\*-----------------------------------------*/ - -#pragma once -#include - -#include "RGBController.h" -#include "HyperXPulsefireHasteController.h" - -class RGBController_HyperXPulsefireHaste : public RGBController -{ -public: - RGBController_HyperXPulsefireHaste(HyperXPulsefireHasteController* controller_ptr); - ~RGBController_HyperXPulsefireHaste(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - void KeepaliveThread(); - -private: - HyperXPulsefireHasteController* controller; - std::thread* keepalive_thread; - std::atomic keepalive_thread_run; - std::chrono::time_point last_update_time; -}; diff --git a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireRaid.cpp b/Controllers/HyperXMouseController/RGBController_HyperXPulsefireRaid.cpp deleted file mode 100644 index 472bdff0..00000000 --- a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireRaid.cpp +++ /dev/null @@ -1,134 +0,0 @@ -/*-------------------------------------------*\ -| RGBController_HyperXPulsefireRaid.cpp | -| | -| Generic RGB Interface for HyperX | -| Pulsefire Raid | -| | -| Morgan Guimard (morg) 04/06/2022 | -\*-------------------------------------------*/ - -#include "RGBController_HyperXPulsefireRaid.h" - -/**------------------------------------------------------------------*\ - @name HyperX Pulsefire Raid - @category Mouse - @type USB - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectHyperXPulsefireRaidControllers - @comment -\*-------------------------------------------------------------------*/ - -using namespace std::chrono_literals; - -RGBController_HyperXPulsefireRaid::RGBController_HyperXPulsefireRaid(HyperXPulsefireRaidController* controller_ptr) -{ - controller = controller_ptr; - - name = "HyperX Pulsefire Raid Device"; - vendor = "HyperX"; - type = DEVICE_TYPE_MOUSE; - description = "HyperX Pulsefire Raid Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = 0x00; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Direct.color_mode = MODE_COLORS_PER_LED; - Direct.brightness = HYPERX_PULSFIRE_RAID_BRIGHTNESS_MAX; - Direct.brightness_min = HYPERX_PULSFIRE_RAID_BRIGHTNESS_MIN; - Direct.brightness_max = HYPERX_PULSFIRE_RAID_BRIGHTNESS_MAX; - - modes.push_back(Direct); - - SetupZones(); - - /*-----------------------------------------------------*\ - | This devices requires a keepalive thread or it will | - | reset to default (flash) | - \*-----------------------------------------------------*/ - keepalive_thread_run = 1; - keepalive_thread = new std::thread(&RGBController_HyperXPulsefireRaid::KeepaliveThread, this); -} - -RGBController_HyperXPulsefireRaid::~RGBController_HyperXPulsefireRaid() -{ - -} - -void RGBController_HyperXPulsefireRaid::SetupZones() -{ - std::string led_names[HYPERX_PULSFIRE_RAID_LEDS_COUNT] = - { - "Scroll Wheel", "Logo" - }; - - for(unsigned int i = 0; i < HYPERX_PULSFIRE_RAID_LEDS_COUNT; i++) - { - zone new_zone; - new_zone.name = led_names[i]; - new_zone.type = ZONE_TYPE_SINGLE; - new_zone.leds_min = 1; - new_zone.leds_max = 1; - new_zone.leds_count = 1; - new_zone.matrix_map = NULL; - zones.push_back(new_zone); - - led new_led; - new_led.name = led_names[i]; - leds.push_back(new_led); - } - - SetupColors(); -} - -void RGBController_HyperXPulsefireRaid::ResizeZone(int /*zone*/, int /*new_size*/) -{ - -} - -void RGBController_HyperXPulsefireRaid::DeviceUpdateLEDs() -{ - UpdateSingleLED(0); -} - -void RGBController_HyperXPulsefireRaid::UpdateZoneLEDs(int zone) -{ - UpdateSingleLED(zone); -} - -void RGBController_HyperXPulsefireRaid::UpdateSingleLED(int /*led*/) -{ - last_update_time = std::chrono::steady_clock::now(); - controller->SendColors(colors); -} - -void RGBController_HyperXPulsefireRaid::DeviceUpdateMode() -{ - -} - -void RGBController_HyperXPulsefireRaid::DeviceSaveMode() -{ - -} - -void RGBController_HyperXPulsefireRaid::KeepaliveThread() -{ - while(keepalive_thread_run.load()) - { - if(active_mode == 0) - { - if((std::chrono::steady_clock::now() - last_update_time) > 1s) - { - UpdateLEDs(); - } - } - - std::this_thread::sleep_for(10ms); - } -} diff --git a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireRaid.h b/Controllers/HyperXMouseController/RGBController_HyperXPulsefireRaid.h deleted file mode 100644 index b14c39bc..00000000 --- a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireRaid.h +++ /dev/null @@ -1,38 +0,0 @@ -/*-------------------------------------------*\ -| RGBController_HyperXPulsefireRaid.h | -| | -| Generic RGB Interface for HyperX | -| Pulsefire Raid | -| | -| Morgan Guimard (morg) 04/06/2022 | -\*-------------------------------------------*/ - -#pragma once -#include - -#include "RGBController.h" -#include "HyperXPulsefireRaidController.h" - -class RGBController_HyperXPulsefireRaid : public RGBController -{ -public: - RGBController_HyperXPulsefireRaid(HyperXPulsefireRaidController* controller_ptr); - ~RGBController_HyperXPulsefireRaid(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - HyperXPulsefireRaidController* controller; - std::thread* keepalive_thread; - std::atomic keepalive_thread_run; - std::chrono::time_point last_update_time; - void KeepaliveThread(); -}; diff --git a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireSurge.h b/Controllers/HyperXMouseController/RGBController_HyperXPulsefireSurge.h deleted file mode 100644 index 3f0e8f3f..00000000 --- a/Controllers/HyperXMouseController/RGBController_HyperXPulsefireSurge.h +++ /dev/null @@ -1,39 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_HyperXPulsefireSurge.h | -| | -| Generic RGB Interface for HyperX | -| Pulsefire Surge | -| | -| Adam Honse (CalcProgrammer1) 7/25/2020 | -\*-----------------------------------------*/ - -#pragma once -#include - -#include "RGBController.h" -#include "HyperXPulsefireSurgeController.h" - -class RGBController_HyperXPulsefireSurge : public RGBController -{ -public: - RGBController_HyperXPulsefireSurge(HyperXPulsefireSurgeController* controller_ptr); - ~RGBController_HyperXPulsefireSurge(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - void KeepaliveThread(); - -private: - HyperXPulsefireSurgeController* controller; - std::thread* keepalive_thread; - std::atomic keepalive_thread_run; - std::chrono::time_point last_update_time; -}; diff --git a/Controllers/HyperXMousematController/HyperXMousematController.cpp b/Controllers/HyperXMousematController/HyperXMousematController.cpp index f1dba85a..5f560b9d 100644 --- a/Controllers/HyperXMousematController/HyperXMousematController.cpp +++ b/Controllers/HyperXMousematController/HyperXMousematController.cpp @@ -1,21 +1,24 @@ -/*-----------------------------------------*\ -| HyperXMousematController.cpp | -| | -| Driver for HyperX Mousemat lighting | -| controller | -| | -| Adam Honse (CalcProgrammer1) 10/25/2020 | -\*-----------------------------------------*/ - -#include "HyperXMousematController.h" +/*---------------------------------------------------------*\ +| HyperXMousematController.cpp | +| | +| Driver for HyperX mousemat | +| | +| Adam Honse (CalcProgrammer1) 25 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "HyperXMousematController.h" +#include "StringUtils.h" -HyperXMousematController::HyperXMousematController(hidapi_wrapper hid_wrapper, hid_device* dev_handle, const char* path) +HyperXMousematController::HyperXMousematController(hidapi_wrapper hid_wrapper, hid_device* dev_handle, const char* path, std::string dev_name) { wrapper = hid_wrapper; dev = dev_handle; location = path; + name = dev_name; } HyperXMousematController::~HyperXMousematController() @@ -28,6 +31,11 @@ std::string HyperXMousematController::GetDeviceLocation() return("HID " + location); } +std::string HyperXMousematController::GetNameString() +{ + return(name); +} + std::string HyperXMousematController::GetSerialString() { wchar_t serial_string[128]; @@ -38,10 +46,7 @@ std::string HyperXMousematController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } /*-------------------------------------------------------------------------------------------------*\ @@ -83,7 +88,7 @@ void HyperXMousematController::SendDirect | Set up Select Profile packet | \*-----------------------------------------------------*/ buf[0x00] = 0x00; - + for(int i = 0; i < 16; i++) { buf[(i * 4) + 1] = 0x81; @@ -106,7 +111,7 @@ void HyperXMousematController::SendDirect | Set up Select Profile packet | \*-----------------------------------------------------*/ buf[0x00] = 0x00; - + for(int i = 0; i < 16; i++) { buf[(i * 4) + 1] = 0x81; diff --git a/Controllers/HyperXMousematController/HyperXMousematController.h b/Controllers/HyperXMousematController/HyperXMousematController.h index df350900..2aff01ca 100644 --- a/Controllers/HyperXMousematController/HyperXMousematController.h +++ b/Controllers/HyperXMousematController/HyperXMousematController.h @@ -1,27 +1,28 @@ -/*-----------------------------------------*\ -| HyperXMousematController.h | -| | -| Definitions and types for HyperX | -| mousemat lighting controller | -| | -| Adam Honse (CalcProgrammer1) 10/25/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include - -#include "hidapi_wrapper.h" +/*---------------------------------------------------------*\ +| HyperXMousematController.h | +| | +| Driver for HyperX mousemat | +| | +| Adam Honse (CalcProgrammer1) 25 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include "RGBController.h" +#include "hidapi_wrapper.h" + class HyperXMousematController { public: - HyperXMousematController(hidapi_wrapper hid_wrapper, hid_device* dev_handle, const char* path); + HyperXMousematController(hidapi_wrapper hid_wrapper, hid_device* dev_handle, const char* path, std::string dev_name); ~HyperXMousematController(); std::string GetDeviceLocation(); + std::string GetNameString(); std::string GetSerialString(); void SendDirect @@ -33,4 +34,5 @@ private: hidapi_wrapper wrapper; hid_device* dev; std::string location; + std::string name; }; diff --git a/Controllers/HyperXMousematController/HyperXMousematControllerDetect.cpp b/Controllers/HyperXMousematController/HyperXMousematControllerDetect.cpp index 505beb6f..5ea4f875 100644 --- a/Controllers/HyperXMousematController/HyperXMousematControllerDetect.cpp +++ b/Controllers/HyperXMousematController/HyperXMousematControllerDetect.cpp @@ -1,9 +1,17 @@ +/*---------------------------------------------------------*\ +| HyperXMousematControllerDetect.cpp | +| | +| Detector for HyperX mousemat | +| | +| Adam Honse (CalcProgrammer1) 25 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "HyperXMousematController.h" -#include "RGBController.h" #include "RGBController_HyperXMousemat.h" -#include - #include "hidapi_wrapper.h" /*-----------------------------------------------------*\ @@ -33,9 +41,8 @@ void DetectHyperXMousematControllers(hidapi_wrapper wrapper, hid_device_info* in int first_zone_leds_count = info->product_id == HYPERX_FURY_A_XL_PID ? 2 : 15; int second_zone_leds_count = info->product_id == HYPERX_FURY_A_XL_PID ? 0 : 5; - HyperXMousematController* controller = new HyperXMousematController(wrapper, dev, info->path); + HyperXMousematController* controller = new HyperXMousematController(wrapper, dev, info->path, name); RGBController_HyperXMousemat* rgb_controller = new RGBController_HyperXMousemat(controller, first_zone_leds_count, second_zone_leds_count); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } diff --git a/Controllers/HyperXMousematController/RGBController_HyperXMousemat.cpp b/Controllers/HyperXMousematController/RGBController_HyperXMousemat.cpp index ff4e0ca5..6b2800c7 100644 --- a/Controllers/HyperXMousematController/RGBController_HyperXMousemat.cpp +++ b/Controllers/HyperXMousematController/RGBController_HyperXMousemat.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_HyperXMousemat.cpp | -| | -| Generic RGB Interface for HyperX | -| mousemat | -| | -| Adam Honse (CalcProgrammer1) 10/25/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_HyperXMousemat.cpp | +| | +| RGBController for HyperX mousemat | +| | +| Adam Honse (CalcProgrammer1) 25 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_HyperXMousemat.h" @@ -22,29 +24,24 @@ using namespace std::chrono_literals; @comment \*-------------------------------------------------------------------*/ -RGBController_HyperXMousemat::RGBController_HyperXMousemat -( - HyperXMousematController* controller_ptr, - unsigned int first_zone_leds_count_arg, - unsigned int second_zone_leds_count_arg -) +RGBController_HyperXMousemat::RGBController_HyperXMousemat(HyperXMousematController* controller_ptr, unsigned int first_zone_leds_count_arg, unsigned int second_zone_leds_count_arg) { controller = controller_ptr; first_zone_leds_count = first_zone_leds_count_arg; second_zone_leds_count = second_zone_leds_count_arg; - name = "HyperX Mousemat Device"; - vendor = "HyperX"; - type = DEVICE_TYPE_MOUSEMAT; - description = "HyperX Mousemat Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "HyperX"; + type = DEVICE_TYPE_MOUSEMAT; + description = "HyperX Mousemat Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0xFFFF; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); SetupZones(); diff --git a/Controllers/HyperXMousematController/RGBController_HyperXMousemat.h b/Controllers/HyperXMousematController/RGBController_HyperXMousemat.h index 3efa17c5..e10af160 100644 --- a/Controllers/HyperXMousematController/RGBController_HyperXMousemat.h +++ b/Controllers/HyperXMousematController/RGBController_HyperXMousemat.h @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_HyperXMousemat.h | -| | -| Generic RGB Interface for HyperX | -| mousemat | -| | -| Adam Honse (CalcProgrammer1) 10/25/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_HyperXMousemat.h | +| | +| RGBController for HyperX mousemat | +| | +| Adam Honse (CalcProgrammer1) 25 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include +#include #include "RGBController.h" #include "HyperXMousematController.h" @@ -22,7 +24,7 @@ public: void SetupZones(); void ResizeZone(int zone, int new_size); - + void DeviceUpdateLEDs(); void UpdateZoneLEDs(int zone); void UpdateSingleLED(int led); @@ -30,7 +32,7 @@ public: void DeviceUpdateMode(); void KeepaliveThread(); - + private: HyperXMousematController* controller; std::thread* keepalive_thread; diff --git a/Controllers/InstantMouseController/InstantMouseController.cpp b/Controllers/InstantMouseController/InstantMouseController.cpp new file mode 100644 index 00000000..fab06b1c --- /dev/null +++ b/Controllers/InstantMouseController/InstantMouseController.cpp @@ -0,0 +1,116 @@ +/*---------------------------------------------------------*\ +| InstantMouseController.cpp | +| | +| Driver for Instant mouse | +| | +| Morgan Guimard (morg) 19 Jan 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "InstantMouseController.h" +#include "StringUtils.h" + +InstantMouseController::InstantMouseController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) +{ + dev = dev_handle; + location = info.path; + pid = info.product_id; + name = dev_name; +} + +InstantMouseController::~InstantMouseController() +{ + hid_close(dev); +} + +std::string InstantMouseController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string InstantMouseController::GetNameString() +{ + return(name); +} + +std::string InstantMouseController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +uint16_t InstantMouseController::GetPID() +{ + return pid; +} + +void InstantMouseController::SendColor(RGBColor color) +{ + /*---------------------------------------------------------*\ + | Packet details | + | 07 14 XG RB 00 00 00 00 | + | where X is the DPI slot | + \*---------------------------------------------------------*/ + + uint8_t red = 0xF - RGBGetRValue(color) / 16; + uint8_t grn = 0xF - RGBGetGValue(color) / 16; + uint8_t blu = 0xF - RGBGetBValue(color) / 16; + + uint8_t pkt[INSTANT_MOUSE_REPORT_SIZE]; + memset(pkt, 0 , INSTANT_MOUSE_REPORT_SIZE); + + pkt[0] = INSTANT_MOUSE_REPORT_ID; + pkt[1] = INSTANT_MOUSE_SET_COLOR; + pkt[3] = (red << 4) | (blu & 0xF); + + for(unsigned int i = 0; i <= 0xA; i+= 2) + { + pkt[2] = (i << 4) | (grn & 0xF); + hid_send_feature_report(dev, pkt, INSTANT_MOUSE_REPORT_SIZE); + } +} + +void InstantMouseController::SetMode(uint8_t mode_value, uint8_t speed, uint8_t brightness, uint8_t direction) +{ + /*---------------------------------------------------------*\ + | Packet details: | + | 07 13 FF MS DN -B M- -- | + | | + | 07 = report id | + | 13 = set mode function | + | FF = constant | + | - = still undiscovered/useless | + | M = mode | + | S = speed 0 -> 5 (6 and above makes the effect static) | + | N = number of leds | + | D = direction (0/1) | + | B = brightness (0 full, 7 off) | + \*---------------------------------------------------------*/ + + uint8_t led_mask = 0xB; + + uint8_t pkt[INSTANT_MOUSE_REPORT_SIZE]; + + pkt[0] = INSTANT_MOUSE_REPORT_ID; + pkt[1] = INSTANT_MOUSE_SET_MODE; + pkt[2] = 0xFF; + + pkt[3] = (mode_value << 4) | (speed & 0xF); + pkt[4] = (direction << 4) | led_mask; + pkt[5] = 0xF - (brightness & 0xF); + + pkt[6] = mode_value & 0xF0; + pkt[7] = 0x00; + + hid_send_feature_report(dev, pkt, INSTANT_MOUSE_REPORT_SIZE); +} diff --git a/Controllers/InstantMouseController/InstantMouseController.h b/Controllers/InstantMouseController/InstantMouseController.h new file mode 100644 index 00000000..c0de34f3 --- /dev/null +++ b/Controllers/InstantMouseController/InstantMouseController.h @@ -0,0 +1,68 @@ +/*---------------------------------------------------------*\ +| InstantMouseController.h | +| | +| Driver for Instant mouse | +| | +| Morgan Guimard (morg) 19 Jan 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define INSTANT_MOUSE_REPORT_ID 0x07 +#define INSTANT_MOUSE_REPORT_SIZE 8 +#define INSTANT_MOUSE_SET_MODE 0x13 +#define INSTANT_MOUSE_SET_COLOR 0x14 + +enum +{ + INSTANT_MOUSE_DIRECT_MODE = 0x0A, + INSTANT_MOUSE_OFF_MODE = 0xFF, + INSTANT_MOUSE_MULTICOLOR_BREATHING_MODE = 0x01, + INSTANT_MOUSE_FILL_DRAIN_MODE = 0x03, + INSTANT_MOUSE_LOOP_MODE = 0x04, + INSTANT_MOUSE_SPECTRUM_CYCLE_MODE = 0x06, + INSTANT_MOUSE_RAINBOW_WAVE_MODE = 0x07, + INSTANT_MOUSE_BREATHING_MODE = 0x08, + ANT_MOUSE_BREATHING_MODE = 0x09, + INSTANT_MOUSE_ENRAPTURED_MODE = 0xBB, + INSTANT_MOUSE_FLICKER_MODE = 0xB8, + INSTANT_MOUSE_RIPPLE_MODE = 0xBA, + INSTANT_MOUSE_STARTRECK_MODE = 0xB9, + +}; + +enum +{ + INSTANT_MOUSE_SPEED_MIN = 0x00, + INSTANT_MOUSE_SPEED_MAX = 0x05, + INSTANT_MOUSE_BRIGHTNESS_MIN = 0x00, + INSTANT_MOUSE_BRIGHTNESS_MAX = 0x07 +}; + +class InstantMouseController +{ +public: + InstantMouseController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~InstantMouseController(); + + std::string GetNameString(); + std::string GetSerialString(); + std::string GetDeviceLocation(); + uint16_t GetPID(); + + void SetMode(uint8_t mode_value, uint8_t speed, uint8_t brightness, uint8_t direction); + void SendColor(RGBColor color); + +private: + hid_device* dev; + std::string location; + std::string name; + uint16_t pid; +}; diff --git a/Controllers/InstantMouseController/InstantMouseControllerDetect.cpp b/Controllers/InstantMouseController/InstantMouseControllerDetect.cpp new file mode 100644 index 00000000..34c80602 --- /dev/null +++ b/Controllers/InstantMouseController/InstantMouseControllerDetect.cpp @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| InstantMouseControllerDetect.cpp | +| | +| Detector for Instant mouse | +| | +| Morgan Guimard (morg) 19 Jan 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "InstantMouseController.h" +#include "RGBController_InstantMouse.h" +#include "InstantMouseDevices.h" + + +void DetectInstantMouseControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + InstantMouseController* controller = new InstantMouseController(dev, *info, name); + RGBController_InstantMouse* rgb_controller = new RGBController_InstantMouse(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR_IPU("Advanced GTA 250 USB Gaming Mouse", DetectInstantMouseControllers, INSTANT_MICROELECTRONICS_VID, ADVANCED_GTA_250_PID, 1, 0xFF01, 0x01); +REGISTER_HID_DETECTOR_IPU("Anko KM43243952 USB Gaming Mouse", DetectInstantMouseControllers, INSTANT_MICROELECTRONICS_VID, ANKO_KM43243952_VID, 1, 0xFF01, 0x01); +REGISTER_HID_DETECTOR_IPU("Anko KM43277483 USB Gaming Mouse", DetectInstantMouseControllers, INSTANT_MICROELECTRONICS_VID, ANKO_KM43277483_VID, 1, 0xFF01, 0x01); +REGISTER_HID_DETECTOR_IPU("AntEsports GM600 USB Gaming Mouse", DetectInstantMouseControllers, INSTANT_MICROELECTRONICS_VID, ANTESPORTS_GM600_PID, 1, 0xFF01, 0001); + diff --git a/Controllers/InstantMouseController/InstantMouseDevices.h b/Controllers/InstantMouseController/InstantMouseDevices.h new file mode 100644 index 00000000..6a17b255 --- /dev/null +++ b/Controllers/InstantMouseController/InstantMouseDevices.h @@ -0,0 +1,19 @@ +/*---------------------------------------------------------*\ +| InstantMouseController.h | +| | +| Driver for Instant mouse | +| | +| shafiahaz2478 29 Aug 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#pragma once + +#define INSTANTMOUSEDEVICES_H + +#define INSTANT_MICROELECTRONICS_VID 0x30FA +#define ADVANCED_GTA_250_PID 0x1030 +#define ANKO_KM43243952_VID 0x1440 +#define ANKO_KM43277483_VID 0x1540 +#define ANTESPORTS_GM600_PID 0x1040 diff --git a/Controllers/InstantMouseController/RGBController_InstantMouse.cpp b/Controllers/InstantMouseController/RGBController_InstantMouse.cpp new file mode 100644 index 00000000..0dde0082 --- /dev/null +++ b/Controllers/InstantMouseController/RGBController_InstantMouse.cpp @@ -0,0 +1,223 @@ +/*---------------------------------------------------------*\ +| RGBController_InstantMouse.cpp | +| | +| RGBController for Instant mouse | +| | +| Morgan Guimard (morg) 19 Jan 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_InstantMouse.h" +#include "InstantMouseDevices.h" + +/**------------------------------------------------------------------*\ + @name Instant mouse + @category Mouse + @type USB + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectInstantMouseControllers + @comment This controller should work with all mouse with this chip. + Identified devices that work with this controller: Advance Gaming + GTA 250 (GX72-A725), Anko KM43243952 (GM8-A825), Anko KM43277483, + Ant Esports GM600 +\*-------------------------------------------------------------------*/ + +RGBController_InstantMouse::RGBController_InstantMouse(InstantMouseController* controller_ptr) +{ + controller = controller_ptr; + + vendor = controller->GetNameString(); + type = DEVICE_TYPE_MOUSE; + description = "Instant USB Gaming Mouse"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode direct; + direct.name = "Direct"; + direct.value = INSTANT_MOUSE_DIRECT_MODE; + direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + direct.color_mode = MODE_COLORS_PER_LED; + direct.brightness = INSTANT_MOUSE_BRIGHTNESS_MAX; + direct.brightness_min = INSTANT_MOUSE_BRIGHTNESS_MIN; + direct.brightness_max = INSTANT_MOUSE_BRIGHTNESS_MAX; + modes.push_back(direct); + + mode rainbow; + rainbow.name = "Rainbow wave"; + rainbow.value = INSTANT_MOUSE_RAINBOW_WAVE_MODE; + rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + rainbow.color_mode = MODE_COLORS_NONE; + rainbow.speed_min = INSTANT_MOUSE_SPEED_MIN; + rainbow.speed_max = INSTANT_MOUSE_SPEED_MAX; + rainbow.speed = INSTANT_MOUSE_SPEED_MAX/2; + modes.push_back(rainbow); + + mode spectrum; + spectrum.name = "Spectrum cycle"; + spectrum.value = INSTANT_MOUSE_SPECTRUM_CYCLE_MODE; + spectrum.flags = MODE_FLAG_HAS_SPEED; + spectrum.color_mode = MODE_COLORS_NONE; + spectrum.speed_min = INSTANT_MOUSE_SPEED_MIN; + spectrum.speed_max = INSTANT_MOUSE_SPEED_MAX; + spectrum.speed = INSTANT_MOUSE_SPEED_MAX/2; + modes.push_back(spectrum); + + mode breathing; + breathing.name = "Breathing"; + /*------------------------------------------------------------------*\ + | ANT ESPORTS GM600 has different mode id for breathing mode. | + \*------------------------------------------------------------------*/ + breathing.value = (controller->GetPID() == ANTESPORTS_GM600_PID ) ? ANT_MOUSE_BREATHING_MODE : INSTANT_MOUSE_BREATHING_MODE; + breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + breathing.colors.resize(1); + breathing.colors_min = 1; + breathing.colors_max = 1; + breathing.speed_min = INSTANT_MOUSE_SPEED_MIN; + breathing.speed_max = INSTANT_MOUSE_SPEED_MAX; + breathing.speed = INSTANT_MOUSE_SPEED_MAX/2; + modes.push_back(breathing); + + mode fill; + fill.name = "Fill"; + fill.value = INSTANT_MOUSE_FILL_DRAIN_MODE; + fill.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + fill.color_mode = MODE_COLORS_NONE; + fill.speed_min = INSTANT_MOUSE_SPEED_MIN; + fill.speed_max = INSTANT_MOUSE_SPEED_MAX; + fill.speed = INSTANT_MOUSE_SPEED_MAX/2; + fill.brightness = INSTANT_MOUSE_BRIGHTNESS_MAX; + fill.brightness_min = INSTANT_MOUSE_BRIGHTNESS_MIN; + fill.brightness_max = INSTANT_MOUSE_BRIGHTNESS_MAX; + modes.push_back(fill); + + mode loop; + loop.name = "Loop"; + loop.value = INSTANT_MOUSE_LOOP_MODE; + loop.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + loop.color_mode = MODE_COLORS_NONE; + loop.speed_min = INSTANT_MOUSE_SPEED_MIN; + loop.speed_max = INSTANT_MOUSE_SPEED_MAX; + loop.speed = INSTANT_MOUSE_SPEED_MAX/2; + loop.brightness = INSTANT_MOUSE_BRIGHTNESS_MAX; + loop.brightness_min = INSTANT_MOUSE_BRIGHTNESS_MIN; + loop.brightness_max = INSTANT_MOUSE_BRIGHTNESS_MAX; + modes.push_back(loop); + /*------------------------------------------------------------------*\ + | Extra modes for Ant Esports GM600. | + \*------------------------------------------------------------------*/ + if(controller->GetPID() == ANTESPORTS_GM600_PID ) + { + mode enraptured; + enraptured.name = "Enrpatured"; + enraptured.value = INSTANT_MOUSE_ENRAPTURED_MODE; + enraptured.flags = MODE_FLAG_HAS_SPEED; + enraptured.color_mode = MODE_COLORS_NONE; + enraptured.speed_min = INSTANT_MOUSE_SPEED_MIN; + enraptured.speed_max = INSTANT_MOUSE_SPEED_MAX; + enraptured.speed = INSTANT_MOUSE_SPEED_MAX/2; + modes.push_back(enraptured); + + mode flicker; + flicker.name = "Flicker"; + flicker.value = INSTANT_MOUSE_FLICKER_MODE; + flicker.flags = MODE_FLAG_HAS_SPEED; + flicker.color_mode = MODE_COLORS_NONE; + flicker.speed_min = INSTANT_MOUSE_SPEED_MIN; + flicker.speed_max = INSTANT_MOUSE_SPEED_MAX; + flicker.speed = INSTANT_MOUSE_SPEED_MAX/2; + modes.push_back(flicker); + + mode ripple; + ripple.name = "Ripple"; + ripple.value = INSTANT_MOUSE_RIPPLE_MODE; + ripple.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + ripple.color_mode = MODE_COLORS_NONE; + ripple.speed_min = INSTANT_MOUSE_SPEED_MIN; + ripple.speed_max = INSTANT_MOUSE_SPEED_MAX; + ripple.speed = INSTANT_MOUSE_SPEED_MAX/2; + modes.push_back(ripple); + + mode startreck; + startreck.name = "Star treck"; + startreck.value = INSTANT_MOUSE_STARTRECK_MODE; + + modes.push_back(startreck); + } + + mode off; + off.name = "Off"; + off.value = INSTANT_MOUSE_OFF_MODE; + + modes.push_back(off); + + SetupZones(); +} + +RGBController_InstantMouse::~RGBController_InstantMouse() +{ + delete controller; +} + +void RGBController_InstantMouse::SetupZones() +{ + zone new_zone; + + new_zone.name = "Mouse"; + new_zone.type = ZONE_TYPE_LINEAR; + new_zone.leds_min = 1; + new_zone.leds_max = 1; + new_zone.leds_count = 1; + new_zone.matrix_map = nullptr; + + zones.emplace_back(new_zone); + + leds.resize(1); + leds[0].name = "Mouse"; + + SetupColors(); +} + +void RGBController_InstantMouse::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_InstantMouse::DeviceUpdateLEDs() +{ + controller->SendColor(colors[0]); +} + +void RGBController_InstantMouse::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_InstantMouse::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_InstantMouse::DeviceUpdateMode() +{ + if(modes[active_mode].value == INSTANT_MOUSE_OFF_MODE) + { + controller->SetMode(INSTANT_MOUSE_DIRECT_MODE, 0, 0, 0); + controller->SendColor(0); + } + else + { + controller->SetMode(modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, modes[active_mode].direction); + + if(modes[active_mode].colors.size() == 1) + { + controller->SendColor(modes[active_mode].colors[0]); + } + } +} diff --git a/Controllers/InstantMouseController/RGBController_InstantMouse.h b/Controllers/InstantMouseController/RGBController_InstantMouse.h new file mode 100644 index 00000000..499c2f66 --- /dev/null +++ b/Controllers/InstantMouseController/RGBController_InstantMouse.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_InstantMouse.h | +| | +| RGBController for Instant mouse | +| | +| Morgan Guimard (morg) 19 Jan 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "InstantMouseController.h" + +class RGBController_InstantMouse : public RGBController +{ +public: + RGBController_InstantMouse(InstantMouseController* controller_ptr); + ~RGBController_InstantMouse(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + InstantMouseController* controller; +}; diff --git a/Controllers/IntelArcA770LEController/IntelArcA770LEController.cpp b/Controllers/IntelArcA770LEController/IntelArcA770LEController.cpp index efc034dc..2d273925 100644 --- a/Controllers/IntelArcA770LEController/IntelArcA770LEController.cpp +++ b/Controllers/IntelArcA770LEController/IntelArcA770LEController.cpp @@ -1,17 +1,20 @@ -/*-----------------------------------------*\ -| IntelArcA770LEController.cpp | -| | -| Driver for Intel Arc A770 LE RGB lighting| -| controller | -| | -| Adam Honse (CalcProgrammer1) 11/1/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| IntelArcA770LEController.cpp | +| | +| Driver for Intel Arc A770 LE | +| | +| Adam Honse (CalcProgrammer1) 01 Nov 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "IntelArcA770LEController.h" #include #include #include #include +#include "IntelArcA770LEController.h" +#include "StringUtils.h" IntelArcA770LEController::IntelArcA770LEController(hid_device* dev_handle, const char* path) { @@ -39,10 +42,7 @@ std::string IntelArcA770LEController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } std::string IntelArcA770LEController::GetFirmwareVersionString() diff --git a/Controllers/IntelArcA770LEController/IntelArcA770LEController.h b/Controllers/IntelArcA770LEController/IntelArcA770LEController.h index 93dbfcc1..f774ca89 100644 --- a/Controllers/IntelArcA770LEController/IntelArcA770LEController.h +++ b/Controllers/IntelArcA770LEController/IntelArcA770LEController.h @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| IntelArcA770LEController.h | -| | -| Definitions and types for Intel Arc A770 | -| LE lighting controller | -| | -| Adam Honse (CalcProgrammer1) 11/1/2022 | -\*-----------------------------------------*/ - -#include -#include - -#include "RGBController.h" +/*---------------------------------------------------------*\ +| IntelArcA770LEController.h | +| | +| Driver for Intel Arc A770 LE | +| | +| Adam Honse (CalcProgrammer1) 01 Nov 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + class IntelArcA770LEController { public: diff --git a/Controllers/IntelArcA770LEController/IntelArcA770LEControllerDetect.cpp b/Controllers/IntelArcA770LEController/IntelArcA770LEControllerDetect.cpp index 53f3c3ea..7028dff0 100644 --- a/Controllers/IntelArcA770LEController/IntelArcA770LEControllerDetect.cpp +++ b/Controllers/IntelArcA770LEController/IntelArcA770LEControllerDetect.cpp @@ -1,8 +1,18 @@ +/*---------------------------------------------------------*\ +| IntelArcA770LEControllerDetect.cpp | +| | +| Detector for Intel Arc A770 LE | +| | +| Adam Honse (CalcProgrammer1) 01 Nov 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "IntelArcA770LEController.h" -#include "RGBController.h" #include "RGBController_IntelArcA770LE.h" -#include #define INTEL_ARC_A770_LIMITED_EDITION_VID 0x2516 #define INTEL_ARC_A770_LIMITED_EDITION_PID 0x01B5 diff --git a/Controllers/IntelArcA770LEController/RGBController_IntelArcA770LE.cpp b/Controllers/IntelArcA770LEController/RGBController_IntelArcA770LE.cpp index 52635ab5..1004d228 100644 --- a/Controllers/IntelArcA770LEController/RGBController_IntelArcA770LE.cpp +++ b/Controllers/IntelArcA770LEController/RGBController_IntelArcA770LE.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_IntelArcA770LE.cpp | -| | -| Generic RGB Interface for Intel Arc A770 | -| LE | -| | -| Adam Honse (CalcProgrammer1) 11/2/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_IntelArcA770LE.cpp | +| | +| RGBController for Intel Arc A770 LE | +| | +| Adam Honse (CalcProgrammer1) 01 Nov 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_IntelArcA770LE.h" @@ -110,6 +112,7 @@ void RGBController_IntelArcA770LE::SetupZones() logo.leds_min = 1; logo.leds_max = 1; logo.leds_count = 1; + logo.matrix_map = NULL; zones.push_back(logo); for(unsigned int led_idx = 0; led_idx < 16; led_idx++) diff --git a/Controllers/IntelArcA770LEController/RGBController_IntelArcA770LE.h b/Controllers/IntelArcA770LEController/RGBController_IntelArcA770LE.h index 3feb6972..40934137 100644 --- a/Controllers/IntelArcA770LEController/RGBController_IntelArcA770LE.h +++ b/Controllers/IntelArcA770LEController/RGBController_IntelArcA770LE.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_IntelArcA770LE.h | -| | -| Generic RGB Interface for Intel Arc A770 | -| LE | -| | -| Adam Honse (CalcProgrammer1) 11/2/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_IntelArcA770LE.h | +| | +| RGBController for Intel Arc A770 LE | +| | +| Adam Honse (CalcProgrammer1) 01 Nov 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "IntelArcA770LEController.h" diff --git a/Controllers/IonicoController/IonicoController.cpp b/Controllers/IonicoController/IonicoController.cpp index 0275815e..005d7c5f 100644 --- a/Controllers/IonicoController/IonicoController.cpp +++ b/Controllers/IonicoController/IonicoController.cpp @@ -1,19 +1,23 @@ -/*-----------------------------------------*\ -| IonicoController.cpp | -| | -| Driver for the Ionico-II-17 lighting | -| controller | -| | -| Lucas Strafe 31/12/2022 | -\*-----------------------------------------*/ -#include "IonicoController.h" -#include +/*---------------------------------------------------------*\ +| IonicoController.cpp | +| | +| Driver for Ionico-II-17 | +| | +| Lucas Strafe 31 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -IonicoController::IonicoController(hid_device* dev_handle, const hid_device_info& info, const unsigned short pid) +#include +#include "IonicoController.h" + +IonicoController::IonicoController(hid_device* dev_handle, const hid_device_info& info, const unsigned short pid, std::string dev_name) { dev = dev_handle; location = info.path; usb_pid = pid; + name = dev_name; } IonicoController::~IonicoController() @@ -26,6 +30,11 @@ std::string IonicoController::GetDeviceLocation() return("HID: " + location); } +std::string IonicoController::GetDeviceName() +{ + return(name); +} + uint16_t IonicoController::GetUSBPID() { return(usb_pid); @@ -76,7 +85,7 @@ void IonicoController::SetColors(int device, std::vector array_colors, for(size_t i = 0; i < array_colors.size(); i++) { usb_buf[1] = IONICO_DIRECT_CMD; - usb_buf[3] = i+1; + usb_buf[3] = (uint8_t)(i + 1); usb_buf[4] = RGBGetRValue(array_colors[i]); usb_buf[5] = RGBGetGValue(array_colors[i]); usb_buf[6] = RGBGetBValue(array_colors[i]); diff --git a/Controllers/IonicoController/IonicoController.h b/Controllers/IonicoController/IonicoController.h index 4286ab1b..c87a84c4 100644 --- a/Controllers/IonicoController/IonicoController.h +++ b/Controllers/IonicoController/IonicoController.h @@ -1,8 +1,19 @@ +/*---------------------------------------------------------*\ +| IonicoController.h | +| | +| Driver for Ionico-II-17 | +| | +| Lucas Strafe 31 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once -#include "RGBController.h" #include -#include +#include +#include "RGBController.h" #define IONICO_REPORT_SIZE 9 #define IONICO_DIRECT_REPORT_SIZE 65 @@ -30,10 +41,11 @@ enum class IonicoController { public: - IonicoController(hid_device* dev_handle, const hid_device_info& info, const unsigned short pid); + IonicoController(hid_device* dev_handle, const hid_device_info& info, const unsigned short pid, std::string dev_name); ~IonicoController(); std::string GetDeviceLocation(); + std::string GetDeviceName(); void SetMode(uint8_t mode_value, uint8_t brightness, uint8_t speed); void SetColors(int device, std::vector array_colors, bool is_mode); @@ -44,7 +56,7 @@ class IonicoController private: hid_device* dev; std::string location; + std::string name; std::string serial_number; - std::string version; uint16_t usb_pid; }; diff --git a/Controllers/IonicoController/IonicoControllerDetect.cpp b/Controllers/IonicoController/IonicoControllerDetect.cpp index 54525a82..ce8a18b8 100644 --- a/Controllers/IonicoController/IonicoControllerDetect.cpp +++ b/Controllers/IonicoController/IonicoControllerDetect.cpp @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| IonicoControllerDetect.cpp | -| | -| Driver for the Ionico-II-17 lighting | -| controller | -| | -| Lucas Strafe 31/12/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| IonicoControllerDetect.cpp | +| | +| Detector for Ionico-II-17 | +| | +| Lucas Strafe 31 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "Detector.h" #include "RGBController.h" -#include "hidapi/hidapi.h" +#include "hidapi.h" #include "IonicoController.h" #include "RGBController_Ionico.h" @@ -32,9 +34,8 @@ void DetectIonicoControllers(hid_device_info* info, const std::string& name) if(dev) { - IonicoController* controller = new IonicoController(dev, *info, info->product_id); + IonicoController* controller = new IonicoController(dev, *info, info->product_id, name); RGBController_Ionico* rgb_controller = new RGBController_Ionico(controller); - rgb_controller->name = name; if(info->product_id == IONICO_KB_PID) { diff --git a/Controllers/IonicoController/RGBController_Ionico.cpp b/Controllers/IonicoController/RGBController_Ionico.cpp index 33cf4196..abb38a25 100644 --- a/Controllers/IonicoController/RGBController_Ionico.cpp +++ b/Controllers/IonicoController/RGBController_Ionico.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_Ionico.cpp | -| | -| Driver for the Ionico-II-17 lighting | -| controller | -| | -| Lucas Strafe 31/12/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Ionico.cpp | +| | +| RGBController for Ionico-II-17 | +| | +| Lucas Strafe 31 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_Ionico.h" @@ -24,7 +26,8 @@ RGBController_Ionico::RGBController_Ionico(IonicoController* controller_ptr) { controller = controller_ptr; - name = "Ionico"; + + name = controller->GetDeviceName(); vendor = "Pcspecialist"; description = name; location = controller->GetDeviceLocation(); @@ -41,21 +44,21 @@ RGBController_Ionico::RGBController_Ionico(IonicoController* controller_ptr) modes.push_back(Direct); mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = IONICO_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.speed_min = IONICO_DIRECT_SPEED_MIN; - Breathing.speed_max = IONICO_DIRECT_SPEED_MAX; - Breathing.speed = IONICO_DIRECT_SPEED_DEFAULT; - Breathing.brightness_min = IONICO_DIRECT_BRIGHTNESS_MIN; - Breathing.brightness_max = IONICO_DIRECT_BRIGHTNESS_MAX; - Breathing.brightness = IONICO_DIRECT_BRIGHTNESS_MAX; + Breathing.name = "Breathing"; + Breathing.value = IONICO_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.speed_min = IONICO_DIRECT_SPEED_MIN; + Breathing.speed_max = IONICO_DIRECT_SPEED_MAX; + Breathing.speed = IONICO_DIRECT_SPEED_DEFAULT; + Breathing.brightness_min = IONICO_DIRECT_BRIGHTNESS_MIN; + Breathing.brightness_max = IONICO_DIRECT_BRIGHTNESS_MAX; + Breathing.brightness = IONICO_DIRECT_BRIGHTNESS_MAX; Breathing.colors.resize(7); modes.push_back(Breathing); mode Wave; - Wave.name = "Wave"; + Wave.name = "Wave"; if(controller->GetUSBPID() == IONICO_KB_PID) { Wave.value = IONICO_MODE_WAVE; @@ -64,30 +67,30 @@ RGBController_Ionico::RGBController_Ionico(IonicoController* controller_ptr) { Wave.value = IONICO_FB_MODE_WAVE; } - Wave.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE; - Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; - Wave.speed_min = IONICO_DIRECT_SPEED_MIN; - Wave.speed_max = IONICO_DIRECT_SPEED_MAX; - Wave.speed = IONICO_DIRECT_SPEED_DEFAULT; - Wave.brightness_min = IONICO_DIRECT_BRIGHTNESS_MIN; - Wave.brightness_max = IONICO_DIRECT_BRIGHTNESS_MAX; - Wave.brightness = IONICO_DIRECT_BRIGHTNESS_MAX; + Wave.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE; + Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; + Wave.speed_min = IONICO_DIRECT_SPEED_MIN; + Wave.speed_max = IONICO_DIRECT_SPEED_MAX; + Wave.speed = IONICO_DIRECT_SPEED_DEFAULT; + Wave.brightness_min = IONICO_DIRECT_BRIGHTNESS_MIN; + Wave.brightness_max = IONICO_DIRECT_BRIGHTNESS_MAX; + Wave.brightness = IONICO_DIRECT_BRIGHTNESS_MAX; Wave.colors.resize(7); modes.push_back(Wave); if(controller->GetUSBPID() == IONICO_KB_PID) { mode Flash; - Flash.name = "Flashing"; - Flash.value = IONICO_MODE_FLASH; - Flash.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE; - Flash.color_mode = MODE_COLORS_MODE_SPECIFIC; - Flash.speed_min = IONICO_DIRECT_SPEED_MIN; - Flash.speed_max = IONICO_DIRECT_SPEED_MAX; - Flash.speed = IONICO_DIRECT_SPEED_DEFAULT; - Flash.brightness_min = IONICO_DIRECT_BRIGHTNESS_MIN; - Flash.brightness_max = IONICO_DIRECT_BRIGHTNESS_MAX; - Flash.brightness = IONICO_DIRECT_BRIGHTNESS_MAX; + Flash.name = "Flashing"; + Flash.value = IONICO_MODE_FLASH; + Flash.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE; + Flash.color_mode = MODE_COLORS_MODE_SPECIFIC; + Flash.speed_min = IONICO_DIRECT_SPEED_MIN; + Flash.speed_max = IONICO_DIRECT_SPEED_MAX; + Flash.speed = IONICO_DIRECT_SPEED_DEFAULT; + Flash.brightness_min = IONICO_DIRECT_BRIGHTNESS_MIN; + Flash.brightness_max = IONICO_DIRECT_BRIGHTNESS_MAX; + Flash.brightness = IONICO_DIRECT_BRIGHTNESS_MAX; Flash.colors.resize(7); modes.push_back(Flash); } @@ -95,16 +98,16 @@ RGBController_Ionico::RGBController_Ionico(IonicoController* controller_ptr) if(controller->GetUSBPID() == IONICO_FB_PID) { mode Raindrops; - Raindrops.name = "Raindrops"; - Raindrops.value = IONICO_MODE_RAIN; - Raindrops.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE; - Raindrops.color_mode = MODE_COLORS_MODE_SPECIFIC; - Raindrops.speed_min = IONICO_DIRECT_SPEED_MIN; - Raindrops.speed_max = IONICO_DIRECT_SPEED_MAX; - Raindrops.speed = IONICO_DIRECT_SPEED_DEFAULT; - Raindrops.brightness_min = IONICO_DIRECT_BRIGHTNESS_MIN; - Raindrops.brightness_max = IONICO_DIRECT_BRIGHTNESS_MAX; - Raindrops.brightness = IONICO_DIRECT_BRIGHTNESS_MAX; + Raindrops.name = "Raindrops"; + Raindrops.value = IONICO_MODE_RAIN; + Raindrops.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_MANUAL_SAVE; + Raindrops.color_mode = MODE_COLORS_MODE_SPECIFIC; + Raindrops.speed_min = IONICO_DIRECT_SPEED_MIN; + Raindrops.speed_max = IONICO_DIRECT_SPEED_MAX; + Raindrops.speed = IONICO_DIRECT_SPEED_DEFAULT; + Raindrops.brightness_min = IONICO_DIRECT_BRIGHTNESS_MIN; + Raindrops.brightness_max = IONICO_DIRECT_BRIGHTNESS_MAX; + Raindrops.brightness = IONICO_DIRECT_BRIGHTNESS_MAX; Raindrops.colors.resize(7); modes.push_back(Raindrops); } @@ -138,9 +141,9 @@ void RGBController_Ionico::SetupZones() zone zone_keyboard; zone_keyboard.name = "Keyboard"; zone_keyboard.type = ZONE_TYPE_LINEAR; - zone_keyboard.leds_min = leds.size(); - zone_keyboard.leds_max = leds.size(); - zone_keyboard.leds_count = leds.size(); + zone_keyboard.leds_min = (unsigned int)leds.size(); + zone_keyboard.leds_max = (unsigned int)leds.size(); + zone_keyboard.leds_count = (unsigned int)leds.size(); zone_keyboard.matrix_map = nullptr; zones.emplace_back(zone_keyboard); for(size_t i = 0; i < leds.size(); ++i) @@ -154,9 +157,9 @@ void RGBController_Ionico::SetupZones() zone zone_bar; zone_bar.name = "Front Bar"; zone_bar.type = ZONE_TYPE_LINEAR; - zone_bar.leds_min = leds.size(); - zone_bar.leds_max = leds.size(); - zone_bar.leds_count = leds.size(); + zone_bar.leds_min = (unsigned int)leds.size(); + zone_bar.leds_max = (unsigned int)leds.size(); + zone_bar.leds_count = (unsigned int)leds.size(); zone_bar.matrix_map = nullptr; zones.emplace_back(zone_bar); for(size_t i = 0; i < leds.size(); ++i) diff --git a/Controllers/IonicoController/RGBController_Ionico.h b/Controllers/IonicoController/RGBController_Ionico.h index 11628af4..e62a0476 100644 --- a/Controllers/IonicoController/RGBController_Ionico.h +++ b/Controllers/IonicoController/RGBController_Ionico.h @@ -1,11 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_Ionico.h | -| | -| Driver for the Ionico-II-17 lighting | -| controller | -| | -| Lucas Strafe 31/12/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Ionico.h | +| | +| RGBController for Ionico-II-17 | +| | +| Lucas Strafe 31 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include "RGBController.h" diff --git a/Controllers/JGINYUEInternalUSBController/JGINYUEInternalUSBController.cpp b/Controllers/JGINYUEInternalUSBController/JGINYUEInternalUSBController.cpp new file mode 100644 index 00000000..68b34250 --- /dev/null +++ b/Controllers/JGINYUEInternalUSBController/JGINYUEInternalUSBController.cpp @@ -0,0 +1,269 @@ +/*---------------------------------------------------------*\ +| JGINYUEInternalUSBController.cpp | +| | +| Driver for JGINYUE USB motherboard | +| | +| Tong R (tcr020) 09 Aug 2023 | +| Liu ShiMeng(Moon dream stars) 09 Aug 2023 | +| Dongguan Yonghang Electronic Technology Co., Ltd | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "RGBController.h" +#include "JGINYUEInternalUSBController.h" +#include "dmiinfo.h" + +#define JGINYUE_USB_GENERAL_COMMAND_HEADER 0x01 +#define JGINYUE_USB_LED_STRIPE_SET_COMMAND_HEADER 0x05 +#define JGINYUE_USB_MODE_SET_COMMAND_HEADER 0x06 +#define JGINYUE_USB_PER_LED_SET_COMMAND_HEADER 0x04 + +#define JGINYUE_USB_GET_FW_VERSION 0xA0 +#define JGINYUE_USB_GET_FW_REPLY 0x5A +#define JGINYUE_RG_DEFAULT 0x01 +#define JGINYUE_RG_SWAP 0x00 + +using namespace std::chrono_literals; + +JGINYUEInternalUSBController::JGINYUEInternalUSBController(hid_device* dev_handle, const char* path) +{ + DMIInfo dmi; + + dev = dev_handle; + location = path; + device_name = "JGINYUE " + dmi.getMainboard(); + + memset(&device_config, 0x00, sizeof(device_config)); + + Init_device(device_config); +} + +JGINYUEInternalUSBController::~JGINYUEInternalUSBController() +{ + hid_close(dev); +} + +unsigned int JGINYUEInternalUSBController::GetZoneCount() +{ + return(JGINYUE_MAX_ZONES); +} + +std::string JGINYUEInternalUSBController::GetDeviceLocation() +{ + return("HID:" + location); +} + +std::string JGINYUEInternalUSBController::GetDeviceName() +{ + return(device_name); +} + +std::string JGINYUEInternalUSBController::GetSerialString() +{ + return(""); +} + +std::string JGINYUEInternalUSBController::GetDeviceFWVersion() +{ + unsigned char usb_buf[16]; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = JGINYUE_USB_GENERAL_COMMAND_HEADER; + usb_buf[0x01] = JGINYUE_USB_GET_FW_VERSION; + + hid_write(dev, usb_buf, 16); + hid_read(dev, usb_buf, 16); + + if((usb_buf[0x00] != JGINYUE_USB_GENERAL_COMMAND_HEADER) || (usb_buf[0x01] != JGINYUE_USB_GET_FW_REPLY)) + { + return(""); + } + + std::string Major_version = std::to_string(usb_buf[0x02]); + std::string Minor_version = std::to_string(usb_buf[0x03]); + + return(Major_version + "." + Minor_version); +} + +void JGINYUEInternalUSBController::Init_device(AreaConfiguration* ptr_device_cfg) +{ + for(int index_config = 1; index_config <= JGINYUE_MAX_ZONES; index_config++) + { + ptr_device_cfg[index_config].Brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + ptr_device_cfg[index_config].Color_B = 0xFF; + ptr_device_cfg[index_config].Color_G = 0xFF; + ptr_device_cfg[index_config].Color_R = 0xFF; + ptr_device_cfg[index_config].RG_Swap = JGINYUE_RG_DEFAULT; + ptr_device_cfg[index_config].Speed = JGINYUE_USB_SPEED_DEFAULT; + ptr_device_cfg[index_config].LED_numbers = 0; + ptr_device_cfg[index_config].Mode_active = JGINYUE_USB_MODE_STATIC; + } +} + +void JGINYUEInternalUSBController::WriteZoneMode + ( + unsigned char zone, + unsigned char mode, + RGBColor rgb, + unsigned char speed, + unsigned char brightness, + unsigned char direction + ) +{ + int Active_zone; + unsigned char usb_buf[65]; + + switch(zone) + { + case 0x01: + Active_zone = 1; + break; + case 0x02: + Active_zone = 2; + break; + default: + Active_zone = 1; + return; + break; + } + + device_config[Active_zone].Mode_active = mode; + device_config[Active_zone].Direct_Mode_control = 0x00; + device_config[Active_zone].Speed = speed; + device_config[Active_zone].Brightness = brightness; + device_config[Active_zone].Direction = direction; + device_config[Active_zone].Color_B = RGBGetBValue(rgb); + device_config[Active_zone].Color_G = RGBGetGValue(rgb); + device_config[Active_zone].Color_R = RGBGetRValue(rgb); + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = JGINYUE_USB_LED_STRIPE_SET_COMMAND_HEADER; + usb_buf[0x01] = zone; + usb_buf[0x02] = device_config[Active_zone].LED_numbers; + usb_buf[0x03] = device_config[Active_zone].RG_Swap; + usb_buf[0x04] = device_config[Active_zone].Direction; + usb_buf[0x05] = device_config[Active_zone].Direct_Mode_control; + + hid_write(dev, usb_buf, 16); + + std::this_thread::sleep_for(20ms); + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = JGINYUE_USB_MODE_SET_COMMAND_HEADER; + usb_buf[0x01] = zone; + usb_buf[0x02] = device_config[Active_zone].Mode_active; + usb_buf[0x03] = device_config[Active_zone].Color_R; + usb_buf[0x04] = device_config[Active_zone].Color_G; + usb_buf[0x05] = device_config[Active_zone].Color_B; + usb_buf[0x06] = device_config[Active_zone].Brightness; + usb_buf[0x07] = device_config[Active_zone].Speed; + + hid_write(dev, usb_buf, 16); +} + +void JGINYUEInternalUSBController::DirectLEDControl + ( + RGBColor* colors, + unsigned char zone + ) +{ + int Active_zone; + unsigned char usb_buf[302]; + + switch(zone) + { + case 0x01: + Active_zone = 1; + break; + case 0x02: + Active_zone = 2; + break; + default: + Active_zone = 1; + return; + break; + } + + device_config[Active_zone].Mode_active =JGINYUE_USB_MODE_DIRECT; + device_config[Active_zone].Direct_Mode_control =0x01; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = JGINYUE_USB_LED_STRIPE_SET_COMMAND_HEADER; + usb_buf[0x01] = zone; + usb_buf[0x02] = device_config[Active_zone].LED_numbers; + usb_buf[0x03] = device_config[Active_zone].RG_Swap; + usb_buf[0x04] = device_config[Active_zone].Direction; + usb_buf[0x05] = device_config[Active_zone].Direct_Mode_control; + + hid_write(dev, usb_buf, 16); + + std::this_thread::sleep_for(20ms); + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = JGINYUE_USB_PER_LED_SET_COMMAND_HEADER; + usb_buf[0x01] = zone; + + for(unsigned int color_idx = 0; color_idx < device_config[Active_zone].LED_numbers; color_idx++) + { + usb_buf[color_idx * 3 + 2] = RGBGetRValue(colors[color_idx]); + usb_buf[color_idx * 3 + 3] = RGBGetGValue(colors[color_idx]); + usb_buf[color_idx * 3 + 4] = RGBGetBValue(colors[color_idx]); + } + + hid_send_feature_report(dev, usb_buf, 302); +} + +void JGINYUEInternalUSBController::Area_resize(unsigned char led_numbers, unsigned char zone) +{ + unsigned char usb_buf[65]; + int Active_zone; + + switch(zone) + { + case 0x01: + Active_zone = 1; + break; + case 0x02: + Active_zone = 2; + break; + default: + Active_zone = 1; + return; + break; + } + + device_config[Active_zone].LED_numbers = led_numbers; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = JGINYUE_USB_LED_STRIPE_SET_COMMAND_HEADER; + usb_buf[0x01] = zone; + usb_buf[0x02] = device_config[Active_zone].LED_numbers; + usb_buf[0x03] = device_config[Active_zone].RG_Swap; + usb_buf[0x04] = device_config[Active_zone].Direction; + usb_buf[0x05] = device_config[Active_zone].Direct_Mode_control; + + hid_write(dev, usb_buf, 16); +} + +void JGINYUEInternalUSBController::SetRGSwap(unsigned char RGSwap) +{ + if((RGSwap != 0x00) && (RGSwap != 0x01)) + { + return; + } + + for(int index_config=1; index_config <=JGINYUE_MAX_ZONES; index_config++) + { + device_config[index_config].RG_Swap = RGSwap; + } +} diff --git a/Controllers/JGINYUEInternalUSBController/JGINYUEInternalUSBController.h b/Controllers/JGINYUEInternalUSBController/JGINYUEInternalUSBController.h new file mode 100644 index 00000000..6623721c --- /dev/null +++ b/Controllers/JGINYUEInternalUSBController/JGINYUEInternalUSBController.h @@ -0,0 +1,110 @@ +/*---------------------------------------------------------*\ +| JGINYUEInternalUSBController.h | +| | +| Driver for JGINYUE USB motherboard | +| | +| Tong R (tcr020) 09 Aug 2023 | +| Liu ShiMeng(Moon dream stars) 09 Aug 2023 | +| Dongguan Yonghang Electronic Technology Co., Ltd | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define JGINYUE_MAX_ZONES 2 +#define JGINYUE_ADDRESSABLE_MAX_LEDS 100 + +enum +{ + JGINYUE_USB_MODE_OFF = 0x10, + JGINYUE_USB_MODE_STATIC = 0x11, + JGINYUE_USB_MODE_BREATHING = 0x12, + JGINYUE_USB_MODE_STROBE = 0x13, + JGINYUE_USB_MODE_CYCLING = 0x14, + JGINYUE_USB_MODE_RANDOM = 0x15, + JGINYUE_USB_MODE_MUSIC = 0x16, /* music mode,not support yet */ + JGINYUE_USB_MODE_WAVE = 0x17, + JGINYUE_USB_MODE_SPRING = 0x18, /* spring mode,not support yet */ + JGINYUE_USB_MODE_WATER = 0x19, + JGINYUE_USB_MODE_RAINBOW = 0x1A, /* rainbow mode,not support yet */ + JGINYUE_USB_MODE_DIRECT = 0x20, /* Not the exact USB protcol - but need a way to differentiate */ +}; + +enum +{ + JGINYUE_USB_SPEED_MAX = 0xFF, + JGINYUE_USB_SPEED_MIN = 0x00, + JGINYUE_USB_SPEED_DEFAULT = 0x80 +}; + +enum +{ + JGINYUE_DIRECTION_RIGHT = 0x00, + JGINYUE_DIRECTION_LEFT = 0x01 +}; + +enum +{ + JGINYUE_USB_BRIGHTNESS_MAX = 0xFF, + JGINYUE_USB_BRIGHTNESS_MIN = 0x00, + JGINYUE_USB_BRIGHTNESS_DEFAULT = 0xFF +}; + +struct AreaConfiguration +{ + unsigned char LED_numbers; + unsigned char RG_Swap; + unsigned char Direction; + unsigned char Direct_Mode_control; /* 0x00 = Disabled, 0x01 = Enabled */ + unsigned char Mode_active; + unsigned char Color_R; + unsigned char Color_G; + unsigned char Color_B; + unsigned char Brightness; + unsigned char Speed; +}; + +class JGINYUEInternalUSBController +{ +public: + JGINYUEInternalUSBController(hid_device* dev_handle, const char* path); + ~JGINYUEInternalUSBController(); + + unsigned int GetZoneCount(); + std::string GetDeviceLocation(); + std::string GetDeviceName(); + std::string GetSerialString(); + std::string GetDeviceFWVersion(); + + void WriteZoneMode + ( + unsigned char zone, + unsigned char mode, + RGBColor rgb, + unsigned char speed, + unsigned char brightness, + unsigned char direction + ); + + void DirectLEDControl + ( + RGBColor* colors, + unsigned char zone + ); + + void SetRGSwap(unsigned char RGSwap); + void Init_device(AreaConfiguration* ptr_device_cfg); + void Area_resize(unsigned char led_numbers,unsigned char zone); + +private: + AreaConfiguration device_config[8]; + hid_device* dev; + std::string location; + std::string device_name; +}; diff --git a/Controllers/JGINYUEInternalUSBController/JGINYUEInternalUSBControllerDetect.cpp b/Controllers/JGINYUEInternalUSBController/JGINYUEInternalUSBControllerDetect.cpp new file mode 100644 index 00000000..31a7c7ca --- /dev/null +++ b/Controllers/JGINYUEInternalUSBController/JGINYUEInternalUSBControllerDetect.cpp @@ -0,0 +1,41 @@ +/*---------------------------------------------------------*\ +| JGINYUEInternalUSBControllerDetect.cpp | +| | +| Detector for JGINYUE USB motherboard | +| | +| Tong R (tcr020) 09 Aug 2023 | +| Liu ShiMeng(Moon dream stars) 09 Aug 2023 | +| Dongguan Yonghang Electronic Technology Co., Ltd | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RGBController_JGINYUEInternalUSB.h" +#include "JGINYUEInternalUSBController.h" +#include "Detector.h" + +/*---------------------------------------------------------*\ +| JGINYUE vendor ID | +\*---------------------------------------------------------*/ +#define JGINYUE_VID 0x0416 + +/*---------------------------------------------------------*\ +| JGINYUE product ID | +\*---------------------------------------------------------*/ +#define JGINYUE_MOTHERBOARD_PID 0xA125 + +void DetectJGINYUEInternalUSBController(hid_device_info* info,const std::string& /*name*/) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + JGINYUEInternalUSBController* controller =new JGINYUEInternalUSBController(dev,info->path); + RGBController_JGINYUEInternalUSB* rgb_controller =new RGBController_JGINYUEInternalUSB(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR("JGINYUE Internal USB Controller", DetectJGINYUEInternalUSBController, JGINYUE_VID, JGINYUE_MOTHERBOARD_PID); diff --git a/Controllers/JGINYUEInternalUSBController/RGBController_JGINYUEInternalUSB.cpp b/Controllers/JGINYUEInternalUSBController/RGBController_JGINYUEInternalUSB.cpp new file mode 100644 index 00000000..353057a9 --- /dev/null +++ b/Controllers/JGINYUEInternalUSBController/RGBController_JGINYUEInternalUSB.cpp @@ -0,0 +1,345 @@ +/*---------------------------------------------------------*\ +| RGBController_JGINYUEInternalUSB.cpp | +| | +| RGBController for JGINYUE USB motherboard | +| | +| Tong R (tcr020) 09 Aug 2023 | +| Liu ShiMeng(Moon dream stars) 09 Aug 2023 | +| Dongguan Yonghang Electronic Technology Co., Ltd | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RGBController_JGINYUEInternalUSB.h" + +#define JGINYUE_MAX_ZONES 2 +#define JGINYUE_ADDRESSABLE_MAX_LEDS 100 + +/**------------------------------------------------------------------*\ + @name JGINYUEInternalUSB + @category MotherBoard + @type USB + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectJGINYUEInternalUSB + @comment Insert multiline JGINYUEInternalUSB comment here +\*--------------------------------------------------------------------*/ + +RGBController_JGINYUEInternalUSB::RGBController_JGINYUEInternalUSB(JGINYUEInternalUSBController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + description = "JGINYUE USB ARGB Device"; + vendor = "JGINYUE"; + type = DEVICE_TYPE_MOTHERBOARD; + location = controller->GetDeviceLocation(); + version = controller->GetDeviceFWVersion(); + + mode Off; + Off.name = "Off"; + Off.value = JGINYUE_USB_MODE_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Static; + Static.name = "Static"; + Static.value = JGINYUE_USB_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors_max = 1; + Static.colors_min = 1; + Static.colors.resize(1); + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = JGINYUE_USB_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.colors_max = 1; + Breathing.colors_min = 1; + Breathing.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Breathing.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Breathing.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Breathing.speed = JGINYUE_USB_SPEED_DEFAULT; + Breathing.speed_max = JGINYUE_USB_SPEED_MAX; + Breathing.speed_min = JGINYUE_USB_SPEED_MIN; + Breathing.colors.resize(1); + modes.push_back(Breathing); + + mode Strobe; + Strobe.name = "Strobe"; + Strobe.value = JGINYUE_USB_MODE_STROBE; + Strobe.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Strobe.color_mode = MODE_COLORS_MODE_SPECIFIC; + Strobe.colors_max = 1; + Strobe.colors_min = 1; + Strobe.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Strobe.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Strobe.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Strobe.speed = JGINYUE_USB_SPEED_DEFAULT; + Strobe.speed_max = JGINYUE_USB_SPEED_MAX; + Strobe.speed_min = JGINYUE_USB_SPEED_MIN; + Strobe.colors.resize(1); + modes.push_back(Strobe); + + mode Cycling; + Cycling.name = "Cycling"; + Cycling.value = JGINYUE_USB_MODE_CYCLING; + Cycling.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Cycling.color_mode = MODE_COLORS_NONE; + Cycling.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Cycling.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Cycling.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Cycling.speed = JGINYUE_USB_SPEED_DEFAULT; + Cycling.speed_max = JGINYUE_USB_SPEED_MAX; + Cycling.speed_min = JGINYUE_USB_SPEED_MIN; + modes.push_back(Cycling); + + mode Random; + Random.name = "Random"; + Random.value = JGINYUE_USB_MODE_RANDOM; + Random.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Random.color_mode = MODE_COLORS_NONE; + Random.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Random.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Random.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Random.speed = JGINYUE_USB_SPEED_DEFAULT; + Random.speed_max = JGINYUE_USB_SPEED_MAX; + Random.speed_min = JGINYUE_USB_SPEED_MIN; + modes.push_back(Random); + + mode Wave; + Wave.name = "Wave"; + Wave.value = JGINYUE_USB_MODE_WAVE; + Wave.flags = MODE_FLAG_HAS_SPEED; + Wave.color_mode = MODE_COLORS_NONE; + Wave.speed = JGINYUE_USB_SPEED_DEFAULT; + Wave.speed_max = JGINYUE_USB_SPEED_MAX; + Wave.speed_min = JGINYUE_USB_SPEED_MIN; + modes.push_back(Wave); + + //mode Spring; + //Spring.name = "Spring"; + //Spring.value = JGINYUE_USB_MODE_SPRING; + //Spring.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + //Spring.color_mode = MODE_COLORS_NONE; + //Spring.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + //Spring.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + //Spring.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + //Spring.speed = JGINYUE_USB_SPEED_DEFAULT; + //Spring.speed_max = JGINYUE_USB_SPEED_MAX; + //Spring.speed_min = JGINYUE_USB_SPEED_MIN; + //Spring.direction = 0x00; + //modes.push_back(Spring); + + mode Water; + Water.name = "Water"; + Water.value = JGINYUE_USB_MODE_WATER; + Water.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + Water.color_mode = MODE_COLORS_NONE; + Water.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Water.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Water.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Water.speed = JGINYUE_USB_SPEED_DEFAULT; + Water.speed_max = JGINYUE_USB_SPEED_MAX; + Water.speed_min = JGINYUE_USB_SPEED_MIN; + Water.direction = MODE_DIRECTION_RIGHT; + modes.push_back(Water); + + //mode Rainbow; + //Rainbow.name = "Rainbow"; + //Rainbow.value = JGINYUE_USB_MODE_RAINBOW; + //Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + //Rainbow.color_mode = MODE_COLORS_NONE; + //Rainbow.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + //Rainbow.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + //Rainbow.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + //Rainbow.speed = JGINYUE_USB_SPEED_DEFAULT; + //Rainbow.speed_max = JGINYUE_USB_SPEED_MAX; + //Rainbow.speed_min = JGINYUE_USB_SPEED_MIN; + //Rainbow.direction = MODE_DIRECTION_RIGHT; + //modes.push_back(Rainbow); + + mode Direct; + Direct.name = "Direct"; + Direct.value = JGINYUE_USB_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + SetupZones(); +} + +void RGBController_JGINYUEInternalUSB::SetupZones() +{ + /*-------------------------------------------------*\ + | Only set LED count on the first run | + \*-------------------------------------------------*/ + bool first_run = false; + + if(zones.size() == 0) + { + first_run = true; + } + + /*-------------------------------------------------*\ + | Clear any existing color/LED configuration | + \*-------------------------------------------------*/ + leds.clear(); + colors.clear(); + zones.resize(JGINYUE_MAX_ZONES); + + /*-------------------------------------------------*\ + | Set zones and leds | + \*-------------------------------------------------*/ + zones[0].name = "ARGB Header 1"; + zones[0].type = ZONE_TYPE_LINEAR; + zones[0].leds_min = 0; + zones[0].leds_max = 100; + zones[0].matrix_map = NULL; + + zones[1].name = "ARGB Header 2"; + zones[1].type = ZONE_TYPE_LINEAR; + zones[1].leds_min = 0; + zones[1].leds_max = 100; + zones[1].matrix_map = NULL; + + if(first_run) + { + zones[0].leds_count = 0; + zones[1].leds_count = 0; + } + + for(unsigned int zone_idx = 0; zone_idx < JGINYUE_MAX_ZONES; zone_idx++) + { + for(unsigned int led_idx = 0; led_idx < zones[zone_idx].leds_count; led_idx++) + { + led new_led; + new_led.name = "ARGB Header " + std::to_string(zone_idx + 1) + " LED " + std::to_string(led_idx + 1); + new_led.value = led_idx; + leds.push_back(new_led); + } + } + + SetupColors(); +} + +void RGBController_JGINYUEInternalUSB::ResizeZone(int zone, int new_size) +{ + unsigned char area; + + switch(zone) + { + case 0: + area = 0x01; + break; + case 1: + area = 0x02; + break; + default: + area = 0x01; + break; + } + + zones[zone].leds_count = new_size; + + SetupZones(); + + controller->Area_resize(new_size, area); +} + +void RGBController_JGINYUEInternalUSB::DeviceUpdateLEDs() +{ + for(int i = 0; i < JGINYUE_MAX_ZONES; i++) + { + UpdateZoneLEDs(i); + } +} + +void RGBController_JGINYUEInternalUSB::UpdateZoneLEDs(int zone) +{ + unsigned char area; + + switch(zone) + { + case 0: + area = 0x01; + break; + case 1: + area = 0x02; + break; + default: + area = 0x01; + break; + } + + controller->DirectLEDControl(zones[zone].colors,area); +} + +void RGBController_JGINYUEInternalUSB::UpdateSingleLED(int led) +{ + int zone; + zone = leds[led].value; + UpdateZoneLEDs(zone); +} + +void RGBController_JGINYUEInternalUSB::DeviceUpdateMode() +{ + unsigned char area; + + if(modes[active_mode].value == JGINYUE_USB_MODE_DIRECT) + { + DeviceUpdateLEDs(); + } + else + { + unsigned char aim_direction = JGINYUE_DIRECTION_RIGHT; + unsigned char aim_speed = JGINYUE_USB_SPEED_DEFAULT; + unsigned char aim_brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + RGBColor aim_rgb = 0x00FFFFFF; + + if(modes[active_mode].flags & MODE_FLAG_HAS_DIRECTION_LR) + { + aim_direction = modes[active_mode].direction; + } + + if(modes[active_mode].flags & MODE_FLAG_HAS_SPEED) + { + aim_speed = modes[active_mode].speed; + } + + if(modes[active_mode].flags & MODE_FLAG_HAS_BRIGHTNESS) + { + aim_brightness = modes[active_mode].brightness; + } + + if(modes[active_mode].flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR) + { + aim_rgb = modes[active_mode].colors[0]; + } + + for(int zone_index = 0; zone_index < JGINYUE_MAX_ZONES; zone_index++) + { + switch(zone_index) + { + case 0: + area = 0x01; + break; + case 1: + area = 0x02; + break; + default: + area = 0x01; + break; + } + + controller->WriteZoneMode(area, modes[active_mode].value, aim_rgb, aim_speed, aim_brightness, aim_direction); + } + } +} diff --git a/Controllers/JGINYUEInternalUSBController/RGBController_JGINYUEInternalUSB.h b/Controllers/JGINYUEInternalUSBController/RGBController_JGINYUEInternalUSB.h new file mode 100644 index 00000000..c37ba87b --- /dev/null +++ b/Controllers/JGINYUEInternalUSBController/RGBController_JGINYUEInternalUSB.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_JGINYUEInternalUSB.h | +| | +| RGBController for JGINYUE USB motherboard | +| | +| Tong R (tcr020) 09 Aug 2023 | +| Liu ShiMeng(Moon dream stars) 09 Aug 2023 | +| Dongguan Yonghang Electronic Technology Co., Ltd | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "JGINYUEInternalUSBController.h" + +class RGBController_JGINYUEInternalUSB : public RGBController +{ +public: + RGBController_JGINYUEInternalUSB(JGINYUEInternalUSBController* controller_ptr); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + JGINYUEInternalUSBController* controller; +}; diff --git a/Controllers/JGINYUEInternalUSBV2Controller/JGINYUEInternalUSBV2Controller.cpp b/Controllers/JGINYUEInternalUSBV2Controller/JGINYUEInternalUSBV2Controller.cpp new file mode 100644 index 00000000..cf96f559 --- /dev/null +++ b/Controllers/JGINYUEInternalUSBV2Controller/JGINYUEInternalUSBV2Controller.cpp @@ -0,0 +1,224 @@ +/*---------------------------------------------------------*\ +| JGINYUEInternalUSBV2Controller.cpp | +| | +| Driver for JGINYUE USB motherboard V2 | +| | +| Tong R (tcr020) 08 Aug 2024 | +| Liu ShiMeng(Moon dream stars) 09 Aug 2023 | +| Dongguan Yonghang Electronic Technology Co., Ltd | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include "RGBController.h" +#include "ResourceManager.h" +#include "SettingsManager.h" +#include "JGINYUEInternalUSBV2Controller.h" + +#include "dmiinfo.h" + +#define JGINYUE_V2_HID_GENERAL_COMMAND_HEADER 0x01 +#define JGINYUE_V2_CDC_COMMAND_HEADER 0x10 + +#define JGINYUE_V2_HID_REQUEST_MCU_STATUS 0x21 +#define JGINYUE_V2_HID_REQUEST_MCUID 0x22 +#define JGINYUE_V2_HID_REQUEST_UNLOCK 0x23 +#define JGINYUE_V2_HID_DOWNLOAD_SKU 0x24 +#define JGINYUE_V2_HID_REQUEST_MCU_STATUS_EX 0x0F +#define JGINYUE_V2_HID_DOWNLOAD_ARGB_SETTING 0x01 +#define JGINYUE_V2_HID_DOWNLOAD_GLOBAL_SETTING 0x02 +#define JGINYUE_V2_HID_REQUEST_ARGB_SETTING 0x11 +#define JGINYUE_V2_HID_REQUEST_GLOBAL_SETTING 0x12 + + + +#define FUNCTION_ID_CDC_ARGB 0x01 + +using namespace std::chrono_literals; + +JGINYUEInternalUSBV2Controller::JGINYUEInternalUSBV2Controller(hid_device* jy_hid_device, const char* path,serial_port* jy_cdc_device) +{ + DMIInfo dmi; + jy_hid_interface = jy_hid_device; + jy_cdc_interface = jy_cdc_device; + location = path; + device_name = "JGINYUE " + dmi.getMainboard() + " Internal USB Controller V2"; + ZoneCount = 0; + support_Global_zone = false; + Init_device(); +} + +JGINYUEInternalUSBV2Controller::~JGINYUEInternalUSBV2Controller() +{ + hid_close(jy_hid_interface); + delete jy_cdc_interface; + +} + +unsigned int JGINYUEInternalUSBV2Controller::GetZoneCount() +{ + return(ZoneCount); +} + +std::string JGINYUEInternalUSBV2Controller::GetDeviceLocation() +{ + return("HID:" + location); +} + +std::string JGINYUEInternalUSBV2Controller::GetDeviceName() +{ + return(device_name); +} + +std::string JGINYUEInternalUSBV2Controller::GetSerialString() +{ + return(""); +} + +std::string JGINYUEInternalUSBV2Controller::GetDeviceFWVersion() +{ + return(""); +} + +void JGINYUEInternalUSBV2Controller::Init_device() +{ + unsigned char usb_buf[64]; + + memset(usb_buf, 0x00, sizeof(usb_buf)); + usb_buf[0] = JGINYUE_V2_HID_GENERAL_COMMAND_HEADER; + usb_buf[1] = 0x0F; + hid_write(jy_hid_interface, usb_buf, 64); + std::this_thread::sleep_for(20ms); + hid_read(jy_hid_interface, usb_buf, 64); + if(usb_buf[1] != 0x0F) + { + ZoneCount = 0x00; + memset(device_config, 0x00, sizeof(device_config)); + memset (&device_config_Global, 0x00, sizeof(device_config_Global)); + return; + } + unsigned char Zone_Info = usb_buf[4]; + for(unsigned char i = 0; i < 8; i ++) + { + if(Zone_Info & (1<>4; + device_config[zone].Speed = usb_buf[6]; + device_config[zone].Brightness = usb_buf[7]; + memcpy(&(device_config[zone].Color_Array[0]),&(usb_buf[8]),Color_num*3); + return; +} + +void JGINYUEInternalUSBV2Controller::WriteZoneMode + ( + unsigned char Area, + unsigned char Mode, + unsigned char Num_LED, + std::vector rgb, + unsigned char Speed, + unsigned char Brightness, + unsigned char Direction + ) +{ + unsigned char usb_buf[64]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + unsigned char num_color = (unsigned char)rgb.size(); + num_color = (num_color < 8) ? num_color : 8; + + usb_buf[0] = JGINYUE_V2_HID_GENERAL_COMMAND_HEADER; + usb_buf[1] = JGINYUE_V2_HID_DOWNLOAD_ARGB_SETTING; + usb_buf[2] = Area; + usb_buf[3] = Mode; + usb_buf[4] = Num_LED; + usb_buf[5] = (num_color&0x0F)|((Direction&0x01)<<4); + usb_buf[6] = Speed; + usb_buf[7] = Brightness; + + for(unsigned char i = 0; i < num_color; i++) + { + RGBColor color = rgb[i]; + usb_buf[8+i*3] = RGBGetRValue(color); + usb_buf[9+i*3] = RGBGetGValue(color); + usb_buf[10+i*3] = RGBGetBValue(color); + } + + hid_write(jy_hid_interface, usb_buf, 64); + std::this_thread::sleep_for(10ms); +} + +void JGINYUEInternalUSBV2Controller::DirectLEDControl + ( + RGBColor* colors, + unsigned char num_LEDs, + unsigned char Area + ) +{ + unsigned char cdc_buf[512]; + memset(cdc_buf, 0x00, sizeof(cdc_buf)); + cdc_buf[0] = JGINYUE_V2_CDC_COMMAND_HEADER; + cdc_buf[1] = FUNCTION_ID_CDC_ARGB; + cdc_buf[2] = Area; + cdc_buf[3] = 0x20; + cdc_buf[4] = num_LEDs; + + for(unsigned char i = 0; i < num_LEDs; i++) + { + cdc_buf[8+i*3] = RGBGetRValue(colors[i]); + cdc_buf[9+i*3] = RGBGetGValue(colors[i]); + cdc_buf[10+i*3] = RGBGetBValue(colors[i]); + } + int TX_len = 10 + num_LEDs*3; + if(TX_len%64 == 0) + { + TX_len = TX_len+2; + } + + jy_cdc_interface->serial_write((char*)cdc_buf,TX_len); +} diff --git a/Controllers/JGINYUEInternalUSBV2Controller/JGINYUEInternalUSBV2Controller.h b/Controllers/JGINYUEInternalUSBV2Controller/JGINYUEInternalUSBV2Controller.h new file mode 100644 index 00000000..8462fc58 --- /dev/null +++ b/Controllers/JGINYUEInternalUSBV2Controller/JGINYUEInternalUSBV2Controller.h @@ -0,0 +1,139 @@ +/*---------------------------------------------------------*\ +| JGINYUEInternalUSBV2Controller.h | +| | +| Driver for JGINYUE USB motherboard V2 | +| | +| Tong R (tcr020) 09 Aug 2023 | +| Liu ShiMeng(Moon dream stars) 06 Aug 2024 | +| Dongguan Yonghang Electronic Technology Co., Ltd | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "serial_port.h" +#include "RGBController.h" + +#define JGINYUE_MAX_ZONES 2 +#define JGINYUE_ADDRESSABLE_MAX_LEDS 100 + +enum +{ + JGINYUE_USB_V2_MODE_SYNC = 0x0F, + JGINYUE_USB_V2_MODE_OFF = 0x10, + JGINYUE_USB_V2_MODE_STATIC = 0x11, + JGINYUE_USB_V2_MODE_BREATHING = 0x12, + JGINYUE_USB_V2_MODE_CYCLING = 0x14, + JGINYUE_USB_V2_MODE_RANDOM = 0x15, + JGINYUE_USB_V2_MODE_SPRING = 0x16, + JGINYUE_USB_V2_MODE_WAVE = 0x17, + JGINYUE_USB_V2_MODE_WATER = 0x19, + JGINYUE_USB_V2_MODE_RAINBOW = 0x1A, + JGINYUE_USB_V2_MODE_MULTICOLOR_WAVE = 0x1B, + JGINYUE_USB_V2_MODE_MULTICOLOR_CYCLING = 0x1C, + JGINYUE_USB_V2_MODE_SUNRISE = 0x1D, + JGINYUE_USB_V2_MODE_ROTATE_STAR = 0x1E, + JGINYUE_USB_V2_MODE_METEOR = 0x1F, + JGINYUE_USB_V2_MODE_DIRECT = 0x20, + JGINYUE_USB_V2_MODE_CYCLING_BREATHING = 0x21, + JGINYUE_USB_V2_MODE_CYCLING_RAINING = 0x22, + JGINYUE_USB_V2_MODE_MULTICOLOR_WATER_2 = 0x23, + JGINYUE_USB_V2_MODE_MULTICOLOR_WATER_1 = 0x24, + JGINYUE_USB_V2_MODE_HOURGLASS = 0x25 +}; + +enum +{ + JGINYUE_USB_SPEED_MAX = 0xFF, + JGINYUE_USB_SPEED_MIN = 0x00, + JGINYUE_USB_SPEED_DEFAULT = 0x80 +}; + +enum +{ + JGINYUE_DIRECTION_RIGHT = 0x00, + JGINYUE_DIRECTION_LEFT = 0x01 +}; + +enum +{ + JGINYUE_USB_BRIGHTNESS_MAX = 0xFF, + JGINYUE_USB_BRIGHTNESS_MIN = 0x00, + JGINYUE_USB_BRIGHTNESS_DEFAULT = 0xFF +}; + +enum +{ + JGINYUE_USB_V2_ARGB_STRIP_1 = 0x01, + JGINYUE_USB_V2_ARGB_STRIP_2 = 0x02, + JGINYUE_USB_V2_ARGB_FAN_1 = 0x04, + JGINYUE_USB_V2_ARGB_FAN_2 = 0x08, + JGINYUE_USB_V2_ARGB_FAN_3 = 0x10, + JGINYUE_USB_V2_ARGB_FAN_4 = 0x20, + JGINYUE_USB_V2_ARGB_FAN_5 = 0x40, +}; + +struct AreaConfigurationV2 +{ + unsigned char Area_ID; + unsigned char Max_LED_numbers; + unsigned char User_LED_numbers; + unsigned char Direction; + unsigned char Direct_Mode_control; /* 0x00 = Disabled, 0x01 = Enabled */ + unsigned char Mode_active; + unsigned char Color_num; + unsigned char Color_Array[30]; + unsigned char Brightness; + unsigned char Speed; +}; + +class JGINYUEInternalUSBV2Controller +{ +public: + JGINYUEInternalUSBV2Controller(hid_device* jy_hid_device, const char* path,serial_port* jy_cdc_device); + ~JGINYUEInternalUSBV2Controller(); + + unsigned int GetZoneCount(); + std::string GetDeviceLocation(); + std::string GetDeviceName(); + std::string GetSerialString(); + std::string GetDeviceFWVersion(); + + void WriteZoneMode + ( + unsigned char Area, + unsigned char Mode, + unsigned char Num_LED, + std::vector rgb, + unsigned char Speed, + unsigned char Brightness, + unsigned char Direction + ); + + void DirectLEDControl + ( + RGBColor* colors, + unsigned char num_LEDs, + unsigned char Area + ); + + AreaConfigurationV2 device_config[8]; + //TODO,When the perzone mode is supported, these parameters will be used to download device configuartion from the device + AreaConfigurationV2 device_config_Global; + //TODO,Can sync its data to other zones,will be used once the perzone mode is supported + bool support_Global_zone; + +private: + void Init_device(); + void Init_Zone(int zone); + unsigned char ZoneCount; + + hid_device* jy_hid_interface; + serial_port* jy_cdc_interface; + std::string location; + std::string device_name; +}; diff --git a/Controllers/JGINYUEInternalUSBV2Controller/JGINYUEInternalUSBV2ControllerDetect.cpp b/Controllers/JGINYUEInternalUSBV2Controller/JGINYUEInternalUSBV2ControllerDetect.cpp new file mode 100644 index 00000000..3bd16b1c --- /dev/null +++ b/Controllers/JGINYUEInternalUSBV2Controller/JGINYUEInternalUSBV2ControllerDetect.cpp @@ -0,0 +1,80 @@ +/*---------------------------------------------------------*\ +| JGINYUEInternalUSBV2ControllerDetect.cpp | +| | +| Detector for JGINYUE USB motherboard V2 | +| | +| Tong R (tcr020) 06 Aug 2024 | +| Liu ShiMeng(Moon dream stars) 09 Aug 2023 | +| Dongguan Yonghang Electronic Technology Co., Ltd | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include +#include "serial_port.h" +#include "find_usb_serial_port.h" +#include "RGBController_JGINYUEInternalUSBV2.h" +#include "JGINYUEInternalUSBV2Controller.h" +#include "RGBController.h" +#include "Detector.h" +#include "dmiinfo.h" +#include "LogManager.h" +/*---------------------------------------------------------*\ +| JGINYUE vendor ID | +\*---------------------------------------------------------*/ +#define JGINYUE_VID_V2 0x1A86 + +/*---------------------------------------------------------*\ +| JGINYUE product ID | +\*---------------------------------------------------------*/ +#define JGINYUE_MOTHERBOARD_PID_V2 0xE30B + +void DetectJGINYUEInternalUSBV2Controller(hid_device_info* info,const std::string& /*name*/) +{ + hid_device* hid_dev = hid_open_path(info->path); + if(hid_dev == nullptr ) + { + return; + } + + DMIInfo dmi_info; + std::string manufacturer = dmi_info.getManufacturer(); + std::transform(manufacturer.begin(), manufacturer.end(), manufacturer.begin(), ::toupper); + if(manufacturer.find("JGINYUE") == std::string::npos) + { + LOG_INFO("JGINYUE Internal USB ControllerV2 not found,error manufacturer name:%s",manufacturer.c_str()); + return; + } + LOG_INFO("Pass manufacture name check.Start to init HID and CDC interface"); + + + if(hid_dev != nullptr ) + { + std::vector serial_ports = find_usb_serial_port(JGINYUE_VID_V2, JGINYUE_MOTHERBOARD_PID_V2); + if(serial_ports.size() ==1) + { + serial_port *port = new serial_port(); + if(!port->serial_open(serial_ports[0]->c_str(), 115200)) + { + LOG_ERROR("Failed to open serial port %s", serial_ports[0]->c_str()); + delete port; + hid_close(hid_dev); + return; + } + JGINYUEInternalUSBV2Controller *controller = new JGINYUEInternalUSBV2Controller(hid_dev, info->path,port); + RGBController_JGINYUEInternalUSBV2 *rgb_controller = new RGBController_JGINYUEInternalUSBV2(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); + LOG_INFO("JGINYUE Internal USB ControllerV2 found"); + } + } +} + +#ifdef _WIN32 +REGISTER_HID_DETECTOR("JGINYUE Internal USB ControllerV2", DetectJGINYUEInternalUSBV2Controller, JGINYUE_VID_V2, JGINYUE_MOTHERBOARD_PID_V2); +#else +REGISTER_HID_DETECTOR_IPU("JGINYUE Internal USB ControllerV2", DetectJGINYUEInternalUSBV2Controller, JGINYUE_VID_V2, JGINYUE_MOTHERBOARD_PID_V2, 0, 0xFF00, 1); +#endif diff --git a/Controllers/JGINYUEInternalUSBV2Controller/RGBController_JGINYUEInternalUSBV2.cpp b/Controllers/JGINYUEInternalUSBV2Controller/RGBController_JGINYUEInternalUSBV2.cpp new file mode 100644 index 00000000..df0d5c40 --- /dev/null +++ b/Controllers/JGINYUEInternalUSBV2Controller/RGBController_JGINYUEInternalUSBV2.cpp @@ -0,0 +1,506 @@ +/*---------------------------------------------------------*\ +| RGBController_JGINYUEInternalUSBV2.cpp | +| | +| RGBController for JGINYUE USB motherboard V2 | +| | +| Tong R (tcr020) 03 July 2024 | +| Liu ShiMeng(Moon dream stars) 09 Aug 2023 | +| Dongguan Yonghang Electronic Technology Co., Ltd | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RGBController_JGINYUEInternalUSBV2.h" + +#define JGINYUE_MAX_ZONES 2 +#define JGINYUE_ADDRESSABLE_MAX_LEDS 100 + +/**------------------------------------------------------------------*\ + @name JGINYUEInternalUSBV2 + @category MotherBoard + @type USB + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectJGINYUEInternalUSBV2 + @comment Insert multiline JGINYUEInternalUSBV2 comment here +\*--------------------------------------------------------------------*/ + +RGBController_JGINYUEInternalUSBV2::RGBController_JGINYUEInternalUSBV2(JGINYUEInternalUSBV2Controller* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + description = "JGINYUE USB ARGB Device"; + vendor = "JGINYUE"; + type = DEVICE_TYPE_MOTHERBOARD; + location = controller->GetDeviceLocation(); + version = controller->GetDeviceFWVersion(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = JGINYUE_USB_V2_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Off; + Off.name = "Off"; + Off.value = JGINYUE_USB_V2_MODE_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Static; + Static.name = "Static"; + Static.value = JGINYUE_USB_V2_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR|MODE_FLAG_HAS_BRIGHTNESS; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors_max = 1; + Static.colors_min = 1; + Static.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Static.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Static.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Static.colors.resize(1); + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = JGINYUE_USB_V2_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.colors_max = 1; + Breathing.colors_min = 1; + Breathing.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Breathing.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Breathing.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Breathing.speed = JGINYUE_USB_SPEED_DEFAULT; + Breathing.speed_max = JGINYUE_USB_SPEED_MAX; + Breathing.speed_min = JGINYUE_USB_SPEED_MIN; + Breathing.colors.resize(1); + modes.push_back(Breathing); + + mode Cycling; + Cycling.name = "Cycling"; + Cycling.value = JGINYUE_USB_V2_MODE_CYCLING; + Cycling.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + Cycling.color_mode = MODE_COLORS_NONE; + Cycling.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Cycling.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Cycling.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Cycling.speed = JGINYUE_USB_SPEED_DEFAULT; + Cycling.speed_max = JGINYUE_USB_SPEED_MAX; + Cycling.speed_min = JGINYUE_USB_SPEED_MIN; + Cycling.direction = JGINYUE_DIRECTION_RIGHT; + modes.push_back(Cycling); + + mode Random; + Random.name = "Random"; + Random.value = JGINYUE_USB_V2_MODE_RANDOM; + Random.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Random.color_mode = MODE_COLORS_NONE; + Random.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Random.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Random.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Random.speed = JGINYUE_USB_SPEED_DEFAULT; + Random.speed_max = JGINYUE_USB_SPEED_MAX; + Random.speed_min = JGINYUE_USB_SPEED_MIN; + modes.push_back(Random); + + mode Wave; + Wave.name = "Wave"; + Wave.value = JGINYUE_USB_V2_MODE_WAVE; + Wave.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS| MODE_FLAG_HAS_DIRECTION_LR; + Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; + Wave.colors_max = 1; + Wave.colors_min = 1; + Wave.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Wave.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Wave.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Wave.speed = JGINYUE_USB_SPEED_DEFAULT; + Wave.speed_max = JGINYUE_USB_SPEED_MAX; + Wave.speed_min = JGINYUE_USB_SPEED_MIN; + Wave.direction = JGINYUE_DIRECTION_LEFT; + Wave.colors.resize(1); + modes.push_back(Wave); + + mode Spring; + Spring.name = "Spring"; + Spring.value = JGINYUE_USB_V2_MODE_SPRING; + Spring.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS| MODE_FLAG_HAS_DIRECTION_LR; + Spring.color_mode = MODE_COLORS_MODE_SPECIFIC; + Spring.colors_max = 1; + Spring.colors_min = 1; + Spring.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Spring.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Spring.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Spring.speed = JGINYUE_USB_SPEED_DEFAULT; + Spring.speed_max = JGINYUE_USB_SPEED_MAX; + Spring.speed_min = JGINYUE_USB_SPEED_MIN; + Spring.direction = JGINYUE_DIRECTION_RIGHT; + Spring.colors.resize(1); + //modes.push_back(Spring); + + mode Water; + Water.name = "Water"; + Water.value = JGINYUE_USB_V2_MODE_WATER; + Water.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR |MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + Water.color_mode = MODE_COLORS_MODE_SPECIFIC; + Water.colors_max = 1; + Water.colors_min = 1; + Water.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Water.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Water.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Water.speed = JGINYUE_USB_SPEED_DEFAULT; + Water.speed_max = JGINYUE_USB_SPEED_MAX; + Water.speed_min = JGINYUE_USB_SPEED_MIN; + Water.direction = MODE_DIRECTION_RIGHT; + Water.colors.resize(1); + modes.push_back(Water); + + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = JGINYUE_USB_V2_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Rainbow.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Rainbow.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Rainbow.speed = JGINYUE_USB_SPEED_DEFAULT; + Rainbow.speed_max = JGINYUE_USB_SPEED_MAX; + Rainbow.speed_min = JGINYUE_USB_SPEED_MIN; + Rainbow.direction = MODE_DIRECTION_RIGHT; + modes.push_back(Rainbow); + + mode MulticolorCycling; + MulticolorCycling.name = "Multicolor CYCLING"; + MulticolorCycling.value = JGINYUE_USB_V2_MODE_MULTICOLOR_CYCLING; + MulticolorCycling.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + MulticolorCycling.color_mode = MODE_COLORS_MODE_SPECIFIC; + MulticolorCycling.colors_max = 8; + MulticolorCycling.colors_min = 1; + MulticolorCycling.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + MulticolorCycling.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + MulticolorCycling.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + MulticolorCycling.speed = JGINYUE_USB_SPEED_DEFAULT; + MulticolorCycling.speed_max = JGINYUE_USB_SPEED_MAX; + MulticolorCycling.speed_min = JGINYUE_USB_SPEED_MIN; + MulticolorCycling.direction = MODE_DIRECTION_RIGHT; + MulticolorCycling.colors.resize(8); + modes.push_back(MulticolorCycling); + + mode Sunrise; + Sunrise.name = "Sunrise"; + Sunrise.value = JGINYUE_USB_V2_MODE_SUNRISE; + Sunrise.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + Sunrise.color_mode = MODE_COLORS_MODE_SPECIFIC; + Sunrise.colors_max = 8; + Sunrise.colors_min = 1; + Sunrise.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Sunrise.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Sunrise.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Sunrise.speed = JGINYUE_USB_SPEED_DEFAULT; + Sunrise.speed_max = JGINYUE_USB_SPEED_MAX; + Sunrise.speed_min = JGINYUE_USB_SPEED_MIN; + Sunrise.direction = MODE_DIRECTION_RIGHT; + Sunrise.colors.resize(8); + modes.push_back(Sunrise); + + mode Rotate_star; + Rotate_star.name = "Rotate Star"; + Rotate_star.value = JGINYUE_USB_V2_MODE_ROTATE_STAR; + Rotate_star.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + Rotate_star.color_mode = MODE_COLORS_MODE_SPECIFIC; + Rotate_star.colors_max = 8; + Rotate_star.colors_min = 1; + Rotate_star.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Rotate_star.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Rotate_star.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Rotate_star.speed = JGINYUE_USB_SPEED_DEFAULT; + Rotate_star.speed_max = JGINYUE_USB_SPEED_MAX; + Rotate_star.speed_min = JGINYUE_USB_SPEED_MIN; + Rotate_star.direction = MODE_DIRECTION_RIGHT; + Rotate_star.colors.resize(8); + modes.push_back(Rotate_star); + + mode Meteor; + Meteor.name = "Meteor"; + Meteor.value = JGINYUE_USB_V2_MODE_METEOR; + Meteor.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + Meteor.color_mode = MODE_COLORS_MODE_SPECIFIC; + Meteor.colors_max = 1; + Meteor.colors_min = 1; + Meteor.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Meteor.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Meteor.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Meteor.speed = JGINYUE_USB_SPEED_DEFAULT; + Meteor.speed_max = JGINYUE_USB_SPEED_MAX; + Meteor.speed_min = JGINYUE_USB_SPEED_MIN; + Meteor.direction = MODE_DIRECTION_RIGHT; + Meteor.colors.resize(8); + modes.push_back(Meteor); + + mode Cycling_Breathing; + Cycling_Breathing.name = "Cycling Breathing"; + Cycling_Breathing.value = JGINYUE_USB_V2_MODE_CYCLING_BREATHING; + Cycling_Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + Cycling_Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Cycling_Breathing.colors_max = 8; + Cycling_Breathing.colors_min = 1; + Cycling_Breathing.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Cycling_Breathing.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Cycling_Breathing.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Cycling_Breathing.speed = JGINYUE_USB_SPEED_DEFAULT; + Cycling_Breathing.speed_max = JGINYUE_USB_SPEED_MAX; + Cycling_Breathing.speed_min = JGINYUE_USB_SPEED_MIN; + Cycling_Breathing.direction = MODE_DIRECTION_RIGHT; + Cycling_Breathing.colors.resize(8); + modes.push_back(Cycling_Breathing); + + mode Raining; + Raining.name = "Raining"; + Raining.value = JGINYUE_USB_V2_MODE_CYCLING_RAINING; + Raining.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + Raining.color_mode = MODE_COLORS_MODE_SPECIFIC; + Raining.colors_max = 1; + Raining.colors_min = 1; + Raining.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Raining.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Raining.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Raining.speed = JGINYUE_USB_SPEED_DEFAULT; + Raining.speed_max = JGINYUE_USB_SPEED_MAX; + Raining.speed_min = JGINYUE_USB_SPEED_MIN; + Raining.direction = MODE_DIRECTION_RIGHT; + Raining.colors.resize(8); + modes.push_back(Raining); + + mode MulticolorWater1; + MulticolorWater1.name = "Multicolor Water 1"; + MulticolorWater1.value = JGINYUE_USB_V2_MODE_MULTICOLOR_WATER_1; + MulticolorWater1.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + MulticolorWater1.color_mode = MODE_COLORS_MODE_SPECIFIC; + MulticolorWater1.colors_max = 8; + MulticolorWater1.colors_min = 1; + MulticolorWater1.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + MulticolorWater1.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + MulticolorWater1.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + MulticolorWater1.speed = JGINYUE_USB_SPEED_DEFAULT; + MulticolorWater1.speed_max = JGINYUE_USB_SPEED_MAX; + MulticolorWater1.speed_min = JGINYUE_USB_SPEED_MIN; + MulticolorWater1.direction = JGINYUE_DIRECTION_LEFT; + MulticolorWater1.colors.resize(8); + modes.push_back(MulticolorWater1); + + + mode MulticolorWater2; + MulticolorWater2.name = "Multicolor Water 2"; + MulticolorWater2.value = JGINYUE_USB_V2_MODE_MULTICOLOR_WATER_2; + MulticolorWater2.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + MulticolorWater2.color_mode = MODE_COLORS_MODE_SPECIFIC; + MulticolorWater2.colors_max = 8; + MulticolorWater2.colors_min = 1; + MulticolorWater2.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + MulticolorWater2.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + MulticolorWater2.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + MulticolorWater2.speed = JGINYUE_USB_SPEED_DEFAULT; + MulticolorWater2.speed_max = JGINYUE_USB_SPEED_MAX; + MulticolorWater2.speed_min = JGINYUE_USB_SPEED_MIN; + MulticolorWater2.direction = JGINYUE_DIRECTION_LEFT; + MulticolorWater2.colors.resize(8); + modes.push_back(MulticolorWater2); + + mode Hourglass; + Hourglass.name = "Hourglass"; + Hourglass.value = JGINYUE_USB_V2_MODE_HOURGLASS; + Hourglass.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + Hourglass.color_mode = MODE_COLORS_MODE_SPECIFIC; + Hourglass.colors_max = 3; + Hourglass.colors_min = 3; + Hourglass.brightness = JGINYUE_USB_BRIGHTNESS_DEFAULT; + Hourglass.brightness_max = JGINYUE_USB_BRIGHTNESS_MAX; + Hourglass.brightness_min = JGINYUE_USB_BRIGHTNESS_MIN; + Hourglass.speed = JGINYUE_USB_SPEED_DEFAULT; + Hourglass.speed_max = JGINYUE_USB_SPEED_MAX; + Hourglass.speed_min = JGINYUE_USB_SPEED_MIN; + Hourglass.direction = MODE_DIRECTION_RIGHT; + Hourglass.colors.resize(8); + //modes.push_back(Hourglass); + + InitZones(); +} + +void RGBController_JGINYUEInternalUSBV2::SetupZones() +{ + /*-------------------------------------------------*\ + | Clear any existing color/LED configuration | + \*-------------------------------------------------*/ + leds.clear(); + colors.clear(); + + /*-------------------------------------------------*\ + | Set zones and leds | + \*-------------------------------------------------*/ + unsigned char normal_zone_count = controller->GetZoneCount(); + if((controller->support_Global_zone == true) && (normal_zone_count > 1)) + { + normal_zone_count--; + //TODO support_Global_zone + } + + for(unsigned int zone_idx = 0; zone_idx < normal_zone_count; 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); + new_led.value = 0; + leds.push_back(new_led); + } + } + + SetupColors(); +} + +void RGBController_JGINYUEInternalUSBV2::ResizeZone(int zone, int new_size) +{ + unsigned char area; + + area = controller->device_config[zone].Area_ID; + + zones[zone].leds_count = new_size; + + SetupZones(); + + if(modes[active_mode].value == JGINYUE_USB_V2_MODE_DIRECT) + { + controller->DirectLEDControl(zones[zone].colors, new_size, area); + } + else + { + controller->WriteZoneMode(area,modes[active_mode].value, new_size,modes[active_mode].colors, modes[active_mode].speed, modes[active_mode].brightness, modes[active_mode].direction); + } +} + +void RGBController_JGINYUEInternalUSBV2::DeviceUpdateLEDs() +{ + unsigned char normal_zone_count = controller->GetZoneCount(); + + if((controller->support_Global_zone == true) && (normal_zone_count > 1)) + { + normal_zone_count--; + //TODO support_Global_zone + } + + for(int i = 0; i < normal_zone_count; i++) + { + UpdateZoneLEDs(i); + } +} + +void RGBController_JGINYUEInternalUSBV2::UpdateZoneLEDs(int zone) +{ + unsigned char area; + area = controller->device_config[zone].Area_ID; + + controller->DirectLEDControl(zones[zone].colors, zones[zone].leds_count, area); +} + +void RGBController_JGINYUEInternalUSBV2::UpdateSingleLED(int led) +{ + int zone; + zone = leds[led].value; + + UpdateZoneLEDs(zone); +} + +void RGBController_JGINYUEInternalUSBV2::DeviceUpdateMode() +{ + if(modes[active_mode].value == JGINYUE_USB_V2_MODE_DIRECT) + { + DeviceUpdateLEDs(); + return; + } + + unsigned int Area_num = 0; + if(controller->support_Global_zone == true) + { + Area_num = controller->GetZoneCount() - 1; + } + else + { + Area_num = controller->GetZoneCount(); + } + for(unsigned int i = 0; i < Area_num; i++) + { + DeviceUpdateZoneMode((int)i); + } +} + +void RGBController_JGINYUEInternalUSBV2::DeviceUpdateZoneMode(int zone) +{ + unsigned char Area_ID = controller->device_config[zone].Area_ID; + controller->WriteZoneMode( + Area_ID, + modes[active_mode].value, + zones[zone].leds_count, + modes[active_mode].colors, + modes[active_mode].speed, + modes[active_mode].brightness, + modes[active_mode].direction); +} + +void RGBController_JGINYUEInternalUSBV2::InitZones() +{ + unsigned char normal_zone_count = controller->GetZoneCount(); + zones.clear(); + zones.resize(normal_zone_count); + + if((controller->support_Global_zone == true) && (normal_zone_count > 1)) + { + normal_zone_count--; + //TODO support_Global_zone + } + + for(size_t i = 0; i < normal_zone_count; i++) + { + zone * zone_to_init = &(zones[i]); + AreaConfigurationV2 * cfg = &(controller->device_config[i]); + + zone_to_init->leds_min = 0; + zone_to_init->leds_max = cfg->Max_LED_numbers; + zone_to_init->leds_count = 0; + zone_to_init->type = ZONE_TYPE_LINEAR; + zone_to_init->matrix_map = NULL; + + switch(cfg->Area_ID) + { + case JGINYUE_USB_V2_ARGB_STRIP_1: + zone_to_init->name = "ARGB Strip Header 1"; + break; + case JGINYUE_USB_V2_ARGB_STRIP_2: + zone_to_init->name = "ARGB Strip Header 2"; + break; + case JGINYUE_USB_V2_ARGB_FAN_1: + zone_to_init->name = "ARGB Fan Header 1"; + break; + case JGINYUE_USB_V2_ARGB_FAN_2: + zone_to_init->name = "ARGB Fan Header 2"; + break; + case JGINYUE_USB_V2_ARGB_FAN_3: + zone_to_init->name = "ARGB Fan Header 3"; + break; + case JGINYUE_USB_V2_ARGB_FAN_4: + zone_to_init->name = "ARGB Fan Header 4"; + break; + case JGINYUE_USB_V2_ARGB_FAN_5: + zone_to_init->name = "ARGB Fan Header 5"; + break; + default: + zone_to_init->name = "Unknow Device"; + break; + } + } + SetupZones(); +} diff --git a/Controllers/JGINYUEInternalUSBV2Controller/RGBController_JGINYUEInternalUSBV2.h b/Controllers/JGINYUEInternalUSBV2Controller/RGBController_JGINYUEInternalUSBV2.h new file mode 100644 index 00000000..765cae8e --- /dev/null +++ b/Controllers/JGINYUEInternalUSBV2Controller/RGBController_JGINYUEInternalUSBV2.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------*\ +| RGBController_JGINYUEInternalUSBV2.h | +| | +| RGBController for JGINYUE USB motherboard V2 | +| | +| Tong R (tcr020) 03 July 2023 | +| Liu ShiMeng(Moon dream stars) 06 Aug 2024 | +| Dongguan Yonghang Electronic Technology Co., Ltd | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "JGINYUEInternalUSBV2Controller.h" + +class RGBController_JGINYUEInternalUSBV2 : public RGBController +{ +public: + RGBController_JGINYUEInternalUSBV2(JGINYUEInternalUSBV2Controller* controller_ptr); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceUpdateZoneMode(int zone); + +private: + JGINYUEInternalUSBV2Controller* controller; + void InitZones(); +}; diff --git a/Controllers/KasaSmartController/KasaSmartController.cpp b/Controllers/KasaSmartController/KasaSmartController.cpp index f61489a1..7c0c85a3 100644 --- a/Controllers/KasaSmartController/KasaSmartController.cpp +++ b/Controllers/KasaSmartController/KasaSmartController.cpp @@ -1,11 +1,17 @@ -/*----------------------------------------------*\ -| Driver for Kasa Smart light bulbs | -| | -| Devin Wendt (umbreon222@gmail.com), 2/16/2023 | -\*----------------------------------------------*/ +/*---------------------------------------------------------*\ +| KasaSmartController.cpp | +| | +| Driver for Kasa Smart bulbs | +| | +| Devin Wendt (umbreon222@gmail.com) 16 Feb 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include "KasaSmartController.h" -#include "json.hpp" +#include #include "hsv.h" using json = nlohmann::json; @@ -105,6 +111,32 @@ bool KasaSmartController::Initialize() return is_initialized; } + std::string model; + if(system_information["system"]["get_sysinfo"].contains("model")) + { + model = system_information["system"]["get_sysinfo"]["model"]; + } + else + { + /*-----------------------*\ + | Can't find device model | + \*-----------------------*/ + return is_initialized; + } + + if(model.find("KL420") != std::string::npos) + { + kasa_type = KASA_SMART_TYPE_KL420; + } + else if(model.find("KL4") != std::string::npos) + { + kasa_type = KASA_SMART_TYPE_OTHER_LEDSTRIP; + } + else + { + kasa_type = KASA_SMART_TYPE_LIGHT; + } + firmware_version = system_information["system"]["get_sysinfo"]["sw_ver"]; module_name = system_information["system"]["get_sysinfo"]["model"]; device_id = system_information["system"]["get_sysinfo"]["deviceId"]; @@ -146,7 +178,12 @@ std::string KasaSmartController::GetUniqueID() return(device_id); } -void KasaSmartController::SetColor(unsigned char red, unsigned char green, unsigned char blue) +int KasaSmartController::GetKasaType() +{ + return(kasa_type); +} + +void KasaSmartController::SetColor(unsigned char red, unsigned char green, unsigned char blue, int device_type) { if(!is_initialized) { @@ -186,14 +223,22 @@ void KasaSmartController::SetColor(unsigned char red, unsigned char green, unsig \*----------------------------*/ if(normalized_saturation == 0 && normalized_value == 0) { - TurnOff(); + TurnOff(device_type); return; } /*------------------------------*\ | Format set light state command | \*------------------------------*/ - const std::string set_lightstate_command_format(KASA_SMART_SET_LIGHT_STATE_COMMAND_FORMAT); + std::string set_lightstate_command_format; + if(device_type == DEVICE_TYPE_LIGHT) + { + set_lightstate_command_format = KASA_SMART_LIGHT_SET_LIGHT_STATE_COMMAND_FORMAT; + } + else if(device_type == DEVICE_TYPE_LEDSTRIP) + { + set_lightstate_command_format = KASA_SMART_LEDSTRIP_SET_LIGHT_STATE_COMMAND_FORMAT; + } int size = std::snprintf(nullptr, 0, set_lightstate_command_format.c_str(), normalized_hue, normalized_saturation, normalized_value) + 1; if(size <= 0) { @@ -213,14 +258,43 @@ void KasaSmartController::SetColor(unsigned char red, unsigned char green, unsig port.tcp_close(); } -void KasaSmartController::TurnOff() +void KasaSmartController::SetEffect(std::string effect) { if(!is_initialized) { return; } - const std::string turn_off_command(KASA_SMART_OFF_COMMAND); + /*-------------------*\ + | Open TCP connection | + \*-------------------*/ + if(!port.connected && !port.tcp_client_connect() && ++retry_count >= KASA_SMART_MAX_CONNECTION_ATTEMPTS) + { + is_initialized = false; + return; + } + + std::string response; + KasaSmartController::SendCommand(effect, response); + port.tcp_close(); +} + +void KasaSmartController::TurnOff(int device_type) +{ + if(!is_initialized) + { + return; + } + + std::string turn_off_command; + if(device_type == DEVICE_TYPE_LIGHT) + { + turn_off_command = KASA_SMART_LIGHT_OFF_COMMAND; + } + else if(device_type == DEVICE_TYPE_LEDSTRIP) + { + turn_off_command = KASA_SMART_LEDSTRIP_OFF_COMMAND; + } if(!port.connected && !port.tcp_client_connect() && ++retry_count >= KASA_SMART_MAX_CONNECTION_ATTEMPTS) { @@ -235,12 +309,12 @@ void KasaSmartController::TurnOff() bool KasaSmartController::SendCommand(std::string command, std::string &response) { const unsigned char* encrypted_payload = KasaSmartController::Encrypt(command); - port.tcp_client_write((char*)encrypted_payload, command.length() + sizeof(unsigned long)); + port.tcp_client_write((char*)encrypted_payload, (int)(command.length() + sizeof(unsigned long))); delete[] encrypted_payload; unsigned char* receive_buffer = new unsigned char[KASA_SMART_RECEIVE_BUFFER_SIZE]; int response_length = port.tcp_listen((char*)receive_buffer, KASA_SMART_RECEIVE_BUFFER_SIZE); - if(response_length > KASA_SMART_RECEIVE_BUFFER_SIZE) { + if(response_length > KASA_SMART_RECEIVE_BUFFER_SIZE || response_length <= 0) { /*-------------------------------------------------------------*\ | Small fail safes to prevent decrypting bad or empty responses | \*-------------------------------------------------------------*/ @@ -251,7 +325,7 @@ bool KasaSmartController::SendCommand(std::string command, std::string &response unsigned long response_full_length = 0; if(response_length > 0) { - response_full_length = ntohl(*(unsigned long*)receive_buffer); + response_full_length = ntohl(*(uint32_t*)receive_buffer); } if(response_full_length > KASA_SMART_RECEIVE_BUFFER_SIZE) { @@ -271,7 +345,7 @@ bool KasaSmartController::SendCommand(std::string command, std::string &response /*------------------------------------------------*\ | Decrypt payload data preceeding the payload size | \*------------------------------------------------*/ - KasaSmartController::Decrypt(receive_buffer + sizeof(unsigned long), received_length - sizeof(unsigned long), response); + KasaSmartController::Decrypt(receive_buffer + sizeof(uint32_t), received_length - sizeof(uint32_t), response); } delete[] receive_buffer; return true; @@ -282,13 +356,13 @@ unsigned char* KasaSmartController::Encrypt(const std::string request) /*----------------------------------------------------------------*\ | "Encrypted" payload consists of size as a uint32 + XOR'd payload | \*----------------------------------------------------------------*/ - unsigned long size = htonl(request.length()); - int payload_size = request.length() + sizeof(size); + uint32_t size = htonl((uint32_t)request.length()); + int payload_size = (int)(request.length() + sizeof(size)); unsigned char* payload = new unsigned char[payload_size]; memcpy(payload, &size, sizeof(size)); unsigned char* request_data = new unsigned char[request.length()]; memcpy(request_data, request.data(), request.length()); - KasaSmartController::XorPayload(request_data, request.length()); + KasaSmartController::XorPayload(request_data, (int)request.length()); memcpy(payload + sizeof(size), request_data, request.length()); delete[] request_data; return payload; diff --git a/Controllers/KasaSmartController/KasaSmartController.h b/Controllers/KasaSmartController/KasaSmartController.h index b97d1dca..7bc72ded 100644 --- a/Controllers/KasaSmartController/KasaSmartController.h +++ b/Controllers/KasaSmartController/KasaSmartController.h @@ -1,22 +1,34 @@ /*---------------------------------------------------------*\ -| Definitions for Kasa Smart | +| KasaSmartController.h | | | -| Devin Wendt (umbreon222@gmail.com), 2/16/2023 | +| Driver for Kasa Smart bulbs | +| | +| Devin Wendt (umbreon222@gmail.com) 16 Feb 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "RGBController.h" -#include "net_port.h" +#pragma once #include #include #include - -#pragma once +#include "RGBController.h" +#include "net_port.h" enum { - KASA_SMART_MODE_DIRECT = 0x00, - KASA_SMART_MODE_OFF = 0x01 + KASA_SMART_MODE_DIRECT = 0x00, + KASA_SMART_MODE_OFF = 0x01, + KASA_SMART_MODE_RAINBOW = 0x02 +}; + +enum +{ + KASA_SMART_TYPE_KL420 = 0x00, + KASA_SMART_TYPE_OTHER_LEDSTRIP = 0x01, + KASA_SMART_TYPE_LIGHT = 0x02 }; #define KASA_SMART_INITIALIZATION_VECTOR 0xAB @@ -27,9 +39,14 @@ enum | Kasa Smart Light Commands | \*-------------------------*/ #define KASA_SMART_SYSTEM_INFO_QUERY "{\"system\": {\"get_sysinfo\": {}}}" -#define KASA_SMART_OFF_COMMAND "{\"smartlife.iot.smartbulb.lightingservice\": {\"transition_light_state\": {\"transition_period\": 0, \"on_off\":0, \"mode\":\"normal\"}}}" -const char KASA_SMART_SET_LIGHT_STATE_COMMAND_FORMAT[] = "{\"smartlife.iot.smartbulb.lightingservice\": {\"transition_light_state\": {\"transition_period\": 0, \"on_off\"" +#define KASA_SMART_LIGHT_OFF_COMMAND "{\"smartlife.iot.smartbulb.lightingservice\": {\"transition_light_state\": {\"transition_period\": 0, \"on_off\":0, \"mode\":\"normal\"}}}" +const char KASA_SMART_LIGHT_SET_LIGHT_STATE_COMMAND_FORMAT[] = "{\"smartlife.iot.smartbulb.lightingservice\": {\"transition_light_state\": {\"transition_period\": 0, \"on_off\"" ":1, \"mode\":\"normal\", \"hue\": %u, \"saturation\": %u, \"brightness\": %u, \"color_temp\": 0}}}"; +#define KASA_SMART_LEDSTRIP_OFF_COMMAND "{\"smartlife.iot.lightStrip\": {\"set_light_state\": {\"transition\": 0, \"on_off\":0, \"mode\":\"normal\"}}}" +const char KASA_SMART_LEDSTRIP_SET_LIGHT_STATE_COMMAND_FORMAT[] = "{\"smartlife.iot.lightStrip\": {\"set_light_state\": {\"transition\": 0, \"on_off\"" + ":1, \"mode\":\"normal\", \"hue\": %u, \"saturation\": %u, \"brightness\": %u, \"color_temp\": 0}}}"; +#define KASA_SMART_EFFECT_RAINBOW_COMMAND "{\"smartlife.iot.lighting_effect\":{\"set_lighting_effect\":{\"custom\":0,\"direction\":1,\"duration\":0,\"enable\":1,\"expansion_strategy\":1,\"name\":\"Rainbow\",\"repeat_times\":0,\"segments\":[0],\"sequence\":[[0,100,100],[100,100,100],[200,100,100],[300,100,100]],\"spread\":12,\"transition\":1500,\"type\":\"sequence\"}}}}" + class KasaSmartController { @@ -42,10 +59,12 @@ public: std::string GetVersion(); std::string GetManufacturer(); std::string GetUniqueID(); + int GetKasaType(); bool Initialize(); - void SetColor(unsigned char red, unsigned char green, unsigned char blue); - void TurnOff(); + void SetColor(unsigned char red, unsigned char green, unsigned char blue, int device_type); + void SetEffect(std::string effect); + void TurnOff(int device_type); private: net_port port; @@ -56,6 +75,7 @@ private: std::string module_name; std::string device_id; std::string location; + int kasa_type; bool SendCommand(std::string command, std::string &response); static unsigned char* Encrypt(const std::string request); static std::string Decrypt(const unsigned char*, int length, std::string &response); diff --git a/Controllers/KasaSmartController/KasaSmartControllerDetect.cpp b/Controllers/KasaSmartController/KasaSmartControllerDetect.cpp index 1d274db6..f5920877 100644 --- a/Controllers/KasaSmartController/KasaSmartControllerDetect.cpp +++ b/Controllers/KasaSmartController/KasaSmartControllerDetect.cpp @@ -1,13 +1,18 @@ +/*---------------------------------------------------------*\ +| KasaSmartControllerDetect.cpp | +| | +| Detector for Kasa Smart bulbs | +| | +| Devin Wendt (umbreon222@gmail.com) 16 Feb 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "KasaSmartController.h" -#include "RGBController.h" #include "RGBController_KasaSmart.h" #include "SettingsManager.h" -#include -#include -#include -#include -#include /******************************************************************************************\ * * diff --git a/Controllers/KasaSmartController/RGBController_KasaSmart.cpp b/Controllers/KasaSmartController/RGBController_KasaSmart.cpp index 462315d8..51565762 100644 --- a/Controllers/KasaSmartController/RGBController_KasaSmart.cpp +++ b/Controllers/KasaSmartController/RGBController_KasaSmart.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_KasaSmart.cpp | -| | -| Generic RGB Interface for KasaSmart | -| | -| Devin Wendt (umbreon222) 2/16/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_KasaSmart.cpp | +| | +| RGBController for Kasa Smart bulbs | +| | +| Devin Wendt (umbreon222) 16 Feb 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_KasaSmart.h" @@ -25,12 +28,21 @@ RGBController_KasaSmart::RGBController_KasaSmart(KasaSmartController* controller name = controller->GetManufacturer() + " " + controller->GetName(); vendor = controller->GetManufacturer(); - type = DEVICE_TYPE_LIGHT; version = controller->GetVersion(); description = "Kasa Smart Device"; serial = controller->GetUniqueID(); location = controller->GetLocation(); + if(controller->GetKasaType() == KASA_SMART_TYPE_LIGHT) + { + type = DEVICE_TYPE_LIGHT; + } + else if(controller->GetKasaType() == KASA_SMART_TYPE_OTHER_LEDSTRIP + || controller->GetKasaType() == KASA_SMART_TYPE_KL420) + { + type = DEVICE_TYPE_LEDSTRIP; + } + mode Direct; Direct.name = "Direct"; Direct.value = KASA_SMART_MODE_DIRECT; @@ -38,6 +50,16 @@ RGBController_KasaSmart::RGBController_KasaSmart(KasaSmartController* controller Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); + if(controller->GetKasaType() == KASA_SMART_TYPE_KL420) + { + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = KASA_SMART_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Rainbow.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Rainbow); + } + mode Off; Off.name = "Off"; Off.value = KASA_SMART_MODE_OFF; @@ -90,7 +112,7 @@ void RGBController_KasaSmart::DeviceUpdateLEDs() unsigned char grn = RGBGetGValue(colors[0]); unsigned char blu = RGBGetBValue(colors[0]); - controller->SetColor(red, grn, blu); + controller->SetColor(red, grn, blu, type); } void RGBController_KasaSmart::UpdateZoneLEDs(int /*zone*/) @@ -105,9 +127,13 @@ void RGBController_KasaSmart::UpdateSingleLED(int /*led*/) void RGBController_KasaSmart::DeviceUpdateMode() { - if(modes[active_mode].value == KASA_SMART_MODE_OFF) + switch(modes[active_mode].value) { - controller->TurnOff(); - return; + case KASA_SMART_MODE_OFF: + controller->TurnOff(type); + break; + case KASA_SMART_MODE_RAINBOW: + controller->SetEffect(KASA_SMART_EFFECT_RAINBOW_COMMAND); + break; } } diff --git a/Controllers/KasaSmartController/RGBController_KasaSmart.h b/Controllers/KasaSmartController/RGBController_KasaSmart.h index 58d71bc2..540228e8 100644 --- a/Controllers/KasaSmartController/RGBController_KasaSmart.h +++ b/Controllers/KasaSmartController/RGBController_KasaSmart.h @@ -1,12 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_KasaSmart.h | -| | -| Generic RGB Interface for Kasa Smart | -| | -| Devin Wendt (umbreon222) 2/16/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_KasaSmart.h | +| | +| RGBController for Kasa Smart bulbs | +| | +| Devin Wendt (umbreon222) 16 Feb 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "KasaSmartController.h" diff --git a/Controllers/KeychronKeyboardController/KeychronKeyboardController.cpp b/Controllers/KeychronKeyboardController/KeychronKeyboardController.cpp index 40fbf9ab..b0f55298 100644 --- a/Controllers/KeychronKeyboardController/KeychronKeyboardController.cpp +++ b/Controllers/KeychronKeyboardController/KeychronKeyboardController.cpp @@ -1,34 +1,25 @@ -/*-----------------------------------------*\ -| KeychronKeyboardController.cpp | -| | -| Driver for Keychron Keyboard lighting | -| controller | -| | -| Guimard Morgan (morg) 2/20/2022 | -\*-----------------------------------------*/ -#include "KeychronKeyboardController.h" +/*---------------------------------------------------------*\ +| KeychronKeyboardController.cpp | +| | +| Driver for Keychron keyboard | +| | +| Morgan Guimard (morg) 20 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include +#include "KeychronKeyboardController.h" +#include "StringUtils.h" using namespace std::chrono_literals; -KeychronKeyboardController::KeychronKeyboardController(hid_device* dev_handle, const hid_device_info& info) +KeychronKeyboardController::KeychronKeyboardController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) { dev = dev_handle; - version = ""; location = info.path; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } + name = dev_name; } KeychronKeyboardController::~KeychronKeyboardController() @@ -41,14 +32,22 @@ std::string KeychronKeyboardController::GetDeviceLocation() return("HID: " + location); } -std::string KeychronKeyboardController::GetSerialString() +std::string KeychronKeyboardController::GetNameString() { - return(serial_number); + return(name); } -std::string KeychronKeyboardController::GetFirmwareVersion() +std::string KeychronKeyboardController::GetSerialString() { - return(version); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } void KeychronKeyboardController:: SetLedSequencePositions(std::vector positions) diff --git a/Controllers/KeychronKeyboardController/KeychronKeyboardController.h b/Controllers/KeychronKeyboardController/KeychronKeyboardController.h index 42e956fb..32802221 100644 --- a/Controllers/KeychronKeyboardController/KeychronKeyboardController.h +++ b/Controllers/KeychronKeyboardController/KeychronKeyboardController.h @@ -1,16 +1,19 @@ -/*-----------------------------------------*\ -| KeychronKeyboardController.h | -| | -| Driver for Keychron Keyboard lighting | -| controller - header file | -| | -| Guimard Morgan (morg) 2/20/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| KeychronKeyboardController.h | +| | +| Driver for Keychron keyboard | +| | +| Morgan Guimard (morg) 20 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include "RGBController.h" #include -#include +#include #define REPORT_ID 0x00 #define PACKET_DATA_LENGTH 64 @@ -88,12 +91,12 @@ enum class KeychronKeyboardController { public: - KeychronKeyboardController(hid_device* dev_handle, const hid_device_info& info); + KeychronKeyboardController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); ~KeychronKeyboardController(); - std::string GetSerialString(); std::string GetDeviceLocation(); - std::string GetFirmwareVersion(); + std::string GetNameString(); + std::string GetSerialString(); void SetLedSequencePositions(std::vector positions); void SetMode(std::vector modes, int active_mode, std::vector colors); @@ -103,8 +106,8 @@ protected: private: std::string location; - std::string serial_number; - std::string version; + std::string name; + std::string version; std::vector led_sequence_positions; void SetCustomization(bool state); diff --git a/Controllers/KeychronKeyboardController/KeychronKeyboardControllerDetect.cpp b/Controllers/KeychronKeyboardController/KeychronKeyboardControllerDetect.cpp index 6f561d7f..75b0abc4 100644 --- a/Controllers/KeychronKeyboardController/KeychronKeyboardControllerDetect.cpp +++ b/Controllers/KeychronKeyboardController/KeychronKeyboardControllerDetect.cpp @@ -1,6 +1,16 @@ +/*---------------------------------------------------------*\ +| KeychronKeyboardControllerDetect.cpp | +| | +| Detector for Keychron keyboard | +| | +| Morgan Guimard (morg) 20 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "KeychronKeyboardController.h" -#include "RGBController.h" #include "RGBController_KeychronKeyboard.h" /*---------------------------------------------------------*\ @@ -19,9 +29,9 @@ void DetectKeychronKeyboardControllers(hid_device_info* info, const std::string& if(dev) { - KeychronKeyboardController* controller = new KeychronKeyboardController(dev, *info); + KeychronKeyboardController* controller = new KeychronKeyboardController(dev, *info, name); RGBController_KeychronKeyboard* rgb_controller = new RGBController_KeychronKeyboard(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } diff --git a/Controllers/KeychronKeyboardController/RGBController_KeychronKeyboard.cpp b/Controllers/KeychronKeyboardController/RGBController_KeychronKeyboard.cpp index f1d85f56..d914a165 100644 --- a/Controllers/KeychronKeyboardController/RGBController_KeychronKeyboard.cpp +++ b/Controllers/KeychronKeyboardController/RGBController_KeychronKeyboard.cpp @@ -1,17 +1,19 @@ -/*-----------------------------------------*\ -| RGBController_KeychronKeyboard.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Keychron Keyboard USB Driver | -| | -| Guimard Morgan (morg) 2/20/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_KeychronKeyboard.cpp | +| | +| RGBController for Keychron keyboard | +| | +| Morgan Guimard (morg) 20 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include #include "RGBControllerKeyNames.h" #include "RGBController_KeychronKeyboard.h" -#include -#include - #define NA 0xFFFFFFFF typedef struct @@ -428,13 +430,13 @@ typedef struct RGBController_KeychronKeyboard::RGBController_KeychronKeyboard(KeychronKeyboardController* controller_ptr) { controller = controller_ptr; - name = "Keychron Keyboard"; + + name = controller->GetNameString(); vendor = "Keychron"; type = DEVICE_TYPE_KEYBOARD; description = name; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); mode Custom; Custom.name = "Custom"; diff --git a/Controllers/KeychronKeyboardController/RGBController_KeychronKeyboard.h b/Controllers/KeychronKeyboardController/RGBController_KeychronKeyboard.h index 521af088..42b66a1d 100644 --- a/Controllers/KeychronKeyboardController/RGBController_KeychronKeyboard.h +++ b/Controllers/KeychronKeyboardController/RGBController_KeychronKeyboard.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_KeychronKeyboard.h | -| | -| Generic RGB Interface for OpenRGB | -| Keychron Keyboard RGB USB Driver | -| | -| Guimard Morgan (morg) 2/20/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_KeychronKeyboard.h | +| | +| RGBController for Keychron keyboard | +| | +| Morgan Guimard (morg) 20 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/KingstonFuryDRAMController/KingstonFuryDRAMController.cpp b/Controllers/KingstonFuryDRAMController/KingstonFuryDRAMController.cpp new file mode 100644 index 00000000..a48f84bd --- /dev/null +++ b/Controllers/KingstonFuryDRAMController/KingstonFuryDRAMController.cpp @@ -0,0 +1,356 @@ +/*---------------------------------------------------------*\ +| KingstonFuryDRAMController.cpp | +| | +| Driver for Kingston Fury DDR4/5 RAM modules | +| | +| Geofrey Mon (geofbot) 14 Jul 2024 | +| Milan Cermak (krysmanta) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "KingstonFuryDRAMController.h" +#include "RGBController.h" +#include "LogManager.h" + +KingstonFuryDRAMController::KingstonFuryDRAMController(i2c_smbus_interface* bus, unsigned char base_addr, std::vector slots, std::string dev_name) +{ + this->bus = bus; + this->base_addr = base_addr; + this->slots = slots; + this->name = dev_name; + + reg_cache.resize(slots.size()); +} + +std::string KingstonFuryDRAMController::GetDeviceLocation() +{ + std::string return_string(bus->device_name); + return_string.append(", addresses ["); + for(std::size_t idx = 0; idx < slots.size(); idx++) + { + char addr[5]; + snprintf(addr, 5, "0x%02X", base_addr + slots[idx]); + return_string.append(addr); + if(idx < slots.size() - 1) + { + return_string.append(","); + } + else + { + return_string.append("]"); + } + } + return("I2C: " + return_string); +} + +std::string KingstonFuryDRAMController::GetDeviceName() +{ + return(name); +} + +unsigned int KingstonFuryDRAMController::GetLEDCount() +{ + return(GetLEDPerDIMM() * (unsigned int)slots.size()); +} + +unsigned int KingstonFuryDRAMController::GetSlotCount() +{ + return((unsigned int)slots.size()); +} + +unsigned char KingstonFuryDRAMController::GetMode() +{ + unsigned char mode = 0; + CachedRead(0, FURY_REG_MODE, &mode); + return mode; +} + +bool KingstonFuryDRAMController::SmbusRead(int slot_idx, unsigned char reg, unsigned char *val) +{ + if(val == NULL) + { + return false; + } + + unsigned char device_addr = base_addr + slots[slot_idx]; + int res; + + for(int retries = 1; retries <= 5; retries++) + { + res = bus->i2c_smbus_read_word_data(device_addr, reg); + if(res >= 0) + { + *val = (res >> 8) & 0xFF; + LOG_DEBUG("[%s] %02X reading register &%02X=%02X; res=%02X", + FURY_CONTROLLER_NAME, device_addr, reg, *val, res); + return true; + } + else + { + std::this_thread::sleep_for(3 * retries * FURY_DELAY); + } + } + return false; +} + +bool KingstonFuryDRAMController::SmbusWrite(int slot_idx, unsigned char reg, unsigned char val) +{ + unsigned char device_addr = base_addr + slots[slot_idx]; + int res; + + for(int retries = 1; retries <= 5; retries++) + { + res = bus->i2c_smbus_write_byte_data(device_addr, + reg, val); + LOG_DEBUG("[%s] %02X setting register &%02X=%02X; res=%02X", + FURY_CONTROLLER_NAME, device_addr, reg, val, res); + if(res >= 0) + { + return true; + } + else + { + std::this_thread::sleep_for(3 * retries * FURY_DELAY); + } + } + return false; +} + +// returns whether a read was successful +bool KingstonFuryDRAMController::CachedRead(int slot_idx, unsigned char reg, unsigned char *val) +{ + if(val == NULL) + { + return false; + } + + unsigned char device_addr = base_addr + slots[slot_idx]; + if(reg_cache[slot_idx].find(reg) == reg_cache[slot_idx].end()) + { + if(SmbusRead(slot_idx, reg, val)) + { + reg_cache[slot_idx][reg] = *val; + return true; + } + LOG_ERROR("[%s] %02X failed to get register &%02X", + FURY_CONTROLLER_NAME, device_addr, reg); + return false; + } + else + { + *val = reg_cache[slot_idx][reg]; + return true; + } +} + +// returns whether a write was actually performed +bool KingstonFuryDRAMController::CachedWrite(int slot_idx, unsigned char reg, unsigned char val) +{ + unsigned char device_addr = base_addr + slots[slot_idx]; + if(reg_cache[slot_idx].find(reg) == reg_cache[slot_idx].end() || + reg_cache[slot_idx][reg] != val) + { + if(SmbusWrite(slot_idx, reg, val)) + { + reg_cache[slot_idx][reg] = val; + return true; + } + LOG_ERROR("[%s] %02X failed to set register &%02X=%02X", + FURY_CONTROLLER_NAME, device_addr, reg, val); + return false; + } + else + { + LOG_DEBUG("[%s] %02X register already set &%02X=%02X", + FURY_CONTROLLER_NAME, device_addr, reg, val); + return false; + } +} + +void KingstonFuryDRAMController::SendPreamble(bool /*synchronize*/) +{ + SendBegin(); + + for(std::size_t idx = 0; idx < slots.size(); idx++) + { + char written_index = 0; +#ifdef FURY_SYNC + if(!synchronize) + { + // some modes set all indices to 0 so that the + // individual sticks don't sync with each other + written_index = 0; + } + else + { + /*--------------------------------------------------------------*\ + | The index tells physical location of the RAM slot | + | from the border to the CPU slot. On most motherboards, | + | the address relates to the slot location, | + | but there are exceptions. | + | The official software writes the indices in decreasing order. | + | | + | Hardware effects seem to support only up to 4 sticks. | + | So we give the first 4 and last 4 sticks separate numbering. | + \*--------------------------------------------------------------*/ + written_index = idx % 4; + } +#endif + LOG_DEBUG("[%s] %02X writing index %d", + FURY_CONTROLLER_NAME, base_addr + slots[idx], + written_index); + SmbusWrite((int)idx, FURY_REG_INDEX, written_index); + } + // The RGB controller is a bit slow and requires delay; + // however, we can delay once for all of the sticks instead of + // delaying individually for each stick. + std::this_thread::sleep_for(FURY_DELAY); + + SendApply(); +} + +void KingstonFuryDRAMController::SendBegin() +{ + for(std::size_t idx = 0; idx < slots.size(); idx++) + { + LOG_DEBUG("[%s] %02X beginning transaction", + FURY_CONTROLLER_NAME, base_addr + slots[idx]); + SmbusWrite((int)idx, FURY_REG_APPLY, FURY_BEGIN_TRNSFER); + } + std::this_thread::sleep_for(FURY_DELAY); +} + +void KingstonFuryDRAMController::SendApply() +{ + for(std::size_t idx = 0; idx < slots.size(); idx++) + { + LOG_DEBUG("[%s] %02X ending transaction", + FURY_CONTROLLER_NAME, base_addr + slots[idx]); + SmbusWrite((int)idx, FURY_REG_APPLY, FURY_END_TRNSFER); + } + std::this_thread::sleep_for(FURY_DELAY); +} + +void KingstonFuryDRAMController::SetMode(unsigned char val) +{ + SetRegister(FURY_REG_MODE, val); +} + +void KingstonFuryDRAMController::SetNumSlots() +{ + if(slots.size() <= 4) + { + SetRegister(FURY_REG_NUM_SLOTS, (unsigned char)slots.size()); + } + else + { + // hardware effects seem to only support at most 4 slots; + // if there are >= 4 slots, then essentially the first 4 slots + // run their effects independent of the last 4 slots + SetRegister(FURY_REG_NUM_SLOTS, 4); + } +} + +void KingstonFuryDRAMController::SetRegister(int reg, unsigned char val) +{ + bool write_occurred = false; + for(std::size_t idx = 0; idx < slots.size(); idx++) + { + write_occurred = CachedWrite((int)idx, reg, val) || write_occurred; + } + if(write_occurred) + { + std::this_thread::sleep_for(FURY_DELAY); + } +} + +void KingstonFuryDRAMController::SetRegister(int reg, std::vector vals) +{ + bool write_occurred = false; + if(vals.size() < slots.size()) + { + LOG_ERROR("[%s] vector of values has wrong size when setting register &%02X", + FURY_CONTROLLER_NAME, reg); + return; + } + for(std::size_t idx = 0; idx < slots.size(); idx++) + { + write_occurred = CachedWrite((int)idx, reg, vals[idx]) || write_occurred; + } + if(write_occurred) + { + std::this_thread::sleep_for(FURY_DELAY); + } +} + +void KingstonFuryDRAMController::SetModeColors(std::vector colors) +{ + if(colors.empty() || (colors.size() > FURY_MAX_MODE_COLORS)) + { + return; + } + + SetRegister(FURY_REG_NUM_COLORS, (unsigned char)colors.size()); + + for(std::size_t idx = 0; idx < colors.size(); idx++) + { + RGBColor color = colors[idx]; + unsigned char red = RGBGetRValue(color); + unsigned char green = RGBGetGValue(color); + unsigned char blue = RGBGetBValue(color); + + int red_idx = FURY_REG_MODE_BASE_RED + (int)idx * 3; + int green_idx = FURY_REG_MODE_BASE_GREEN + (int)idx * 3; + int blue_idx = FURY_REG_MODE_BASE_BLUE + (int)idx * 3; + + SetRegister(red_idx, red); + SetRegister(green_idx, green); + SetRegister(blue_idx, blue); + } +} + +void KingstonFuryDRAMController::SetLEDColors(std::vector colors) +{ + if(colors.size() != GetLEDCount()) + { + return; + } + + unsigned int led_per_dimm = GetLEDPerDIMM(); + for(unsigned int led_idx = 0; led_idx < led_per_dimm; led_idx++) + { + int red_register = FURY_REG_BASE_RED + 3 * led_idx; + int green_register = FURY_REG_BASE_GREEN + 3 * led_idx; + int blue_register = FURY_REG_BASE_BLUE + 3 * led_idx; + + std::vector reds, greens, blues; + for(std::size_t slot_idx = 0; slot_idx < GetSlotCount(); slot_idx++) + { + RGBColor color = colors[slot_idx * led_per_dimm + led_idx]; + unsigned char red = RGBGetRValue(color); + unsigned char green = RGBGetGValue(color); + unsigned char blue = RGBGetBValue(color); + + reds.push_back(red); + greens.push_back(green); + blues.push_back(blue); + } + + SetRegister(red_register, reds); + SetRegister(blue_register, blues); + SetRegister(green_register, greens); + } +} + +unsigned int KingstonFuryDRAMController::GetLEDPerDIMM() +{ + if(base_addr == FURY_BASE_ADDR_DDR4) + { + return(FURY_LEDS_PER_DIMM_DDR4); + } + return(FURY_LEDS_PER_DIMM_DDR5); +} diff --git a/Controllers/KingstonFuryDRAMController/KingstonFuryDRAMController.h b/Controllers/KingstonFuryDRAMController/KingstonFuryDRAMController.h new file mode 100644 index 00000000..6f4bfc8b --- /dev/null +++ b/Controllers/KingstonFuryDRAMController/KingstonFuryDRAMController.h @@ -0,0 +1,159 @@ +/*---------------------------------------------------------*\ +| KingstonFuryDRAMController.h | +| | +| Driver for Kingston Fury DDR4/5 RAM modules | +| | +| Geofrey Mon (geofbot) 14 Jul 2024 | +| Milan Cermak (krysmanta) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "i2c_smbus.h" +#include "RGBController.h" + +#define FURY_CONTROLLER_NAME "Kingston Fury DDR4/5 DRAM" +#define FURY_BASE_ADDR_DDR4 0x58 +#define FURY_BASE_ADDR_DDR5 0x60 +#define FURY_DELAY std::chrono::milliseconds(10) +#define FURY_LEDS_PER_DIMM_DDR4 10 +#define FURY_LEDS_PER_DIMM_DDR5 12 +#define FURY_MAX_MODE_COLORS 10 +#define FURY_DEFAULT_BG_COLOR ToRGBColor(16,16,16) +#define FURY_ALT_DIRECTIONS {\ + FURY_DIR_BOTTOM_TO_TOP,\ + FURY_DIR_TOP_TO_BOTTOM,\ + FURY_DIR_BOTTOM_TO_TOP,\ + FURY_DIR_TOP_TO_BOTTOM,\ + FURY_DIR_BOTTOM_TO_TOP,\ + FURY_DIR_TOP_TO_BOTTOM,\ + FURY_DIR_BOTTOM_TO_TOP,\ + FURY_DIR_TOP_TO_BOTTOM} + +enum +{ + FURY_MODEL_BEAST_DDR5 = 0x10, + FURY_MODEL_RENEGADE_DDR5 = 0x11, + FURY_MODEL_BEAST_RGB_WHITE_DDR5 = 0x12, + FURY_MODEL_BEAST2_DDR5 = 0x15, + FURY_MODEL_BEAST_WHITE_DDR4 = 0x21, + FURY_MODEL_BEAST_DDR4 = 0x23, +}; + +enum +{ + FURY_REG_MODEL = 0x06, + FURY_REG_APPLY = 0x08, + FURY_REG_MODE = 0x09, + FURY_REG_INDEX = 0x0B, + FURY_REG_DIRECTION = 0x0C, + FURY_REG_DELAY = 0x0D, + FURY_REG_SPEED = 0x0E, + FURY_REG_DYNAMIC_HOLD_A = 0x12, + FURY_REG_DYNAMIC_HOLD_B = 0x13, + FURY_REG_DYNAMIC_FADE_A = 0x14, + FURY_REG_DYNAMIC_FADE_B = 0x15, + FURY_REG_BREATH_MIN_TO_MID = 0x16, + FURY_REG_BREATH_MID_TO_MAX = 0x17, + FURY_REG_BREATH_MAX_TO_MID = 0x18, + FURY_REG_BREATH_MID_TO_MIN = 0x19, + FURY_REG_BREATH_MIN_HOLD = 0x1A, + FURY_REG_BREATH_MAX_BRIGHTNESS = 0x1B, + FURY_REG_BREATH_MID_BRIGHTNESS = 0x1C, + FURY_REG_BREATH_MIN_BRIGHTNESS = 0x1D, + FURY_REG_BRIGHTNESS = 0x20, + FURY_REG_BG_RED = 0x23, + FURY_REG_BG_GREEN = 0x24, + FURY_REG_BG_BLUE = 0x25, + FURY_REG_LENGTH = 0x26, + FURY_REG_NUM_SLOTS = 0x27, + FURY_REG_NUM_COLORS = 0x30, + FURY_REG_MODE_BASE_RED = 0x31, + FURY_REG_MODE_BASE_GREEN = 0x32, + FURY_REG_MODE_BASE_BLUE = 0x33, + FURY_REG_BASE_RED = 0x50, + FURY_REG_BASE_GREEN = 0x51, + FURY_REG_BASE_BLUE = 0x52, +}; + +enum +{ + FURY_BEGIN_TRNSFER = 0x53, + FURY_END_TRNSFER = 0x44, +}; + +// Differentiate modes which use the same written value using the upper bytes. +// The lowest order byte is generally the value written to the mode register. +enum +{ + FURY_MODE_STATIC = 0x00, + FURY_MODE_RAINBOW = 0x001, + FURY_MODE_SPECTRUM = 0x101, + FURY_MODE_RHYTHM = 0x02, + FURY_MODE_BREATH = 0x03, + FURY_MODE_DYNAMIC = 0x04, + FURY_MODE_SLIDE = 0x005, + FURY_MODE_SLITHER = 0x105, + FURY_MODE_TELEPORT = 0x205, + FURY_MODE_WIND = 0x305, + FURY_MODE_COMET = 0x006, + FURY_MODE_RAIN = 0x106, + FURY_MODE_FIREWORK = 0x206, + FURY_MODE_VOLTAGE = 0x07, + FURY_MODE_COUNTDOWN = 0x08, + FURY_MODE_FLAME = 0x09, + FURY_MODE_TWILIGHT = 0x0A, + FURY_MODE_FURY = 0x0B, + FURY_MODE_DIRECT = 0x10, + FURY_MODE_PRISM = 0x11, + FURY_MODE_BREATH_DIRECT = 0x13, +}; + +enum +{ + FURY_DIR_BOTTOM_TO_TOP = 0x01, + FURY_DIR_TOP_TO_BOTTOM = 0x02, +}; + +class KingstonFuryDRAMController +{ +public: + KingstonFuryDRAMController(i2c_smbus_interface* bus, unsigned char base_addr, std::vector slots, std::string dev_name); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + + unsigned int GetLEDCount(); + unsigned int GetLEDPerDIMM(); + unsigned int GetSlotCount(); + unsigned char GetMode(); + + void SendPreamble(bool synchronize); + void SendBegin(); + void SendApply(); + void SetMode(unsigned char val); + void SetNumSlots(); + + void SetRegister(int reg, unsigned char val); + void SetRegister(int reg, std::vector vals); + void SetModeColors(std::vector colors); + void SetLEDColors(std::vector colors); + +private: + bool CachedRead(int slot_idx, unsigned char reg, unsigned char *val); + bool CachedWrite(int slot_idx, unsigned char reg, unsigned char val); + bool SmbusRead(int slot_idx, unsigned char reg, unsigned char *val); + bool SmbusWrite(int slot_idx, unsigned char reg, unsigned char val); + + i2c_smbus_interface* bus; + std::vector slots; + unsigned char base_addr; + std::string name; + std::vector> reg_cache; +}; diff --git a/Controllers/KingstonFuryDRAMController/KingstonFuryDRAMControllerDetect.cpp b/Controllers/KingstonFuryDRAMController/KingstonFuryDRAMControllerDetect.cpp new file mode 100644 index 00000000..667ae490 --- /dev/null +++ b/Controllers/KingstonFuryDRAMController/KingstonFuryDRAMControllerDetect.cpp @@ -0,0 +1,201 @@ +/*---------------------------------------------------------*\ +| KingstonFuryDRAMControllerDetect.cpp | +| | +| Detection of Kingston Fury DDR4/5 RAM modules | +| | +| Geofrey Mon (geofbot) 14 Jul 2024 | +| Milan Cermak (krysmanta) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "KingstonFuryDRAMController.h" +#include "LogManager.h" +#include "RGBController_KingstonFuryDRAM.h" +#include "i2c_smbus.h" +#include "pci_ids.h" + +using namespace std::chrono_literals; + +typedef enum +{ + RESULT_PASS = 0, + RESULT_FAIL = 1, + RESULT_ERROR = 2 +} TestResult; + +bool TestDDR4Models(char code) +{ + return (code == FURY_MODEL_BEAST_WHITE_DDR4 || + code == FURY_MODEL_BEAST_DDR4); +} + +bool TestDDR5Models(char code) +{ + return (code == FURY_MODEL_BEAST_DDR5 || + code == FURY_MODEL_BEAST2_DDR5 || + code == FURY_MODEL_RENEGADE_DDR5 || + code == FURY_MODEL_BEAST_RGB_WHITE_DDR5); +} + +// Checking Fury signature in the RGB address space +TestResult TestForFurySignature(i2c_smbus_interface *bus, unsigned int slot_addr, bool (*modelChecker)(char)) +{ + bool passed = true; + char test_str[] = "FURY"; + int res; + + LOG_DEBUG("[%s] looking at 0x%02X", + FURY_CONTROLLER_NAME, slot_addr); + + // Start transaction + res = bus->i2c_smbus_write_byte_data(slot_addr, FURY_REG_APPLY, FURY_BEGIN_TRNSFER); + if(res < 0) + { + LOG_DEBUG("[%s] DIMM not present at 0x%02X", + FURY_CONTROLLER_NAME, slot_addr); + return RESULT_ERROR; + } + + std::this_thread::sleep_for(FURY_DELAY); + LOG_DEBUG("[%s] %02X beginning transaction; res=%02X", + FURY_CONTROLLER_NAME, slot_addr, res); + + // Read and check the signature + for(int i = 1; i <= 4; i++) + { + for(int retry = 3; retry > 0; retry--) + { + res = bus->i2c_smbus_read_word_data(slot_addr, i); + std::this_thread::sleep_for(FURY_DELAY); + LOG_DEBUG("[%s] Testing address %02X register %02X, res=%04X", + FURY_CONTROLLER_NAME, slot_addr, i, res); + // retry when there is an error or the returned value is 0xFFFF + if((res >= 0) && (res < 0xFFFF)) + { + break; + } + } + if(res < 0) + { + return RESULT_ERROR; + } + + char shifted = (res >> 8) & 0xFF; + if(shifted != test_str[i-1]) + { + passed = false; + break; + } + } + + if(passed) + { + // Get the model code + res = bus->i2c_smbus_read_word_data(slot_addr, FURY_REG_MODEL); + int model_code = res >> 8; + std::this_thread::sleep_for(FURY_DELAY); + LOG_DEBUG("[%s] Reading model code at address %02X register %02X, res=%02X", + FURY_CONTROLLER_NAME, slot_addr, FURY_REG_MODEL, res); + + if(!modelChecker(model_code)) + { + LOG_INFO("[%s] Unknown model code 0x%02X", FURY_CONTROLLER_NAME, model_code); + passed = false; + } + } + + // Close transaction + res = bus->i2c_smbus_write_byte_data(slot_addr, FURY_REG_APPLY, FURY_END_TRNSFER); + if(res < 0) + { + return RESULT_ERROR; + } + std::this_thread::sleep_for(FURY_DELAY); + LOG_DEBUG("[%s] %02X ending transaction; res=%02X", + FURY_CONTROLLER_NAME, slot_addr, res); + + return passed ? RESULT_PASS : RESULT_FAIL; +} + +void DetectKingstonFuryDRAMControllers(i2c_smbus_interface* bus, std::vector &slots, + uint8_t fury_base_addr, bool (*modelChecker)(char), std::vector &fury_slots) +{ + // Are these the Kingston Fury DRAMs + for(SPDWrapper *slot : slots) + { + TestResult result; + int retries = 0; + + result = RESULT_ERROR; + while(retries < 3 && result == RESULT_ERROR) + { + result = TestForFurySignature(bus, fury_base_addr + slot->index(), modelChecker); + if(result == RESULT_PASS) + { + break; + } + if(result == RESULT_ERROR) + { + // I/O error - wait for a bit and retry + retries++; + std::this_thread::sleep_for(FURY_DELAY); + } + } + + // RAM module successfully detected in the slot 'slot_index' + if(result == RESULT_PASS) + { + LOG_DEBUG("[%s] detected at slot index %d", + FURY_CONTROLLER_NAME, slot->index()); + fury_slots.push_back(slot->index()); + } + } +} + +/******************************************************************************************\ +* * +* DetectKingstonFuryDRAMControllers * +* * +* Detect Kingston Fury DDR4/5 DRAM controllers on the enumerated I2C busses. * +* * +\******************************************************************************************/ + +void DetectKingstonFuryDDR4Controllers(i2c_smbus_interface* bus, std::vector &slots, const std::string &name) +{ + std::vector fury_slots; + + DetectKingstonFuryDRAMControllers(bus, slots, FURY_BASE_ADDR_DDR4, TestDDR4Models, fury_slots); + + if(!fury_slots.empty()) + { + KingstonFuryDRAMController* controller = new KingstonFuryDRAMController(bus, FURY_BASE_ADDR_DDR4, fury_slots, name); + RGBController_KingstonFuryDRAM* rgb_controller = new RGBController_KingstonFuryDRAM(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectKingstonFuryDDR5Controllers(i2c_smbus_interface* bus, std::vector &slots, const std::string &name) +{ + std::vector fury_slots; + + DetectKingstonFuryDRAMControllers(bus, slots, FURY_BASE_ADDR_DDR5, TestDDR5Models, fury_slots); + + if(!fury_slots.empty()) + { + KingstonFuryDRAMController* controller = new KingstonFuryDRAMController(bus, FURY_BASE_ADDR_DDR5, fury_slots, name); + RGBController_KingstonFuryDRAM* rgb_controller = new RGBController_KingstonFuryDRAM(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_I2C_DIMM_DETECTOR("Kingston Fury DDR4 DRAM", DetectKingstonFuryDDR4Controllers, JEDEC_KINGSTON, SPD_DDR4_SDRAM); +REGISTER_I2C_DIMM_DETECTOR("Kingston Fury DDR4 DRAM", DetectKingstonFuryDDR4Controllers, JEDEC_KINGSTON_2, SPD_DDR4_SDRAM); +REGISTER_I2C_DIMM_DETECTOR("Kingston Fury DDR5 DRAM", DetectKingstonFuryDDR5Controllers, JEDEC_KINGSTON, SPD_DDR5_SDRAM); +REGISTER_I2C_DIMM_DETECTOR("Kingston Fury DDR5 DRAM", DetectKingstonFuryDDR5Controllers, JEDEC_KINGSTON_2, SPD_DDR5_SDRAM); +REGISTER_I2C_DIMM_DETECTOR("Kingston Fury DDR5 DRAM", DetectKingstonFuryDDR5Controllers, JEDEC_KINGSTON_3, SPD_DDR5_SDRAM); diff --git a/Controllers/KingstonFuryDRAMController/RGBController_KingstonFuryDRAM.cpp b/Controllers/KingstonFuryDRAMController/RGBController_KingstonFuryDRAM.cpp new file mode 100644 index 00000000..02da5f4a --- /dev/null +++ b/Controllers/KingstonFuryDRAMController/RGBController_KingstonFuryDRAM.cpp @@ -0,0 +1,723 @@ +/*---------------------------------------------------------*\ +| RGBController_KingstonFuryDRAM.cpp | +| | +| Driver for Kingston Fury DDR4/5 RAM modules | +| | +| Geofrey Mon (geofbot) 14 Jul 2024 | +| Milan Cermak (krysmanta) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_KingstonFuryDRAM.h" +#include "KingstonFuryDRAMController.h" +#include "LogManager.h" + +const RGBColor default_colors[] = +{ + ToRGBColor(0xFF, 0x00, 0x00), + ToRGBColor(0x00, 0xFF, 0x00), + ToRGBColor(0xFF, 0x64, 0x00), + ToRGBColor(0x00, 0x00, 0xFF), + ToRGBColor(0xEF, 0xEF, 0x00), + ToRGBColor(0x80, 0x00, 0x80), + ToRGBColor(0x00, 0x6D, 0x77), + ToRGBColor(0xFF, 0xC8, 0x00), + ToRGBColor(0xFF, 0x55, 0xFF), + ToRGBColor(0x3C, 0x7D, 0xFF), +}; + + +/**------------------------------------------------------------------*\ + @name Kingston Fury DDR4/5 DRAM + @category RAM + @type SMBus + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectKingstonFuryDRAMControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_KingstonFuryDRAM::RGBController_KingstonFuryDRAM(KingstonFuryDRAMController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "Kingston"; + type = DEVICE_TYPE_DRAM; + description = "Kingston Fury Beast/Renegade DDR4/5 DRAM Device"; + location = controller->GetDeviceLocation(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = FURY_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = 0; + Direct.brightness_max = 100; + Direct.brightness = 80; + modes.push_back(Direct); + + mode Static; + Static.name = "Static"; + Static.value = FURY_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.assign(default_colors, default_colors + 1); + Static.brightness_min = 0; + Static.brightness_max = 100; + Static.brightness = 80; + modes.push_back(Static); + + // All speed values are inverted + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = FURY_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_UD; + Rainbow.speed_min = 60; + Rainbow.speed_max = 0; + Rainbow.speed = 25; + Rainbow.direction = MODE_DIRECTION_UP; + Rainbow.brightness_min = 0; + Rainbow.brightness_max = 100; + Rainbow.brightness = 80; + Rainbow.color_mode = MODE_COLORS_NONE; + modes.push_back(Rainbow); + + mode Spectrum; + Spectrum.name = "Spectrum"; + Spectrum.value = FURY_MODE_SPECTRUM; + Spectrum.flags = MODE_FLAG_HAS_SPEED | + MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_UD; + Spectrum.speed_min = 60; + Spectrum.speed_max = 0; + Spectrum.speed = 25; + Spectrum.direction = MODE_DIRECTION_UP; + Spectrum.brightness_min = 0; + Spectrum.brightness_max = 100; + Spectrum.brightness = 80; + Spectrum.color_mode = MODE_COLORS_NONE; + modes.push_back(Spectrum); + + mode Rhythm; + Rhythm.name = "Rhythm"; + Rhythm.value = FURY_MODE_RHYTHM; + Rhythm.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Rhythm.color_mode = MODE_COLORS_MODE_SPECIFIC; + Rhythm.colors_min = 2; + Rhythm.colors_max = 11; + Rhythm.colors.assign(default_colors, default_colors + 10); + Rhythm.colors.push_back(FURY_DEFAULT_BG_COLOR); + Rhythm.speed_min = 10; + Rhythm.speed_max = 0; + Rhythm.speed = 0; + Rhythm.brightness_min = 0; + Rhythm.brightness_max = 100; + Rhythm.brightness = 80; + modes.push_back(Rhythm); + + mode Breath; + Breath.name = "Breath"; + Breath.value = FURY_MODE_BREATH; + Breath.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Breath.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breath.colors_min = 1; + Breath.colors_max = 10; + Breath.colors.assign(default_colors, default_colors + 10); + Breath.speed_min = 10; + Breath.speed_max = 1; + Breath.speed = 5; + Breath.brightness_min = 0; + Breath.brightness_max = 100; + Breath.brightness = 80; + modes.push_back(Breath); + + mode Dynamic; + Dynamic.name = "Dynamic"; + Dynamic.value = FURY_MODE_DYNAMIC; + Dynamic.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Dynamic.color_mode = MODE_COLORS_MODE_SPECIFIC; + Dynamic.colors_min = 1; + Dynamic.colors_max = 10; + Dynamic.colors.assign(default_colors, default_colors + 10); + Dynamic.speed_min = 1000; + Dynamic.speed_max = 100; + Dynamic.speed = 300; + Dynamic.brightness_min = 0; + Dynamic.brightness_max = 100; + Dynamic.brightness = 80; + modes.push_back(Dynamic); + + mode Slide; + Slide.name = "Slide"; + Slide.value = FURY_MODE_SLIDE; + Slide.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_UD; + Slide.color_mode = MODE_COLORS_MODE_SPECIFIC; + Slide.colors_min = 2; + Slide.colors_max = 11; + Slide.colors.assign(default_colors, default_colors + 10); + Slide.colors.push_back(FURY_DEFAULT_BG_COLOR); + Slide.speed_min = 255; + Slide.speed_max = 0; + Slide.speed = 8; + Slide.direction = MODE_DIRECTION_UP; + Slide.brightness_min = 0; + Slide.brightness_max = 100; + Slide.brightness = 80; + modes.push_back(Slide); + + mode Slither; + Slither.name = "Slither"; + Slither.value = FURY_MODE_SLITHER; + Slither.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Slither.color_mode = MODE_COLORS_MODE_SPECIFIC; + Slither.colors_min = 2; + Slither.colors_max = 11; + Slither.colors.assign(default_colors, default_colors + 10); + Slither.colors.push_back(FURY_DEFAULT_BG_COLOR); + Slither.speed_min = 255; + Slither.speed_max = 0; + Slither.speed = 40; + Slither.brightness_min = 0; + Slither.brightness_max = 100; + Slither.brightness = 80; + modes.push_back(Slither); + + mode Teleport; + Teleport.name = "Teleport"; + Teleport.value = FURY_MODE_TELEPORT; + Teleport.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Teleport.color_mode = MODE_COLORS_MODE_SPECIFIC; + Teleport.colors_min = 2; + Teleport.colors_max = 11; + Teleport.colors.assign(default_colors, default_colors + 10); + Teleport.colors.push_back(FURY_DEFAULT_BG_COLOR); + Teleport.speed_min = 255; + Teleport.speed_max = 0; + Teleport.speed = 8; + Teleport.brightness_min = 0; + Teleport.brightness_max = 100; + Teleport.brightness = 80; + modes.push_back(Teleport); + + mode Wind; + Wind.name = "Wind"; + Wind.value = FURY_MODE_WIND; + Wind.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_UD; + Wind.color_mode = MODE_COLORS_MODE_SPECIFIC; + Wind.colors_min = 2; + Wind.colors_max = 11; + Wind.colors.assign(default_colors, default_colors + 10); + Wind.colors.push_back(FURY_DEFAULT_BG_COLOR); + Wind.speed_min = 255; + Wind.speed_max = 0; + Wind.speed = 8; + Wind.direction = MODE_DIRECTION_UP; + Wind.brightness_min = 0; + Wind.brightness_max = 100; + Wind.brightness = 80; + modes.push_back(Wind); + + mode Comet; + Comet.name = "Comet"; + Comet.value = FURY_MODE_COMET; + Comet.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_UD; + Comet.color_mode = MODE_COLORS_MODE_SPECIFIC; + Comet.colors_min = 1; + Comet.colors_max = 10; + Comet.colors.assign(default_colors, default_colors + 10); + Comet.speed_min = 255; + Comet.speed_max = 0; + Comet.speed = 25; + Comet.direction = MODE_DIRECTION_UP; + Comet.brightness_min = 0; + Comet.brightness_max = 100; + Comet.brightness = 80; + modes.push_back(Comet); + + mode Rain; + Rain.name = "Rain"; + Rain.value = FURY_MODE_RAIN; + Rain.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_UD; + Rain.color_mode = MODE_COLORS_MODE_SPECIFIC; + Rain.colors_min = 1; + Rain.colors_max = 10; + Rain.colors.assign(default_colors, default_colors + 10); + Rain.speed_min = 28; + Rain.speed_max = 8; + Rain.speed = 25; + Rain.direction = MODE_DIRECTION_DOWN; + Rain.brightness_min = 0; + Rain.brightness_max = 100; + Rain.brightness = 80; + modes.push_back(Rain); + + mode Firework; + Firework.name = "Firework"; + Firework.value = FURY_MODE_FIREWORK; + Firework.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_UD; + Firework.color_mode = MODE_COLORS_MODE_SPECIFIC; + Firework.colors_min = 1; + Firework.colors_max = 10; + Firework.colors.assign(default_colors, default_colors + 10); + Firework.speed_min = 83; + Firework.speed_max = 33; + Firework.speed = 33; + Firework.direction = MODE_DIRECTION_UP; + Firework.brightness_min = 0; + Firework.brightness_max = 100; + Firework.brightness = 80; + modes.push_back(Firework); + + mode Voltage; + Voltage.name = "Voltage"; + Voltage.value = FURY_MODE_VOLTAGE; + Voltage.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_UD; + Voltage.color_mode = MODE_COLORS_MODE_SPECIFIC; + Voltage.colors_min = 2; + Voltage.colors_max = 11; + Voltage.colors.assign(default_colors, default_colors + 10); + Voltage.colors.push_back(FURY_DEFAULT_BG_COLOR); + Voltage.speed_min = 18; + Voltage.speed_max = 5; + Voltage.speed = 16; + Voltage.direction = MODE_DIRECTION_UP; + Voltage.brightness_min = 0; + Voltage.brightness_max = 100; + Voltage.brightness = 80; + modes.push_back(Voltage); + +#ifdef FURY_SYNC + mode Countdown; + Countdown.name = "Countdown"; + Countdown.value = FURY_MODE_COUNTDOWN; + Countdown.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_UD; + Countdown.color_mode = MODE_COLORS_MODE_SPECIFIC; + Countdown.colors_min = 2; + Countdown.colors_max = 11; + Countdown.colors.assign(default_colors, default_colors + 10); + Countdown.colors.push_back(FURY_DEFAULT_BG_COLOR); + Countdown.speed_min = 76; + Countdown.speed_max = 20; + Countdown.speed = 76; + Countdown.direction = MODE_DIRECTION_UP; + Countdown.brightness_min = 0; + Countdown.brightness_max = 100; + Countdown.brightness = 80; + modes.push_back(Countdown); +#endif + + mode Flame; + Flame.name = "Flame"; + Flame.value = FURY_MODE_FLAME; + Flame.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_UD; + Flame.speed_min = 64; + Flame.speed_max = 40; + Flame.speed = 64; + Flame.direction = MODE_DIRECTION_UP; + Flame.brightness_min = 0; + Flame.brightness_max = 100; + Flame.brightness = 80; + Flame.color_mode = MODE_COLORS_NONE; + modes.push_back(Flame); + + mode Twilight; + Twilight.name = "Twilight"; + Twilight.value = FURY_MODE_TWILIGHT; + Twilight.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Twilight.speed_min = 255; + Twilight.speed_max = 0; + Twilight.speed = 64; + Twilight.brightness_min = 0; + Twilight.brightness_max = 100; + Twilight.brightness = 80; + Twilight.color_mode = MODE_COLORS_NONE; + modes.push_back(Twilight); + + mode Fury; + Fury.name = "Fury"; + Fury.value = FURY_MODE_FURY; + Fury.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_UD; + Fury.color_mode = MODE_COLORS_MODE_SPECIFIC; + Fury.colors_min = 2; + Fury.colors_max = 11; + Fury.colors.assign(default_colors, default_colors + 10); + Fury.colors.push_back(FURY_DEFAULT_BG_COLOR); + Fury.speed_min = 255; + Fury.speed_max = 0; + Fury.speed = 76; + Fury.direction = MODE_DIRECTION_UP; + Fury.brightness_min = 0; + Fury.brightness_max = 100; + Fury.brightness = 80; + modes.push_back(Fury); + + mode Prism; + Prism.name = "Prism"; + Prism.value = FURY_MODE_PRISM; + Prism.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Prism.speed_min = 60; + Prism.speed_max = 0; + Prism.speed = 40; + Prism.brightness_min = 0; + Prism.brightness_max = 100; + Prism.brightness = 80; + Prism.color_mode = MODE_COLORS_NONE; + modes.push_back(Prism); + + SetupZones(); + + // default per-LED color is red + colors.assign(colors.size(), default_colors[0]); +} + +RGBController_KingstonFuryDRAM::~RGBController_KingstonFuryDRAM() +{ + delete controller; +} + +void RGBController_KingstonFuryDRAM::SetupZones() +{ + for(unsigned int slot = 0; slot < controller->GetSlotCount(); slot++) + { + zone* new_zone = new zone; + + new_zone->name = "Fury Slot "; + new_zone->name.append(std::to_string(slot + 1)); + new_zone->type = ZONE_TYPE_LINEAR; + new_zone->leds_min = controller->GetLEDPerDIMM(); + new_zone->leds_max = new_zone->leds_min; + new_zone->leds_count = new_zone->leds_min; + new_zone->matrix_map = NULL; + + zones.push_back(*new_zone); + } + + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + for(std::size_t led_idx = 0; led_idx < zones[zone_idx].leds_count; led_idx++) + { + led* new_led = new led(); + + new_led->name = "Fury Slot "; + new_led->name.append(std::to_string(zone_idx + 1)); + new_led->name.append(", LED "); + new_led->name.append(std::to_string(led_idx + 1)); + + new_led->value = (unsigned int)leds.size(); + + leds.push_back(*new_led); + } + } + + SetupColors(); +} + +void RGBController_KingstonFuryDRAM::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ + LOG_DEBUG("[%s] resize zone", + FURY_CONTROLLER_NAME); +} + +// some modes have different actual values to be written, depending on the color mode +unsigned char RGBController_KingstonFuryDRAM::GetRealModeValue() +{ + int mode_value = modes[active_mode].value; + switch(mode_value) + { + case FURY_MODE_BREATH: + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + return FURY_MODE_BREATH; + } + else + { + return FURY_MODE_BREATH_DIRECT; + } + } + return mode_value; +} + +void RGBController_KingstonFuryDRAM::DeviceUpdateLEDs() +{ + controller->SendBegin(); + controller->SetMode(GetRealModeValue()); + + // Fixed mode specific parameters + switch(modes[active_mode].value) + { + case FURY_MODE_STATIC: + controller->SetRegister(FURY_REG_DIRECTION, FURY_DIR_BOTTOM_TO_TOP); + controller->SetRegister(FURY_REG_DELAY, 0); + controller->SetRegister(FURY_REG_SPEED, 0); + break; + + case FURY_MODE_RAINBOW: + case FURY_MODE_VOLTAGE: + case FURY_MODE_COUNTDOWN: + case FURY_MODE_FLAME: + case FURY_MODE_TWILIGHT: + case FURY_MODE_FURY: + controller->SetRegister(FURY_REG_DELAY, 0); + break; + + case FURY_MODE_RHYTHM: + controller->SetRegister(FURY_REG_DIRECTION, + FURY_DIR_BOTTOM_TO_TOP); + break; + + case FURY_MODE_BREATH: + controller->SetRegister(FURY_REG_DIRECTION, + FURY_DIR_BOTTOM_TO_TOP); + controller->SetRegister(FURY_REG_DELAY, 0); + break; + + case FURY_MODE_DYNAMIC: + controller->SetRegister(FURY_REG_DIRECTION, + FURY_DIR_BOTTOM_TO_TOP); + controller->SetRegister(FURY_REG_DELAY, 0); + break; + + case FURY_MODE_SLITHER: + controller->SetRegister(FURY_REG_DELAY, 12); + controller->SetRegister(FURY_REG_DIRECTION, + FURY_ALT_DIRECTIONS); + break; + + case FURY_MODE_TELEPORT: + controller->SetRegister(FURY_REG_DELAY, 0); + controller->SetRegister(FURY_REG_DIRECTION, + FURY_ALT_DIRECTIONS); + break; + + case FURY_MODE_RAIN: + controller->SetRegister(FURY_REG_DELAY, 0); + controller->SetRegister(FURY_REG_LENGTH, 3); + break; + + case FURY_MODE_FIREWORK: + controller->SetRegister(FURY_REG_DELAY, 0); + controller->SetRegister(FURY_REG_LENGTH, 7); + break; + } + + // Mode-specific parameters that are customizable in Kingston's software + // but which are not yet available in the OpenRGB interface. + // Default values are used here and the parameter ranges are annotated + switch(modes[active_mode].value) + { + case FURY_MODE_RHYTHM: + // between 2 and 5 + controller->SetRegister(FURY_REG_DELAY, 3); + break; + + + case FURY_MODE_SLIDE: + // between 1 and 4 + controller->SetRegister(FURY_REG_DELAY, 3); + // between 1 and 12 + controller->SetRegister(FURY_REG_LENGTH, 4); + break; + + case FURY_MODE_SLITHER: + // between 1 and 32 + controller->SetRegister(FURY_REG_LENGTH, 12); + break; + + case FURY_MODE_TELEPORT: + // between 1 and 12 + controller->SetRegister(FURY_REG_LENGTH, 3); + break; + + case FURY_MODE_WIND: + // between 0 and 32 + controller->SetRegister(FURY_REG_DELAY, 0); + // between 1 and 32 + controller->SetRegister(FURY_REG_LENGTH, 12); + break; + + case FURY_MODE_COMET: + // between 0 and 20 + controller->SetRegister(FURY_REG_DELAY, 0); + // between 1 and 18 + controller->SetRegister(FURY_REG_LENGTH, 7); + break; + + case FURY_MODE_PRISM: + // between 2 and 4 + controller->SetRegister(FURY_REG_DELAY, 2); + break; + + case FURY_MODE_SPECTRUM: + // between 2 and 6 + controller->SetRegister(FURY_REG_DELAY, 4); + break; + } + + switch(modes[active_mode].color_mode) + { + case MODE_COLORS_PER_LED: + controller->SetLEDColors(colors); + break; + + case MODE_COLORS_MODE_SPECIFIC: + switch(modes[active_mode].value) + { + case FURY_MODE_RHYTHM: + case FURY_MODE_SLIDE: + case FURY_MODE_SLITHER: + case FURY_MODE_TELEPORT: + case FURY_MODE_WIND: + case FURY_MODE_VOLTAGE: + case FURY_MODE_COUNTDOWN: + case FURY_MODE_FURY: + { + std::vector mode_colors(modes[active_mode].colors.begin(), + modes[active_mode].colors.end() - 1); + controller->SetModeColors(mode_colors); + // handle background color + RGBColor color = modes[active_mode].colors[mode_colors.size()]; + unsigned char red = RGBGetRValue(color); + unsigned char green = RGBGetGValue(color); + unsigned char blue = RGBGetBValue(color); + + controller->SetRegister(FURY_REG_BG_RED, red); + controller->SetRegister(FURY_REG_BG_GREEN, green); + controller->SetRegister(FURY_REG_BG_BLUE, blue); + break; + } + default: + controller->SetModeColors(modes[active_mode].colors); + break; + } + break; + } + + if(modes[active_mode].flags & MODE_FLAG_HAS_DIRECTION_UD) + { + if(modes[active_mode].direction == MODE_DIRECTION_UP) + { + controller->SetRegister(FURY_REG_DIRECTION, + FURY_DIR_BOTTOM_TO_TOP); + } + else + { + controller->SetRegister(FURY_REG_DIRECTION, + FURY_DIR_TOP_TO_BOTTOM); + } + } + + if(modes[active_mode].flags & MODE_FLAG_HAS_SPEED) + { + switch(modes[active_mode].value) + { + case FURY_MODE_DYNAMIC: + controller->SetRegister(FURY_REG_SPEED, 0); + + // time spent holding a color + controller->SetRegister(FURY_REG_DYNAMIC_HOLD_A, + modes[active_mode].speed >> 8); + // set to 1 as long as the time above is nonzero + controller->SetRegister(FURY_REG_DYNAMIC_HOLD_B, 1); + + // time spent fading to next color + controller->SetRegister(FURY_REG_DYNAMIC_FADE_A, + (modes[active_mode].speed * 5) >> 8); + // set to 1 as long as the time above is nonzero + controller->SetRegister(FURY_REG_DYNAMIC_FADE_B, 1); + break; + + case FURY_MODE_BREATH: + controller->SetRegister(FURY_REG_SPEED, 0); + + // These are the speed values used by Kingston's software, + // representing the time spent fading between two brightness levels + controller->SetRegister(FURY_REG_BREATH_MIN_TO_MID, + modes[active_mode].speed * 3); + controller->SetRegister(FURY_REG_BREATH_MID_TO_MAX, + modes[active_mode].speed); + controller->SetRegister(FURY_REG_BREATH_MAX_TO_MID, + modes[active_mode].speed); + controller->SetRegister(FURY_REG_BREATH_MID_TO_MIN, + modes[active_mode].speed * 3); + + // Time spent holding min brightness + controller->SetRegister(FURY_REG_BREATH_MIN_HOLD, 1); + + // Brightness values (relative to overall brightness) + controller->SetRegister(FURY_REG_BREATH_MAX_BRIGHTNESS, 100); + controller->SetRegister(FURY_REG_BREATH_MID_BRIGHTNESS, 64); + controller->SetRegister(FURY_REG_BREATH_MIN_BRIGHTNESS, 0); + // Kingston software uses 1 for min brightness, + // but 0 seems to look better. + + break; + + case FURY_MODE_RAIN: + { + // speed offsets taken from Kingston software + unsigned char offsets[4] = {11, 0, 15, 9}; + std::vector speeds; + for (std::size_t idx = 0; idx < controller->GetSlotCount(); idx++) + { + speeds.push_back(modes[active_mode].speed + offsets[idx % 4]); + } + controller->SetRegister(FURY_REG_SPEED, speeds); + break; + } + + case FURY_MODE_FIREWORK: + { + // speed offsets taken from Kingston software + unsigned char offsets[4] = {15, 0, 19, 4}; + std::vector speeds; + for (std::size_t idx = 0; idx < controller->GetSlotCount(); idx++) + { + speeds.push_back(modes[active_mode].speed + offsets[idx % 4]); + } + controller->SetRegister(FURY_REG_SPEED, speeds); + break; + } + + default: + controller->SetRegister(FURY_REG_SPEED, modes[active_mode].speed); + break; + } + } + + controller->SetRegister(FURY_REG_BRIGHTNESS, + modes[active_mode].brightness); + controller->SetNumSlots(); + controller->SendApply(); +} + +void RGBController_KingstonFuryDRAM::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_KingstonFuryDRAM::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_KingstonFuryDRAM::DeviceUpdateMode() +{ + LOG_DEBUG("[%s] device update mode", + FURY_CONTROLLER_NAME); + // Preamble only necessary when changing modes. + if(GetRealModeValue() != controller->GetMode()) + { + controller->SendPreamble(modes[active_mode].value != FURY_MODE_RAIN && + modes[active_mode].value != FURY_MODE_FIREWORK && + modes[active_mode].value != FURY_MODE_DIRECT); + } + DeviceUpdateLEDs(); +} diff --git a/Controllers/KingstonFuryDRAMController/RGBController_KingstonFuryDRAM.h b/Controllers/KingstonFuryDRAMController/RGBController_KingstonFuryDRAM.h new file mode 100644 index 00000000..21ebc283 --- /dev/null +++ b/Controllers/KingstonFuryDRAMController/RGBController_KingstonFuryDRAM.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_KingstonFuryDRAM.h | +| | +| Driver for Kingston Fury DDR4/5 RAM modules | +| | +| Geofrey Mon (geofbot) 14 Jul 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "KingstonFuryDRAMController.h" + +class RGBController_KingstonFuryDRAM : public RGBController +{ +public: + RGBController_KingstonFuryDRAM(KingstonFuryDRAMController* controller_ptr); + ~RGBController_KingstonFuryDRAM(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + unsigned char GetRealModeValue(); + KingstonFuryDRAMController* controller; +}; diff --git a/Controllers/LEDStripController/LEDStripController.cpp b/Controllers/LEDStripController/LEDStripController.cpp index 2a220572..e44b619c 100644 --- a/Controllers/LEDStripController/LEDStripController.cpp +++ b/Controllers/LEDStripController/LEDStripController.cpp @@ -1,19 +1,23 @@ /*---------------------------------------------------------*\ -| Processing Code for Generic LED Strip Interface | +| LEDStripController.cpp | | | -| Adam Honse (calcprogrammer1@gmail.com), 12/11/2016 | +| Driver for serial LED strips | +| | +| Adam Honse (calcprogrammer1@gmail.com) 11 Dec 2016 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "LEDStripController.h" -#include "ResourceManager.h" - #include #include #include +#include "LEDStripController.h" +#include "ResourceManager.h" -LEDStripController::LEDStripController() +LEDStripController::LEDStripController(std::string dev_name) { - + name = dev_name; } @@ -134,6 +138,11 @@ void LEDStripController::InitializeUDP(char * clientname, char * port) i2cport = NULL; } +char* LEDStripController::GetLEDString() +{ + return(led_string); +} + std::string LEDStripController::GetLocation() { if(serialport != NULL) @@ -154,9 +163,9 @@ std::string LEDStripController::GetLocation() } } -char* LEDStripController::GetLEDString() +std::string LEDStripController::GetName() { - return(led_string); + return(name); } void LEDStripController::SetLEDs(std::vector colors) @@ -195,7 +204,7 @@ void LEDStripController::SetLEDsKeyboardVisualizer(std::vector colors) | n+1: Checksum MSB | | n+2: Checksum LSB | \*-------------------------------------------------------------*/ - unsigned int payload_size = (colors.size() * 3); + unsigned int payload_size = (unsigned int)(colors.size() * 3); unsigned int packet_size = payload_size + 3; serial_buf = new unsigned char[packet_size]; @@ -265,7 +274,7 @@ void LEDStripController::SetLEDsAdalight(std::vector colors) | 5: Checksum (MSB xor LSB xor 0x55) | | 6-n: Data Bytes | \*-------------------------------------------------------------*/ - unsigned int led_count = colors.size(); + unsigned int led_count = (unsigned int)colors.size(); unsigned int payload_size = (led_count * 3); unsigned int packet_size = payload_size + 6; @@ -320,7 +329,7 @@ void LEDStripController::SetLEDsTPM2(std::vector colors) | 4-n: Data Bytes | | n+1: Packet End Byte (0x36) | \*-------------------------------------------------------------*/ - unsigned int payload_size = (colors.size() * 3); + unsigned int payload_size = (unsigned int)(colors.size() * 3); unsigned int packet_size = payload_size + 5; serial_buf = new unsigned char[packet_size]; diff --git a/Controllers/LEDStripController/LEDStripController.h b/Controllers/LEDStripController/LEDStripController.h index aae68e0e..e4dc184d 100644 --- a/Controllers/LEDStripController/LEDStripController.h +++ b/Controllers/LEDStripController/LEDStripController.h @@ -1,18 +1,21 @@ /*---------------------------------------------------------*\ -| Definitions for Generic LED Strip Interface | +| LEDStripController.h | | | -| Adam Honse (calcprogrammer1@gmail.com), 12/11/2016 | +| Driver for serial LED strips | +| | +| Adam Honse (calcprogrammer1@gmail.com) Dec 11 2016 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#ifndef LED_STRIP_H -#define LED_STRIP_H +#pragma once +#include #include "RGBController.h" #include "i2c_smbus.h" #include "serial_port.h" #include "net_port.h" -#include - #ifndef TRUE #define TRUE true @@ -38,15 +41,15 @@ struct LEDStripDevice { std::string name; std::string port; - unsigned int baud; - unsigned int num_leds; + unsigned int baud = 0; + unsigned int num_leds = 0; led_protocol protocol; }; class LEDStripController { public: - LEDStripController(); + LEDStripController(std::string dev_name); ~LEDStripController(); void Initialize(char* ledstring, led_protocol proto); @@ -57,6 +60,7 @@ public: char* GetLEDString(); std::string GetLocation(); + std::string GetName(); void SetLEDs(std::vector colors); @@ -73,11 +77,10 @@ private: char led_string[1024]; std::string port_name; std::string client_name; + std::string name; serial_port *serialport; net_port *udpport; i2c_smbus_interface *i2cport; unsigned char i2c_addr; led_protocol protocol; }; - -#endif diff --git a/Controllers/LEDStripController/LEDStripControllerDetect.cpp b/Controllers/LEDStripController/LEDStripControllerDetect.cpp index 3ecd3527..e9c61b03 100644 --- a/Controllers/LEDStripController/LEDStripControllerDetect.cpp +++ b/Controllers/LEDStripController/LEDStripControllerDetect.cpp @@ -1,11 +1,19 @@ +/*---------------------------------------------------------*\ +| LEDStripControllerDetect.cpp | +| | +| Detector for serial LED strips | +| | +| Adam Honse (calcprogrammer1@gmail.com) 11 Dec 2016 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "LEDStripController.h" -#include "RGBController.h" #include "RGBController_LEDStrip.h" #include "SettingsManager.h" -#include -#include -#include +#include "LogManager.h" /******************************************************************************************\ * * @@ -32,16 +40,17 @@ void DetectLEDStripControllers() { for(unsigned int device_idx = 0; device_idx < ledstrip_settings["devices"].size(); device_idx++) { - /*-------------------------------------------------*\ - | Default to the Keyboard Visualizer protocol | - \*-------------------------------------------------*/ - dev.name = "LED Strip"; - dev.protocol = LED_PROTOCOL_KEYBOARD_VISUALIZER; - if(ledstrip_settings["devices"][device_idx].contains("name")) { dev.name = ledstrip_settings["devices"][device_idx]["name"]; } + else + { + /*-------------------------------------------------*\ + | Default name | + \*-------------------------------------------------*/ + dev.name = "LED Strip"; + } if(ledstrip_settings["devices"][device_idx].contains("port")) { @@ -78,15 +87,44 @@ void DetectLEDStripControllers() { dev.protocol = LED_PROTOCOL_BASIC_I2C; } + else + { + LOG_WARNING("[LEDStripController] '%s' is not a valid value for protocol", protocol_string.c_str()); + return; + } + } + else + { + /*-------------------------------------------------*\ + | Default to the Keyboard Visualizer protocol | + \*-------------------------------------------------*/ + dev.protocol = LED_PROTOCOL_KEYBOARD_VISUALIZER; + } + + if(dev.port.empty()) + { + LOG_WARNING("[LEDStripController] port value cannot be left empty."); + return; + } + + if(dev.baud <= 0) + { + LOG_WARNING("[LEDStripController] baud value cannot be left empty."); + return; + } + + if(dev.num_leds <= 0) + { + LOG_WARNING("[LEDStripController] num_leds value cannot be left empty."); + return; } std::string value = dev.port + "," + std::to_string(dev.baud) + "," + std::to_string(dev.num_leds); - LEDStripController* controller = new LEDStripController(); + LEDStripController* controller = new LEDStripController(dev.name); controller->Initialize((char *)value.c_str(), dev.protocol); RGBController_LEDStrip* rgb_controller = new RGBController_LEDStrip(controller); - rgb_controller->name = dev.name; ResourceManager::get()->RegisterRGBController(rgb_controller); } diff --git a/Controllers/LEDStripController/RGBController_LEDStrip.cpp b/Controllers/LEDStripController/RGBController_LEDStrip.cpp index e3301ba2..13ab64a6 100644 --- a/Controllers/LEDStripController/RGBController_LEDStrip.cpp +++ b/Controllers/LEDStripController/RGBController_LEDStrip.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_LEDStrip.cpp | -| | -| Generic RGB Interface for OpenAuraSDK | -| KeyboardVisualizer LED strip interface | -| | -| Adam Honse (CalcProgrammer1) 6/20/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LEDStrip.cpp | +| | +| RGBController for serial LED strips | +| | +| Adam Honse (calcprogrammer1@gmail.com) 20 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_LEDStrip.h" @@ -22,18 +24,18 @@ RGBController_LEDStrip::RGBController_LEDStrip(LEDStripController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "LED Strip"; - type = DEVICE_TYPE_LEDSTRIP; - description = "Serial LED Strip Device"; - location = controller->GetLocation(); + name = controller->GetName(); + type = DEVICE_TYPE_LEDSTRIP; + description = "Serial LED Strip Device"; + location = controller->GetLocation(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + 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(); diff --git a/Controllers/LEDStripController/RGBController_LEDStrip.h b/Controllers/LEDStripController/RGBController_LEDStrip.h index 31bebfba..dcdcd296 100644 --- a/Controllers/LEDStripController/RGBController_LEDStrip.h +++ b/Controllers/LEDStripController/RGBController_LEDStrip.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_LEDStrip.h | -| | -| Generic RGB Interface for OpenAuraSDK | -| KeyboardVisualizer LED strip interface | -| | -| Adam Honse (CalcProgrammer1) 6/20/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LEDStrip.h | +| | +| RGBController for serial LED strips | +| | +| Adam Honse (calcprogrammer1@gmail.com) 20 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "serial_port.h" #include "LEDStripController.h" diff --git a/Controllers/LGMonitorController/LGMonitorController.cpp b/Controllers/LGMonitorController/LGMonitorController.cpp new file mode 100644 index 00000000..dfecf659 --- /dev/null +++ b/Controllers/LGMonitorController/LGMonitorController.cpp @@ -0,0 +1,249 @@ +/*---------------------------------------------------------*\ +| LGMonitorController.cpp | +| | +| Driver for LG monitor | +| | +| Morgan Guimard (morg) 11 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "LGMonitorController.h" +#include "StringUtils.h" + +LGMonitorController::LGMonitorController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) +{ + dev = dev_handle; + location = info.path; + name = dev_name; +} + +LGMonitorController::~LGMonitorController() +{ + hid_close(dev); +} + +std::string LGMonitorController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string LGMonitorController::GetNameString() +{ + return(name); +} + +std::string LGMonitorController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void LGMonitorController::SetDirect(const std::vector colors) +{ + /*---------------------------------------------------------*\ + | Make sure the device is set to on | + \*---------------------------------------------------------*/ + if(!on) + { + TurnOn(true); + } + + /*---------------------------------------------------------*\ + | Make sure the direct mode is enabled | + \*---------------------------------------------------------*/ + if(!direct_mode_enabled) + { + EnableDirectMode(); + } + + /*---------------------------------------------------------*\ + | Prepare the colors data | + \*---------------------------------------------------------*/ + uint8_t data[192]; + memset(data, 0x00, 192); + + unsigned int offset = 0; + + data[offset++] = LG_MONITOR_START_CMD_1; + data[offset++] = LG_MONITOR_START_CMD_2; + data[offset++] = LG_MONITOR_DIRECT_CTL; + data[offset++] = 0x02; + data[offset++] = 0x91; + data[offset++] = 0x00; + + for(const RGBColor color: colors) + { + data[offset++] = RGBGetRValue(color); + data[offset++] = RGBGetGValue(color); + data[offset++] = RGBGetBValue(color); + } + + data[offset] = crc(data, 0, offset); + offset++; + + data[offset++] = LG_MONITOR_END_CMD_1; + data[offset] = LG_MONITOR_END_CMD_2; + + /*---------------------------------------------------------*\ + | Send the data (3 packets of 64 bytes) | + \*---------------------------------------------------------*/ + uint8_t buf[LG_MONITOR_PACKET_SIZE]; + memset(buf, 0x00, LG_MONITOR_PACKET_SIZE); + + for(unsigned int i = 0; i < 3; i++) + { + memcpy(&buf[1], &data[64 * i], 64); + hid_write(dev, buf, LG_MONITOR_PACKET_SIZE); + } +} + +void LGMonitorController::SetMode(uint8_t mode_value, uint8_t brightness, const std::vector colors) +{ + switch(mode_value) + { + case LG_MONITOR_OFF_MODE_VALUE: + /*---------------------------------------------------------*\ + | Turn off lighting | + \*---------------------------------------------------------*/ + TurnOn(false); + break; + + case LG_MONITOR_STATIC_SLOT_1_MODE_VALUE: + /*---------------------------------------------------------*\ + | Set slot 1 active | + \*---------------------------------------------------------*/ + EnableMode(LG_MONITOR_STATIC_SLOT_1_MODE_VALUE); + + SetBrightness(brightness); + /*---------------------------------------------------------*\ + | Send color in slot 1 | + \*---------------------------------------------------------*/ + SetSlotColor(LG_MONITOR_STATIC_SLOT_1_MODE_VALUE, colors[0]); + + break; + + case LG_MONITOR_SPECTRUM_CYCLE_MODE_VALUE: + case LG_MONITOR_RAINBOW_MODE_VALUE: + /*---------------------------------------------------------*\ + | Enable given mode | + \*---------------------------------------------------------*/ + EnableMode(mode_value); + SetBrightness(brightness); + break; + + default: + break; + } + + direct_mode_enabled = false; +} + +void LGMonitorController::EnableDirectMode() +{ + EnableMode(LG_MONITOR_DIRECT_MODE_VALUE); + direct_mode_enabled = true; +} + +void LGMonitorController::EnableMode(uint8_t mode_value) +{ + uint8_t buf[LG_MONITOR_PACKET_SIZE]; + memset(buf, 0x00, LG_MONITOR_PACKET_SIZE); + + buf[1] = LG_MONITOR_START_CMD_1; + buf[2] = LG_MONITOR_START_CMD_2; + buf[3] = LG_MONITOR_SET_MODE; + buf[4] = 0x02; + buf[5] = 0x02; + buf[6] = LG_MONITOR_MODE_CTL; + buf[7] = mode_value; + buf[8] = crc(buf, 1, 8); + buf[9] = LG_MONITOR_END_CMD_1; + buf[10] = LG_MONITOR_END_CMD_2; + + hid_write(dev, buf, LG_MONITOR_PACKET_SIZE); +} + +void LGMonitorController::SetBrightness(uint8_t brightness) +{ + uint8_t buf[LG_MONITOR_PACKET_SIZE]; + memset(buf, 0x00, LG_MONITOR_PACKET_SIZE); + + buf[1] = LG_MONITOR_START_CMD_1; + buf[2] = LG_MONITOR_START_CMD_2; + buf[3] = LG_MONITOR_SET_POWER_STATE; + buf[4] = 0x02; + buf[5] = 0x02; + buf[6] = LG_MONITOR_BRIGHTNESS_CTL; + buf[7] = brightness; + buf[8] = crc(buf, 1, 8); + buf[9] = LG_MONITOR_END_CMD_1; + buf[10] = LG_MONITOR_END_CMD_2; + + hid_write(dev, buf, LG_MONITOR_PACKET_SIZE); +} + +void LGMonitorController::TurnOn(bool value) +{ + uint8_t buf[LG_MONITOR_PACKET_SIZE]; + memset(buf, 0x00, LG_MONITOR_PACKET_SIZE); + + buf[1] = LG_MONITOR_START_CMD_1; + buf[2] = LG_MONITOR_START_CMD_2; + buf[3] = LG_MONITOR_SET_POWER_STATE; + buf[4] = 0x02; + buf[5] = 0x02; + buf[6] = value ? LG_MONITOR_POWER_ON : LG_MONITOR_POWER_OFF; + buf[8] = crc(buf, 1, 8); + buf[9] = LG_MONITOR_END_CMD_1; + buf[10] = LG_MONITOR_END_CMD_2; + + hid_write(dev, buf, LG_MONITOR_PACKET_SIZE); + + on = value; +} + +void LGMonitorController::SetSlotColor(uint8_t slot, const RGBColor color) +{ + uint8_t buf[LG_MONITOR_PACKET_SIZE]; + memset(buf, 0x00, LG_MONITOR_PACKET_SIZE); + + buf[1] = LG_MONITOR_START_CMD_1; + buf[2] = LG_MONITOR_START_CMD_2; + buf[3] = LG_MONITOR_SET_COLOR; + + buf[4] = 0x02; + buf[5] = 0x04; + buf[6] = slot; + + buf[7] = RGBGetRValue(color); + buf[8] = RGBGetGValue(color); + buf[9] = RGBGetBValue(color); + + buf[10] = crc(buf, 1, 10); + buf[11] = LG_MONITOR_END_CMD_1; + buf[12] = LG_MONITOR_END_CMD_2; + + hid_write(dev, buf, LG_MONITOR_PACKET_SIZE); +} + +uint8_t LGMonitorController::crc(const uint8_t data[], uint8_t start, uint8_t end) +{ + uint8_t crc = 0; + + for(unsigned int i = start; i < end; i++) + { + crc = crc ^ data[i]; + } + + return crc; +} diff --git a/Controllers/LGMonitorController/LGMonitorController.h b/Controllers/LGMonitorController/LGMonitorController.h new file mode 100644 index 00000000..eef95e2e --- /dev/null +++ b/Controllers/LGMonitorController/LGMonitorController.h @@ -0,0 +1,73 @@ +/*---------------------------------------------------------*\ +| LGMonitorController.h | +| | +| Driver for LG monitor | +| | +| Morgan Guimard (morg) 11 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define LG_MONITOR_LEDS 48 +#define LG_MONITOR_PACKET_SIZE 65 +#define LG_MONITOR_READ_CMD 0x52 // R (Read) +#define LG_MONITOR_START_CMD_1 0x53 // S (Send) +#define LG_MONITOR_START_CMD_2 0x43 // C (Command) +#define LG_MONITOR_END_CMD_1 0x45 // E (End) +#define LG_MONITOR_END_CMD_2 0x44 // D (Data) +#define LG_MONITOR_READ_POWER_STATE 0xCE +#define LG_MONITOR_SET_POWER_STATE 0xCF +#define LG_MONITOR_SET_COLOR 0xCD +#define LG_MONITOR_SET_MODE 0xCA +#define LG_MONITOR_DIRECT_CTL 0xC1 +#define LG_MONITOR_POWER_ON 0x01 +#define LG_MONITOR_POWER_OFF 0x02 +#define LG_MONITOR_MODE_CTL 0x03 +#define LG_MONITOR_BRIGHTNESS_CTL 0x01 + +enum +{ + LG_MONITOR_DIRECT_MODE_VALUE = 0x08, + LG_MONITOR_STATIC_SLOT_1_MODE_VALUE = 0x01, + LG_MONITOR_SPECTRUM_CYCLE_MODE_VALUE = 0x05, + LG_MONITOR_RAINBOW_MODE_VALUE = 0x06, + LG_MONITOR_OFF_MODE_VALUE = 0x00 +}; + +class LGMonitorController +{ +public: + LGMonitorController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~LGMonitorController(); + + std::string GetDeviceLocation(); + std::string GetFirmwareVersion(); + std::string GetNameString(); + std::string GetSerialString(); + + void SetDirect(const std::vector colors); + void SetMode(uint8_t mode_value, uint8_t brightness, const std::vector colors); + +private: + hid_device* dev; + std::string description; + std::string location; + std::string name; + std::string version; + bool on = false; + bool direct_mode_enabled = false; + + static uint8_t crc(const uint8_t data[], uint8_t start, uint8_t end); + void SetBrightness(uint8_t value); + void TurnOn(bool value); + void EnableDirectMode(); + void EnableMode(uint8_t mode_value); + void SetSlotColor(uint8_t slot, const RGBColor color); +}; diff --git a/Controllers/LGMonitorController/LGMonitorControllerDetect.cpp b/Controllers/LGMonitorController/LGMonitorControllerDetect.cpp new file mode 100644 index 00000000..9b8f4e72 --- /dev/null +++ b/Controllers/LGMonitorController/LGMonitorControllerDetect.cpp @@ -0,0 +1,43 @@ +/*---------------------------------------------------------*\ +| LGMonitorControllerDetect.cpp | +| | +| Detector for LG monitor | +| | +| Morgan Guimard (morg) 11 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "LGMonitorController.h" +#include "RGBController_LGMonitor.h" + +/*---------------------------------------------------------*\ +| vendor ID | +\*---------------------------------------------------------*/ +#define LG_MONITOR_VID 0x043E + +/*---------------------------------------------------------*\ +| Product ID | +\*---------------------------------------------------------*/ +#define LG_27GN950_B_PID 0x9A8A +#define LG_38GL950G_PID 0x9A57 + +static void DetectLGMonitorControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + LGMonitorController* controller = new LGMonitorController(dev, *info, name); + RGBController_LGMonitor* rgb_controller = new RGBController_LGMonitor(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR_IPU("LG 27GN950-B Monitor", DetectLGMonitorControllers, LG_MONITOR_VID, LG_27GN950_B_PID, 1, 0xFF01, 0x01); + +// Untested +//REGISTER_HID_DETECTOR("LG 38GL950G Monitor", DetectLGMonitorControllers, LG_MONITOR_VID, LG_38GL950G_PID); diff --git a/Controllers/LGMonitorController/RGBController_LGMonitor.cpp b/Controllers/LGMonitorController/RGBController_LGMonitor.cpp new file mode 100644 index 00000000..91c5f199 --- /dev/null +++ b/Controllers/LGMonitorController/RGBController_LGMonitor.cpp @@ -0,0 +1,163 @@ +/*---------------------------------------------------------*\ +| RGBController_LGMonitor.cpp | +| | +| RGBController for LG monitor | +| | +| Morgan Guimard (morg) 11 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "RGBController_LGMonitor.h" + +using namespace std::chrono_literals; + +/**------------------------------------------------------------------*\ + @name LGMonitor + @category Accessory + @type USB + @save :robot: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectLGMonitorControllers + @comment +\*-------------------------------------------------------------------*/ +RGBController_LGMonitor::RGBController_LGMonitor(LGMonitorController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "LG"; + type = DEVICE_TYPE_MONITOR; + description = "LG Monitor"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = LG_MONITOR_DIRECT_MODE_VALUE; + 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 = LG_MONITOR_STATIC_SLOT_1_MODE_VALUE; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors.resize(1); + Static.colors_min = 1; + Static.colors_max = 1; + Static.brightness_min = 1; + Static.brightness_max = 12; + Static.brightness = 12; + modes.push_back(Static); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = LG_MONITOR_SPECTRUM_CYCLE_MODE_VALUE; + SpectrumCycle.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.brightness_min = 1; + SpectrumCycle.brightness_max = 12; + SpectrumCycle.brightness = 12; + modes.push_back(SpectrumCycle); + + mode RainbowWave; + RainbowWave.name = "Rainbow Wave"; + RainbowWave.value = LG_MONITOR_RAINBOW_MODE_VALUE; + RainbowWave.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + RainbowWave.color_mode = MODE_COLORS_NONE; + RainbowWave.brightness_min = 1; + RainbowWave.brightness_max = 12; + RainbowWave.brightness = 12; + modes.push_back(RainbowWave); + + mode Off; + Off.name = "Off"; + Off.value = LG_MONITOR_OFF_MODE_VALUE; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + SetupZones(); + + keepalive_thread_run = 1; + keepalive_thread = new std::thread(&RGBController_LGMonitor::KeepaliveThread, this); +} + +RGBController_LGMonitor::~RGBController_LGMonitor() +{ + keepalive_thread_run = 0; + keepalive_thread->join(); + delete keepalive_thread; + + delete controller; +} + +void RGBController_LGMonitor::SetupZones() +{ + zone new_zone; + + new_zone.name = "Screen"; + new_zone.type = ZONE_TYPE_LINEAR; + new_zone.leds_min = 48; + new_zone.leds_max = 48; + new_zone.leds_count = 48; + new_zone.matrix_map = nullptr; + + zones.emplace_back(new_zone); + + for(unsigned int i = 0 ; i < 48; i ++) + { + led new_led; + new_led.name = "LED " + std::to_string(i + 1); + leds.push_back(new_led); + } + + SetupColors(); +} + +void RGBController_LGMonitor::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_LGMonitor::DeviceUpdateLEDs() +{ + last_update_time = std::chrono::steady_clock::now(); + controller->SetDirect(colors); +} + +void RGBController_LGMonitor::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_LGMonitor::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_LGMonitor::DeviceUpdateMode() +{ + controller->SetMode(modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].colors); +} + +void RGBController_LGMonitor::KeepaliveThread() +{ + while(keepalive_thread_run.load()) + { + if((modes[active_mode].value == LG_MONITOR_DIRECT_MODE_VALUE) && (std::chrono::steady_clock::now() - last_update_time) > std::chrono::milliseconds(500)) + { + UpdateLEDs(); + } + + std::this_thread::sleep_for(15ms); + } +} diff --git a/Controllers/LGMonitorController/RGBController_LGMonitor.h b/Controllers/LGMonitorController/RGBController_LGMonitor.h new file mode 100644 index 00000000..d1a66e65 --- /dev/null +++ b/Controllers/LGMonitorController/RGBController_LGMonitor.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------*\ +| RGBController_LGMonitor.h | +| | +| RGBController for LG monitor | +| | +| Morgan Guimard (morg) 11 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "LGMonitorController.h" + +class RGBController_LGMonitor : public RGBController +{ +public: + RGBController_LGMonitor(LGMonitorController* controller_ptr); + ~RGBController_LGMonitor(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + void DeviceUpdateMode(); + +private: + LGMonitorController* controller; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::chrono::time_point last_update_time; + + void KeepaliveThread(); +}; diff --git a/Controllers/LIFXController/LIFXController.cpp b/Controllers/LIFXController/LIFXController.cpp index fbb8cd36..e0026057 100644 --- a/Controllers/LIFXController/LIFXController.cpp +++ b/Controllers/LIFXController/LIFXController.cpp @@ -1,29 +1,37 @@ /*---------------------------------------------------------*\ -| Driver for LIFX | +| LIFXController.cpp | | | -| Adam Honse (calcprogrammer1@gmail.com), 2/5/2022 | +| Driver for LIFX | +| | +| Adam Honse (calcprogrammer1@gmail.com) 05 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ #include "LIFXController.h" -#include "json.hpp" +#include #include "hsv.h" using json = nlohmann::json; using namespace std::chrono_literals; -LIFXController::LIFXController(std::string ip, std::string name) +LIFXController::LIFXController(std::string ip, std::string name, bool multizone, bool extended_multizone) { - this->name = name; + this->name = name; + zone_count = 1; + this->multizone = multizone; + this->extended_multizone = extended_multizone; /*-----------------------------------------------------------------*\ | Fill in location string with device's IP address | \*-----------------------------------------------------------------*/ - location = "IP: " + ip; + location = "IP: " + ip; /*-----------------------------------------------------------------*\ | Open a UDP client sending to the device's IP, port 56700 | \*-----------------------------------------------------------------*/ - port.udp_client(ip.c_str(), "56700"); + port.udp_client(ip.c_str(), LIFX_UDP_PORT); } LIFXController::~LIFXController() @@ -48,7 +56,7 @@ std::string LIFXController::GetVersion() std::string LIFXController::GetManufacturer() { - return("LIFX"); + return(LIFX_MANUFACTURER); } std::string LIFXController::GetUniqueID() @@ -56,78 +64,417 @@ std::string LIFXController::GetUniqueID() return(module_mac); } -void LIFXController::SetColor(unsigned char red, unsigned char green, unsigned char blue) +unsigned int LIFXController::GetZoneCount() +{ + return(zone_count); +} + +void LIFXController::SetColors(std::vector colors) +{ + /*-------------------------*\ + | Non-multizone lifx device | + \*-------------------------*/ + if(!multizone) + { + SetColor(colors[0]); + + return; + } + + /*-------------------------------------------*\ + | Multizone lifx device with extended support | + \*-------------------------------------------*/ + if(extended_multizone) + { + SetZoneColors(colors); + + return; + } + + /*----------------------------------------------*\ + | Multizone lifx device without extended support | + \*----------------------------------------------*/ + for(size_t i = 0; i < zone_count; i++) + { + /*-----------------------------------------------------------------*\ + | Utilize caching to avoid setting all zones when 1 zone is changed | + \*-----------------------------------------------------------------*/ + if(cached_colors[i] == colors[i]) + { + continue; + } + + SetZoneColor(colors[i], (unsigned int)i); + cached_colors[i] = colors[i]; + } +} + +void LIFXController::FetchZoneCount() +{ + if(!multizone) + { + return; + } + + /*---------------------------*\ + | Send get color zones packet | + \*---------------------------*/ + data_buf_size = LIFX_PACKET_HEADER_LENGTH + LIFX_GET_COLOR_ZONES_PACKET_LENGTH; + data = new unsigned char[data_buf_size]; + memset(data, 0, data_buf_size); + + HeaderPacketSetDefaults(LIFX_PACKET_TYPE_GET_COLOR_ZONES); + + GetColorZonesPacketSetStartIndex(0); + GetColorZonesPacketSetEndIndex(0); + + port.udp_write((char*)data, (int)data_buf_size); + delete[] data; + + /*----------------------------*\ + | Listen for state zone packet | + \*----------------------------*/ + data_buf_size = LIFX_PACKET_HEADER_LENGTH + LIFX_STATE_ZONE_PACKET_LENGTH; + data = new unsigned char[data_buf_size]; + memset(data, 0, data_buf_size); + + port.set_receive_timeout(5, 0); + port.udp_listen((char*)data, (int)data_buf_size); + + /*-----------------*\ + | Validate response | + \*-----------------*/ + if(HeaderPacketGetSize() != data_buf_size || HeaderPacketGetProtocol() != LIFX_PROTOCOL || HeaderPacketGetPacketType() != LIFX_PACKET_TYPE_STATE_ZONE) + { + return; + } + + zone_count = StateZonePacketGetZonesCount(); + delete[] data; +} + +void LIFXController::SetColor(RGBColor color) +{ + /*---------------------*\ + | Send set color packet | + \*---------------------*/ + data_buf_size = LIFX_PACKET_HEADER_LENGTH + LIFX_SET_COLOR_PACKET_LENGTH; + data = new unsigned char[data_buf_size]; + memset(data, 0, data_buf_size); + + HeaderPacketSetDefaults(LIFX_PACKET_TYPE_SET_COLOR); + + hsbk_t hsbk; + RGBColorToHSBK(color, &hsbk); + + SetColorPacketSetHSBK(&hsbk); + SetColorPacketSetDuration(0); + + port.udp_write((char*)data, (int)data_buf_size); + delete[] data; +} + +void LIFXController::SetZoneColor(RGBColor color, unsigned int zone) +{ + /*---------------------------*\ + | Send set color zones packet | + \*---------------------------*/ + data_buf_size = LIFX_PACKET_HEADER_LENGTH + LIFX_SET_COLOR_ZONES_PACKET_LENGTH; + data = new unsigned char[data_buf_size]; + memset(data, 0, data_buf_size); + + HeaderPacketSetDefaults(LIFX_PACKET_TYPE_SET_COLOR_ZONES); + + SetColorZonesPacketSetStartIndex(zone); + SetColorZonesPacketSetEndIndex(zone); + + hsbk_t hsbk; + RGBColorToHSBK(color, &hsbk); + + SetColorZonesPacketSetHSBK(&hsbk); + SetColorZonesPacketSetDuration(0); + SetColorZonesPacketSetApply(LIFX_MULTIZONE_APPLICATION_REQUEST_APPLY); + + port.udp_write((char*)data, (int)data_buf_size); + delete[] data; +} + +void LIFXController::SetZoneColors(std::vector colors) +{ + /*------------------------------------*\ + | Send set extended color zones packet | + \*------------------------------------*/ + data_buf_size = LIFX_PACKET_HEADER_LENGTH + LIFX_SET_EXTENDED_COLOR_ZONES_PACKET_LENGTH; + data = new unsigned char[data_buf_size]; + memset(data, 0, data_buf_size); + + HeaderPacketSetDefaults(LIFX_PACKET_TYPE_SET_EXTENDED_COLOR_ZONES); + + SetExtendedColorZonesPacketSetDuration(0); + SetExtendedColorZonesPacketSetApply(LIFX_MULTIZONE_APPLICATION_REQUEST_APPLY); + SetExtendedColorZonesPacketSetZoneIndex(0); + SetExtendedColorZonesPacketSetColors(colors); + + port.udp_write((char*)data, (int)data_buf_size); + delete[] data; +} + +void LIFXController::RGBColorToHSBK(RGBColor color, hsbk_t* hsbk) { - RGBColor color = ToRGBColor(red, green, blue); hsv_t hsv; rgb2hsv(color, &hsv); - data = data_buf; - memset( data, 0, 49 ); - - source = 2; - sequence = 1; - - unsigned char target[8] = {0}; - - FrameHeader( 49, true, false, 0, source ); - FrameAddress( target, false, false, sequence ); - ProtocolAddress( 102 ); - - unsigned char * set_color = &data[36]; - - unsigned short hue = hsv.hue * (65536/360); - unsigned short saturation = hsv.saturation * (65536/256); - unsigned short brightness = hsv.value * (65536/256); - unsigned short kelvin = 3500; - unsigned int duration = 0; - - memcpy(&set_color[LIFX_SET_COLOR_OFFSET_HUE], &hue, sizeof(unsigned short)); - memcpy(&set_color[LIFX_SET_COLOR_OFFSET_SATURATION], &saturation, sizeof(unsigned short)); - memcpy(&set_color[LIFX_SET_COLOR_OFFSET_BRIGHTNESS], &brightness, sizeof(unsigned short)); - memcpy(&set_color[LIFX_SET_COLOR_OFFSET_KELVIN], &kelvin, sizeof(unsigned short)); - memcpy(&set_color[LIFX_SET_COLOR_OFFSET_DURATION], &duration, sizeof(unsigned int)); - - port.udp_write((char *)data, 49); + hsbk->hue = hsv.hue * (USHRT_MAX/360); + hsbk->saturation = hsv.saturation * (USHRT_MAX/256); + hsbk->brightness = hsv.value * (USHRT_MAX/256); + hsbk->kelvin = DEFAULT_KELVIN; } -void LIFXController::FrameHeader - ( - unsigned short size, - bool addressable, - bool tagged, - unsigned char origin, - unsigned int source - ) +/*----------------------------*\ +| Header packet helper methods | +\*----------------------------*/ +void LIFXController::HeaderPacketSetDefaults(unsigned short packet_type) { - unsigned short protocol = 1024; - memcpy(&data[LIFX_FRAME_HEADER_OFFSET_SIZE], &size, sizeof(unsigned short)); - memcpy(&data[LIFX_FRAME_HEADER_OFFSET_PROTOCOL], &protocol, sizeof(unsigned short)); - if(addressable) data[LIFX_FRAME_HEADER_OFFSET_FLAGS] |= (1 << 4); - if(tagged) data[LIFX_FRAME_HEADER_OFFSET_FLAGS] |= (1 << 5); - data[LIFX_FRAME_HEADER_OFFSET_FLAGS] |= origin << 6; - memcpy(&data[LIFX_FRAME_HEADER_OFFSET_SOURCE], &source, sizeof(unsigned int)); + /*-----*\ + | Frame | + \*-----*/ + HeaderPacketSetSize((unsigned short)data_buf_size); + HeaderPacketSetProtocol(); + HeaderPacketSetAddressable(true); + HeaderPacketSetTagged(false); + HeaderPacketSetOrigin(0); + HeaderPacketSetSource(2); + + /*-------------*\ + | Frame address | + \*-------------*/ + unsigned char target[TARGET_LENGTH] = {0}; + HeaderPacketSetTarget(target); + HeaderPacketSetResponseRequired(false); + HeaderPacketSetAcknowledgeRequired(false); + HeaderPacketSetSequence(++sequence); + + /*---------------*\ + | Protocol header | + \*---------------*/ + HeaderPacketSetPacketType(packet_type); } -void LIFXController::FrameAddress - ( - unsigned char * target, - bool res_required, - bool ack_required, - unsigned char sequence - ) +unsigned short LIFXController::HeaderPacketGetSize() { - memcpy(&data[LIFX_FRAME_ADDRESS_OFFSET_TARGET], target, 8); - - data[LIFX_FRAME_ADDRESS_OFFSET_FLAGS] = (1 << 0) & res_required; - data[LIFX_FRAME_ADDRESS_OFFSET_FLAGS] |= (1 << 1) & ack_required; - data[LIFX_FRAME_ADDRESS_OFFSET_SEQUENCE] = sequence; + return data[LIFX_HEADER_PACKET_OFFSET_SIZE]; } -void LIFXController::ProtocolAddress - ( - unsigned short type - ) +void LIFXController::HeaderPacketSetSize(unsigned short size) { - memcpy(&data[LIFX_PROTOCOL_HEADER_OFFSET_TYPE], &type, sizeof(unsigned short)); + memcpy(&data[LIFX_HEADER_PACKET_OFFSET_SIZE], &size, sizeof(unsigned short)); +} + +unsigned short LIFXController::HeaderPacketGetProtocol() +{ + unsigned short protocol; + memcpy(&protocol, &data[LIFX_HEADER_PACKET_OFFSET_PROTOCOL], sizeof(unsigned short)); + return protocol & 0x0FFF; +} + +void LIFXController::HeaderPacketSetProtocol(unsigned short protocol) +{ + data[LIFX_HEADER_PACKET_OFFSET_PROTOCOL] = protocol & 0xFF; + unsigned char current = data[LIFX_HEADER_PACKET_OFFSET_ADDRESSABLE_TAGGED_ORIGIN]; + data[LIFX_HEADER_PACKET_OFFSET_ADDRESSABLE_TAGGED_ORIGIN] = (current & 0xF0) | ((protocol >> 8) & 0x0F); +} + +void LIFXController::HeaderPacketSetAddressable(bool addressable) +{ + if(addressable) + { + data[LIFX_HEADER_PACKET_OFFSET_ADDRESSABLE_TAGGED_ORIGIN] |= 0x10; + } + else + { + data[LIFX_HEADER_PACKET_OFFSET_ADDRESSABLE_TAGGED_ORIGIN] &= ~0x10; + } +} + +void LIFXController::HeaderPacketSetTagged(bool tagged) +{ + if(tagged) + { + data[LIFX_HEADER_PACKET_OFFSET_ADDRESSABLE_TAGGED_ORIGIN] |= 0x20; + } + else + { + data[LIFX_HEADER_PACKET_OFFSET_ADDRESSABLE_TAGGED_ORIGIN] &= ~0x20; + } +} + +void LIFXController::HeaderPacketSetOrigin(unsigned char origin) +{ + data[LIFX_HEADER_PACKET_OFFSET_ADDRESSABLE_TAGGED_ORIGIN] = + (data[LIFX_HEADER_PACKET_OFFSET_ADDRESSABLE_TAGGED_ORIGIN] & 0xFC) | (origin & 0x03); +} + +void LIFXController::HeaderPacketSetSource(unsigned int source) +{ + memcpy(&data[LIFX_HEADER_PACKET_OFFSET_SOURCE], &source, sizeof(unsigned int)); +} + +void LIFXController::HeaderPacketSetTarget(unsigned char* target) +{ + memcpy(&data[LIFX_HEADER_PACKET_OFFSET_TARGET], target, TARGET_LENGTH); +} + +void LIFXController::HeaderPacketSetResponseRequired(bool response_required) +{ + if(response_required) + { + data[LIFX_HEADER_PACKET_OFFSET_RESPONSE_REQUIRED_ACKNOWLEDGE_REQUIRED] |= 0x01; + } + else + { + data[LIFX_HEADER_PACKET_OFFSET_RESPONSE_REQUIRED_ACKNOWLEDGE_REQUIRED] &= ~0x01; + } +} + +void LIFXController::HeaderPacketSetAcknowledgeRequired(bool acknowledge_required) +{ + if(acknowledge_required) + { + data[LIFX_HEADER_PACKET_OFFSET_RESPONSE_REQUIRED_ACKNOWLEDGE_REQUIRED] |= 0x02; + } + else + { + data[LIFX_HEADER_PACKET_OFFSET_RESPONSE_REQUIRED_ACKNOWLEDGE_REQUIRED] &= ~0x02; + } +} + +void LIFXController::HeaderPacketSetSequence(unsigned char sequence) +{ + data[LIFX_HEADER_PACKET_OFFSET_SEQUENCE] = sequence; +} + +unsigned short LIFXController::HeaderPacketGetPacketType() +{ + unsigned short packet_type_value; + memcpy(&packet_type_value, &data[LIFX_HEADER_PACKET_OFFSET_PACKET_TYPE], sizeof(unsigned short)); + + return packet_type_value; +} + +void LIFXController::HeaderPacketSetPacketType(unsigned short packet_type) +{ + memcpy(&data[LIFX_HEADER_PACKET_OFFSET_PACKET_TYPE], &packet_type, sizeof(unsigned short)); +} + +/*-------------------------------*\ +| Set color packet helper methods | +\*-------------------------------*/ +void LIFXController::SetColorPacketSetHSBK(hsbk_t* hsbk) +{ + memcpy(&data[LIFX_SET_COLOR_PACKET_OFFSET_HUE], &hsbk->hue, sizeof(unsigned short)); + memcpy(&data[LIFX_SET_COLOR_PACKET_OFFSET_SATURATION], &hsbk->saturation, sizeof(unsigned short)); + memcpy(&data[LIFX_SET_COLOR_PACKET_OFFSET_BRIGHTNESS], &hsbk->brightness, sizeof(unsigned short)); + memcpy(&data[LIFX_SET_COLOR_PACKET_OFFSET_KELVIN], &hsbk->kelvin, sizeof(unsigned short)); +} + +void LIFXController::SetColorPacketSetDuration(unsigned int duration) +{ + memcpy(&data[LIFX_SET_COLOR_PACKET_OFFSET_DURATION], &duration, sizeof(unsigned int)); +} + +/*-------------------------------------*\ +| Set color zones packet helper methods | +\*-------------------------------------*/ +void LIFXController::SetColorZonesPacketSetStartIndex(unsigned char start_index) +{ + memcpy(&data[LIFX_SET_COLOR_ZONES_PACKET_OFFSET_START_INDEX], &start_index, sizeof(unsigned char)); +} + +void LIFXController::SetColorZonesPacketSetEndIndex(unsigned char end_index) +{ + memcpy(&data[LIFX_SET_COLOR_ZONES_PACKET_OFFSET_END_INDEX], &end_index, sizeof(unsigned char)); +} + +void LIFXController::SetColorZonesPacketSetHSBK(hsbk_t* hsbk) +{ + memcpy(&data[LIFX_SET_COLOR_ZONES_PACKET_OFFSET_HUE], &hsbk->hue, sizeof(unsigned short)); + memcpy(&data[LIFX_SET_COLOR_ZONES_PACKET_OFFSET_SATURATION], &hsbk->saturation, sizeof(unsigned short)); + memcpy(&data[LIFX_SET_COLOR_ZONES_PACKET_OFFSET_BRIGHTNESS], &hsbk->brightness, sizeof(unsigned short)); + memcpy(&data[LIFX_SET_COLOR_ZONES_PACKET_OFFSET_KELVIN], &hsbk->kelvin, sizeof(unsigned short)); +} + +void LIFXController::SetColorZonesPacketSetDuration(unsigned int duration) +{ + memcpy(&data[LIFX_SET_COLOR_ZONES_PACKET_OFFSET_DURATION], &duration, sizeof(unsigned int)); +} + +void LIFXController::SetColorZonesPacketSetApply(unsigned char apply) +{ + memcpy(&data[LIFX_SET_COLOR_ZONES_PACKET_OFFSET_APPLY], &apply, sizeof(unsigned char)); +} + +/*-------------------------------------*\ +| Get color zones packet helper methods | +\*-------------------------------------*/ +void LIFXController::GetColorZonesPacketSetStartIndex(unsigned char start_index) +{ + memcpy(&data[LIFX_GET_COLOR_ZONES_PACKET_OFFSET_START_INDEX], &start_index, sizeof(unsigned char)); +} + +void LIFXController::GetColorZonesPacketSetEndIndex(unsigned char end_index) +{ + memcpy(&data[LIFX_GET_COLOR_ZONES_PACKET_OFFSET_END_INDEX], &end_index, sizeof(unsigned char)); +} + +/*--------------------------------*\ +| State zone packet helper methods | +\*--------------------------------*/ +unsigned char LIFXController::StateZonePacketGetZonesCount() +{ + unsigned char zones_count; + memcpy(&zones_count, &data[LIFX_STATE_ZONE_PACKET_OFFSET_ZONES_COUNT], sizeof(unsigned char)); + + return zones_count; +} + +/*----------------------------------------------*\ +| Set extended color zones packet helper methods | +\*----------------------------------------------*/ +void LIFXController::SetExtendedColorZonesPacketSetDuration(unsigned int duration) +{ + memcpy(&data[LIFX_SET_EXTENDED_COLOR_ZONES_PACKET_OFFSET_DURATION], &duration, sizeof(unsigned int)); +} + +void LIFXController::SetExtendedColorZonesPacketSetApply(unsigned char apply) +{ + memcpy(&data[LIFX_SET_EXTENDED_COLOR_ZONES_PACKET_OFFSET_APPLY], &apply, sizeof(unsigned char)); +} + +void LIFXController::SetExtendedColorZonesPacketSetZoneIndex(unsigned short zone_index) +{ + memcpy(&data[LIFX_SET_EXTENDED_COLOR_ZONES_PACKET_OFFSET_ZONE_INDEX], &zone_index, sizeof(unsigned short)); +} + +void LIFXController::SetExtendedColorZonesPacketSetColors(std::vector colors) +{ + unsigned char colors_count = (unsigned char)colors.size(); + memcpy(&data[LIFX_SET_EXTENDED_COLOR_ZONES_PACKET_OFFSET_COLORS_COUNT], &colors_count, sizeof(unsigned char)); + + for(size_t i = 0; i < colors.size(); i++) + { + hsbk_t hsbk; + RGBColorToHSBK(colors[i], &hsbk); + + size_t current_color_offset = LIFX_SET_EXTENDED_COLOR_ZONES_PACKET_OFFSET_COLORS + (i * HSBK_LENGTH); + + size_t hue_offset = current_color_offset; + size_t saturation_offset = hue_offset + sizeof(unsigned short); + size_t brightness_offset = saturation_offset + sizeof(unsigned short); + size_t kelvin_offset = brightness_offset + sizeof(unsigned short); + + memcpy(&data[hue_offset], &hsbk.hue, sizeof(unsigned short)); + memcpy(&data[saturation_offset], &hsbk.saturation, sizeof(unsigned short)); + memcpy(&data[brightness_offset], &hsbk.brightness, sizeof(unsigned short)); + memcpy(&data[kelvin_offset], &hsbk.kelvin, sizeof(unsigned short)); + } } diff --git a/Controllers/LIFXController/LIFXController.h b/Controllers/LIFXController/LIFXController.h index 8f41d1a6..05936dcd 100644 --- a/Controllers/LIFXController/LIFXController.h +++ b/Controllers/LIFXController/LIFXController.h @@ -1,92 +1,240 @@ /*---------------------------------------------------------*\ -| Definitions for LIFX | +| LIFXController.h | | | -| Adam Honse (calcprogrammer1@gmail.com), 2/5/2022 | +| Driver for LIFX | +| | +| Adam Honse (calcprogrammer1@gmail.com) 05 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "RGBController.h" -#include "net_port.h" - -#include -#include -#include - #pragma once +#include +#include +#include +#include "RGBController.h" +#include "net_port.h" + +#define LIFX_MANUFACTURER "LIFX" +#define LIFX_UDP_PORT "56700" +#define LIFX_PROTOCOL 1024 +#define TARGET_LENGTH 8 +#define DEFAULT_KELVIN 3500 +#define HSBK_LENGTH 8 + +/*---------------------*\ +| Packet size constants | +\*---------------------*/ +#define LIFX_PACKET_HEADER_LENGTH 36 +#define LIFX_SET_COLOR_PACKET_LENGTH 13 +#define LIFX_SET_COLOR_ZONES_PACKET_LENGTH 15 +#define LIFX_GET_COLOR_ZONES_PACKET_LENGTH 2 +#define LIFX_STATE_ZONE_PACKET_LENGTH 10 +#define LIFX_SET_EXTENDED_COLOR_ZONES_PACKET_LENGTH 664 + +/*---------------------------------------------------------------------------*\ +| https://lan.developer.lifx.com/docs/field-types#multizoneapplicationrequest | +\*---------------------------------------------------------------------------*/ enum { - LIFX_FRAME_HEADER_OFFSET_SIZE = 0, /* 2 bytes, size of the entire message in bytes */ - LIFX_FRAME_HEADER_OFFSET_PROTOCOL = 2, /* Protocol number, must be 1024 */ - LIFX_FRAME_HEADER_OFFSET_FLAGS = 3, /* Bits 0-3 are part of Protocol */ - /* Bit 4, addressable flag */ - /* Bit 5, tagged flag */ - /* Bit 6/7, origin value */ - LIFX_FRAME_HEADER_OFFSET_SOURCE = 4, /* Source identifier, unique value set by client*/ - LIFX_FRAME_ADDRESS_OFFSET_TARGET = 8, /* 6 byte device address (MAC) or zero */ - /* Last two bytes should be 0 */ - LIFX_FRAME_ADDRESS_OFFSET_FLAGS = 22, /* Bit 0, res_required flag */ - /* Bit 1, ack_required flag */ - LIFX_FRAME_ADDRESS_OFFSET_SEQUENCE = 23, /* Wrap around message sequence number */ - LIFX_PROTOCOL_HEADER_OFFSET_TYPE = 32, /* Message type determines the payload used */ + LIFX_MULTIZONE_APPLICATION_REQUEST_NO_APPLY = 0, + LIFX_MULTIZONE_APPLICATION_REQUEST_APPLY = 1, + LIFX_MULTIZONE_APPLICATION_REQUEST_APPLY_ONLY = 2 }; + +/*----------------------------------------------------------------*\ +| https://lan.developer.lifx.com/docs/representing-color-with-hsbk | +\*----------------------------------------------------------------*/ +typedef struct +{ + unsigned short hue; /* 0-360 value normalized to 0-65535 */ + unsigned short saturation; /* 0-1 value normalized to 0-65535 */ + unsigned short brightness; /* 0-1 value normalized to 0-65535 */ + unsigned short kelvin; /* 0-65535 value */ + /* Note: Devices may only support a subset of the full range. */ +} hsbk_t; + +/*-----------------*\ +| LIFX packet types | +\*-----------------*/ enum { - LIFX_SET_COLOR_OFFSET_HUE = 1, /* 16-bit hue value */ - LIFX_SET_COLOR_OFFSET_SATURATION = 3, /* 16-bit saturation value */ - LIFX_SET_COLOR_OFFSET_BRIGHTNESS = 5, /* 16-bit brightness value */ - LIFX_SET_COLOR_OFFSET_KELVIN = 7, /* 16-bit kelvin value */ - LIFX_SET_COLOR_OFFSET_DURATION = 9, /* 32-bit brightness value */ + LIFX_PACKET_TYPE_SET_COLOR = 102, + LIFX_PACKET_TYPE_SET_COLOR_ZONES = 501, + LIFX_PACKET_TYPE_GET_COLOR_ZONES = 502, + LIFX_PACKET_TYPE_STATE_ZONE = 503, + LIFX_PACKET_TYPE_SET_EXTENDED_COLOR_ZONES = 510 +}; + +/*-----------------------------------------------------*\ +| LIFX header packet offsets | +| https://lan.developer.lifx.com/docs/encoding-a-packet | +\*-----------------------------------------------------*/ +enum +{ + LIFX_HEADER_PACKET_OFFSET_SIZE = 0, /* 2 bytes, size of the entire message in bytes */ + LIFX_HEADER_PACKET_OFFSET_PROTOCOL = 2, /* Protocol number, must be 1024 */ + LIFX_HEADER_PACKET_OFFSET_ADDRESSABLE_TAGGED_ORIGIN = 3, /* Bits 0-3 are part of Protocol */ + /* Bit 4, addressable flag */ + /* Bit 5, tagged flag */ + /* Bit 6/7, origin value */ + LIFX_HEADER_PACKET_OFFSET_SOURCE = 4, /* Source identifier, unique value set by client */ + LIFX_HEADER_PACKET_OFFSET_TARGET = 8, /* 6 byte device address (MAC) or zero */ + /* Last two bytes should be 0 */ + LIFX_HEADER_PACKET_OFFSET_RESPONSE_REQUIRED_ACKNOWLEDGE_REQUIRED = 22, /* Bit 0, res_required flag */ + /* Bit 1, ack_required flag */ + LIFX_HEADER_PACKET_OFFSET_SEQUENCE = 23, /* Wrap around message sequence number */ + LIFX_HEADER_PACKET_OFFSET_PACKET_TYPE = 32 /* Message type determines the payload used */ +}; + +/*---------------------------------------------------------------------------*\ +| LIFX set color packet offsets | +| https://lan.developer.lifx.com/docs/changing-a-device#setcolor---packet-102 | +\*---------------------------------------------------------------------------*/ +enum +{ + /* 1 byte, reserved */ + LIFX_SET_COLOR_PACKET_OFFSET_HUE = LIFX_PACKET_HEADER_LENGTH + 1, /* 2 bytes, hue as a 0-65535 value */ + LIFX_SET_COLOR_PACKET_OFFSET_SATURATION = LIFX_PACKET_HEADER_LENGTH + 3, /* 2 bytes, saturation as a 0-65535 value */ + LIFX_SET_COLOR_PACKET_OFFSET_BRIGHTNESS = LIFX_PACKET_HEADER_LENGTH + 5, /* 2 bytes, brightness as a 0-65535 value */ + LIFX_SET_COLOR_PACKET_OFFSET_KELVIN = LIFX_PACKET_HEADER_LENGTH + 7, /* 2 bytes, kelvin as a 0-65535 value. */ + /* Note: The actual max for this is device specific */ + LIFX_SET_COLOR_PACKET_OFFSET_DURATION = LIFX_PACKET_HEADER_LENGTH + 9, /* 4 bytes, transition time in ms */ +}; + +/*--------------------------------------------------------------------------------*\ +| LIFX set color zones packet offsets | +| https://lan.developer.lifx.com/docs/changing-a-device#setcolorzones---packet-501 | +\*--------------------------------------------------------------------------------*/ +enum +{ + LIFX_SET_COLOR_ZONES_PACKET_OFFSET_START_INDEX = LIFX_PACKET_HEADER_LENGTH + 0, /* 1 byte, the first zone in the segment we are changing */ + LIFX_SET_COLOR_ZONES_PACKET_OFFSET_END_INDEX = LIFX_PACKET_HEADER_LENGTH + 1, /* 1 byte, the last zone in the segment we are changing */ + LIFX_SET_COLOR_ZONES_PACKET_OFFSET_HUE = LIFX_PACKET_HEADER_LENGTH + 2, /* 2 bytes, hue as a 0-65535 value */ + LIFX_SET_COLOR_ZONES_PACKET_OFFSET_SATURATION = LIFX_PACKET_HEADER_LENGTH + 4, /* 2 bytes, saturation as a 0-65535 value */ + LIFX_SET_COLOR_ZONES_PACKET_OFFSET_BRIGHTNESS = LIFX_PACKET_HEADER_LENGTH + 6, /* 2 bytes, brightness as a 0-65535 value */ + LIFX_SET_COLOR_ZONES_PACKET_OFFSET_KELVIN = LIFX_PACKET_HEADER_LENGTH + 8, /* 2 bytes, kelvin as a 0-65535 value. */ + /* Note: The actual max for this is device specific */ + LIFX_SET_COLOR_ZONES_PACKET_OFFSET_DURATION = LIFX_PACKET_HEADER_LENGTH + 10, /* 4 bytes, transition time in ms */ + LIFX_SET_COLOR_ZONES_PACKET_OFFSET_APPLY = LIFX_PACKET_HEADER_LENGTH + 14 /* 1 byte, multizone application request */ +}; + +/*-------------------------------------------------------------------------------------------*\ +| LIFX get color zones packet offsets | +| https://lan.developer.lifx.com/docs/querying-the-device-for-data#getcolorzones---packet-502 | +\*-------------------------------------------------------------------------------------------*/ +enum +{ + LIFX_GET_COLOR_ZONES_PACKET_OFFSET_START_INDEX = LIFX_PACKET_HEADER_LENGTH + 0, /* 1 byte, The first zone you want to get information from */ + LIFX_GET_COLOR_ZONES_PACKET_OFFSET_END_INDEX = LIFX_PACKET_HEADER_LENGTH + 1, /* 1 byte, The second zone you want to get information from */ +}; + +/*-------------------------------------------------------------------------------*\ +| LIFX state zone packet offsets | +| https://lan.developer.lifx.com/docs/information-messages#statezone---packet-503 | +\*-------------------------------------------------------------------------------*/ +enum +{ + LIFX_STATE_ZONE_PACKET_OFFSET_ZONES_COUNT = LIFX_PACKET_HEADER_LENGTH + 0, /* 1 byte, the total number of zones on the strip. */ + LIFX_STATE_ZONE_PACKET_OFFSET_ZONE_INDEX = LIFX_PACKET_HEADER_LENGTH + 1, /* 1 byte, the zone this packet refers to. */ + LIFX_STATE_ZONE_PACKET_OFFSET_HUE = LIFX_PACKET_HEADER_LENGTH + 2, /* 2 bytes, hue as a 0-65535 value */ + LIFX_STATE_ZONE_PACKET_OFFSET_SATURATION = LIFX_PACKET_HEADER_LENGTH + 4, /* 2 bytes, saturation as a 0-65535 value */ + LIFX_STATE_ZONE_PACKET_OFFSET_BRIGHTNESS = LIFX_PACKET_HEADER_LENGTH + 6, /* 2 bytes, brightness as a 0-65535 value */ + LIFX_STATE_ZONE_PACKET_OFFSET_KELVIN = LIFX_PACKET_HEADER_LENGTH + 8, /* 2 bytes, kelvin as a 0-65535 value. */ + /* Note: The actual max for this is device specific */ +}; + +/*----------------------------------------------------------------------------------------*\ +| LIFX set extended color zones packet offsets | +| https://lan.developer.lifx.com/docs/changing-a-device#setextendedcolorzones---packet-510 | +\*----------------------------------------------------------------------------------------*/ +enum +{ + LIFX_SET_EXTENDED_COLOR_ZONES_PACKET_OFFSET_DURATION = LIFX_PACKET_HEADER_LENGTH + 0, /* 4 bytes, transition time in ms */ + LIFX_SET_EXTENDED_COLOR_ZONES_PACKET_OFFSET_APPLY = LIFX_PACKET_HEADER_LENGTH + 4, /* 1 byte, multizone application request */ + LIFX_SET_EXTENDED_COLOR_ZONES_PACKET_OFFSET_ZONE_INDEX = LIFX_PACKET_HEADER_LENGTH + 5, /* 2 bytes, The first zone to apply colors from. */ + /* If the light has more than 82 zones, then */ + /* send multiple messages with different indices */ + /* to update the whole device. */ + LIFX_SET_EXTENDED_COLOR_ZONES_PACKET_OFFSET_COLORS_COUNT = LIFX_PACKET_HEADER_LENGTH + 7, /* 1 byte, The number of colors in the colors field */ + LIFX_SET_EXTENDED_COLOR_ZONES_PACKET_OFFSET_COLORS = LIFX_PACKET_HEADER_LENGTH + 8, /* 656 bytes (82 * 4 * 2), 82 HSBK values to change */ + /* the device with */ }; class LIFXController { public: - LIFXController(std::string ip, std::string name); + LIFXController(std::string ip, std::string name, bool multizone, bool extended_multizone); ~LIFXController(); - std::string GetLocation(); - std::string GetName(); - std::string GetVersion(); - std::string GetManufacturer(); - std::string GetUniqueID(); + std::string GetLocation(); + std::string GetName(); + std::string GetVersion(); + std::string GetManufacturer(); + std::string GetUniqueID(); + unsigned int GetZoneCount(); - void SetColor(unsigned char red, unsigned char green, unsigned char blue); + void FetchZoneCount(); + void SetColors(std::vector colors); private: - unsigned char data_buf[49]; - unsigned char* data; - unsigned char sequence; - unsigned int source; - std::string name; - std::string firmware_version; - std::string module_name; - std::string module_mac; - std::string location; - net_port port; + RGBColor cached_colors[UCHAR_MAX]; + unsigned int zone_count; + size_t data_buf_size; + unsigned char* data; + unsigned char sequence; + std::string name; + std::string firmware_version; + std::string module_name; + std::string module_mac; + std::string location; + net_port port; + bool multizone; + bool extended_multizone; - /*-----------------------------------------------------*\ - | Functions for filling in LIFX header | - \*-----------------------------------------------------*/ - void FrameHeader - ( - unsigned short size, - bool addressable, - bool tagged, - unsigned char origin, - unsigned int source - ); + void SetColor(RGBColor color); + void SetZoneColor(RGBColor color, unsigned int zone); + void SetZoneColors(std::vector colors); + void RGBColorToHSBK(RGBColor color, hsbk_t* hsbk); - void FrameAddress - ( - unsigned char * target, - bool res_required, - bool ack_required, - unsigned char sequence - ); + /*---------------------*\ + | Packet helper methods | + \*---------------------*/ + void HeaderPacketSetDefaults(unsigned short packet_type); + unsigned short HeaderPacketGetSize(); + void HeaderPacketSetSize(unsigned short size); + unsigned short HeaderPacketGetProtocol(); + void HeaderPacketSetProtocol(unsigned short protocol=LIFX_PROTOCOL); + void HeaderPacketSetAddressable(bool addressable=true); + void HeaderPacketSetTagged(bool tagged=false); + void HeaderPacketSetOrigin(unsigned char origin=0); + void HeaderPacketSetSource(unsigned int source=2); + void HeaderPacketSetTarget(unsigned char* target); + void HeaderPacketSetResponseRequired(bool response_required=false); + void HeaderPacketSetAcknowledgeRequired(bool acknowledge_required=false); + void HeaderPacketSetSequence(unsigned char sequence); + unsigned short HeaderPacketGetPacketType(); + void HeaderPacketSetPacketType(unsigned short packet_type); - void ProtocolAddress - ( - unsigned short type - ); + void SetColorPacketSetDuration(unsigned int duration=0); + void SetColorPacketSetHSBK(hsbk_t* hsbk); + + void SetColorZonesPacketSetStartIndex(unsigned char start_index); + void SetColorZonesPacketSetEndIndex(unsigned char end_index); + void SetColorZonesPacketSetHSBK(hsbk_t* hsbk); + void SetColorZonesPacketSetDuration(unsigned int duration=0); + void SetColorZonesPacketSetApply(unsigned char apply=LIFX_MULTIZONE_APPLICATION_REQUEST_APPLY); + + void GetColorZonesPacketSetStartIndex(unsigned char start_index=0); + void GetColorZonesPacketSetEndIndex(unsigned char end_index=0); + + unsigned char StateZonePacketGetZonesCount(); + + void SetExtendedColorZonesPacketSetDuration(unsigned int duration=0); + void SetExtendedColorZonesPacketSetApply(unsigned char apply=LIFX_MULTIZONE_APPLICATION_REQUEST_APPLY); + void SetExtendedColorZonesPacketSetZoneIndex(unsigned short zone_index=0); + void SetExtendedColorZonesPacketSetColors(std::vector colors); }; diff --git a/Controllers/LIFXController/LIFXControllerDetect.cpp b/Controllers/LIFXController/LIFXControllerDetect.cpp index a9ddf44b..4e0166f5 100644 --- a/Controllers/LIFXController/LIFXControllerDetect.cpp +++ b/Controllers/LIFXController/LIFXControllerDetect.cpp @@ -1,11 +1,18 @@ +/*---------------------------------------------------------*\ +| LIFXControllerDetect.cpp | +| | +| Detector for LIFX | +| | +| Adam Honse (calcprogrammer1@gmail.com) 05 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "LIFXController.h" -#include "RGBController.h" #include "RGBController_LIFX.h" #include "SettingsManager.h" -#include -#include -#include /******************************************************************************************\ * * @@ -33,10 +40,14 @@ void DetectLIFXControllers() { if(lifx_settings["devices"][device_idx].contains("ip")) { - std::string lifx_ip = lifx_settings["devices"][device_idx]["ip"]; - std::string name = lifx_settings["devices"][device_idx]["name"]; + std::string lifx_ip = lifx_settings["devices"][device_idx]["ip"]; + std::string name = lifx_settings["devices"][device_idx]["name"]; + bool multizone = lifx_settings["devices"][device_idx]["multizone"]; + bool extended_multizone = lifx_settings["devices"][device_idx]["extended_multizone"]; + + LIFXController* controller = new LIFXController(lifx_ip, name, multizone, extended_multizone); + controller->FetchZoneCount(); - LIFXController* controller = new LIFXController(lifx_ip, name); RGBController_LIFX* rgb_controller = new RGBController_LIFX(controller); ResourceManager::get()->RegisterRGBController(rgb_controller); diff --git a/Controllers/LIFXController/RGBController_LIFX.cpp b/Controllers/LIFXController/RGBController_LIFX.cpp index 99dbe4cf..93bf6525 100644 --- a/Controllers/LIFXController/RGBController_LIFX.cpp +++ b/Controllers/LIFXController/RGBController_LIFX.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_LIFX.cpp | -| | -| Generic RGB Interface for LIFX | -| | -| Adam Honse (CalcProgrammer1) 2/5/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LIFX.cpp | +| | +| RGBController for LIFX | +| | +| Adam Honse (calcprogrammer1@gmail.com) 05 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_LIFX.h" @@ -49,18 +52,54 @@ RGBController_LIFX::~RGBController_LIFX() void RGBController_LIFX::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"; + unsigned int zone_count = controller->GetZoneCount(); - leds.push_back(new_led); + /*---------------------------------------------------------*\ + | If there is only one zone, set up a single LED | + \*---------------------------------------------------------*/ + if(zone_count <= 1) + { + 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); + } + else + { + /*---------------------------------------------------------*\ + | Set up multiple LEDs | + \*---------------------------------------------------------*/ + led_zone.name = "RGB Light Strip"; + led_zone.type = ZONE_TYPE_LINEAR; + led_zone.leds_min = 1; + led_zone.leds_max = zone_count; + led_zone.leds_count = zone_count; + led_zone.matrix_map = NULL; + + zones.push_back(led_zone); + + for(size_t zone_idx = 0; zone_idx < zone_count; zone_idx++) + { + + /*---------------------------------------------------------*\ + | Set up LEDs | + \*---------------------------------------------------------*/ + led new_led; + + new_led.name = "LED " + std::to_string(zone_idx); + + leds.push_back(new_led); + } + } SetupColors(); } @@ -74,11 +113,7 @@ void RGBController_LIFX::ResizeZone(int /*zone*/, int /*new_size*/) void RGBController_LIFX::DeviceUpdateLEDs() { - unsigned char red = RGBGetRValue(colors[0]); - unsigned char grn = RGBGetGValue(colors[0]); - unsigned char blu = RGBGetBValue(colors[0]); - - controller->SetColor(red, grn, blu); + controller->SetColors(colors); } void RGBController_LIFX::UpdateZoneLEDs(int /*zone*/) diff --git a/Controllers/LIFXController/RGBController_LIFX.h b/Controllers/LIFXController/RGBController_LIFX.h index 7c73da6f..29b5c960 100644 --- a/Controllers/LIFXController/RGBController_LIFX.h +++ b/Controllers/LIFXController/RGBController_LIFX.h @@ -1,12 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_LIFX.h | -| | -| Generic RGB Interface for LIFX | -| | -| Adam Honse (CalcProgrammer1) 2/5/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LIFX.cpp | +| | +| RGBController for LIFX | +| | +| Adam Honse (calcprogrammer1@gmail.com) 05 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "LIFXController.h" diff --git a/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.cpp b/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.cpp index 5f4f345f..cf62f47a 100644 --- a/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.cpp +++ b/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.cpp @@ -1,32 +1,23 @@ -/*-----------------------------------------*\ -| LegoDimensionsToypadBaseController.h | -| | -| Driver for Lego Dimensions ToypadBase | -| controller | -| | -| Guimard Morgan (morg) 06/02/2023 | -\*-----------------------------------------*/ -#include "LegoDimensionsToypadBaseController.h" -#include +/*---------------------------------------------------------*\ +| LegoDimensionsToypadBaseController.cpp | +| | +| Driver for Lego Dimensions Toypad Base | +| | +| Morgan Guimard (morg) 02 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -LegoDimensionsToypadBaseController::LegoDimensionsToypadBaseController(hid_device* dev_handle, const hid_device_info& info) +#include +#include "LegoDimensionsToypadBaseController.h" +#include "StringUtils.h" + +LegoDimensionsToypadBaseController::LegoDimensionsToypadBaseController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) { dev = dev_handle; location = info.path; - version = ""; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } + name = dev_name; Activate(); } @@ -41,14 +32,22 @@ std::string LegoDimensionsToypadBaseController::GetDeviceLocation() return("HID: " + location); } -std::string LegoDimensionsToypadBaseController::GetSerialString() +std::string LegoDimensionsToypadBaseController::GetNameString() { - return(serial_number); + return(name); } -std::string LegoDimensionsToypadBaseController::GetFirmwareVersion() +std::string LegoDimensionsToypadBaseController::GetSerialString() { - return(version); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } void LegoDimensionsToypadBaseController::Activate() diff --git a/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.h b/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.h index 26e0545c..5f0189ae 100644 --- a/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.h +++ b/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.h @@ -1,16 +1,19 @@ -/*-----------------------------------------*\ -| LegoDimensionsToypadBaseController.h | -| | -| Driver for Lego Dimensions ToypadBase | -| controller - header file | -| | -| Guimard Morgan (morg) 06/02/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LegoDimensionsToypadBaseController.h | +| | +| Driver for Lego Dimensions Toypad Base | +| | +| Morgan Guimard (morg) 02 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once -#include "RGBController.h" #include -#include +#include +#include "RGBController.h" #define LEGO_DIMENSIONS_TOYPAD_BASE_REPORT_ID 0x55 #define LEGO_DIMENSIONS_TOYPAD_BASE_PACKET_LENGTH 32 @@ -32,12 +35,12 @@ enum class LegoDimensionsToypadBaseController { public: - LegoDimensionsToypadBaseController(hid_device* dev_handle, const hid_device_info& info); + LegoDimensionsToypadBaseController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); ~LegoDimensionsToypadBaseController(); - std::string GetSerialString(); std::string GetDeviceLocation(); - std::string GetFirmwareVersion(); + std::string GetNameString(); + std::string GetSerialString(); void SetDirect(unsigned char zone, RGBColor color); void SetMode(unsigned char zone, unsigned char mode_value, uint8_t speed, RGBColor color); @@ -47,7 +50,7 @@ protected: private: std::string location; - std::string serial_number; + std::string name; std::string version; void Activate(); diff --git a/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseControllerDetect.cpp b/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseControllerDetect.cpp index 3a4b30cd..812a040a 100644 --- a/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseControllerDetect.cpp +++ b/Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseControllerDetect.cpp @@ -1,6 +1,16 @@ +/*---------------------------------------------------------*\ +| LegoDimensionsToypadBaseControllerDetect.cpp | +| | +| Detector for Lego Dimensions Toypad Base | +| | +| Morgan Guimard (morg) 02 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "LegoDimensionsToypadBaseController.h" -#include "RGBController.h" #include "RGBController_LegoDimensionsToypadBase.h" /*---------------------------------------------------------*\ @@ -19,9 +29,9 @@ void DetectLegoDimensionsToypadBaseControllers(hid_device_info* info, const std: if(dev) { - LegoDimensionsToypadBaseController* controller = new LegoDimensionsToypadBaseController(dev, *info); + LegoDimensionsToypadBaseController* controller = new LegoDimensionsToypadBaseController(dev, *info, name); RGBController_LegoDimensionsToypadBase* rgb_controller = new RGBController_LegoDimensionsToypadBase(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } diff --git a/Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.cpp b/Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.cpp index d6ad048e..5f7da700 100644 --- a/Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.cpp +++ b/Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.cpp @@ -1,16 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_LegoDimensionsToypadBase.h | -| | -| Generic RGB Interface for OpenRGB | -| Lego Dimensions Toypad Base USB Driver | -| | -| Guimard Morgan (morg) 06/02/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LegoDimensionsToypadBase.cpp | +| | +| RGBController for Lego Dimensions Toypad Base | +| | +| Morgan Guimard (morg) 02 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_LegoDimensionsToypadBase.h" - -#include #include +#include +#include "RGBController_LegoDimensionsToypadBase.h" /**------------------------------------------------------------------*\ @name Lego Dimensions Toypad Base @@ -25,13 +26,14 @@ RGBController_LegoDimensionsToypadBase::RGBController_LegoDimensionsToypadBase(LegoDimensionsToypadBaseController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; + + name = controller->GetNameString(); vendor = "Logic3"; type = DEVICE_TYPE_LEDSTRIP; description = "Lego Dimensions Toypad Base"; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); mode Direct; Direct.name = "Direct"; @@ -130,5 +132,8 @@ void RGBController_LegoDimensionsToypadBase::UpdateSingleLED(int /*led*/) void RGBController_LegoDimensionsToypadBase::DeviceUpdateMode() { - controller->SetMode(0, modes[active_mode].value, modes[active_mode].speed, modes[active_mode].colors[0]); + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + controller->SetMode(0, modes[active_mode].value, modes[active_mode].speed, modes[active_mode].colors[0]); + } } diff --git a/Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.h b/Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.h index 490a6f9f..a5d2f1d1 100644 --- a/Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.h +++ b/Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_LegoDimensionsToypadBase.h | -| | -| Generic RGB Interface for OpenRGB | -| Lego Dimensions Toypad Base USB Driver | -| | -| Guimard Morgan (morg) 06/02/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LegoDimensionsToypadBase.h | +| | +| RGBController for Lego Dimensions Toypad Base | +| | +| Morgan Guimard (morg) 02 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/LenovoControllers/Lenovo4ZoneUSBController.cpp b/Controllers/LenovoControllers/Lenovo4ZoneUSBController.cpp deleted file mode 100644 index 36cc8d22..00000000 --- a/Controllers/LenovoControllers/Lenovo4ZoneUSBController.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/*-------------------------------------------------------------------*\ -| Lenovo4ZoneUSBController.cpp | -| | -| interface for Lenovo 4-Zones Devices | -\*-------------------------------------------------------------------*/ - -#include -#include "Lenovo4ZoneUSBController.h" -#include "LogManager.h" - -Lenovo4ZoneUSBController::Lenovo4ZoneUSBController(hid_device* dev_handle, const char* path, uint16_t in_pid) -{ - const uint8_t sz = HID_MAX_STR; - wchar_t tmp[sz]; - - dev = dev_handle; - location = path; - pid = in_pid; - - hid_get_manufacturer_string(dev, tmp, sz); - std::wstring w_tmp = std::wstring(tmp); - name = std::string(w_tmp.begin(), w_tmp.end()); - - hid_get_product_string(dev, tmp, sz); - w_tmp = std::wstring(tmp); - name.append(" ").append(std::string(w_tmp.begin(), w_tmp.end())); -} - -Lenovo4ZoneUSBController::~Lenovo4ZoneUSBController() -{ - hid_close(dev); -} - -void Lenovo4ZoneUSBController::setMode(const KeyboardState &in_mode) -{ - uint8_t buffer[LENOVO_4_ZONE_HID_PACKET_SIZE] = {in_mode.header[0], in_mode.header[1], in_mode.effect, in_mode.speed, in_mode.brightness, in_mode.zone0_rgb[0], in_mode.zone0_rgb[1], in_mode.zone0_rgb[2], in_mode.zone1_rgb[0], in_mode.zone1_rgb[1], in_mode.zone1_rgb[2], in_mode.zone2_rgb[0], in_mode.zone2_rgb[1], in_mode.zone3_rgb[2], in_mode.zone3_rgb[0], in_mode.zone3_rgb[1], in_mode.zone3_rgb[2], 0x00, in_mode.wave_ltr, in_mode.wave_rtl}; - hid_send_feature_report(dev, buffer, LENOVO_4_ZONE_HID_PACKET_SIZE); -} - -uint16_t Lenovo4ZoneUSBController::getPid() -{ - return pid; -} - -std::string Lenovo4ZoneUSBController::getName() -{ - return name; -} - -std::string Lenovo4ZoneUSBController::getLocation() -{ - return location; -} diff --git a/Controllers/LenovoControllers/Lenovo4ZoneUSBController.h b/Controllers/LenovoControllers/Lenovo4ZoneUSBController.h deleted file mode 100644 index d7364186..00000000 --- a/Controllers/LenovoControllers/Lenovo4ZoneUSBController.h +++ /dev/null @@ -1,57 +0,0 @@ -/*-------------------------------------------------------------------*\ -| Lenovo4ZoneUSBController.h | -| | -| interface for Lenovo 4-Zones Devices | -\*-------------------------------------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "LogManager.h" -#include "LenovoDevices4Zone.h" - -#include -#include -#include -#include -#include - -#ifndef HID_MAX_STR -#define HID_MAX_STR 255 -#endif - -#define LENOVO_4_ZONE_HID_PACKET_SIZE 33 - -class Lenovo4ZoneUSBController -{ - public: - /*--------------*\ - |ctor(s) and dtor| - \*--------------*/ - Lenovo4ZoneUSBController(hid_device* dev_handle, const char* path, uint16_t in_pid); - ~Lenovo4ZoneUSBController(); - - void setMode(const KeyboardState &in_mode); - - /*--------------*\ - |device functions| - \*--------------*/ - uint16_t getPid(); - std::string getName(); - std::string getLocation(); - - private: - /*--------------*\ - |data members | - \*--------------*/ - std::string name; - hid_device *dev; - std::string location; - uint16_t pid; - KeyboardState mode; - - /*--------------*\ - |device functions| - \*--------------*/ - void sendBasicInstruction(uint8_t instruction); -}; diff --git a/Controllers/LenovoControllers/Lenovo4ZoneUSBController/Lenovo4ZoneUSBController.cpp b/Controllers/LenovoControllers/Lenovo4ZoneUSBController/Lenovo4ZoneUSBController.cpp new file mode 100644 index 00000000..020fbcb6 --- /dev/null +++ b/Controllers/LenovoControllers/Lenovo4ZoneUSBController/Lenovo4ZoneUSBController.cpp @@ -0,0 +1,59 @@ +/*---------------------------------------------------------*\ +| Lenovo4ZoneUSBController.cpp | +| | +| Driver for Lenovo 4-Zone devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Lenovo4ZoneUSBController.h" +#include "LogManager.h" +#include "StringUtils.h" + +Lenovo4ZoneUSBController::Lenovo4ZoneUSBController(hid_device* dev_handle, const char* path, uint16_t in_pid, std::string dev_name) +{ + dev = dev_handle; + location = path; + pid = in_pid; + name = dev_name; +} + +Lenovo4ZoneUSBController::~Lenovo4ZoneUSBController() +{ + hid_close(dev); +} + +void Lenovo4ZoneUSBController::setMode(const KeyboardState &in_mode) +{ + uint8_t buffer[LENOVO_4_ZONE_HID_PACKET_SIZE] = + { + in_mode.header[0], in_mode.header[1], + in_mode.effect, + in_mode.speed, + in_mode.brightness, + in_mode.zone0_rgb[0], in_mode.zone0_rgb[1], in_mode.zone0_rgb[2], + in_mode.zone1_rgb[0], in_mode.zone1_rgb[1], in_mode.zone1_rgb[2], + in_mode.zone2_rgb[0], in_mode.zone2_rgb[1], in_mode.zone2_rgb[2], + in_mode.zone3_rgb[0], in_mode.zone3_rgb[1], in_mode.zone3_rgb[2], + 0x00, + in_mode.wave_ltr, in_mode.wave_rtl + }; + hid_send_feature_report(dev, buffer, LENOVO_4_ZONE_HID_PACKET_SIZE); +} + +uint16_t Lenovo4ZoneUSBController::getPid() +{ + return pid; +} + +std::string Lenovo4ZoneUSBController::getName() +{ + return name; +} + +std::string Lenovo4ZoneUSBController::getLocation() +{ + return location; +} diff --git a/Controllers/LenovoControllers/Lenovo4ZoneUSBController/Lenovo4ZoneUSBController.h b/Controllers/LenovoControllers/Lenovo4ZoneUSBController/Lenovo4ZoneUSBController.h new file mode 100644 index 00000000..bb8a4a51 --- /dev/null +++ b/Controllers/LenovoControllers/Lenovo4ZoneUSBController/Lenovo4ZoneUSBController.h @@ -0,0 +1,59 @@ +/*---------------------------------------------------------*\ +| Lenovo4ZoneUSBController.h | +| | +| Driver for Lenovo 4-Zone devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include +#include +#include "RGBController.h" +#include "LogManager.h" +#include "LenovoDevices4Zone.h" + +#ifndef HID_MAX_STR +#define HID_MAX_STR 255 +#endif + +#define LENOVO_4_ZONE_HID_PACKET_SIZE 33 + +class Lenovo4ZoneUSBController +{ + public: + /*--------------*\ + |ctor(s) and dtor| + \*--------------*/ + Lenovo4ZoneUSBController(hid_device* dev_handle, const char* path, uint16_t in_pid, std::string dev_name); + ~Lenovo4ZoneUSBController(); + + void setMode(const KeyboardState &in_mode); + + /*--------------*\ + |device functions| + \*--------------*/ + uint16_t getPid(); + std::string getName(); + std::string getLocation(); + + private: + /*--------------*\ + |data members | + \*--------------*/ + std::string name; + hid_device *dev; + std::string location; + uint16_t pid; + KeyboardState mode; + + /*--------------*\ + |device functions| + \*--------------*/ + void sendBasicInstruction(uint8_t instruction); +}; diff --git a/Controllers/LenovoControllers/Lenovo4ZoneUSBController/Lenovo4ZoneUSBControllerDetect.cpp b/Controllers/LenovoControllers/Lenovo4ZoneUSBController/Lenovo4ZoneUSBControllerDetect.cpp new file mode 100644 index 00000000..a1439cf8 --- /dev/null +++ b/Controllers/LenovoControllers/Lenovo4ZoneUSBController/Lenovo4ZoneUSBControllerDetect.cpp @@ -0,0 +1,50 @@ +/*---------------------------------------------------------*\ +| Lenovo4ZoneUSBControllerDetect.cpp | +| | +| Detector for Lenovo 4-Zone devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "Lenovo4ZoneUSBController.h" +#include "LenovoDevices4Zone.h" +#include "RGBController_Lenovo4ZoneUSB.h" + +/*-----------------------------------------------------*\ +| vendor IDs | +\*-----------------------------------------------------*/ +#define ITE_VID 0x048D + +/*-----------------------------------------------------*\ +| Interface, Usage, and Usage Page | +\*-----------------------------------------------------*/ +enum +{ + LENOVO_PAGE = 0xFF89, + LENOVO_USAGE = 0xCC +}; + +void DetectLenovo4ZoneUSBControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + Lenovo4ZoneUSBController* controller = new Lenovo4ZoneUSBController(dev, info->path, info->product_id, name); + RGBController_Lenovo4ZoneUSB* rgb_controller = new RGBController_Lenovo4ZoneUSB(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR_PU("Lenovo Ideapad 3-15ach6", DetectLenovo4ZoneUSBControllers, ITE_VID, IDEAPAD_315ACH6, LENOVO_PAGE, LENOVO_USAGE); +REGISTER_HID_DETECTOR_PU("Lenovo 5 2023", DetectLenovo4ZoneUSBControllers, ITE_VID, LEGION_5_2023_PID, LENOVO_PAGE, LENOVO_USAGE); +REGISTER_HID_DETECTOR_PU("Lenovo 5 2023 Ideapad", DetectLenovo4ZoneUSBControllers, ITE_VID, LEGION_5_2023_IDEAPAD_PID, LENOVO_PAGE, LENOVO_USAGE); +REGISTER_HID_DETECTOR_PU("Lenovo 5 2022", DetectLenovo4ZoneUSBControllers, ITE_VID, LEGION_5_2022_PID, LENOVO_PAGE, LENOVO_USAGE); +REGISTER_HID_DETECTOR_PU("Lenovo 5 2022 Ideapad", DetectLenovo4ZoneUSBControllers, ITE_VID, LEGION_5_2022_IDEAPAD_PID, LENOVO_PAGE, LENOVO_USAGE); +REGISTER_HID_DETECTOR_PU("Lenovo 5 2021", DetectLenovo4ZoneUSBControllers, ITE_VID, LEGION_5_2021_PID, LENOVO_PAGE, LENOVO_USAGE); +REGISTER_HID_DETECTOR_PU("Lenovo 5 2021 Ideapad", DetectLenovo4ZoneUSBControllers, ITE_VID, LEGION_5_2021_IDEAPAD_PID, LENOVO_PAGE, LENOVO_USAGE); +REGISTER_HID_DETECTOR_PU("Lenovo 5 2020", DetectLenovo4ZoneUSBControllers, ITE_VID, LEGION_5_2020_PID, LENOVO_PAGE, LENOVO_USAGE); diff --git a/Controllers/LenovoControllers/LenovoDevices4Zone.h b/Controllers/LenovoControllers/Lenovo4ZoneUSBController/LenovoDevices4Zone.h similarity index 80% rename from Controllers/LenovoControllers/LenovoDevices4Zone.h rename to Controllers/LenovoControllers/Lenovo4ZoneUSBController/LenovoDevices4Zone.h index 72d6db47..3af6ad4a 100644 --- a/Controllers/LenovoControllers/LenovoDevices4Zone.h +++ b/Controllers/LenovoControllers/Lenovo4ZoneUSBController/LenovoDevices4Zone.h @@ -1,9 +1,12 @@ -/*-------------------------------------------------------------------*\ -| LenovoDevices4Zone.h | -| | -| Describes zones for Lenovo 4-Zone Device | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| LenovoDevices4Zone.h | +| | +| Device list for Lenovo 4-Zone devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include @@ -15,8 +18,12 @@ | Keyboard product IDs | \*-----------------------------------------------------*/ #define IDEAPAD_315ACH6 0xC963 +#define LEGION_5_2023_PID 0xC985 +#define LEGION_5_2023_IDEAPAD_PID 0xC984 #define LEGION_5_2022_PID 0xC975 +#define LEGION_5_2022_IDEAPAD_PID 0xC973 #define LEGION_5_2021_PID 0xC965 +#define LEGION_5_2021_IDEAPAD_PID 0xC963 #define LEGION_5_2020_PID 0xC955 enum LENOVO_4_ZONE_EFFECT @@ -98,4 +105,3 @@ static const lenovo_led lenovo_4_zone_leds[] {0x02, "Right center"}, {0x03, "Right side"}, }; - diff --git a/Controllers/LenovoControllers/Lenovo4ZoneUSBController/RGBController_Lenovo4ZoneUSB.cpp b/Controllers/LenovoControllers/Lenovo4ZoneUSBController/RGBController_Lenovo4ZoneUSB.cpp new file mode 100644 index 00000000..394b91a2 --- /dev/null +++ b/Controllers/LenovoControllers/Lenovo4ZoneUSBController/RGBController_Lenovo4ZoneUSB.cpp @@ -0,0 +1,176 @@ +/*---------------------------------------------------------*\ +| RGBController_Lenovo4ZoneUSB.cpp | +| | +| Device list for Lenovo 4-Zone devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include "Lenovo4ZoneUSBController.h" +#include "LenovoDevices4Zone.h" +#include "RGBController_Lenovo4ZoneUSB.h" +#include "LogManager.h" + +/**------------------------------------------------------------------*\ + @name Lenovo 4 Zone USB + @category Keyboard + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectLenovo4ZoneUSBControllers + @comment Tested on Lenovo Legion 5 2021 +\*-------------------------------------------------------------------*/ + + +#define LENOVO_4_ZONE_NUM_LEDS 4 + +RGBController_Lenovo4ZoneUSB::RGBController_Lenovo4ZoneUSB(Lenovo4ZoneUSBController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->getName(); + type = DEVICE_TYPE_LAPTOP; + vendor = "Lenovo"; + description = "Lenovo 4-Zone device"; + + mode Direct; + Direct.name = "Direct"; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = 1; + Direct.brightness_max = 2; + + modes.push_back(Direct); + + mode Breath; + Breath.name = "Breathing"; + Breath.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Breath.color_mode = MODE_COLORS_PER_LED; + Breath.brightness_min = 1; + Breath.brightness_max = 2; + Breath.speed_min = 1; + Breath.speed_max = 4; + + modes.push_back(Breath); + + mode Wave; + Wave.name = "Rainbow Wave"; + Wave.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + Wave.color_mode = MODE_COLORS_RANDOM; + Wave.brightness_min = 1; + Wave.brightness_max = 2; + Wave.speed_min = 1; + Wave.speed_max = 4; + Wave.direction = MODE_DIRECTION_LEFT | MODE_DIRECTION_RIGHT; + modes.push_back(Wave); + + mode Smooth; + Smooth.name = "Spectrum Cycle"; + Smooth.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Smooth.color_mode = MODE_COLORS_RANDOM; + Smooth.brightness_min = 1; + Smooth.brightness_max = 2; + Smooth.speed_min = 1; + Smooth.speed_max = 4; + modes.push_back(Smooth); + + SetupZones(); +} + +RGBController_Lenovo4ZoneUSB::~RGBController_Lenovo4ZoneUSB() +{ + delete controller; +} + +void RGBController_Lenovo4ZoneUSB::SetupZones() +{ + zone new_zone; + new_zone.name = ZONE_EN_KEYBOARD; + new_zone.type = ZONE_TYPE_LINEAR; + new_zone.leds_count = LENOVO_4_ZONE_NUM_LEDS; + new_zone.leds_max = new_zone.leds_count; + new_zone.leds_min = new_zone.leds_count; + + new_zone.matrix_map = NULL; + + + zones.push_back(new_zone); + + for(unsigned int led_idx = 0; led_idx < LENOVO_4_ZONE_NUM_LEDS; led_idx++ ) + { + led new_led; + new_led.name = lenovo_4_zone_leds[led_idx].name; + new_led.value = lenovo_4_zone_leds[led_idx].led_num; + leds.push_back(new_led); + } + + SetupColors(); +} + +void RGBController_Lenovo4ZoneUSB::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_Lenovo4ZoneUSB::UpdateSingleLED(int /*led*/) +{ +} + +void RGBController_Lenovo4ZoneUSB::UpdateZoneLEDs(int /*zone*/) +{ +} + +void RGBController_Lenovo4ZoneUSB::DeviceUpdateLEDs() +{ + state.SetColors(colors); + controller->setMode(state); +} + +void RGBController_Lenovo4ZoneUSB::DeviceUpdateMode() +{ + state.Reset(); + state.SetColors(colors); + + switch (active_mode) + { + case 0: + state.effect = LENOVO_4_ZONE_EFFECT_STATIC; + break; + case 1: + state.effect = LENOVO_4_ZONE_EFFECT_BREATH; + break; + case 2: + state.effect = LENOVO_4_ZONE_EFFECT_WAVE; + state.wave_ltr = modes[active_mode].direction?0:1; + state.wave_rtl = modes[active_mode].direction?1:0; + break; + case 3: + state.effect = LENOVO_4_ZONE_EFFECT_SMOOTH; + break; + } + + if(active_mode != (LENOVO_4_ZONE_EFFECT_STATIC - 1)) // mode number from 0, but in mode from 1 + { + state.speed = modes[active_mode].speed; + } + state.brightness = modes[active_mode].brightness; + + controller->setMode(state); +} + +void RGBController_Lenovo4ZoneUSB::DeviceSaveMode() +{ + /*---------------------------------------------------------*\ + | This device does not support saving or multiple modes | + \*---------------------------------------------------------*/ +} diff --git a/Controllers/LenovoControllers/Lenovo4ZoneUSBController/RGBController_Lenovo4ZoneUSB.h b/Controllers/LenovoControllers/Lenovo4ZoneUSBController/RGBController_Lenovo4ZoneUSB.h new file mode 100644 index 00000000..5cbdcd51 --- /dev/null +++ b/Controllers/LenovoControllers/Lenovo4ZoneUSBController/RGBController_Lenovo4ZoneUSB.h @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| RGBController_Lenovo4ZoneUSB.h | +| | +| RGBController for Lenovo 4-Zone devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "LenovoDevices.h" +#include "Lenovo4ZoneUSBController.h" +#include "RGBController.h" + +#define NA 0xFFFFFFFF + +class RGBController_Lenovo4ZoneUSB : public RGBController +{ +public: + RGBController_Lenovo4ZoneUSB(Lenovo4ZoneUSBController* controller_ptr); + ~RGBController_Lenovo4ZoneUSB(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + KeyboardState state; + + Lenovo4ZoneUSBController *controller; +}; diff --git a/Controllers/LenovoControllers/Lenovo4ZoneUSBDetect.cpp b/Controllers/LenovoControllers/Lenovo4ZoneUSBDetect.cpp deleted file mode 100644 index b181b58c..00000000 --- a/Controllers/LenovoControllers/Lenovo4ZoneUSBDetect.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/*-------------------------------------------------------------------*\ -| Lenovo4ZoneUSBDetect.h | -| | -| Describes zones for Lenovo 4-Zone Device | -\*-------------------------------------------------------------------*/ - -#include "Detector.h" -#include "LogManager.h" -#include "RGBController.h" -#include "Lenovo4ZoneUSBController.h" -#include "LenovoDevices4Zone.h" -#include "RGBController_Lenovo4ZoneUSB.h" -#include - -/*-----------------------------------------------------*\ -| vendor IDs | -\*-----------------------------------------------------*/ -#define ITE_VID 0x048D - -/*-----------------------------------------------------*\ -| Interface, Usage, and Usage Page | -\*-----------------------------------------------------*/ -enum -{ - LENOVO_PAGE = 0xFF89, - LENOVO_USAGE = 0xCC -}; - -void DetectLenovo4ZoneUSBControllers(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - - if(dev) - { - Lenovo4ZoneUSBController* controller = new Lenovo4ZoneUSBController(dev, info->path, info->product_id); - RGBController_Lenovo4ZoneUSB* rgb_controller = new RGBController_Lenovo4ZoneUSB(controller); - rgb_controller->name = name; - - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -REGISTER_HID_DETECTOR_PU("Lenovo Ideapad 3-15ach6", DetectLenovo4ZoneUSBControllers, ITE_VID, IDEAPAD_315ACH6, LENOVO_PAGE, LENOVO_USAGE); -REGISTER_HID_DETECTOR_PU("Lenovo 5 2022", DetectLenovo4ZoneUSBControllers, ITE_VID, LEGION_5_2022_PID, LENOVO_PAGE, LENOVO_USAGE); -REGISTER_HID_DETECTOR_PU("Lenovo 5 2021", DetectLenovo4ZoneUSBControllers, ITE_VID, LEGION_5_2021_PID, LENOVO_PAGE, LENOVO_USAGE); -REGISTER_HID_DETECTOR_PU("Lenovo 5 2020", DetectLenovo4ZoneUSBControllers, ITE_VID, LEGION_5_2020_PID, LENOVO_PAGE, LENOVO_USAGE); diff --git a/Controllers/LenovoControllers/LenovoDevices.h b/Controllers/LenovoControllers/LenovoDevices.h index 7c6f642f..24345a6e 100644 --- a/Controllers/LenovoControllers/LenovoDevices.h +++ b/Controllers/LenovoControllers/LenovoDevices.h @@ -1,21 +1,28 @@ +/*---------------------------------------------------------*\ +| LenovoDevices.h | +| | +| Device list for Lenovo USB devices | +| | +| Cooper Hall (geobot19) 17 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBControllerKeyNames.h" +#include "RGBController.h" + +#define NA 0xFFFFFFFF + /*-------------------------------------------------------------------*\ -| LenovoDevices.h | -| | -| Describes zones for various Lenovo Legion Devices | -| | -| Cooper Hall (geobot19) 17 Apr 2022 | -| | | Note: additions here must be adeed to RGBController_LenovoUSB.cpp in| | the switch statements which are on lines 28 and 60 at time of | | writing | \*-------------------------------------------------------------------*/ - #include - #include "RGBControllerKeyNames.h" - #include "RGBController.h" -#define NA 0xFFFFFFFF -#ifndef LENOVODEVICES_H -#define LENOVODEVICES_H /*-----------------------------------------------------*\ | Keyboard product IDs | \*-----------------------------------------------------*/ @@ -24,6 +31,11 @@ #define LEGION_Y750S 0xC957 #define LEGION_Y760 0xC968 #define LEGION_Y760S 0xC967 +#define LEGION_S7GEN7 0xC977 +#define LEGION_7GEN7 0xC978 +#define LEGION_7GEN8 0xC988 +#define LEGION_7GEN9 0xC997 +#define LEGION_7GEN9_H 0xC998 enum LENOVO_KEYBOARD { @@ -268,7 +280,7 @@ const lenovo_led legion_Y760_ansi_leds[] {0x75, "Key: >"},//107 {0x76, "Key: ?"},//108 {0x8D, KEY_EN_RIGHT_SHIFT},//109 - {0xa2, KEY_EN_RIGHT_SHIFT},//110 + {0xA2, KEY_EN_RIGHT_SHIFT},//110 {0x79, KEY_EN_NUMPAD_4},//111 {0x7A, "Key: Number Pad Right Arrow"},//112 {0x7B, KEY_EN_NUMPAD_5},//113 @@ -285,7 +297,7 @@ const lenovo_led legion_Y760_ansi_leds[] {0x91, "Key: Number Pad Down Arrow"},//122 {0x92, KEY_EN_NUMPAD_3},//123 {0x93, "Key: Number Pad Page Down"},//124 - {0xa7, KEY_EN_NUMPAD_ENTER},//125 + {0xA7, KEY_EN_NUMPAD_ENTER},//125 //row 8 {0x7F, KEY_EN_LEFT_CONTROL},//126 @@ -434,7 +446,7 @@ const lenovo_led legion_Y760_iso_leds[] {0x75, "Key: >"},//105 {0x76, "Key: ?"},//106 {0x8D, KEY_EN_RIGHT_SHIFT},//107 - {0xa2, KEY_EN_RIGHT_SHIFT},//108 + {0xA2, KEY_EN_RIGHT_SHIFT},//108 {0x79, KEY_EN_NUMPAD_4},//109 {0x7A, "Key: Number Pad Right Arrow"},//110 {0x7B, KEY_EN_NUMPAD_5},//111 @@ -451,7 +463,7 @@ const lenovo_led legion_Y760_iso_leds[] {0x91, "Key: Number Pad Down Arrow"},//120 {0x92, KEY_EN_NUMPAD_3},//121 {0x93, "Key: Number Pad Page Down"},//122 - {0xa7, KEY_EN_NUMPAD_ENTER},//123 + {0xA7, KEY_EN_NUMPAD_ENTER},//123 //row 8 {0x7F, KEY_EN_LEFT_CONTROL},//124 @@ -607,7 +619,7 @@ const lenovo_led legion_Y760_jp_leds[] {0x8B, KEY_EN_FORWARD_SLASH}, //112 {0x8C, KEY_JP_RO}, //113 {0x8D, KEY_EN_RIGHT_SHIFT}, //114 - {0xa2, KEY_EN_RIGHT_SHIFT}, //115 + {0xA2, KEY_EN_RIGHT_SHIFT}, //115 {0x79, KEY_EN_NUMPAD_4}, //116 {0x7A, "Key: Number Pad Right Arrow"}, //117 {0x7B, KEY_EN_NUMPAD_5}, //118 @@ -621,7 +633,7 @@ const lenovo_led legion_Y760_jp_leds[] {0x91, "Key: Number Pad Down Arrow"}, //124 {0x92, KEY_EN_NUMPAD_3}, //125 {0x93, "Key: Number Pad Page Down"}, //126 - {0xa7, KEY_EN_NUMPAD_ENTER}, //127 + {0xA7, KEY_EN_NUMPAD_ENTER}, //127 //row 8 {0x7F, KEY_EN_LEFT_CONTROL}, //128 @@ -1168,7 +1180,7 @@ const lenovo_led legion_Y740_15_ansi_leds[] {0x79, KEY_EN_F10}, //10 {0x7A, KEY_EN_F11}, //11 {0x7B, KEY_EN_F12}, //12 - {0x7D, KEY_EN_DELETE}, //13 + {0x4C, KEY_EN_DELETE}, //13 //Row 2 {0x01, KEY_EN_BACK_TICK}, //14 @@ -1244,7 +1256,7 @@ const lenovo_led legion_Y740_15_ansi_leds[] {0x3D, KEY_EN_SPACE}, //76 {0x91, KEY_EN_SPACE}, //77 {0x3E, KEY_EN_RIGHT_ALT}, //78 - {0x81, KEY_EN_RIGHT_CONTROL}, //79 + {0x40, KEY_EN_RIGHT_CONTROL}, //79 {0x53, KEY_EN_UP_ARROW}, //80 //Row 7 @@ -1253,12 +1265,12 @@ const lenovo_led legion_Y740_15_ansi_leds[] {0x59, KEY_EN_RIGHT_ARROW}, //83 //Left Column - {0x40, "Key: Vantage"}, //84 - {0x92, "Key: Capture"}, //85 - {0x86, "Key: M1"}, //86 - {0x81, "Key: M2"}, //87 - {0x53, "Key: Kb Brightness Up"}, //88 - {0x54, "Key: Kb Brightness Down"}, //89 + {0xC1, "Key: Vantage"}, //84 + {0xC2, "Key: Capture"}, //85 + {0xC3, "Key: M1"}, //86 + {0xC4, "Key: M2"}, //87 + {0xC5, "Key: Kb Brightness Up"}, //88 + {0xC6, "Key: Kb Brightness Down"}, //89 }; const lenovo_led legion_Y740_15_iso_leds[] @@ -1351,7 +1363,7 @@ const lenovo_led legion_Y740_15_iso_leds[] {0x3D, KEY_EN_SPACE}, //75 {0x91, KEY_EN_SPACE}, //76 {0x3E, KEY_EN_RIGHT_ALT}, //77 - {0x81, KEY_EN_RIGHT_CONTROL}, //78 + {0x40, KEY_EN_RIGHT_CONTROL}, //78 {0x53, KEY_EN_UP_ARROW}, //79 //Row 7 @@ -1360,12 +1372,12 @@ const lenovo_led legion_Y740_15_iso_leds[] {0x59, KEY_EN_RIGHT_ARROW}, //82 //Left Column - {0x40, "Key: Vantage"}, //83 - {0x92, "Key: Capture"}, //84 - {0x86, "Key: M1"}, //85 - {0x81, "Key: M2"}, //86 - {0x53, "Key: Kb Brightness Up"}, //87 - {0x54, "Key: Kb Brightness Down"}, //88 + {0xC1, "Key: Vantage"}, //83 + {0xC2, "Key: Capture"}, //84 + {0xC3, "Key: M1"}, //85 + {0xC4, "Key: M2"}, //86 + {0xC5, "Key: Kb Brightness Up"}, //87 + {0xC6, "Key: Kb Brightness Down"}, //88 }; /*--------------------------------------------------------*\ @@ -1705,4 +1717,231 @@ static lenovo_zone lenovo_legion_Y740_15_kbd_iso 88, }; -#endif +/*--------------------------------------------------------*\ +| Legion 7 gen7: 4 zones | +\*--------------------------------------------------------*/ + +static const unsigned int legion7_gen7and8_ansi_leds_map[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, NA, 30, 31, 32, 33, NA, 34, 35, 36, 37, + 38, 39, 40, 41, NA, 42, 43, 44, 45, 46, 47, 48, 49, 50, NA, 51, 52, 53, 54, NA, + 55, 56, NA, 57, 58, 59, 60, 61, 62, 63, 64, 65, NA, 66, 67, NA, 68, 69, 70, 71, + 72, NA, 73, 74, 75, NA, 76, 77, 78, 79, 80, 81, 82, NA, 83, NA, 84, 85, 86, NA, + 87, 88, 89, 90, 91, NA, NA, NA, NA, NA, 92, 93, NA, 94, NA, NA, 95, NA, 96, 97, + NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 98, 99, NA, 100, NA, NA, NA, NA}; + +/*---------------------*\ +| zone 1, keyboard ANSI | +\*---------------------*/ +const lenovo_led legion7_gen7and8_ansi_leds[] +{ + //row 1 + {0x01, KEY_EN_ESCAPE},//0 + {0x02, KEY_EN_F1},//1 + {0x03, KEY_EN_F2},//2 + {0x04, KEY_EN_F3},//3 + {0x05, KEY_EN_F4},//4 + {0x06, KEY_EN_F5},//5 + {0x07, KEY_EN_F6},//6 + {0x08, KEY_EN_F7},//7 + {0x09, KEY_EN_F8},//8 + {0x0A, KEY_EN_F9},//9 + {0x0B, KEY_EN_F10},//10 + {0x0C, KEY_EN_F11},//11 + {0x0D, KEY_EN_F12},//12 + {0x0E, KEY_EN_INSERT},//13 + {0x0F, KEY_EN_PRINT_SCREEN},//14 + {0x10, KEY_EN_DELETE},//15 + {0x11, KEY_EN_HOME},//16 + {0x12, KEY_EN_END},//17 + {0x13, KEY_EN_PAGE_UP},//18 + {0x14, KEY_EN_PAGE_DOWN},//19 + + //row 2 + {0x16, KEY_EN_BACK_TICK},//20 + {0x17, KEY_EN_1},//21 + {0x18, KEY_EN_2},//22 + {0x19, KEY_EN_3},//23 + {0x1A, KEY_EN_4},//24 + {0x1B, KEY_EN_5},//25 + {0x1C, KEY_EN_6},//26 + {0x1D, KEY_EN_7},//27 + {0x1E, KEY_EN_8},//28 + {0x1F, KEY_EN_9},//29 + {0x20, KEY_EN_0},//30 + {0x21, KEY_EN_MINUS},//31 + {0x22, KEY_EN_EQUALS},//32 + {0x38, KEY_EN_BACKSPACE},//33 + {0x26, KEY_EN_NUMPAD_LOCK},//34 + {0x27, KEY_EN_NUMPAD_DIVIDE},//35 + {0x28, KEY_EN_NUMPAD_TIMES},//36 + {0x29, KEY_EN_NUMPAD_MINUS},//37 + + //row 3 + {0x40, KEY_EN_TAB},//38 + {0x42, KEY_EN_Q},//39 + {0x43, KEY_EN_W},//40 + {0x44, KEY_EN_E},//41 + {0x45, KEY_EN_R},//42 + {0x46, KEY_EN_T},//43 + {0x47, KEY_EN_Y},//44 + {0x48, KEY_EN_U},//45 + {0x49, KEY_EN_I},//46 + {0x4A, KEY_EN_O},//47 + {0x4B, KEY_EN_P},//48 + {0x4C, KEY_EN_LEFT_BRACKET},//49 + {0x4D, KEY_EN_RIGHT_BRACKET},//50 + {0x4E, KEY_EN_ANSI_BACK_SLASH},//51 + {0x4F, KEY_EN_NUMPAD_7},//52 + {0x50, KEY_EN_NUMPAD_8},//53 + {0x51, KEY_EN_NUMPAD_9},//54 + + //row 4 + {0x55, KEY_EN_CAPS_LOCK},//55 + {0x6D, KEY_EN_A},//56 + {0x6E, KEY_EN_S},//57 + {0x58, KEY_EN_D},//58 + {0x59, KEY_EN_F},//59 + {0x5A, KEY_EN_G},//60 + {0x71, KEY_EN_H},//61 + {0x72, KEY_EN_J},//62 + {0x5B, KEY_EN_K},//63 + {0x5C, KEY_EN_L},//64 + {0x5D, KEY_EN_SEMICOLON},//65 + {0x5F, KEY_EN_QUOTE},//66 + {0x77, KEY_EN_ANSI_ENTER},//67 + {0x79, KEY_EN_NUMPAD_4},//68 + {0x7B, KEY_EN_NUMPAD_5},//69 + {0x7C, KEY_EN_NUMPAD_6},//70 + {0x68, KEY_EN_NUMPAD_PLUS},//71 + + //row 5 + {0x6A, KEY_EN_LEFT_SHIFT},//72 + {0x82, KEY_EN_Z},//73 + {0x83, KEY_EN_X},//74 + {0x6F, KEY_EN_C},//75 + {0x70, KEY_EN_V},//76 + {0x87, KEY_EN_B},//77 + {0x88, KEY_EN_N},//78 + {0x73, KEY_EN_M},//79 + {0x74, KEY_EN_COMMA},//80 + {0x75, KEY_EN_PERIOD},//81 + {0x76, KEY_EN_FORWARD_SLASH},//82 + {0x8D, KEY_EN_RIGHT_SHIFT},//83 + {0x8E, KEY_EN_NUMPAD_1},//84 + {0x90, KEY_EN_NUMPAD_2},//85 + {0x92, KEY_EN_NUMPAD_3},//86 + + //row 6 + {0x7F, KEY_EN_LEFT_CONTROL},//87 + {0x80, KEY_EN_LEFT_FUNCTION},//88 + {0x96, KEY_EN_LEFT_WINDOWS},//89 + {0x97, KEY_EN_LEFT_ALT},//90 + {0x98, KEY_EN_SPACE},//91 + {0x9A, KEY_EN_RIGHT_ALT},//92 + {0x9B, KEY_EN_RIGHT_CONTROL},//93 + {0x9D, KEY_EN_UP_ARROW},//94 + {0xA3, KEY_EN_NUMPAD_0},//95 + {0xA5, KEY_EN_NUMPAD_PERIOD},//96 + {0xA7, KEY_EN_NUMPAD_ENTER},//97 + + //row 7 + {0x9C, KEY_EN_LEFT_ARROW},//98 + {0x9F, KEY_EN_DOWN_ARROW},//99 + {0xA1, KEY_EN_RIGHT_ARROW},//100 +}; + +const lenovo_led legion7_gen7and8_neon_leds[] +{ + {0xF5, "Neon group 1"},//0 + {0xF6, "Neon group 2"},//1 + {0xF7, "Neon group 3"},//2 + {0xF8, "Neon group 4"},//3 + {0xF9, "Neon group 5"},//4 + {0xFA, "Neon group 6"},//5 + {0xFB, "Neon group 7"},//6 + {0xFC, "Neon group 8"},//7 + {0xFD, "Neon group 9"},//8 + {0xFE, "Neon group 10"},//9 +}; + +const lenovo_led legion_7gen7_vents_leds[] +{ + {0xE9, "Vent group 1"},//0 + {0xEA, "Vent group 2"},//1 + {0xEB, "Vent group 3"},//2 + {0xEC, "Vent group 4"},//3 + {0xED, "Vent group 5"},//4 + {0xEE, "Vent group 6"},//5 + {0xEF, "Vent group 7"},//6 + {0xF0, "Vent group 8"},//7 +}; + +const lenovo_led legion_7gen7_logo_leds[] +{ + {0xDD, "Logo"},//0 +}; + +/*------*\ +|keyboard| +\*------*/ +static lenovo_zone legion7_gen7and8_kbd_ansi +{ + "Keyboard", + ZONE_TYPE_MATRIX, + 0, + 7, + 20, + legion7_gen7and8_ansi_leds_map, + legion7_gen7and8_ansi_leds, + 0, + 100, +}; + +/*------*\ +|logo | +\*------*/ +static lenovo_zone lenovo_legion_7gen7_logo +{ + "Logo", + ZONE_TYPE_LINEAR, + 5, + 1, + 1, + NULL, + legion_7gen7_logo_leds, + 0, + 0, +}; + +/*------*\ +|vents | +\*------*/ +static lenovo_zone lenovo_legion_7gen7_vents +{ + "Vents", + ZONE_TYPE_LINEAR, + 3, + 1, + 8, + NULL, + legion_7gen7_vents_leds, + 0, + 7, +}; + +/*------*\ +|neon | +\*------*/ +static lenovo_zone legion7_gen7and8_neon +{ + "Neon", + ZONE_TYPE_LINEAR, + 1, + 1, + 10, + NULL, + legion7_gen7and8_neon_leds, + 0, + 9, +}; diff --git a/Controllers/LenovoControllers/LenovoM300Controller/LenovoM300Controller.cpp b/Controllers/LenovoControllers/LenovoM300Controller/LenovoM300Controller.cpp new file mode 100644 index 00000000..d4ae28ca --- /dev/null +++ b/Controllers/LenovoControllers/LenovoM300Controller/LenovoM300Controller.cpp @@ -0,0 +1,94 @@ +/*---------------------------------------------------------*\ +| LenovoM300Controller.cpp | +| | +| Driver for Lenovo Legion M300 mouse | +| | +| Wayne Riordan 09 Jan 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "LenovoM300Controller.h" + +using namespace std; + +LenovoM300Controller::LenovoM300Controller(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) +{ + device = dev_handle; + location = info.path; + name = dev_name; +} + +LenovoM300Controller::~LenovoM300Controller() +{ + hid_close(device); +} + +std::string LenovoM300Controller::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string LenovoM300Controller::GetDeviceName() +{ + return(name); +} + +void LenovoM300Controller::SetMode(std::vector colors, unsigned char mode_value, unsigned int brigthness) +{ + unsigned char usb_buf[M300_DATA_SIZE]; + memset(usb_buf, 0x00, M300_DATA_SIZE); + + usb_buf[0x01] = 0x25; + usb_buf[0x03] = 0x01; + usb_buf[0x04] = 0x01; + usb_buf[0x05] = 0x0C; + + switch(mode_value) + { + case M300_MODE_RAINBOW: + usb_buf[0x06] = 0x01; + usb_buf[0x07] = 0x64; + usb_buf[0x09] = 0x0A; + usb_buf[0x40] = CalculateFinalByte(usb_buf, 0x0A); + break; + case M300_MODE_BREATHING: + usb_buf[0x06] = 0x02; + usb_buf[0x07] = 0x64; + usb_buf[0x09] = 0x02; + usb_buf[0x0A] = 0x03; + usb_buf[0x0C] = RGBGetRValue(colors[0]); + usb_buf[0x0D] = RGBGetGValue(colors[0]); + usb_buf[0x0E] = RGBGetBValue(colors[0]); + usb_buf[0x0F] = RGBGetRValue(colors[1]); + usb_buf[0x10] = RGBGetGValue(colors[1]); + usb_buf[0x11] = RGBGetBValue(colors[1]); + usb_buf[0x40] = CalculateFinalByte(usb_buf, 0x12); + break; + case M300_MODE_STATIC: + usb_buf[0x06] = 0x03; + usb_buf[0x07] = brigthness; + usb_buf[0x09] = RGBGetRValue(colors[0]); + usb_buf[0x0A] = RGBGetGValue(colors[0]); + usb_buf[0x0B] = RGBGetBValue(colors[0]); + usb_buf[0x40] = CalculateFinalByte(usb_buf, 0x0C); + break; + case M300_MODE_OFF: + default: + usb_buf[0x06] = 0x03; + usb_buf[0x40] = 0x36; + } + hid_write(device, usb_buf, M300_DATA_SIZE); +} + +unsigned char LenovoM300Controller::CalculateFinalByte(unsigned char* ptr, int count) +{ + unsigned char final_byte = 0; + for(int i = 0; i < count; i++) + { + final_byte += ptr[i]; + } + return final_byte; +} diff --git a/Controllers/LenovoControllers/LenovoM300Controller/LenovoM300Controller.h b/Controllers/LenovoControllers/LenovoM300Controller/LenovoM300Controller.h new file mode 100644 index 00000000..d1d0cec2 --- /dev/null +++ b/Controllers/LenovoControllers/LenovoM300Controller/LenovoM300Controller.h @@ -0,0 +1,49 @@ +/*---------------------------------------------------------*\ +| LenovoM300Controller.h | +| | +| Driver for Lenovo Legion M300 mouse | +| | +| Wayne Riordan 09 Jan 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define M300_DATA_SIZE 0x41 +#define M300_MAX_BRIGTH 0x64 +#define M300_MIN_BRIGHT 0x01 + +enum +{ + M300_MODE_OFF = 0x00, + M300_MODE_RAINBOW = 0x01, + M300_MODE_BREATHING = 0x02, + M300_MODE_STATIC = 0X03 +}; + +class LenovoM300Controller +{ +public: + LenovoM300Controller(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~LenovoM300Controller(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + + void SetMode(std::vector colors, unsigned char mode_value, unsigned int brightness); + +protected: + hid_device* device; + +private: + std::string location; + std::string name; + + unsigned char CalculateFinalByte(unsigned char* ptr, int count); +}; diff --git a/Controllers/LenovoControllers/LenovoM300Controller/LenovoM300ControllerDetect.cpp b/Controllers/LenovoControllers/LenovoM300Controller/LenovoM300ControllerDetect.cpp new file mode 100644 index 00000000..81a2169f --- /dev/null +++ b/Controllers/LenovoControllers/LenovoM300Controller/LenovoM300ControllerDetect.cpp @@ -0,0 +1,37 @@ +/*---------------------------------------------------------*\ +| LenovoM300ControllerDetect.cpp | +| | +| Detector for Lenovo Legion M300 mouse | +| | +| Wayne Riordan 09 Jan 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "RGBController_LenovoM300.h" +#include "LenovoM300Controller.h" + +/*---------------------------------------------------------*\ +| Lenovo vendor, product, usage and page IDs | +\*---------------------------------------------------------*/ +#define LENOVO_VID 0x17EF +#define LEGION_M300_PID 0x60E4 +#define LENOVO_USAGE 0X01 +#define LENOVO_PAGE 0XFF01 + +void DetectLenovoLegionM300Controllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + LenovoM300Controller* controller = new LenovoM300Controller(dev, *info, name); + RGBController_LenovoM300* rgb_controller = new RGBController_LenovoM300(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR_PU("Lenovo Legion M300", DetectLenovoLegionM300Controllers, LENOVO_VID, LEGION_M300_PID, LENOVO_PAGE, LENOVO_USAGE); diff --git a/Controllers/LenovoControllers/LenovoM300Controller/RGBController_LenovoM300.cpp b/Controllers/LenovoControllers/LenovoM300Controller/RGBController_LenovoM300.cpp new file mode 100644 index 00000000..305cc51d --- /dev/null +++ b/Controllers/LenovoControllers/LenovoM300Controller/RGBController_LenovoM300.cpp @@ -0,0 +1,120 @@ +/*---------------------------------------------------------*\ +| RGBController_LenovoM300.cpp | +| | +| RGBController for Lenovo Legion M300 mouse | +| | +| Wayne Riordan 09 Jan 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_LenovoM300.h" + +/**------------------------------------------------------------------*\ + @name Lenovo Legion M300 + @category Mouse + @type USB + @save :robot: + @direct :x: + @effects :white_check_mark: + @detectors DetectLenovoLegionM300Controllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_LenovoM300::RGBController_LenovoM300(LenovoM300Controller* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "Lenovo"; + type = DEVICE_TYPE_MOUSE; + description = "Lenovo M300 Device"; + location = controller->GetDeviceLocation(); + + mode Static; + Static.name = "Static"; + Static.value = M300_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Static.brightness_max = M300_MAX_BRIGTH; + Static.brightness_min = M300_MIN_BRIGHT; + Static.brightness = M300_MAX_BRIGTH; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors.resize(1); + modes.push_back(Static); + + mode Off; + Off.name = "Off"; + Off.value = M300_MODE_OFF; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = M300_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.brightness_max = M300_MAX_BRIGTH; + Breathing.brightness_min = M300_MIN_BRIGHT; + Breathing.brightness = M300_MAX_BRIGTH; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.colors.resize(2); + modes.push_back(Breathing); + + mode Spectrum; + Spectrum.name = "Spectrum Cycle"; + Spectrum.value = M300_MODE_RAINBOW; + Spectrum.flags = MODE_FLAG_AUTOMATIC_SAVE; + Spectrum.color_mode = MODE_COLORS_NONE; + modes.push_back(Spectrum); + + SetupZones(); +} + +RGBController_LenovoM300::~RGBController_LenovoM300() +{ + delete controller; +} + +void RGBController_LenovoM300::SetupZones() +{ + zone default_zone; + default_zone.name = "Mouse"; + default_zone.type = ZONE_TYPE_SINGLE; + default_zone.leds_min = 1; + default_zone.leds_max = 1; + default_zone.leds_count = 1; + default_zone.matrix_map = nullptr; + zones.emplace_back(default_zone); + + leds.resize(1); + leds[0].name = "LED 1"; + + SetupColors(); +} + +void RGBController_LenovoM300::ResizeZone(int /*zone*/, int /*new_size*/) +{ + // Not Supported +} + +void RGBController_LenovoM300::DeviceUpdateLEDs() +{ + const mode& active = modes[active_mode]; + controller->SetMode(active.colors, active.value, active.brightness); +} + +void RGBController_LenovoM300::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_LenovoM300::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_LenovoM300::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} diff --git a/Controllers/LenovoControllers/LenovoM300Controller/RGBController_LenovoM300.h b/Controllers/LenovoControllers/LenovoM300Controller/RGBController_LenovoM300.h new file mode 100644 index 00000000..b6480eb3 --- /dev/null +++ b/Controllers/LenovoControllers/LenovoM300Controller/RGBController_LenovoM300.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_LenovoM300.h | +| | +| RGBController for Lenovo Legion M300 mouse | +| | +| Wayne Riordan 09 Jan 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LenovoM300Controller.h" + +class RGBController_LenovoM300 : public RGBController +{ +public: + RGBController_LenovoM300(LenovoM300Controller* controller_ptr); + ~RGBController_LenovoM300(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LenovoM300Controller* controller; +}; diff --git a/Controllers/LenovoControllers/LenovoUSBController.h b/Controllers/LenovoControllers/LenovoUSBController.h deleted file mode 100644 index f3db8c8b..00000000 --- a/Controllers/LenovoControllers/LenovoUSBController.h +++ /dev/null @@ -1,68 +0,0 @@ -/*-------------------------------------------------------------------*\ -| LenovoUSBController.h | -| | -| Driver for various Lenovo Devices | -| | -| Cooper Hall (geobot19) 17 Apr 2022 | -| | -\*-------------------------------------------------------------------*/ - -#include "RGBController.h" -#include "LogManager.h" - -#include -#include -#include -#include -#include - -#ifndef HID_MAX_STR -#define HID_MAX_STR 255 -#endif - -#ifndef LENOVOUSBCONTROLLER_H -#define LENOVOUSBCONTROLLER_H - -#define LENOVO_INSTRUCTION_START 0x07 -#define LENOVO_ZONE_ID_0 0xA0 - -#define LENOVO_HID_PACKET_SIZE 192 -#define LENOVO_MAX_LEDS_PER_PACKET 0x2F - -class LenovoUSBController -{ - public: - /*--------------*\ - |ctor(s) and dtor| - \*--------------*/ - LenovoUSBController(hid_device* dev_handle, const char* path, uint16_t in_pid); - ~LenovoUSBController(); - - /*--------------*\ - |device functions| - \*--------------*/ - void setZoneLeds(uint8_t zone_num, std::vector> &led_colors); - void setSingleLED(uint8_t zone_num, uint8_t led_num, RGBColor color); - uint16_t getPid(); - std::string getName(); - std::string getLocation(); - std::vector getInformation(uint8_t information_id); - void setDeviceSoftwareMode(); - void setDeviceHardwareMode(); - - private: - /*--------------*\ - |data members | - \*--------------*/ - std::string name; - hid_device *dev; - std::string location; - uint16_t pid; - - /*--------------*\ - |device functions| - \*--------------*/ - void sendBasicInstruction(uint8_t instruction); -}; - -#endif diff --git a/Controllers/LenovoControllers/LenovoUSBController.cpp b/Controllers/LenovoControllers/LenovoUSBController/LenovoUSBController.cpp similarity index 79% rename from Controllers/LenovoControllers/LenovoUSBController.cpp rename to Controllers/LenovoControllers/LenovoUSBController/LenovoUSBController.cpp index 252c72d0..9a9a201e 100644 --- a/Controllers/LenovoControllers/LenovoUSBController.cpp +++ b/Controllers/LenovoControllers/LenovoUSBController/LenovoUSBController.cpp @@ -1,33 +1,26 @@ -/*-------------------------------------------------------------------*\ -| LenovoUSBController.cpp | -| | -| Driver for various Lenovo Devices | -| | -| Cooper Hall (geobot19) 17 Apr 2022 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| LenovoUSBController.cpp | +| | +| Driver for Lenovo USB devices | +| | +| Cooper Hall (geobot19) 17 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "LenovoUSBController.h" #include "LogManager.h" +#include "StringUtils.h" using namespace std; -LenovoUSBController::LenovoUSBController(hid_device* dev_handle, const char* path, uint16_t in_pid) +LenovoUSBController::LenovoUSBController(hid_device* dev_handle, const char* path, uint16_t in_pid, std::string dev_name) { - const uint8_t sz = HID_MAX_STR; - wchar_t tmp[sz]; - dev = dev_handle; location = path; pid = in_pid; - - hid_get_manufacturer_string(dev, tmp, sz); - std::wstring w_tmp = wstring(tmp); - name = string(w_tmp.begin(), w_tmp.end()); - - hid_get_product_string(dev, tmp, sz); - w_tmp = wstring(tmp); - name.append(" ").append(string(w_tmp.begin(), w_tmp.end())); + name = dev_name; setDeviceSoftwareMode(); } diff --git a/Controllers/LenovoControllers/LenovoUSBController/LenovoUSBController.h b/Controllers/LenovoControllers/LenovoUSBController/LenovoUSBController.h new file mode 100644 index 00000000..10e6bb14 --- /dev/null +++ b/Controllers/LenovoControllers/LenovoUSBController/LenovoUSBController.h @@ -0,0 +1,69 @@ +/*---------------------------------------------------------*\ +| LenovoUSBController.h | +| | +| Driver for Lenovo USB devices | +| | +| Cooper Hall (geobot19) 17 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include "RGBController.h" +#include "LogManager.h" + +#ifndef HID_MAX_STR +#define HID_MAX_STR 255 +#endif + +#ifndef LENOVOUSBCONTROLLER_H +#define LENOVOUSBCONTROLLER_H + +#define LENOVO_INSTRUCTION_START 0x07 +#define LENOVO_ZONE_ID_0 0xA0 + +#define LENOVO_HID_PACKET_SIZE 192 +#define LENOVO_MAX_LEDS_PER_PACKET 0x2F + +class LenovoUSBController +{ + public: + /*--------------*\ + |ctor(s) and dtor| + \*--------------*/ + LenovoUSBController(hid_device* dev_handle, const char* path, uint16_t in_pid, std::string dev_name); + ~LenovoUSBController(); + + /*--------------*\ + |device functions| + \*--------------*/ + void setZoneLeds(uint8_t zone_num, std::vector> &led_colors); + void setSingleLED(uint8_t zone_num, uint8_t led_num, RGBColor color); + uint16_t getPid(); + std::string getName(); + std::string getLocation(); + std::vector getInformation(uint8_t information_id); + void setDeviceSoftwareMode(); + void setDeviceHardwareMode(); + + private: + /*--------------*\ + |data members | + \*--------------*/ + std::string name; + hid_device *dev; + std::string location; + uint16_t pid; + + /*--------------*\ + |device functions| + \*--------------*/ + void sendBasicInstruction(uint8_t instruction); +}; + +#endif diff --git a/Controllers/LenovoControllers/RGBController_LenovoUSB.cpp b/Controllers/LenovoControllers/LenovoUSBController/RGBController_LenovoUSB.cpp similarity index 91% rename from Controllers/LenovoControllers/RGBController_LenovoUSB.cpp rename to Controllers/LenovoControllers/LenovoUSBController/RGBController_LenovoUSB.cpp index c0a7624d..219a8b8b 100644 --- a/Controllers/LenovoControllers/RGBController_LenovoUSB.cpp +++ b/Controllers/LenovoControllers/LenovoUSBController/RGBController_LenovoUSB.cpp @@ -1,12 +1,23 @@ +/*---------------------------------------------------------*\ +| RGBController_Lenovo_USB.cpp | +| | +| RGBController for Lenovo USB devices | +| | +| Cooper Hall (geobot19) 17 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include +#include #include "LenovoDevices.h" #include "RGBController_LenovoUSB.h" #include "LogManager.h" -#include -#include -#include -#include -#include using namespace std; /*--------------------------------------------------------------------------------------*\ @@ -288,6 +299,21 @@ void RGBController_LenovoUSB::SetupZones() lenovo_zones.push_back(lenovo_legion_Y760_vent_back_left); lenovo_zones.push_back(lenovo_legion_Y760_neon); break; + case LEGION_S7GEN7: + lenovo_zones.push_back(legion7_gen7and8_kbd_ansi); + break; + case LEGION_7GEN7: + lenovo_zones.push_back(legion7_gen7and8_kbd_ansi); + lenovo_zones.push_back(lenovo_legion_7gen7_logo); + lenovo_zones.push_back(lenovo_legion_7gen7_vents); + lenovo_zones.push_back(legion7_gen7and8_neon); + break; + case LEGION_7GEN8: + case LEGION_7GEN9: + case LEGION_7GEN9_H: + lenovo_zones.push_back(legion7_gen7and8_kbd_ansi); + lenovo_zones.push_back(legion7_gen7and8_neon); + break; } for(unsigned int i = 0; i < lenovo_zones.size(); i++) @@ -351,7 +377,7 @@ void RGBController_LenovoUSB::UpdateZoneLEDs(int zone) { int index = zones[zone].start_idx+i; - color_map.push_back({leds[index].value & 0xFF, colors[index]}); + color_map.push_back({(uint8_t)leds[index].value & 0xFF, colors[index]}); } color_map.shrink_to_fit(); @@ -377,15 +403,13 @@ void RGBController_LenovoUSB::DeviceUpdateLEDs() prev_zone_id = zone_id; - curr_color_map.push_back({leds[i].value & 0xFF, colors[i]}); - + curr_color_map.push_back({(uint8_t)(leds[i].value & 0xFF), colors[i]}); } if(curr_color_map.size() > 0) { controller->setZoneLeds(prev_zone_id, curr_color_map); } - } void RGBController_LenovoUSB::DeviceUpdateMode() diff --git a/Controllers/LenovoControllers/LenovoUSBController/RGBController_LenovoUSB.h b/Controllers/LenovoControllers/LenovoUSBController/RGBController_LenovoUSB.h new file mode 100644 index 00000000..0299cd3d --- /dev/null +++ b/Controllers/LenovoControllers/LenovoUSBController/RGBController_LenovoUSB.h @@ -0,0 +1,47 @@ +/*---------------------------------------------------------*\ +| RGBController_Lenovo_USB.h | +| | +| RGBController for Lenovo USB devices | +| | +| Cooper Hall (geobot19) 17 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "LenovoDevices.h" +#include "LenovoUSBController.h" +#include "RGBController.h" + +#define NA 0xFFFFFFFF + +class RGBController_LenovoUSB : public RGBController +{ +public: + RGBController_LenovoUSB(LenovoUSBController* controller_ptr); + ~RGBController_LenovoUSB(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + std::string ConvertBytesToHex(const std::vector &input); + std::string keyboardToString(LENOVO_KEYBOARD kb); + std::string sizeToString(LENOVO_SIZE size); + void DumpControllerInformation(); + + LENOVO_KEYBOARD keyboard_type; + LENOVO_SIZE chasis_size; + + LenovoUSBController *controller; +}; diff --git a/Controllers/LenovoControllers/LenovoUSBControllerDetect.cpp b/Controllers/LenovoControllers/LenovoUSBControllerDetect.cpp new file mode 100644 index 00000000..cc272452 --- /dev/null +++ b/Controllers/LenovoControllers/LenovoUSBControllerDetect.cpp @@ -0,0 +1,67 @@ +/*---------------------------------------------------------*\ +| LenovoUSBControllerDetect.cpp | +| | +| Detector for Lenovo USB devices | +| | +| Cooper Hall (geobot19) 17 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "LenovoDevices.h" +#include "RGBController_LenovoUSB.h" +#include "RGBController_Lenovo_Gen7_8.h" + +/*-----------------------------------------------------*\ +| vendor IDs | +\*-----------------------------------------------------*/ +#define ITE_VID 0x048D + +/*-----------------------------------------------------*\ +| Interface, Usage, and Usage Page | +\*-----------------------------------------------------*/ +enum +{ + LENOVO_PAGE = 0xFF89, + LENOVO_USAGE = 0x07 +}; + +void DetectLenovoLegionUSBControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + LenovoUSBController* controller = new LenovoUSBController(dev, info->path, info->product_id, name); + RGBController_LenovoUSB* rgb_controller = new RGBController_LenovoUSB(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectLenovoLegionUSBControllersGen7And8(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + LenovoGen7And8USBController* controller = new LenovoGen7And8USBController(dev, info->path, info->product_id, name); + LenovoRGBController_Gen7_8* rgb_controller = new LenovoRGBController_Gen7_8(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR_PU("Lenovo Legion Y740", DetectLenovoLegionUSBControllers, ITE_VID, LEGION_Y740, LENOVO_PAGE, LENOVO_USAGE); +REGISTER_HID_DETECTOR_PU("Lenovo Legion 7 Gen 5", DetectLenovoLegionUSBControllers, ITE_VID, LEGION_Y750, LENOVO_PAGE, LENOVO_USAGE); +REGISTER_HID_DETECTOR_PU("Lenovo Legion 7S Gen 5", DetectLenovoLegionUSBControllers, ITE_VID, LEGION_Y750S, LENOVO_PAGE, LENOVO_USAGE); +REGISTER_HID_DETECTOR_PU("Lenovo Legion 7 Gen 6", DetectLenovoLegionUSBControllers, ITE_VID, LEGION_Y760, LENOVO_PAGE, LENOVO_USAGE); +REGISTER_HID_DETECTOR_PU("Lenovo Legion 7S Gen 6", DetectLenovoLegionUSBControllers, ITE_VID, LEGION_Y760S, LENOVO_PAGE, LENOVO_USAGE); +REGISTER_HID_DETECTOR_PU("Lenovo Legion 7S Gen 7", DetectLenovoLegionUSBControllersGen7And8, ITE_VID, LEGION_S7GEN7, LENOVO_PAGE, LENOVO_USAGE); +REGISTER_HID_DETECTOR_PU("Lenovo Legion 7 Gen 7", DetectLenovoLegionUSBControllersGen7And8, ITE_VID, LEGION_7GEN7, LENOVO_PAGE, LENOVO_USAGE); +REGISTER_HID_DETECTOR_PU("Lenovo Legion 7 Gen 8", DetectLenovoLegionUSBControllersGen7And8, ITE_VID, LEGION_7GEN8, LENOVO_PAGE, LENOVO_USAGE); +REGISTER_HID_DETECTOR_PU("Lenovo Legion 7 Gen 9", DetectLenovoLegionUSBControllersGen7And8, ITE_VID, LEGION_7GEN9, LENOVO_PAGE, LENOVO_USAGE); +REGISTER_HID_DETECTOR_PU("Lenovo Legion 7 Gen 9", DetectLenovoLegionUSBControllersGen7And8, ITE_VID, LEGION_7GEN9_H, LENOVO_PAGE, LENOVO_USAGE); diff --git a/Controllers/LenovoControllers/LenovoUSBController_Gen7_8/LenovoUSBController_Gen7_8.cpp b/Controllers/LenovoControllers/LenovoUSBController_Gen7_8/LenovoUSBController_Gen7_8.cpp new file mode 100644 index 00000000..b5278293 --- /dev/null +++ b/Controllers/LenovoControllers/LenovoUSBController_Gen7_8/LenovoUSBController_Gen7_8.cpp @@ -0,0 +1,300 @@ +/*---------------------------------------------------------*\ +| LenovoUSBController_Gen7_8.cpp | +| | +| Driver for Lenovo Gen7 and Gen8 devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "LenovoUSBController_Gen7_8.h" +#include "StringUtils.h" + +using namespace std; + +LenovoGen7And8USBController::LenovoGen7And8USBController(hid_device* dev_handle, const char* path, uint16_t in_pid, std::string dev_name) +{ + dev = dev_handle; + location = path; + pid = in_pid; + name = dev_name; +} + +LenovoGen7And8USBController::~LenovoGen7And8USBController() +{ + hid_close(dev); +} + +uint16_t LenovoGen7And8USBController::getPid() +{ + return pid; +} + +string LenovoGen7And8USBController::getName() +{ + return name; +} + +string LenovoGen7And8USBController::getLocation() +{ + return location; +} + +void LenovoGen7And8USBController::setLedsByGroup(uint8_t profile_id, vector led_groups) +{ + uint8_t buffer[PACKET_SIZE]; + memset(buffer, 0x00, PACKET_SIZE); + + size_t i = 0; + buffer[i++] = REPORT_ID; + buffer[i++] = SAVE_PROFILE; + buffer[i++] = 0xC0; + buffer[i++] = 0x03; + buffer[i++] = profile_id; + buffer[i++] = 0x01; + buffer[i++] = 0x01; + + for(size_t group = 0; group < led_groups.size() && i < PACKET_SIZE - 21; group++) + { + buffer[i++] = (uint8_t)group + 1; //Group index + buffer[i++] = 0x06; + buffer[i++] = 0x01; + buffer[i++] = led_groups[group].mode; + buffer[i++] = 0x02; + buffer[i++] = led_groups[group].speed; + buffer[i++] = 0x03; + buffer[i++] = led_groups[group].spin; + buffer[i++] = 0x04; + buffer[i++] = led_groups[group].direction; + buffer[i++] = 0x05; + buffer[i++] = led_groups[group].color_mode; + buffer[i++] = 0x06; + buffer[i++] = 0x00; + + buffer[i++] = (uint8_t)led_groups[group].colors.size(); + for(RGBColor c : led_groups[group].colors) + { + buffer[i++] = RGBGetRValue(c); + buffer[i++] = RGBGetGValue(c); + buffer[i++] = RGBGetBValue(c); + } + + vector leds = led_groups[group].leds; + size_t led_count = min(leds.size(), (PACKET_SIZE - i)/2); + buffer[i++] = (uint8_t)led_count; + uint8_t* byte_ptr = reinterpret_cast(leds.data()); + std::copy(byte_ptr, byte_ptr + led_count * sizeof(uint16_t), buffer + i); + i+= led_count * sizeof(uint16_t); + } + + buffer[2] = (uint8_t)i; + + sendFeatureReport(buffer, PACKET_SIZE); +} + +void LenovoGen7And8USBController::setLedsDirectOn(uint8_t profile_id) +{ + uint8_t buffer[PACKET_SIZE]; + memset(buffer, 0x00, PACKET_SIZE); + + size_t i = 0; + buffer[i++] = REPORT_ID; + buffer[i++] = SET_DIRECT_MODE; + buffer[i++] = 0xC0; + buffer[i++] = 0x03; + buffer[i++] = 0x01; + buffer[i++] = profile_id; + + sendFeatureReport(buffer, PACKET_SIZE); +} + +void LenovoGen7And8USBController::setLedsDirectOff(uint8_t profile_id) +{ + uint8_t buffer[PACKET_SIZE]; + memset(buffer, 0x00, PACKET_SIZE); + + size_t i = 0; + buffer[i++] = REPORT_ID; + buffer[i++] = SET_DIRECT_MODE; + buffer[i++] = 0xC0; + buffer[i++] = 0x03; + buffer[i++] = 0x02; + buffer[i++] = profile_id; + + sendFeatureReport(buffer, PACKET_SIZE); +} + +void LenovoGen7And8USBController::setLedsDirect(std::vector &leds, std::vector &colors) +{ + uint8_t buffer[PACKET_SIZE]; + memset(buffer, 0x00, PACKET_SIZE); + + size_t i = 0; + buffer[i++] = REPORT_ID; + buffer[i++] = DIRECT_MODE; + buffer[i++] = 0xC0; + buffer[i++] = 0x03; + + for(size_t index = 0; index < leds.size() && i < PACKET_SIZE; index++) + { + buffer[i++] = leds[index].value & 0xFF; + buffer[i++] = leds[index].value >> 8 & 0xFF; + buffer[i++] = RGBGetRValue(colors[index]); + buffer[i++] = RGBGetGValue(colors[index]); + buffer[i++] = RGBGetBValue(colors[index]); + } + + sendFeatureReport(buffer, PACKET_SIZE); +} + +void LenovoGen7And8USBController::setLedsAllOff(uint8_t profile_id) +{ + uint8_t buffer[PACKET_SIZE] = {REPORT_ID, SAVE_PROFILE, 0xC0, 0x03, profile_id, 0x01, 0x01}; + + sendFeatureReport(buffer, PACKET_SIZE); +} + +uint8_t LenovoGen7And8USBController::getCurrentProfileId() +{ + uint8_t buffer[PACKET_SIZE] = {REPORT_ID, GET_ACTIVE_PROFILE, 0xC0, 0x03}; + + vector response = getFeatureReport(buffer, PACKET_SIZE); + + return response.size()>4?response[4]:0x01; +} + +uint8_t LenovoGen7And8USBController::getCurrentBrightness() +{ + uint8_t buffer[PACKET_SIZE] = {REPORT_ID, GET_BRIGHTNESS, 0xC0, 0x03}; + + vector response = getFeatureReport(buffer, PACKET_SIZE); + + return response.size()>4?response[4]:0x00; +} + + +void LenovoGen7And8USBController::setBrightness(uint8_t brightness) +{ + uint8_t buffer[PACKET_SIZE] = {REPORT_ID, SET_BRIGHTNESS, 0xC0, 0x03, brightness}; + + sendFeatureReport(buffer, PACKET_SIZE); +} + +void LenovoGen7And8USBController::switchProfileTo(uint8_t profile_id) +{ + uint8_t buffer[PACKET_SIZE] = {REPORT_ID, SWITCH_PROFILE, 0xC0, 0x03, profile_id}; + + sendFeatureReport(buffer, PACKET_SIZE); +} + +std::vector LenovoGen7And8USBController::getProfileSettings(uint8_t profile_id) +{ + uint8_t buffer[PACKET_SIZE] = {REPORT_ID, GET_PROFILE, 0xC0, 0x03, profile_id}; + + vector response = getFeatureReport(buffer, PACKET_SIZE); + + vector groups; + + size_t i = 7; + while(i < response.size() && response[i] != 0x00){ + i++; + + led_group group; + + /*-----------------*\ + |read group settings| + \*-----------------*/ + + size_t cnt = response[i++]; + for(size_t j = 0; j < cnt && i < response.size(); j++, i+=2) + { + switch(response[i]) + { + case 0x01: + group.mode = response[i+1]; + break; + case 0x02: + group.speed = response[i+1]; + break; + case 0x03: + group.spin = response[i+1]; + break; + case 0x04: + group.direction = response[i+1]; + break; + case 0x05: + group.color_mode = response[i+1]; + break; + case 0x06: + //group.mode = response[i+1]; + break; + } + } + + /*-----------------*\ + |read group colors | + \*-----------------*/ + + cnt = response[i++]; + for(size_t j = 0; j < cnt && i < response.size(); j++, i+=3) + { + group.colors.push_back(ToRGBColor(response[i],response[i+1],response[i+2])); + } + + /*-----------------*\ + |read group LEDs | + \*-----------------*/ + + cnt = response[i++]; + for(size_t j = 0; j < cnt && i < response.size(); j++, i+=2) + { + group.leds.push_back(response[i] | response[i+1] << 8); + } + + groups.push_back(group); + } + + return groups; + +} + +void LenovoGen7And8USBController::sendFeatureReport(uint8_t packet[], size_t packet_size) +{ + hid_send_feature_report(dev, packet, packet_size); + LOG_TRACE("[Lenovo Gen 7 Controller] Buffer: %s", ConvertBytesToHex(packet, packet_size).c_str()); +} + +std::vector LenovoGen7And8USBController::getFeatureReport(uint8_t packet[], size_t packet_size) +{ + sendFeatureReport(packet, packet_size); + + uint8_t read_buffer[PACKET_SIZE] = {REPORT_ID}; + int num_bytes = 0; + num_bytes = hid_get_feature_report(dev, read_buffer, sizeof(read_buffer)); + + vector response = {}; + if(num_bytes > 0) + { + response.insert(response.begin(), read_buffer, read_buffer + num_bytes); + } + + LOG_TRACE("[Lenovo Gen 7 Controller] Read Buffer: %s", ConvertBytesToHex(response).c_str()); + return response; +} + +std::string LenovoGen7And8USBController::ConvertBytesToHex(uint8_t packet[], size_t packet_size) +{ + return ConvertBytesToHex(std::vector(packet, packet + packet_size)); +} + +std::string LenovoGen7And8USBController::ConvertBytesToHex(const std::vector &input) +{ + std::ostringstream temp_stream; + for(const uint8_t &oneInputByte : input) + { + temp_stream << (temp_stream.tellp()==0 ? "" : " ") << std::setw(2) << std::setfill('0') << std::hex << (int)oneInputByte; + } + return temp_stream.str(); +} diff --git a/Controllers/LenovoControllers/LenovoUSBController_Gen7_8/LenovoUSBController_Gen7_8.h b/Controllers/LenovoControllers/LenovoUSBController_Gen7_8/LenovoUSBController_Gen7_8.h new file mode 100644 index 00000000..65c161bd --- /dev/null +++ b/Controllers/LenovoControllers/LenovoUSBController_Gen7_8/LenovoUSBController_Gen7_8.h @@ -0,0 +1,92 @@ +/*---------------------------------------------------------*\ +| LenovoUSBController_Gen7_8.h | +| | +| Driver for Lenovo Gen7 and Gen8 devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include +#include +#include "RGBController.h" +#include "LogManager.h" + +#ifndef HID_MAX_STR +#define HID_MAX_STR 255 +#endif + +#define PACKET_SIZE 960 +#define REPORT_ID 0x07 +#define DIRECT_MODE 0xA1 +#define SWITCH_PROFILE 0xC8 +#define GET_ACTIVE_PROFILE 0xCA +#define SAVE_PROFILE 0xCB +#define GET_PROFILE 0xCC +#define GET_BRIGHTNESS 0xCD +#define SET_BRIGHTNESS 0xCE +#define SET_DIRECT_MODE 0xD0 +#define GET_DIRECT_MODE_PROFILE 0xD1 + +struct led_group +{ + uint8_t mode; + uint8_t speed; + uint8_t spin; + uint8_t direction; + uint8_t color_mode; + std::vector colors; + std::vector leds; +}; + +class LenovoGen7And8USBController +{ + + public: + /*--------------*\ + |ctor(s) and dtor| + \*--------------*/ + LenovoGen7And8USBController(hid_device* dev_handle, const char* path, uint16_t in_pid, std::string dev_name); + ~LenovoGen7And8USBController(); + + /*--------------*\ + |device functions| + \*--------------*/ + void setLedsByGroup(uint8_t profile_id, std::vector led_groups); + void setLedsDirect(std::vector &leds, std::vector &colors); + void setLedsAllOff(uint8_t profile_id); + void setLedsDirectOn(uint8_t profile_id); + void setLedsDirectOff(uint8_t profile_id); + uint16_t getPid(); + std::string getName(); + std::string getLocation(); + uint8_t getCurrentProfileId(); + uint8_t getCurrentBrightness(); + void setBrightness(uint8_t brightness); + uint8_t getKeyboardId(); + void switchProfileTo(uint8_t profile_id); + std::vector getProfileSettings(uint8_t profile_id); + + + private: + /*--------------*\ + |data members | + \*--------------*/ + std::string name; + hid_device *dev; + std::string location; + uint16_t pid; + + /*--------------*\ + |device functions| + \*--------------*/ + void sendFeatureReport(uint8_t packet[], size_t packet_size); + std::vector getFeatureReport(uint8_t packet[], size_t packet_size); + std::string ConvertBytesToHex(uint8_t packet[], size_t packet_size); + std::string ConvertBytesToHex(const std::vector &input); +}; diff --git a/Controllers/LenovoControllers/LenovoUSBController_Gen7_8/RGBController_Lenovo_Gen7_8.cpp b/Controllers/LenovoControllers/LenovoUSBController_Gen7_8/RGBController_Lenovo_Gen7_8.cpp new file mode 100644 index 00000000..af8370d7 --- /dev/null +++ b/Controllers/LenovoControllers/LenovoUSBController_Gen7_8/RGBController_Lenovo_Gen7_8.cpp @@ -0,0 +1,651 @@ +/*---------------------------------------------------------*\ +| RGBController_Lenovo_Gen7_8.cpp | +| | +| RGBController for Lenovo Gen7 and Gen8 devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RGBController_Lenovo_Gen7_8.h" +#include "LenovoDevices.h" + +using namespace std; + +LenovoRGBController_Gen7_8::LenovoRGBController_Gen7_8(LenovoGen7And8USBController* controller_ptr) +{ + controller = controller_ptr; + + mode Screw; + Screw.name = "Screw Rainbow"; + Screw.value = LENOVO_LEGION_GEN7_8_MODE_SCREW_RAINBOW; + Screw.flags = MODE_FLAG_HAS_SPEED | + MODE_FLAG_HAS_DIRECTION_LR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_AUTOMATIC_SAVE; + Screw.speed_min = 0x01; + Screw.speed_max = 0x03; + Screw.speed = 2; + Screw.color_mode = MODE_COLORS_NONE; + Screw.brightness_min = 0; + Screw.brightness_max = 9; + Screw.brightness = brightness; + Screw.direction = MODE_DIRECTION_RIGHT; + modes.push_back(Screw); + + mode Rainbow; + Rainbow.name = "Rainbow Wave"; + Rainbow.value = LENOVO_LEGION_GEN7_8_MODE_RAINBOW_WAVE; + Rainbow.flags = MODE_FLAG_HAS_SPEED | + MODE_FLAG_HAS_DIRECTION_LR | + MODE_FLAG_HAS_DIRECTION_UD | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_AUTOMATIC_SAVE; + Rainbow.speed_min = 0x01; + Rainbow.speed_max = 0x03; + Rainbow.speed = 2; + Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.brightness_min = 0; + Rainbow.brightness_max = 9; + Rainbow.brightness = brightness; + Rainbow.direction = MODE_DIRECTION_RIGHT; + modes.push_back(Rainbow); + + mode ColorChange; + ColorChange.name = "Color Change"; + ColorChange.value = LENOVO_LEGION_GEN7_8_MODE_COLOR_CHANGE; + ColorChange.flags = MODE_FLAG_HAS_SPEED | + MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_RANDOM_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_AUTOMATIC_SAVE; + ColorChange.speed_min = 0x01; + ColorChange.speed_max = 0x03; + ColorChange.speed = 2; + ColorChange.colors_min = 1; + ColorChange.colors_max = 4; + ColorChange.colors.resize(4); + ColorChange.colors[0] = 0xFFF500; + ColorChange.color_mode = MODE_COLORS_RANDOM; + ColorChange.brightness_min = 0; + ColorChange.brightness_max = 9; + ColorChange.brightness = brightness; + modes.push_back(ColorChange); + + mode ColorPulse; + ColorPulse.name = "Color Pulse"; + ColorPulse.value = LENOVO_LEGION_GEN7_8_MODE_COLOR_PULSE; + ColorPulse.flags = MODE_FLAG_HAS_SPEED | + MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_RANDOM_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_AUTOMATIC_SAVE; + ColorPulse.speed_min = 0x01; + ColorPulse.speed_max = 0x03; + ColorPulse.speed = 2; + ColorPulse.colors_min = 1; + ColorPulse.colors_max = 4; + ColorPulse.colors.resize(4); + ColorPulse.colors[0] = 0xFFF500; + ColorPulse.color_mode = MODE_COLORS_RANDOM; + ColorPulse.brightness_min = 0; + ColorPulse.brightness_max = 9; + ColorPulse.brightness = brightness; + modes.push_back(ColorPulse); + + mode ColorWave; + ColorWave.name = "Color Wave"; + ColorWave.value = LENOVO_LEGION_GEN7_8_MODE_COLOR_WAVE; + ColorWave.flags = MODE_FLAG_HAS_SPEED | + MODE_FLAG_HAS_DIRECTION_LR | + MODE_FLAG_HAS_DIRECTION_UD | + MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_RANDOM_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_AUTOMATIC_SAVE; + ColorWave.speed_min = 0x01; + ColorWave.speed_max = 0x03; + ColorWave.speed = 2; + ColorWave.colors_min = 1; + ColorWave.colors_max = 4; + ColorWave.colors.resize(4); + ColorWave.colors[0] = 0xFFF500; + ColorWave.color_mode = MODE_COLORS_RANDOM; + ColorWave.brightness_min = 0; + ColorWave.brightness_max = 9; + ColorWave.brightness = brightness; + ColorWave.direction = MODE_DIRECTION_RIGHT; + modes.push_back(ColorWave); + + mode Smooth; + Smooth.name = "Smooth"; + Smooth.value = LENOVO_LEGION_GEN7_8_MODE_SMOOTH; + Smooth.flags = MODE_FLAG_HAS_SPEED | + MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_RANDOM_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_AUTOMATIC_SAVE; + Smooth.speed_min = 0x01; + Smooth.speed_max = 0x03; + Smooth.speed = 2; + Smooth.colors_min = 1; + Smooth.colors_max = 4; + Smooth.colors.resize(4); + Smooth.colors[0] = 0xFFF500; + Smooth.color_mode = MODE_COLORS_RANDOM; + Smooth.brightness_min = 0; + Smooth.brightness_max = 9; + Smooth.brightness = brightness; + modes.push_back(Smooth); + + mode Rain; + Rain.name = "Rain"; + Rain.value = LENOVO_LEGION_GEN7_8_MODE_RAIN; + Rain.flags = MODE_FLAG_HAS_SPEED | + MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_RANDOM_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_AUTOMATIC_SAVE; + Rain.speed_min = 0x01; + Rain.speed_max = 0x03; + Rain.speed = 2; + Rain.colors_min = 1; + Rain.colors_max = 4; + Rain.colors.resize(4); + Rain.colors[0] = 0xFFF500; + Rain.color_mode = MODE_COLORS_RANDOM; + Rain.brightness_min = 0; + Rain.brightness_max = 9; + Rain.brightness = brightness; + modes.push_back(Rain); + + mode Ripple; + Ripple.name = "Ripple"; + Ripple.value = LENOVO_LEGION_GEN7_8_MODE_RIPPLE; + Ripple.flags = MODE_FLAG_HAS_SPEED | + MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_RANDOM_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_AUTOMATIC_SAVE; + Ripple.speed_min = 0x01; + Ripple.speed_max = 0x03; + Ripple.speed = 2; + Ripple.colors_min = 1; + Ripple.colors_max = 4; + Ripple.colors.resize(4); + Ripple.colors[0] = 0xFFF500; + Ripple.color_mode = MODE_COLORS_RANDOM; + Ripple.brightness_min = 0; + Ripple.brightness_max = 9; + Ripple.brightness = brightness; + modes.push_back(Ripple); + + mode AudioBounce; + AudioBounce.name = "Audio Bounce Lighting"; + AudioBounce.value = LENOVO_LEGION_GEN7_8_MODE_AUDIO_BOUNCE; + AudioBounce.flags = MODE_FLAG_HAS_BRIGHTNESS; + AudioBounce.color_mode = MODE_COLORS_NONE; + AudioBounce.brightness_min = 0; + AudioBounce.brightness_max = 9; + AudioBounce.brightness = brightness; + modes.push_back(AudioBounce); + + mode AudioRipple; + AudioRipple.name = "Audio Ripple Lighting"; + AudioRipple.value = LENOVO_LEGION_GEN7_8_MODE_AUDIO_RIPPLE; + AudioRipple.flags = MODE_FLAG_HAS_BRIGHTNESS; + AudioRipple.color_mode = MODE_COLORS_NONE; + AudioRipple.brightness_min = 0; + AudioRipple.brightness_max = 9; + AudioRipple.brightness = brightness; + modes.push_back(AudioRipple); + + mode Static; + Static.name = "Static"; + Static.value = LENOVO_LEGION_GEN7_8_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_AUTOMATIC_SAVE; + Static.color_mode = MODE_COLORS_PER_LED; + Static.brightness_min = 0; + Static.brightness_max = 9; + Static.brightness = brightness; + modes.push_back(Static); + + mode Type; + Type.name = "Type Lighting"; + Type.value = LENOVO_LEGION_GEN7_8_MODE_TYPE; + Type.flags = MODE_FLAG_HAS_SPEED | + MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_RANDOM_COLOR | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_AUTOMATIC_SAVE; + Type.speed_min = 0x01; + Type.speed_max = 0x03; + Type.speed = 2; + Type.colors_min = 1; + Type.colors_max = 4; + Type.colors.resize(4); + Type.colors[0] = 0xFFF500; + Type.color_mode = MODE_COLORS_RANDOM; + Type.brightness_min = 0; + Type.brightness_max = 9; + Type.brightness = brightness; + modes.push_back(Type); + + mode Direct; + Direct.name = "Direct"; + Direct.value = LENOVO_LEGION_GEN7_8_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | + MODE_FLAG_HAS_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = 0; + Direct.brightness_max = 9; + Direct.brightness = brightness; + modes.push_back(Direct); + + + name = controller->getName(); + type = DEVICE_TYPE_KEYBOARD; + vendor = "Lenovo"; + + switch (controller->getPid()) + { + case LEGION_S7GEN7: + description = "Lenovo Legion 7 Slim Generation 7"; + break; + + case LEGION_7GEN7: + description = "Lenovo Legion 7 Generation 7"; + break; + + case LEGION_7GEN8: + description = "Lenovo Legion 7 Generation 8"; + break; + + case LEGION_7GEN9: + case LEGION_7GEN9_H: + description = "Lenovo Legion 7 Generation 9"; + break; + } + + brightness = controller->getCurrentBrightness(); + profile_id = controller->getCurrentProfileId(); + + SetupZones(); + + /*-----------------*\ + | Initiliaze Static | + \*-----------------*/ + // ToDo: Commented causes a crash. (???) + active_mode = 10; + ReadDeviceSettings(); + last_mode = active_mode; +} + +LenovoRGBController_Gen7_8::~LenovoRGBController_Gen7_8() +{ + delete controller; +} + + +void LenovoRGBController_Gen7_8::SetupZones() +{ + vector lenovo_zones; + lenovo_zones.push_back(legion7_gen7and8_kbd_ansi); + lenovo_zones.push_back(legion7_gen7and8_neon); + + if (controller->getPid() == LEGION_7GEN7) + { + lenovo_zones.push_back(lenovo_legion_7gen7_logo); + lenovo_zones.push_back(lenovo_legion_7gen7_vents); + } + + for(unsigned int i = 0; i < lenovo_zones.size(); i++) + { + zone new_zone; + new_zone.name = lenovo_zones[i].name; + new_zone.type = lenovo_zones[i].type; + new_zone.leds_count = lenovo_zones[i].end - lenovo_zones[i].start + 1; + new_zone.leds_max = new_zone.leds_count; + new_zone.leds_min = new_zone.leds_count; + + LOG_DEBUG("[Lenovo Gen7/8 Controller] adding zone: %s with %u LEDs", new_zone.name.c_str(), new_zone.leds_count); + + if(lenovo_zones[i].type == ZONE_TYPE_MATRIX) + { + new_zone.matrix_map = new matrix_map_type; + new_zone.matrix_map->height = lenovo_zones[i].height; + new_zone.matrix_map->width = lenovo_zones[i].width; + new_zone.matrix_map->map = new unsigned int[new_zone.matrix_map->height * new_zone.matrix_map->width]; + + if(lenovo_zones[i].matrix_map != NULL) + { + new_zone.matrix_map->map = (unsigned int *) lenovo_zones[i].matrix_map; + } + } + else + { + new_zone.matrix_map = NULL; + } + + zones.push_back(new_zone); + + for(unsigned int led_idx = lenovo_zones[i].start; led_idx <= lenovo_zones[i].end; led_idx++ ) + { + led new_led; + new_led.name = lenovo_zones[i].leds[led_idx].name; + new_led.value = lenovo_zones[i].id << 8 | lenovo_zones[i].leds[led_idx].led_num ; + leds.push_back(new_led); + + /*---------------------------------------------------------*\ + | create led id to index map for fast look up | + \*---------------------------------------------------------*/ + led_id_to_index[new_led.value]=leds.size() - 1; + } + } + + SetupColors(); +} + +void LenovoRGBController_Gen7_8::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void LenovoRGBController_Gen7_8::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void LenovoRGBController_Gen7_8::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void LenovoRGBController_Gen7_8::DeviceUpdateMode() +{ + uint8_t hw_profile_id = controller->getCurrentProfileId(); + if(hw_profile_id != profile_id) + { + profile_id = hw_profile_id; + ReadDeviceSettings(); + last_mode = active_mode; + } + + if(brightness != modes[active_mode].brightness) + { + brightness = modes[active_mode].brightness; + controller->setBrightness(brightness); + for(mode &m : modes) + { + m.brightness = brightness; + } + } + + if(last_mode != active_mode) + { + + if(modes[last_mode].value == LENOVO_LEGION_GEN7_8_MODE_DIRECT) + { + controller->setLedsDirectOff(profile_id); + } + + + if(modes[active_mode].value == LENOVO_LEGION_GEN7_8_MODE_DIRECT) + { + controller->setLedsDirectOn(profile_id); + controller->setLedsByGroup(profile_id, GetLedGroups()); + } + + last_mode = active_mode; + } + + if(modes[active_mode].value != LENOVO_LEGION_GEN7_8_MODE_DIRECT) + { + DeviceUpdateLEDs(); + } +} + +void LenovoRGBController_Gen7_8::DeviceUpdateLEDs() +{ + if(modes[active_mode].value == LENOVO_LEGION_GEN7_8_MODE_DIRECT) + { + controller->setLedsDirect(leds, colors); + } + else + { + controller->setLedsByGroup(profile_id, GetLedGroups()); + } + +} + +void LenovoRGBController_Gen7_8::ReadDeviceSettings() +{ + vector current_settings = controller->getProfileSettings(profile_id); + if(current_settings.size() > 0) + { + for(unsigned int i = 0; i < modes.size(); i++) + { + if(modes[i].value == current_settings[0].mode) + { + switch(current_settings[0].color_mode) + { + case 0x02: + if(modes[i].flags & MODE_FLAG_HAS_PER_LED_COLOR) + { + modes[i].color_mode = MODE_COLORS_PER_LED; + } + else + { + modes[i].color_mode = MODE_COLORS_MODE_SPECIFIC; + } + break; + + case 0x01: + modes[i].color_mode = MODE_COLORS_RANDOM; + break; + + default: + modes[i].color_mode = MODE_COLORS_NONE; + } + + switch(modes[i].color_mode) + { + case MODE_COLORS_PER_LED: + for(size_t j=0; j < colors.size(); j++) + { + colors[j]=0x00; + } + for(const led_group &lg : current_settings) + { + if(lg.colors.size() > 0) + { + for(uint16_t led_id : lg.leds) + { + if(auto search = led_id_to_index.find(led_id); search != led_id_to_index.end()) + { + colors[search->second] = lg.colors[0]; + } + } + } + } + break; + + case MODE_COLORS_MODE_SPECIFIC: + for(size_t j=0; j < modes[i].colors.size(); j++) + { + if(j < current_settings[0].colors.size()) + { + modes[i].colors[j] = current_settings[0].colors[j]; + } + else + { + modes[i].colors[j] = 0x00; + } + } + } + + switch(current_settings[0].direction) + { + case 0x01: + modes[i].direction = MODE_DIRECTION_UP; + break; + case 0x02: + modes[i].direction = MODE_DIRECTION_DOWN; + break; + case 0x03: + modes[i].direction = MODE_DIRECTION_LEFT; + break; + case 0x04: + modes[i].direction = MODE_DIRECTION_RIGHT; + break; + } + + switch(current_settings[0].spin) + { + case 0x01: + modes[i].direction = MODE_DIRECTION_RIGHT; + break; + case 0x02: + modes[i].direction = MODE_DIRECTION_LEFT; + break; + } + + active_mode = i; + break; //stop for loop + } + } + } +} + +std::vector LenovoRGBController_Gen7_8::GetLedGroups() +{ + std::unordered_map> led_map; + + if(modes[active_mode].color_mode == MODE_COLORS_PER_LED && + modes[active_mode].value != LENOVO_LEGION_GEN7_8_MODE_DIRECT) + { + for(size_t i = 0; i < leds.size(); i++) + { + led_map[colors[i]].push_back(leds[i].value); + } + } + else + { + size_t start = 0; + size_t end = leds.size(); + + /*---------------------------------------------------------*\ + | Riplle and Type only apply to keyboard | + \*---------------------------------------------------------*/ + if(modes[active_mode].value == LENOVO_LEGION_GEN7_8_MODE_RIPPLE || + modes[active_mode].value == LENOVO_LEGION_GEN7_8_MODE_TYPE) + { + for(const zone &z : zones) + { + if(z.name == "Keyboard") + { + start = z.start_idx; + end = start + z.leds_count; + } + } + + } + + for(size_t i = start; i < end; i++) + { + led_map[0x00].push_back(leds[i].value); + } + } + + vector led_groups; + for(const auto &pair : led_map) + { + if(pair.first == 0x00 && led_map.size() != 1) + { + continue; + } + + led_group group; + group.mode = modes[active_mode].value; + group.speed = modes[active_mode].speed; + group.spin = 0x00; + group.direction = 0x00; + + switch(modes[active_mode].direction) + { + case MODE_DIRECTION_UP: + group.direction = 0x01; + break; + + case MODE_DIRECTION_DOWN: + group.direction = 0x02; + break; + + case MODE_DIRECTION_LEFT: + if(modes[active_mode].value == LENOVO_LEGION_GEN7_8_MODE_SCREW_RAINBOW) + { + group.spin = 0x02; + } + else + { + group.direction = 0x03; + } + break; + + case MODE_DIRECTION_RIGHT: + if(modes[active_mode].value == LENOVO_LEGION_GEN7_8_MODE_SCREW_RAINBOW) + { + group.spin = 0x01; + } + else + { + group.direction = 0x04; + } + break; + } + + switch(modes[active_mode].color_mode) + { + default: + case MODE_COLORS_NONE: + group.color_mode = 0x00; + break; + + case MODE_COLORS_RANDOM: + group.color_mode = 0x01; + break; + + case MODE_COLORS_MODE_SPECIFIC: + group.color_mode = 0x02; + for(RGBColor c : modes[active_mode].colors) + { + if(c) + { + group.colors.push_back(c); + } + } + + if(group.colors.size() == 0) + { + group.colors.push_back(0xFFF500); + } + break; + + case MODE_COLORS_PER_LED: + group.color_mode = 0x02; + group.colors.push_back(pair.first); + break; + } + + group.leds = pair.second; + + led_groups.push_back(group); + } + + return led_groups; +} diff --git a/Controllers/LenovoControllers/LenovoUSBController_Gen7_8/RGBController_Lenovo_Gen7_8.h b/Controllers/LenovoControllers/LenovoUSBController_Gen7_8/RGBController_Lenovo_Gen7_8.h new file mode 100644 index 00000000..e39ff727 --- /dev/null +++ b/Controllers/LenovoControllers/LenovoUSBController_Gen7_8/RGBController_Lenovo_Gen7_8.h @@ -0,0 +1,56 @@ +/*---------------------------------------------------------*\ +| RGBController_Lenovo_Gen7_8.h | +| | +| RGBController for Lenovo Gen7 and Gen8 devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LenovoUSBController_Gen7_8.h" + +enum +{ + LENOVO_LEGION_GEN7_8_MODE_SCREW_RAINBOW = 0x01, + LENOVO_LEGION_GEN7_8_MODE_RAINBOW_WAVE = 0x02, + LENOVO_LEGION_GEN7_8_MODE_COLOR_CHANGE = 0x03, + LENOVO_LEGION_GEN7_8_MODE_COLOR_PULSE = 0x04, + LENOVO_LEGION_GEN7_8_MODE_COLOR_WAVE = 0x05, + LENOVO_LEGION_GEN7_8_MODE_SMOOTH = 0x06, + LENOVO_LEGION_GEN7_8_MODE_RAIN = 0x07, + LENOVO_LEGION_GEN7_8_MODE_RIPPLE = 0x08, + LENOVO_LEGION_GEN7_8_MODE_AUDIO_BOUNCE = 0x09, + LENOVO_LEGION_GEN7_8_MODE_AUDIO_RIPPLE = 0x0A, + LENOVO_LEGION_GEN7_8_MODE_STATIC = 0x0B, + LENOVO_LEGION_GEN7_8_MODE_TYPE = 0x0C, + LENOVO_LEGION_GEN7_8_MODE_DIRECT = 0x0D, +}; + +class LenovoRGBController_Gen7_8 : public RGBController +{ +public: + LenovoRGBController_Gen7_8(LenovoGen7And8USBController* controller_ptr); + ~LenovoRGBController_Gen7_8(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LenovoGen7And8USBController* controller; + std::vector GetLedGroups(); + void ReadDeviceSettings(); + std::unordered_map led_id_to_index; + int last_mode = 0; + uint8_t brightness = 0x00; + uint8_t profile_id = 0x01; +}; diff --git a/Controllers/LenovoControllers/LenovoUSBDetect.cpp b/Controllers/LenovoControllers/LenovoUSBDetect.cpp deleted file mode 100644 index 9f2c07bb..00000000 --- a/Controllers/LenovoControllers/LenovoUSBDetect.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/*-------------------------------------------------------------------*\ -| LenovoUSBDetect.h | -| | -| Describes zones for various Lenovo Legion Devices | -| | -| Cooper Hall (geobot19) 17 Apr 2022 | -| | -\*-------------------------------------------------------------------*/ - -#include "Detector.h" -#include "LogManager.h" -#include "RGBController.h" -#include "LenovoUSBController.h" -#include "LenovoDevices.h" -#include "RGBController_LenovoUSB.h" -#include - -/*-----------------------------------------------------*\ -| vendor IDs | -\*-----------------------------------------------------*/ -#define ITE_VID 0x048D - -/*-----------------------------------------------------*\ -| Interface, Usage, and Usage Page | -\*-----------------------------------------------------*/ -enum -{ - LENOVO_PAGE = 0xFF89, - LENOVO_USEAGE = 0x07 -}; - -void DetectLenovoLegionUSBControllers(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - - if(dev) - { - LenovoUSBController* controller = new LenovoUSBController(dev, info->path, info->product_id); - RGBController_LenovoUSB* rgb_controller = new RGBController_LenovoUSB(controller); - rgb_controller->name = name; - - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -REGISTER_HID_DETECTOR_PU("Lenovo Legion Y740", DetectLenovoLegionUSBControllers, ITE_VID, LEGION_Y740, LENOVO_PAGE, LENOVO_USEAGE); -REGISTER_HID_DETECTOR_PU("Lenovo Legion 7 gen 5", DetectLenovoLegionUSBControllers, ITE_VID, LEGION_Y750, LENOVO_PAGE, LENOVO_USEAGE); -REGISTER_HID_DETECTOR_PU("Lenovo Legion 7S gen 5", DetectLenovoLegionUSBControllers, ITE_VID, LEGION_Y750S, LENOVO_PAGE, LENOVO_USEAGE); -REGISTER_HID_DETECTOR_PU("Lenovo Legion 7 gen 6", DetectLenovoLegionUSBControllers, ITE_VID, LEGION_Y760, LENOVO_PAGE, LENOVO_USEAGE); -REGISTER_HID_DETECTOR_PU("Lenovo Legion 7S gen 6", DetectLenovoLegionUSBControllers, ITE_VID, LEGION_Y760S, LENOVO_PAGE, LENOVO_USEAGE); diff --git a/Controllers/LenovoControllers/RGBController_Lenovo4ZoneUSB.cpp b/Controllers/LenovoControllers/RGBController_Lenovo4ZoneUSB.cpp deleted file mode 100644 index 00b6f727..00000000 --- a/Controllers/LenovoControllers/RGBController_Lenovo4ZoneUSB.cpp +++ /dev/null @@ -1,164 +0,0 @@ -#include "Lenovo4ZoneUSBController.h" -#include "LenovoDevices4Zone.h" -#include "RGBController_Lenovo4ZoneUSB.h" -#include "LogManager.h" - -#include -#include -#include -#include -#include -#include - -#define LENOVO_4_ZONE_NUM_LEDS 4 - -RGBController_Lenovo4ZoneUSB::RGBController_Lenovo4ZoneUSB(Lenovo4ZoneUSBController* controller_ptr) -{ - controller = controller_ptr; - - name = controller->getName(); - type = DEVICE_TYPE_KEYBOARD; - vendor = "Lenovo"; - - - description = "Lenovo 4-Zone device"; - - mode Direct; - Direct.name = "Direct"; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Direct.color_mode = MODE_COLORS_PER_LED; - Direct.brightness_min = 1; - Direct.brightness_max = 2; - - modes.push_back(Direct); - - mode Breath; - Breath.name = "Breathing"; - Breath.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | - MODE_FLAG_HAS_SPEED; - Breath.color_mode = MODE_COLORS_PER_LED; - Breath.brightness_min = 1; - Breath.brightness_max = 2; - Breath.speed_min = 1; - Breath.speed_max = 4; - - modes.push_back(Breath); - - mode Wave; - Wave.name = "Rainbow Wave"; - Wave.flags = MODE_FLAG_HAS_RANDOM_COLOR | - MODE_FLAG_HAS_BRIGHTNESS | - MODE_FLAG_HAS_SPEED | - MODE_FLAG_HAS_DIRECTION_LR; - Wave.color_mode = MODE_COLORS_RANDOM; - Wave.brightness_min = 1; - Wave.brightness_max = 2; - Wave.speed_min = 1; - Wave.speed_max = 4; - Wave.direction = MODE_DIRECTION_LEFT | MODE_DIRECTION_RIGHT; - modes.push_back(Wave); - - mode Smooth; - Smooth.name = "Spectrum Cycle"; - Smooth.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | - MODE_FLAG_HAS_SPEED; - Smooth.color_mode = MODE_COLORS_RANDOM; - Smooth.brightness_min = 1; - Smooth.brightness_max = 2; - Smooth.speed_min = 1; - Smooth.speed_max = 4; - modes.push_back(Smooth); - - - SetupZones(); -} - -RGBController_Lenovo4ZoneUSB::~RGBController_Lenovo4ZoneUSB() -{ - delete controller; -} - -void RGBController_Lenovo4ZoneUSB::SetupZones() -{ - zone new_zone; - new_zone.name = ZONE_EN_KEYBOARD; - new_zone.type = ZONE_TYPE_LINEAR; - new_zone.leds_count = LENOVO_4_ZONE_NUM_LEDS; - new_zone.leds_max = new_zone.leds_count; - new_zone.leds_min = new_zone.leds_count; - - new_zone.matrix_map = NULL; - - - zones.push_back(new_zone); - - for(unsigned int led_idx = 0; led_idx < LENOVO_4_ZONE_NUM_LEDS; led_idx++ ) - { - led new_led; - new_led.name = lenovo_4_zone_leds[led_idx].name; - new_led.value = lenovo_4_zone_leds[led_idx].led_num; - leds.push_back(new_led); - } - - SetupColors(); -} - -void RGBController_Lenovo4ZoneUSB::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_Lenovo4ZoneUSB::UpdateSingleLED(int /*led*/) -{ -} - -void RGBController_Lenovo4ZoneUSB::UpdateZoneLEDs(int /*zone*/) -{ -} - -void RGBController_Lenovo4ZoneUSB::DeviceUpdateLEDs() -{ - state.SetColors(colors); - controller->setMode(state); -} - -void RGBController_Lenovo4ZoneUSB::DeviceUpdateMode() -{ - state.Reset(); - state.SetColors(colors); - - switch (active_mode) - { - case 0: - state.effect = LENOVO_4_ZONE_EFFECT_STATIC; - break; - case 1: - state.effect = LENOVO_4_ZONE_EFFECT_BREATH; - break; - case 2: - state.effect = LENOVO_4_ZONE_EFFECT_WAVE; - state.wave_ltr = modes[active_mode].direction?0:1; - state.wave_rtl = modes[active_mode].direction?1:0; - break; - case 3: - state.effect = LENOVO_4_ZONE_EFFECT_SMOOTH; - break; - } - - if(active_mode != (LENOVO_4_ZONE_EFFECT_STATIC - 1)) // mode number from 0, but in mode from 1 - { - state.speed = modes[active_mode].speed; - } - state.brightness = modes[active_mode].brightness; - - controller->setMode(state); -} - -void RGBController_Lenovo4ZoneUSB::DeviceSaveMode() -{ - /*---------------------------------------------------------*\ - | This device does not support saving or multiple modes | - \*---------------------------------------------------------*/ -} diff --git a/Controllers/LenovoControllers/RGBController_Lenovo4ZoneUSB.h b/Controllers/LenovoControllers/RGBController_Lenovo4ZoneUSB.h deleted file mode 100644 index ca377c5a..00000000 --- a/Controllers/LenovoControllers/RGBController_Lenovo4ZoneUSB.h +++ /dev/null @@ -1,37 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_Lenovo4ZoneUSB.h | -| | -| interface for Lenovo 4-Zones Devices | -\*-------------------------------------------------------------------*/ - -#pragma once - -#include "LenovoDevices.h" -#include "Lenovo4ZoneUSBController.h" -#include "RGBController.h" - -#include - -#define NA 0xFFFFFFFF - -class RGBController_Lenovo4ZoneUSB : public RGBController -{ -public: - RGBController_Lenovo4ZoneUSB(Lenovo4ZoneUSBController* controller_ptr); - ~RGBController_Lenovo4ZoneUSB(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - KeyboardState state; - - Lenovo4ZoneUSBController *controller; -}; diff --git a/Controllers/LenovoControllers/RGBController_LenovoUSB.h b/Controllers/LenovoControllers/RGBController_LenovoUSB.h deleted file mode 100644 index 550e4d6c..00000000 --- a/Controllers/LenovoControllers/RGBController_LenovoUSB.h +++ /dev/null @@ -1,49 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_LenovoUSB.h | -| | -| interface for various Lenovo Legion Devices | -| | -| Cooper Hall (geobot19) 17 Apr 2022 | -| | -\*-------------------------------------------------------------------*/ - -#include "LenovoDevices.h" -#include "LenovoUSBController.h" -#include "RGBController.h" - -#include - -#ifndef RGBCONTROLLER_LENOVOUSB_H -#define RGBCONTROLLER_LENOVOUSB_H - -#define NA 0xFFFFFFFF - -class RGBController_LenovoUSB : public RGBController -{ -public: - RGBController_LenovoUSB(LenovoUSBController* controller_ptr); - ~RGBController_LenovoUSB(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - std::string ConvertBytesToHex(const std::vector &input); - std::string keyboardToString(LENOVO_KEYBOARD kb); - std::string sizeToString(LENOVO_SIZE size); - void DumpControllerInformation(); - - LENOVO_KEYBOARD keyboard_type; - LENOVO_SIZE chasis_size; - - LenovoUSBController *controller; -}; - -#endif diff --git a/Controllers/LenovoMotherboardController/LenovoMotherboardController.cpp b/Controllers/LenovoMotherboardController/LenovoMotherboardController.cpp index 36eeae62..21d8f505 100644 --- a/Controllers/LenovoMotherboardController/LenovoMotherboardController.cpp +++ b/Controllers/LenovoMotherboardController/LenovoMotherboardController.cpp @@ -1,32 +1,23 @@ -/*-----------------------------------------*\ -| LenovoMotherboardController.cpp | -| | -| Driver for Lenovo motherboards lighting | -| controller | -| | -| Guimard Morgan (morg) 12/26/2022 | -\*-----------------------------------------*/ -#include "LenovoMotherboardController.h" -#include +/*---------------------------------------------------------*\ +| LenovoMotherboardController.cpp | +| | +| Driver for Lenovo motherboard | +| | +| Morgan Guimard (morg) 26 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -LenovoMotherboardController::LenovoMotherboardController(hid_device* dev_handle, const hid_device_info& info) +#include +#include "LenovoMotherboardController.h" +#include "StringUtils.h" + +LenovoMotherboardController::LenovoMotherboardController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) { dev = dev_handle; location = info.path; - version = ""; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } + name = dev_name; } LenovoMotherboardController::~LenovoMotherboardController() @@ -39,14 +30,22 @@ std::string LenovoMotherboardController::GetDeviceLocation() return("HID: " + location); } -std::string LenovoMotherboardController::GetSerialString() +std::string LenovoMotherboardController::GetNameString() { - return(serial_number); + return(name); } -std::string LenovoMotherboardController::GetFirmwareVersion() +std::string LenovoMotherboardController::GetSerialString() { - return(version); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } void LenovoMotherboardController::SetMode(uint8_t zone, uint8_t mode, uint8_t brightness, uint8_t speed, RGBColor color) diff --git a/Controllers/LenovoMotherboardController/LenovoMotherboardController.h b/Controllers/LenovoMotherboardController/LenovoMotherboardController.h index 1f0d4381..2d698f7b 100644 --- a/Controllers/LenovoMotherboardController/LenovoMotherboardController.h +++ b/Controllers/LenovoMotherboardController/LenovoMotherboardController.h @@ -1,15 +1,18 @@ -/*-----------------------------------------*\ -| LenovoMotherboardController.cpp | -| | -| Driver for Lenovo motherboards lighting | -| controller - header file | -| | -| Guimard Morgan (morg) 12/26/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LenovoMotherboardController.h | +| | +| Driver for Lenovo motherboard | +| | +| Morgan Guimard (morg) 26 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include -#include +#include #include "RGBController.h" #define LENOVO_MB_PACKET_LENGTH 64 @@ -40,18 +43,17 @@ enum class LenovoMotherboardController { public: - LenovoMotherboardController(hid_device* dev_handle, const hid_device_info& info); + LenovoMotherboardController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); ~LenovoMotherboardController(); - std::string GetSerialString(); std::string GetDeviceLocation(); - std::string GetFirmwareVersion(); + std::string GetNameString(); + std::string GetSerialString(); void SetMode(uint8_t zone, uint8_t mode, uint8_t brightness, uint8_t speed, RGBColor color); private: hid_device* dev; std::string location; - std::string serial_number; - std::string version; + std::string name; }; diff --git a/Controllers/LenovoMotherboardController/LenovoMotherboardControllerDetect.cpp b/Controllers/LenovoMotherboardController/LenovoMotherboardControllerDetect.cpp index 92ca1385..9fe29316 100644 --- a/Controllers/LenovoMotherboardController/LenovoMotherboardControllerDetect.cpp +++ b/Controllers/LenovoMotherboardController/LenovoMotherboardControllerDetect.cpp @@ -1,8 +1,18 @@ +/*---------------------------------------------------------*\ +| LenovoMotherboardControllerDetect.cpp | +| | +| Detector for Lenovo motherboard | +| | +| Morgan Guimard (morg) 26 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "LenovoMotherboardController.h" -#include "RGBController.h" #include "RGBController_LenovoMotherboard.h" -#include "dependencies/dmiinfo.h" +#include "dmiinfo.h" /*---------------------------------------------------------*\ | vendor ID | @@ -22,9 +32,8 @@ void DetectLenovoMotherboardControllers(hid_device_info* info, const std::string { DMIInfo dmi; - LenovoMotherboardController* controller = new LenovoMotherboardController(dev, *info); + LenovoMotherboardController* controller = new LenovoMotherboardController(dev, *info, name + " " + dmi.getMainboard()); RGBController_LenovoMotherboard* rgb_controller = new RGBController_LenovoMotherboard(controller); - rgb_controller->name = name + " " + dmi.getMainboard(); ResourceManager::get()->RegisterRGBController(rgb_controller); } diff --git a/Controllers/LenovoMotherboardController/RGBController_LenovoMotherboard.cpp b/Controllers/LenovoMotherboardController/RGBController_LenovoMotherboard.cpp index 1146c58a..c3ef3732 100644 --- a/Controllers/LenovoMotherboardController/RGBController_LenovoMotherboard.cpp +++ b/Controllers/LenovoMotherboardController/RGBController_LenovoMotherboard.cpp @@ -1,16 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_LenovoMotherboard.h | -| | -| Generic RGB Interface for OpenRGB | -| Lenovo motherboards RGB USB Driver | -| | -| Guimard Morgan (morg) 12/26/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LenovoMotherboard.cpp | +| | +| RGBController for Lenovo motherboard | +| | +| Morgan Guimard (morg) 26 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_LenovoMotherboard.h" - -#include #include +#include +#include "RGBController_LenovoMotherboard.h" /**------------------------------------------------------------------*\ @name LenovoMotherboard mouse @@ -26,13 +27,13 @@ RGBController_LenovoMotherboard::RGBController_LenovoMotherboard(LenovoMotherboardController* controller_ptr) { controller = controller_ptr; - name = "Lenovo motherboard"; + + name = controller->GetNameString(); vendor = "Lenovo"; type = DEVICE_TYPE_MOTHERBOARD; description = name; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); mode Static; Static.name = "Static"; @@ -198,6 +199,6 @@ void RGBController_LenovoMotherboard::UpdateSingleLED(int /*led*/) } void RGBController_LenovoMotherboard::DeviceUpdateMode() -{ +{ DeviceUpdateLEDs(); } diff --git a/Controllers/LenovoMotherboardController/RGBController_LenovoMotherboard.h b/Controllers/LenovoMotherboardController/RGBController_LenovoMotherboard.h index 7f312a5d..8b196486 100644 --- a/Controllers/LenovoMotherboardController/RGBController_LenovoMotherboard.h +++ b/Controllers/LenovoMotherboardController/RGBController_LenovoMotherboard.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_LenovoMotherboard.h | -| | -| Generic RGB Interface for OpenRGB | -| Lenovo motherboards RGB USB Driver | -| | -| Guimard Morgan (morg) 12/26/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LenovoMotherboard.h | +| | +| RGBController for Lenovo motherboard | +| | +| Morgan Guimard (morg) 26 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/LexipMouseController/LexipMouseController.cpp b/Controllers/LexipMouseController/LexipMouseController.cpp index 160378b9..417c762d 100644 --- a/Controllers/LexipMouseController/LexipMouseController.cpp +++ b/Controllers/LexipMouseController/LexipMouseController.cpp @@ -1,33 +1,23 @@ -/*-----------------------------------------*\ -| LexipMouseController.cpp | -| | -| Driver for Lexip mouse lighting | -| controller | -| | -| Guimard Morgan (morg) 2/21/2022 | -\*-----------------------------------------*/ -#include "LexipMouseController.h" -#include +/*---------------------------------------------------------*\ +| LexipMouseController.cpp | +| | +| Driver for Lexip mouse | +| | +| Morgan Guimard (morg) 21 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -LexipMouseController::LexipMouseController(hid_device* dev_handle, const hid_device_info& info) +#include +#include "LexipMouseController.h" +#include "StringUtils.h" + +LexipMouseController::LexipMouseController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) { dev = dev_handle; location = info.path; - version = ""; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } - + name = dev_name; } LexipMouseController::~LexipMouseController() @@ -40,14 +30,22 @@ std::string LexipMouseController::GetDeviceLocation() return("HID: " + location); } -std::string LexipMouseController::GetSerialString() +std::string LexipMouseController::GetNameString() { - return(serial_number); + return(name); } -std::string LexipMouseController::GetFirmwareVersion() +std::string LexipMouseController::GetSerialString() { - return(version); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } void LexipMouseController::SetDirect(RGBColor color) diff --git a/Controllers/LexipMouseController/LexipMouseController.h b/Controllers/LexipMouseController/LexipMouseController.h index 59ecb13f..482da99a 100644 --- a/Controllers/LexipMouseController/LexipMouseController.h +++ b/Controllers/LexipMouseController/LexipMouseController.h @@ -1,28 +1,31 @@ -/*-----------------------------------------*\ -| LexipMouseController.h | -| | -| Driver for Lexip mouse lighting | -| controller - header file | -| | -| Guimard Morgan (morg) 2/21/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LexipMouseController.h | +| | +| Driver for Lexip mouse | +| | +| Morgan Guimard (morg) 21 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once -#include "RGBController.h" #include -#include +#include +#include "RGBController.h" #define PACKET_DATA_LENGTH 64 class LexipMouseController { public: - LexipMouseController(hid_device* dev_handle, const hid_device_info& info); + LexipMouseController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); ~LexipMouseController(); - std::string GetSerialString(); std::string GetDeviceLocation(); - std::string GetFirmwareVersion(); + std::string GetNameString(); + std::string GetSerialString(); void SetDirect(RGBColor color); protected: @@ -30,6 +33,6 @@ protected: private: std::string location; - std::string serial_number; + std::string name; std::string version; }; diff --git a/Controllers/LexipMouseController/LexipMouseControllerDetect.cpp b/Controllers/LexipMouseController/LexipMouseControllerDetect.cpp index 9325b99f..049f7d5d 100644 --- a/Controllers/LexipMouseController/LexipMouseControllerDetect.cpp +++ b/Controllers/LexipMouseController/LexipMouseControllerDetect.cpp @@ -1,6 +1,16 @@ +/*---------------------------------------------------------*\ +| LexipMouseControllerDetect.cpp | +| | +| Detector for Lexip mouse | +| | +| Morgan Guimard (morg) 21 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "LexipMouseController.h" -#include "RGBController.h" #include "RGBController_LexipMouse.h" /*---------------------------------------------------------*\ @@ -19,9 +29,9 @@ void DetectLexipMouseControllers(hid_device_info* info, const std::string& name) if(dev) { - LexipMouseController* controller = new LexipMouseController(dev, *info); + LexipMouseController* controller = new LexipMouseController(dev, *info, name); RGBController_LexipMouse* rgb_controller = new RGBController_LexipMouse(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } diff --git a/Controllers/LexipMouseController/RGBController_LexipMouse.cpp b/Controllers/LexipMouseController/RGBController_LexipMouse.cpp index efe198dc..6baa55da 100644 --- a/Controllers/LexipMouseController/RGBController_LexipMouse.cpp +++ b/Controllers/LexipMouseController/RGBController_LexipMouse.cpp @@ -1,16 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_LexipMouse.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Lexip mouse USB Driver | -| | -| Guimard Morgan (morg) 2/21/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LexipMouse.cpp | +| | +| RGBController for Lexip mouse | +| | +| Morgan Guimard (morg) 21 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_LexipMouse.h" - -#include #include +#include +#include "RGBController_LexipMouse.h" /**------------------------------------------------------------------*\ @name Lexip Mouse @@ -26,13 +27,13 @@ RGBController_LexipMouse::RGBController_LexipMouse(LexipMouseController* controller_ptr) { controller = controller_ptr; - name = "Lexip Gaming Mouse"; + + name = controller->GetNameString(); vendor = "Lexip"; type = DEVICE_TYPE_MOUSE; description = name; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); mode Direct; Direct.name = "Direct"; diff --git a/Controllers/LexipMouseController/RGBController_LexipMouse.h b/Controllers/LexipMouseController/RGBController_LexipMouse.h index 34d9aa82..835c32e9 100644 --- a/Controllers/LexipMouseController/RGBController_LexipMouse.h +++ b/Controllers/LexipMouseController/RGBController_LexipMouse.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_LexipMouse.h | -| | -| Generic RGB Interface for OpenRGB | -| Lexip mouse RGB USB Driver | -| | -| Guimard Morgan (morg) 2/21/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LexipMouse.h | +| | +| RGBController for Lexip mouse | +| | +| Morgan Guimard (morg) 21 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/LianLiController/LianLiControllerDetect.cpp b/Controllers/LianLiController/LianLiControllerDetect.cpp index db10faa4..a903fa9b 100644 --- a/Controllers/LianLiController/LianLiControllerDetect.cpp +++ b/Controllers/LianLiController/LianLiControllerDetect.cpp @@ -1,29 +1,23 @@ -/*-----------------------------------------*\ -| LianLiControllerDetect.cpp | -| | -| Detector for Lian Li Uni Hub USB | -| lighting controller | -| | -| Luca Lovisa 2/20/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LianLiControllerDetect.cpp | +| | +| Detector for Lian Li devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include #include - +#include #include "Detector.h" #include "ResourceManager.h" -#ifdef __FreeBSD__ -#include -#else -#include -#endif - /*-----------------------------------------------------*\ | LianLi USB Controller specific includes | \*-----------------------------------------------------*/ #include "RGBController_LianLiUniHub.h" -#include "RGBController_StrimerLConnect.h" +#include "RGBController_LianLiStrimerLConnect.h" #include "LianLiUniHubController.h" #include "RGBController_LianLiUniHub.h" #include "LianLiUniHubALController.h" @@ -32,11 +26,16 @@ #include "RGBController_LianLiUniHub_AL10.h" #include "LianLiUniHubSLV2Controller.h" #include "RGBController_LianLiUniHubSLV2.h" +#include "LianLiUniHubSLInfinityController.h" +#include "RGBController_LianLiUniHubSLInfinity.h" +#include "LianLiGAIITrinityController.h" +#include "RGBController_LianLiGAIITrinity.h" /*-----------------------------------------------------*\ -| ENE USB vendor ID | +| USB vendor IDs | \*-----------------------------------------------------*/ #define ENE_USB_VID 0x0CF2 +#define NUVOTON_USB_VID 0x0416 /*-----------------------------------------------------*\ | Keyboard product IDs | @@ -48,8 +47,12 @@ \*-----------------------------------------------------*/ #define UNI_HUB_PID 0x7750 #define UNI_HUB_AL_PID 0xA101 +#define UNI_HUB_SLINF_PID 0xA102 #define UNI_HUB_SLV2_PID 0xA103 +#define UNI_HUB_ALV2_PID 0xA104 #define UNI_HUB_SLV2_V05_PID 0xA105 +#define GAII_USB_PID 0x7373 +#define GAII_Perf_USB_PID 0x7371 /*----------------------------------------------------------------------------*\ | The Uni Hub is controlled by sending control transfers to various wIndex | @@ -61,7 +64,7 @@ void DetectLianLiUniHub() { libusb_device** devices = nullptr; - int ret; + ssize_t ret; ret = libusb_init(NULL); if(ret < 0) @@ -75,7 +78,7 @@ void DetectLianLiUniHub() return; } - int deviceCount = ret; + ssize_t deviceCount = ret; for(int i = 0; i < deviceCount; i++) { @@ -107,7 +110,7 @@ void DetectLianLiUniHub_AL10() { libusb_device** devices = nullptr; - int ret; + ssize_t ret; ret = libusb_init(NULL); if(ret < 0) @@ -121,7 +124,7 @@ void DetectLianLiUniHub_AL10() return; } - int deviceCount = ret; + ssize_t deviceCount = ret; for(int i = 0; i < deviceCount; i++) { @@ -191,28 +194,57 @@ void DetectLianLiUniHubSLV2(hid_device_info* info, const std::string& name) } } /* DetectLianLiUniHubSLV2() */ -void DetectStrimerControllers(hid_device_info* info, const std::string& name) +void DetectLianLiUniHubSLInfinity(hid_device_info* info, const std::string& name) { hid_device* dev = hid_open_path(info->path); if(dev) { - StrimerLConnectController* controller = new StrimerLConnectController(dev, info->path); - RGBController_StrimerLConnect* rgb_controller = new RGBController_StrimerLConnect(controller); - rgb_controller->name = name; + LianLiUniHubSLInfinityController* controller = new LianLiUniHubSLInfinityController(dev, info->path, name); + + RGBController_LianLiUniHubSLInfinity* rgb_controller = new RGBController_LianLiUniHubSLInfinity(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} /* DetectLianLiUniHubSLInfinity() */ + +void DetectLianLiStrimerControllers(hid_device_info* info, const std::string& /*name*/) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + LianLiStrimerLConnectController* controller = new LianLiStrimerLConnectController(dev, info->path); + RGBController_LianLiStrimerLConnect* rgb_controller = new RGBController_LianLiStrimerLConnect(controller); ResourceManager::get()->RegisterRGBController(rgb_controller); } } -REGISTER_DETECTOR("Lian Li Uni Hub", DetectLianLiUniHub); -REGISTER_HID_DETECTOR_IPU("Lian Li Uni Hub - AL", DetectLianLiUniHubAL, ENE_USB_VID, UNI_HUB_AL_PID, 0x01, 0xFF72, 0xA1); -REGISTER_HID_DETECTOR_IPU("Lian Li Uni Hub - SL V2", DetectLianLiUniHubSLV2, ENE_USB_VID, UNI_HUB_SLV2_PID, 0x01, 0xFF72, 0xA1); -REGISTER_HID_DETECTOR_IPU("Lian Li Uni Hub - SL V2 v0.5", DetectLianLiUniHubSLV2, ENE_USB_VID, UNI_HUB_SLV2_V05_PID, 0x01, 0xFF72, 0xA1); +void DetectLianLiGAIITrinity(hid_device_info* info, const std::string& /*name*/) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + LianLiGAIITrinityController* controller = new LianLiGAIITrinityController(dev, info->path); + RGBController_LianLiGAIITrinity* rgb_controller = new RGBController_LianLiGAIITrinity(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_DETECTOR("Lian Li Uni Hub", DetectLianLiUniHub); +REGISTER_HID_DETECTOR_IPU("Lian Li Uni Hub - AL", DetectLianLiUniHubAL, ENE_USB_VID, UNI_HUB_AL_PID, 0x01, 0xFF72, 0xA1); +REGISTER_HID_DETECTOR_IPU("Lian Li Uni Hub - SL V2", DetectLianLiUniHubSLV2, ENE_USB_VID, UNI_HUB_SLV2_PID, 0x01, 0xFF72, 0xA1); +REGISTER_HID_DETECTOR_IPU("Lian Li Uni Hub - AL V2", DetectLianLiUniHubSLV2, ENE_USB_VID, UNI_HUB_ALV2_PID, 0x01, 0xFF72, 0xA1); +REGISTER_HID_DETECTOR_IPU("Lian Li Uni Hub - SL V2 v0.5", DetectLianLiUniHubSLV2, ENE_USB_VID, UNI_HUB_SLV2_V05_PID, 0x01, 0xFF72, 0xA1); +REGISTER_HID_DETECTOR_IPU("Lian Li Uni Hub - SL Infinity", DetectLianLiUniHubSLInfinity, ENE_USB_VID, UNI_HUB_SLINF_PID, 0x01, 0xFF72, 0xA1); /*---------------------------------------------------------------------------------------------------------*\ | Entries for dynamic UDEV rules | | | | DUMMY_DEVICE_DETECTOR("Lian Li Uni Hub", DetectLianLiUniHub, 0x0CF2, 0x7750 ) | \*---------------------------------------------------------------------------------------------------------*/ -REGISTER_HID_DETECTOR_IPU("Strimer L Connect", DetectStrimerControllers, ENE_USB_VID, STRIMER_L_CONNECT_PID, 1, 0xFF72, 0xA1); +REGISTER_HID_DETECTOR_IPU("Lian Li Strimer L Connect", DetectLianLiStrimerControllers, ENE_USB_VID, STRIMER_L_CONNECT_PID, 1, 0xFF72, 0xA1); +REGISTER_HID_DETECTOR_I("Lian Li GA II Trinity", DetectLianLiGAIITrinity, NUVOTON_USB_VID, GAII_USB_PID, 0x02); +REGISTER_HID_DETECTOR_I("Lian Li GA II Trinity Performance", DetectLianLiGAIITrinity, NUVOTON_USB_VID, GAII_Perf_USB_PID, 0x02); diff --git a/Controllers/LianLiController/LianLiGAIITrinityController/LianLiGAIITrinityController.cpp b/Controllers/LianLiController/LianLiGAIITrinityController/LianLiGAIITrinityController.cpp new file mode 100644 index 00000000..6151bc8d --- /dev/null +++ b/Controllers/LianLiController/LianLiGAIITrinityController/LianLiGAIITrinityController.cpp @@ -0,0 +1,306 @@ +/*---------------------------------------------------------*\ +| LianLiGAIITrinityController.cpp | +| | +| Driver for Lian Li GAII Trinity | +| | +| Michael Losert 27 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include +#include "LianLiGAIITrinityController.h" +#include "StringUtils.h" + +LianLiGAIITrinityController::LianLiGAIITrinityController(hid_device* dev_handle, char* path) +{ + dev = dev_handle; + location = path; +} + +LianLiGAIITrinityController::~LianLiGAIITrinityController() +{ + if(dev) + { + hid_close(dev); + } +} + +std::string LianLiGAIITrinityController::GetLocation() +{ + return("HID: " + location); +} + +LianLiGAIITrinityController::GAII_Info LianLiGAIITrinityController::GetControllerInfo() +{ + GAII_Info controllerInfo; + + // get serial number + const uint8_t sz = 255; + wchar_t tmp[sz]; + + hid_get_serial_number_string(dev, tmp, sz); + controllerInfo.serial = StringUtils::wstring_to_string(tmp); + + // get firmware version + unsigned char data[64] = ""; + data[0x00] = 0x01; + data[GAII_ByteAddress::BA_PACKET_TYPE] = GAII_PacketType::PT_FIRMWARE_INFO; + hid_write(dev, data, sizeof(data)); + memset(data, 0, sizeof(data)); + hid_read(dev, data, sizeof(data)); + data[sizeof(data) - 1] = 0; + std::string response(reinterpret_cast(&data[0x06])); + memset(data, 0, sizeof(data)); + hid_read(dev, data, sizeof(data)); + data[sizeof(data) - 1] = 0; + response += " (" + std::string(reinterpret_cast(&data[0x06])) + ")"; + std::replace( response.begin(), response.end(), ',', ' '); + controllerInfo.version = response.substr(0, 100); + + return controllerInfo; +} + +unsigned char* LianLiGAIITrinityController::GetRGBControlPacketTemplate() +{ + static unsigned char usb_buf[64]; + memset(usb_buf, 0, sizeof(usb_buf)); + + usb_buf[0x00] = 0x01; + usb_buf[GAII_ByteAddress::BA_PACKET_TYPE] = GAII_PacketType::PT_RGB_CONTROL; + usb_buf[0x05] = 0x13; + + return usb_buf; +} + +void LianLiGAIITrinityController::SetRGB(unsigned char* usb_buf, RGBColor* rgb0, RGBColor* rgb1, RGBColor* rgb2, RGBColor* rgb3) +{ + if(rgb0) + { + usb_buf[GAII_ByteAddress::BA_R0] = RGBGetRValue(*rgb0); + usb_buf[GAII_ByteAddress::BA_G0] = RGBGetGValue(*rgb0); + usb_buf[GAII_ByteAddress::BA_B0] = RGBGetBValue(*rgb0); + } + + if(rgb1) + { + usb_buf[GAII_ByteAddress::BA_R1] = RGBGetRValue(*rgb1); + usb_buf[GAII_ByteAddress::BA_G1] = RGBGetGValue(*rgb1); + usb_buf[GAII_ByteAddress::BA_B1] = RGBGetBValue(*rgb1); + } + + if(rgb2) + { + usb_buf[GAII_ByteAddress::BA_R2] = RGBGetRValue(*rgb2); + usb_buf[GAII_ByteAddress::BA_G2] = RGBGetGValue(*rgb2); + usb_buf[GAII_ByteAddress::BA_B2] = RGBGetBValue(*rgb2); + } + + if(rgb3) + { + usb_buf[GAII_ByteAddress::BA_R3] = RGBGetRValue(*rgb3); + usb_buf[GAII_ByteAddress::BA_G3] = RGBGetGValue(*rgb3); + usb_buf[GAII_ByteAddress::BA_B3] = RGBGetBValue(*rgb3); + } +} + +void LianLiGAIITrinityController::SetMode_Rainbow(GAII_Brightness brightness, GAII_Speed speed, GAII_Direction direction) +{ + unsigned char *usb_buf = GetRGBControlPacketTemplate(); + + usb_buf[GAII_ByteAddress::BA_MODE] = GAII_Modes::M_RAINBOW; + usb_buf[GAII_ByteAddress::BA_RING] = GAII_Ring::R_BOTH; + usb_buf[GAII_ByteAddress::BA_BRIGHTNESS] = brightness; + usb_buf[GAII_ByteAddress::BA_SPEED] = speed; + usb_buf[GAII_ByteAddress::BA_DIRECTION] = direction; + + hid_write(dev, usb_buf, 64); +} + +void LianLiGAIITrinityController::SetMode_RainbowMorph(GAII_Brightness brightness, GAII_Speed speed) +{ + unsigned char *usb_buf = GetRGBControlPacketTemplate(); + + usb_buf[GAII_ByteAddress::BA_MODE] = GAII_Modes::M_RAINBOW_MORPH; + usb_buf[GAII_ByteAddress::BA_RING] = GAII_Ring::R_BOTH; + usb_buf[GAII_ByteAddress::BA_BRIGHTNESS] = brightness; + usb_buf[GAII_ByteAddress::BA_SPEED] = speed; + + hid_write(dev, usb_buf, 64); +} + +void LianLiGAIITrinityController::SetMode_StaticColor(GAII_Brightness brightness, RGBColor rgb0, RGBColor rgb1) +{ + unsigned char *usb_buf = GetRGBControlPacketTemplate(); + + usb_buf[GAII_ByteAddress::BA_MODE] = GAII_Modes::M_STATIC_COLOR; + usb_buf[GAII_ByteAddress::BA_RING] = GAII_Ring::R_BOTH; + usb_buf[GAII_ByteAddress::BA_BRIGHTNESS] = brightness; + SetRGB(usb_buf, rgb0, rgb1); + + hid_write(dev, usb_buf, 64); +} + +void LianLiGAIITrinityController::SetMode_BreathingColor(GAII_Brightness brightness, GAII_Speed speed, RGBColor rgb0, RGBColor rgb1) +{ + unsigned char *usb_buf = GetRGBControlPacketTemplate(); + + usb_buf[GAII_ByteAddress::BA_MODE] = GAII_Modes::M_BREATHING_COLOR; + usb_buf[GAII_ByteAddress::BA_RING] = GAII_Ring::R_BOTH; + usb_buf[GAII_ByteAddress::BA_BRIGHTNESS] = brightness; + usb_buf[GAII_ByteAddress::BA_SPEED] = speed; + SetRGB(usb_buf, rgb0, rgb1); + + hid_write(dev, usb_buf, 64); +} + +void LianLiGAIITrinityController::SetMode_Runway(GAII_Brightness brightness, GAII_Speed speed, RGBColor rgb0, RGBColor rgb1) +{ + unsigned char *usb_buf = GetRGBControlPacketTemplate(); + + usb_buf[GAII_ByteAddress::BA_MODE] = GAII_Modes::M_RUNWAY; + usb_buf[GAII_ByteAddress::BA_RING] = GAII_Ring::R_BOTH; + usb_buf[GAII_ByteAddress::BA_BRIGHTNESS] = brightness; + usb_buf[GAII_ByteAddress::BA_SPEED] = speed; + SetRGB(usb_buf, rgb0, rgb1); + + hid_write(dev, usb_buf, 64); +} + +void LianLiGAIITrinityController::SetMode_Meteor(GAII_Brightness brightness, GAII_Speed speed, GAII_Direction direction, RGBColor rgb0, RGBColor rgb1, RGBColor rgb2, RGBColor rgb3) +{ + unsigned char *usb_buf = GetRGBControlPacketTemplate(); + + usb_buf[GAII_ByteAddress::BA_MODE] = GAII_Modes::M_METEOR; + usb_buf[GAII_ByteAddress::BA_RING] = GAII_Ring::R_BOTH; + usb_buf[GAII_ByteAddress::BA_BRIGHTNESS] = brightness; + usb_buf[GAII_ByteAddress::BA_SPEED] = speed; + usb_buf[GAII_ByteAddress::BA_DIRECTION] = direction; + SetRGB(usb_buf, rgb0, rgb1, rgb2, rgb3); + + hid_write(dev, usb_buf, 64); +} + +void LianLiGAIITrinityController::SetMode_Vortex(GAII_Brightness brightness, GAII_Speed speed, GAII_Direction direction, RGBColor rgb0, RGBColor rgb1, RGBColor rgb2, RGBColor rgb3) +{ + unsigned char *usb_buf = GetRGBControlPacketTemplate(); + + usb_buf[GAII_ByteAddress::BA_MODE] = GAII_Modes::M_VORTEX; + usb_buf[GAII_ByteAddress::BA_RING] = GAII_Ring::R_BOTH; + usb_buf[GAII_ByteAddress::BA_BRIGHTNESS] = brightness; + usb_buf[GAII_ByteAddress::BA_SPEED] = speed; + usb_buf[GAII_ByteAddress::BA_DIRECTION] = direction; + SetRGB(usb_buf, rgb0, rgb1, rgb2, rgb3); + + hid_write(dev, usb_buf, 64); +} + +void LianLiGAIITrinityController::SetMode_CrossingOver(GAII_Brightness brightness, GAII_Speed speed, GAII_Direction direction, RGBColor rgb0, RGBColor rgb1, RGBColor rgb2, RGBColor rgb3) +{ + unsigned char *usb_buf = GetRGBControlPacketTemplate(); + + usb_buf[GAII_ByteAddress::BA_MODE] = GAII_Modes::M_CROSSING_OVER; + usb_buf[GAII_ByteAddress::BA_RING] = GAII_Ring::R_BOTH; + usb_buf[GAII_ByteAddress::BA_BRIGHTNESS] = brightness; + usb_buf[GAII_ByteAddress::BA_SPEED] = speed; + usb_buf[GAII_ByteAddress::BA_DIRECTION] = direction; + SetRGB(usb_buf, rgb0, rgb1, rgb2, rgb3); + + hid_write(dev, usb_buf, 64); +} + +void LianLiGAIITrinityController::SetMode_TaiChi(GAII_Brightness brightness, GAII_Speed speed, GAII_Direction direction, RGBColor rgb0, RGBColor rgb1) +{ + unsigned char *usb_buf = GetRGBControlPacketTemplate(); + + usb_buf[GAII_ByteAddress::BA_MODE] = GAII_Modes::M_TAI_CHI; + usb_buf[GAII_ByteAddress::BA_RING] = GAII_Ring::R_BOTH; + usb_buf[GAII_ByteAddress::BA_BRIGHTNESS] = brightness; + usb_buf[GAII_ByteAddress::BA_SPEED] = speed; + usb_buf[GAII_ByteAddress::BA_DIRECTION] = direction; + SetRGB(usb_buf, rgb0, rgb1); + + hid_write(dev, usb_buf, 64); +} + +void LianLiGAIITrinityController::SetMode_ColorfulStarryNight(GAII_Brightness brightness, GAII_Speed speed) +{ + unsigned char *usb_buf = GetRGBControlPacketTemplate(); + + usb_buf[GAII_ByteAddress::BA_MODE] = GAII_Modes::M_COLORFUL_STARRY_NIGHT; + usb_buf[GAII_ByteAddress::BA_RING] = GAII_Ring::R_BOTH; + usb_buf[GAII_ByteAddress::BA_BRIGHTNESS] = brightness; + usb_buf[GAII_ByteAddress::BA_SPEED] = speed; + + hid_write(dev, usb_buf, 64); +} + +void LianLiGAIITrinityController::SetMode_StaticStarryNight(GAII_Brightness brightness, GAII_Speed speed, RGBColor rgb0) +{ + unsigned char *usb_buf = GetRGBControlPacketTemplate(); + + usb_buf[GAII_ByteAddress::BA_MODE] = GAII_Modes::M_STATIC_STARRY_NIGHT; + usb_buf[GAII_ByteAddress::BA_RING] = GAII_Ring::R_BOTH; + usb_buf[GAII_ByteAddress::BA_BRIGHTNESS] = brightness; + usb_buf[GAII_ByteAddress::BA_SPEED] = speed; + SetRGB(usb_buf, rgb0); + + hid_write(dev, usb_buf, 64); +} + +void LianLiGAIITrinityController::SetMode_Voice(GAII_Brightness brightness, GAII_Speed speed, RGBColor rgb0, RGBColor rgb1) +{ + unsigned char *usb_buf = GetRGBControlPacketTemplate(); + + usb_buf[GAII_ByteAddress::BA_MODE] = GAII_Modes::M_VOICE; + usb_buf[GAII_ByteAddress::BA_RING] = GAII_Ring::R_BOTH; + usb_buf[GAII_ByteAddress::BA_BRIGHTNESS] = brightness; + usb_buf[GAII_ByteAddress::BA_SPEED] = speed; + SetRGB(usb_buf, rgb0, rgb1); + + hid_write(dev, usb_buf, 64); +} + +void LianLiGAIITrinityController::SetMode_BigBang(GAII_Brightness brightness, GAII_Speed speed, RGBColor rgb0, RGBColor rgb1, RGBColor rgb2, RGBColor rgb3) +{ + unsigned char *usb_buf = GetRGBControlPacketTemplate(); + + usb_buf[GAII_ByteAddress::BA_MODE] = GAII_Modes::M_BIG_BANG; + usb_buf[GAII_ByteAddress::BA_RING] = GAII_Ring::R_BOTH; + usb_buf[GAII_ByteAddress::BA_BRIGHTNESS] = brightness; + usb_buf[GAII_ByteAddress::BA_SPEED] = speed; + SetRGB(usb_buf, rgb0, rgb1, rgb2, rgb3); + + hid_write(dev, usb_buf, 64); +} + +void LianLiGAIITrinityController::SetMode_Pump(GAII_Brightness brightness, GAII_Speed speed, GAII_Direction direction, RGBColor rgb0, RGBColor rgb1) +{ + unsigned char *usb_buf = GetRGBControlPacketTemplate(); + + usb_buf[GAII_ByteAddress::BA_MODE] = GAII_Modes::M_PUMP; + usb_buf[GAII_ByteAddress::BA_RING] = GAII_Ring::R_BOTH; + usb_buf[GAII_ByteAddress::BA_BRIGHTNESS] = brightness; + usb_buf[GAII_ByteAddress::BA_SPEED] = speed; + usb_buf[GAII_ByteAddress::BA_DIRECTION] = direction; + SetRGB(usb_buf, rgb0, rgb1); + + hid_write(dev, usb_buf, 64); +} + +void LianLiGAIITrinityController::SetMode_ColorsMorph(GAII_Brightness brightness, GAII_Speed speed, GAII_Direction direction) +{ + unsigned char *usb_buf = GetRGBControlPacketTemplate(); + + usb_buf[GAII_ByteAddress::BA_MODE] = GAII_Modes::M_COLORS_MORPH; + usb_buf[GAII_ByteAddress::BA_RING] = GAII_Ring::R_BOTH; + usb_buf[GAII_ByteAddress::BA_BRIGHTNESS] = brightness; + usb_buf[GAII_ByteAddress::BA_SPEED] = speed; + usb_buf[GAII_ByteAddress::BA_DIRECTION] = direction; + + hid_write(dev, usb_buf, 64); +} diff --git a/Controllers/LianLiController/LianLiGAIITrinityController/LianLiGAIITrinityController.h b/Controllers/LianLiController/LianLiGAIITrinityController/LianLiGAIITrinityController.h new file mode 100644 index 00000000..3ab8db53 --- /dev/null +++ b/Controllers/LianLiController/LianLiGAIITrinityController/LianLiGAIITrinityController.h @@ -0,0 +1,147 @@ +/*---------------------------------------------------------*\ +| LianLiGAIITrinityController.h | +| | +| Driver for Lian Li GAII Trinity | +| | +| Michael Losert 27 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" + +/*----------------------------------------------------------------------------*\ +| Definitions related to LED configuration. | +\*----------------------------------------------------------------------------*/ + +class LianLiGAIITrinityController +{ +public: + struct GAII_Info + { + std::string serial; + std::string version; + }; + + enum GAII_PacketType : unsigned char + { + PT_RGB_CONTROL = 0x83, + PT_FIRMWARE_INFO = 0x86 + }; + + enum GAII_Modes : unsigned char + { + M_RAINBOW = 0x01, + M_RAINBOW_MORPH, + M_STATIC_COLOR, + M_BREATHING_COLOR, + M_RUNWAY, + M_METEOR, + M_VORTEX, + M_CROSSING_OVER, + M_TAI_CHI, + M_COLORFUL_STARRY_NIGHT, + M_STATIC_STARRY_NIGHT, + M_VOICE, + M_BIG_BANG, + M_PUMP, + M_COLORS_MORPH, + /* M_BOUNCE, */ // TODO: requires zone-specific modes + }; + + enum GAII_Ring : unsigned char + { + R_INNER, + R_OUTER, + R_BOTH, + }; + + enum GAII_Brightness : unsigned char + { + B_OFF, + B_25, + B_50, + B_75, + B_100, + }; + + enum GAII_Speed : unsigned char + { + S_VERY_SLOW, + S_SLOW, + S_MODERATE, + S_FAST, + S_VERY_FAST, + }; + + enum GAII_Direction : unsigned char + { + D_RIGHT, + D_LEFT + }; + + enum GAII_ByteAddress : unsigned char + { + BA_PACKET_TYPE = 0x01, + + BA_RING = 0x06, + BA_MODE, + BA_BRIGHTNESS, + BA_SPEED, + + BA_R0 = 0x0A, + BA_G0, + BA_B0, + BA_R1, + BA_G1, + BA_B1, + BA_R2, + BA_G2, + BA_B2, + BA_R3, + BA_G3, + BA_B3, + + BA_DIRECTION = 0x16, + }; + + LianLiGAIITrinityController(hid_device* dev_handle, char* path); + ~LianLiGAIITrinityController(); + + std::string GetLocation(); + + GAII_Info GetControllerInfo(); + + void SetMode_Rainbow(GAII_Brightness brightness, GAII_Speed speed, GAII_Direction direction); + void SetMode_RainbowMorph(GAII_Brightness brightness, GAII_Speed speed); + void SetMode_StaticColor(GAII_Brightness brightness, RGBColor rgb0, RGBColor rgb1); + void SetMode_BreathingColor(GAII_Brightness brightness, GAII_Speed speed, RGBColor rgb0, RGBColor rgb1); + void SetMode_Runway(GAII_Brightness brightness, GAII_Speed speed, RGBColor rgb0, RGBColor rgb1); + void SetMode_Meteor(GAII_Brightness brightness, GAII_Speed speed, GAII_Direction direction, RGBColor rgb0, RGBColor rgb1, RGBColor rgb2, RGBColor rgb3); + void SetMode_Vortex(GAII_Brightness brightness, GAII_Speed speed, GAII_Direction direction, RGBColor rgb0, RGBColor rgb1, RGBColor rgb2, RGBColor rgb3); + void SetMode_CrossingOver(GAII_Brightness brightness, GAII_Speed speed, GAII_Direction direction, RGBColor rgb0, RGBColor rgb1, RGBColor rgb2, RGBColor rgb3); + void SetMode_TaiChi(GAII_Brightness brightness, GAII_Speed speed, GAII_Direction direction, RGBColor rgb0, RGBColor rgb1); + void SetMode_ColorfulStarryNight(GAII_Brightness brightness, GAII_Speed speed); + void SetMode_StaticStarryNight(GAII_Brightness brightness, GAII_Speed speed, RGBColor rgb0); + void SetMode_Voice(GAII_Brightness brightness, GAII_Speed speed, RGBColor rgb0, RGBColor rgb1); + void SetMode_BigBang(GAII_Brightness brightness, GAII_Speed speed, RGBColor rgb0, RGBColor rgb1, RGBColor rgb2, RGBColor rgb3); + void SetMode_Pump(GAII_Brightness brightness, GAII_Speed speed, GAII_Direction direction, RGBColor rgb0, RGBColor rgb1); + void SetMode_ColorsMorph(GAII_Brightness brightness, GAII_Speed speed, GAII_Direction direction); + +private: + std::string location; + unsigned char* GetRGBControlPacketTemplate(); + void SetRGB(unsigned char* usb_buf, RGBColor rgb0) { SetRGB(usb_buf, &rgb0, nullptr, nullptr, nullptr); }; + void SetRGB(unsigned char* usb_buf, RGBColor rgb0, RGBColor rgb1) { SetRGB(usb_buf, &rgb0, &rgb1, nullptr, nullptr); }; + void SetRGB(unsigned char* usb_buf, RGBColor rgb0, RGBColor rgb1, RGBColor rgb2) { SetRGB(usb_buf, &rgb0, &rgb1, &rgb2, nullptr); }; + void SetRGB(unsigned char* usb_buf, RGBColor rgb0, RGBColor rgb1, RGBColor rgb2, RGBColor rgb3) { SetRGB(usb_buf, &rgb0, &rgb1, &rgb2, &rgb3); }; + void SetRGB(unsigned char* usb_buf, RGBColor* rgb0, RGBColor* rgb1, RGBColor* rgb2, RGBColor* rgb3); + + hid_device* dev; +}; diff --git a/Controllers/LianLiController/LianLiGAIITrinityController/RGBController_LianLiGAIITrinity.cpp b/Controllers/LianLiController/LianLiGAIITrinityController/RGBController_LianLiGAIITrinity.cpp new file mode 100644 index 00000000..e2519a3d --- /dev/null +++ b/Controllers/LianLiController/LianLiGAIITrinityController/RGBController_LianLiGAIITrinity.cpp @@ -0,0 +1,418 @@ +/*---------------------------------------------------------*\ +| RGBController_LianLiGAIITrinity.cpp | +| | +| RGBController for Lian Li GAII Trinity | +| | +| Michael Losert 27 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RGBController_LianLiGAIITrinity.h" + +/**------------------------------------------------------------------*\ + @name Lian Li GAII Trinity + @type USB + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectLianLiGAIITrinity + @comment +\*-------------------------------------------------------------------*/ + +RGBController_LianLiGAIITrinity::RGBController_LianLiGAIITrinity(LianLiGAIITrinityController* controller_ptr) +{ + controller = controller_ptr; + + name = "Lian Li GAII Trinity"; + vendor = "Lian Li"; + type = DEVICE_TYPE_COOLER; + description = "Lian Li Galahad II Trinity AIO"; + location = controller->GetLocation(); + + LianLiGAIITrinityController::GAII_Info controllerInfo = controller->GetControllerInfo(); + version = controllerInfo.version; + serial = controllerInfo.serial; + + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = LianLiGAIITrinityController::GAII_Modes::M_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + Rainbow.color_mode = MODE_COLORS_RANDOM; + Rainbow.brightness_min = LianLiGAIITrinityController::GAII_Brightness::B_OFF; + Rainbow.brightness_max = LianLiGAIITrinityController::GAII_Brightness::B_100; + Rainbow.brightness = LianLiGAIITrinityController::GAII_Brightness::B_75; + Rainbow.speed_min = LianLiGAIITrinityController::GAII_Speed::S_VERY_SLOW; + Rainbow.speed_max = LianLiGAIITrinityController::GAII_Speed::S_VERY_FAST; + Rainbow.speed = LianLiGAIITrinityController::GAII_Speed::S_FAST; + Rainbow.direction = MODE_DIRECTION_RIGHT; + modes.push_back(Rainbow); + + mode RainbowMorph; + RainbowMorph.name = "Rainbow Morph"; + RainbowMorph.value = LianLiGAIITrinityController::GAII_Modes::M_RAINBOW_MORPH; + RainbowMorph.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + RainbowMorph.color_mode = MODE_COLORS_RANDOM; + RainbowMorph.brightness_min = LianLiGAIITrinityController::GAII_Brightness::B_OFF; + RainbowMorph.brightness_max = LianLiGAIITrinityController::GAII_Brightness::B_100; + RainbowMorph.brightness = LianLiGAIITrinityController::GAII_Brightness::B_75; + RainbowMorph.speed_min = LianLiGAIITrinityController::GAII_Speed::S_VERY_SLOW; + RainbowMorph.speed_max = LianLiGAIITrinityController::GAII_Speed::S_VERY_FAST; + RainbowMorph.speed = LianLiGAIITrinityController::GAII_Speed::S_SLOW; + modes.push_back(RainbowMorph); + + mode Direct; + Direct.name = "Direct"; + Direct.value = LianLiGAIITrinityController::GAII_Modes::M_STATIC_COLOR; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = LianLiGAIITrinityController::GAII_Brightness::B_OFF; + Direct.brightness_max = LianLiGAIITrinityController::GAII_Brightness::B_100; + Direct.brightness = LianLiGAIITrinityController::GAII_Brightness::B_50; + modes.push_back(Direct); + + mode BreathingColor; + BreathingColor.name = "Breathing Color"; + BreathingColor.value = LianLiGAIITrinityController::GAII_Modes::M_BREATHING_COLOR; + BreathingColor.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + BreathingColor.color_mode = MODE_COLORS_MODE_SPECIFIC; + BreathingColor.colors.resize(2); + BreathingColor.colors[0] = ToRGBColor(255, 255, 255); + BreathingColor.colors[1] = ToRGBColor(255, 0, 0); + BreathingColor.brightness_min = LianLiGAIITrinityController::GAII_Brightness::B_OFF; + BreathingColor.brightness_max = LianLiGAIITrinityController::GAII_Brightness::B_100; + BreathingColor.brightness = LianLiGAIITrinityController::GAII_Brightness::B_100; + BreathingColor.speed_min = LianLiGAIITrinityController::GAII_Speed::S_VERY_SLOW; + BreathingColor.speed_max = LianLiGAIITrinityController::GAII_Speed::S_VERY_FAST; + BreathingColor.speed = LianLiGAIITrinityController::GAII_Speed::S_MODERATE; + modes.push_back(BreathingColor); + + mode Runway; + Runway.name = "Runway"; + Runway.value = LianLiGAIITrinityController::GAII_Modes::M_RUNWAY; + Runway.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Runway.color_mode = MODE_COLORS_MODE_SPECIFIC; + Runway.colors.resize(2); + Runway.colors[0] = ToRGBColor(0, 0, 0); + Runway.colors[1] = ToRGBColor(255, 255, 255); + Runway.brightness_min = LianLiGAIITrinityController::GAII_Brightness::B_OFF; + Runway.brightness_max = LianLiGAIITrinityController::GAII_Brightness::B_100; + Runway.brightness = LianLiGAIITrinityController::GAII_Brightness::B_50; + Runway.speed_min = LianLiGAIITrinityController::GAII_Speed::S_VERY_SLOW; + Runway.speed_max = LianLiGAIITrinityController::GAII_Speed::S_VERY_FAST; + Runway.speed = LianLiGAIITrinityController::GAII_Speed::S_FAST; + modes.push_back(Runway); + + mode Meteor; + Meteor.name = "Meteor"; + Meteor.value = LianLiGAIITrinityController::GAII_Modes::M_METEOR; + Meteor.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + Meteor.color_mode = MODE_COLORS_MODE_SPECIFIC; + Meteor.colors.resize(4); + Meteor.colors[0] = ToRGBColor(50, 50, 50); + Meteor.colors[1] = ToRGBColor(100, 100, 100); + Meteor.colors[2] = ToRGBColor(180, 180, 180); + Meteor.colors[3] = ToRGBColor(255, 0, 0); + Meteor.brightness_min = LianLiGAIITrinityController::GAII_Brightness::B_OFF; + Meteor.brightness_max = LianLiGAIITrinityController::GAII_Brightness::B_100; + Meteor.brightness = LianLiGAIITrinityController::GAII_Brightness::B_100; + Meteor.speed_min = LianLiGAIITrinityController::GAII_Speed::S_VERY_SLOW; + Meteor.speed_max = LianLiGAIITrinityController::GAII_Speed::S_VERY_FAST; + Meteor.speed = LianLiGAIITrinityController::GAII_Speed::S_VERY_FAST; + Meteor.direction = MODE_DIRECTION_RIGHT; + modes.push_back(Meteor); + + mode Vortex; + Vortex.name = "Vortex"; + Vortex.value = LianLiGAIITrinityController::GAII_Modes::M_VORTEX; + Vortex.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + Vortex.color_mode = MODE_COLORS_MODE_SPECIFIC; + Vortex.colors.resize(4); + Vortex.colors[0] = ToRGBColor(100, 100, 100); + Vortex.colors[1] = ToRGBColor(0, 100, 0); + Vortex.colors[2] = ToRGBColor(255, 255, 255); + Vortex.colors[3] = ToRGBColor(255, 0, 0); + Vortex.brightness_min = LianLiGAIITrinityController::GAII_Brightness::B_OFF; + Vortex.brightness_max = LianLiGAIITrinityController::GAII_Brightness::B_100; + Vortex.brightness = LianLiGAIITrinityController::GAII_Brightness::B_75; + Vortex.speed_min = LianLiGAIITrinityController::GAII_Speed::S_VERY_SLOW; + Vortex.speed_max = LianLiGAIITrinityController::GAII_Speed::S_VERY_FAST; + Vortex.speed = LianLiGAIITrinityController::GAII_Speed::S_VERY_FAST; + Vortex.direction = MODE_DIRECTION_RIGHT; + modes.push_back(Vortex); + + mode CrossingOver; + CrossingOver.name = "Crossing Over"; + CrossingOver.value = LianLiGAIITrinityController::GAII_Modes::M_CROSSING_OVER; + CrossingOver.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + CrossingOver.color_mode = MODE_COLORS_MODE_SPECIFIC; + CrossingOver.colors.resize(4); + CrossingOver.colors[0] = ToRGBColor(255, 0, 0); + CrossingOver.colors[1] = ToRGBColor(0, 255, 0); + CrossingOver.colors[2] = ToRGBColor(0, 0, 255); + CrossingOver.colors[3] = ToRGBColor(255, 255, 0); + CrossingOver.brightness_min = LianLiGAIITrinityController::GAII_Brightness::B_OFF; + CrossingOver.brightness_max = LianLiGAIITrinityController::GAII_Brightness::B_100; + CrossingOver.brightness = LianLiGAIITrinityController::GAII_Brightness::B_75; + CrossingOver.speed_min = LianLiGAIITrinityController::GAII_Speed::S_VERY_SLOW; + CrossingOver.speed_max = LianLiGAIITrinityController::GAII_Speed::S_VERY_FAST; + CrossingOver.speed = LianLiGAIITrinityController::GAII_Speed::S_FAST; + CrossingOver.direction = MODE_DIRECTION_RIGHT; + modes.push_back(CrossingOver); + + mode TaiChi; + TaiChi.name = "Tai Chi"; + TaiChi.value = LianLiGAIITrinityController::GAII_Modes::M_TAI_CHI; + TaiChi.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + TaiChi.color_mode = MODE_COLORS_MODE_SPECIFIC; + TaiChi.colors.resize(2); + TaiChi.colors[0] = ToRGBColor(255, 0, 0); + TaiChi.colors[1] = ToRGBColor(0, 255, 0); + TaiChi.brightness_min = LianLiGAIITrinityController::GAII_Brightness::B_OFF; + TaiChi.brightness_max = LianLiGAIITrinityController::GAII_Brightness::B_100; + TaiChi.brightness = LianLiGAIITrinityController::GAII_Brightness::B_75; + TaiChi.speed_min = LianLiGAIITrinityController::GAII_Speed::S_VERY_SLOW; + TaiChi.speed_max = LianLiGAIITrinityController::GAII_Speed::S_VERY_FAST; + TaiChi.speed = LianLiGAIITrinityController::GAII_Speed::S_MODERATE; + TaiChi.direction = MODE_DIRECTION_RIGHT; + modes.push_back(TaiChi); + + mode ColorfulStarryNight; + ColorfulStarryNight.name = "Colorful Starry Night"; + ColorfulStarryNight.value = LianLiGAIITrinityController::GAII_Modes::M_COLORFUL_STARRY_NIGHT; + ColorfulStarryNight.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + ColorfulStarryNight.color_mode = MODE_COLORS_RANDOM; + ColorfulStarryNight.brightness_min = LianLiGAIITrinityController::GAII_Brightness::B_OFF; + ColorfulStarryNight.brightness_max = LianLiGAIITrinityController::GAII_Brightness::B_100; + ColorfulStarryNight.brightness = LianLiGAIITrinityController::GAII_Brightness::B_50; + ColorfulStarryNight.speed_min = LianLiGAIITrinityController::GAII_Speed::S_VERY_SLOW; + ColorfulStarryNight.speed_max = LianLiGAIITrinityController::GAII_Speed::S_VERY_FAST; + ColorfulStarryNight.speed = LianLiGAIITrinityController::GAII_Speed::S_SLOW; + modes.push_back(ColorfulStarryNight); + + mode StaticStarryNight; + StaticStarryNight.name = "Static Starry Night"; + StaticStarryNight.value = LianLiGAIITrinityController::GAII_Modes::M_STATIC_STARRY_NIGHT; + StaticStarryNight.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + StaticStarryNight.color_mode = MODE_COLORS_MODE_SPECIFIC; + StaticStarryNight.colors.resize(1); + StaticStarryNight.colors[0] = ToRGBColor(255, 255, 0); + StaticStarryNight.brightness_min = LianLiGAIITrinityController::GAII_Brightness::B_OFF; + StaticStarryNight.brightness_max = LianLiGAIITrinityController::GAII_Brightness::B_100; + StaticStarryNight.brightness = LianLiGAIITrinityController::GAII_Brightness::B_50; + StaticStarryNight.speed_min = LianLiGAIITrinityController::GAII_Speed::S_VERY_SLOW; + StaticStarryNight.speed_max = LianLiGAIITrinityController::GAII_Speed::S_VERY_FAST; + StaticStarryNight.speed = LianLiGAIITrinityController::GAII_Speed::S_VERY_SLOW; + modes.push_back(StaticStarryNight); + + mode Voice; + Voice.name = "Voice"; + Voice.value = LianLiGAIITrinityController::GAII_Modes::M_VOICE; + Voice.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Voice.color_mode = MODE_COLORS_MODE_SPECIFIC; + Voice.colors.resize(2); + Voice.colors[0] = ToRGBColor(255, 255, 255); + Voice.colors[1] = ToRGBColor(130, 130, 130); + Voice.brightness_min = LianLiGAIITrinityController::GAII_Brightness::B_OFF; + Voice.brightness_max = LianLiGAIITrinityController::GAII_Brightness::B_100; + Voice.brightness = LianLiGAIITrinityController::GAII_Brightness::B_100; + Voice.speed_min = LianLiGAIITrinityController::GAII_Speed::S_VERY_SLOW; + Voice.speed_max = LianLiGAIITrinityController::GAII_Speed::S_VERY_FAST; + Voice.speed = LianLiGAIITrinityController::GAII_Speed::S_SLOW; + modes.push_back(Voice); + + + mode BigBang; + BigBang.name = "Big Bang"; + BigBang.value = LianLiGAIITrinityController::GAII_Modes::M_BIG_BANG; + BigBang.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + BigBang.color_mode = MODE_COLORS_MODE_SPECIFIC; + BigBang.colors.resize(4); + BigBang.colors[0] = ToRGBColor(255, 255, 255); + BigBang.colors[1] = ToRGBColor(255, 0, 0); + BigBang.colors[2] = ToRGBColor(255, 255, 255); + BigBang.colors[3] = ToRGBColor(0, 255, 0); + BigBang.brightness_min = LianLiGAIITrinityController::GAII_Brightness::B_OFF; + BigBang.brightness_max = LianLiGAIITrinityController::GAII_Brightness::B_100; + BigBang.brightness = LianLiGAIITrinityController::GAII_Brightness::B_75; + BigBang.speed_min = LianLiGAIITrinityController::GAII_Speed::S_VERY_SLOW; + BigBang.speed_max = LianLiGAIITrinityController::GAII_Speed::S_VERY_FAST; + BigBang.speed = LianLiGAIITrinityController::GAII_Speed::S_FAST; + modes.push_back(BigBang); + + mode Pump; + Pump.name = "Pump"; + Pump.value = LianLiGAIITrinityController::GAII_Modes::M_PUMP; + Pump.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + Pump.color_mode = MODE_COLORS_MODE_SPECIFIC; + Pump.colors.resize(2); + Pump.colors[0] = ToRGBColor(0, 255, 0); + Pump.colors[1] = ToRGBColor(150, 150, 150); + Pump.brightness_min = LianLiGAIITrinityController::GAII_Brightness::B_OFF; + Pump.brightness_max = LianLiGAIITrinityController::GAII_Brightness::B_100; + Pump.brightness = LianLiGAIITrinityController::GAII_Brightness::B_75; + Pump.speed_min = LianLiGAIITrinityController::GAII_Speed::S_VERY_SLOW; + Pump.speed_max = LianLiGAIITrinityController::GAII_Speed::S_VERY_FAST; + Pump.speed = LianLiGAIITrinityController::GAII_Speed::S_FAST; + Pump.direction = MODE_DIRECTION_RIGHT; + modes.push_back(Pump); + + mode ColorsMorph; + ColorsMorph.name = "Colors Morph"; + ColorsMorph.value = LianLiGAIITrinityController::GAII_Modes::M_COLORS_MORPH; + ColorsMorph.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + ColorsMorph.color_mode = MODE_COLORS_RANDOM; + ColorsMorph.brightness_min = LianLiGAIITrinityController::GAII_Brightness::B_OFF; + ColorsMorph.brightness_max = LianLiGAIITrinityController::GAII_Brightness::B_100; + ColorsMorph.brightness = LianLiGAIITrinityController::GAII_Brightness::B_100; + ColorsMorph.speed_min = LianLiGAIITrinityController::GAII_Speed::S_VERY_SLOW; + ColorsMorph.speed_max = LianLiGAIITrinityController::GAII_Speed::S_VERY_FAST; + ColorsMorph.speed = LianLiGAIITrinityController::GAII_Speed::S_MODERATE; + ColorsMorph.direction = MODE_DIRECTION_RIGHT; + modes.push_back(ColorsMorph); + + SetupZones(); +} + +RGBController_LianLiGAIITrinity::~RGBController_LianLiGAIITrinity() +{ + delete controller; +} + +void RGBController_LianLiGAIITrinity::SetupZones() +{ + /*-------------------------------------------------*\ + | Set zones and leds | + \*-------------------------------------------------*/ + + zone gaii_trinity; + gaii_trinity.name = "GAII Trinity"; + gaii_trinity.type = ZONE_TYPE_SINGLE; + gaii_trinity.leds_min = 2; + gaii_trinity.leds_max = 2; + gaii_trinity.leds_count = 2; + gaii_trinity.matrix_map = NULL; + zones.push_back(gaii_trinity); + + led inner_led; + inner_led.name = "Inner Ring LEDs"; + leds.push_back(inner_led); + + led outer_led; + outer_led.name = "Outer Ring LEDs"; + leds.push_back(outer_led); + + SetupColors(); + + // set default color values + zones[0].colors[0] = ToRGBColor(255, 255, 255); + zones[0].colors[1] = ToRGBColor(0, 0, 255); +} + +void RGBController_LianLiGAIITrinity::ResizeZone(int /* zone */, int /* new_size */) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_LianLiGAIITrinity::DeviceUpdateLEDs() +{ + switch(modes[active_mode].value) + { + case LianLiGAIITrinityController::GAII_Modes::M_RAINBOW: + controller->SetMode_Rainbow(static_cast(modes[active_mode].brightness), + static_cast(modes[active_mode].speed), + OpenRGBDirection2GAIIDirection(modes[active_mode].direction)); + break; + case LianLiGAIITrinityController::GAII_Modes::M_RAINBOW_MORPH: + controller->SetMode_RainbowMorph(static_cast(modes[active_mode].brightness), + static_cast(modes[active_mode].speed)); + break; + case LianLiGAIITrinityController::GAII_Modes::M_STATIC_COLOR: + controller->SetMode_StaticColor(static_cast(modes[active_mode].brightness), + zones[0].colors[0], zones[0].colors[1]); + break; + case LianLiGAIITrinityController::GAII_Modes::M_BREATHING_COLOR: + controller->SetMode_BreathingColor(static_cast(modes[active_mode].brightness), + static_cast(modes[active_mode].speed), + modes[active_mode].colors[0], modes[active_mode].colors[1]); + break; + case LianLiGAIITrinityController::GAII_Modes::M_RUNWAY: + controller->SetMode_Runway(static_cast(modes[active_mode].brightness), + static_cast(modes[active_mode].speed), + modes[active_mode].colors[0], modes[active_mode].colors[1]); + break; + case LianLiGAIITrinityController::GAII_Modes::M_METEOR: + controller->SetMode_Meteor(static_cast(modes[active_mode].brightness), + static_cast(modes[active_mode].speed), + OpenRGBDirection2GAIIDirection(modes[active_mode].direction), + modes[active_mode].colors[0], modes[active_mode].colors[1], modes[active_mode].colors[2], modes[active_mode].colors[3]); + break; + case LianLiGAIITrinityController::GAII_Modes::M_VORTEX: + controller->SetMode_Vortex(static_cast(modes[active_mode].brightness), + static_cast(modes[active_mode].speed), + OpenRGBDirection2GAIIDirection(modes[active_mode].direction), + modes[active_mode].colors[0], modes[active_mode].colors[1], modes[active_mode].colors[2], modes[active_mode].colors[3]); + break; + case LianLiGAIITrinityController::GAII_Modes::M_CROSSING_OVER: + controller->SetMode_CrossingOver(static_cast(modes[active_mode].brightness), + static_cast(modes[active_mode].speed), + OpenRGBDirection2GAIIDirection(modes[active_mode].direction), + modes[active_mode].colors[0], modes[active_mode].colors[1], modes[active_mode].colors[2], modes[active_mode].colors[3]); + break; + case LianLiGAIITrinityController::GAII_Modes::M_TAI_CHI: + controller->SetMode_TaiChi(static_cast(modes[active_mode].brightness), + static_cast(modes[active_mode].speed), + OpenRGBDirection2GAIIDirection(modes[active_mode].direction), + modes[active_mode].colors[0], modes[active_mode].colors[1]); + break; + case LianLiGAIITrinityController::GAII_Modes::M_COLORFUL_STARRY_NIGHT: + controller->SetMode_ColorfulStarryNight(static_cast(modes[active_mode].brightness), + static_cast(modes[active_mode].speed)); + break; + case LianLiGAIITrinityController::GAII_Modes::M_STATIC_STARRY_NIGHT: + controller->SetMode_StaticStarryNight(static_cast(modes[active_mode].brightness), + static_cast(modes[active_mode].speed), + modes[active_mode].colors[0]); + break; + case LianLiGAIITrinityController::GAII_Modes::M_VOICE: + controller->SetMode_Voice(static_cast(modes[active_mode].brightness), + static_cast(modes[active_mode].speed), + modes[active_mode].colors[0], modes[active_mode].colors[1]); + break; + case LianLiGAIITrinityController::GAII_Modes::M_BIG_BANG: + controller->SetMode_BigBang(static_cast(modes[active_mode].brightness), + static_cast(modes[active_mode].speed), + modes[active_mode].colors[0], modes[active_mode].colors[1], modes[active_mode].colors[2], modes[active_mode].colors[3]); + break; + case LianLiGAIITrinityController::GAII_Modes::M_PUMP: + controller->SetMode_Pump(static_cast(modes[active_mode].brightness), + static_cast(modes[active_mode].speed), + OpenRGBDirection2GAIIDirection(modes[active_mode].direction), + modes[active_mode].colors[0], modes[active_mode].colors[1]); + break; + case LianLiGAIITrinityController::GAII_Modes::M_COLORS_MORPH: + controller->SetMode_ColorsMorph(static_cast(modes[active_mode].brightness), + static_cast(modes[active_mode].speed), + OpenRGBDirection2GAIIDirection(modes[active_mode].direction)); + break; + } +} + +void RGBController_LianLiGAIITrinity::UpdateZoneLEDs(int /* zone */) +{ + DeviceUpdateLEDs(); +} + +void RGBController_LianLiGAIITrinity::UpdateSingleLED(int /* led */) +{ + DeviceUpdateLEDs(); +} + +void RGBController_LianLiGAIITrinity::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} diff --git a/Controllers/LianLiController/LianLiGAIITrinityController/RGBController_LianLiGAIITrinity.h b/Controllers/LianLiController/LianLiGAIITrinityController/RGBController_LianLiGAIITrinity.h new file mode 100644 index 00000000..b186af6c --- /dev/null +++ b/Controllers/LianLiController/LianLiGAIITrinityController/RGBController_LianLiGAIITrinity.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------*\ +| RGBController_LianLiGAIITrinity.h | +| | +| RGBController for Lian Li GAII Trinity | +| | +| Michael Losert 27 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "LianLiGAIITrinityController.h" +#include "RGBController.h" + +class RGBController_LianLiGAIITrinity : public RGBController +{ +public: + RGBController_LianLiGAIITrinity(LianLiGAIITrinityController* controller_ptr); + ~RGBController_LianLiGAIITrinity(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + LianLiGAIITrinityController::GAII_Direction OpenRGBDirection2GAIIDirection(unsigned int openrgb_direction) + { + if(openrgb_direction == MODE_DIRECTION_LEFT) + return LianLiGAIITrinityController::GAII_Direction::D_LEFT; + + return LianLiGAIITrinityController::GAII_Direction::D_RIGHT; + } + +private: + LianLiGAIITrinityController* controller; +}; diff --git a/Controllers/LianLiController/LianLiStrimerLConnectController/LianLiStrimerLConnectController.cpp b/Controllers/LianLiController/LianLiStrimerLConnectController/LianLiStrimerLConnectController.cpp new file mode 100644 index 00000000..c19b10c2 --- /dev/null +++ b/Controllers/LianLiController/LianLiStrimerLConnectController/LianLiStrimerLConnectController.cpp @@ -0,0 +1,107 @@ +/*---------------------------------------------------------*\ +| LianLiStrimerLConnectController.cpp | +| | +| Driver for Lian Li Strimer L Connect | +| | +| Chris M (Dr_No) 03 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "LianLiStrimerLConnectController.h" +#include "StringUtils.h" + +static uint8_t speed_data[5] = +{ + 0x02, 0x01, 0x00, 0xFE, 0xFF /* Slow to fast */ +}; + +static uint8_t brightness_data[5] = +{ + 0x08, 0x03, 0x02, 0x01, 0x00 /* 0%, 25%, 50%, 75%, 100% */ +}; + +LianLiStrimerLConnectController::LianLiStrimerLConnectController(hid_device* dev_handle, const char* path) +{ + dev = dev_handle; + location = path; + + /*---------------------------------------------------------*\ + | Get device name from HID manufacturer and product strings | + \*---------------------------------------------------------*/ + wchar_t name_string[HID_MAX_STR]; + + hid_get_manufacturer_string(dev, name_string, HID_MAX_STR); + device_name = StringUtils::wstring_to_string(name_string); + + hid_get_product_string(dev, name_string, HID_MAX_STR); + device_name.append(" ").append(StringUtils::wstring_to_string(name_string)); +} + +LianLiStrimerLConnectController::~LianLiStrimerLConnectController() +{ + hid_close(dev); +} + +std::string LianLiStrimerLConnectController::GetDeviceName() +{ + return device_name; +} + +std::string LianLiStrimerLConnectController::GetSerial() +{ + wchar_t serial_string[HID_MAX_STR]; + int ret = hid_get_serial_number_string(dev, serial_string, HID_MAX_STR); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string LianLiStrimerLConnectController::GetLocation() +{ + return("HID: " + location); +} + +void LianLiStrimerLConnectController::SendApply() +{ + uint8_t buffer[STRIMERLCONNECT_PACKET_SIZE] = { STRIMERLCONNECT_REPORT_ID, 0x2C, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00 }; + + hid_write(dev, buffer, STRIMERLCONNECT_PACKET_SIZE); +} + +void LianLiStrimerLConnectController::SetMode(uint8_t mode, uint8_t zone, uint8_t speed, uint8_t brightness, uint8_t direction, bool /*random_colours*/) +{ + uint8_t buffer[STRIMERLCONNECT_PACKET_SIZE] = { STRIMERLCONNECT_REPORT_ID, STRIMERLCONNECT_MODE_COMMAND, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + buffer[STRIMERLCONNECT_COMMAND_BYTE] |= zone; + + buffer[STRIMERLCONNECT_DATA_BYTE] = mode; + buffer[STRIMERLCONNECT_SPEED_BYTE] = speed_data[speed]; + buffer[STRIMERLCONNECT_DIRECTION_BYTE] = (direction == 0) ? 1 : 0; + buffer[STRIMERLCONNECT_BRIGHTNESS_BYTE] = brightness_data[brightness]; + + hid_write(dev, buffer, STRIMERLCONNECT_PACKET_SIZE); +} + +void LianLiStrimerLConnectController::SetLedsDirect(uint8_t zone, RGBColor * led_colours, uint8_t led_count) +{ + uint8_t buffer[STRIMERLCONNECT_PACKET_SIZE] = { STRIMERLCONNECT_REPORT_ID, STRIMERLCONNECT_COLOUR_COMMAND, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + + buffer[STRIMERLCONNECT_COMMAND_BYTE] |= zone; + + for(size_t i = 0; i < led_count; i++) + { + uint8_t offset = (3 * (uint8_t)i) + STRIMERLCONNECT_DATA_BYTE; + + buffer[offset] = RGBGetRValue(led_colours[i]); + buffer[offset + 1] = RGBGetBValue(led_colours[i]); + buffer[offset + 2] = RGBGetGValue(led_colours[i]); + } + + hid_write(dev, buffer, STRIMERLCONNECT_PACKET_SIZE); +} diff --git a/Controllers/LianLiController/LianLiStrimerLConnectController/LianLiStrimerLConnectController.h b/Controllers/LianLiController/LianLiStrimerLConnectController/LianLiStrimerLConnectController.h new file mode 100644 index 00000000..d0dcabfc --- /dev/null +++ b/Controllers/LianLiController/LianLiStrimerLConnectController/LianLiStrimerLConnectController.h @@ -0,0 +1,95 @@ +/*---------------------------------------------------------*\ +| LianLiStrimerLConnectController.h | +| | +| Driver for Lian Li Strimer L Connect | +| | +| Chris M (Dr_No) 03 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "LogManager.h" +#include "RGBController.h" + +#define HID_MAX_STR 255 +#define STRIMERLCONNECT_PACKET_SIZE 255 //Buffer requires a prepended ReportID hence + 1 + +#define STRIMERLCONNECT_BRIGHTNESS_MIN 0 //Brightness indexes not values +#define STRIMERLCONNECT_BRIGHTNESS_MAX 4 +#define STRIMERLCONNECT_STRIP_COUNT 12 + +enum +{ + STRIMERLCONNECT_MODE_OFF = 0x00, //Turn off - All leds off + STRIMERLCONNECT_MODE_DIRECT = 0x01, //Direct Led Control - Independently set LEDs in zone + STRIMERLCONNECT_MODE_BREATHING = 0x02, //Breathing Mode - Fades between fully off and fully on. + STRIMERLCONNECT_MODE_FLASHING = 0x03, //Flashing Mode - Abruptly changing between fully off and fully on. + STRIMERLCONNECT_MODE_RAINBOWMORPH = 0x04, //Rainbow Morph Mode + STRIMERLCONNECT_MODE_RAINBOW = 0x05, //Rainbow Wave Mode - Cycle thru the color spectrum as a wave across all LEDs + STRIMERLCONNECT_MODE_BREATHCYCLE = 0x06, //Spectrum Cycle Mode - Cycles through the color spectrum on all lights on the device + + STRIMERLCONNECT_MODE_SNOOKER = 0x19, //Snooker Mode + STRIMERLCONNECT_MODE_MIXING = 0x1A, //Mixing Mode + STRIMERLCONNECT_MODE_PINGPONG = 0x1B, //Ping Pong Mode + STRIMERLCONNECT_MODE_RUNWAY = 0x1C, //Runway Mode + STRIMERLCONNECT_MODE_PAINTING = 0x1D, //Painting Mode + STRIMERLCONNECT_MODE_TIDE = 0x1E, //Tide Mode + STRIMERLCONNECT_MODE_BLOWUP = 0x1F, //Blow Up Mode + STRIMERLCONNECT_MODE_METEOR = 0x20, //Meteor Mode + + STRIMERLCONNECT_MODE_SHOCKWAVE = 0x21, //Shock Wave Mode + STRIMERLCONNECT_MODE_RIPPLE = 0x22, //Ripple Mode + STRIMERLCONNECT_MODE_VOICE = 0x23, //Voice Mode + STRIMERLCONNECT_MODE_BULLETSTACK = 0x24, //Bullet Stack Mode + STRIMERLCONNECT_MODE_DRIZZLING = 0x25, //Drizzling Mode + STRIMERLCONNECT_MODE_FADEOUT = 0x26, //Fade Out Mode + STRIMERLCONNECT_MODE_COLORTRANSFER = 0x27, //Color Transfer Mode + STRIMERLCONNECT_MODE_CROSSOVER = 0x28, //Cross Over Mode + STRIMERLCONNECT_MODE_TWINKLE = 0x29, //Twinkle Mode + STRIMERLCONNECT_MODE_CONTEST = 0x2A, //Contest Mode + STRIMERLCONNECT_MODE_PARALLEL = 0x2B, //Parallel Mode +}; + +enum +{ + STRIMERLCONNECT_COMMAND_BYTE = 1, + STRIMERLCONNECT_DATA_BYTE = 2, + STRIMERLCONNECT_SPEED_BYTE = 3, + STRIMERLCONNECT_DIRECTION_BYTE = 4, + STRIMERLCONNECT_BRIGHTNESS_BYTE = 5, + + STRIMERLCONNECT_MODE_COMMAND = 0x10, + STRIMERLCONNECT_COLOUR_COMMAND = 0x30, + STRIMERLCONNECT_REPORT_ID = 0xE0, +}; + +enum +{ + STRIMERLCONNECT_SPEED_SLOWEST = 0, + STRIMERLCONNECT_SPEED_NORMAL = 2, + STRIMERLCONNECT_SPEED_FASTEST = 4, +}; + +class LianLiStrimerLConnectController +{ +public: + LianLiStrimerLConnectController(hid_device* dev_handle, const char* path); + ~LianLiStrimerLConnectController(); + + std::string GetDeviceName(); + std::string GetSerial(); + std::string GetLocation(); + + void SendApply(); + void SetMode(uint8_t mode, uint8_t zone, uint8_t speed, uint8_t brightness, uint8_t direction, bool random_colours); + void SetLedsDirect(uint8_t zone, RGBColor *led_colours, uint8_t led_count); +private: + std::string device_name; + std::string location; + hid_device* dev; +}; diff --git a/Controllers/LianLiController/LianLiStrimerLConnectController/RGBController_LianLiStrimerLConnect.cpp b/Controllers/LianLiController/LianLiStrimerLConnectController/RGBController_LianLiStrimerLConnect.cpp new file mode 100644 index 00000000..0c6dc23c --- /dev/null +++ b/Controllers/LianLiController/LianLiStrimerLConnectController/RGBController_LianLiStrimerLConnect.cpp @@ -0,0 +1,336 @@ +/*---------------------------------------------------------*\ +| RGBController_LianLiStrimerLConnect.cpp | +| | +| RGBController for Lian Li Strimer L Connect | +| | +| Chris M (Dr_No) 03 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_LianLiStrimerLConnect.h" + +/**------------------------------------------------------------------*\ + @name Lian Li Strimer L Connect + @category LEDStrip + @type USB + @save :x: + @direct :rotating_light: + @effects :white_check_mark: + @detectors DetectLianLiStrimerControllers + @comment The Lian Li Strimer L Connect `Direct` mode stutters at high frame rates and + and has been rate limited to ~10FPS. +\*-------------------------------------------------------------------*/ + +RGBController_LianLiStrimerLConnect::RGBController_LianLiStrimerLConnect(LianLiStrimerLConnectController *controller_ptr) +{ + controller = controller_ptr; + + name = "Lian Li Strimer L Connect"; + vendor = "Lian Li"; + type = DEVICE_TYPE_LEDSTRIP; + description = controller->GetDeviceName(); + serial = controller->GetSerial(); + location = controller->GetLocation(); + + mode Off; + Off.name = "Off"; + Off.value = STRIMERLCONNECT_MODE_DIRECT; + Off.brightness = STRIMERLCONNECT_BRIGHTNESS_MIN; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Direct; + Direct.name = "Direct"; + Direct.value = STRIMERLCONNECT_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Breathing = CreateMode("Breathing", STRIMERLCONNECT_MODE_BREATHING, 0, MODE_COLORS_PER_LED); + Breathing.flags |= MODE_FLAG_HAS_PER_LED_COLOR; + modes.push_back(Breathing); + + mode Flashing = CreateMode("Flashing", STRIMERLCONNECT_MODE_FLASHING, 0, MODE_COLORS_PER_LED); + Flashing.flags |= MODE_FLAG_HAS_PER_LED_COLOR; + modes.push_back(Flashing); + + mode BreathCycle = CreateMode("Breathing Cycle", STRIMERLCONNECT_MODE_BREATHCYCLE, 0, MODE_COLORS_NONE); + modes.push_back(BreathCycle); + + mode Rainbow = CreateMode("Rainbow", STRIMERLCONNECT_MODE_RAINBOW, 0, MODE_COLORS_NONE); + Rainbow.flags |= MODE_FLAG_HAS_DIRECTION_LR; + modes.push_back(Rainbow); + + mode RainbowMorph = CreateMode("Rainbow Morph", STRIMERLCONNECT_MODE_RAINBOWMORPH, 0, MODE_COLORS_NONE); + modes.push_back(RainbowMorph); + + mode Snooker = CreateMode("Snooker", STRIMERLCONNECT_MODE_SNOOKER, 6, MODE_COLORS_MODE_SPECIFIC); + Snooker.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + modes.push_back(Snooker); + + mode Mixing = CreateMode("Mixing", STRIMERLCONNECT_MODE_MIXING, 2, MODE_COLORS_MODE_SPECIFIC); + Mixing.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + modes.push_back(Mixing); + + mode PingPong = CreateMode("Ping Pong", STRIMERLCONNECT_MODE_PINGPONG, 6, MODE_COLORS_MODE_SPECIFIC); + PingPong.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + modes.push_back(PingPong); + + mode Runway = CreateMode("Runway", STRIMERLCONNECT_MODE_RUNWAY, 2, MODE_COLORS_MODE_SPECIFIC); + Runway.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + modes.push_back(Runway); + + mode Painting = CreateMode("Painting", STRIMERLCONNECT_MODE_PAINTING, 6, MODE_COLORS_MODE_SPECIFIC); + Painting.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + modes.push_back(Painting); + + mode Tide = CreateMode("Tide", STRIMERLCONNECT_MODE_TIDE, 6, MODE_COLORS_MODE_SPECIFIC); + Tide.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + modes.push_back(Tide); + + mode BlowUp = CreateMode("Blow Up", STRIMERLCONNECT_MODE_BLOWUP, 6, MODE_COLORS_MODE_SPECIFIC); + BlowUp.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + modes.push_back(BlowUp); + + mode Meteor = CreateMode("Meteor", STRIMERLCONNECT_MODE_METEOR, 6, MODE_COLORS_MODE_SPECIFIC); + Meteor.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + modes.push_back(Meteor); + + mode ColorTransfer = CreateMode("Color Transfer", STRIMERLCONNECT_MODE_COLORTRANSFER, 6, MODE_COLORS_MODE_SPECIFIC); + ColorTransfer.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + modes.push_back(ColorTransfer); + + mode FadeOut = CreateMode("Fade Out", STRIMERLCONNECT_MODE_FADEOUT, 6, MODE_COLORS_MODE_SPECIFIC); + FadeOut.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + modes.push_back(FadeOut); + + mode Contest = CreateMode("Contest", STRIMERLCONNECT_MODE_CONTEST, 6, MODE_COLORS_MODE_SPECIFIC); + Contest.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + modes.push_back(Contest); + + mode CrossOver = CreateMode("Cross Over", STRIMERLCONNECT_MODE_CROSSOVER, 6, MODE_COLORS_MODE_SPECIFIC); + CrossOver.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + modes.push_back(CrossOver); + + mode BulletStack = CreateMode("Bullet Stack", STRIMERLCONNECT_MODE_BULLETSTACK, 0, MODE_COLORS_NONE); + BulletStack.flags |= MODE_FLAG_HAS_DIRECTION_LR; + modes.push_back(BulletStack); + + mode Twinkle = CreateMode("Twinkle", STRIMERLCONNECT_MODE_TWINKLE, 0, MODE_COLORS_NONE); + modes.push_back(Twinkle); + + mode Parallel = CreateMode("Parallel", STRIMERLCONNECT_MODE_PARALLEL, 6, MODE_COLORS_MODE_SPECIFIC); + Parallel.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + modes.push_back(Parallel); + + mode ShockWave = CreateMode("Shock Wave", STRIMERLCONNECT_MODE_SHOCKWAVE, 6, MODE_COLORS_MODE_SPECIFIC); + ShockWave.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + modes.push_back(ShockWave); + + mode Ripple = CreateMode("Ripple", STRIMERLCONNECT_MODE_RIPPLE, 6, MODE_COLORS_MODE_SPECIFIC); + Ripple.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + modes.push_back(Ripple); + + mode Voice = CreateMode("Voice", STRIMERLCONNECT_MODE_VOICE, 6, MODE_COLORS_MODE_SPECIFIC); + Voice.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + modes.push_back(Voice); + + mode Drizzling = CreateMode("Drizzling", STRIMERLCONNECT_MODE_DRIZZLING, 6, MODE_COLORS_MODE_SPECIFIC); + Drizzling.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + modes.push_back(Drizzling); + + Init_Controller(); + SetupZones(); +} + +RGBController_LianLiStrimerLConnect::~RGBController_LianLiStrimerLConnect() +{ + delete controller; +} + +void RGBController_LianLiStrimerLConnect::Init_Controller() +{ + const uint8_t zone_split = STRIMERLCONNECT_STRIP_COUNT / 2; + + /*-------------------------------------------------*\ + | Create the device's controllable zones | + \*-------------------------------------------------*/ + for(std::size_t zone_idx = 0; zone_idx < zone_split; zone_idx++) + { + zone new_zone; + new_zone.name = "24 Pin ATX Strip "; + new_zone.name.append(std::to_string(zone_idx)); + new_zone.type = ZONE_TYPE_LINEAR; + new_zone.leds_min = 20; + new_zone.leds_max = 20; + new_zone.leds_count = new_zone.leds_max; + new_zone.matrix_map = NULL; + zones.push_back(new_zone); + } + + for(std::size_t zone_idx = zone_split; zone_idx < STRIMERLCONNECT_STRIP_COUNT; zone_idx++) + { + zone new_zone; + new_zone.name = "8 Pin GPU Strip "; + new_zone.name.append(std::to_string(zone_idx - zone_split)); + new_zone.type = ZONE_TYPE_LINEAR; + new_zone.leds_min = 27; + new_zone.leds_max = 27; + new_zone.leds_count = new_zone.leds_max; + new_zone.matrix_map = NULL; + zones.push_back(new_zone); + } +} + +void RGBController_LianLiStrimerLConnect::SetupZones() +{ + /*-------------------------------------------------*\ + | Clear any existing color/LED configuration | + \*-------------------------------------------------*/ + leds.clear(); + colors.clear(); + + /*---------------------------------------------------------*\ + | Set up zones | + \*---------------------------------------------------------*/ + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + for(unsigned int lp_idx = 0; lp_idx < zones[zone_idx].leds_count; lp_idx++) + { + led new_led; + + new_led.name = zones[zone_idx].name; + new_led.name.append(" LED " + std::to_string(lp_idx)); + + leds.push_back(new_led); + } + } + + SetupColors(); +} + +void RGBController_LianLiStrimerLConnect::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +bool RGBController_LianLiStrimerLConnect::TimeToSend() +{ + /*-----------------------------------------------------*\ + | Rate limit is 1000(ms) / wait_time in Frames Per Sec | + \*-----------------------------------------------------*/ + const uint8_t wait_time = 90; + + return (std::chrono::steady_clock::now() - last_commit_time) > std::chrono::milliseconds(wait_time); +} + +void RGBController_LianLiStrimerLConnect::DeviceUpdateLEDs() +{ + if(TimeToSend()) + { + + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + UpdateZoneLEDs((int)zone_idx); + } + + controller->SendApply(); + + /*-----------------------------------------------------*\ + | Update last commit time | + \*-----------------------------------------------------*/ + last_commit_time = std::chrono::steady_clock::now(); + } +} + +void RGBController_LianLiStrimerLConnect::UpdateZoneLEDs(int zone) +{ + mode current_mode = modes[active_mode]; + + controller->SetLedsDirect(zone, zones[zone].colors, zones[zone].leds_count); + controller->SetMode(current_mode.value, zone, current_mode.speed, current_mode.brightness, current_mode.direction, false); +} + +void RGBController_LianLiStrimerLConnect::UpdateSingleLED(int led) +{ + UpdateZoneLEDs(GetLED_Zone(led)); + controller->SendApply(); +} + +void RGBController_LianLiStrimerLConnect::DeviceUpdateMode() +{ + if(TimeToSend()) + { + mode current_mode = modes[active_mode]; + + if(current_mode.color_mode == MODE_COLORS_PER_LED) + { + return; + } + + bool random_colours = (modes[active_mode].color_mode == MODE_COLORS_RANDOM); + + if(current_mode.color_mode == MODE_COLORS_NONE) + { + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + controller->SetMode((uint8_t)current_mode.value, (uint8_t)zone_idx, current_mode.speed, current_mode.brightness, current_mode.direction, random_colours); + } + } + else + { + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + controller->SetLedsDirect((uint8_t)zone_idx, ¤t_mode.colors[0], (uint8_t)current_mode.colors.size()); + controller->SetMode((uint8_t)current_mode.value, (uint8_t)zone_idx, current_mode.speed, current_mode.brightness, current_mode.direction, random_colours); + } + } + + controller->SendApply(); + + /*-----------------------------------------------------*\ + | Update last commit time | + \*-----------------------------------------------------*/ + last_commit_time = std::chrono::steady_clock::now(); + } +} + +int RGBController_LianLiStrimerLConnect::GetLED_Zone(int led_idx) +{ + for(size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + int zone_start = zones[zone_idx].start_idx; + int zone_end = zone_start + zones[zone_idx].leds_count - 1; + + if( zone_start <= led_idx && zone_end >= led_idx) + { + return((int)zone_idx); + } + } + + return(-1); +} + +mode RGBController_LianLiStrimerLConnect::CreateMode(std::string name, int value, uint8_t colour_count, uint8_t colour_mode) +{ + mode new_mode; + new_mode.name = name; + new_mode.value = value; + new_mode.colors_min = colour_count; + new_mode.colors_max = colour_count; + new_mode.colors.resize(colour_count); + new_mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + new_mode.brightness_min = STRIMERLCONNECT_BRIGHTNESS_MIN; + new_mode.brightness_max = STRIMERLCONNECT_BRIGHTNESS_MAX; + new_mode.brightness = STRIMERLCONNECT_BRIGHTNESS_MAX; + new_mode.speed_min = STRIMERLCONNECT_SPEED_SLOWEST; + new_mode.speed_max = STRIMERLCONNECT_SPEED_FASTEST; + new_mode.speed = STRIMERLCONNECT_SPEED_NORMAL; + new_mode.color_mode = colour_mode; + + return new_mode; +} diff --git a/Controllers/LianLiController/LianLiStrimerLConnectController/RGBController_LianLiStrimerLConnect.h b/Controllers/LianLiController/LianLiStrimerLConnectController/RGBController_LianLiStrimerLConnect.h new file mode 100644 index 00000000..9a344d92 --- /dev/null +++ b/Controllers/LianLiController/LianLiStrimerLConnectController/RGBController_LianLiStrimerLConnect.h @@ -0,0 +1,44 @@ +/*---------------------------------------------------------*\ +| RGBController_LianLiStrimerLConnect.h | +| | +| RGBController for Lian Li Strimer L Connect | +| | +| Chris M (Dr_No) 03 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "LogManager.h" +#include "RGBController.h" +#include "LianLiStrimerLConnectController.h" + +class RGBController_LianLiStrimerLConnect : public RGBController +{ +public: + RGBController_LianLiStrimerLConnect(LianLiStrimerLConnectController* controller_ptr); + ~RGBController_LianLiStrimerLConnect(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + void Init_Controller(); + int GetDeviceMode(); + int GetLED_Zone(int led_idx); + + mode CreateMode(std::string name, int value, uint8_t colour_count, uint8_t colour_mode); + bool TimeToSend(); + + LianLiStrimerLConnectController* controller; + std::chrono::time_point last_commit_time; +}; diff --git a/Controllers/LianLiController/LianLiUniHubALController.cpp b/Controllers/LianLiController/LianLiUniHubALController/LianLiUniHubALController.cpp similarity index 85% rename from Controllers/LianLiController/LianLiUniHubALController.cpp rename to Controllers/LianLiController/LianLiUniHubALController/LianLiUniHubALController.cpp index fa246872..c3f176ce 100644 --- a/Controllers/LianLiController/LianLiUniHubALController.cpp +++ b/Controllers/LianLiController/LianLiUniHubALController/LianLiUniHubALController.cpp @@ -1,16 +1,18 @@ -/*-----------------------------------------*\ -| LianLiUniHubALController.cpp | -| | -| Driver for Lian Li Uni Hub AL USB | -| lighting controller | -| | -| Oliver P 04/26/2022 | -| Credit to Luca Lovisa for original work. | -\*-----------------------------------------*/ - -#include "LianLiUniHubALController.h" +/*---------------------------------------------------------*\ +| LianLiUniHubALController.cpp | +| | +| Driver for Lian Li AL Uni Hub | +| | +| Oliver P 26 Apr 2022 | +| Credit to Luca Lovisa for original work | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "LianLiUniHubALController.h" +#include "StringUtils.h" using namespace std::chrono_literals; @@ -42,8 +44,7 @@ std::string LianLiUniHubALController::GetFirmwareVersionString() return (""); } - std::wstring return_wstring = product_string; - std::string return_string(return_wstring.begin(),return_wstring.end()); + std::string return_string = StringUtils::wstring_to_string(product_string); return(return_string.substr(return_string.find_last_of("-")+1,4).c_str()); } @@ -63,8 +64,7 @@ std::string LianLiUniHubALController::GetSerialString() return (""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); + std::string return_string = StringUtils::wstring_to_string(serial_string); return(return_string); @@ -105,18 +105,18 @@ void LianLiUniHubALController::SetChannelLEDs(unsigned char channel, RGBColor * //Determine current position of led_data array from colors array cur_led_idx = ((mod_led_idx + (fan_idx * 8)) * 3); - fan_led_data[cur_led_idx + 0] = RGBGetRValue(colors[led_idx]) * brightness; - fan_led_data[cur_led_idx + 1] = RGBGetBValue(colors[led_idx]) * brightness; - fan_led_data[cur_led_idx + 2] = RGBGetGValue(colors[led_idx]) * brightness; + fan_led_data[cur_led_idx + 0] = (unsigned char)(RGBGetRValue(colors[led_idx]) * brightness); + fan_led_data[cur_led_idx + 1] = (unsigned char)(RGBGetBValue(colors[led_idx]) * brightness); + fan_led_data[cur_led_idx + 2] = (unsigned char)(RGBGetGValue(colors[led_idx]) * brightness); } else // Edge LEDs, 12 LEDs per fan { //Determine current position of led_data array from colors array cur_led_idx = (((mod_led_idx - 8) + (fan_idx * 12)) * 3); - edge_led_data[cur_led_idx + 0] = RGBGetRValue(colors[led_idx]) * brightness; - edge_led_data[cur_led_idx + 1] = RGBGetBValue(colors[led_idx]) * brightness; - edge_led_data[cur_led_idx + 2] = RGBGetGValue(colors[led_idx]) * brightness; + edge_led_data[cur_led_idx + 0] = (unsigned char)(RGBGetRValue(colors[led_idx]) * brightness); + edge_led_data[cur_led_idx + 1] = (unsigned char)(RGBGetBValue(colors[led_idx]) * brightness); + edge_led_data[cur_led_idx + 2] = (unsigned char)(RGBGetGValue(colors[led_idx]) * brightness); } } @@ -228,17 +228,17 @@ void LianLiUniHubALController::SetChannelMode(unsigned char channel, unsigned in for(unsigned int led_idx = 0; led_idx < 22; led_idx += 3) { cur_led_idx = (i * 8 * 3) + led_idx; - fan_led_data[cur_led_idx + 0] = (RGBGetRValue(colors[i]) * brightness_scale); - fan_led_data[cur_led_idx + 1] = (RGBGetBValue(colors[i]) * brightness_scale); - fan_led_data[cur_led_idx + 2] = (RGBGetGValue(colors[i]) * brightness_scale); + fan_led_data[cur_led_idx + 0] = (unsigned char)(RGBGetRValue(colors[i]) * brightness_scale); + fan_led_data[cur_led_idx + 1] = (unsigned char)(RGBGetBValue(colors[i]) * brightness_scale); + fan_led_data[cur_led_idx + 2] = (unsigned char)(RGBGetGValue(colors[i]) * brightness_scale); } for(unsigned int led_idx = 0; led_idx < 34; led_idx += 3) { cur_led_idx = (i * 12 * 3) + led_idx; - edge_led_data[cur_led_idx + 0] = (RGBGetRValue(colors[i]) * brightness_scale); - edge_led_data[cur_led_idx + 1] = (RGBGetBValue(colors[i]) * brightness_scale); - edge_led_data[cur_led_idx + 2] = (RGBGetGValue(colors[i]) * brightness_scale); + edge_led_data[cur_led_idx + 0] = (unsigned char)(RGBGetRValue(colors[i]) * brightness_scale); + edge_led_data[cur_led_idx + 1] = (unsigned char)(RGBGetBValue(colors[i]) * brightness_scale); + edge_led_data[cur_led_idx + 2] = (unsigned char)(RGBGetGValue(colors[i]) * brightness_scale); } } break; diff --git a/Controllers/LianLiController/LianLiUniHubALController.h b/Controllers/LianLiController/LianLiUniHubALController/LianLiUniHubALController.h similarity index 89% rename from Controllers/LianLiController/LianLiUniHubALController.h rename to Controllers/LianLiController/LianLiUniHubALController/LianLiUniHubALController.h index 87be3291..f664dedd 100644 --- a/Controllers/LianLiController/LianLiUniHubALController.h +++ b/Controllers/LianLiController/LianLiUniHubALController/LianLiUniHubALController.h @@ -1,19 +1,21 @@ -/*-----------------------------------------*\ -| LianLiHubALController.h | -| | -| Definitions and types for Lian Li AL120 | -| | -| Oliver P 04/26/2022 | -| Credit to Luca Lovisa for original work. | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| LianLiUniHubALController.h | +| | +| Driver for Lian Li AL Uni Hub | +| | +| Oliver P 26 Apr 2022 | +| Credit to Luca Lovisa for original work | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + /*----------------------------------------------------------------------------*\ | Global definitions. | \*----------------------------------------------------------------------------*/ @@ -206,24 +208,10 @@ private: hid_device* dev; unsigned short dev_pid; - /*---------------------------------------------------------*\ - | Device-specific protocol settings | - \*---------------------------------------------------------*/ - unsigned char dev_transaction_id; - unsigned char dev_led_id; - /*---------------------------------------------------------*\ | Device information strings | \*---------------------------------------------------------*/ std::string firmware_version; std::string location; std::string name; - device_type type; - - /*---------------------------------------------------------*\ - | HID report index for request and response | - \*---------------------------------------------------------*/ - unsigned char report_index; - unsigned char response_index; - }; diff --git a/Controllers/LianLiController/RGBController_LianLiUniHubAL.cpp b/Controllers/LianLiController/LianLiUniHubALController/RGBController_LianLiUniHubAL.cpp similarity index 94% rename from Controllers/LianLiController/RGBController_LianLiUniHubAL.cpp rename to Controllers/LianLiController/LianLiUniHubALController/RGBController_LianLiUniHubAL.cpp index 261ad43b..1df41d8e 100644 --- a/Controllers/LianLiController/RGBController_LianLiUniHubAL.cpp +++ b/Controllers/LianLiController/LianLiUniHubALController/RGBController_LianLiUniHubAL.cpp @@ -1,16 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_LianLiUniHubAL.cpp | -| | -| Generic RGB Interface for Lian Li Uni | -| Hub AL USB controller driver | -| | -| Oliver P 04/26/2022 | -| Credit to Luca Lovisa for original work. | -\*-----------------------------------------*/ - -#include "RGBController_LianLiUniHubAL.h" +/*---------------------------------------------------------*\ +| RGBController_LianLiUniHubAL.cpp | +| | +| RGBController for Lian Li AL Uni Hub | +| | +| Oliver P 26 Apr 2022 | +| Credit to Luca Lovisa for original work | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "RGBController_LianLiUniHubAL.h" //0xFFFFFFFF indicates an unused entry in matrix #define NA 0xFFFFFFFF @@ -462,7 +463,7 @@ void RGBController_LianLiUniHubAL::DeviceUpdateLEDs() for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) { - controller->SetChannelLEDs(zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count, brightness_scale); + controller->SetChannelLEDs((unsigned char)zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count, brightness_scale); } } @@ -518,16 +519,6 @@ void RGBController_LianLiUniHubAL::DeviceUpdateMode() } fan_idx = ((zones[zone_idx].leds_count / 20) - 1); // Indexes start at 0 - controller->SetChannelMode(zone_idx, modes[active_mode].value,modes[active_mode].colors, modes[active_mode].colors.size(), (fan_idx >= 0 ? fan_idx : 0), upd_both_fan_edge, modes[active_mode].brightness, modes[active_mode].speed, modes[active_mode].direction); - + controller->SetChannelMode((unsigned char)zone_idx, modes[active_mode].value,modes[active_mode].colors, (unsigned int)modes[active_mode].colors.size(), (fan_idx >= 0 ? fan_idx : 0), upd_both_fan_edge, modes[active_mode].brightness, modes[active_mode].speed, modes[active_mode].direction); } } - -void RGBController_LianLiUniHubAL::SetCustomMode() -{ - /*-------------------------------------------------*\ - | Set mode to Static Color | - \*-------------------------------------------------*/ - active_mode = 0; -} - diff --git a/Controllers/LianLiController/LianLiUniHubALController/RGBController_LianLiUniHubAL.h b/Controllers/LianLiController/LianLiUniHubALController/RGBController_LianLiUniHubAL.h new file mode 100644 index 00000000..52277a43 --- /dev/null +++ b/Controllers/LianLiController/LianLiUniHubALController/RGBController_LianLiUniHubAL.h @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| RGBController_LianLiUniHub_AL.h | +| | +| RGBController for Lian Li AL Uni Hub | +| | +| Oliver P 26 Apr 2022 | +| Credit to Luca Lovisa for original work | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "LianLiUniHubALController.h" +#include "RGBController.h" + +class RGBController_LianLiUniHubAL : public RGBController +{ +public: + RGBController_LianLiUniHubAL(LianLiUniHubALController* controller_ptr); + ~RGBController_LianLiUniHubAL(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LianLiUniHubALController* controller; + bool initializedMode; +}; diff --git a/Controllers/LianLiController/LianLiUniHubController.cpp b/Controllers/LianLiController/LianLiUniHubController/LianLiUniHubController.cpp similarity index 95% rename from Controllers/LianLiController/LianLiUniHubController.cpp rename to Controllers/LianLiController/LianLiUniHubController/LianLiUniHubController.cpp index 5b4e77f0..f00cc08d 100644 --- a/Controllers/LianLiController/LianLiUniHubController.cpp +++ b/Controllers/LianLiController/LianLiUniHubController/LianLiUniHubController.cpp @@ -1,15 +1,16 @@ -/*-----------------------------------------*\ -| LianLiUniHubController.cpp | -| | -| Driver for Lian Li Uni Hub USB | -| lighting controller | -| | -| Luca Lovisa 2/20/2021 | -\*-----------------------------------------*/ - -#include "LianLiUniHubController.h" +/*---------------------------------------------------------*\ +| LianLiUniHubController.cpp | +| | +| Driver for Lian Li Uni Hub | +| | +| Luca Lovisa 20 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "LianLiUniHubController.h" using namespace std::chrono_literals; @@ -666,14 +667,14 @@ void LianLiUniHubController::SendConfig(uint16_t wIndex, uint8_t *config, size_ /*-------------------------------------*\ | Send packet | \*-------------------------------------*/ - size_t ret = libusb_control_transfer(handle, /* dev_handle */ - 0x40, /* bmRequestType */ - 0x80, /* bRequest */ - 0x00, /* wValue */ - wIndex, /* wIndex */ - config, /* data */ - length, /* wLength */ - 1000); /* timeout */ + size_t ret = libusb_control_transfer(handle, /* dev_handle */ + 0x40, /* bmRequestType */ + 0x80, /* bRequest */ + 0x00, /* wValue */ + wIndex, /* wIndex */ + config, /* data */ + (uint16_t)length, /* wLength */ + 1000); /* timeout */ /*-------------------------------------*\ | Check for communication error | diff --git a/Controllers/LianLiController/LianLiUniHubController.h b/Controllers/LianLiController/LianLiUniHubController/LianLiUniHubController.h similarity index 94% rename from Controllers/LianLiController/LianLiUniHubController.h rename to Controllers/LianLiController/LianLiUniHubController/LianLiUniHubController.h index 76fc36a6..cacbe589 100644 --- a/Controllers/LianLiController/LianLiUniHubController.h +++ b/Controllers/LianLiController/LianLiUniHubController/LianLiUniHubController.h @@ -1,25 +1,21 @@ -/*-----------------------------------------*\ -| LianLiUniHubController.h | -| | -| Definitions and types for Lian Li Uni | -| Hub USB RGB lighting controller | -| | -| Luca Lovisa 2/20/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LianLiUniHubController.h | +| | +| Driver for Lian Li Uni Hub | +| | +| Luca Lovisa 20 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once #include #include #include - -#include "RGBController.h" - -#ifdef __FreeBSD__ #include -#else -#include -#endif +#include "RGBController.h" /*----------------------------------------------------------------------------*\ | Global definitions. | diff --git a/Controllers/LianLiController/RGBController_LianLiUniHub.cpp b/Controllers/LianLiController/LianLiUniHubController/RGBController_LianLiUniHub.cpp similarity index 92% rename from Controllers/LianLiController/RGBController_LianLiUniHub.cpp rename to Controllers/LianLiController/LianLiUniHubController/RGBController_LianLiUniHub.cpp index 2c7c232a..73e830ac 100644 --- a/Controllers/LianLiController/RGBController_LianLiUniHub.cpp +++ b/Controllers/LianLiController/LianLiUniHubController/RGBController_LianLiUniHub.cpp @@ -1,15 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_LianLiUniHub.cpp | -| | -| Generic RGB Interface for Lian Li Uni | -| Hub USB controller driver | -| | -| Luca Lovisa 2/20/2021 | -\*-----------------------------------------*/ - -#include "RGBController_LianLiUniHub.h" +/*---------------------------------------------------------*\ +| RGBController_LianLiUniHub.cpp | +| | +| RGBController for Lian Li Uni Hub | +| | +| Luca Lovisa 20 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "RGBController_LianLiUniHub.h" mode makeMode() { diff --git a/Controllers/LianLiController/LianLiUniHubController/RGBController_LianLiUniHub.h b/Controllers/LianLiController/LianLiUniHubController/RGBController_LianLiUniHub.h new file mode 100644 index 00000000..9e742067 --- /dev/null +++ b/Controllers/LianLiController/LianLiUniHubController/RGBController_LianLiUniHub.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------*\ +| RGBController_LianLiUniHub.h | +| | +| RGBController for Lian Li Uni Hub | +| | +| Luca Lovisa 20 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "LianLiUniHubController.h" +#include "RGBController.h" + +class RGBController_LianLiUniHub : public RGBController +{ +public: + RGBController_LianLiUniHub(LianLiUniHubController* controller_ptr); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + uint8_t convertAnyFanCount(uint8_t count); + uint8_t convertLedSpeed(uint8_t speed); + uint8_t convertLedDirection(uint8_t direction); + + uint8_t convertLedCountToFanCount(uint8_t count); + +private: + LianLiUniHubController* controller; + bool initializedMode; +}; diff --git a/Controllers/LianLiController/LianLiUniHubSLInfinityController/LianLiUniHubSLInfinityController.cpp b/Controllers/LianLiController/LianLiUniHubSLInfinityController/LianLiUniHubSLInfinityController.cpp new file mode 100644 index 00000000..bf101c05 --- /dev/null +++ b/Controllers/LianLiController/LianLiUniHubSLInfinityController/LianLiUniHubSLInfinityController.cpp @@ -0,0 +1,319 @@ +/*---------------------------------------------------------*\ +| LianLiUniHubSLInfinityController.cpp | +| | +| Driver for Lian Li SL Infinity Uni Hub | +| | +| Simon McKenna 21 Oct 2023 | +| Will Kennedy 17 Jan 2023 | +| Oliver P 26 Apr 2022 | +| Credit to Luca Lovisa for original work. | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "LianLiUniHubSLInfinityController.h" +#include "StringUtils.h" + +using namespace std::chrono_literals; + +LianLiUniHubSLInfinityController::LianLiUniHubSLInfinityController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; +} + +LianLiUniHubSLInfinityController::~LianLiUniHubSLInfinityController() +{ + hid_close(dev); +} + +std::string LianLiUniHubSLInfinityController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string LianLiUniHubSLInfinityController::GetFirmwareVersionString() +{ + wchar_t product_string[40]; + int ret = hid_get_product_string(dev, product_string, 40); + + if (ret != 0) + { + return (""); + } + + std::string return_string = StringUtils::wstring_to_string(product_string); + + return(return_string.substr(return_string.find_last_of("-")+1,4).c_str()); +} + +std::string LianLiUniHubSLInfinityController::GetName() +{ + return(name); +} + +std::string LianLiUniHubSLInfinityController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +float infinityBrightnessLimit(RGBColor color) +{ + /*---------------------------------------------------------*\ + | Limiter to protect LEDs | + \*---------------------------------------------------------*/ + if(UNIHUB_SLINF_LED_LIMITER && (RGBGetRValue(color) + RGBGetBValue(color) + RGBGetGValue(color) > 460)) + { + return 460.f / (RGBGetRValue(color) + RGBGetBValue(color) + RGBGetGValue(color)); + } + return 1; +} + +void LianLiUniHubSLInfinityController::SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors, float brightness) +{ + unsigned char led_data[16 * 6 * 3]; + int fan_idx = 0; + int mod_led_idx; + int cur_led_idx; + + if(num_colors == 0) + { + return; // Do nothing, channel isn't in use + } + + for(unsigned int led_idx = 0; led_idx < num_colors; led_idx++) + { + mod_led_idx = (led_idx % 16); + + if((mod_led_idx == 0) && (led_idx != 0)) + { + fan_idx++; + } + + float brightness_scale = brightness * infinityBrightnessLimit(colors[led_idx]); + + //Determine current position of led_data array from colors array + cur_led_idx = ((mod_led_idx + (fan_idx * 16)) * 3); + + led_data[cur_led_idx + 0] = (unsigned char)(RGBGetRValue(colors[led_idx]) * brightness_scale); + led_data[cur_led_idx + 1] = (unsigned char)(RGBGetBValue(colors[led_idx]) * brightness_scale); + led_data[cur_led_idx + 2] = (unsigned char)(RGBGetGValue(colors[led_idx]) * brightness_scale); + } + + /*---------------------------------------------------------*\ + | Send fan LED data | + \*---------------------------------------------------------*/ + + SendStartAction + ( + channel, // Current channel + (fan_idx + 1) // Number of fans + ); + + SendColorData + ( + channel, // Channel + (fan_idx + 1)*16, + led_data + ); + + SendCommitAction + ( + channel, // Channel + UNIHUB_SLINF_LED_MODE_STATIC_COLOR, // Effect + UNIHUB_SLINF_LED_SPEED_000, // Speed + UNIHUB_SLINF_LED_DIRECTION_LTR, // Direction + UNIHUB_SLINF_LED_BRIGHTNESS_100 // Brightness + ); + +} + +void LianLiUniHubSLInfinityController::SetChannelMode(unsigned char channel, const mode active_mode, unsigned int num_fans) +{ + static unsigned int brightness_code[5] = + { + UNIHUB_SLINF_LED_BRIGHTNESS_000, + UNIHUB_SLINF_LED_BRIGHTNESS_025, + UNIHUB_SLINF_LED_BRIGHTNESS_050, + UNIHUB_SLINF_LED_BRIGHTNESS_075, + UNIHUB_SLINF_LED_BRIGHTNESS_100 + }; + + static unsigned int speed_code[5] = + { + UNIHUB_SLINF_LED_SPEED_000, + UNIHUB_SLINF_LED_SPEED_025, + UNIHUB_SLINF_LED_SPEED_050, + UNIHUB_SLINF_LED_SPEED_075, + UNIHUB_SLINF_LED_SPEED_100 + }; + + unsigned char fan_led_data[16 * 6 * 3]; + int cur_led_idx; + float brightness; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(fan_led_data, 0x00, sizeof(fan_led_data)); + + std::vector colors = active_mode.colors; + unsigned int num_colors = (unsigned int)colors.size(); + + if(!colors.empty()) // Update led_data if there's colors + { + brightness = static_cast(active_mode.brightness)/4; + if(num_colors == 6) + { + for(unsigned int i = 0; i < 6; i++) + { + float brightness_scale = brightness * infinityBrightnessLimit(colors[i]); + for(unsigned int led_idx = 0; led_idx < 16 * 3; led_idx += 3) + { + cur_led_idx = (i * 16 * 3) + led_idx; + fan_led_data[cur_led_idx + 0] = (unsigned char)(RGBGetRValue(colors[i]) * brightness_scale); + fan_led_data[cur_led_idx + 1] = (unsigned char)(RGBGetBValue(colors[i]) * brightness_scale); + fan_led_data[cur_led_idx + 2] = (unsigned char)(RGBGetGValue(colors[i]) * brightness_scale); + } + } + } + else + { + colors.resize(4); + for(unsigned int i = num_colors; i < 4; i++) + { + colors[i] = 0x00; + } + + // needs a 72 length array of 4 colors, even if less are defined + for(unsigned int j = 0; j < 4; j++) + { + float brightness_scale = brightness * infinityBrightnessLimit(colors[j]); + for(unsigned int i = 0; i < 6; i++) + { + cur_led_idx = (i * 12) + (j * 3); + fan_led_data[cur_led_idx + 0] = (unsigned char)(RGBGetRValue(colors[j]) * brightness_scale); + fan_led_data[cur_led_idx + 1] = (unsigned char)(RGBGetBValue(colors[j]) * brightness_scale); + fan_led_data[cur_led_idx + 2] = (unsigned char)(RGBGetGValue(colors[j]) * brightness_scale); + } + } + } + + } + + SendStartAction + ( + channel, // Current channel + (num_fans + 1) // Number of fans + ); + + SendColorData + ( + channel, // Channel + (num_fans + 1)*16, + fan_led_data // Data + ); + + SendCommitAction + ( + channel, // Channel + active_mode.value, // Effect + speed_code[active_mode.speed], // Speed + active_mode.direction, // Direction + brightness_code[active_mode.brightness] // Brightness + ); +} + +void LianLiUniHubSLInfinityController::SendStartAction(unsigned char channel, unsigned int /*num_fans*/) +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up message packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = UNIHUB_SLINF_TRANSACTION_ID; + usb_buf[0x01] = 0x10; + usb_buf[0x02] = 0x60; + usb_buf[0x03] = 1 + (channel / 2); // every fan-array uses two channels (one for the spinner and one for the led-band on the side) + usb_buf[0x04] = 0x04; // TODO: number of fans (1-4) on this channel, hardcoding this to 4 for now + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, sizeof(usb_buf)); + std::this_thread::sleep_for(5ms); + +} + +void LianLiUniHubSLInfinityController::SendColorData(unsigned char channel, unsigned int num_leds, unsigned char* led_data) +{ + /*---------------------------------------------------------*\ + | Send LED data | + \*---------------------------------------------------------*/ + + unsigned char usb_buf[353]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up message packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = UNIHUB_SLINF_TRANSACTION_ID; + usb_buf[0x01] = 0x30 + channel; // action + channel(30 = channel 1, 31 = channel 2, etc.) + + /*-----------------------------------------------------*\ + | Copy in color data bytes | + \*-----------------------------------------------------*/ + memcpy(&usb_buf[0x02], led_data, num_leds * 3); + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, sizeof(usb_buf)); + std::this_thread::sleep_for(5ms); +} + +void LianLiUniHubSLInfinityController::SendCommitAction(unsigned char channel, unsigned char effect, unsigned char speed, unsigned int direction, unsigned int brightness) +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up message packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = UNIHUB_SLINF_TRANSACTION_ID; + usb_buf[0x01] = 0x10 + channel; // Channel+device (10 = channel 1, 11 = channel 2, etc.) + usb_buf[0x02] = effect; // Effect + usb_buf[0x03] = speed; // Speed, 02=0%, 01=25%, 00=50%, ff=75%, fe=100% + usb_buf[0x04] = direction; // Direction, right=00, left=01 + usb_buf[0x05] = brightness; // Brightness, 0=100%, 1= 75%, 2 = 50%, 3 = 25%, 8 = 0% + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, sizeof(usb_buf)); + std::this_thread::sleep_for(5ms); +} diff --git a/Controllers/LianLiController/LianLiUniHubSLInfinityController/LianLiUniHubSLInfinityController.h b/Controllers/LianLiController/LianLiUniHubSLInfinityController/LianLiUniHubSLInfinityController.h new file mode 100644 index 00000000..1dd43542 --- /dev/null +++ b/Controllers/LianLiController/LianLiUniHubSLInfinityController/LianLiUniHubSLInfinityController.h @@ -0,0 +1,211 @@ +/*---------------------------------------------------------*\ +| LianLiUniHubSLInfinityController.h | +| | +| Driver for Lian Li SL Infinity Uni Hub | +| | +| Simon McKenna 21 Oct 2023 | +| Will Kennedy 17 Jan 2023 | +| Oliver P 26 Apr 2022 | +| Credit to Luca Lovisa for original work. | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +/*----------------------------------------------------------------------------*\ +| Global definitions. | +\*----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------*\ +| Definitions related to zone Sizes | +\*----------------------------------------------------------------------------*/ + +enum +{ + UNIHUB_SLINF_CHANNEL_COUNT = 0x08, /* Channel count */ + UNIHUB_SLINF_CHAN_LED_COUNT = 0x10 * 6, /* Max-LED per channel count - 96 */ +}; + +/*----------------------------------------------------------------------------*\ +| Definitions related to LED configuration. | +\*----------------------------------------------------------------------------*/ + +// Used for sync'd mode between Fan and Edge + +enum +{ + UNIHUB_SLINF_LED_MODE_STATIC_COLOR = 0x01, // full data array + UNIHUB_SLINF_LED_MODE_BREATHING = 0x02, // full data array + UNIHUB_SLINF_LED_MODE_RAINBOW_MORPH = 0x04, // no array + UNIHUB_SLINF_LED_MODE_RAINBOW = 0x05, // no array + UNIHUB_SLINF_LED_MODE_STAGGERED = 0x18, // size 2 + UNIHUB_SLINF_LED_MODE_TIDE = 0x1A, // size 2 + UNIHUB_SLINF_LED_MODE_RUNWAY = 0x1C, // size 2 + UNIHUB_SLINF_LED_MODE_MIXING = 0x1E, // size 2 + UNIHUB_SLINF_LED_MODE_STACK = 0x20, // size 1 + UNIHUB_SLINF_LED_MODE_STACK_MULTI_COLOR = 0x21, // no array + UNIHUB_SLINF_LED_MODE_NEON = 0x22, // no array + UNIHUB_SLINF_LED_MODE_COLOR_CYCLE = 0x23, // size 3 + UNIHUB_SLINF_LED_MODE_METEOR = 0x24, // size 2 + UNIHUB_SLINF_LED_MODE_VOICE = 0x26, // no array + UNIHUB_SLINF_LED_MODE_GROOVE = 0x27, // size 2 + UNIHUB_SLINF_LED_MODE_RENDER = 0x28, // size 4 + UNIHUB_SLINF_LED_MODE_TUNNEL = 0x29, // size 4 + // merged modes + UNIHUB_SLINF_LED_MODE_METEOR_MERGED = 0x2A, + UNIHUB_SLINF_LED_MODE_RUNWAY_MERGED = 0x2B, + UNIHUB_SLINF_LED_MODE_TIDE_MERGED = 0x2C, + UNIHUB_SLINF_LED_MODE_MIXING_MERGED = 0x2D, + UNIHUB_SLINF_LED_MODE_STACK_MULTI_COLOR_MERGED = 0x2E +}; + +enum +{ + UNIHUB_SLINF_LED_SPEED_000 = 0x02, /* Very slow speed */ + UNIHUB_SLINF_LED_SPEED_025 = 0x01, /* Rather slow speed */ + UNIHUB_SLINF_LED_SPEED_050 = 0x00, /* Medium speed */ + UNIHUB_SLINF_LED_SPEED_075 = 0xFF, /* Rather fast speed */ + UNIHUB_SLINF_LED_SPEED_100 = 0xFE, /* Very fast speed */ +}; + +enum +{ + UNIHUB_SLINF_LED_DIRECTION_LTR = 0x00, /* Left-to-Right direction */ + UNIHUB_SLINF_LED_DIRECTION_RTL = 0x01, /* Right-to-Left direction */ +}; + +enum +{ + UNIHUB_SLINF_LED_BRIGHTNESS_000 = 0x08, /* Very dark (off) */ + UNIHUB_SLINF_LED_BRIGHTNESS_025 = 0x03, /* Rather dark */ + UNIHUB_SLINF_LED_BRIGHTNESS_050 = 0x02, /* Medium bright */ + UNIHUB_SLINF_LED_BRIGHTNESS_075 = 0x01, /* Rather bright */ + UNIHUB_SLINF_LED_BRIGHTNESS_100 = 0x00, /* Very bright */ +}; + +enum +{ + UNIHUB_SLINF_LED_LIMITER = 0x01 /* Limit the color white to 999999 as per manufacturer limits */ +}; + + +/*----------------------------------------------------------------------------*\ +| Definitions related to packet configuration. | +\*----------------------------------------------------------------------------*/ + +enum +{ + UNIHUB_SLINF_TRANSACTION_ID = 0xE0, /* Command value to start all packets */ +}; + +/*----------------------------------------------------------------------------*\ +| Uni Hub SL Infinity controller. | +\*----------------------------------------------------------------------------*/ + +class LianLiUniHubSLInfinityController +{ + + +public: + LianLiUniHubSLInfinityController(hid_device* dev_handle, const char* path, std::string dev_name); + ~LianLiUniHubSLInfinityController(); + + std::string GetDeviceLocation(); + std::string GetFirmwareVersionString(); + std::string GetName(); + std::string GetSerialString(); + + void SetChannelMode + ( + unsigned char channel, + const mode active_mode, + unsigned int num_fans + ); + + void SetChannelLEDs + ( + unsigned char channel, + RGBColor * colors, + unsigned int num_colors, + float brightness + ); + + void SendStartAction + ( + unsigned char channel, + unsigned int num_fans + ); + + void SendColorData + ( + unsigned char channel, // Zone index + unsigned int num_leds, + unsigned char* led_data // Color data payload + ); + + void SendCommitAction + ( + unsigned char channel, // Zone index + unsigned char effect, + unsigned char speed, + unsigned int direction, + unsigned int brightness + ); + +private: + /* The Uni Hub requires colors in RBG order */ + struct Color + { + uint8_t r; + uint8_t b; + uint8_t g; + }; + + /* The values correspond to the definitions above */ + struct Channel + { + uint8_t index; + + uint8_t anyFanCountOffset; + uint8_t anyFanCount; + + uint16_t ledActionAddress; + uint16_t ledCommitAddress; + uint16_t ledModeAddress; + uint16_t ledSpeedAddress; + uint16_t ledDirectionAddress; + uint16_t ledBrightnessAddress; + + Color colors[UNIHUB_SLINF_CHAN_LED_COUNT]; + + uint8_t ledMode; + uint8_t ledSpeed; + uint8_t ledDirection; + uint8_t ledBrightness; + + uint16_t fanHubActionAddress; + uint16_t fanHubCommitAddress; + + uint16_t fanPwmActionAddress; + uint16_t fanPwmCommitAddress; + uint16_t fanRpmActionAddress; + + uint16_t fanSpeed; + }; + +private: + hid_device* dev; + + /*---------------------------------------------------------*\ + | Device information strings | + \*---------------------------------------------------------*/ + std::string firmware_version; + std::string location; + std::string name; +}; diff --git a/Controllers/LianLiController/LianLiUniHubSLInfinityController/RGBController_LianLiUniHubSLInfinity.cpp b/Controllers/LianLiController/LianLiUniHubSLInfinityController/RGBController_LianLiUniHubSLInfinity.cpp new file mode 100644 index 00000000..9780690c --- /dev/null +++ b/Controllers/LianLiController/LianLiUniHubSLInfinityController/RGBController_LianLiUniHubSLInfinity.cpp @@ -0,0 +1,445 @@ +/*---------------------------------------------------------*\ +| RGBController_LianLiUniHubSLInfinity.cpp | +| | +| RGBController for Lian Li SL Infinity Uni Hub | +| | +| Simon McKenna 21 Oct 2023 | +| Will Kennedy 17 Jan 2023 | +| Oliver P 26 Apr 2022 | +| Credit to Luca Lovisa for original work. | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RGBController_LianLiUniHubSLInfinity.h" + +/**------------------------------------------------------------------*\ + @name Lian Li Uni Hub SL Infinity + @type USB + @save :x: + @direct :rotating_light: + @effects :white_check_mark: + @detectors DetectLianLiUniHubSLInfinity + @comment +\*-------------------------------------------------------------------*/ + +RGBController_LianLiUniHubSLInfinity::RGBController_LianLiUniHubSLInfinity(LianLiUniHubSLInfinityController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = "Lian Li"; + type = DEVICE_TYPE_COOLER; + description = "Lian Li Uni Hub - SL Infinity"; + version = controller->GetFirmwareVersionString(); + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + initializedMode = false; + + mode Custom; + Custom.name = "Custom"; + Custom.value = UNIHUB_SLINF_LED_MODE_STATIC_COLOR; + Custom.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR; + Custom.brightness_min = 0; + Custom.brightness_max = 50; + Custom.brightness = 37; + Custom.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Custom); + + mode StaticColor; + StaticColor.name = "Static"; + StaticColor.value = UNIHUB_SLINF_LED_MODE_STATIC_COLOR; + StaticColor.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + StaticColor.brightness_min = 0; + StaticColor.brightness_max = 4; + StaticColor.colors_min = 0; + StaticColor.colors_max = 6; + StaticColor.brightness = 4; + StaticColor.color_mode = MODE_COLORS_MODE_SPECIFIC; + StaticColor.colors.resize(6); + modes.push_back(StaticColor); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = UNIHUB_SLINF_LED_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Breathing.speed_min = 0; + Breathing.speed_max = 4; + Breathing.brightness_min = 0; + Breathing.brightness_max = 4; + Breathing.colors_min = 0; + Breathing.colors_max = 6; + Breathing.speed = 2; + Breathing.brightness = 4; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.colors.resize(6); + modes.push_back(Breathing); + + mode RainbowMorph; + RainbowMorph.name = "Spectrum Cycle"; + RainbowMorph.value = UNIHUB_SLINF_LED_MODE_RAINBOW_MORPH; + RainbowMorph.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + RainbowMorph.speed_min = 0; + RainbowMorph.speed_max = 4; + RainbowMorph.brightness_min = 0; + RainbowMorph.brightness_max = 4; + RainbowMorph.speed = 2; + RainbowMorph.brightness = 4; + RainbowMorph.color_mode = MODE_COLORS_NONE; + modes.push_back(RainbowMorph); + + mode RainbowWave; + RainbowWave.name = "Rainbow Wave"; + RainbowWave.value = UNIHUB_SLINF_LED_MODE_RAINBOW; + RainbowWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + RainbowWave.speed_min = 0; + RainbowWave.speed_max = 4; + RainbowWave.brightness_min = 0; + RainbowWave.brightness_max = 4; + RainbowWave.speed = 2; + RainbowWave.brightness = 4; + RainbowWave.direction = UNIHUB_SLINF_LED_DIRECTION_LTR; + RainbowWave.color_mode = MODE_COLORS_NONE; + modes.push_back(RainbowWave); + + mode Staggered; + Staggered.name = "Staggered"; + Staggered.value = UNIHUB_SLINF_LED_MODE_STAGGERED; + Staggered.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Staggered.speed_min = 0; + Staggered.speed_max = 4; + Staggered.brightness_min = 0; + Staggered.brightness_max = 4; + Staggered.colors_min = 0; + Staggered.colors_max = 2; + Staggered.speed = 2; + Staggered.brightness = 4; + Staggered.color_mode = MODE_COLORS_MODE_SPECIFIC; + Staggered.colors.resize(2); + modes.push_back(Staggered); + + mode Tide; // TODO: Has merge + Tide.name = "Tide"; + Tide.value = UNIHUB_SLINF_LED_MODE_TIDE; + Tide.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Tide.speed_min = 0; + Tide.speed_max = 4; + Tide.brightness_min = 0; + Tide.brightness_max = 4; + Tide.colors_min = 0; + Tide.colors_max = 2; + Tide.speed = 2; + Tide.brightness = 4; + Tide.color_mode = MODE_COLORS_MODE_SPECIFIC; + Tide.colors.resize(2); + modes.push_back(Tide); + + mode Runway; //TODO: Has merge + Runway.name = "Runway"; + Runway.value = UNIHUB_SLINF_LED_MODE_RUNWAY; + Runway.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Runway.speed_min = 0; + Runway.speed_max = 4; + Runway.brightness_min = 0; + Runway.brightness_max = 4; + Runway.colors_min = 0; + Runway.colors_max = 2; + Runway.speed = 2; + Runway.brightness = 4; + Runway.color_mode = MODE_COLORS_MODE_SPECIFIC; + Runway.colors.resize(2); + modes.push_back(Runway); + + mode Mixing; //TODO: Has merge + Mixing.name = "Mixing"; + Mixing.value = UNIHUB_SLINF_LED_MODE_MIXING; + Mixing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Mixing.speed_min = 0; + Mixing.speed_max = 4; + Mixing.brightness_min = 0; + Mixing.brightness_max = 4; + Mixing.colors_min = 0; + Mixing.colors_max = 2; + Mixing.speed = 2; + Mixing.brightness = 4; + Mixing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Mixing.colors.resize(2); + modes.push_back(Mixing); + + mode Stack; + Stack.name = "Stack"; + Stack.value = UNIHUB_SLINF_LED_MODE_STACK; + Stack.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + Stack.speed_min = 0; + Stack.speed_max = 4; + Stack.brightness_min = 0; + Stack.brightness_max = 4; + Stack.colors_min = 0; + Stack.colors_max = 1; + Stack.speed = 2; + Stack.brightness = 4; + Stack.direction = UNIHUB_SLINF_LED_DIRECTION_LTR; + Stack.color_mode = MODE_COLORS_MODE_SPECIFIC; + Stack.colors.resize(1); + modes.push_back(Stack); + + mode StackMultiColor; //TODO: Has merge + Stack.name = "Stack Multi Color"; + Stack.value = UNIHUB_SLINF_LED_MODE_STACK_MULTI_COLOR; + Stack.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR; + Stack.speed_min = 0; + Stack.speed_max = 4; + Stack.brightness_min = 0; + Stack.brightness_max = 4; + Stack.speed = 2; + Stack.brightness = 4; + Stack.direction = UNIHUB_SLINF_LED_DIRECTION_LTR; + Stack.color_mode = MODE_COLORS_NONE; + modes.push_back(Stack); + + mode Neon; + Neon.name = "Neon"; + Neon.value = UNIHUB_SLINF_LED_MODE_NEON; + Neon.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Neon.speed_min = 0; + Neon.speed_max = 4; + Neon.brightness_min = 0; + Neon.brightness_max = 4; + Neon.speed = 2; + Neon.brightness = 4; + Neon.color_mode = MODE_COLORS_NONE; + modes.push_back(Neon); + + mode ColorCycle; + ColorCycle.name = "ColorCycle"; + ColorCycle.value = UNIHUB_SLINF_LED_MODE_COLOR_CYCLE; + ColorCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + ColorCycle.speed_min = 0; + ColorCycle.speed_max = 4; + ColorCycle.brightness_min = 0; + ColorCycle.brightness_max = 4; + ColorCycle.colors_min = 0; + ColorCycle.colors_max = 3; + ColorCycle.speed = 2; + ColorCycle.brightness = 4; + ColorCycle.direction = UNIHUB_SLINF_LED_DIRECTION_LTR; + ColorCycle.color_mode = MODE_COLORS_MODE_SPECIFIC; + ColorCycle.colors.resize(3); + modes.push_back(ColorCycle); + + mode Meteor; //TODO: Has merge + Meteor.name = "Meteor"; + Meteor.value = UNIHUB_SLINF_LED_MODE_METEOR; + Meteor.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Meteor.speed_min = 0; + Meteor.speed_max = 4; + Meteor.brightness_min = 0; + Meteor.brightness_max = 4; + Meteor.colors_min = 0; + Meteor.colors_max = 2; + Meteor.speed = 2; + Meteor.brightness = 4; + Meteor.color_mode = MODE_COLORS_MODE_SPECIFIC; + Meteor.colors.resize(2); + modes.push_back(Meteor); + + mode Voice; + Voice.name = "Voice"; + Voice.value = UNIHUB_SLINF_LED_MODE_VOICE; + Voice.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Voice.speed_min = 0; + Voice.speed_max = 4; + Voice.brightness_min = 0; + Voice.brightness_max = 4; + Voice.speed = 2; + Voice.brightness = 4; + modes.push_back(Voice); + + mode Groove; + Groove.name = "Groove"; + Groove.value = UNIHUB_SLINF_LED_MODE_GROOVE; + Groove.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + Groove.speed_min = 0; + Groove.speed_max = 4; + Groove.brightness_min = 0; + Groove.brightness_max = 4; + Groove.colors_min = 0; + Groove.colors_max = 1; + Groove.speed = 2; + Groove.brightness = 4; + Groove.direction = UNIHUB_SLINF_LED_DIRECTION_LTR; + Groove.color_mode = MODE_COLORS_MODE_SPECIFIC; + Groove.colors.resize(1); + modes.push_back(Groove); + + mode Render; + Render.name = "Render"; + Render.value = UNIHUB_SLINF_LED_MODE_RENDER; + Render.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + Render.speed_min = 0; + Render.speed_max = 4; + Render.brightness_min = 0; + Render.brightness_max = 4; + Render.colors_min = 0; + Render.colors_max = 4; + Render.speed = 2; + Render.brightness = 4; + Render.direction = UNIHUB_SLINF_LED_DIRECTION_LTR; + Render.color_mode = MODE_COLORS_MODE_SPECIFIC; + Render.colors.resize(4); + modes.push_back(Render); + + mode Tunnel; + Tunnel.name = "Tunnel"; + Tunnel.value = UNIHUB_SLINF_LED_MODE_TUNNEL; + Tunnel.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + Tunnel.speed_min = 0; + Tunnel.speed_max = 4; + Tunnel.brightness_min = 0; + Tunnel.brightness_max = 4; + Tunnel.colors_min = 0; + Tunnel.colors_max = 4; + Tunnel.speed = 2; + Tunnel.brightness = 4; + Tunnel.direction = UNIHUB_SLINF_LED_DIRECTION_LTR; + Tunnel.color_mode = MODE_COLORS_MODE_SPECIFIC; + Tunnel.colors.resize(4); + modes.push_back(Tunnel); + + RGBController_LianLiUniHubSLInfinity::SetupZones(); +} + +RGBController_LianLiUniHubSLInfinity::~RGBController_LianLiUniHubSLInfinity() +{ + delete controller; +} + +void RGBController_LianLiUniHubSLInfinity::SetupZones() +{ + /*-------------------------------------------------*\ + | Only set LED count on the first run | + \*-------------------------------------------------*/ + bool first_run = false; + + if(zones.size() == 0) + { + first_run = true; + zones.resize(UNIHUB_SLINF_CHANNEL_COUNT); + } + + /*-------------------------------------------------*\ + | Clear any existing color/LED configuration | + \*-------------------------------------------------*/ + leds.clear(); + colors.clear(); + + /*-------------------------------------------------*\ + | Set zones and leds | + \*-------------------------------------------------*/ + for(unsigned int channel_idx = 0; channel_idx < zones.size(); channel_idx++) + { + zones[channel_idx].name = "Channel "; + zones[channel_idx].name.append(std::to_string(channel_idx + 1)); + + zones[channel_idx].type = ZONE_TYPE_LINEAR; + zones[channel_idx].leds_min = 0; + zones[channel_idx].leds_max = UNIHUB_SLINF_CHAN_LED_COUNT; + + if(first_run) + { + zones[channel_idx].leds_count = zones[channel_idx].leds_min; + } + + for(unsigned int led_ch_idx = 0; led_ch_idx < zones[channel_idx].leds_count; led_ch_idx++) + { + led new_led; + new_led.name = zones[channel_idx].name; + new_led.name.append(", LED "); + new_led.name.append(std::to_string(led_ch_idx + 1)); + new_led.value = channel_idx; + + leds.push_back(new_led); + } + + } + + SetupColors(); +} + +void RGBController_LianLiUniHubSLInfinity::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_LianLiUniHubSLInfinity::DeviceUpdateLEDs() +{ + + if(!initializedMode) + { + DeviceUpdateMode(); + } + + float brightness_scale = static_cast(modes[active_mode].brightness)/modes[active_mode].brightness_max; + + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + controller->SetChannelLEDs((unsigned char)zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count, brightness_scale); + } +} + +void RGBController_LianLiUniHubSLInfinity::UpdateZoneLEDs(int zone) +{ + if(!initializedMode) + { + DeviceUpdateMode(); + } + + float brightness_scale = static_cast(modes[active_mode].brightness)/modes[active_mode].brightness_max; + + controller->SetChannelLEDs(zone, zones[zone].colors, zones[zone].leds_count, brightness_scale); +} + +void RGBController_LianLiUniHubSLInfinity::UpdateSingleLED(int /* led */) +{ + DeviceUpdateMode(); + +} + +void RGBController_LianLiUniHubSLInfinity::DeviceUpdateMode() +{ + if(!active_mode) + { + return; // Do nothing, custom mode should go through DeviceUpdateLEDs() to avoid flooding controller + } + + initializedMode = true; + + int fan_idx = 0; + + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + if(zones[zone_idx].leds_count == 0) + { + return; // Do nothing, channel isn't in use + } + fan_idx = ((zones[zone_idx].leds_count / 16) - 1); // Indexes start at 0 + + controller->SetChannelMode((unsigned char)zone_idx, + modes[active_mode], + fan_idx); + + } +} diff --git a/Controllers/LianLiController/LianLiUniHubSLInfinityController/RGBController_LianLiUniHubSLInfinity.h b/Controllers/LianLiController/LianLiUniHubSLInfinityController/RGBController_LianLiUniHubSLInfinity.h new file mode 100644 index 00000000..2b544659 --- /dev/null +++ b/Controllers/LianLiController/LianLiUniHubSLInfinityController/RGBController_LianLiUniHubSLInfinity.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------*\ +| RGBController_LianLiUniHubSLInfinity.h | +| | +| RGBController for Lian Li SL Infinity Uni Hub | +| | +| Simon McKenna 21 Oct 2023 | +| Will Kennedy 17 Jan 2023 | +| Oliver P 26 Apr 2022 | +| Credit to Luca Lovisa for original work. | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "LianLiUniHubSLInfinityController.h" +#include "RGBController.h" + +class RGBController_LianLiUniHubSLInfinity : public RGBController +{ +public: + RGBController_LianLiUniHubSLInfinity(LianLiUniHubSLInfinityController* controller_ptr); + ~RGBController_LianLiUniHubSLInfinity(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LianLiUniHubSLInfinityController* controller; + bool initializedMode; +}; diff --git a/Controllers/LianLiController/LianLiUniHubSLV2Controller.cpp b/Controllers/LianLiController/LianLiUniHubSLV2Controller/LianLiUniHubSLV2Controller.cpp similarity index 82% rename from Controllers/LianLiController/LianLiUniHubSLV2Controller.cpp rename to Controllers/LianLiController/LianLiUniHubSLV2Controller/LianLiUniHubSLV2Controller.cpp index b9870338..bf263c4f 100644 --- a/Controllers/LianLiController/LianLiUniHubSLV2Controller.cpp +++ b/Controllers/LianLiController/LianLiUniHubSLV2Controller/LianLiUniHubSLV2Controller.cpp @@ -1,17 +1,19 @@ -/*-----------------------------------------*\ -| LianLiUniHubSLV2Controller.cpp | -| | -| Driver for Lian Li Uni Hub SLV2 USB | -| lighting controller | -| | -| Will Kennedy 01/17/2023 | -| Oliver P 04/26/2022 | -| Credit to Luca Lovisa for original work. | -\*-----------------------------------------*/ - -#include "LianLiUniHubSLV2Controller.h" +/*---------------------------------------------------------*\ +| LianLiUniHubSLV2Controller.cpp | +| | +| Driver for Lian Li SLV2 Uni Hub | +| | +| Will Kennedy 17 Jan 2023 | +| Oliver P 26 Apr 2022 | +| Credit to Luca Lovisa for original work. | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "LianLiUniHubSLV2Controller.h" +#include "StringUtils.h" using namespace std::chrono_literals; @@ -42,8 +44,7 @@ std::string LianLiUniHubSLV2Controller::GetFirmwareVersionString() return (""); } - std::wstring return_wstring = product_string; - std::string return_string(return_wstring.begin(),return_wstring.end()); + std::string return_string = StringUtils::wstring_to_string(product_string); return(return_string.substr(return_string.find_last_of("-")+1,4).c_str()); } @@ -55,19 +56,15 @@ std::string LianLiUniHubSLV2Controller::GetName() std::string LianLiUniHubSLV2Controller::GetSerialString() { - wchar_t serial_string[20]; - int ret = hid_get_serial_number_string(dev, serial_string, 20); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); - if (ret != 0) + if(ret != 0) { - return (""); + return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); - + return(StringUtils::wstring_to_string(serial_string)); } float brightnessLimit(RGBColor color) @@ -108,9 +105,9 @@ void LianLiUniHubSLV2Controller::SetChannelLEDs(unsigned char channel, RGBColor //Determine current position of led_data array from colors array cur_led_idx = ((mod_led_idx + (fan_idx * 16)) * 3); - led_data[cur_led_idx + 0] = RGBGetRValue(colors[led_idx]) * brightness_scale; - led_data[cur_led_idx + 1] = RGBGetBValue(colors[led_idx]) * brightness_scale; - led_data[cur_led_idx + 2] = RGBGetGValue(colors[led_idx]) * brightness_scale; + led_data[cur_led_idx + 0] = (unsigned char)(RGBGetRValue(colors[led_idx]) * brightness_scale); + led_data[cur_led_idx + 1] = (unsigned char)(RGBGetBValue(colors[led_idx]) * brightness_scale); + led_data[cur_led_idx + 2] = (unsigned char)(RGBGetGValue(colors[led_idx]) * brightness_scale); } /*---------------------------------------------------------*\ @@ -171,7 +168,7 @@ void LianLiUniHubSLV2Controller::SetChannelMode(unsigned char channel, const mod memset(fan_led_data, 0x00, sizeof(fan_led_data)); std::vector colors = active_mode.colors; - unsigned int num_colors = colors.size(); + unsigned int num_colors = (unsigned int)colors.size(); if(!colors.empty()) // Update led_data if there's colors { @@ -184,9 +181,9 @@ void LianLiUniHubSLV2Controller::SetChannelMode(unsigned char channel, const mod for(unsigned int led_idx = 0; led_idx < 16 * 3; led_idx += 3) { cur_led_idx = (i * 16 * 3) + led_idx; - fan_led_data[cur_led_idx + 0] = (RGBGetRValue(colors[i]) * brightness_scale); - fan_led_data[cur_led_idx + 1] = (RGBGetBValue(colors[i]) * brightness_scale); - fan_led_data[cur_led_idx + 2] = (RGBGetGValue(colors[i]) * brightness_scale); + fan_led_data[cur_led_idx + 0] = (unsigned char)(RGBGetRValue(colors[i]) * brightness_scale); + fan_led_data[cur_led_idx + 1] = (unsigned char)(RGBGetBValue(colors[i]) * brightness_scale); + fan_led_data[cur_led_idx + 2] = (unsigned char)(RGBGetGValue(colors[i]) * brightness_scale); } } } @@ -205,13 +202,12 @@ void LianLiUniHubSLV2Controller::SetChannelMode(unsigned char channel, const mod for(unsigned int i = 0; i < 6; i++) { cur_led_idx = (i * 12) + (j * 3); - fan_led_data[cur_led_idx + 0] = RGBGetRValue(colors[j]) * brightness_scale; - fan_led_data[cur_led_idx + 1] = RGBGetBValue(colors[j]) * brightness_scale; - fan_led_data[cur_led_idx + 2] = RGBGetGValue(colors[j]) * brightness_scale; + fan_led_data[cur_led_idx + 0] = (unsigned char)(RGBGetRValue(colors[j]) * brightness_scale); + fan_led_data[cur_led_idx + 1] = (unsigned char)(RGBGetBValue(colors[j]) * brightness_scale); + fan_led_data[cur_led_idx + 2] = (unsigned char)(RGBGetGValue(colors[j]) * brightness_scale); } } } - } SendStartAction diff --git a/Controllers/LianLiController/LianLiUniHubSLV2Controller.h b/Controllers/LianLiController/LianLiUniHubSLV2Controller/LianLiUniHubSLV2Controller.h similarity index 87% rename from Controllers/LianLiController/LianLiUniHubSLV2Controller.h rename to Controllers/LianLiController/LianLiUniHubSLV2Controller/LianLiUniHubSLV2Controller.h index 513b0980..104b1e33 100644 --- a/Controllers/LianLiController/LianLiUniHubSLV2Controller.h +++ b/Controllers/LianLiController/LianLiUniHubSLV2Controller/LianLiUniHubSLV2Controller.h @@ -1,20 +1,22 @@ -/*-----------------------------------------*\ -| LianLiHubSLV2Controller.h | -| | -| Definitions and types for Lian Li SLV2120| -| | -| Will Kennedy 01/17/2023 | -| Oliver P 04/26/2022 | -| Credit to Luca Lovisa for original work. | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| LianLiUniHubSLV2Controller.h | +| | +| Driver for Lian Li SLV2 Uni Hub | +| | +| Will Kennedy 17 Jan 2023 | +| Oliver P 26 Apr 2022 | +| Credit to Luca Lovisa for original work. | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + /*----------------------------------------------------------------------------*\ | Global definitions. | \*----------------------------------------------------------------------------*/ @@ -199,13 +201,6 @@ private: private: hid_device* dev; - unsigned short dev_pid; - - /*---------------------------------------------------------*\ - | Device-specific protocol settings | - \*---------------------------------------------------------*/ - unsigned char dev_transaction_id; - unsigned char dev_led_id; /*---------------------------------------------------------*\ | Device information strings | @@ -213,12 +208,4 @@ private: std::string firmware_version; std::string location; std::string name; - device_type type; - - /*---------------------------------------------------------*\ - | HID report index for request and response | - \*---------------------------------------------------------*/ - unsigned char report_index; - unsigned char response_index; - }; diff --git a/Controllers/LianLiController/RGBController_LianLiUniHubSLV2.cpp b/Controllers/LianLiController/LianLiUniHubSLV2Controller/RGBController_LianLiUniHubSLV2.cpp similarity index 94% rename from Controllers/LianLiController/RGBController_LianLiUniHubSLV2.cpp rename to Controllers/LianLiController/LianLiUniHubSLV2Controller/RGBController_LianLiUniHubSLV2.cpp index 52073ff7..267db8ed 100644 --- a/Controllers/LianLiController/RGBController_LianLiUniHubSLV2.cpp +++ b/Controllers/LianLiController/LianLiUniHubSLV2Controller/RGBController_LianLiUniHubSLV2.cpp @@ -1,17 +1,18 @@ -/*-----------------------------------------*\ -| RGBController_LianLiUniHubSLV2.cpp | -| | -| Generic RGB Interface for Lian Li Uni | -| Hub SLV2 USB controller driver | -| | -| Will Kennedy 01/17/2023 | -| Oliver P 04/26/2022 | -| Credit to Luca Lovisa for original work. | -\*-----------------------------------------*/ - -#include "RGBController_LianLiUniHubSLV2.h" +/*---------------------------------------------------------*\ +| RGBController_LianLiUniHubSLV2.cpp | +| | +| RGBController for Lian Li SLV2 Uni Hub | +| | +| Will Kennedy 17 Jan 2023 | +| Oliver P 26 Apr 2022 | +| Credit to Luca Lovisa for original work. | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "RGBController_LianLiUniHubSLV2.h" /**------------------------------------------------------------------*\ @name Lian Li Uni Hub SLV2 @@ -43,7 +44,7 @@ RGBController_LianLiUniHubSLV2::RGBController_LianLiUniHubSLV2(LianLiUniHubSLV2C Custom.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR; Custom.brightness_min = 0; Custom.brightness_max = 50; - Custom.brightness = 37; + Custom.brightness = 50; Custom.color_mode = MODE_COLORS_PER_LED; modes.push_back(Custom); @@ -394,7 +395,7 @@ void RGBController_LianLiUniHubSLV2::DeviceUpdateLEDs() for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) { - controller->SetChannelLEDs(zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count, brightness_scale); + controller->SetChannelLEDs((unsigned char)zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count, brightness_scale); } } @@ -435,18 +436,9 @@ void RGBController_LianLiUniHubSLV2::DeviceUpdateMode() } fan_idx = ((zones[zone_idx].leds_count / 16) - 1); // Indexes start at 0 - controller->SetChannelMode(zone_idx, + controller->SetChannelMode((unsigned char)zone_idx, modes[active_mode], fan_idx); } } - -void RGBController_LianLiUniHubSLV2::SetCustomMode() -{ - /*-------------------------------------------------*\ - | Set mode to Static Color | - \*-------------------------------------------------*/ - active_mode = 0; -} - diff --git a/Controllers/LianLiController/LianLiUniHubSLV2Controller/RGBController_LianLiUniHubSLV2.h b/Controllers/LianLiController/LianLiUniHubSLV2Controller/RGBController_LianLiUniHubSLV2.h new file mode 100644 index 00000000..381f19af --- /dev/null +++ b/Controllers/LianLiController/LianLiUniHubSLV2Controller/RGBController_LianLiUniHubSLV2.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------*\ +| RGBController_LianLiUniHubSLV2.h | +| | +| RGBController for Lian Li SLV2 Uni Hub | +| | +| Will Kennedy 17 Jan 2023 | +| Oliver P 26 Apr 2022 | +| Credit to Luca Lovisa for original work. | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "LianLiUniHubSLV2Controller.h" +#include "RGBController.h" + +class RGBController_LianLiUniHubSLV2 : public RGBController +{ +public: + RGBController_LianLiUniHubSLV2(LianLiUniHubSLV2Controller* controller_ptr); + ~RGBController_LianLiUniHubSLV2(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LianLiUniHubSLV2Controller* controller; + bool initializedMode; +}; diff --git a/Controllers/LianLiController/LianLiUniHub_AL10Controller.cpp b/Controllers/LianLiController/LianLiUniHub_AL10Controller/LianLiUniHub_AL10Controller.cpp similarity index 95% rename from Controllers/LianLiController/LianLiUniHub_AL10Controller.cpp rename to Controllers/LianLiController/LianLiUniHub_AL10Controller/LianLiUniHub_AL10Controller.cpp index 79e2a819..7bf6048b 100644 --- a/Controllers/LianLiController/LianLiUniHub_AL10Controller.cpp +++ b/Controllers/LianLiController/LianLiUniHub_AL10Controller/LianLiUniHub_AL10Controller.cpp @@ -1,16 +1,17 @@ -/*-----------------------------------------*\ -| LianLiUniHub_AL10Controller.cpp | -| | -| Driver for Lian Li Uni Hub USB | -| lighting controller | -| | -| Oliver P 05/05/2022 | -| Credit to Luca Lovisa for original work. | -\*-----------------------------------------*/ - -#include "LianLiUniHub_AL10Controller.h" +/*---------------------------------------------------------*\ +| LianLiUniHub_AL10Controller.cpp | +| | +| Driver for Lian Li AL10 Uni Hub | +| | +| Oliver P 05 May 2022 | +| Credit to Luca Lovisa for original work | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "LianLiUniHub_AL10Controller.h" using namespace std::chrono_literals; @@ -754,14 +755,14 @@ void LianLiUniHub_AL10Controller::SendConfig(uint16_t wIndex, uint8_t *config, /*-------------------------------------*\ | Send packet | \*-------------------------------------*/ - size_t ret = libusb_control_transfer(handle, /* dev_handle */ - 0x40, /* bmRequestType */ - 0x80, /* bRequest */ - 0x00, /* wValue */ - wIndex, /* wIndex */ - config, /* data */ - length, /* wLength */ - 1000); /* timeout */ + size_t ret = libusb_control_transfer(handle, /* dev_handle */ + 0x40, /* bmRequestType */ + 0x80, /* bRequest */ + 0x00, /* wValue */ + wIndex, /* wIndex */ + config, /* data */ + (uint16_t)length, /* wLength */ + 1000); /* timeout */ std::this_thread::sleep_for(5ms); /*-------------------------------------*\ | Check for communication error | diff --git a/Controllers/LianLiController/LianLiUniHub_AL10Controller.h b/Controllers/LianLiController/LianLiUniHub_AL10Controller/LianLiUniHub_AL10Controller.h similarity index 94% rename from Controllers/LianLiController/LianLiUniHub_AL10Controller.h rename to Controllers/LianLiController/LianLiUniHub_AL10Controller/LianLiUniHub_AL10Controller.h index 0be07f2a..e72b89dc 100644 --- a/Controllers/LianLiController/LianLiUniHub_AL10Controller.h +++ b/Controllers/LianLiController/LianLiUniHub_AL10Controller/LianLiUniHub_AL10Controller.h @@ -1,23 +1,23 @@ -/*-----------------------------------------*\ -| LianLiUniHub_AL10Controller.h | -| | -| Definitions and types for Lian Li Uni | -| Hub USB RGB lighting controller | -| | -| Oliver P 05/05/2022 | -| Credit to Luca Lovisa for original work. | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LianLiUniHub_AL10Controller.h | +| | +| Driver for Lian Li AL10 Uni Hub | +| | +| Oliver P 05 May 2022 | +| Credit to Luca Lovisa for original work | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once #include #include #include - +#include #include "RGBController.h" -#include - /*----------------------------------------------------------------------------*\ | Global definitions. | \*----------------------------------------------------------------------------*/ diff --git a/Controllers/LianLiController/RGBController_LianLiUniHub_AL10.cpp b/Controllers/LianLiController/LianLiUniHub_AL10Controller/RGBController_LianLiUniHub_AL10.cpp similarity index 97% rename from Controllers/LianLiController/RGBController_LianLiUniHub_AL10.cpp rename to Controllers/LianLiController/LianLiUniHub_AL10Controller/RGBController_LianLiUniHub_AL10.cpp index 12b26761..b17fe5e0 100644 --- a/Controllers/LianLiController/RGBController_LianLiUniHub_AL10.cpp +++ b/Controllers/LianLiController/LianLiUniHub_AL10Controller/RGBController_LianLiUniHub_AL10.cpp @@ -1,16 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_LianLiUniHub_AL10.cpp | -| | -| Generic RGB Interface for Lian Li Uni | -| Hub USB controller driver | -| | -| Oliver P 05/05/2022 | -| Credit to Luca Lovisa for original work. | -\*-----------------------------------------*/ - -#include "RGBController_LianLiUniHub_AL10.h" +/*---------------------------------------------------------*\ +| RGBController_LianLiUniHub_AL10.cpp | +| | +| RGBController for Lian Li AL10 Uni Hub | +| | +| Oliver P 05 May 2022 | +| Credit to Luca Lovisa for original work | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "RGBController_LianLiUniHub_AL10.h" /**------------------------------------------------------------------*\ @name Lian Li Uni Hub @@ -543,14 +544,6 @@ void RGBController_LianLiUniHub_AL10::DeviceUpdateMode() controller->Synchronize(); } -void RGBController_LianLiUniHub_AL10::SetCustomMode() -{ - /*-------------------------------------------------*\ - | Set mode to Static Color | - \*-------------------------------------------------*/ - active_mode = 0; -} - uint8_t RGBController_LianLiUniHub_AL10::convertAnyFanCount(uint8_t count) { switch (count) diff --git a/Controllers/LianLiController/LianLiUniHub_AL10Controller/RGBController_LianLiUniHub_AL10.h b/Controllers/LianLiController/LianLiUniHub_AL10Controller/RGBController_LianLiUniHub_AL10.h new file mode 100644 index 00000000..a72df08b --- /dev/null +++ b/Controllers/LianLiController/LianLiUniHub_AL10Controller/RGBController_LianLiUniHub_AL10.h @@ -0,0 +1,46 @@ +/*---------------------------------------------------------*\ +| RGBController_LianLiUniHub_AL10.h | +| | +| RGBController for Lian Li AL Uni Hub | +| | +| Oliver P 05 May 2022 | +| Credit to Luca Lovisa for original work | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "LianLiUniHub_AL10Controller.h" +#include "RGBController.h" + +class RGBController_LianLiUniHub_AL10 : public RGBController +{ +public: + RGBController_LianLiUniHub_AL10(LianLiUniHub_AL10Controller* controller_ptr); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + uint8_t convertAnyFanCount(uint8_t count); + uint8_t convertLedSpeed(uint8_t speed); + uint8_t convertLedDirection(uint8_t direction); + uint8_t convertLedBrightness(uint8_t brightness); + + uint8_t convertLedCountToFanCount(uint8_t count); + +private: + LianLiUniHub_AL10Controller* controller; + bool initializedMode; +}; diff --git a/Controllers/LianLiController/RGBController_LianLiUniHub.h b/Controllers/LianLiController/RGBController_LianLiUniHub.h deleted file mode 100644 index faa65a00..00000000 --- a/Controllers/LianLiController/RGBController_LianLiUniHub.h +++ /dev/null @@ -1,42 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LianLiUniHub.h | -| | -| Generic RGB Interface for Lian Li Uni | -| Hub USB controller driver | -| | -| Luca Lovisa 2/20/2021 | -\*-----------------------------------------*/ - -#pragma once - -#include -#include - -#include "LianLiUniHubController.h" -#include "RGBController.h" - -class RGBController_LianLiUniHub : public RGBController -{ -public: - RGBController_LianLiUniHub(LianLiUniHubController* controller_ptr); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - uint8_t convertAnyFanCount(uint8_t count); - uint8_t convertLedSpeed(uint8_t speed); - uint8_t convertLedDirection(uint8_t direction); - - uint8_t convertLedCountToFanCount(uint8_t count); - -private: - LianLiUniHubController* controller; - bool initializedMode; -}; diff --git a/Controllers/LianLiController/RGBController_LianLiUniHubAL.h b/Controllers/LianLiController/RGBController_LianLiUniHubAL.h deleted file mode 100644 index 4520e4a4..00000000 --- a/Controllers/LianLiController/RGBController_LianLiUniHubAL.h +++ /dev/null @@ -1,40 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LianLiUniHubAL.h | -| | -| Generic RGB Interface for Lian Li Uni | -| Hub AL USB controller driver | -| | -| Oliver P 04/26/2022 | -| Credit to Luca Lovisa for original work. | -\*-----------------------------------------*/ - -#pragma once - -#include -#include - -#include "LianLiUniHubALController.h" -#include "RGBController.h" - -class RGBController_LianLiUniHubAL : public RGBController -{ -public: - RGBController_LianLiUniHubAL(LianLiUniHubALController* controller_ptr); - ~RGBController_LianLiUniHubAL(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - void SetCustomMode(); - -private: - LianLiUniHubALController* controller; - bool initializedMode; -}; diff --git a/Controllers/LianLiController/RGBController_LianLiUniHubSLV2.h b/Controllers/LianLiController/RGBController_LianLiUniHubSLV2.h deleted file mode 100644 index d4098fb8..00000000 --- a/Controllers/LianLiController/RGBController_LianLiUniHubSLV2.h +++ /dev/null @@ -1,41 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LianLiUniHubSLV2.h | -| | -| Generic RGB Interface for Lian Li Uni | -| Hub SLV2 USB controller driver | -| | -| Will Kennedy 01/17/2023 | -| Oliver P 04/26/2022 | -| Credit to Luca Lovisa for original work. | -\*-----------------------------------------*/ - -#pragma once - -#include -#include - -#include "LianLiUniHubSLV2Controller.h" -#include "RGBController.h" - -class RGBController_LianLiUniHubSLV2 : public RGBController -{ -public: - RGBController_LianLiUniHubSLV2(LianLiUniHubSLV2Controller* controller_ptr); - ~RGBController_LianLiUniHubSLV2(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - void SetCustomMode(); - -private: - LianLiUniHubSLV2Controller* controller; - bool initializedMode; -}; diff --git a/Controllers/LianLiController/RGBController_LianLiUniHub_AL10.h b/Controllers/LianLiController/RGBController_LianLiUniHub_AL10.h deleted file mode 100644 index beea7cc6..00000000 --- a/Controllers/LianLiController/RGBController_LianLiUniHub_AL10.h +++ /dev/null @@ -1,47 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LianLiUniHub_AL10.h | -| | -| Generic RGB Interface for Lian Li Uni | -| Hub USB controller driver | -| | -| Oliver P 05/05/2022 | -| Credit to Luca Lovisa for original work. | -\*-----------------------------------------*/ - -#pragma once - -#include -#include - -#include "LianLiUniHub_AL10Controller.h" -#include "RGBController.h" - -class RGBController_LianLiUniHub_AL10 : public RGBController -{ -public: - RGBController_LianLiUniHub_AL10(LianLiUniHub_AL10Controller* controller_ptr); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - void SetCustomMode(); - -private: - uint8_t convertAnyFanCount(uint8_t count); - uint8_t convertLedSpeed(uint8_t speed); - uint8_t convertLedDirection(uint8_t direction); - uint8_t convertLedBrightness(uint8_t brightness); - - uint8_t convertLedCountToFanCount(uint8_t count); - -private: - LianLiUniHub_AL10Controller* controller; - bool initializedMode; -}; diff --git a/Controllers/LianLiController/RGBController_StrimerLConnect.cpp b/Controllers/LianLiController/RGBController_StrimerLConnect.cpp deleted file mode 100644 index 9dfe424f..00000000 --- a/Controllers/LianLiController/RGBController_StrimerLConnect.cpp +++ /dev/null @@ -1,334 +0,0 @@ -/*---------------------------------------------------------------------*\ -| RGBController_StrimerLConnect.cpp | -| | -| Driver for StrimerLConnect USB Controller | -| | -| Chris M (Dr_No) 03 Jul 2022 | -| | -\*---------------------------------------------------------------------*/ - -#include "RGBController_StrimerLConnect.h" - -/**------------------------------------------------------------------*\ - @name Lian Li Strimer L Connect - @category LEDStrip - @type USB - @save :x: - @direct :rotating_light: - @effects :white_check_mark: - @detectors DetectStrimerControllers - @comment The Lian Li Strimer L Connect `Direct` mode stutters at high frame rates and - and has been rate limited to ~10FPS. -\*-------------------------------------------------------------------*/ - -RGBController_StrimerLConnect::RGBController_StrimerLConnect(StrimerLConnectController *controller_ptr) -{ - controller = controller_ptr; - - name = "Lian Li Strimer L Connect"; - vendor = "Lian Li"; - type = DEVICE_TYPE_LEDSTRIP; - description = controller->GetDeviceName(); - serial = controller->GetSerial(); - location = controller->GetLocation(); - - mode Off; - Off.name = "Off"; - Off.value = STRIMERLCONNECT_MODE_DIRECT; - Off.brightness = STRIMERLCONNECT_BRIGHTNESS_MIN; - Off.color_mode = MODE_COLORS_NONE; - modes.push_back(Off); - - mode Direct; - Direct.name = "Direct"; - Direct.value = STRIMERLCONNECT_MODE_DIRECT; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - - mode Breathing = CreateMode("Breathing", STRIMERLCONNECT_MODE_BREATHING, 0, MODE_COLORS_PER_LED); - Breathing.flags |= MODE_FLAG_HAS_PER_LED_COLOR; - modes.push_back(Breathing); - - mode Flashing = CreateMode("Flashing", STRIMERLCONNECT_MODE_FLASHING, 0, MODE_COLORS_PER_LED); - Flashing.flags |= MODE_FLAG_HAS_PER_LED_COLOR; - modes.push_back(Flashing); - - mode BreathCycle = CreateMode("Breathing Cycle", STRIMERLCONNECT_MODE_BREATHCYCLE, 0, MODE_COLORS_NONE); - modes.push_back(BreathCycle); - - mode Rainbow = CreateMode("Rainbow", STRIMERLCONNECT_MODE_RAINBOW, 0, MODE_COLORS_NONE); - Rainbow.flags |= MODE_FLAG_HAS_DIRECTION_LR; - modes.push_back(Rainbow); - - mode RainbowMorph = CreateMode("Rainbow Morph", STRIMERLCONNECT_MODE_RAINBOWMORPH, 0, MODE_COLORS_NONE); - modes.push_back(RainbowMorph); - - mode Snooker = CreateMode("Snooker", STRIMERLCONNECT_MODE_SNOOKER, 6, MODE_COLORS_MODE_SPECIFIC); - Snooker.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - modes.push_back(Snooker); - - mode Mixing = CreateMode("Mixing", STRIMERLCONNECT_MODE_MIXING, 2, MODE_COLORS_MODE_SPECIFIC); - Mixing.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - modes.push_back(Mixing); - - mode PingPong = CreateMode("Ping Pong", STRIMERLCONNECT_MODE_PINGPONG, 6, MODE_COLORS_MODE_SPECIFIC); - PingPong.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - modes.push_back(PingPong); - - mode Runway = CreateMode("Runway", STRIMERLCONNECT_MODE_RUNWAY, 2, MODE_COLORS_MODE_SPECIFIC); - Runway.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - modes.push_back(Runway); - - mode Painting = CreateMode("Painting", STRIMERLCONNECT_MODE_PAINTING, 6, MODE_COLORS_MODE_SPECIFIC); - Painting.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - modes.push_back(Painting); - - mode Tide = CreateMode("Tide", STRIMERLCONNECT_MODE_TIDE, 6, MODE_COLORS_MODE_SPECIFIC); - Tide.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - modes.push_back(Tide); - - mode BlowUp = CreateMode("Blow Up", STRIMERLCONNECT_MODE_BLOWUP, 6, MODE_COLORS_MODE_SPECIFIC); - BlowUp.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - modes.push_back(BlowUp); - - mode Meteor = CreateMode("Meteor", STRIMERLCONNECT_MODE_METEOR, 6, MODE_COLORS_MODE_SPECIFIC); - Meteor.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; - modes.push_back(Meteor); - - mode ColorTransfer = CreateMode("Color Transfer", STRIMERLCONNECT_MODE_COLORTRANSFER, 6, MODE_COLORS_MODE_SPECIFIC); - ColorTransfer.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; - modes.push_back(ColorTransfer); - - mode FadeOut = CreateMode("Fade Out", STRIMERLCONNECT_MODE_FADEOUT, 6, MODE_COLORS_MODE_SPECIFIC); - FadeOut.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - modes.push_back(FadeOut); - - mode Contest = CreateMode("Contest", STRIMERLCONNECT_MODE_CONTEST, 6, MODE_COLORS_MODE_SPECIFIC); - Contest.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; - modes.push_back(Contest); - - mode CrossOver = CreateMode("Cross Over", STRIMERLCONNECT_MODE_CROSSOVER, 6, MODE_COLORS_MODE_SPECIFIC); - CrossOver.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; - modes.push_back(CrossOver); - - mode BulletStack = CreateMode("Bullet Stack", STRIMERLCONNECT_MODE_BULLETSTACK, 0, MODE_COLORS_NONE); - BulletStack.flags |= MODE_FLAG_HAS_DIRECTION_LR; - modes.push_back(BulletStack); - - mode Twinkle = CreateMode("Twinkle", STRIMERLCONNECT_MODE_TWINKLE, 0, MODE_COLORS_NONE); - modes.push_back(Twinkle); - - mode Parallel = CreateMode("Parallel", STRIMERLCONNECT_MODE_PARALLEL, 6, MODE_COLORS_MODE_SPECIFIC); - Parallel.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; - modes.push_back(Parallel); - - mode ShockWave = CreateMode("Shock Wave", STRIMERLCONNECT_MODE_SHOCKWAVE, 6, MODE_COLORS_MODE_SPECIFIC); - ShockWave.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; - modes.push_back(ShockWave); - - mode Ripple = CreateMode("Ripple", STRIMERLCONNECT_MODE_RIPPLE, 6, MODE_COLORS_MODE_SPECIFIC); - Ripple.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - modes.push_back(Ripple); - - mode Voice = CreateMode("Voice", STRIMERLCONNECT_MODE_VOICE, 6, MODE_COLORS_MODE_SPECIFIC); - Voice.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - modes.push_back(Voice); - - mode Drizzling = CreateMode("Drizzling", STRIMERLCONNECT_MODE_DRIZZLING, 6, MODE_COLORS_MODE_SPECIFIC); - Drizzling.flags |= MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; - modes.push_back(Drizzling); - - Init_Controller(); - SetupZones(); -} - -RGBController_StrimerLConnect::~RGBController_StrimerLConnect() -{ - delete controller; -} - -void RGBController_StrimerLConnect::Init_Controller() -{ - const uint8_t zone_split = STRIMERLCONNECT_STRIP_COUNT / 2; - - /*-------------------------------------------------*\ - | Create the device's controllable zones | - \*-------------------------------------------------*/ - for(std::size_t zone_idx = 0; zone_idx < zone_split; zone_idx++) - { - zone new_zone; - new_zone.name = "24 Pin ATX Strip "; - new_zone.name.append(std::to_string(zone_idx)); - new_zone.type = ZONE_TYPE_LINEAR; - new_zone.leds_min = 20; - new_zone.leds_max = 20; - new_zone.leds_count = new_zone.leds_max; - new_zone.matrix_map = NULL; - zones.push_back(new_zone); - } - - for(std::size_t zone_idx = zone_split; zone_idx < STRIMERLCONNECT_STRIP_COUNT; zone_idx++) - { - zone new_zone; - new_zone.name = "8 Pin GPU Strip "; - new_zone.name.append(std::to_string(zone_idx - zone_split)); - new_zone.type = ZONE_TYPE_LINEAR; - new_zone.leds_min = 27; - new_zone.leds_max = 27; - new_zone.leds_count = new_zone.leds_max; - new_zone.matrix_map = NULL; - zones.push_back(new_zone); - } -} - -void RGBController_StrimerLConnect::SetupZones() -{ - /*-------------------------------------------------*\ - | Clear any existing color/LED configuration | - \*-------------------------------------------------*/ - leds.clear(); - colors.clear(); - - /*---------------------------------------------------------*\ - | Set up zones | - \*---------------------------------------------------------*/ - for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) - { - for(unsigned int lp_idx = 0; lp_idx < zones[zone_idx].leds_count; lp_idx++) - { - led new_led; - - new_led.name = zones[zone_idx].name; - new_led.name.append(" LED " + std::to_string(lp_idx)); - - leds.push_back(new_led); - } - } - - SetupColors(); -} - -void RGBController_StrimerLConnect::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -bool RGBController_StrimerLConnect::TimeToSend() -{ - /*-----------------------------------------------------*\ - | Rate limit is 1000(ms) / wait_time in Frames Per Sec | - \*-----------------------------------------------------*/ - const uint8_t wait_time = 90; - - return (std::chrono::steady_clock::now() - last_commit_time) > std::chrono::milliseconds(wait_time); -} - -void RGBController_StrimerLConnect::DeviceUpdateLEDs() -{ - if(TimeToSend()) - { - - for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) - { - UpdateZoneLEDs(zone_idx); - } - - controller->SendApply(); - - /*-----------------------------------------------------*\ - | Update last commit time | - \*-----------------------------------------------------*/ - last_commit_time = std::chrono::steady_clock::now(); - } -} - -void RGBController_StrimerLConnect::UpdateZoneLEDs(int zone) -{ - mode current_mode = modes[active_mode]; - - controller->SetLedsDirect(zone, zones[zone].colors, zones[zone].leds_count); - controller->SetMode(current_mode.value, zone, current_mode.speed, current_mode.brightness, current_mode.direction, false); -} - -void RGBController_StrimerLConnect::UpdateSingleLED(int led) -{ - UpdateZoneLEDs(GetLED_Zone(led)); - controller->SendApply(); -} - -void RGBController_StrimerLConnect::DeviceUpdateMode() -{ - if(TimeToSend()) - { - mode current_mode = modes[active_mode]; - - if(current_mode.color_mode == MODE_COLORS_PER_LED) - { - return; - } - - bool random_colours = (modes[active_mode].color_mode == MODE_COLORS_RANDOM); - - if(current_mode.color_mode == MODE_COLORS_NONE) - { - for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) - { - controller->SetMode(current_mode.value, zone_idx, current_mode.speed, current_mode.brightness, current_mode.direction, random_colours); - } - } - else - { - for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) - { - controller->SetLedsDirect(zone_idx, ¤t_mode.colors[0], current_mode.colors.size()); - controller->SetMode(current_mode.value, zone_idx, current_mode.speed, current_mode.brightness, current_mode.direction, random_colours); - } - } - - controller->SendApply(); - - /*-----------------------------------------------------*\ - | Update last commit time | - \*-----------------------------------------------------*/ - last_commit_time = std::chrono::steady_clock::now(); - } -} - -int RGBController_StrimerLConnect::GetLED_Zone(int led_idx) -{ - for(size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) - { - int zone_start = zones[zone_idx].start_idx; - int zone_end = zone_start + zones[zone_idx].leds_count - 1; - - if( zone_start <= led_idx && zone_end >= led_idx) - { - return(zone_idx); - } - } - - return -1; -} - -mode RGBController_StrimerLConnect::CreateMode(std::string name, int value, uint8_t colour_count, uint8_t colour_mode) -{ - mode new_mode; - new_mode.name = name; - new_mode.value = value; - new_mode.colors_min = colour_count; - new_mode.colors_max = colour_count; - new_mode.colors.resize(colour_count); - new_mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; - new_mode.brightness_min = STRIMERLCONNECT_BRIGHTNESS_MIN; - new_mode.brightness_max = STRIMERLCONNECT_BRIGHTNESS_MAX; - new_mode.brightness = STRIMERLCONNECT_BRIGHTNESS_MAX; - new_mode.speed_min = STRIMERLCONNECT_SPEED_SLOWEST; - new_mode.speed_max = STRIMERLCONNECT_SPEED_FASTEST; - new_mode.speed = STRIMERLCONNECT_SPEED_NORMAL; - new_mode.color_mode = colour_mode; - - return new_mode; -} diff --git a/Controllers/LianLiController/RGBController_StrimerLConnect.h b/Controllers/LianLiController/RGBController_StrimerLConnect.h deleted file mode 100644 index 81c44c12..00000000 --- a/Controllers/LianLiController/RGBController_StrimerLConnect.h +++ /dev/null @@ -1,41 +0,0 @@ -/*---------------------------------------------------------------------*\ -| RGBController_StrimerLConnect.h | -| | -| Driver for StrimerLConnect USB Controller | -| | -| Chris M (Dr_No) 03 Jul 2022 | -| | -\*---------------------------------------------------------------------*/ - -#pragma once -#include -#include "LogManager.h" -#include "RGBController.h" -#include "StrimerLConnectController.h" - -class RGBController_StrimerLConnect : public RGBController -{ -public: - RGBController_StrimerLConnect(StrimerLConnectController* controller_ptr); - ~RGBController_StrimerLConnect(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - void Init_Controller(); - int GetDeviceMode(); - int GetLED_Zone(int led_idx); - - mode CreateMode(std::string name, int value, uint8_t colour_count, uint8_t colour_mode); - bool TimeToSend(); - - StrimerLConnectController* controller; - std::chrono::time_point last_commit_time; -}; diff --git a/Controllers/LianLiController/StrimerLConnectController.cpp b/Controllers/LianLiController/StrimerLConnectController.cpp deleted file mode 100644 index 9c918733..00000000 --- a/Controllers/LianLiController/StrimerLConnectController.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/*---------------------------------------------------------------------*\ -| StrimerLConnectController.cpp | -| | -| Driver for StrimerLConnect USB Controller | -| | -| Chris M (Dr_No) 03 Jul 2022 | -| | -\*---------------------------------------------------------------------*/ - -#include "StrimerLConnectController.h" - -static uint8_t speed_data[5] = -{ - 0x02, 0x01, 0x00, 0xFE, 0xFF /* Slow to fast */ -}; - -static uint8_t brightness_data[5] = -{ - 0x08, 0x03, 0x02, 0x01, 0x00 /* 0%, 25%, 50%, 75%, 100% */ -}; - -StrimerLConnectController::StrimerLConnectController(hid_device* dev_handle, const char* path) -{ - const uint8_t sz = HID_MAX_STR; - wchar_t tmp[sz]; - - dev = dev_handle; - location = path; - - hid_get_manufacturer_string(dev, tmp, sz); - std::wstring wName = std::wstring(tmp); - device_name = std::string(wName.begin(), wName.end()); - - hid_get_product_string(dev, tmp, sz); - wName = std::wstring(tmp); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); -} - -StrimerLConnectController::~StrimerLConnectController() -{ - hid_close(dev); -} - -std::string StrimerLConnectController::GetDeviceName() -{ - return device_name; -} - -std::string StrimerLConnectController::GetSerial() -{ - const uint8_t sz = HID_MAX_STR; - wchar_t tmp[sz]; - - int ret = hid_get_serial_number_string(dev, tmp, sz); - - if (ret != 0) - { - LOG_DEBUG("[%s] Get HID Serial string failed", device_name.c_str()); - return(""); - } - - std::wstring w_tmp = std::wstring(tmp); - std::string serial = std::string(w_tmp.begin(), w_tmp.end()); - - return serial; -} - -std::string StrimerLConnectController::GetLocation() -{ - return("HID: " + location); -} - -void StrimerLConnectController::SendApply() -{ - uint8_t buffer[STRIMERLCONNECT_PACKET_SIZE] = { STRIMERLCONNECT_REPORT_ID, 0x2C, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00 }; - - hid_write(dev, buffer, STRIMERLCONNECT_PACKET_SIZE); -} - -void StrimerLConnectController::SetMode(uint8_t mode, uint8_t zone, uint8_t speed, uint8_t brightness, uint8_t direction, bool /*random_colours*/) -{ - uint8_t buffer[STRIMERLCONNECT_PACKET_SIZE] = { STRIMERLCONNECT_REPORT_ID, STRIMERLCONNECT_MODE_COMMAND, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - buffer[STRIMERLCONNECT_COMMAND_BYTE] |= zone; - - buffer[STRIMERLCONNECT_DATA_BYTE] = mode; - buffer[STRIMERLCONNECT_SPEED_BYTE] = speed_data[speed]; - buffer[STRIMERLCONNECT_DIRECTION_BYTE] = (direction == 0) ? 1 : 0; - buffer[STRIMERLCONNECT_BRIGHTNESS_BYTE] = brightness_data[brightness]; - - hid_write(dev, buffer, STRIMERLCONNECT_PACKET_SIZE); -} - -void StrimerLConnectController::SetLedsDirect(uint8_t zone, RGBColor * led_colours, uint8_t led_count) -{ - uint8_t buffer[STRIMERLCONNECT_PACKET_SIZE] = { STRIMERLCONNECT_REPORT_ID, STRIMERLCONNECT_COLOUR_COMMAND, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - buffer[STRIMERLCONNECT_COMMAND_BYTE] |= zone; - - for(size_t i = 0; i < led_count; i++) - { - uint8_t offset = (3 * i) + STRIMERLCONNECT_DATA_BYTE; - - buffer[offset] = RGBGetRValue(led_colours[i]); - buffer[offset + 1] = RGBGetBValue(led_colours[i]); - buffer[offset + 2] = RGBGetGValue(led_colours[i]); - } - - hid_write(dev, buffer, STRIMERLCONNECT_PACKET_SIZE); -} diff --git a/Controllers/LianLiController/StrimerLConnectController.h b/Controllers/LianLiController/StrimerLConnectController.h deleted file mode 100644 index f6e7a239..00000000 --- a/Controllers/LianLiController/StrimerLConnectController.h +++ /dev/null @@ -1,93 +0,0 @@ -/*---------------------------------------------------------------------*\ -| StrimerLConnectController.h | -| | -| Driver for StrimerLConnect USB Controller | -| | -| Chris M (Dr_No) 03 Jul 2022 | -| | -\*---------------------------------------------------------------------*/ - -#include -#include -#include "LogManager.h" -#include "RGBController.h" - -#pragma once - -#define HID_MAX_STR 255 -#define STRIMERLCONNECT_PACKET_SIZE 255 //Buffer requires a prepended ReportID hence + 1 - -#define STRIMERLCONNECT_BRIGHTNESS_MIN 0 //Brightness indexes not values -#define STRIMERLCONNECT_BRIGHTNESS_MAX 4 -#define STRIMERLCONNECT_STRIP_COUNT 12 - -enum -{ - STRIMERLCONNECT_MODE_OFF = 0x00, //Turn off - All leds off - STRIMERLCONNECT_MODE_DIRECT = 0x01, //Direct Led Control - Independently set LEDs in zone - STRIMERLCONNECT_MODE_BREATHING = 0x02, //Breathing Mode - Fades between fully off and fully on. - STRIMERLCONNECT_MODE_FLASHING = 0x03, //Flashing Mode - Abruptly changing between fully off and fully on. - STRIMERLCONNECT_MODE_RAINBOWMORPH = 0x04, //Rainbow Morph Mode - STRIMERLCONNECT_MODE_RAINBOW = 0x05, //Rainbow Wave Mode - Cycle thru the color spectrum as a wave across all LEDs - STRIMERLCONNECT_MODE_BREATHCYCLE = 0x06, //Spectrum Cycle Mode - Cycles through the color spectrum on all lights on the device - - STRIMERLCONNECT_MODE_SNOOKER = 0x19, //Snooker Mode - STRIMERLCONNECT_MODE_MIXING = 0x1A, //Mixing Mode - STRIMERLCONNECT_MODE_PINGPONG = 0x1B, //Ping Pong Mode - STRIMERLCONNECT_MODE_RUNWAY = 0x1C, //Runway Mode - STRIMERLCONNECT_MODE_PAINTING = 0x1D, //Painting Mode - STRIMERLCONNECT_MODE_TIDE = 0x1E, //Tide Mode - STRIMERLCONNECT_MODE_BLOWUP = 0x1F, //Blow Up Mode - STRIMERLCONNECT_MODE_METEOR = 0x20, //Meteor Mode - - STRIMERLCONNECT_MODE_SHOCKWAVE = 0x21, //Shock Wave Mode - STRIMERLCONNECT_MODE_RIPPLE = 0x22, //Ripple Mode - STRIMERLCONNECT_MODE_VOICE = 0x23, //Voice Mode - STRIMERLCONNECT_MODE_BULLETSTACK = 0x24, //Bullet Stack Mode - STRIMERLCONNECT_MODE_DRIZZLING = 0x25, //Drizzling Mode - STRIMERLCONNECT_MODE_FADEOUT = 0x26, //Fade Out Mode - STRIMERLCONNECT_MODE_COLORTRANSFER = 0x27, //Color Transfer Mode - STRIMERLCONNECT_MODE_CROSSOVER = 0x28, //Cross Over Mode - STRIMERLCONNECT_MODE_TWINKLE = 0x29, //Twinkle Mode - STRIMERLCONNECT_MODE_CONTEST = 0x2A, //Contest Mode - STRIMERLCONNECT_MODE_PARALLEL = 0x2B, //Parallel Mode -}; - -enum -{ - STRIMERLCONNECT_COMMAND_BYTE = 1, - STRIMERLCONNECT_DATA_BYTE = 2, - STRIMERLCONNECT_SPEED_BYTE = 3, - STRIMERLCONNECT_DIRECTION_BYTE = 4, - STRIMERLCONNECT_BRIGHTNESS_BYTE = 5, - - STRIMERLCONNECT_MODE_COMMAND = 0x10, - STRIMERLCONNECT_COLOUR_COMMAND = 0x30, - STRIMERLCONNECT_REPORT_ID = 0xE0, -}; - -enum -{ - STRIMERLCONNECT_SPEED_SLOWEST = 0, - STRIMERLCONNECT_SPEED_NORMAL = 2, - STRIMERLCONNECT_SPEED_FASTEST = 4, -}; - -class StrimerLConnectController -{ -public: - StrimerLConnectController(hid_device* dev_handle, const char* path); - ~StrimerLConnectController(); - - std::string GetDeviceName(); - std::string GetSerial(); - std::string GetLocation(); - - void SendApply(); - void SetMode(uint8_t mode, uint8_t zone, uint8_t speed, uint8_t brightness, uint8_t direction, bool random_colours); - void SetLedsDirect(uint8_t zone, RGBColor *led_colours, uint8_t led_count); -private: - std::string device_name; - std::string location; - hid_device* dev; -}; diff --git a/Controllers/LightSaltController/LightSaltController.cpp b/Controllers/LightSaltController/LightSaltController.cpp new file mode 100644 index 00000000..d21be8fd --- /dev/null +++ b/Controllers/LightSaltController/LightSaltController.cpp @@ -0,0 +1,311 @@ +/*---------------------------------------------------------*\ +| LightSaltController.cpp | +| | +| Driver for LightSalt Peripherals | +| | +| James Buren (braewoods) 23 Jul 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "LightSaltController.h" +#include "StringUtils.h" + +static const int mode_map[LIGHTSALT_MODE_MAXIMUM][6] = +{ + {0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, + {0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, + {0x0400, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, + {0x0700, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, + {0x0A00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, + {0x0D00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, + {0x0E00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, + {0x0F00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, + {0x1100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, + {0x0000, 0x0000, 0x0000, 0x0000, 0x3301, 0x3302}, + {0x3402, 0x3401, 0x0000, 0x0000, 0x0000, 0x0000}, + {0x3502, 0x3501, 0x0000, 0x0000, 0x0000, 0x0000}, + {0x3602, 0x3601, 0x0000, 0x0000, 0x0000, 0x0000}, + {0x3802, 0x3801, 0x0000, 0x0000, 0x0000, 0x0000}, + {0x0000, 0x0000, 0x3901, 0x3902, 0x0000, 0x0000}, + {0x0000, 0x0000, 0x3A01, 0x3A02, 0x0000, 0x0000}, + {0x0000, 0x0000, 0x0000, 0x0000, 0x3702, 0x3701}, + {0x3B02, 0x3B01, 0x0000, 0x0000, 0x0000, 0x0000} +}; + +LightSaltController::LightSaltController(hid_device* dev_handle, const hid_device_info& info) +{ + wchar_t usb_string[128]; + + dev = dev_handle; + device_location = info.path; + + if(hid_get_manufacturer_string(dev, usb_string, 128) == 0) + { + manufacturer = StringUtils::wstring_to_string(usb_string); + } + else + { + manufacturer = ""; + } + + if(hid_get_product_string(dev, usb_string, 128) == 0) + { + product = StringUtils::wstring_to_string(usb_string); + } + else + { + product = ""; + } + + if(strstr(manufacturer.c_str(), "Light&Salt") && strstr(product.c_str(), "Light&Salt")) + { + QueryDeviceModel(); + QueryDeviceClass(); + SetDeviceType(); + } + else + { + device_model = ""; + device_class = ""; + firmware_version = ""; + device_type = LIGHTSALT_TYPE_MAXIMUM; + } +} + +LightSaltController::~LightSaltController() +{ + hid_close(dev); +} + +std::string LightSaltController::GetDeviceLocation() +{ + return("HID: " + device_location); +} + +std::string LightSaltController::GetSerial() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string LightSaltController::GetManufacturer() +{ + return(manufacturer); +} + +std::string LightSaltController::GetProduct() +{ + return(product); +} + +std::string LightSaltController::GetDeviceModel() +{ + return(device_model); +} + +std::string LightSaltController::GetDeviceClass() +{ + return(device_class); +} + +std::string LightSaltController::GetFirmwareVersion() +{ + return(firmware_version); +} + +int LightSaltController::GetDeviceType() +{ + return(device_type); +} + +void LightSaltController::SetColors(RGBColor* colors, int sets, int rows, int columns) +{ + uint8_t write_buffer[LIGHTSALT_WRITE_LENGTH]; + int color_idx = 0; + + write_buffer[0] = 0x00; + + for(int set_idx = 0; set_idx < sets; set_idx++) + { + write_buffer[1] = 0x03 + set_idx; + + for(int row_idx = 0; row_idx < rows; row_idx++) + { + int write_idx = 2; + + write_buffer[write_idx++] = 0x01 + row_idx * columns; + + for(int column_idx = 0; column_idx < columns; column_idx++) + { + RGBColor color = colors[color_idx++]; + write_buffer[write_idx++] = RGBGetRValue(color); + write_buffer[write_idx++] = RGBGetGValue(color); + write_buffer[write_idx++] = RGBGetBValue(color); + } + + hid_write(dev, write_buffer, sizeof(write_buffer)); + } + } +} + +void LightSaltController::ApplyColors(int sets) +{ + uint8_t write_buffer[LIGHTSALT_WRITE_LENGTH]; + int write_idx = 1; + + memset(write_buffer, 0x00, sizeof(write_buffer)); + write_buffer[write_idx++] = 0xFE; + write_buffer[write_idx++] = 0x01; + + for(int set_idx = 0; set_idx < sets; set_idx++) + { + write_buffer[write_idx++] = 0x03 + set_idx; + } + + hid_write(dev, write_buffer, sizeof(write_buffer)); +} + +void LightSaltController::SaveColors(int sets) +{ + uint8_t write_buffer[LIGHTSALT_WRITE_LENGTH]; + int write_idx = 1; + + memset(write_buffer, 0x00, sizeof(write_buffer)); + write_buffer[write_idx++] = 0xFE; + write_buffer[write_idx++] = 0xF0; + + for(int set_idx = 0; set_idx < sets; set_idx++) + { + write_buffer[write_idx++] = 0x03 + set_idx; + } + + hid_write(dev, write_buffer, sizeof(write_buffer)); +} + +void LightSaltController::SetMode(int mode, int direction, int speed) +{ + uint8_t write_buffer[LIGHTSALT_WRITE_LENGTH]; + int actual_mode = mode_map[mode][direction]; + + memset(write_buffer, 0x00, sizeof(write_buffer)); + write_buffer[1] = 0xFE; + write_buffer[2] = 0x03; + write_buffer[3] = (actual_mode & 0xFF00) >> 8; + write_buffer[4] = (actual_mode & 0x00FF) >> 0; + write_buffer[5] = speed; + + hid_write(dev, write_buffer, sizeof(write_buffer)); +} + +void LightSaltController::SetFilter(RGBColor color) +{ + uint8_t write_buffer[LIGHTSALT_WRITE_LENGTH]; + + memset(write_buffer, 0x00, sizeof(write_buffer)); + write_buffer[1] = 0xFE; + write_buffer[2] = 0x04; + write_buffer[3] = RGBGetRValue(color); + write_buffer[4] = RGBGetGValue(color); + write_buffer[5] = RGBGetBValue(color); + + hid_write(dev, write_buffer, sizeof(write_buffer)); +} + +void LightSaltController::SetBrightness(uint8_t brightness) +{ + uint8_t write_buffer[LIGHTSALT_WRITE_LENGTH]; + + memset(write_buffer, 0x00, sizeof(write_buffer)); + write_buffer[1] = 0xFE; + write_buffer[2] = 0x05; + write_buffer[3] = brightness; + + hid_write(dev, write_buffer, sizeof(write_buffer)); +} + +void LightSaltController::QueryDeviceModel() +{ + uint8_t write_buffer[LIGHTSALT_WRITE_LENGTH]; + uint8_t read_buffer[LIGHTSALT_READ_LENGTH]; + + memset(write_buffer, 0x00, sizeof(write_buffer)); + write_buffer[1] = 0xFE; + write_buffer[2] = 0xF5; + write_buffer[3] = 0x06; + + if(hid_write(dev, write_buffer, sizeof(write_buffer)) != sizeof(write_buffer)) + { + device_model = ""; + return; + } + + if(hid_read_timeout(dev, read_buffer, sizeof(read_buffer), 100) != sizeof(read_buffer)) + { + device_model = ""; + return; + } + + device_model = (char *)(read_buffer + 3); +} + +void LightSaltController::QueryDeviceClass() +{ + uint8_t write_buffer[LIGHTSALT_WRITE_LENGTH]; + uint8_t read_buffer[LIGHTSALT_READ_LENGTH]; + + memset(write_buffer, 0x00, sizeof(write_buffer)); + write_buffer[1] = 0xFE; + write_buffer[2] = 0xFF; + + if(hid_write(dev, write_buffer, sizeof(write_buffer)) != sizeof(write_buffer)) + { + device_class = ""; + firmware_version = ""; + return; + } + + if(hid_read_timeout(dev, read_buffer, sizeof(read_buffer), 100) != sizeof(read_buffer)) + { + device_class = ""; + firmware_version = ""; + return; + } + + device_class = (char *)(read_buffer ); + firmware_version = (char *)(read_buffer + device_class.size() + 1); +} + +void LightSaltController::SetDeviceType() +{ + struct device_class_table + { + std::string device_class; + int device_type; + }; + static const device_class_table table[] = + { + {"Light&Salt_keyboard1", LIGHTSALT_TYPE_KEYBOARD}, + {"Light&Salt_KEY_PAD", LIGHTSALT_TYPE_KEYPAD } + }; + + device_type = LIGHTSALT_TYPE_MAXIMUM; + + for(const device_class_table& match : table) + { + if(match.device_class == device_class) + { + device_type = match.device_type; + break; + } + } +} diff --git a/Controllers/LightSaltController/LightSaltController.h b/Controllers/LightSaltController/LightSaltController.h new file mode 100644 index 00000000..d88b6458 --- /dev/null +++ b/Controllers/LightSaltController/LightSaltController.h @@ -0,0 +1,109 @@ +/*---------------------------------------------------------*\ +| LightSaltController.h | +| | +| Driver for LightSalt Peripherals | +| | +| James Buren (braewoods) 23 Jul 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define LIGHTSALT_PACKET_LENGTH 32 +#define LIGHTSALT_WRITE_LENGTH (LIGHTSALT_PACKET_LENGTH + 1) +#define LIGHTSALT_READ_LENGTH (LIGHTSALT_PACKET_LENGTH) + +enum +{ + LIGHTSALT_TYPE_KEYBOARD, + LIGHTSALT_TYPE_KEYPAD, + LIGHTSALT_TYPE_MAXIMUM +}; + +enum +{ + LIGHTSALT_MODE_CUSTOM, + LIGHTSALT_MODE_POINT, + LIGHTSALT_MODE_AREA, + LIGHTSALT_MODE_COLLAPSE, + LIGHTSALT_MODE_EXPAND, + LIGHTSALT_MODE_EXPLODE, + LIGHTSALT_MODE_DART, + LIGHTSALT_MODE_FLAME, + LIGHTSALT_MODE_LASER, + LIGHTSALT_MODE_BREATHING, + LIGHTSALT_MODE_TRICOLOR_RADAR, + LIGHTSALT_MODE_WHEEL_1, + LIGHTSALT_MODE_WHEEL_2, + LIGHTSALT_MODE_WAVE_1, + LIGHTSALT_MODE_WAVE_2, + LIGHTSALT_MODE_WAVE_3, + LIGHTSALT_MODE_RAINBOW_1, + LIGHTSALT_MODE_RAINBOW_2, + LIGHTSALT_MODE_MAXIMUM +}; + +enum +{ + LIGHTSALT_SETS_MAX = 4, + LIGHTSALT_ROWS_MAX = 9, + LIGHTSALT_COLUMNS_MAX = 10 +}; + +enum +{ + LIGHTSALT_SPEED_MINIMUM = 0x01, + LIGHTSALT_SPEED_MAXIMUM = 0x32, + LIGHTSALT_SPEED_DEFAULT = 0x19 +}; + +enum +{ + LIGHTSALT_BRIGHTNESS_MINIMUM = 0x00, + LIGHTSALT_BRIGHTNESS_MAXIMUM = 0xFF, + LIGHTSALT_BRIGHTNESS_DEFAULT = 0x80 +}; + +class LightSaltController +{ +public: + LightSaltController(hid_device* dev_handle, const hid_device_info& info); + ~LightSaltController(); + + std::string GetDeviceLocation(); + std::string GetSerial(); + std::string GetManufacturer(); + std::string GetProduct(); + std::string GetDeviceModel(); + std::string GetDeviceClass(); + std::string GetFirmwareVersion(); + int GetDeviceType(); + + void SetColors(RGBColor* colors, int sets, int rows, int columns); + void ApplyColors(int sets); + void SaveColors(int sets); + void SetMode(int mode, int direction, int speed); + void SetFilter(RGBColor color); + void SetBrightness(uint8_t brightness); + +private: + hid_device* dev; + + std::string device_location; + std::string manufacturer; + std::string product; + std::string device_model; + std::string device_class; + std::string firmware_version; + int device_type; + + void QueryDeviceModel(); + void QueryDeviceClass(); + void SetDeviceType(); +}; diff --git a/Controllers/LightSaltController/LightSaltControllerDetect.cpp b/Controllers/LightSaltController/LightSaltControllerDetect.cpp new file mode 100644 index 00000000..fd40eaab --- /dev/null +++ b/Controllers/LightSaltController/LightSaltControllerDetect.cpp @@ -0,0 +1,52 @@ +/*---------------------------------------------------------*\ +| LightSaltControllerDetect.cpp | +| | +| Detector for LightSalt Peripherals | +| | +| James Buren (braewoods) 23 Jul 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "LightSaltController.h" +#include "RGBController_LightSaltKeyboard.h" +#include "RGBController_LightSaltKeypad.h" + +#define LIGHTSALT_VID 0x0483 +#define LIGHTSALT_PID 0x5750 + +void DetectLightSaltControllers(hid_device_info* info, const std::string &) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + LightSaltController* controller = new LightSaltController(dev, *info); + RGBController* rgb_controller = nullptr; + + switch(controller->GetDeviceType()) + { + case LIGHTSALT_TYPE_KEYBOARD: + rgb_controller = new RGBController_LightSaltKeyboard(controller); + break; + + case LIGHTSALT_TYPE_KEYPAD: + rgb_controller = new RGBController_LightSaltKeypad(controller); + break; + + default: + delete controller; + break; + } + + if(rgb_controller != nullptr) + { + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + } +} /* DetectLightSaltControllers() */ + +REGISTER_HID_DETECTOR_IPU("LightSalt Peripherals", DetectLightSaltControllers, LIGHTSALT_VID, LIGHTSALT_PID, 1, 1, 0); diff --git a/Controllers/LightSaltController/RGBController_LightSalt.cpp b/Controllers/LightSaltController/RGBController_LightSalt.cpp new file mode 100644 index 00000000..290df7d5 --- /dev/null +++ b/Controllers/LightSaltController/RGBController_LightSalt.cpp @@ -0,0 +1,452 @@ +/*---------------------------------------------------------*\ +| RGBController_LightSalt.cpp | +| | +| RGBController for LightSalt Peripherals | +| | +| James Buren (braewoods) 23 Jul 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RGBControllerKeyNames.h" +#include "RGBController_LightSalt.h" + +static RGBColor DeflectColor(bool deflection, RGBColor color) +{ + if(deflection) + { + int old_red = RGBGetRValue(color); + int old_grn = RGBGetGValue(color); + int old_blu = RGBGetBValue(color); + int new_red = old_red + ((255 - old_red) * 50 / 100); + int new_grn = old_grn + ((255 - old_grn) * 50 / 100); + int new_blu = old_blu + ((255 - old_blu) * 50 / 100); + return ToRGBColor(new_red, new_grn, new_blu); + } + else + { + return color; + } +} + +RGBController_LightSalt::~RGBController_LightSalt() +{ + /*---------------------------------------------------------*\ + | Delete the matrix map | + \*---------------------------------------------------------*/ + for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++) + { + if(zones[zone_index].matrix_map != nullptr) + { + delete zones[zone_index].matrix_map; + } + } + + delete controller; +} + +void RGBController_LightSalt::SetupData(LightSaltController* controller_ptr) +{ + controller = controller_ptr; + name = "LightSalt " + table.device.name; + vendor = "LightSalt"; + type = table.device.type; + description = "LightSalt " + table.device.name + " (" + controller->GetDeviceModel() + ")"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerial(); + version = controller->GetFirmwareVersion(); +} + +void RGBController_LightSalt::SetupModes() +{ + { + mode mode; + mode.name = "Custom"; + mode.value = LIGHTSALT_MODE_CUSTOM; + mode.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_PER_LED; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Reactive Point"; + mode.value = LIGHTSALT_MODE_POINT; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Reactive Area"; + mode.value = LIGHTSALT_MODE_AREA; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Reactive Collapse"; + mode.value = LIGHTSALT_MODE_COLLAPSE; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Reactive Expand"; + mode.value = LIGHTSALT_MODE_EXPAND; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Reactive Explode"; + mode.value = LIGHTSALT_MODE_EXPLODE; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Reactive Dart"; + mode.value = LIGHTSALT_MODE_DART; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Reactive Flame"; + mode.value = LIGHTSALT_MODE_FLAME; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Reactive Laser"; + mode.value = LIGHTSALT_MODE_LASER; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Breathing"; + mode.value = LIGHTSALT_MODE_BREATHING; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_HV | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.direction = MODE_DIRECTION_HORIZONTAL; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Tricolor Radar"; + mode.value = LIGHTSALT_MODE_TRICOLOR_RADAR; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.direction = MODE_DIRECTION_LEFT; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Wheel 1"; + mode.value = LIGHTSALT_MODE_WHEEL_1; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.direction = MODE_DIRECTION_LEFT; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Wheel 2"; + mode.value = LIGHTSALT_MODE_WHEEL_2; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.direction = MODE_DIRECTION_LEFT; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Wave 1"; + mode.value = LIGHTSALT_MODE_WAVE_1; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.direction = MODE_DIRECTION_LEFT; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Wave 2"; + mode.value = LIGHTSALT_MODE_WAVE_2; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.direction = MODE_DIRECTION_UP; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Wave 3"; + mode.value = LIGHTSALT_MODE_WAVE_3; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.direction = MODE_DIRECTION_UP; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Rainbow 1"; + mode.value = LIGHTSALT_MODE_RAINBOW_1; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_HV | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.direction = MODE_DIRECTION_HORIZONTAL; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } + + { + mode mode; + mode.name = "Rainbow 2"; + mode.value = LIGHTSALT_MODE_RAINBOW_2; + mode.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + mode.speed_min = LIGHTSALT_SPEED_MINIMUM; + mode.speed_max = LIGHTSALT_SPEED_MAXIMUM; + mode.speed = LIGHTSALT_SPEED_DEFAULT; + mode.direction = MODE_DIRECTION_LEFT; + mode.brightness_min = LIGHTSALT_BRIGHTNESS_MINIMUM; + mode.brightness_max = LIGHTSALT_BRIGHTNESS_MAXIMUM; + mode.brightness = LIGHTSALT_BRIGHTNESS_DEFAULT; + mode.color_mode = MODE_COLORS_NONE; + modes.push_back(mode); + } +} + +void RGBController_LightSalt::SetupZones() +{ + { + zone zone; + zone.name = table.device.name; + zone.type = ZONE_TYPE_MATRIX; + zone.leds_min = table.led.count; + zone.leds_max = table.led.count; + zone.leds_count = table.led.count; + zone.matrix_map = new matrix_map_type; + zone.matrix_map->height = table.map.height; + zone.matrix_map->width = table.map.width; + zone.matrix_map->map = table.map.matrix; + zones.push_back(zone); + } + + for(int led_idx = 0; led_idx < table.led.count; led_idx++) + { + led led; + led.name = table.led.names[led_idx]; + leds.push_back(led); + } + + { + zone zone; + zone.name = "Color Filter"; + zone.type = ZONE_TYPE_SINGLE; + zone.leds_min = 1; + zone.leds_max = 1; + zone.leds_count = 1; + zone.matrix_map = NULL; + zones.push_back(zone); + } + + { + led led; + led.name = "Color Filter"; + leds.push_back(led); + } + + SetupColors(); + + colors[colors.size() - 1] = ToRGBColor(0xFF, 0xFF, 0xFF); +} + +void RGBController_LightSalt::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_LightSalt::DeviceUpdateColors(bool save) +{ + int sets = table.led.sets; + int rows = table.led.rows; + int columns = table.led.columns; + + RGBColor colors_data[LIGHTSALT_SETS_MAX][LIGHTSALT_ROWS_MAX][LIGHTSALT_COLUMNS_MAX]; + memset(colors_data, 0x00, sizeof(colors_data)); + + for(int led_idx = 0; led_idx < table.led.count; led_idx++) + { + int index = table.led.indices[led_idx]; + int deflection = table.led.deflections[led_idx]; + int row = index / columns; + int column = index % columns; + RGBColor color = colors[led_idx]; + + for(int set_idx = 0; set_idx < sets; set_idx++) + { + colors_data[set_idx][row][column] = DeflectColor(deflection & (1 << set_idx), color); + } + } + + controller->SetFilter(colors[colors.size() - 1]); + controller->SetColors((RGBColor*)colors_data, sets, rows, columns); + controller->ApplyColors(sets); + if(save) + { + controller->SaveColors(sets); + } +} + +void RGBController_LightSalt::DeviceUpdateLEDs() +{ + DeviceUpdateColors(false); +} + +void RGBController_LightSalt::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_LightSalt::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_LightSalt::DeviceUpdateMode() +{ + const mode& mode = modes[active_mode]; + + controller->SetBrightness(mode.brightness); + std::this_thread::sleep_for(std::chrono::milliseconds(25)); + controller->SetMode(mode.value, mode.direction, mode.speed); +} + +void RGBController_LightSalt::DeviceSaveMode() +{ + DeviceUpdateColors(true); +} diff --git a/Controllers/LightSaltController/RGBController_LightSalt.h b/Controllers/LightSaltController/RGBController_LightSalt.h new file mode 100644 index 00000000..55b8461a --- /dev/null +++ b/Controllers/LightSaltController/RGBController_LightSalt.h @@ -0,0 +1,62 @@ +/*---------------------------------------------------------*\ +| RGBController_LightSalt.h | +| | +| RGBController for LightSalt Peripherals | +| | +| James Buren (braewoods) 23 Jul 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LightSaltController.h" + +class RGBController_LightSalt : public RGBController +{ +public: + ~RGBController_LightSalt(); + + void SetupData(LightSaltController* controller_ptr); + void SetupModes(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateColors(bool save); + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +protected: + struct + { + struct + { + std::string name; + int type; + } device; + struct + { + int sets; + int rows; + int columns; + int count; + char const * const * names; + const int* indices; + const int* deflections; + } led; + struct + { + unsigned int height; + unsigned int width; + unsigned int* matrix; + } map; + } table; + LightSaltController* controller; +}; diff --git a/Controllers/LightSaltController/RGBController_LightSaltKeyboard.cpp b/Controllers/LightSaltController/RGBController_LightSaltKeyboard.cpp new file mode 100644 index 00000000..86a68236 --- /dev/null +++ b/Controllers/LightSaltController/RGBController_LightSaltKeyboard.cpp @@ -0,0 +1,207 @@ +/*---------------------------------------------------------*\ +| RGBController_LightSaltKeyboard.cpp | +| | +| RGBController for LightSalt Keyboard | +| | +| James Buren (braewoods) 23 Jul 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBControllerKeyNames.h" +#include "RGBController_LightSaltKeyboard.h" + +// 0xFFFFFFFF indicates an unused entry in matrix +#define NA 0xFFFFFFFF + +enum +{ + LED_SETS = 4, + LED_ROWS = 9, + LED_COLUMNS = 10, + LED_COUNT = 83, + MAP_HEIGHT = 6, + MAP_WIDTH = 15, +}; + +static char const * const led_names[LED_COUNT] = +{ + /* Row 1 */ + KEY_EN_ESCAPE, + KEY_EN_F1, + KEY_EN_F2, + KEY_EN_F3, + KEY_EN_F4, + KEY_EN_F5, + KEY_EN_F6, + KEY_EN_F7, + KEY_EN_F8, + KEY_EN_F9, + KEY_EN_F10, + KEY_EN_F11, + KEY_EN_F12, + + /* Row 2 */ + KEY_EN_BACK_TICK, + KEY_EN_1, + KEY_EN_2, + KEY_EN_3, + KEY_EN_4, + KEY_EN_5, + KEY_EN_6, + KEY_EN_7, + KEY_EN_8, + KEY_EN_9, + KEY_EN_0, + KEY_EN_MINUS, + KEY_EN_EQUALS, + KEY_EN_BACKSPACE, + KEY_EN_DELETE, + + /* Row 3 */ + KEY_EN_TAB, + KEY_EN_Q, + KEY_EN_W, + KEY_EN_E, + KEY_EN_R, + KEY_EN_T, + KEY_EN_Y, + KEY_EN_U, + KEY_EN_I, + KEY_EN_O, + KEY_EN_P, + KEY_EN_LEFT_BRACKET, + KEY_EN_RIGHT_BRACKET, + KEY_EN_ANSI_BACK_SLASH, + KEY_EN_PRINT_SCREEN, + + /* Row 4 */ + KEY_EN_CAPS_LOCK, + KEY_EN_A, + KEY_EN_S, + KEY_EN_D, + KEY_EN_F, + KEY_EN_G, + KEY_EN_H, + KEY_EN_J, + KEY_EN_K, + KEY_EN_L, + KEY_EN_SEMICOLON, + KEY_EN_QUOTE, + KEY_EN_ANSI_ENTER, + + /* Row 5 */ + KEY_EN_LEFT_SHIFT, + KEY_EN_Z, + KEY_EN_X, + KEY_EN_C, + KEY_EN_V, + KEY_EN_B, + KEY_EN_N, + KEY_EN_M, + KEY_EN_COMMA, + KEY_EN_PERIOD, + KEY_EN_FORWARD_SLASH, + KEY_EN_RIGHT_SHIFT, + KEY_EN_UP_ARROW, + + /* Row 6 */ + KEY_EN_LEFT_CONTROL, + KEY_EN_LEFT_WINDOWS, + KEY_EN_LEFT_ALT, + KEY_EN_SPACE, + KEY_EN_SPACE, + KEY_EN_SPACE, + KEY_EN_SPACE, + KEY_EN_SPACE, + KEY_EN_RIGHT_ALT, + KEY_EN_RIGHT_FUNCTION, + KEY_EN_RIGHT_CONTROL, + KEY_EN_LEFT_ARROW, + KEY_EN_DOWN_ARROW, + KEY_EN_RIGHT_ARROW +}; + +static const int led_indices[LED_COUNT] = +{ + /* Row 1 */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + + /* Row 2 */ + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + + /* Row 3 */ + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + + /* Row 4 */ + 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, + + /* Row 5 */ + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 73, + + /* Row 6 */ + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 87, 88, 89 +}; + +static const int led_deflections[LED_COUNT] = +{ + /* Row 1 */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + + /* Row 2 */ + 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0x0, 0x0, + + /* Row 3 */ + 0x0, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0xA, 0xA, 0xA, 0x0, + + /* Row 4 */ + 0x0, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0xA, 0xA, 0x0, + + /* Row 5 */ + 0x0, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0x6, 0xA, 0xA, 0xA, 0x0, 0x0, + + /* Row 6 */ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 +}; + +static const unsigned int matrix_map[MAP_HEIGHT][MAP_WIDTH] = +{ + /* Row 1 */ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, NA, NA }, + + /* Row 2 */ + { 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 }, + + /* Row 3 */ + { 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42 }, + + /* Row 4 */ + { 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, NA, NA }, + + /* Row 5 */ + { 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, NA, 68, NA }, + + /* Row 6 */ + { 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, NA, 80, 81, 82 } +}; + +RGBController_LightSaltKeyboard::RGBController_LightSaltKeyboard(LightSaltController* controller_ptr) +{ + table.device.name = "Keyboard"; + table.device.type = DEVICE_TYPE_KEYBOARD; + table.led.sets = LED_SETS; + table.led.rows = LED_ROWS; + table.led.columns = LED_COLUMNS; + table.led.count = LED_COUNT; + table.led.names = led_names; + table.led.indices = led_indices; + table.led.deflections = led_deflections; + table.map.height = MAP_HEIGHT; + table.map.width = MAP_WIDTH; + table.map.matrix = (unsigned int *)matrix_map; + + SetupData(controller_ptr); + SetupModes(); + SetupZones(); +} diff --git a/Controllers/LightSaltController/RGBController_LightSaltKeyboard.h b/Controllers/LightSaltController/RGBController_LightSaltKeyboard.h new file mode 100644 index 00000000..9b111cbe --- /dev/null +++ b/Controllers/LightSaltController/RGBController_LightSaltKeyboard.h @@ -0,0 +1,20 @@ +/*---------------------------------------------------------*\ +| RGBController_LightSaltKeyboard.h | +| | +| RGBController for LightSalt Keyboard | +| | +| James Buren (braewoods) 23 Jul 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController_LightSalt.h" + +class RGBController_LightSaltKeyboard : public RGBController_LightSalt +{ +public: + RGBController_LightSaltKeyboard(LightSaltController* controller_ptr); +}; diff --git a/Controllers/LightSaltController/RGBController_LightSaltKeypad.cpp b/Controllers/LightSaltController/RGBController_LightSaltKeypad.cpp new file mode 100644 index 00000000..dae7f5cb --- /dev/null +++ b/Controllers/LightSaltController/RGBController_LightSaltKeypad.cpp @@ -0,0 +1,131 @@ +/*---------------------------------------------------------*\ +| RGBController_LightSaltKeypad.cpp | +| | +| RGBController for LightSalt Keypad | +| | +| James Buren (braewoods) 23 Jul 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBControllerKeyNames.h" +#include "RGBController_LightSaltKeypad.h" + +// 0xFFFFFFFF indicates an unused entry in matrix +#define NA 0xFFFFFFFF + +enum +{ + LED_SETS = 1, + LED_ROWS = 5, + LED_COLUMNS = 10, + LED_COUNT = 18, + MAP_HEIGHT = 5, + MAP_WIDTH = 4 +}; + +static char const * const led_names[LED_COUNT] = +{ + /* Row 1 */ + KEY_EN_TAB, + KEY_EN_NUMPAD_DIVIDE, + KEY_EN_NUMPAD_TIMES, + KEY_EN_BACKSPACE, + + /* Row 2 */ + KEY_EN_NUMPAD_7, + KEY_EN_NUMPAD_8, + KEY_EN_NUMPAD_9, + KEY_EN_NUMPAD_MINUS, + + /* Row 3 */ + KEY_EN_NUMPAD_4, + KEY_EN_NUMPAD_5, + KEY_EN_NUMPAD_6, + KEY_EN_PLUS, + + /* Row 4 */ + KEY_EN_NUMPAD_1, + KEY_EN_NUMPAD_2, + KEY_EN_NUMPAD_3, + + /* Row 5 */ + KEY_EN_NUMPAD_0, + KEY_EN_NUMPAD_PERIOD, + KEY_EN_NUMPAD_ENTER +}; + +static const int led_indices[LED_COUNT] = +{ + /* Row 1 */ + 0, 1, 2, 3, + + /* Row 2 */ + 4, 5, 6, 7, + + /* Row 3 */ + 8, 9, 10, 11, + + /* Row 4 */ + 12, 13, 14, + + /* Row 5 */ + 16, 17, 18 +}; + +static const int led_deflections[LED_COUNT] = +{ + /* Row 1 */ + 0x0, 0x0, 0x0, 0x0, + + /* Row 2 */ + 0x0, 0x0, 0x0, 0x0, + + /* Row 3 */ + 0x0, 0x0, 0x0, 0x0, + + /* Row 4 */ + 0x0, 0x0, 0x0, + + /* Row 5 */ + 0x0, 0x0, 0x0 +}; + +static const unsigned int matrix_map[MAP_HEIGHT][MAP_WIDTH] = +{ + /* Row 1 */ + { 0, 1 , 2, 3}, + + /* Row 2 */ + { 4, 5, 6, 7}, + + /* Row 3 */ + { 8, 9, 10, 11}, + + /* Row 4 */ + {12, 13, 14, NA}, + + /* Row 5 */ + {15, NA, 16, 17} +}; + +RGBController_LightSaltKeypad::RGBController_LightSaltKeypad(LightSaltController* controller_ptr) +{ + table.device.name = "Keypad"; + table.device.type = DEVICE_TYPE_KEYPAD; + table.led.sets = LED_SETS; + table.led.rows = LED_ROWS; + table.led.columns = LED_COLUMNS; + table.led.count = LED_COUNT; + table.led.names = led_names; + table.led.indices = led_indices; + table.led.deflections = led_deflections; + table.map.height = MAP_HEIGHT; + table.map.width = MAP_WIDTH; + table.map.matrix = (unsigned int *)matrix_map; + + SetupData(controller_ptr); + SetupModes(); + SetupZones(); +} diff --git a/Controllers/LightSaltController/RGBController_LightSaltKeypad.h b/Controllers/LightSaltController/RGBController_LightSaltKeypad.h new file mode 100644 index 00000000..73a48aa1 --- /dev/null +++ b/Controllers/LightSaltController/RGBController_LightSaltKeypad.h @@ -0,0 +1,20 @@ +/*---------------------------------------------------------*\ +| RGBController_LightSaltKeypad.h | +| | +| RGBController for LightSalt Keypad | +| | +| James Buren (braewoods) 23 Jul 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController_LightSalt.h" + +class RGBController_LightSaltKeypad : public RGBController_LightSalt +{ +public: + RGBController_LightSaltKeypad(LightSaltController* controller_ptr); +}; diff --git a/Controllers/LinuxLEDController/LinuxLEDController.cpp b/Controllers/LinuxLEDController/LinuxLEDController.cpp deleted file mode 100644 index b17ec17b..00000000 --- a/Controllers/LinuxLEDController/LinuxLEDController.cpp +++ /dev/null @@ -1,71 +0,0 @@ -#include "LinuxLEDController.h" - -LinuxLEDController::LinuxLEDController() -{ - -} - -LinuxLEDController::~LinuxLEDController() -{ - -} - -std::string LinuxLEDController::GetRedPath() -{ - return(led_r_path); -} - -std::string LinuxLEDController::GetGreenPath() -{ - return(led_g_path); -} - -std::string LinuxLEDController::GetBluePath() -{ - return(led_b_path); -} - -void LinuxLEDController::OpenRedPath(std::string red_path) -{ - led_r_path = red_path; - led_r_brightness.open(led_r_path + "brightness"); -} - -void LinuxLEDController::OpenGreenPath(std::string green_path) -{ - led_g_path = green_path; - led_g_brightness.open(led_g_path + "brightness"); -} - -void LinuxLEDController::OpenBluePath(std::string blue_path) -{ - led_b_path = blue_path; - led_b_brightness.open(led_b_path + "brightness"); -} - -void LinuxLEDController::SetRGB(unsigned char red, unsigned char grn, unsigned char blu) -{ - std::string brightness_str; - - /*-------------------------------------------------------------*\ - | My phone LED that I tested this on shuts down if you set zero | - \*-------------------------------------------------------------*/ - if(red == 0) red = 1; - if(grn == 0) grn = 1; - if(blu == 0) blu = 1; - - brightness_str = std::to_string((unsigned int)red); - - led_r_brightness.write(brightness_str.c_str(), brightness_str.length()); - led_r_brightness.flush(); - - brightness_str = std::to_string((unsigned int)grn); - - led_g_brightness.write(brightness_str.c_str(), brightness_str.length()); - led_g_brightness.flush(); - - brightness_str = std::to_string((unsigned int)blu); - - led_b_brightness.write(brightness_str.c_str(), brightness_str.length()); - led_b_brightness.flush(); -} diff --git a/Controllers/LinuxLEDController/LinuxLEDController.h b/Controllers/LinuxLEDController/LinuxLEDController.h deleted file mode 100644 index 53bdd7b7..00000000 --- a/Controllers/LinuxLEDController/LinuxLEDController.h +++ /dev/null @@ -1,28 +0,0 @@ - -#pragma once - -#include - -class LinuxLEDController -{ -public: - LinuxLEDController(); - ~LinuxLEDController(); - - std::string GetRedPath(); - std::string GetBluePath(); - std::string GetGreenPath(); - - void OpenRedPath(std::string red_path); - void OpenGreenPath(std::string green_path); - void OpenBluePath(std::string blue_path); - - void SetRGB(unsigned char red, unsigned char grn, unsigned char blu); -private: - std::string led_r_path; - std::string led_g_path; - std::string led_b_path; - std::ofstream led_r_brightness; - std::ofstream led_g_brightness; - std::ofstream led_b_brightness; -}; diff --git a/Controllers/LinuxLEDController/LinuxLEDControllerDetect.cpp b/Controllers/LinuxLEDController/LinuxLEDControllerDetect.cpp deleted file mode 100644 index eb488b86..00000000 --- a/Controllers/LinuxLEDController/LinuxLEDControllerDetect.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "Detector.h" -#include "LinuxLEDController.h" -#include "RGBController.h" -#include "RGBController_LinuxLED.h" -#include "SettingsManager.h" -#include -#include -#include - -#include - - -/******************************************************************************************\ -* * -* DetectLinuxLEDControllers * -* * -* Detect devices supported by the LinuxLED driver * -* * -\******************************************************************************************/ - -void DetectLinuxLEDControllers() -{ - json linux_led_settings; - - /*-------------------------------------------------*\ - | Get Linux LED settings from settings manager | - \*-------------------------------------------------*/ - linux_led_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("LinuxLEDDevices"); - - /*-------------------------------------------------*\ - | If the LinuxLED settings contains devices, process| - \*-------------------------------------------------*/ - if(linux_led_settings.contains("devices")) - { - for(unsigned int device_idx = 0; device_idx < linux_led_settings["devices"].size(); device_idx++) - { - std::string name; - std::string red_path; - std::string green_path; - std::string blue_path; - - if(linux_led_settings["devices"][device_idx].contains("name")) - { - name = linux_led_settings["devices"][device_idx]["name"]; - } - - if(linux_led_settings["devices"][device_idx].contains("red_path")) - { - red_path = linux_led_settings["devices"][device_idx]["red_path"]; - } - - if(linux_led_settings["devices"][device_idx].contains("green_path")) - { - green_path = linux_led_settings["devices"][device_idx]["green_path"]; - } - - if(linux_led_settings["devices"][device_idx].contains("blue_path")) - { - blue_path = linux_led_settings["devices"][device_idx]["blue_path"]; - } - - LinuxLEDController* controller = new LinuxLEDController(); - controller->OpenRedPath(red_path); - controller->OpenGreenPath(green_path); - controller->OpenBluePath(blue_path); - - RGBController_LinuxLED* rgb_controller = new RGBController_LinuxLED(controller); - rgb_controller->name = name; - - ResourceManager::get()->RegisterRGBController(rgb_controller); - } - } - -} /* DetectLinuxLEDControllers() */ - -REGISTER_DETECTOR("Linux LED", DetectLinuxLEDControllers); diff --git a/Controllers/LinuxLEDController/LinuxLEDControllerDetect_Linux.cpp b/Controllers/LinuxLEDController/LinuxLEDControllerDetect_Linux.cpp new file mode 100644 index 00000000..a09a9cad --- /dev/null +++ b/Controllers/LinuxLEDController/LinuxLEDControllerDetect_Linux.cpp @@ -0,0 +1,79 @@ +/*---------------------------------------------------------*\ +| LinuxLEDControllerDetect_Linux.cpp | +| | +| Detector for Linux sysfs LEDs | +| | +| Adam Honse (calcprogrammer1@gmail.com) 25 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "RGBController_LinuxLED_Linux.h" +#include "SettingsManager.h" + +/******************************************************************************************\ +* * +* DetectLinuxLEDControllers * +* * +* Detect devices supported by the LinuxLED driver * +* * +\******************************************************************************************/ + +void DetectLinuxLEDControllers() +{ + json linux_led_settings; + + /*-------------------------------------------------*\ + | Get Linux LED settings from settings manager | + \*-------------------------------------------------*/ + linux_led_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("LinuxLEDDevices"); + + /*-------------------------------------------------*\ + | If the LinuxLED settings contains devices, process| + \*-------------------------------------------------*/ + if(linux_led_settings.contains("devices")) + { + for(unsigned int device_idx = 0; device_idx < linux_led_settings["devices"].size(); device_idx++) + { + std::string name; + std::string red_path; + std::string green_path; + std::string blue_path; + + if(linux_led_settings["devices"][device_idx].contains("name")) + { + name = linux_led_settings["devices"][device_idx]["name"]; + } + + if(linux_led_settings["devices"][device_idx].contains("red_path")) + { + red_path = linux_led_settings["devices"][device_idx]["red_path"]; + } + + if(linux_led_settings["devices"][device_idx].contains("green_path")) + { + green_path = linux_led_settings["devices"][device_idx]["green_path"]; + } + + if(linux_led_settings["devices"][device_idx].contains("blue_path")) + { + blue_path = linux_led_settings["devices"][device_idx]["blue_path"]; + } + + LinuxLEDController* controller = new LinuxLEDController(name); + controller->OpenRedPath(red_path); + controller->OpenGreenPath(green_path); + controller->OpenBluePath(blue_path); + + RGBController_LinuxLED* rgb_controller = new RGBController_LinuxLED(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + } + +} /* DetectLinuxLEDControllers() */ + +REGISTER_DETECTOR("Linux LED", DetectLinuxLEDControllers); diff --git a/Controllers/LinuxLEDController/LinuxLEDController_Linux.cpp b/Controllers/LinuxLEDController/LinuxLEDController_Linux.cpp new file mode 100644 index 00000000..9d059fcd --- /dev/null +++ b/Controllers/LinuxLEDController/LinuxLEDController_Linux.cpp @@ -0,0 +1,87 @@ +/*---------------------------------------------------------*\ +| LinuxLEDController_Linux.cpp | +| | +| Driver for Linux sysfs LEDs | +| | +| Adam Honse (calcprogrammer1@gmail.com) 25 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "LinuxLEDController_Linux.h" + +LinuxLEDController::LinuxLEDController(std::string dev_name) +{ + name = dev_name; +} + +LinuxLEDController::~LinuxLEDController() +{ + +} + +std::string LinuxLEDController::GetName() +{ + return(name); +} + +std::string LinuxLEDController::GetRedPath() +{ + return(led_r_path); +} + +std::string LinuxLEDController::GetGreenPath() +{ + return(led_g_path); +} + +std::string LinuxLEDController::GetBluePath() +{ + return(led_b_path); +} + +void LinuxLEDController::OpenRedPath(std::string red_path) +{ + led_r_path = red_path; + led_r_brightness.open(led_r_path + "brightness"); +} + +void LinuxLEDController::OpenGreenPath(std::string green_path) +{ + led_g_path = green_path; + led_g_brightness.open(led_g_path + "brightness"); +} + +void LinuxLEDController::OpenBluePath(std::string blue_path) +{ + led_b_path = blue_path; + led_b_brightness.open(led_b_path + "brightness"); +} + +void LinuxLEDController::SetRGB(unsigned char red, unsigned char grn, unsigned char blu) +{ + std::string brightness_str; + + /*-------------------------------------------------------------*\ + | My phone LED that I tested this on shuts down if you set zero | + \*-------------------------------------------------------------*/ + if(red == 0) red = 1; + if(grn == 0) grn = 1; + if(blu == 0) blu = 1; + + brightness_str = std::to_string((unsigned int)red); + + led_r_brightness.write(brightness_str.c_str(), brightness_str.length()); + led_r_brightness.flush(); + + brightness_str = std::to_string((unsigned int)grn); + + led_g_brightness.write(brightness_str.c_str(), brightness_str.length()); + led_g_brightness.flush(); + + brightness_str = std::to_string((unsigned int)blu); + + led_b_brightness.write(brightness_str.c_str(), brightness_str.length()); + led_b_brightness.flush(); +} diff --git a/Controllers/LinuxLEDController/LinuxLEDController_Linux.h b/Controllers/LinuxLEDController/LinuxLEDController_Linux.h new file mode 100644 index 00000000..0bdc250a --- /dev/null +++ b/Controllers/LinuxLEDController/LinuxLEDController_Linux.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------*\ +| LinuxLEDController_Linux.h | +| | +| Driver for Linux sysfs LEDs | +| | +| Adam Honse (calcprogrammer1@gmail.com) 25 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include + +class LinuxLEDController +{ +public: + LinuxLEDController(std::string dev_name); + ~LinuxLEDController(); + + std::string GetName(); + + std::string GetRedPath(); + std::string GetBluePath(); + std::string GetGreenPath(); + + void OpenRedPath(std::string red_path); + void OpenGreenPath(std::string green_path); + void OpenBluePath(std::string blue_path); + + void SetRGB(unsigned char red, unsigned char grn, unsigned char blu); + +private: + std::string led_r_path; + std::string led_g_path; + std::string led_b_path; + std::ofstream led_r_brightness; + std::ofstream led_g_brightness; + std::ofstream led_b_brightness; + std::string name; +}; diff --git a/Controllers/LinuxLEDController/RGBController_LinuxLED.cpp b/Controllers/LinuxLEDController/RGBController_LinuxLED.cpp deleted file mode 100644 index 85dd7ef6..00000000 --- a/Controllers/LinuxLEDController/RGBController_LinuxLED.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LinuxLED.cpp | -| | -| Generic RGB Interface for Linux LED | -| | -| Adam Honse (CalcProgrammer1) 9/25/2020 | -\*-----------------------------------------*/ - -#include "RGBController_LinuxLED.h" - -/**------------------------------------------------------------------*\ - @name Dummy - @category LEDStrip - @type File Stream - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectLinuxLEDControllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_LinuxLED::RGBController_LinuxLED(LinuxLEDController* controller_ptr) -{ - controller = controller_ptr; - - name = "Linux LED"; - type = DEVICE_TYPE_LEDSTRIP; - description = "Linux Sysfs LED Device"; - - location = "R: " + controller->GetRedPath() + "\r\n" + - "G: " + controller->GetGreenPath() + "\r\n" + - "B: " + controller->GetBluePath(); - - 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(); -} - -RGBController_LinuxLED::~RGBController_LinuxLED() -{ - delete controller; -} - -void RGBController_LinuxLED::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_LinuxLED::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_LinuxLED::DeviceUpdateLEDs() -{ - unsigned char red = RGBGetRValue(colors[0]); - unsigned char grn = RGBGetGValue(colors[0]); - unsigned char blu = RGBGetBValue(colors[0]); - - controller->SetRGB(red, grn, blu); -} - -void RGBController_LinuxLED::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_LinuxLED::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_LinuxLED::DeviceUpdateMode() -{ - -} diff --git a/Controllers/LinuxLEDController/RGBController_LinuxLED.h b/Controllers/LinuxLEDController/RGBController_LinuxLED.h deleted file mode 100644 index b021167f..00000000 --- a/Controllers/LinuxLEDController/RGBController_LinuxLED.h +++ /dev/null @@ -1,31 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LinuxLED.h | -| | -| Generic RGB Interface for Linux LED | -| | -| Adam Honse (CalcProgrammer1) 9/25/2020 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "LinuxLEDController.h" - -class RGBController_LinuxLED : public RGBController -{ -public: - RGBController_LinuxLED(LinuxLEDController* controller_ptr); - ~RGBController_LinuxLED(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - LinuxLEDController* controller; -}; diff --git a/Controllers/LinuxLEDController/RGBController_LinuxLED_Linux.cpp b/Controllers/LinuxLEDController/RGBController_LinuxLED_Linux.cpp new file mode 100644 index 00000000..6276b535 --- /dev/null +++ b/Controllers/LinuxLEDController/RGBController_LinuxLED_Linux.cpp @@ -0,0 +1,100 @@ +/*---------------------------------------------------------*\ +| RGBController_LinuxLED.cpp | +| | +| RGBController for Linux sysfs LEDs | +| | +| Adam Honse (calcprogrammer1@gmail.com) 25 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_LinuxLED_Linux.h" + +/**------------------------------------------------------------------*\ + @name Dummy + @category LEDStrip + @type File Stream + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectLinuxLEDControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_LinuxLED::RGBController_LinuxLED(LinuxLEDController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + type = DEVICE_TYPE_LEDSTRIP; + description = "Linux Sysfs LED Device"; + + location = "R: " + controller->GetRedPath() + "\r\n" + + "G: " + controller->GetGreenPath() + "\r\n" + + "B: " + controller->GetBluePath(); + + 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(); +} + +RGBController_LinuxLED::~RGBController_LinuxLED() +{ + delete controller; +} + +void RGBController_LinuxLED::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_LinuxLED::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_LinuxLED::DeviceUpdateLEDs() +{ + unsigned char red = RGBGetRValue(colors[0]); + unsigned char grn = RGBGetGValue(colors[0]); + unsigned char blu = RGBGetBValue(colors[0]); + + controller->SetRGB(red, grn, blu); +} + +void RGBController_LinuxLED::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_LinuxLED::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_LinuxLED::DeviceUpdateMode() +{ + +} diff --git a/Controllers/LinuxLEDController/RGBController_LinuxLED_Linux.h b/Controllers/LinuxLEDController/RGBController_LinuxLED_Linux.h new file mode 100644 index 00000000..bdc142e0 --- /dev/null +++ b/Controllers/LinuxLEDController/RGBController_LinuxLED_Linux.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_LinuxLED.h | +| | +| RGBController for Linux sysfs LEDs | +| | +| Adam Honse (calcprogrammer1@gmail.com) 25 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LinuxLEDController_Linux.h" + +class RGBController_LinuxLED : public RGBController +{ +public: + RGBController_LinuxLED(LinuxLEDController* controller_ptr); + ~RGBController_LinuxLED(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LinuxLEDController* controller; +}; diff --git a/Controllers/LogitechController/LogitechControllerDetect.cpp b/Controllers/LogitechController/LogitechControllerDetect.cpp index 674e706c..9b0aee36 100644 --- a/Controllers/LogitechController/LogitechControllerDetect.cpp +++ b/Controllers/LogitechController/LogitechControllerDetect.cpp @@ -1,3 +1,14 @@ +/*---------------------------------------------------------*\ +| LogitechControllerDetect.cpp | +| | +| Detector for Logitech devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include #include "Detector.h" #include "LogManager.h" #include "LogitechProtocolCommon.h" @@ -13,7 +24,6 @@ #include "LogitechGLightsyncController.h" #include "LogitechLightspeedController.h" #include "LogitechX56Controller.h" -#include "RGBController.h" #include "RGBController_LogitechG203L.h" #include "RGBController_LogitechG213.h" #include "RGBController_LogitechG560.h" @@ -26,12 +36,8 @@ #include "RGBController_LogitechGLightsync.h" #include "RGBController_LogitechGLightsync1zone.h" #include "RGBController_LogitechLightspeed.h" -#include "RGBController_LogitechGPowerPlay.h" +#include "RGBController_LogitechGPowerPlay.h" // Linux-only #include "RGBController_LogitechX56.h" -#include -#include -#include -#include using namespace std::chrono_literals; @@ -67,6 +73,7 @@ using namespace std::chrono_literals; \*-----------------------------------------------------*/ #define LOGITECH_G203_PID 0xC084 #define LOGITECH_G203_LIGHTSYNC_PID 0xC092 +#define LOGITECH_G203_LIGHTSYNC_PID_2 0xC09D #define LOGITECH_G303_PID 0xC080 #define LOGITECH_G403_PID 0xC083 #define LOGITECH_G403_HERO_PID 0xC08F @@ -96,10 +103,13 @@ using namespace std::chrono_literals; /*-----------------------------------------------------*\ | Headset product IDs | \*-----------------------------------------------------*/ +#define LOGITECH_G633_PID 0x0A5C +#define LOGITECH_G635_PID 0x0A89 +#define LOGITECH_G733_PID 0x0AB5 +#define LOGITECH_G733_2_PID 0x0AFE +#define LOGITECH_G733_3_PID 0x0B1F #define LOGITECH_G933_PID 0x0A5B #define LOGITECH_G935_PID 0x0A87 -#define LOGITECH_G733_PID 0x0AB5 -#define LOGITECH_G633_PID 0X0A5C /*-----------------------------------------------------*\ | Unifying Device IDs (Including Lightspeed receivers) | @@ -138,9 +148,9 @@ void DetectLogitechKeyboardG213(hid_device_info* info, const std::string& name) if(dev) { - LogitechG213Controller* controller = new LogitechG213Controller(dev, info->path); + LogitechG213Controller* controller = new LogitechG213Controller(dev, info->path, name); RGBController_LogitechG213* rgb_controller = new RGBController_LogitechG213(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -180,9 +190,8 @@ void DetectLogitechKeyboardG810(hid_device_info* info, const std::string& name) } if(dev_usage_0x0602 && dev_usage_0x0604) { - LogitechG810Controller* controller = new LogitechG810Controller(dev_usage_0x0602, dev_usage_0x0604); + LogitechG810Controller* controller = new LogitechG810Controller(dev_usage_0x0602, dev_usage_0x0604, name); RGBController_LogitechG810* rgb_controller = new RGBController_LogitechG810(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -197,9 +206,8 @@ void DetectLogitechKeyboardG810(hid_device_info* info, const std::string& name) if(dev) { - LogitechG810Controller* controller = new LogitechG810Controller(dev, dev); + LogitechG810Controller* controller = new LogitechG810Controller(dev, dev, name); RGBController_LogitechG810* rgb_controller = new RGBController_LogitechG810(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -241,9 +249,8 @@ void DetectLogitechKeyboardG910(hid_device_info* info, const std::string& name) } if(dev_usage_0x0602 && dev_usage_0x0604) { - LogitechG910Controller* controller = new LogitechG910Controller(dev_usage_0x0602, dev_usage_0x0604); + LogitechG910Controller* controller = new LogitechG910Controller(dev_usage_0x0602, dev_usage_0x0604, name); RGBController_LogitechG910* rgb_controller = new RGBController_LogitechG910(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -258,9 +265,8 @@ void DetectLogitechKeyboardG910(hid_device_info* info, const std::string& name) if(dev) { - LogitechG910Controller* controller = new LogitechG910Controller(dev, dev); + LogitechG910Controller* controller = new LogitechG910Controller(dev, dev, name); RGBController_LogitechG910* rgb_controller = new RGBController_LogitechG910(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -302,9 +308,8 @@ void DetectLogitechKeyboardG815(hid_device_info* info, const std::string& name) } if(dev_usage_0x0602 && dev_usage_0x0604) { - LogitechG815Controller* controller = new LogitechG815Controller(dev_usage_0x0602, dev_usage_0x0604); + LogitechG815Controller* controller = new LogitechG815Controller(dev_usage_0x0602, dev_usage_0x0604, name); RGBController_LogitechG815* rgb_controller = new RGBController_LogitechG815(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -327,9 +332,8 @@ void DetectLogitechKeyboardG815(hid_device_info* info, const std::string& name) if(dev) { - LogitechG815Controller* controller = new LogitechG815Controller(dev, dev); + LogitechG815Controller* controller = new LogitechG815Controller(dev, dev, name); RGBController_LogitechG815* rgb_controller = new RGBController_LogitechG815(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -343,9 +347,8 @@ void DetectLogitechKeyboardG915(hid_device_info* info, const std::string& name) if(dev) { - LogitechG915Controller* controller = new LogitechG915Controller(dev, false); + LogitechG915Controller* controller = new LogitechG915Controller(dev, false, name); RGBController_LogitechG915* rgb_controller = new RGBController_LogitechG915(controller, is_tkl); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -358,9 +361,8 @@ void DetectLogitechKeyboardG915Wired(hid_device_info* info, const std::string& n if(dev) { - LogitechG915Controller* controller = new LogitechG915Controller(dev, true); + LogitechG915Controller* controller = new LogitechG915Controller(dev, true, name); RGBController_LogitechG915* rgb_controller = new RGBController_LogitechG915(controller, is_tkl); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -401,9 +403,8 @@ void DetectLogitechKeyboardGPro(hid_device_info* info, const std::string& name) } if(dev_usage_0x0602 && dev_usage_0x0604) { - LogitechGProKeyboardController* controller = new LogitechGProKeyboardController(dev_usage_0x0602, dev_usage_0x0604); + LogitechGProKeyboardController* controller = new LogitechGProKeyboardController(dev_usage_0x0602, dev_usage_0x0604, name); RGBController_LogitechGProKeyboard* rgb_controller = new RGBController_LogitechGProKeyboard(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -418,9 +419,8 @@ void DetectLogitechKeyboardGPro(hid_device_info* info, const std::string& name) if(dev) { - LogitechGProKeyboardController* controller = new LogitechGProKeyboardController(dev, dev); + LogitechGProKeyboardController* controller = new LogitechGProKeyboardController(dev, dev, name); RGBController_LogitechGProKeyboard* rgb_controller = new RGBController_LogitechGProKeyboard(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -462,9 +462,8 @@ static void addLogitechLightsyncMouse1zone(hid_device_info* info, const std::str } if(dev_usage_1 && dev_usage_2) { - LogitechGLightsyncController* controller = new LogitechGLightsyncController(dev_usage_1, dev_usage_2, info->path, hid_dev_index, hid_feature_index, hid_fctn_ase_id); + LogitechGLightsyncController* controller = new LogitechGLightsyncController(dev_usage_1, dev_usage_2, info->path, hid_dev_index, hid_feature_index, hid_fctn_ase_id, name); RGBController_LogitechGLightsync1zone* rgb_controller = new RGBController_LogitechGLightsync1zone (controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -482,9 +481,8 @@ static void addLogitechLightsyncMouse1zone(hid_device_info* info, const std::str if(dev) { - LogitechGLightsyncController* controller = new LogitechGLightsyncController(dev, dev, info->path, hid_dev_index, hid_feature_index, hid_fctn_ase_id); + LogitechGLightsyncController* controller = new LogitechGLightsyncController(dev, dev, info->path, hid_dev_index, hid_feature_index, hid_fctn_ase_id, name); RGBController_LogitechGLightsync1zone* rgb_controller = new RGBController_LogitechGLightsync1zone(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -524,9 +522,8 @@ static void addLogitechLightsyncMouse2zone(hid_device_info* info, const std::str } if(dev_usage_1 && dev_usage_2) { - LogitechGLightsyncController* controller = new LogitechGLightsyncController(dev_usage_1, dev_usage_2, info->path, hid_dev_index, hid_feature_index, hid_fctn_ase_id); + LogitechGLightsyncController* controller = new LogitechGLightsyncController(dev_usage_1, dev_usage_2, info->path, hid_dev_index, hid_feature_index, hid_fctn_ase_id, name); RGBController_LogitechGLightsync* rgb_controller = new RGBController_LogitechGLightsync (controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -543,9 +540,8 @@ static void addLogitechLightsyncMouse2zone(hid_device_info* info, const std::str if(dev) { - LogitechGLightsyncController* controller = new LogitechGLightsyncController(dev, dev, info->path, hid_dev_index, hid_feature_index, hid_fctn_ase_id); + LogitechGLightsyncController* controller = new LogitechGLightsyncController(dev, dev, info->path, hid_dev_index, hid_feature_index, hid_fctn_ase_id, name); RGBController_LogitechGLightsync* rgb_controller = new RGBController_LogitechGLightsync(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -564,9 +560,8 @@ void DetectLogitechMouseG203L(hid_device_info* info, const std::string& name) if(dev) { - LogitechG203LController* controller = new LogitechG203LController(dev, info->path); + LogitechG203LController* controller = new LogitechG203LController(dev, info->path, name); RGBController_LogitechG203L* rgb_controller = new RGBController_LogitechG203L(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -599,9 +594,8 @@ void DetectLogitechG560(hid_device_info* info, const std::string& name) /*---------------------------------------------*\ | Add G560 Speaker | \*---------------------------------------------*/ - LogitechG560Controller* controller = new LogitechG560Controller(dev, info->path); + LogitechG560Controller* controller = new LogitechG560Controller(dev, info->path, name); RGBController_LogitechG560* rgb_controller = new RGBController_LogitechG560(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -616,9 +610,8 @@ void DetectLogitechG933(hid_device_info* info, const std::string& name) /*---------------------------------------------*\ | Add G933 Headset | \*---------------------------------------------*/ - LogitechG933Controller* controller = new LogitechG933Controller(dev, info->path); + LogitechG933Controller* controller = new LogitechG933Controller(dev, info->path, name); RGBController_LogitechG933* rgb_controller = new RGBController_LogitechG933(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -633,9 +626,8 @@ void DetectLogitechX56(hid_device_info* info, const std::string& name) /*---------------------------------------------*\ | Add X56 Devices | \*---------------------------------------------*/ - LogitechX56Controller* controller = new LogitechX56Controller(dev, info->path); + LogitechX56Controller* controller = new LogitechX56Controller(dev, info->path, name); RGBController_LogitechX56* rgb_controller = new RGBController_LogitechX56(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -667,10 +659,11 @@ REGISTER_HID_DETECTOR_IPU("Logitech G915TKL Wireless RGB Mechanical Gaming Keybo \*-------------------------------------------------------------------------------------------------------------------------------------------------*/ 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_IPU("Logitech G203 Lightsync", DetectLogitechMouseG203L, LOGITECH_VID, LOGITECH_G203_LIGHTSYNC_PID_2, 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 G403 HERO", DetectLogitechMouseG403, LOGITECH_VID, LOGITECH_G403_HERO_PID, 1, 0xFF00); REGISTER_HID_DETECTOR_IP ("Logitech G Pro Gaming Mouse", DetectLogitechMouseGPRO, LOGITECH_VID, LOGITECH_G_PRO_PID, 1, 0xFF00); -REGISTER_HID_DETECTOR_IP ("Logitech G Pro (HERO) Gaming Mouse", DetectLogitechMouseGPRO, LOGITECH_VID, LOGITECH_G_PRO_HERO_PID, 1, 0xFF00); +REGISTER_HID_DETECTOR_IP ("Logitech G Pro HERO Gaming Mouse", DetectLogitechMouseGPRO, LOGITECH_VID, LOGITECH_G_PRO_HERO_PID, 1, 0xFF00); /*-------------------------------------------------------------------------------------------------------------------------------------------------*\ | Speakers | \*-------------------------------------------------------------------------------------------------------------------------------------------------*/ @@ -888,30 +881,34 @@ void DetectLogitechWireless(hid_device_info* info, const std::string& /*name*/) 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 G703 Hero Wireless Gaming Mouse", DetectLogitechWireless, LOGITECH_VID, LOGITECH_G703_HERO_LIGHTSPEED_VIRTUAL_PID, 2, 0xFF00, 2); +REGISTER_HID_DETECTOR_IPU("Logitech G703 HERO Wireless Gaming Mouse", DetectLogitechWireless, LOGITECH_VID, LOGITECH_G703_HERO_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 G903 Hero Wireless Gaming Mouse", DetectLogitechWireless, LOGITECH_VID, LOGITECH_G903_LIGHTSPEED_VIRTUAL_HERO_PID, 2, 0xFF00, 2); +REGISTER_HID_DETECTOR_IPU("Logitech G903 HERO Wireless Gaming Mouse", DetectLogitechWireless, LOGITECH_VID, LOGITECH_G903_LIGHTSPEED_VIRTUAL_HERO_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); REGISTER_HID_DETECTOR_IPU("Logitech Powerplay Mat", DetectLogitechWireless, LOGITECH_VID, LOGITECH_POWERPLAY_MAT_VIRTUAL_PID, 2, 0xFF00, 2); #endif /*-------------------------------------------------------------------------------------------------------------------------------------------------*\ -| Lightspeed Wireless Devices (Common Wired) | +| Lightspeed Wireless Devices (Common Wired) | +| G502 changed to PU to accomodate old and new firmware. Other devices may require similar update #4627 | \*-------------------------------------------------------------------------------------------------------------------------------------------------*/ -REGISTER_HID_DETECTOR_IPU("Logitech G502 Proteus Spectrum Gaming Mouse", DetectLogitechWired, LOGITECH_VID, LOGITECH_G502_PROTEUS_SPECTRUM_PID, 1, 0xFF00, 2); -REGISTER_HID_DETECTOR_IPU("Logitech G502 Hero Gaming Mouse", DetectLogitechWired, LOGITECH_VID, LOGITECH_G502_HERO_PID, 1, 0xFF00, 2); +REGISTER_HID_DETECTOR_PU("Logitech G502 Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G502_LIGHTSPEED_PID, 0xFF00, 2); +REGISTER_HID_DETECTOR_IPU("Logitech G502 Proteus Spectrum Gaming Mouse", DetectLogitechWired, LOGITECH_VID, LOGITECH_G502_PROTEUS_SPECTRUM_PID, 1, 0xFF00, 2); +REGISTER_HID_DETECTOR_IPU("Logitech G502 HERO Gaming Mouse", DetectLogitechWired, LOGITECH_VID, LOGITECH_G502_HERO_PID, 1, 0xFF00, 2); REGISTER_HID_DETECTOR_IPU("Logitech G403 Prodigy Gaming Mouse", DetectLogitechWired, LOGITECH_VID, LOGITECH_G403_PID, 1, 0xFF00, 2); 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 G703 Hero Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G703_HERO_LIGHTSPEED_PID, 1, 0xFF00, 2); +REGISTER_HID_DETECTOR_IPU("Logitech G703 HERO Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G703_HERO_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 G903 Hero Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G903_LIGHTSPEED_HERO_PID, 1, 0xFF00, 2); +REGISTER_HID_DETECTOR_IPU("Logitech G903 HERO Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G903_LIGHTSPEED_HERO_PID, 2, 0xFF00, 2); REGISTER_HID_DETECTOR_IPU("Logitech G Pro Wireless Gaming Mouse (wired)", DetectLogitechWired, LOGITECH_VID, LOGITECH_G_PRO_WIRELESS_PID, 2, 0xFF00, 2); REGISTER_HID_DETECTOR_IPU("Logitech G633 Gaming Headset", DetectLogitechWired, LOGITECH_VID, LOGITECH_G633_PID, 3, 0xFF43, 514); +REGISTER_HID_DETECTOR_IPU("Logitech G635 Gaming Headset", DetectLogitechWired, LOGITECH_VID, LOGITECH_G635_PID, 3, 0xFF43, 514); REGISTER_HID_DETECTOR_IPU("Logitech G733 Gaming Headset", DetectLogitechWired, LOGITECH_VID, LOGITECH_G733_PID, 3, 0xFF43, 514); +REGISTER_HID_DETECTOR_IPU("Logitech G733 Gaming Headset", DetectLogitechWired, LOGITECH_VID, LOGITECH_G733_2_PID, 3, 0xFF43, 514); +REGISTER_HID_DETECTOR_IPU("Logitech G733 Gaming Headset", DetectLogitechWired, LOGITECH_VID, LOGITECH_G733_3_PID, 3, 0xFF43, 514); REGISTER_HID_DETECTOR_IPU("Logitech G935 Gaming Headset", DetectLogitechWired, LOGITECH_VID, LOGITECH_G935_PID, 3, 0xFF43, 514); diff --git a/Controllers/LogitechController/LogitechG203LController.h b/Controllers/LogitechController/LogitechG203LController.h deleted file mode 100644 index 82fcea34..00000000 --- a/Controllers/LogitechController/LogitechG203LController.h +++ /dev/null @@ -1,38 +0,0 @@ -#include "RGBController.h" - -#include -#include - -#pragma once - -enum -{ - LOGITECH_G203L_MODE_DIRECT = 0x07, - LOGITECH_G203L_MODE_OFF = 0x00, - LOGITECH_G203L_MODE_STATIC = 0x01, - LOGITECH_G203L_MODE_CYCLE = 0x02, - LOGITECH_G203L_MODE_WAVE = 0x03, - LOGITECH_G203L_MODE_BREATHING = 0x04, - LOGITECH_G203L_MODE_COLORMIXING = 0x06, -}; - -class LogitechG203LController -{ -public: - LogitechG203LController(hid_device* dev_handle, const char* path); - ~LogitechG203LController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - - void SetSingleLED(int led, unsigned char red, unsigned char green, unsigned char blue); - void SetMode(int mode, int speed, unsigned char brightness, unsigned char dir, unsigned char red, unsigned char green, unsigned char blue); - void SetDevice(std::vector colors); - -private: - hid_device* dev; - std::string location; - - void SendApply(); - void SendPacket(unsigned char* buffer); -}; diff --git a/Controllers/LogitechController/LogitechG203LController.cpp b/Controllers/LogitechController/LogitechG203LController/LogitechG203LController.cpp similarity index 86% rename from Controllers/LogitechController/LogitechG203LController.cpp rename to Controllers/LogitechController/LogitechG203LController/LogitechG203LController.cpp index da353774..36e80440 100644 --- a/Controllers/LogitechController/LogitechG203LController.cpp +++ b/Controllers/LogitechController/LogitechG203LController/LogitechG203LController.cpp @@ -1,14 +1,23 @@ -#include "LogitechG203LController.h" +/*---------------------------------------------------------*\ +| LogitechG203LController.cpp | +| | +| Driver for Logitech G203L | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "LogitechG203LController.h" +#include "StringUtils.h" #define PACKET_SIZE 20 - -LogitechG203LController::LogitechG203LController(hid_device* dev_handle, const char* path) +LogitechG203LController::LogitechG203LController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; // enable software control unsigned char usb_buf[PACKET_SIZE]; @@ -39,6 +48,11 @@ std::string LogitechG203LController::GetDeviceLocation() return("HID: " + location); } +std::string LogitechG203LController::GetNameString() +{ + return(name); +} + std::string LogitechG203LController::GetSerialString() { wchar_t serial_string[128]; @@ -49,10 +63,7 @@ std::string LogitechG203LController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void LogitechG203LController::SendApply() @@ -149,7 +160,7 @@ void LogitechG203LController::SetMode( usb_buf[0x0D] = (unsigned char)((speed>>8) & 0x000000FF); usb_buf[0x0E] = brightness; } - + //END BYTE usb_buf[0x10] = 0x01; @@ -181,7 +192,7 @@ void LogitechG203LController::SetDevice(std::vector colors) usb_buf[0x0D] = RGBGetRValue(colors[2]); usb_buf[0x0E] = RGBGetGValue(colors[2]); usb_buf[0x0F] = RGBGetBValue(colors[2]); - + usb_buf[0x10] = 0xFF; SendPacket(usb_buf); diff --git a/Controllers/LogitechController/LogitechG203LController/LogitechG203LController.h b/Controllers/LogitechController/LogitechG203LController/LogitechG203LController.h new file mode 100644 index 00000000..47ea94c8 --- /dev/null +++ b/Controllers/LogitechController/LogitechG203LController/LogitechG203LController.h @@ -0,0 +1,48 @@ +/*---------------------------------------------------------*\ +| LogitechG203LController.h | +| | +| Driver for Logitech G203L | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +enum +{ + LOGITECH_G203L_MODE_DIRECT = 0x07, + LOGITECH_G203L_MODE_OFF = 0x00, + LOGITECH_G203L_MODE_STATIC = 0x01, + LOGITECH_G203L_MODE_CYCLE = 0x02, + LOGITECH_G203L_MODE_WAVE = 0x03, + LOGITECH_G203L_MODE_BREATHING = 0x04, + LOGITECH_G203L_MODE_COLORMIXING = 0x06, +}; + +class LogitechG203LController +{ +public: + LogitechG203LController(hid_device* dev_handle, const char* path, std::string dev_name); + ~LogitechG203LController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SetSingleLED(int led, unsigned char red, unsigned char green, unsigned char blue); + void SetMode(int mode, int speed, unsigned char brightness, unsigned char dir, unsigned char red, unsigned char green, unsigned char blue); + void SetDevice(std::vector colors); + +private: + hid_device* dev; + std::string location; + std::string name; + + void SendApply(); + void SendPacket(unsigned char* buffer); +}; diff --git a/Controllers/LogitechController/RGBController_LogitechG203L.cpp b/Controllers/LogitechController/LogitechG203LController/RGBController_LogitechG203L.cpp similarity index 84% rename from Controllers/LogitechController/RGBController_LogitechG203L.cpp rename to Controllers/LogitechController/LogitechG203LController/RGBController_LogitechG203L.cpp index 4f3d53ab..fc4e8a13 100644 --- a/Controllers/LogitechController/RGBController_LogitechG203L.cpp +++ b/Controllers/LogitechController/LogitechG203LController/RGBController_LogitechG203L.cpp @@ -1,3 +1,12 @@ +/*---------------------------------------------------------*\ +| RGBController_LogitechG203L.cpp | +| | +| Driver for Logitech G203L | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "RGBController_LogitechG203L.h" /**------------------------------------------------------------------*\ @@ -13,14 +22,14 @@ RGBController_LogitechG203L::RGBController_LogitechG203L(LogitechG203LController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Logitech Mouse Device"; - vendor = "Logitech"; - type = DEVICE_TYPE_MOUSE; - description = "Logitech Mouse Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "Logitech"; + type = DEVICE_TYPE_MOUSE; + description = "Logitech Mouse Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; Direct.name = "Direct"; diff --git a/Controllers/LogitechController/LogitechG203LController/RGBController_LogitechG203L.h b/Controllers/LogitechController/LogitechG203LController/RGBController_LogitechG203L.h new file mode 100644 index 00000000..d1188336 --- /dev/null +++ b/Controllers/LogitechController/LogitechG203LController/RGBController_LogitechG203L.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------*\ +| RGBController_LogitechG203L.h | +| | +| Driver for Logitech G203L | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LogitechG203LController.h" + +class RGBController_LogitechG203L : public RGBController +{ +public: + RGBController_LogitechG203L(LogitechG203LController* controller_ptr); + ~RGBController_LogitechG203L(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LogitechG203LController* controller; +}; diff --git a/Controllers/LogitechController/LogitechG213Controller.cpp b/Controllers/LogitechController/LogitechG213Controller/LogitechG213Controller.cpp similarity index 79% rename from Controllers/LogitechController/LogitechG213Controller.cpp rename to Controllers/LogitechController/LogitechG213Controller/LogitechG213Controller.cpp index e793658d..900f5e1e 100644 --- a/Controllers/LogitechController/LogitechG213Controller.cpp +++ b/Controllers/LogitechController/LogitechG213Controller/LogitechG213Controller.cpp @@ -1,18 +1,23 @@ -/*-----------------------------------------*\ -| LogitechG213Controller.cpp | -| | -| Generic RGB Interface for Logitech G213 | -| | -| Eric Samuelson (edbgon) 10/06/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LogitechG203LController.cpp | +| | +| Driver for Logitech G203L | +| | +| Eric Samuelson (edbgon) 06 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "LogitechG213Controller.h" #include +#include "LogitechG213Controller.h" +#include "StringUtils.h" -LogitechG213Controller::LogitechG213Controller(hid_device* dev_handle, const char* path) +LogitechG213Controller::LogitechG213Controller(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } LogitechG213Controller::~LogitechG213Controller() @@ -25,6 +30,11 @@ std::string LogitechG213Controller::GetDeviceLocation() return("HID: " + location); } +std::string LogitechG213Controller::GetNameString() +{ + return(name); +} + std::string LogitechG213Controller::GetSerialString() { wchar_t serial_string[128]; @@ -35,10 +45,7 @@ std::string LogitechG213Controller::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void LogitechG213Controller::SetDirect @@ -73,8 +80,8 @@ void LogitechG213Controller::SetDirect /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, 20); - hid_read(dev, (unsigned char *)usb_buf, 20); + hid_write(dev, usb_buf, 20); + hid_read(dev, usb_buf, 20); } void LogitechG213Controller::SetMode @@ -101,7 +108,7 @@ void LogitechG213Controller::SendMode unsigned char blue ) { - char usb_buf[20]; + unsigned char usb_buf[20]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -148,6 +155,6 @@ void LogitechG213Controller::SendMode /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, (unsigned char *)usb_buf, 20); - hid_read(dev, (unsigned char *)usb_buf, 20); + hid_write(dev, usb_buf, 20); + hid_read(dev, usb_buf, 20); } diff --git a/Controllers/LogitechController/LogitechG213Controller.h b/Controllers/LogitechController/LogitechG213Controller/LogitechG213Controller.h similarity index 77% rename from Controllers/LogitechController/LogitechG213Controller.h rename to Controllers/LogitechController/LogitechG213Controller/LogitechG213Controller.h index 14ab0f99..7d26cf9d 100644 --- a/Controllers/LogitechController/LogitechG213Controller.h +++ b/Controllers/LogitechController/LogitechG213Controller/LogitechG213Controller.h @@ -1,15 +1,18 @@ -/*-----------------------------------------*\ -| LogitechG213Controller.h | -| | -| Generic RGB Interface for Logitech G213 | -| | -| Eric Samuelson (edbgon) 10/06/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LogitechG203LController.h | +| | +| Driver for Logitech G203L | +| | +| Eric Samuelson (edbgon) 06 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController.h" #include -#include +#include #pragma once @@ -49,10 +52,11 @@ enum class LogitechG213Controller { public: - LogitechG213Controller(hid_device* dev_handle, const char* path); + LogitechG213Controller(hid_device* dev_handle, const char* path, std::string dev_name); ~LogitechG213Controller(); std::string GetDeviceLocation(); + std::string GetNameString(); std::string GetSerialString(); void SetDirect @@ -76,6 +80,7 @@ public: private: hid_device* dev; std::string location; + std::string name; void SendMode ( diff --git a/Controllers/LogitechController/RGBController_LogitechG213.cpp b/Controllers/LogitechController/LogitechG213Controller/RGBController_LogitechG213.cpp similarity index 78% rename from Controllers/LogitechController/RGBController_LogitechG213.cpp rename to Controllers/LogitechController/LogitechG213Controller/RGBController_LogitechG213.cpp index e8628a5c..99f1717c 100644 --- a/Controllers/LogitechController/RGBController_LogitechG213.cpp +++ b/Controllers/LogitechController/LogitechG213Controller/RGBController_LogitechG213.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_LogitechG213.cpp | -| | -| Generic RGB Interface for Logitech G213 | -| | -| Eric Samuelson (edbgon) 10/06/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LogitechG213.cpp | +| | +| RGBController for Logitech G203L | +| | +| Eric Samuelson (edbgon) 06 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_LogitechG213.h" @@ -41,14 +44,14 @@ static const unsigned char led_values[] = RGBController_LogitechG213::RGBController_LogitechG213(LogitechG213Controller* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Logitech G213 Keyboard Device"; - vendor = "Logitech"; - type = DEVICE_TYPE_KEYBOARD; - description = "Logitech G213 Keyboard Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "Logitech"; + type = DEVICE_TYPE_KEYBOARD; + description = "Logitech G213 Keyboard Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; Direct.name = "Direct"; @@ -75,14 +78,14 @@ RGBController_LogitechG213::RGBController_LogitechG213(LogitechG213Controller* c modes.push_back(Cycle); mode Wave; - Wave.name = "Wave"; - Wave.value = LOGITECH_G213_MODE_WAVE; - Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD; - Wave.color_mode = MODE_COLORS_NONE; - Wave.speed_min = LOGITECH_G213_SPEED_SLOWEST; - Wave.speed_max = LOGITECH_G213_SPEED_FASTEST; - Wave.speed = LOGITECH_G213_SPEED_NORMAL; - Wave.direction = MODE_DIRECTION_LEFT; + Wave.name = "Wave"; + Wave.value = LOGITECH_G213_MODE_WAVE; + Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD; + Wave.color_mode = MODE_COLORS_NONE; + Wave.speed_min = LOGITECH_G213_SPEED_SLOWEST; + Wave.speed_max = LOGITECH_G213_SPEED_FASTEST; + Wave.speed = LOGITECH_G213_SPEED_NORMAL; + Wave.direction = MODE_DIRECTION_LEFT; modes.push_back(Wave); mode Breathing; diff --git a/Controllers/LogitechController/LogitechG213Controller/RGBController_LogitechG213.h b/Controllers/LogitechController/LogitechG213Controller/RGBController_LogitechG213.h new file mode 100644 index 00000000..27099f90 --- /dev/null +++ b/Controllers/LogitechController/LogitechG213Controller/RGBController_LogitechG213.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_LogitechG213.h | +| | +| RGBController for Logitech G203L | +| | +| Eric Samuelson (edbgon) 06 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LogitechG213Controller.h" + +class RGBController_LogitechG213 : public RGBController +{ +public: + RGBController_LogitechG213(LogitechG213Controller* controller_ptr); + ~RGBController_LogitechG213(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LogitechG213Controller* controller; +}; diff --git a/Controllers/LogitechController/LogitechG560Controller.h b/Controllers/LogitechController/LogitechG560Controller.h deleted file mode 100644 index 3259d929..00000000 --- a/Controllers/LogitechController/LogitechG560Controller.h +++ /dev/null @@ -1,57 +0,0 @@ -/*-----------------------------------------*\ -| LogitechG560Controller.h | -| | -| Definitions and types for Logitech G560 | -| RGB Speaker | -| | -| Cheerpipe 10/28/2020 | -| Based on | -| TheRogueZeta 8/31/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include - -#pragma once - -#define LOGI_G560_LED_PACKET_SIZE 20 -#define LOGI_G560_LED_COMMAND_SEND_RETRIES 3 - -enum -{ - LOGITECH_G560_MODE_OFF = 0x00, - LOGITECH_G560_MODE_DIRECT = 0x01, - LOGITECH_G560_MODE_CYCLE = 0x02, - LOGITECH_G560_MODE_BREATHING = 0x03, -}; - -class LogitechG560Controller -{ -public: - LogitechG560Controller(hid_device* dev_handle, const char* path); - ~LogitechG560Controller(); - - std::string GetDeviceLocation(); - - void SetDirectMode(uint8_t zone); - void SetOffMode(uint8_t zone); - - void SendSpeakerMode - ( - unsigned char zone, - unsigned char mode, - unsigned char red, - unsigned char green, - unsigned char blue - ); - -private: - hid_device* dev; - std::string location; - - void fail_retry_write(hid_device *device, const unsigned char *data, size_t length); -}; - - diff --git a/Controllers/LogitechController/LogitechG560Controller.cpp b/Controllers/LogitechController/LogitechG560Controller/LogitechG560Controller.cpp similarity index 82% rename from Controllers/LogitechController/LogitechG560Controller.cpp rename to Controllers/LogitechController/LogitechG560Controller/LogitechG560Controller.cpp index 8cf23f30..11b5d36f 100644 --- a/Controllers/LogitechController/LogitechG560Controller.cpp +++ b/Controllers/LogitechController/LogitechG560Controller/LogitechG560Controller.cpp @@ -1,25 +1,27 @@ -/*-----------------------------------------*\ -| LogitechG560Controller.cpp | -| | -| Driver for Logitech G560 RGB Speaker | -| Charging System | -| | -| Cheerpipe 10/28/2020 | -| Based on | -| TheRogueZeta 8/31/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LogitechG560Controller.cpp | +| | +| Driver for Logitech G560 | +| | +| Cheerpipe 28 Oct 2020 | +| based on TheRogueZeta 31 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "LogitechG560Controller.h" #include #include #include +#include "LogitechG560Controller.h" using namespace std::chrono_literals; -LogitechG560Controller::LogitechG560Controller(hid_device* dev_handle, const char* path) +LogitechG560Controller::LogitechG560Controller(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } LogitechG560Controller::~LogitechG560Controller() @@ -32,6 +34,11 @@ std::string LogitechG560Controller::GetDeviceLocation() return("HID: " + location); } +std::string LogitechG560Controller::GetDeviceName() +{ + return(name); +} + void LogitechG560Controller::SetDirectMode(uint8_t zone) { unsigned char usb_buf[LOGI_G560_LED_PACKET_SIZE]; diff --git a/Controllers/LogitechController/LogitechG560Controller/LogitechG560Controller.h b/Controllers/LogitechController/LogitechG560Controller/LogitechG560Controller.h new file mode 100644 index 00000000..d04195c6 --- /dev/null +++ b/Controllers/LogitechController/LogitechG560Controller/LogitechG560Controller.h @@ -0,0 +1,59 @@ +/*---------------------------------------------------------*\ +| LogitechG560Controller.h | +| | +| Driver for Logitech G560 | +| | +| Cheerpipe 28 Oct 2020 | +| based on TheRogueZeta 31 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define LOGI_G560_LED_PACKET_SIZE 20 +#define LOGI_G560_LED_COMMAND_SEND_RETRIES 3 + +enum +{ + LOGITECH_G560_MODE_OFF = 0x00, + LOGITECH_G560_MODE_DIRECT = 0x01, + LOGITECH_G560_MODE_CYCLE = 0x02, + LOGITECH_G560_MODE_BREATHING = 0x03, +}; + +class LogitechG560Controller +{ +public: + LogitechG560Controller(hid_device* dev_handle, const char* path, std::string dev_name); + ~LogitechG560Controller(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + + void SetDirectMode(uint8_t zone); + void SetOffMode(uint8_t zone); + + void SendSpeakerMode + ( + unsigned char zone, + unsigned char mode, + unsigned char red, + unsigned char green, + unsigned char blue + ); + +private: + hid_device* dev; + std::string location; + std::string name; + + void fail_retry_write(hid_device *device, const unsigned char *data, size_t length); +}; + + diff --git a/Controllers/LogitechController/RGBController_LogitechG560.cpp b/Controllers/LogitechController/LogitechG560Controller/RGBController_LogitechG560.cpp similarity index 79% rename from Controllers/LogitechController/RGBController_LogitechG560.cpp rename to Controllers/LogitechController/LogitechG560Controller/RGBController_LogitechG560.cpp index d690c09f..e5abaccc 100644 --- a/Controllers/LogitechController/RGBController_LogitechG560.cpp +++ b/Controllers/LogitechController/LogitechG560Controller/RGBController_LogitechG560.cpp @@ -1,13 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_LogitechG560.cpp | -| | -| Generic RGB Interface for | -| Logitech G560 RGB Speaker | -| | -| Cheerpipe 10/28/2020 | -| Based on | -| TheRogueZeta 8/31/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LogitechG560.cpp | +| | +| RGBController for Logitech G560 | +| | +| Cheerpipe 28 Oct 2020 | +| based on TheRogueZeta 31 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_LogitechG560.h" @@ -24,13 +25,13 @@ RGBController_LogitechG560::RGBController_LogitechG560(LogitechG560Controller* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Logitech G560 Lightsync Speaker"; - vendor = "Logitech"; - type = DEVICE_TYPE_SPEAKER; - description = "Logitech G560 Lightsync Speaker"; - location = controller->GetDeviceLocation(); + name = controller->GetDeviceName(); + vendor = "Logitech"; + type = DEVICE_TYPE_SPEAKER; + description = "Logitech G560 Lightsync Speaker"; + location = controller->GetDeviceLocation(); mode Off; Off.name = "Off"; diff --git a/Controllers/LogitechController/LogitechG560Controller/RGBController_LogitechG560.h b/Controllers/LogitechController/LogitechG560Controller/RGBController_LogitechG560.h new file mode 100644 index 00000000..b28e7f1a --- /dev/null +++ b/Controllers/LogitechController/LogitechG560Controller/RGBController_LogitechG560.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_LogitechG560.h | +| | +| RGBController for Logitech G560 | +| | +| Cheerpipe 28 Oct 2020 | +| based on TheRogueZeta 31 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LogitechG560Controller.h" + +class RGBController_LogitechG560 : public RGBController +{ +public: + RGBController_LogitechG560(LogitechG560Controller* controller_ptr); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LogitechG560Controller* controller; +}; diff --git a/Controllers/LogitechController/LogitechG810Controller.cpp b/Controllers/LogitechController/LogitechG810Controller/LogitechG810Controller.cpp similarity index 79% rename from Controllers/LogitechController/LogitechG810Controller.cpp rename to Controllers/LogitechController/LogitechG810Controller/LogitechG810Controller.cpp index 124028e2..7ab5d427 100644 --- a/Controllers/LogitechController/LogitechG810Controller.cpp +++ b/Controllers/LogitechController/LogitechG810Controller/LogitechG810Controller.cpp @@ -1,19 +1,23 @@ -/*-----------------------------------------*\ -| LogitechG810Controller.cpp | -| | -| Driver for Logitech G810 Orion Spectrum | -| keyboard light controller | -| | -| Adam Honse (CalcProgrammer1) 6/11/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LogitechG810Controller.cpp | +| | +| Driver for Logitech G810 Orion Spectrum | +| | +| Adam Honse (CalcProgrammer1) 11 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "LogitechG810Controller.h" #include +#include "LogitechG810Controller.h" +#include "StringUtils.h" -LogitechG810Controller::LogitechG810Controller(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12) +LogitechG810Controller::LogitechG810Controller(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12, std::string dev_name) { - dev_pkt_0x11 = dev_handle_0x11; - dev_pkt_0x12 = dev_handle_0x12; + dev_pkt_0x11 = dev_handle_0x11; + dev_pkt_0x12 = dev_handle_0x12; + name = dev_name; } LogitechG810Controller::~LogitechG810Controller() @@ -22,6 +26,11 @@ LogitechG810Controller::~LogitechG810Controller() hid_close(dev_pkt_0x12); } +std::string LogitechG810Controller::GetNameString() +{ + return(name); +} + std::string LogitechG810Controller::GetSerialString() { wchar_t serial_string[128]; @@ -32,10 +41,7 @@ std::string LogitechG810Controller::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void LogitechG810Controller::Commit() @@ -74,7 +80,7 @@ void LogitechG810Controller::SetMode void LogitechG810Controller::SendCommit() { - char usb_buf[20]; + unsigned char usb_buf[20]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -92,8 +98,8 @@ void LogitechG810Controller::SendCommit() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x11, (unsigned char *)usb_buf, 20); - hid_read(dev_pkt_0x11, (unsigned char *)usb_buf, 20); + hid_write(dev_pkt_0x11, usb_buf, 20); + hid_read(dev_pkt_0x11, usb_buf, 20); } void LogitechG810Controller::SendDirectFrame @@ -103,7 +109,7 @@ void LogitechG810Controller::SendDirectFrame unsigned char * frame_data ) { - char usb_buf[64]; + unsigned char usb_buf[64]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -128,8 +134,8 @@ void LogitechG810Controller::SendDirectFrame /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x12, (unsigned char *)usb_buf, 64); - hid_read(dev_pkt_0x11, (unsigned char *)usb_buf, 20); + hid_write(dev_pkt_0x12, usb_buf, 64); + hid_read(dev_pkt_0x11, usb_buf, 20); } void LogitechG810Controller::SendMode @@ -142,7 +148,7 @@ void LogitechG810Controller::SendMode unsigned char blue ) { - char usb_buf[20]; + unsigned char usb_buf[20]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -181,6 +187,6 @@ void LogitechG810Controller::SendMode /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x11, (unsigned char *)usb_buf, 20); - hid_read(dev_pkt_0x11, (unsigned char *)usb_buf, 20); + hid_write(dev_pkt_0x11, usb_buf, 20); + hid_read(dev_pkt_0x11, usb_buf, 20); } diff --git a/Controllers/LogitechController/LogitechG810Controller.h b/Controllers/LogitechController/LogitechG810Controller/LogitechG810Controller.h similarity index 78% rename from Controllers/LogitechController/LogitechG810Controller.h rename to Controllers/LogitechController/LogitechG810Controller/LogitechG810Controller.h index 18b91666..757a6e2d 100644 --- a/Controllers/LogitechController/LogitechG810Controller.h +++ b/Controllers/LogitechController/LogitechG810Controller/LogitechG810Controller.h @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| LogitechG810Controller.h | -| | -| Definitions and types for Logitech G810 | -| Orion Spectrum keyboard light controller | -| | -| Adam Honse (CalcProgrammer1) 6/11/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| LogitechG810Controller.h | +| | +| Driver for Logitech G810 Orion Spectrum | +| | +| Adam Honse (CalcProgrammer1) 11 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + enum { LOGITECH_G810_ZONE_MODE_KEYBOARD = 0x00, @@ -51,13 +52,14 @@ enum class LogitechG810Controller { public: - LogitechG810Controller(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12); + LogitechG810Controller(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12, std::string dev_name); ~LogitechG810Controller(); + std::string GetNameString(); std::string GetSerialString(); void Commit(); - + void SetDirect ( unsigned char zone, @@ -77,6 +79,7 @@ public: private: hid_device* dev_pkt_0x11; hid_device* dev_pkt_0x12; + std::string name; void SendDirectFrame ( diff --git a/Controllers/LogitechController/RGBController_LogitechG810.cpp b/Controllers/LogitechController/LogitechG810Controller/RGBController_LogitechG810.cpp similarity index 93% rename from Controllers/LogitechController/RGBController_LogitechG810.cpp rename to Controllers/LogitechController/LogitechG810Controller/RGBController_LogitechG810.cpp index 761584fe..ae178271 100644 --- a/Controllers/LogitechController/RGBController_LogitechG810.cpp +++ b/Controllers/LogitechController/LogitechG810Controller/RGBController_LogitechG810.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_LogitechG810.cpp | -| | -| Generic RGB Interface for Logitech G810 | -| Orion Spectrum Keyboard | -| | -| Adam Honse (CalcProgrammer1) 6/12/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LogitechG810.cpp | +| | +| RGBController for Logitech G810 Orion Spectrum | +| | +| Adam Honse (CalcProgrammer1) 12 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_LogitechG810.h" @@ -179,13 +181,13 @@ static const led_type led_names[] = RGBController_LogitechG810::RGBController_LogitechG810(LogitechG810Controller* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Logitech Keyboard Device"; - vendor = "Logitech"; - type = DEVICE_TYPE_KEYBOARD; - description = "Logitech Keyboard Device"; - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "Logitech"; + type = DEVICE_TYPE_KEYBOARD; + description = "Logitech Keyboard Device"; + serial = controller->GetSerialString(); mode Direct; Direct.name = "Direct"; diff --git a/Controllers/LogitechController/LogitechG810Controller/RGBController_LogitechG810.h b/Controllers/LogitechController/LogitechG810Controller/RGBController_LogitechG810.h new file mode 100644 index 00000000..eae16c56 --- /dev/null +++ b/Controllers/LogitechController/LogitechG810Controller/RGBController_LogitechG810.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_LogitechG810.h | +| | +| RGBController for Logitech G810 Orion Spectrum | +| | +| Adam Honse (CalcProgrammer1) 12 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LogitechG810Controller.h" + +class RGBController_LogitechG810 : public RGBController +{ +public: + RGBController_LogitechG810(LogitechG810Controller* controller_ptr); + ~RGBController_LogitechG810(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LogitechG810Controller* controller; +}; diff --git a/Controllers/LogitechController/LogitechG815Controller.cpp b/Controllers/LogitechController/LogitechG815Controller/LogitechG815Controller.cpp similarity index 83% rename from Controllers/LogitechController/LogitechG815Controller.cpp rename to Controllers/LogitechController/LogitechG815Controller/LogitechG815Controller.cpp index f9946b1a..f411f2c9 100644 --- a/Controllers/LogitechController/LogitechG815Controller.cpp +++ b/Controllers/LogitechController/LogitechG815Controller/LogitechG815Controller.cpp @@ -1,19 +1,23 @@ -/*-----------------------------------------*\ -| LogitechG815Controller.cpp | -| | -| Generic RGB Interface for Logitech G815 | -| RGB Mechanical Gaming Keyboard | -| | -| Cheerpipe 3/20/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LogitechG815Controller.cpp | +| | +| Driver for Logitech G815 | +| | +| Cheerpipe 20 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "LogitechG815Controller.h" #include +#include "LogitechG815Controller.h" +#include "StringUtils.h" -LogitechG815Controller::LogitechG815Controller(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12) +LogitechG815Controller::LogitechG815Controller(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12, std::string dev_name) { - dev_pkt_0x11 = dev_handle_0x11; - dev_pkt_0x12 = dev_handle_0x12; + dev_pkt_0x11 = dev_handle_0x11; + dev_pkt_0x12 = dev_handle_0x12; + name = dev_name; } LogitechG815Controller::~LogitechG815Controller() @@ -21,6 +25,11 @@ LogitechG815Controller::~LogitechG815Controller() } +std::string LogitechG815Controller::GetNameString() +{ + return(name); +} + std::string LogitechG815Controller::GetSerialString() { wchar_t serial_string[128]; @@ -31,10 +40,7 @@ std::string LogitechG815Controller::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void LogitechG815Controller::Commit() @@ -71,7 +77,7 @@ void LogitechG815Controller::SetMode void LogitechG815Controller::SendCommit() { - char usb_buf[20]; + unsigned char usb_buf[20]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -89,13 +95,13 @@ void LogitechG815Controller::SendCommit() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x11, (unsigned char *)usb_buf, 20); - hid_read_timeout(dev_pkt_0x11, (unsigned char *)usb_buf, 20, LOGITECH_READ_TIMEOUT); + hid_write(dev_pkt_0x11, usb_buf, 20); + hid_read_timeout(dev_pkt_0x11, usb_buf, 20, LOGITECH_READ_TIMEOUT); } void LogitechG815Controller::InitializeDirect() { - char usb_buf[20]; + unsigned char usb_buf[20]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -113,8 +119,8 @@ void LogitechG815Controller::InitializeDirect() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x11, (unsigned char *)usb_buf, 20); - hid_read(dev_pkt_0x11, (unsigned char *)usb_buf, 20); + hid_write(dev_pkt_0x11, usb_buf, 20); + hid_read(dev_pkt_0x11, usb_buf, 20); /*-----------------------------------------------------*\ | Zero out buffer | @@ -132,8 +138,8 @@ void LogitechG815Controller::InitializeDirect() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x11, (unsigned char *)usb_buf, 20); - hid_read(dev_pkt_0x11, (unsigned char *)usb_buf, 20); + hid_write(dev_pkt_0x11, usb_buf, 20); + hid_read(dev_pkt_0x11, usb_buf, 20); /*-----------------------------------------------------*\ | Zero out buffer | @@ -152,8 +158,8 @@ void LogitechG815Controller::InitializeDirect() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x11, (unsigned char *)usb_buf, 20); - hid_read(dev_pkt_0x11, (unsigned char *)usb_buf, 20); + hid_write(dev_pkt_0x11, usb_buf, 20); + hid_read(dev_pkt_0x11, usb_buf, 20); /*-----------------------------------------------------*\ | Zero out buffer | @@ -173,8 +179,8 @@ void LogitechG815Controller::InitializeDirect() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x11, (unsigned char *)usb_buf, 20); - hid_read(dev_pkt_0x11, (unsigned char *)usb_buf, 20); + hid_write(dev_pkt_0x11, usb_buf, 20); + hid_read(dev_pkt_0x11, usb_buf, 20); } void LogitechG815Controller::SendSingleLed @@ -185,7 +191,7 @@ void LogitechG815Controller::SendSingleLed unsigned char b ) { - char usb_buf[20]; + unsigned char usb_buf[20]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -209,8 +215,8 @@ void LogitechG815Controller::SendSingleLed /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x11, (unsigned char *)usb_buf, 20); - hid_read(dev_pkt_0x11, (unsigned char *)usb_buf, 20); + hid_write(dev_pkt_0x11, usb_buf, 20); + hid_read(dev_pkt_0x11, usb_buf, 20); } void LogitechG815Controller::SendDirectFrame @@ -219,7 +225,7 @@ void LogitechG815Controller::SendDirectFrame unsigned char * frame_data ) { - char usb_buf[20]; + unsigned char usb_buf[20]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -242,8 +248,8 @@ void LogitechG815Controller::SendDirectFrame /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x11, (unsigned char *)usb_buf, 20); - hid_read_timeout(dev_pkt_0x11, (unsigned char *)usb_buf, 20, LOGITECH_READ_TIMEOUT); + hid_write(dev_pkt_0x11, usb_buf, 20); + hid_read_timeout(dev_pkt_0x11, usb_buf, 20, LOGITECH_READ_TIMEOUT); } void LogitechG815Controller::SendMode @@ -256,7 +262,7 @@ void LogitechG815Controller::SendMode unsigned char blue ) { - char usb_buf[20]; + unsigned char usb_buf[20]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -266,7 +272,6 @@ void LogitechG815Controller::SendMode /*-----------------------------------------------------*\ | Set up Lighting Control packet | \*-----------------------------------------------------*/ - usb_buf[0x00] = 0x11; usb_buf[0x01] = 0xFF; usb_buf[0x02] = 0x0D; @@ -301,6 +306,6 @@ void LogitechG815Controller::SendMode /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x11, (unsigned char *)usb_buf, 20); - hid_read(dev_pkt_0x11, (unsigned char *)usb_buf, 20); + hid_write(dev_pkt_0x11, usb_buf, 20); + hid_read(dev_pkt_0x11, usb_buf, 20); } diff --git a/Controllers/LogitechController/LogitechG815Controller.h b/Controllers/LogitechController/LogitechG815Controller/LogitechG815Controller.h similarity index 82% rename from Controllers/LogitechController/LogitechG815Controller.h rename to Controllers/LogitechController/LogitechG815Controller/LogitechG815Controller.h index 1fd29f2d..618e6b7f 100644 --- a/Controllers/LogitechController/LogitechG815Controller.h +++ b/Controllers/LogitechController/LogitechG815Controller/LogitechG815Controller.h @@ -1,22 +1,23 @@ -/*-----------------------------------------*\ -| LogitechG815Controller.h | -| | -| Generic RGB Interface for Logitech G815 | -| RGB Mechanical Gaming Keyboard | -| | -| Cheerpipe 3/20/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LogitechG815Controller.h | +| | +| Driver for Logitech G815 | +| | +| Cheerpipe 20 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController.h" +#pragma once #include -#include +#include +#include "RGBController.h" #define LOGITECH_G815_COMMIT_BYTE 0x7F #define LOGITECH_READ_TIMEOUT 300 //Timeout in ms -#pragma once - enum { LOGITECH_G815_ZONE_MODE_KEYBOARD = 0x00, @@ -64,10 +65,12 @@ enum class LogitechG815Controller { public: - LogitechG815Controller(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12); + LogitechG815Controller(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12, std::string dev_name); ~LogitechG815Controller(); + std::string GetNameString(); std::string GetSerialString(); + void Commit(); void InitializeDirect(); void SetDirect @@ -94,6 +97,7 @@ public: private: hid_device* dev_pkt_0x11; hid_device* dev_pkt_0x12; + std::string name; void SendDirectFrame ( diff --git a/Controllers/LogitechController/RGBController_LogitechG815.cpp b/Controllers/LogitechController/LogitechG815Controller/RGBController_LogitechG815.cpp similarity index 94% rename from Controllers/LogitechController/RGBController_LogitechG815.cpp rename to Controllers/LogitechController/LogitechG815Controller/RGBController_LogitechG815.cpp index 76ef80d0..050cd259 100644 --- a/Controllers/LogitechController/RGBController_LogitechG815.cpp +++ b/Controllers/LogitechController/LogitechG815Controller/RGBController_LogitechG815.cpp @@ -1,17 +1,19 @@ -/*-----------------------------------------*\ -| RGBController_LogitechG815.cpp | -| | -| Generic RGB Interface for Logitech G815 | -| RGB Mechanical Gaming Keyboard | -| | -| Cheerpipe 3/20/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LogitechG815.cpp | +| | +| RGBController for Logitech G815 | +| | +| Cheerpipe 20 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBControllerKeyNames.h" -#include "RGBController_LogitechG815.h" #include #include #include +#include "RGBControllerKeyNames.h" +#include "RGBController_LogitechG815.h" #define NA 0xFFFFFFFF const size_t max_key_per_color = 13; @@ -46,9 +48,9 @@ typedef struct const char * name; const unsigned char zone; const unsigned char idx; -} led_type; +} logitech_g815_led; -static const led_type led_names[] = +static const logitech_g815_led led_names[] = { /* Key Label Zone, Index */ { KEY_EN_A, LOGITECH_G815_ZONE_DIRECT_KEYBOARD, 0x04 }, @@ -183,13 +185,13 @@ static const led_type led_names[] = RGBController_LogitechG815::RGBController_LogitechG815(LogitechG815Controller* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Logitech G815 Keyboard Device"; - vendor = "Logitech"; - type = DEVICE_TYPE_KEYBOARD; - description = "Logitech G815 Keyboard Device"; - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "Logitech"; + type = DEVICE_TYPE_KEYBOARD; + description = "Logitech G815 Keyboard Device"; + serial = controller->GetSerialString(); mode Direct; Direct.name = "Direct"; @@ -331,7 +333,7 @@ void RGBController_LogitechG815::DeviceUpdateLEDs() zone = ( leds[led_idx].value >> 8 ); idx = ( leds[led_idx].value ); - if (current_colors[led_idx]==new_colors[led_idx]) + if(current_colors[led_idx]==new_colors[led_idx]) { /*-------------------------------------------------*\ | Don't send if key color is not changed | @@ -364,7 +366,7 @@ void RGBController_LogitechG815::DeviceUpdateLEDs() colorkey = new_colors[led_idx]; - if (ledsByColors.count(colorkey) == 0) + if(ledsByColors.count(colorkey) == 0) { ledsByColors.insert(std::pair>(colorkey, {})); } @@ -398,16 +400,16 @@ void RGBController_LogitechG815::DeviceUpdateLEDs() frame_buffer_big_mode[2] = RGBGetBValue(x.first); frame_pos = 3; - for(uint8_t i = 0; i < max_key_per_color; i++) + for(uint8_t i = 0; i < (uint8_t)max_key_per_color; i++) { - if(bi + i < x.second.size()) + if((bi + i) < (uint8_t)x.second.size()) { frame_buffer_big_mode[frame_pos] = x.second[bi+i]; frame_pos++; } } - if (frame_pos < data_size) + if(frame_pos < data_size) { /*-----------------------------------------*\ | Zeroing just what is needed and if needed | @@ -444,7 +446,7 @@ void RGBController_LogitechG815::DeviceUpdateLEDs() li++; led_in_little_frame++; - if (led_in_little_frame == 4) + if(led_in_little_frame == 4) { /*-----------------------------------------*\ | No End of Data byte if the packet is full | @@ -465,7 +467,7 @@ void RGBController_LogitechG815::DeviceUpdateLEDs() /*-----------------------------------------------------*\ | Zeroing just what is needed | \*-----------------------------------------------------*/ - memset(frame_buffer_little_mode + (led_in_little_frame * 4 + 1), 0x00, sizeof(frame_buffer_little_mode) - led_in_little_frame * 4); + memset(frame_buffer_little_mode + (led_in_little_frame * 4 - 1), 0x00, sizeof(frame_buffer_little_mode) - led_in_little_frame * 4); /*-----------------------------------------------------*\ | Data byte | diff --git a/Controllers/LogitechController/LogitechG815Controller/RGBController_LogitechG815.h b/Controllers/LogitechController/LogitechG815Controller/RGBController_LogitechG815.h new file mode 100644 index 00000000..44d4711a --- /dev/null +++ b/Controllers/LogitechController/LogitechG815Controller/RGBController_LogitechG815.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_LogitechG815.h | +| | +| RGBController for Logitech G815 | +| | +| Cheerpipe 20 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LogitechG815Controller.h" + +class RGBController_LogitechG815 : public RGBController +{ +public: + RGBController_LogitechG815(LogitechG815Controller* controller_ptr); + ~RGBController_LogitechG815(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LogitechG815Controller* controller; + std::vector current_colors; +}; diff --git a/Controllers/LogitechController/LogitechG910Controller.cpp b/Controllers/LogitechController/LogitechG910Controller/LogitechG910Controller.cpp similarity index 79% rename from Controllers/LogitechController/LogitechG910Controller.cpp rename to Controllers/LogitechController/LogitechG910Controller/LogitechG910Controller.cpp index c212a45a..cdaf99b8 100644 --- a/Controllers/LogitechController/LogitechG910Controller.cpp +++ b/Controllers/LogitechController/LogitechG910Controller/LogitechG910Controller.cpp @@ -1,19 +1,23 @@ -/*-----------------------------------------*\ -| LogitechG910Controller.cpp | -| | -| Driver for Logitech G910 Orion Spectrum | -| keyboard light controller | -| | -| Adam Honse (CalcProgrammer1) 6/11/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LogitechG910Controller.cpp | +| | +| Driver for Logitech G910 Orion Spectrum | +| | +| Adam Honse (CalcProgrammer1) 11 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "LogitechG910Controller.h" #include +#include "LogitechG910Controller.h" +#include "StringUtils.h" -LogitechG910Controller::LogitechG910Controller(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12) +LogitechG910Controller::LogitechG910Controller(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12, std::string dev_name) { - dev_pkt_0x11 = dev_handle_0x11; - dev_pkt_0x12 = dev_handle_0x12; + dev_pkt_0x11 = dev_handle_0x11; + dev_pkt_0x12 = dev_handle_0x12; + name = dev_name; } LogitechG910Controller::~LogitechG910Controller() @@ -22,6 +26,11 @@ LogitechG910Controller::~LogitechG910Controller() hid_close(dev_pkt_0x12); } +std::string LogitechG910Controller::GetNameString() +{ + return(name); +} + std::string LogitechG910Controller::GetSerialString() { wchar_t serial_string[128]; @@ -32,10 +41,7 @@ std::string LogitechG910Controller::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void LogitechG910Controller::Commit() @@ -74,7 +80,7 @@ void LogitechG910Controller::SetMode void LogitechG910Controller::SendCommit() { - char usb_buf[20]; + unsigned char usb_buf[20]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -92,8 +98,8 @@ void LogitechG910Controller::SendCommit() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x11, (unsigned char *)usb_buf, 20); - hid_read(dev_pkt_0x11, (unsigned char *)usb_buf, 20); + hid_write(dev_pkt_0x11, usb_buf, 20); + hid_read(dev_pkt_0x11, usb_buf, 20); } void LogitechG910Controller::SendDirectFrame @@ -103,7 +109,7 @@ void LogitechG910Controller::SendDirectFrame unsigned char * frame_data ) { - char usb_buf[64]; + unsigned char usb_buf[64]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -128,8 +134,8 @@ void LogitechG910Controller::SendDirectFrame /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x12, (unsigned char *)usb_buf, 64); - hid_read(dev_pkt_0x11, (unsigned char *)usb_buf, 20); + hid_write(dev_pkt_0x12, usb_buf, 64); + hid_read(dev_pkt_0x11, usb_buf, 20); } void LogitechG910Controller::SendMode @@ -142,7 +148,7 @@ void LogitechG910Controller::SendMode unsigned char blue ) { - char usb_buf[20]; + unsigned char usb_buf[20]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -181,6 +187,6 @@ void LogitechG910Controller::SendMode /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x11, (unsigned char *)usb_buf, 20); - hid_read(dev_pkt_0x11, (unsigned char *)usb_buf, 20); + hid_write(dev_pkt_0x11, usb_buf, 20); + hid_read(dev_pkt_0x11, usb_buf, 20); } diff --git a/Controllers/LogitechController/LogitechG910Controller.h b/Controllers/LogitechController/LogitechG910Controller/LogitechG910Controller.h similarity index 78% rename from Controllers/LogitechController/LogitechG910Controller.h rename to Controllers/LogitechController/LogitechG910Controller/LogitechG910Controller.h index 317fc4e2..91a509c7 100644 --- a/Controllers/LogitechController/LogitechG910Controller.h +++ b/Controllers/LogitechController/LogitechG910Controller/LogitechG910Controller.h @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| LogitechG910Controller.h | -| | -| Definitions and types for Logitech G910 | -| Orion Spectrum keyboard light controller | -| | -| Adam Honse (CalcProgrammer1) 6/11/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| LogitechG910Controller.h | +| | +| Driver for Logitech G910 Orion Spectrum | +| | +| Adam Honse (CalcProgrammer1) 11 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + enum { LOGITECH_G910_ZONE_MODE_KEYBOARD = 0x00, @@ -51,13 +52,14 @@ enum class LogitechG910Controller { public: - LogitechG910Controller(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12); + LogitechG910Controller(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12, std::string dev_name); ~LogitechG910Controller(); + std::string GetNameString(); std::string GetSerialString(); void Commit(); - + void SetDirect ( unsigned char zone, @@ -77,6 +79,7 @@ public: private: hid_device* dev_pkt_0x11; hid_device* dev_pkt_0x12; + std::string name; void SendDirectFrame ( diff --git a/Controllers/LogitechController/RGBController_LogitechG910.cpp b/Controllers/LogitechController/LogitechG910Controller/RGBController_LogitechG910.cpp similarity index 93% rename from Controllers/LogitechController/RGBController_LogitechG910.cpp rename to Controllers/LogitechController/LogitechG910Controller/RGBController_LogitechG910.cpp index cb82fdf5..f94b9998 100644 --- a/Controllers/LogitechController/RGBController_LogitechG910.cpp +++ b/Controllers/LogitechController/LogitechG910Controller/RGBController_LogitechG910.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_LogitechG910.cpp | -| | -| Generic RGB Interface for Logitech G910 | -| Orion Spectrum Keyboard | -| | -| Adam Honse (CalcProgrammer1) 6/12/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LogitechG910.cpp | +| | +| RGBController for Logitech G910 Orion Spectrum | +| | +| Adam Honse (CalcProgrammer1) 12 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_LogitechG910.h" @@ -180,13 +182,13 @@ static const led_type led_names[] = RGBController_LogitechG910::RGBController_LogitechG910(LogitechG910Controller* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Logitech Keyboard Device"; - vendor = "Logitech"; - type = DEVICE_TYPE_KEYBOARD; - description = "Logitech Keyboard Device"; - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "Logitech"; + type = DEVICE_TYPE_KEYBOARD; + description = "Logitech Keyboard Device"; + serial = controller->GetSerialString(); mode Direct; Direct.name = "Direct"; diff --git a/Controllers/LogitechController/LogitechG910Controller/RGBController_LogitechG910.h b/Controllers/LogitechController/LogitechG910Controller/RGBController_LogitechG910.h new file mode 100644 index 00000000..53a04b6d --- /dev/null +++ b/Controllers/LogitechController/LogitechG910Controller/RGBController_LogitechG910.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_LogitechG910.h | +| | +| RGBController for Logitech G910 Orion Spectrum | +| | +| Adam Honse (CalcProgrammer1) 12 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LogitechG910Controller.h" + +class RGBController_LogitechG910 : public RGBController +{ +public: + RGBController_LogitechG910(LogitechG910Controller* controller_ptr); + ~RGBController_LogitechG910(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LogitechG910Controller* controller; +}; diff --git a/Controllers/LogitechController/LogitechG915Controller.h b/Controllers/LogitechController/LogitechG915Controller.h deleted file mode 100644 index 9bbad50f..00000000 --- a/Controllers/LogitechController/LogitechG915Controller.h +++ /dev/null @@ -1,139 +0,0 @@ -/*-----------------------------------------*\ -| LogitechG915Controller.h | -| | -| Generic RGB Interface for Logitech G915 | -| RGB Mechanical Gaming Keyboard | -| | -| Cheerpipe 3/20/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include - -#define LOGITECH_G915_COMMIT_BYTE 0x7F -#define LOGITECH_READ_TIMEOUT 300 //Timeout in ms - -#pragma once - -enum -{ - LOGITECH_G915_ZONE_MODE_KEYBOARD = 0x01, - LOGITECH_G915_ZONE_MODE_LOGO = 0x00, - LOGITECH_G915_ZONE_MODE_MULTIMEDIA = 0x02, - LOGITECH_G915_ZONE_MODE_GKEYS = 0x03, - LOGITECH_G915_ZONE_MODE_MODIFIERS = 0x04 -}; - -enum -{ - LOGITECH_G915_ZONE_FRAME_TYPE_LITTLE = 0x1F, - LOGITECH_G915_ZONE_FRAME_TYPE_BIG = 0x6F -}; - -enum -{ - LOGITECH_G915_ZONE_DIRECT_KEYBOARD = 0x01, - LOGITECH_G915_ZONE_DIRECT_MEDIA = 0x02, - LOGITECH_G915_ZONE_DIRECT_LOGO = 0x10, - LOGITECH_G915_ZONE_DIRECT_INDICATORS = 0x40, -}; - -enum -{ - LOGITECH_G915_MODE_OFF = 0x00, - LOGITECH_G915_MODE_STATIC = 0x01, - LOGITECH_G915_MODE_BREATHING = 0x02, - LOGITECH_G915_MODE_CYCLE = 0x03, - LOGITECH_G915_MODE_WAVE = 0x04, - LOGITECH_G915_MODE_RIPPLE = 0x05, - LOGITECH_G915_MODE_DIRECT = 0xFF, -}; - -enum -{ - LOGITECH_G915_LOGO_MODE_OFF = 0x00, - LOGITECH_G915_LOGO_MODE_STATIC = 0x01, - LOGITECH_G915_LOGO_MODE_CYCLE = 0x02, - LOGITECH_G915_LOGO_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_G915_SPEED_SLOWEST = 0xC8, /* Slowest speed */ - LOGITECH_G915_SPEED_NORMAL = 0x32, /* Normal speed */ - LOGITECH_G915_SPEED_FASTEST = 0x0A, /* Fastest speed */ -}; - -/* Ripple speeds are in ms directly. */ -enum -{ - LOGITECH_G915_SPEED_RIPPLE_SLOW = 200, - LOGITECH_G915_SPEED_RIPPLE_NORMAL = 20, - LOGITECH_G915_SPEED_RIPPLE_FAST = 2, -}; - -class LogitechG915Controller -{ -public: - LogitechG915Controller(hid_device* dev_handle, bool wired); - ~LogitechG915Controller(); - - std::string GetSerialString(); - void Commit(); - void InitializeDirect(); - void InitializeModeSet(); - void BeginModeSet(); - void SetDirect - ( - unsigned char frame_type, - unsigned char * frame_data - ); - void SendSingleLed - ( - unsigned char keyCode, - unsigned char r, - unsigned char g, - unsigned char b - ); - void SetMode - ( - unsigned char mode, - unsigned short speed, - unsigned short brightness, - unsigned char red, - unsigned char green, - unsigned char blue - ); - -private: - hid_device* dev_handle; - char feature_4522_idx; - char device_index; - char feature_8040_idx; - char feature_8071_idx; - char feature_8081_idx; - - void SendDirectFrame - ( - unsigned char frame_type, - unsigned char * frame_data - ); - - void SendMode - ( - unsigned char zone, - unsigned char mode, - unsigned short speed, - unsigned short brightness, - unsigned char red, - unsigned char green, - unsigned char blue - ); - void SendCommit(); -}; diff --git a/Controllers/LogitechController/LogitechG915Controller.cpp b/Controllers/LogitechController/LogitechG915Controller/LogitechG915Controller.cpp similarity index 78% rename from Controllers/LogitechController/LogitechG915Controller.cpp rename to Controllers/LogitechController/LogitechG915Controller/LogitechG915Controller.cpp index cf48a605..a7fe0565 100644 --- a/Controllers/LogitechController/LogitechG915Controller.cpp +++ b/Controllers/LogitechController/LogitechG915Controller/LogitechG915Controller.cpp @@ -1,34 +1,44 @@ -/*-----------------------------------------*\ -| LogitechG915Controller.cpp | -| | -| Generic RGB Interface for Logitech G915 | -| RGB Mechanical Gaming Keyboard | -| | -| Cheerpipe 3/20/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LogitechG915Controller.cpp | +| | +| Driver for Logitech G915 | +| | +| Cheerpipe 20 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "LogitechG915Controller.h" #include +#include "LogitechG915Controller.h" +#include "StringUtils.h" -LogitechG915Controller::LogitechG915Controller(hid_device* dev_handle, bool wired) +const size_t MIN_DATA_FRAME_SIZE = 4; +const size_t MAX_DATA_FRAME_SIZE = 16; +const size_t HEADER_SIZE = 4; +const size_t MESSAGE_LEN = 20; +const size_t RESPONSE_LEN = 20; + +LogitechG915Controller::LogitechG915Controller(hid_device* dev_handle, bool wired, std::string dev_name) { - this->dev_handle = dev_handle; + this->dev_handle = dev_handle; + this->name = dev_name; if(wired) { - device_index = 0xFF; - feature_4522_idx = 0x0E; - feature_8040_idx = 0x13; - feature_8071_idx = 0x09; - feature_8081_idx = 0x0A; + device_index = 0xFF; + feature_4522_idx = 0x0E; + feature_8040_idx = 0x13; + feature_8071_idx = 0x09; + feature_8081_idx = 0x0A; } else { - device_index = 0x01; - feature_4522_idx = 0x0F; - feature_8040_idx = 0x14; - feature_8071_idx = 0x0A; - feature_8081_idx = 0x0B; + device_index = 0x01; + feature_4522_idx = 0x0F; + feature_8040_idx = 0x14; + feature_8071_idx = 0x0A; + feature_8081_idx = 0x0B; } } @@ -37,6 +47,11 @@ LogitechG915Controller::~LogitechG915Controller() } +std::string LogitechG915Controller::GetNameString() +{ + return(name); +} + std::string LogitechG915Controller::GetSerialString() { wchar_t serial_string[128]; @@ -47,10 +62,7 @@ std::string LogitechG915Controller::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void LogitechG915Controller::Commit() @@ -61,10 +73,11 @@ void LogitechG915Controller::Commit() void LogitechG915Controller::SetDirect ( unsigned char frame_type, - unsigned char * frame_data + unsigned char * frame_data, + size_t length ) { - SendDirectFrame(frame_type, frame_data); + SendDirectFrame(frame_type, frame_data, length); } void LogitechG915Controller::SetMode @@ -115,7 +128,7 @@ void LogitechG915Controller::SetMode void LogitechG915Controller::SendCommit() { - char usb_buf[20]; + unsigned char usb_buf[MESSAGE_LEN]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -133,13 +146,13 @@ void LogitechG915Controller::SendCommit() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_handle, (unsigned char *)usb_buf, 20); - hid_read_timeout(dev_handle, (unsigned char *)usb_buf, 20, LOGITECH_READ_TIMEOUT); + hid_write(dev_handle, usb_buf, 4); + hid_read_timeout(dev_handle, usb_buf, RESPONSE_LEN, LOGITECH_READ_TIMEOUT); } void LogitechG915Controller::BeginModeSet() { - char usb_buf[20]; + unsigned char usb_buf[MESSAGE_LEN]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -157,8 +170,8 @@ void LogitechG915Controller::BeginModeSet() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_handle, (unsigned char *)usb_buf, 20); - hid_read(dev_handle, (unsigned char *)usb_buf, 20); + hid_write(dev_handle, usb_buf, 4); + hid_read(dev_handle, usb_buf, RESPONSE_LEN); /*-----------------------------------------------------*\ | Zero out buffer | @@ -176,13 +189,13 @@ void LogitechG915Controller::BeginModeSet() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_handle, (unsigned char *)usb_buf, 20); - hid_read(dev_handle, (unsigned char *)usb_buf, 20); + hid_write(dev_handle, usb_buf, 4); + hid_read(dev_handle, usb_buf, RESPONSE_LEN); } void LogitechG915Controller::InitializeModeSet() { - char usb_buf[20]; + unsigned char usb_buf[20]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -203,13 +216,13 @@ void LogitechG915Controller::InitializeModeSet() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_handle, (unsigned char *)usb_buf, 20); - hid_read(dev_handle, (unsigned char *)usb_buf, 20); + hid_write(dev_handle, usb_buf, 7); + hid_read(dev_handle, usb_buf, RESPONSE_LEN); } void LogitechG915Controller::InitializeDirect() { - char usb_buf[20]; + unsigned char usb_buf[MESSAGE_LEN]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -227,8 +240,8 @@ void LogitechG915Controller::InitializeDirect() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_handle, (unsigned char *)usb_buf, 20); - hid_read(dev_handle, (unsigned char *)usb_buf, 20); + hid_write(dev_handle, usb_buf, 4); + hid_read(dev_handle, usb_buf, RESPONSE_LEN); /*-----------------------------------------------------*\ | Zero out buffer | @@ -246,8 +259,8 @@ void LogitechG915Controller::InitializeDirect() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_handle, (unsigned char *)usb_buf, 20); - hid_read(dev_handle, (unsigned char *)usb_buf, 20); + hid_write(dev_handle, usb_buf, 4); + hid_read(dev_handle, usb_buf, RESPONSE_LEN); /*-----------------------------------------------------*\ | Zero out buffer | @@ -266,8 +279,8 @@ void LogitechG915Controller::InitializeDirect() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_handle, (unsigned char *)usb_buf, 20); - hid_read(dev_handle, (unsigned char *)usb_buf, 20); + hid_write(dev_handle, usb_buf, 17); + hid_read(dev_handle, usb_buf, MESSAGE_LEN); /*-----------------------------------------------------*\ | Zero out buffer | @@ -287,8 +300,8 @@ void LogitechG915Controller::InitializeDirect() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_handle, (unsigned char *)usb_buf, 20); - hid_read(dev_handle, (unsigned char *)usb_buf, 20); + hid_write(dev_handle, usb_buf, 17); + hid_read(dev_handle, usb_buf, RESPONSE_LEN); } void LogitechG915Controller::SendSingleLed @@ -299,41 +312,27 @@ void LogitechG915Controller::SendSingleLed unsigned char b ) { - char usb_buf[20]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, sizeof(usb_buf)); - - /*-----------------------------------------------------*\ - | Set up a 6F packet with a single color | - \*-----------------------------------------------------*/ - usb_buf[0x00] = 0x11; - usb_buf[0x01] = device_index; - usb_buf[0x02] = feature_8081_idx; - usb_buf[0x03] = LOGITECH_G915_ZONE_FRAME_TYPE_LITTLE; - - usb_buf[0x04] = keyCode; - - usb_buf[0x05] = r; - usb_buf[0x06] = g; - usb_buf[0x07] = b; - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_write(dev_handle, (unsigned char *)usb_buf, 20); - hid_read(dev_handle, (unsigned char *)usb_buf, 20); + unsigned char little_frame[4] = { keyCode, r, g, b }; + SendDirectFrame(LOGITECH_G915_ZONE_FRAME_TYPE_LITTLE, little_frame, 4); } void LogitechG915Controller::SendDirectFrame ( unsigned char frame_type, - unsigned char * frame_data + unsigned char * frame_data, + size_t length ) { - char usb_buf[20]; + if(length < MIN_DATA_FRAME_SIZE) + { + return; + } + else if(length > MAX_DATA_FRAME_SIZE) + { + length = MAX_DATA_FRAME_SIZE; + } + + unsigned char usb_buf[MESSAGE_LEN]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -351,13 +350,13 @@ void LogitechG915Controller::SendDirectFrame /*-----------------------------------------------------*\ | Copy in frame data | \*-----------------------------------------------------*/ - memcpy(&usb_buf[0x04], frame_data, 16); + memcpy(&usb_buf[0x04], frame_data, length); /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_handle, (unsigned char *)usb_buf, 20); - hid_read_timeout(dev_handle, (unsigned char *)usb_buf, 20, LOGITECH_READ_TIMEOUT); + hid_write(dev_handle, usb_buf, HEADER_SIZE + length); + hid_read_timeout(dev_handle, usb_buf, RESPONSE_LEN, LOGITECH_READ_TIMEOUT); } void LogitechG915Controller::SendMode @@ -371,7 +370,7 @@ void LogitechG915Controller::SendMode unsigned char blue ) { - char usb_buf[20]; + unsigned char usb_buf[HEADER_SIZE + 13]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -385,7 +384,7 @@ void LogitechG915Controller::SendMode usb_buf[0x00] = 0x11; usb_buf[0x01] = device_index; usb_buf[0x02] = feature_8071_idx; - usb_buf[0x03] = 0x1E; + usb_buf[0x03] = LOGITECH_G915_ZONE_FRAME_TYPE_MODE; usb_buf[0x04] = zone; usb_buf[0x05] = mode; @@ -434,6 +433,6 @@ void LogitechG915Controller::SendMode /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_handle, (unsigned char *)usb_buf, 20); - hid_read(dev_handle, (unsigned char *)usb_buf, 20); + hid_write(dev_handle, usb_buf, HEADER_SIZE + 13); + hid_read(dev_handle, usb_buf, RESPONSE_LEN); } diff --git a/Controllers/LogitechController/LogitechG915Controller/LogitechG915Controller.h b/Controllers/LogitechController/LogitechG915Controller/LogitechG915Controller.h new file mode 100644 index 00000000..729c3a32 --- /dev/null +++ b/Controllers/LogitechController/LogitechG915Controller/LogitechG915Controller.h @@ -0,0 +1,146 @@ +/*---------------------------------------------------------*\ +| LogitechG915Controller.h | +| | +| Driver for Logitech G915 | +| | +| Cheerpipe 20 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define LOGITECH_G915_COMMIT_BYTE 0x7F +#define LOGITECH_READ_TIMEOUT 300 //Timeout in ms + +enum +{ + LOGITECH_G915_ZONE_MODE_KEYBOARD = 0x01, + LOGITECH_G915_ZONE_MODE_LOGO = 0x00, + LOGITECH_G915_ZONE_MODE_MULTIMEDIA = 0x02, + LOGITECH_G915_ZONE_MODE_GKEYS = 0x03, + LOGITECH_G915_ZONE_MODE_MODIFIERS = 0x04 +}; + +enum +{ + LOGITECH_G915_ZONE_FRAME_TYPE_LITTLE = 0x1F, + LOGITECH_G915_ZONE_FRAME_TYPE_BIG = 0x6F, + LOGITECH_G915_ZONE_FRAME_TYPE_MODE = 0x1E +}; + +enum +{ + LOGITECH_G915_ZONE_DIRECT_KEYBOARD = 0x01, + LOGITECH_G915_ZONE_DIRECT_MEDIA = 0x02, + LOGITECH_G915_ZONE_DIRECT_LOGO = 0x10, + LOGITECH_G915_ZONE_DIRECT_INDICATORS = 0x40, +}; + +enum +{ + LOGITECH_G915_MODE_OFF = 0x00, + LOGITECH_G915_MODE_STATIC = 0x01, + LOGITECH_G915_MODE_BREATHING = 0x02, + LOGITECH_G915_MODE_CYCLE = 0x03, + LOGITECH_G915_MODE_WAVE = 0x04, + LOGITECH_G915_MODE_RIPPLE = 0x05, + LOGITECH_G915_MODE_DIRECT = 0xFF, +}; + +enum +{ + LOGITECH_G915_LOGO_MODE_OFF = 0x00, + LOGITECH_G915_LOGO_MODE_STATIC = 0x01, + LOGITECH_G915_LOGO_MODE_CYCLE = 0x02, + LOGITECH_G915_LOGO_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_G915_SPEED_SLOWEST = 0xC8, /* Slowest speed */ + LOGITECH_G915_SPEED_NORMAL = 0x32, /* Normal speed */ + LOGITECH_G915_SPEED_FASTEST = 0x0A, /* Fastest speed */ +}; + +/* Ripple speeds are in ms directly. */ +enum +{ + LOGITECH_G915_SPEED_RIPPLE_SLOW = 200, + LOGITECH_G915_SPEED_RIPPLE_NORMAL = 20, + LOGITECH_G915_SPEED_RIPPLE_FAST = 2, +}; + +class LogitechG915Controller +{ +public: + LogitechG915Controller(hid_device* dev_handle, bool wired, std::string dev_name); + ~LogitechG915Controller(); + + std::string GetNameString(); + std::string GetSerialString(); + + void Commit(); + void InitializeDirect(); + void InitializeModeSet(); + void BeginModeSet(); + void SetDirect + ( + unsigned char frame_type, + unsigned char * frame_data, + size_t length + ); + void SendSingleLed + ( + unsigned char keyCode, + unsigned char r, + unsigned char g, + unsigned char b + ); + void SetMode + ( + unsigned char mode, + unsigned short speed, + unsigned short brightness, + unsigned char red, + unsigned char green, + unsigned char blue + ); + +private: + hid_device* dev_handle; + unsigned char feature_4522_idx; + unsigned char device_index; + unsigned char feature_8040_idx; + unsigned char feature_8071_idx; + unsigned char feature_8081_idx; + std::string name; + + void SendDirectFrame + ( + unsigned char frame_type, + unsigned char * frame_data, + size_t length + ); + + void SendMode + ( + unsigned char zone, + unsigned char mode, + unsigned short speed, + unsigned short brightness, + unsigned char red, + unsigned char green, + unsigned char blue + ); + void SendCommit(); +}; diff --git a/Controllers/LogitechController/RGBController_LogitechG915.cpp b/Controllers/LogitechController/LogitechG915Controller/RGBController_LogitechG915.cpp similarity index 78% rename from Controllers/LogitechController/RGBController_LogitechG915.cpp rename to Controllers/LogitechController/LogitechG915Controller/RGBController_LogitechG915.cpp index 2177ae3d..6518b6fb 100644 --- a/Controllers/LogitechController/RGBController_LogitechG915.cpp +++ b/Controllers/LogitechController/LogitechG915Controller/RGBController_LogitechG915.cpp @@ -1,21 +1,24 @@ -/*-----------------------------------------*\ -| RGBController_LogitechG915.cpp | -| | -| Generic RGB Interface for Logitech G915 | -| RGB Mechanical Gaming Keyboard | -| | -| Cheerpipe 3/20/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LogitechG915.cpp | +| | +| RGBController for Logitech G915 | +| | +| Cheerpipe 20 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBControllerKeyNames.h" -#include "RGBController_LogitechG915.h" #include #include #include +#include "RGBControllerKeyNames.h" +#include "RGBController_LogitechG915.h" #define NA 0xFFFFFFFF -const size_t max_key_per_color = 13; -const size_t data_size = 16; +const size_t DATA_FRAME_SIZE = 16; +const size_t BIG_FRAME_MAX_KEYS = 13; +const size_t LITTLE_FRAME_MAX_KEYS = 4; static unsigned int matrix_map[7][27] = { { 93, NA, NA, NA, NA, NA, NA, NA, NA, NA, 94, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA }, @@ -48,11 +51,6 @@ static zone_type zone_types[] = static const unsigned int tkl_led_count = 95; static const unsigned int full_led_count = 117; -static const unsigned int zone_sizes[] = -{ - 117, -}; - typedef struct { const char * name; @@ -182,6 +180,90 @@ static const led_type led_names[] = { "Key: G5", LOGITECH_G915_ZONE_MODE_GKEYS, 0x05 }, }; +/*--------------------------------------*\ +| Small dataframe | +| Contains a max of 4 pairs | +\*--------------------------------------*/ +struct LittleFrame +{ + std::pair color_key[LITTLE_FRAME_MAX_KEYS]; + size_t len = 0; +}; + +/*--------------------------------------*\ +| Small dataframe | +| Contains 1 color for max 13 keys | +\*--------------------------------------*/ +struct BigFrame +{ + RGBColor color; + char keys[BIG_FRAME_MAX_KEYS]; + size_t len = 0; +}; + +/*-------------------------------------------*\ +| Add termination byte and zero out rest | +\*-------------------------------------------*/ +void terminate_buffer(unsigned char buf[DATA_FRAME_SIZE], size_t idx) +{ + memset(&buf[idx], 0x00, DATA_FRAME_SIZE - idx); + buf[idx] = 0xFF; +} + +/*-------------------------------------------*\ +| small frame: [KEY, R, G, B] | +| If less than 4 keys, terminate using 0xFF | +\*-------------------------------------------*/ +size_t populate_little_frame_data(unsigned char buf[DATA_FRAME_SIZE], const LittleFrame& frame) +{ + if(frame.len == 0) + { + return 0; + } + + for(size_t i = 0; i < frame.len && i < LITTLE_FRAME_MAX_KEYS; i++) + { + buf[4 * i + 0] = frame.color_key[i].second; + buf[4 * i + 1] = RGBGetRValue(frame.color_key[i].first); + buf[4 * i + 2] = RGBGetGValue(frame.color_key[i].first); + buf[4 * i + 3] = RGBGetBValue(frame.color_key[i].first); + } + + if(frame.len < LITTLE_FRAME_MAX_KEYS) + { + terminate_buffer(buf, 4 * frame.len); + return 4 * frame.len + 1; // termination byte + } + return DATA_FRAME_SIZE; +} + +/*-------------------------------------------------*\ +| Large frame: [R, G, B, Key0, Key1, ..., Key12] | +| If less than 13 keys, terminate using 0xFF | +\*--------------------------------------------------*/ +size_t populate_big_frame_data(unsigned char buf[DATA_FRAME_SIZE], const BigFrame& frame) +{ + if(frame.len == 0) + { + return 0; + } + + buf[0] = RGBGetRValue(frame.color); + buf[1] = RGBGetGValue(frame.color); + buf[2] = RGBGetBValue(frame.color); + for(size_t i = 0; i < frame.len && i < BIG_FRAME_MAX_KEYS; i++) + { + buf[i + 3] = frame.keys[i]; + } + + if(frame.len < BIG_FRAME_MAX_KEYS) + { + terminate_buffer(buf, frame.len + 3); + return frame.len + 4; // color + termination byte + } + return DATA_FRAME_SIZE; +} + /**------------------------------------------------------------------*\ @name Logitech G915 @category Keyboard @@ -200,14 +282,14 @@ RGBController_LogitechG915::RGBController_LogitechG915(LogitechG915Controller* c if(is_tkl) { - name = "Logitech G915TKL Keyboard Device"; + description = "Logitech G915TKL Keyboard Device"; } else { - name = "Logitech G915 Keyboard Device"; + description = "Logitech G915 Keyboard Device"; } - description = name; + name = controller->GetNameString(); vendor = "Logitech"; type = DEVICE_TYPE_KEYBOARD; serial = controller->GetSerialString(); @@ -378,8 +460,6 @@ void RGBController_LogitechG915::DeviceUpdateLEDs() std::vector new_colors; unsigned char zone = 0; unsigned char idx = 0; - unsigned char frame_buffer_big_mode[data_size]; - unsigned char frame_buffer_little_mode[data_size]; RGBColor colorkey; /*---------------------------------------------------------*\ @@ -396,7 +476,7 @@ void RGBController_LogitechG915::DeviceUpdateLEDs() zone = ( leds[led_idx].value >> 8 ); idx = ( leds[led_idx].value ); - if (current_colors[led_idx]==new_colors[led_idx]) + if(current_colors[led_idx]==new_colors[led_idx]) { /*-------------------------------------------------*\ | Don't send if key color is not changed | @@ -404,7 +484,7 @@ void RGBController_LogitechG915::DeviceUpdateLEDs() continue; } - switch (zone) + switch(zone) { case LOGITECH_G915_ZONE_MODE_GKEYS: idx = ((idx & 0x00ff) + 0xb3); @@ -429,7 +509,7 @@ void RGBController_LogitechG915::DeviceUpdateLEDs() colorkey = new_colors[led_idx]; - if (ledsByColors.count(colorkey) == 0) + if(ledsByColors.count(colorkey) == 0) { ledsByColors.insert(std::pair>(colorkey, {})); } @@ -437,10 +517,23 @@ void RGBController_LogitechG915::DeviceUpdateLEDs() ledsByColors[colorkey].push_back(idx); } - uint8_t led_in_little_frame = 0; - uint8_t bi = 0; - size_t frame_pos = 3; - uint8_t li = 0; + /*-------------------------------------------------*\ + | Nothing to do, we can skip rest of work | + \*-------------------------------------------------*/ + if(ledsByColors.size() == 0) + { + return; + } + + /*-----------------------------------------------------*\ + | Copy the current color vector to avoid set keys that | + | have not changed | + \*-----------------------------------------------------*/ + std::copy(new_colors.begin(), new_colors.end(),current_colors.begin()); + + std::vector little_frames; + std::vector big_frames; + LittleFrame cur_small; /*---------------------------------------------------------*\ | Create frame_buffers of type 1F (Little, up to 4 leds | @@ -448,109 +541,71 @@ void RGBController_LogitechG915::DeviceUpdateLEDs() \*---------------------------------------------------------*/ for(std::pair>& x: ledsByColors) { - /*-----------------------------------------------------*\ - | For colors with more than 4 keys. Better to use big | - | (6F) packets to save USB transfers. | - \*-----------------------------------------------------*/ - if(x.second.size() > 4) + for(size_t bi = 0; bi < x.second.size(); bi += BIG_FRAME_MAX_KEYS) { - bi = 0; + size_t n_colors_left = x.second.size() - bi; - while(bi < x.second.size()) + /*-----------------------------------------------------*\ + | For colors with more than 4 keys. Better to use big | + | (6F) packets to save USB transfers. | + \*-----------------------------------------------------*/ + if(n_colors_left > 4) { - frame_buffer_big_mode[0] = RGBGetRValue(x.first); - frame_buffer_big_mode[1] = RGBGetGValue(x.first); - frame_buffer_big_mode[2] = RGBGetBValue(x.first); - frame_pos = 3; + BigFrame b_frame; + b_frame.color = x.first; - for(uint8_t i = 0; i < max_key_per_color; i++) + for(size_t i = 0; i < BIG_FRAME_MAX_KEYS && i < n_colors_left; i++) { - if(bi + i < x.second.size()) + b_frame.keys[i] = x.second[bi + i]; + b_frame.len++; + } + big_frames.push_back(b_frame); + } + /*-----------------------------------------------------*\ + | For colors with up to 4 keys. Use 1F packet to send | + | up to 4 colors-keys combinations per packet. | + \*-----------------------------------------------------*/ + else + { + for(size_t li = 0; li < n_colors_left; li++) + { + cur_small.color_key[cur_small.len] = std::make_pair(x.first, x.second[bi + li]); + cur_small.len++; + /*-------------------------------*\ + | Frame is full, create a new one | + \*-------------------------------*/ + if(cur_small.len >= LITTLE_FRAME_MAX_KEYS) { - frame_buffer_big_mode[frame_pos] = x.second[bi+i]; - frame_pos++; + little_frames.push_back(std::move(cur_small)); + cur_small = LittleFrame(); } } - - if (frame_pos < data_size) - { - /*-----------------------------------------*\ - | Zeroing just what is needed and if needed | - \*-----------------------------------------*/ - memset(frame_buffer_big_mode + frame_pos, 0x00, sizeof(frame_buffer_big_mode) - frame_pos); - - /*-----------------------------------------*\ - | End of Data byte | - \*-----------------------------------------*/ - frame_buffer_big_mode[frame_pos] = 0xFF; - } - - /*-----------------------------------------------------*\ - | Zeroing just what is needed | - \*-----------------------------------------------------*/ - controller->SetDirect(LOGITECH_G915_ZONE_FRAME_TYPE_BIG, frame_buffer_big_mode); - bi = bi + max_key_per_color; - } - } - /*-----------------------------------------------------*\ - | For colors with up to 4 keys. Use 1F packet to send | - | up to 4 colors-keys combinations per packet. | - \*-----------------------------------------------------*/ - else - { - li = 0; - - while(li < x.second.size()) - { - frame_buffer_little_mode[led_in_little_frame*4 + 0] = x.second[li]; - frame_buffer_little_mode[led_in_little_frame*4 + 1] = RGBGetRValue(x.first); - frame_buffer_little_mode[led_in_little_frame*4 + 2] = RGBGetGValue(x.first); - frame_buffer_little_mode[led_in_little_frame*4 + 3] = RGBGetBValue(x.first); - li++; - led_in_little_frame++; - - if (led_in_little_frame == 4) - { - /*-----------------------------------------*\ - | No End of Data byte if the packet is full | - \*-----------------------------------------*/ - controller->SetDirect(LOGITECH_G915_ZONE_FRAME_TYPE_LITTLE, frame_buffer_little_mode); - led_in_little_frame=0; - } } } } - /*---------------------------------------------------------*\ - | If there is a left 1F packet with less than 4 keys, send | - | it and add an End of Data byte. | - \*---------------------------------------------------------*/ - if(led_in_little_frame > 0) + /*-------------------------------*\ + | Move leftover small frame | + \*-------------------------------*/ + if(cur_small.len > 0) { - /*-----------------------------------------------------*\ - | Zeroing just what is needed | - \*-----------------------------------------------------*/ - memset(frame_buffer_little_mode + (led_in_little_frame * 4 + 1), 0x00, sizeof(frame_buffer_little_mode) - led_in_little_frame * 4); - - /*-----------------------------------------------------*\ - | Data byte | - \*-----------------------------------------------------*/ - frame_buffer_little_mode[led_in_little_frame*4 + 0] = 0xFF; - - /*-----------------------------------------------------*\ - | Send little frame and clear little frame buffer | - \*-----------------------------------------------------*/ - controller->SetDirect(LOGITECH_G915_ZONE_FRAME_TYPE_LITTLE, frame_buffer_little_mode); + little_frames.push_back(std::move(cur_small)); } - if(ledsByColors.size() > 0) + + unsigned char frame_buffer[DATA_FRAME_SIZE]; + for(const BigFrame& frame : big_frames) { - /*-----------------------------------------------------*\ - | Copy the current color vector to avoid set keys that | - | has not being | - \*-----------------------------------------------------*/ - controller->Commit(); - std::copy(new_colors.begin(), new_colors.end(),current_colors.begin()); + size_t length = populate_big_frame_data(frame_buffer, frame); + controller->SetDirect(LOGITECH_G915_ZONE_FRAME_TYPE_BIG, frame_buffer, length); } + + for(const LittleFrame& frame : little_frames) + { + size_t length = populate_little_frame_data(frame_buffer, frame); + controller->SetDirect(LOGITECH_G915_ZONE_FRAME_TYPE_LITTLE, frame_buffer, length); + } + + controller->Commit(); } void RGBController_LogitechG915::UpdateZoneLEDs(int /*zone*/) diff --git a/Controllers/LogitechController/LogitechG915Controller/RGBController_LogitechG915.h b/Controllers/LogitechController/LogitechG915Controller/RGBController_LogitechG915.h new file mode 100644 index 00000000..73ff2a99 --- /dev/null +++ b/Controllers/LogitechController/LogitechG915Controller/RGBController_LogitechG915.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------*\ +| RGBController_LogitechG915.h | +| | +| RGBController for Logitech G915 | +| | +| Cheerpipe 20 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LogitechG915Controller.h" + +class RGBController_LogitechG915 : public RGBController +{ +public: + RGBController_LogitechG915(LogitechG915Controller* controller_ptr, bool tkl); + ~RGBController_LogitechG915(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + bool is_tkl; + + LogitechG915Controller* controller; + std::vector current_colors; +}; diff --git a/Controllers/LogitechController/LogitechG933Controller.h b/Controllers/LogitechController/LogitechG933Controller.h deleted file mode 100644 index 9981ca4d..00000000 --- a/Controllers/LogitechController/LogitechG933Controller.h +++ /dev/null @@ -1,56 +0,0 @@ -/*-----------------------------------------*\ -| LogitechG933Controller.h | -| | -| Definitions and types for | -| Logitech G933 RGB Headset | -| | -| Edbgon 06/21/2021 | -| Based on | -| TheRogueZeta 8/31/2020 | -\*-----------------------------------------*/ -#include "RGBController.h" - -#include -#include - -#pragma once - -#define LOGI_G933_LED_PACKET_SIZE 20 -#define LOGI_G933_LED_COMMAND_SEND_RETRIES 3 - -enum -{ - LOGITECH_G933_MODE_OFF = 0x00, - LOGITECH_G933_MODE_DIRECT = 0x01, - LOGITECH_G933_MODE_CYCLE = 0x02, - LOGITECH_G933_MODE_BREATHING = 0x03, -}; - -class LogitechG933Controller -{ -public: - LogitechG933Controller(hid_device* dev_handle, const char* path); - ~LogitechG933Controller(); - - std::string GetDeviceLocation(); - - void SetDirectMode(uint8_t zone); - void SetOffMode(uint8_t zone); - - void SendHeadsetMode - ( - unsigned char zone, - unsigned char mode, - unsigned char red, - unsigned char green, - unsigned char blue - ); - -private: - hid_device* dev; - std::string location; - - void fail_retry_write(hid_device *device, const unsigned char *data, size_t length); -}; - - diff --git a/Controllers/LogitechController/LogitechG933Controller.cpp b/Controllers/LogitechController/LogitechG933Controller/LogitechG933Controller.cpp similarity index 82% rename from Controllers/LogitechController/LogitechG933Controller.cpp rename to Controllers/LogitechController/LogitechG933Controller/LogitechG933Controller.cpp index 3b9a5ddd..ef65c174 100644 --- a/Controllers/LogitechController/LogitechG933Controller.cpp +++ b/Controllers/LogitechController/LogitechG933Controller/LogitechG933Controller.cpp @@ -1,24 +1,27 @@ -/*-----------------------------------------*\ -| LogitechG933Controller.cpp | -| | -| Driver for Logitech G933 RGB Headset | -| | -| Edbgon 06/21/2021 | -| Based on | -| TheRogueZeta 8/31/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LogitechG933Controller.cpp | +| | +| Driver for Logitech G933 | +| | +| Edbgon 21 Jun 2021 | +| Based on TheRogueZeta 31 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "LogitechG933Controller.h" #include #include #include +#include "LogitechG933Controller.h" using namespace std::chrono_literals; -LogitechG933Controller::LogitechG933Controller(hid_device* dev_handle, const char* path) +LogitechG933Controller::LogitechG933Controller(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } LogitechG933Controller::~LogitechG933Controller() @@ -31,6 +34,11 @@ std::string LogitechG933Controller::GetDeviceLocation() return("HID: " + location); } +std::string LogitechG933Controller::GetDeviceName() +{ + return(name); +} + void LogitechG933Controller::SetDirectMode(uint8_t zone) { unsigned char usb_buf[LOGI_G933_LED_PACKET_SIZE]; diff --git a/Controllers/LogitechController/LogitechG933Controller/LogitechG933Controller.h b/Controllers/LogitechController/LogitechG933Controller/LogitechG933Controller.h new file mode 100644 index 00000000..455953c1 --- /dev/null +++ b/Controllers/LogitechController/LogitechG933Controller/LogitechG933Controller.h @@ -0,0 +1,59 @@ +/*---------------------------------------------------------*\ +| LogitechG933Controller.h | +| | +| Driver for Logitech G933 | +| | +| Edbgon 21 Jun 2021 | +| Based on TheRogueZeta 31 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define LOGI_G933_LED_PACKET_SIZE 20 +#define LOGI_G933_LED_COMMAND_SEND_RETRIES 3 + +enum +{ + LOGITECH_G933_MODE_OFF = 0x00, + LOGITECH_G933_MODE_DIRECT = 0x01, + LOGITECH_G933_MODE_CYCLE = 0x02, + LOGITECH_G933_MODE_BREATHING = 0x03, +}; + +class LogitechG933Controller +{ +public: + LogitechG933Controller(hid_device* dev_handle, const char* path, std::string dev_name); + ~LogitechG933Controller(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + + void SetDirectMode(uint8_t zone); + void SetOffMode(uint8_t zone); + + void SendHeadsetMode + ( + unsigned char zone, + unsigned char mode, + unsigned char red, + unsigned char green, + unsigned char blue + ); + +private: + hid_device* dev; + std::string location; + std::string name; + + void fail_retry_write(hid_device *device, const unsigned char *data, size_t length); +}; + + diff --git a/Controllers/LogitechController/LogitechG933Controller/RGBController_LogitechG933.cpp b/Controllers/LogitechController/LogitechG933Controller/RGBController_LogitechG933.cpp new file mode 100644 index 00000000..b58f732a --- /dev/null +++ b/Controllers/LogitechController/LogitechG933Controller/RGBController_LogitechG933.cpp @@ -0,0 +1,134 @@ +/*---------------------------------------------------------*\ +| RGBController_LogitechG933.cpp | +| | +| RGBController for Logitech G933 | +| | +| Edbgon 21 Jun 2021 | +| Based on TheRogueZeta 31 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_LogitechG933.h" + +/**------------------------------------------------------------------*\ + @name Logitech G933 + @category Headset + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectLogitechG933 + @comment +\*-------------------------------------------------------------------*/ + +RGBController_LogitechG933::RGBController_LogitechG933(LogitechG933Controller* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "Logitech"; + type = DEVICE_TYPE_HEADSET; + description = "Logitech G933 Lightsync Headset"; + location = controller->GetDeviceLocation(); + + mode Off; + Off.name = "Off"; + Off.value = LOGITECH_G933_MODE_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Off); + + mode Direct; + Direct.name = "Direct"; + Direct.value = LOGITECH_G933_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + SetupZones(); +} + +void RGBController_LogitechG933::SetupZones() +{ + zone G933_logo; + G933_logo.name = "Logo"; + G933_logo.type = ZONE_TYPE_SINGLE; + G933_logo.leds_min = 1; + G933_logo.leds_max = 1; + G933_logo.leds_count = 1; + G933_logo.matrix_map = NULL; + zones.push_back(G933_logo); + + led G933_logo_led; + G933_logo_led.name = "Logo"; + G933_logo_led.value = 0x00; + leds.push_back(G933_logo_led); + + zone G933_strip; + G933_strip.name = "LED Strip"; + G933_strip.type = ZONE_TYPE_SINGLE; + G933_strip.leds_min = 1; + G933_strip.leds_max = 1; + G933_strip.leds_count = 1; + G933_strip.matrix_map = NULL; + zones.push_back(G933_strip); + + led G933_strip_led; + G933_strip_led.name = "Led Strip"; + G933_strip_led.value = 0x01; + leds.push_back(G933_strip_led); + + SetupColors(); +} + +void RGBController_LogitechG933::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_LogitechG933::DeviceUpdateLEDs() +{ + for(std::size_t led_idx = 0; led_idx < leds.size(); led_idx++) + { + unsigned char red = RGBGetRValue(colors[led_idx]); + unsigned char grn = RGBGetGValue(colors[led_idx]); + unsigned char blu = RGBGetBValue(colors[led_idx]); + + controller->SendHeadsetMode((unsigned char)leds[led_idx].value, modes[active_mode].value, red, grn, blu); + } +} + +void RGBController_LogitechG933::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_LogitechG933::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_LogitechG933::DeviceUpdateMode() +{ + for(std::size_t led_idx = 0; led_idx < leds.size(); led_idx++) + { + if(modes[active_mode].value == LOGITECH_G933_MODE_OFF) + { + controller->SetOffMode(leds[led_idx].value); + } + else + { + /*---------------------------------------------------------*\ + | Required to "reset" RGB controller and start receiving | + | color in direct mode | + \*---------------------------------------------------------*/ + controller->SetDirectMode(leds[led_idx].value); + } + + } + DeviceUpdateLEDs(); +} diff --git a/Controllers/LogitechController/LogitechG933Controller/RGBController_LogitechG933.h b/Controllers/LogitechController/LogitechG933Controller/RGBController_LogitechG933.h new file mode 100644 index 00000000..1e3b7db4 --- /dev/null +++ b/Controllers/LogitechController/LogitechG933Controller/RGBController_LogitechG933.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_LogitechG933.h | +| | +| RGBController for Logitech G933 | +| | +| Edbgon 21 Jun 2021 | +| Based on TheRogueZeta 31 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LogitechG933Controller.h" + +class RGBController_LogitechG933 : public RGBController +{ +public: + RGBController_LogitechG933(LogitechG933Controller* controller_ptr); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LogitechG933Controller* controller; +}; diff --git a/Controllers/LogitechController/LogitechGLightsyncController.h b/Controllers/LogitechController/LogitechGLightsyncController.h deleted file mode 100644 index 0ba30e87..00000000 --- a/Controllers/LogitechController/LogitechGLightsyncController.h +++ /dev/null @@ -1,82 +0,0 @@ -/*-----------------------------------------*\ -| LogitechGLightsyncController.h | -| | -| Definitions and types for Logitech | -| Lightsync lighting controllers | -| | -| TheRogueZeta 04/21/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include -#include - -#pragma once - -enum -{ - LOGITECH_G_LIGHTSYNC_MODE_OFF = 0x00, - LOGITECH_G_LIGHTSYNC_MODE_STATIC = 0x01, - LOGITECH_G_LIGHTSYNC_MODE_CYCLE = 0x02, - LOGITECH_G_LIGHTSYNC_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_LIGHTSYNC_SPEED_SLOWEST = 0xC8, /* Slowest speed */ - LOGITECH_G_LIGHTSYNC_SPEED_NORMAL = 0x32, /* Normal speed */ - LOGITECH_G_LIGHTSYNC_SPEED_FASTEST = 0x0A, /* Fastest speed */ -}; - -class LogitechGLightsyncController -{ -public: - LogitechGLightsyncController( - hid_device* dev_cmd_handle, - hid_device* dev_handle, - const char* path, - unsigned char hid_dev_index, - unsigned char hid_feature_index, - unsigned char hid_fctn_ase_id); - LogitechGLightsyncController( - hid_device* dev_cmd_handle, - hid_device* dev_handle, - const char* path, - unsigned char hid_dev_index, - unsigned char hid_feature_index, - unsigned char hid_fctn_ase_id, - std::shared_ptr mutex_ptr); - - ~LogitechGLightsyncController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - - void UpdateMouseLED - ( - unsigned char mode, - unsigned short speed, - unsigned char zone, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char brightness - ); - void SetDirectMode(bool direct); - -private: - hid_device* dev; - hid_device* cmd_dev; - std::string location; - unsigned char dev_index; - unsigned char feature_index; - unsigned char fctn_ase_id; - bool direct_state; - std::shared_ptr mutex; -}; diff --git a/Controllers/LogitechController/LogitechGLightsyncController.cpp b/Controllers/LogitechController/LogitechGLightsyncController/LogitechGLightsyncController.cpp similarity index 81% rename from Controllers/LogitechController/LogitechGLightsyncController.cpp rename to Controllers/LogitechController/LogitechGLightsyncController/LogitechGLightsyncController.cpp index 6d7f8874..8e21b33d 100644 --- a/Controllers/LogitechController/LogitechGLightsyncController.cpp +++ b/Controllers/LogitechController/LogitechGLightsyncController/LogitechGLightsyncController.cpp @@ -1,17 +1,19 @@ -/*-----------------------------------------*\ -| LogitechGLightsyncController.cpp | -| | -| Driver for Logitech G Lightsync | -| lighting controllers | -| | -| TheRogueZeta 04/21/2021 | -\*-----------------------------------------*/ - -#include "LogitechGLightsyncController.h" +/*---------------------------------------------------------*\ +| LogitechGLightsyncController.cpp | +| | +| Driver for Logitech Lightsync | +| | +| TheRogueZeta 21 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "LogitechGLightsyncController.h" +#include "StringUtils.h" -LogitechGLightsyncController::LogitechGLightsyncController(hid_device* dev_cmd_handle, hid_device *dev_handle, const char *path, unsigned char hid_dev_index, unsigned char hid_feature_index, unsigned char hid_fctn_ase_id) +LogitechGLightsyncController::LogitechGLightsyncController(hid_device* dev_cmd_handle, hid_device *dev_handle, const char *path, unsigned char hid_dev_index, unsigned char hid_feature_index, unsigned char hid_fctn_ase_id, std::string dev_name) { dev = dev_handle; cmd_dev = dev_cmd_handle; @@ -20,9 +22,10 @@ LogitechGLightsyncController::LogitechGLightsyncController(hid_device* dev_cmd_h feature_index = hid_feature_index; fctn_ase_id = hid_fctn_ase_id; mutex = nullptr; + name = dev_name; } -LogitechGLightsyncController::LogitechGLightsyncController(hid_device* dev_cmd_handle, hid_device *dev_handle, const char *path, unsigned char hid_dev_index, unsigned char hid_feature_index, unsigned char hid_fctn_ase_id, std::shared_ptr mutex_ptr) +LogitechGLightsyncController::LogitechGLightsyncController(hid_device* dev_cmd_handle, hid_device *dev_handle, const char *path, unsigned char hid_dev_index, unsigned char hid_feature_index, unsigned char hid_fctn_ase_id, std::shared_ptr mutex_ptr, std::string dev_name) { dev = dev_handle; cmd_dev = dev_cmd_handle; @@ -31,6 +34,7 @@ LogitechGLightsyncController::LogitechGLightsyncController(hid_device* dev_cmd_h feature_index = hid_feature_index; fctn_ase_id = hid_fctn_ase_id; mutex = mutex_ptr; + name = dev_name; } LogitechGLightsyncController::~LogitechGLightsyncController() @@ -43,6 +47,11 @@ std::string LogitechGLightsyncController::GetDeviceLocation() return ("HID: " + location); } +std::string LogitechGLightsyncController::GetNameString() +{ + return(name); +} + std::string LogitechGLightsyncController::GetSerialString() { wchar_t serial_string[128]; @@ -53,10 +62,7 @@ std::string LogitechGLightsyncController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void LogitechGLightsyncController::UpdateMouseLED( @@ -132,8 +138,8 @@ void LogitechGLightsyncController::UpdateMouseLED( void LogitechGLightsyncController::SetDirectMode(bool direct) { - char cmd_buf[7]; - char usb_buf[20]; + unsigned char cmd_buf[7]; + unsigned char usb_buf[20]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -170,12 +176,12 @@ void LogitechGLightsyncController::SetDirectMode(bool direct) { std::lock_guard guard(*mutex); - hid_write(cmd_dev, (unsigned char *)cmd_buf, 7); - hid_read(dev, (unsigned char *)usb_buf, 20); + hid_write(cmd_dev, cmd_buf, 7); + hid_read(dev, usb_buf, 20); } else { - hid_write(cmd_dev, (unsigned char *)cmd_buf, 7); - hid_read(dev, (unsigned char *)usb_buf, 20); + hid_write(cmd_dev, cmd_buf, 7); + hid_read(dev, usb_buf, 20); } } diff --git a/Controllers/LogitechController/LogitechGLightsyncController/LogitechGLightsyncController.h b/Controllers/LogitechController/LogitechGLightsyncController/LogitechGLightsyncController.h new file mode 100644 index 00000000..a5ad8ab1 --- /dev/null +++ b/Controllers/LogitechController/LogitechGLightsyncController/LogitechGLightsyncController.h @@ -0,0 +1,91 @@ +/*---------------------------------------------------------*\ +| LogitechGLightsyncController.h | +| | +| Driver for Logitech Lightsync | +| | +| TheRogueZeta 21 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" + +enum +{ + LOGITECH_G_LIGHTSYNC_MODE_OFF = 0x00, + LOGITECH_G_LIGHTSYNC_MODE_STATIC = 0x01, + LOGITECH_G_LIGHTSYNC_MODE_CYCLE = 0x02, + LOGITECH_G_LIGHTSYNC_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_LIGHTSYNC_SPEED_SLOWEST = 0xC8, /* Slowest speed */ + LOGITECH_G_LIGHTSYNC_SPEED_NORMAL = 0x32, /* Normal speed */ + LOGITECH_G_LIGHTSYNC_SPEED_FASTEST = 0x0A, /* Fastest speed */ +}; + +class LogitechGLightsyncController +{ +public: + LogitechGLightsyncController + ( + hid_device* ev_cmd_handle, + hid_device* ev_handle, + const char* ath, + unsigned char id_dev_index, + unsigned char id_feature_index, + unsigned char id_fctn_ase_id, + std::string ev_name + ); + + LogitechGLightsyncController + ( + hid_device* dev_cmd_handle, + hid_device* dev_handle, + const char* path, + unsigned char hid_dev_index, + unsigned char hid_feature_index, + unsigned char hid_fctn_ase_id, + std::shared_ptr mutex_ptr, + std::string dev_name + ); + + ~LogitechGLightsyncController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void UpdateMouseLED + ( + unsigned char mode, + unsigned short speed, + unsigned char zone, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char brightness + ); + void SetDirectMode(bool direct); + +private: + hid_device* dev; + hid_device* cmd_dev; + std::string location; + std::string name; + unsigned char dev_index; + unsigned char feature_index; + unsigned char fctn_ase_id; + std::shared_ptr mutex; +}; diff --git a/Controllers/LogitechController/RGBController_LogitechGLightsync.cpp b/Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGLightsync.cpp similarity index 89% rename from Controllers/LogitechController/RGBController_LogitechGLightsync.cpp rename to Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGLightsync.cpp index b771a407..55c8a310 100644 --- a/Controllers/LogitechController/RGBController_LogitechGLightsync.cpp +++ b/Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGLightsync.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_LogitechGLightsync.cpp | -| | -| Generic RGB Interface for | -| Logitech G Lightsync Devices | -| | -| TheRogueZeta 04/21/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LogitechGLightsync.cpp | +| | +| RGBController for Logitech Lightsync | +| | +| TheRogueZeta 21 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_LogitechGLightsync.h" @@ -24,7 +26,7 @@ RGBController_LogitechGLightsync::RGBController_LogitechGLightsync(LogitechGLigh { controller = controller_ptr; - name = "Logitech G Lightsync Mouse"; + name = controller->GetNameString(); vendor = "Logitech"; type = DEVICE_TYPE_MOUSE; description = "Logitech G Lightsync Mouse"; diff --git a/Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGLightsync.h b/Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGLightsync.h new file mode 100644 index 00000000..b827e2d9 --- /dev/null +++ b/Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGLightsync.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_LogitechGLightsync.h | +| | +| RGBController for Logitech Lightsync | +| | +| TheRogueZeta 21 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LogitechGLightsyncController.h" + +class RGBController_LogitechGLightsync : public RGBController +{ +public: + RGBController_LogitechGLightsync(LogitechGLightsyncController* controller_ptr); + ~RGBController_LogitechGLightsync(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LogitechGLightsyncController* controller; +}; diff --git a/Controllers/LogitechController/RGBController_LogitechGLightsync1zone.cpp b/Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGLightsync1zone.cpp similarity index 88% rename from Controllers/LogitechController/RGBController_LogitechGLightsync1zone.cpp rename to Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGLightsync1zone.cpp index 2cd1b8f9..6d895ae0 100644 --- a/Controllers/LogitechController/RGBController_LogitechGLightsync1zone.cpp +++ b/Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGLightsync1zone.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_LogitechGLightsync1zone.cpp| -| | -| Generic RGB Interface for single zone | -| Logitech G Lightsync Devices | -| | -| TheRogueZeta 04/21/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LogitechGLightsync1zone.cpp | +| | +| RGBController for single zone Logitech Lightsync | +| | +| TheRogueZeta 21 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_LogitechGLightsync1zone.h" @@ -24,7 +26,7 @@ RGBController_LogitechGLightsync1zone::RGBController_LogitechGLightsync1zone(Log { controller = controller_ptr; - name = "Logitech G Lightsync Mouse Single Zone"; + name = controller->GetNameString(); vendor = "Logitech"; type = DEVICE_TYPE_MOUSE; description = "Logitech G Lightsync Mouse Single Zone"; diff --git a/Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGLightsync1zone.h b/Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGLightsync1zone.h new file mode 100644 index 00000000..593d33df --- /dev/null +++ b/Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGLightsync1zone.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_LogitechGLightsync1zone.h | +| | +| RGBController for single zone Logitech Lightsync | +| | +| TheRogueZeta 21 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LogitechGLightsyncController.h" + +class RGBController_LogitechGLightsync1zone : public RGBController +{ +public: + RGBController_LogitechGLightsync1zone(LogitechGLightsyncController* controller_ptr); + ~RGBController_LogitechGLightsync1zone(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LogitechGLightsyncController* controller; +}; diff --git a/Controllers/LogitechController/RGBController_LogitechGPowerPlay.cpp b/Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGPowerPlay.cpp similarity index 85% rename from Controllers/LogitechController/RGBController_LogitechGPowerPlay.cpp rename to Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGPowerPlay.cpp index 50a1a6a9..43cb4534 100644 --- a/Controllers/LogitechController/RGBController_LogitechGPowerPlay.cpp +++ b/Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGPowerPlay.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_LogitechGPowerPlay.cpp | -| | -| Generic RGB Interface for | -| Logitech G PowerPlay Wireless Mousemat | -| | -| TheRogueZeta 8/31/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LogitechGPowerPlay.cpp | +| | +| RGBController for Logitech G PowerPlay | +| | +| TheRogueZeta 31 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_LogitechGPowerPlay.h" @@ -24,7 +26,7 @@ RGBController_LogitechGPowerPlay::RGBController_LogitechGPowerPlay(LogitechGLigh { controller = controller_ptr; - name = "Logitech G PowerPlay Wireless Charging System"; + name = controller->GetNameString(); vendor = "Logitech"; type = DEVICE_TYPE_MOUSEMAT; description = "Logitech G PowerPlay Wireless Charging System"; diff --git a/Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGPowerPlay.h b/Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGPowerPlay.h new file mode 100644 index 00000000..7fd4d619 --- /dev/null +++ b/Controllers/LogitechController/LogitechGLightsyncController/RGBController_LogitechGPowerPlay.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_LogitechGPowerPlay.h | +| | +| RGBController for Logitech G PowerPlay | +| | +| TheRogueZeta 31 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LogitechGLightsyncController.h" + +class RGBController_LogitechGPowerPlay : public RGBController +{ +public: + RGBController_LogitechGPowerPlay(LogitechGLightsyncController* controller_ptr); + ~RGBController_LogitechGPowerPlay(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LogitechGLightsyncController* controller; +}; diff --git a/Controllers/LogitechController/LogitechGProKeyboardController.cpp b/Controllers/LogitechController/LogitechGProKeyboardController/LogitechGProKeyboardController.cpp similarity index 79% rename from Controllers/LogitechController/LogitechGProKeyboardController.cpp rename to Controllers/LogitechController/LogitechGProKeyboardController/LogitechGProKeyboardController.cpp index cfba6e6c..cb6c33a2 100644 --- a/Controllers/LogitechController/LogitechGProKeyboardController.cpp +++ b/Controllers/LogitechController/LogitechGProKeyboardController/LogitechGProKeyboardController.cpp @@ -1,19 +1,23 @@ -/*-----------------------------------------*\ -| LogitechGProController.cpp | -| | -| Driver for Logitech G Pro | -| keyboard light controller | -| | -| sanchezzzs 20/10/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LogitechGProController.cpp | +| | +| Driver for Logitech G Pro keyboard | +| | +| sanchezzzs 20 Oct 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "LogitechGProKeyboardController.h" #include +#include "LogitechGProKeyboardController.h" +#include "StringUtils.h" -LogitechGProKeyboardController::LogitechGProKeyboardController(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12) +LogitechGProKeyboardController::LogitechGProKeyboardController(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12, std::string dev_name) { - dev_pkt_0x11 = dev_handle_0x11; - dev_pkt_0x12 = dev_handle_0x12; + dev_pkt_0x11 = dev_handle_0x11; + dev_pkt_0x12 = dev_handle_0x12; + name = dev_name; } LogitechGProKeyboardController::~LogitechGProKeyboardController() @@ -22,6 +26,11 @@ LogitechGProKeyboardController::~LogitechGProKeyboardController() hid_close(dev_pkt_0x12); } +std::string LogitechGProKeyboardController::GetNameString() +{ + return(name); +} + std::string LogitechGProKeyboardController::GetSerialString() { wchar_t serial_string[128]; @@ -32,10 +41,7 @@ std::string LogitechGProKeyboardController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void LogitechGProKeyboardController::Commit() @@ -74,7 +80,7 @@ void LogitechGProKeyboardController::SetMode void LogitechGProKeyboardController::SendCommit() { - char usb_buf[20]; + unsigned char usb_buf[20]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -92,8 +98,8 @@ void LogitechGProKeyboardController::SendCommit() /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x11, (unsigned char *)usb_buf, 20); - hid_read(dev_pkt_0x11, (unsigned char *)usb_buf, 20); + hid_write(dev_pkt_0x11, usb_buf, 20); + hid_read(dev_pkt_0x11, usb_buf, 20); } void LogitechGProKeyboardController::SendDirectFrame @@ -103,7 +109,7 @@ void LogitechGProKeyboardController::SendDirectFrame unsigned char * frame_data ) { - char usb_buf[64]; + unsigned char usb_buf[64]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -128,8 +134,8 @@ void LogitechGProKeyboardController::SendDirectFrame /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x12, (unsigned char *)usb_buf, 64); - hid_read(dev_pkt_0x11, (unsigned char *)usb_buf, 20); + hid_write(dev_pkt_0x12, usb_buf, 64); + hid_read(dev_pkt_0x11, usb_buf, 20); } void LogitechGProKeyboardController::SendMode @@ -142,7 +148,7 @@ void LogitechGProKeyboardController::SendMode unsigned char blue ) { - char usb_buf[20]; + unsigned char usb_buf[20]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -181,6 +187,6 @@ void LogitechGProKeyboardController::SendMode /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev_pkt_0x11, (unsigned char *)usb_buf, 20); - hid_read(dev_pkt_0x11, (unsigned char *)usb_buf, 20); + hid_write(dev_pkt_0x11, usb_buf, 20); + hid_read(dev_pkt_0x11, usb_buf, 20); } diff --git a/Controllers/LogitechController/LogitechGProKeyboardController.h b/Controllers/LogitechController/LogitechGProKeyboardController/LogitechGProKeyboardController.h similarity index 78% rename from Controllers/LogitechController/LogitechGProKeyboardController.h rename to Controllers/LogitechController/LogitechGProKeyboardController/LogitechGProKeyboardController.h index 8d336171..24da85d0 100644 --- a/Controllers/LogitechController/LogitechGProKeyboardController.h +++ b/Controllers/LogitechController/LogitechGProKeyboardController/LogitechGProKeyboardController.h @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| LogitechGProController.h | -| | -| Definitions and types for Logitech G Pro | -| keyboard light controller | -| | -| sanchezzzs 20/10/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| LogitechGProController.h | +| | +| Driver for Logitech G Pro keyboard | +| | +| sanchezzzs 20 Oct 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + enum { LOGITECH_GPRO_ZONE_MODE_KEYBOARD = 0x00, @@ -51,13 +52,14 @@ enum class LogitechGProKeyboardController { public: - LogitechGProKeyboardController(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12); + LogitechGProKeyboardController(hid_device* dev_handle_0x11, hid_device* dev_handle_0x12, std::string dev_name); ~LogitechGProKeyboardController(); + std::string GetNameString(); std::string GetSerialString(); void Commit(); - + void SetDirect ( unsigned char zone, @@ -77,6 +79,7 @@ public: private: hid_device* dev_pkt_0x11; hid_device* dev_pkt_0x12; + std::string name; void SendDirectFrame ( diff --git a/Controllers/LogitechController/RGBController_LogitechGProKeyboard.cpp b/Controllers/LogitechController/LogitechGProKeyboardController/RGBController_LogitechGProKeyboard.cpp similarity index 94% rename from Controllers/LogitechController/RGBController_LogitechGProKeyboard.cpp rename to Controllers/LogitechController/LogitechGProKeyboardController/RGBController_LogitechGProKeyboard.cpp index 65308064..7cd93004 100644 --- a/Controllers/LogitechController/RGBController_LogitechGProKeyboard.cpp +++ b/Controllers/LogitechController/LogitechGProKeyboardController/RGBController_LogitechGProKeyboard.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_LogitechGPro.cpp | -| | -| Generic RGB Interface for Logitech G Pro | -| Keyboard | -| | -| sanchezzzs 20/10/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LogitechGPro.cpp | +| | +| RGBController for Logitech G Pro keyboard | +| | +| sanchezzzs 20 Oct 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_LogitechGProKeyboard.h" @@ -156,13 +158,13 @@ static const led_type led_names[] = RGBController_LogitechGProKeyboard::RGBController_LogitechGProKeyboard(LogitechGProKeyboardController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Logitech Keyboard Device"; - vendor = "Logitech"; - type = DEVICE_TYPE_KEYBOARD; - description = "Logitech Keyboard Device"; - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "Logitech"; + type = DEVICE_TYPE_KEYBOARD; + description = "Logitech Keyboard Device"; + serial = controller->GetSerialString(); mode Direct; Direct.name = "Direct"; diff --git a/Controllers/LogitechController/LogitechGProKeyboardController/RGBController_LogitechGProKeyboard.h b/Controllers/LogitechController/LogitechGProKeyboardController/RGBController_LogitechGProKeyboard.h new file mode 100644 index 00000000..492d8f93 --- /dev/null +++ b/Controllers/LogitechController/LogitechGProKeyboardController/RGBController_LogitechGProKeyboard.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_LogitechGPro.h | +| | +| RGBController for Logitech G Pro keyboard | +| | +| sanchezzzs 20 Oct 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LogitechGProKeyboardController.h" + +class RGBController_LogitechGProKeyboard : public RGBController +{ +public: + RGBController_LogitechGProKeyboard(LogitechGProKeyboardController* controller_ptr); + ~RGBController_LogitechGProKeyboard(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + LogitechGProKeyboardController* controller; +}; diff --git a/Controllers/LogitechController/LogitechLightspeedController.cpp b/Controllers/LogitechController/LogitechLightspeedController.cpp deleted file mode 100644 index 14856c7d..00000000 --- a/Controllers/LogitechController/LogitechLightspeedController.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/*-----------------------------------------*\ -| LogitechLightspeedController.cpp | -| | -| Driver for Logitech Lightspeed Wireless | -| Gaming Mice lighting controller | -| | -| TheRogueZeta 8/5/2020 | -\*-----------------------------------------*/ - -#include "LogitechLightspeedController.h" - -#include - -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() -{ - if (lightspeed->device_index == 255 && lightspeed->wireless) - { - LOG_DEBUG("[%s] Skipped get serial number as this is the reciever", lightspeed->device_name.c_str()); - return(""); - } - else - { - wchar_t serial_string[128]; - //int ret = hid_get_serial_number_string(dev, serial_string, 128); - //LOG_DEBUG("[%s] hid_get_serial_number_string Returned status - %i : %s", lightspeed->device_name.c_str(), ret, ((ret == 0) ? "SUCCESS" : "FAILED")); - - //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 - ( - uint8_t mode, - uint16_t speed, - uint8_t zone, - uint8_t red, - uint8_t green, - uint8_t blue, - uint8_t brightness - ) -{ - lightspeed->setMode(mode, speed, zone, red, green, blue, brightness); -} diff --git a/Controllers/LogitechController/LogitechLightspeedController.h b/Controllers/LogitechController/LogitechLightspeedController.h deleted file mode 100644 index 1915cd66..00000000 --- a/Controllers/LogitechController/LogitechLightspeedController.h +++ /dev/null @@ -1,58 +0,0 @@ -/*-----------------------------------------*\ -| LogitechLightspeedController.h | -| | -| Definitions and types for Logitech G | -| Lightsync Wireless Gaming Mice lighting | -| controller | -| | -| TheRogueZeta 8/5/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include "LogManager.h" -#include "LogitechProtocolCommon.h" - -#include -#include - -#pragma once -#define LOGITECH_G_PRO_WIRELESS_BRIGHTNESS_MIN 0x01 -#define LOGITECH_G_PRO_WIRELESS_BRIGHTNESS_MAX 0x64 - -/*---------------------------------------------------------------------------------------------*\ -| 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 - ( - uint8_t mode, - uint16_t speed, - uint8_t zone, - uint8_t red, - uint8_t green, - uint8_t blue, - uint8_t brightness - ); - -private: - hid_device* dev; - std::string location; -}; diff --git a/Controllers/LogitechController/LogitechLightspeedController/LogitechLightspeedController.cpp b/Controllers/LogitechController/LogitechLightspeedController/LogitechLightspeedController.cpp new file mode 100644 index 00000000..3e04ad08 --- /dev/null +++ b/Controllers/LogitechController/LogitechLightspeedController/LogitechLightspeedController.cpp @@ -0,0 +1,68 @@ +/*---------------------------------------------------------*\ +| LogitechLightspeedController.cpp | +| | +| Driver for Logitech Lightspeed | +| | +| TheRogueZeta 05 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "LogitechLightspeedController.h" +#include "StringUtils.h" + +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() +{ + if (lightspeed->device_index == 255 && lightspeed->wireless) + { + LOG_DEBUG("[%s] Skipped get serial number as this is the reciever", lightspeed->device_name.c_str()); + return(""); + } + else + { + wchar_t serial_string[128]; + //int ret = hid_get_serial_number_string(dev, serial_string, 128); + //LOG_DEBUG("[%s] hid_get_serial_number_string Returned status - %i : %s", lightspeed->device_name.c_str(), ret, ((ret == 0) ? "SUCCESS" : "FAILED")); + + //if(ret != 0) + { + return(""); + } + + std::string return_string(StringUtils::wstring_to_string(serial_string)); + + return(return_string); + } +} + +void LogitechLightspeedController::SendMouseMode + ( + uint8_t mode, + uint16_t speed, + uint8_t zone, + uint8_t red, + uint8_t green, + uint8_t blue, + uint8_t brightness + ) +{ + lightspeed->setMode(mode, speed, zone, red, green, blue, brightness); +} diff --git a/Controllers/LogitechController/LogitechLightspeedController/LogitechLightspeedController.h b/Controllers/LogitechController/LogitechLightspeedController/LogitechLightspeedController.h new file mode 100644 index 00000000..7469bb11 --- /dev/null +++ b/Controllers/LogitechController/LogitechLightspeedController/LogitechLightspeedController.h @@ -0,0 +1,59 @@ +/*---------------------------------------------------------*\ +| LogitechLightspeedController.h | +| | +| Driver for Logitech Lightspeed | +| | +| TheRogueZeta 05 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" +#include "LogManager.h" +#include "LogitechProtocolCommon.h" + +#define LOGITECH_G_PRO_WIRELESS_BRIGHTNESS_MIN 0x01 +#define LOGITECH_G_PRO_WIRELESS_BRIGHTNESS_MAX 0x64 + +/*---------------------------------------------------------------------------------------------*\ +| 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 + ( + uint8_t mode, + uint16_t speed, + uint8_t zone, + uint8_t red, + uint8_t green, + uint8_t blue, + uint8_t brightness + ); + +private: + hid_device* dev; + std::string location; +}; diff --git a/Controllers/LogitechController/RGBController_LogitechLightspeed.cpp b/Controllers/LogitechController/LogitechLightspeedController/RGBController_LogitechLightspeed.cpp similarity index 92% rename from Controllers/LogitechController/RGBController_LogitechLightspeed.cpp rename to Controllers/LogitechController/LogitechLightspeedController/RGBController_LogitechLightspeed.cpp index ac3ad350..7b70ada6 100644 --- a/Controllers/LogitechController/RGBController_LogitechLightspeed.cpp +++ b/Controllers/LogitechController/LogitechLightspeedController/RGBController_LogitechLightspeed.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_LogitechLightspeed.cpp | -| | -| Generic RGB Interface for | -| Logitech Lightspeed Gaming Mice | -| | -| TheRogueZeta 8/5/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LogitechLightspeed.cpp | +| | +| RGBController for Logitech Lightspeed | +| | +| TheRogueZeta 05 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_LogitechLightspeed.h" @@ -166,13 +168,14 @@ void RGBController_LogitechLightspeed::SetupZones() const std::string led_string = "LED"; uint8_t led_count = controller->lightspeed->getLED_count(); + LOG_DEBUG("[%s] Setting up %d LEDs", name.c_str(), led_count); if(led_count > 0) { for(size_t i = 0; i < led_count; i++) { zone Lightspeed_logo_zone; led Lightspeed_logo_led; - logitech_led new_led = controller->lightspeed->getLED_info(i); + logitech_led new_led = controller->lightspeed->getLED_info((uint8_t)i); if(new_led.location < NUM_LOGITECH_LED_LOCATIONS ) { @@ -196,7 +199,7 @@ void RGBController_LogitechLightspeed::SetupZones() Lightspeed_logo_zone.matrix_map = NULL; zones.push_back(Lightspeed_logo_zone); - Lightspeed_logo_led.value = i; + Lightspeed_logo_led.value = (unsigned int)i; leds.push_back(Lightspeed_logo_led); } } diff --git a/Controllers/LogitechController/LogitechLightspeedController/RGBController_LogitechLightspeed.h b/Controllers/LogitechController/LogitechLightspeedController/RGBController_LogitechLightspeed.h new file mode 100644 index 00000000..3d57b0fb --- /dev/null +++ b/Controllers/LogitechController/LogitechLightspeedController/RGBController_LogitechLightspeed.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_LogitechLightspeed.h | +| | +| RGBController for Logitech Lightspeed | +| | +| TheRogueZeta 05 Aug 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LogitechLightspeedController.h" + +class RGBController_LogitechLightspeed : public RGBController +{ +public: + RGBController_LogitechLightspeed(LogitechLightspeedController* controller_ptr); + ~RGBController_LogitechLightspeed(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + uint16_t pid; //This is a workaround fix for G502 mode breathing / spectrum cycle swap +private: + LogitechLightspeedController* controller; +}; diff --git a/Controllers/LogitechController/LogitechProtocolCommon.cpp b/Controllers/LogitechController/LogitechProtocolCommon.cpp index 6f3c31b6..052c44b6 100644 --- a/Controllers/LogitechController/LogitechProtocolCommon.cpp +++ b/Controllers/LogitechController/LogitechProtocolCommon.cpp @@ -1,11 +1,13 @@ -/*-------------------------------------------------------------------*\ -| LogitechProtocolCommon.cpp | -| | -| Common Logitech RAP and FAP protocol calls | -| | -| Chris M (Dr_No) 4th May 2021 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| LogitechProtocolCommon.cpp | +| | +| Common functionality for Logitech RAP and FAP protocols | +| | +| Chris M (Dr_No) 04 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include @@ -15,7 +17,14 @@ const char* logitech_led_locations[] = "Primary", "Logo", "Left", - "Right" + "Right", + "Combined", + "Group One", + "Group Two", + "Group Three", + "Group Four", + "Group Five", + "Group Six" }; const int NUM_LOGITECH_LED_LOCATIONS = sizeof(logitech_led_locations); @@ -115,7 +124,7 @@ int getWirelessDevice(usages device_usages, uint16_t pid, wireless_map *wireless } } - return wireless_devices->size(); + return((int)wireless_devices->size()); } logitech_device::logitech_device(char *path, usages _usages, uint8_t _device_index, bool _wireless) @@ -218,7 +227,7 @@ bool logitech_device::is_valid() LOG_INFO("Unable add this Logitech device: Not Connected"); } - return valid_test; + return(valid_test); } bool logitech_device::connected() @@ -245,17 +254,17 @@ bool logitech_device::connected() LOG_DEBUG("Wireless device index %i is %s - %02X %02X %02X", get_connected_devices.device_index, (test ? "connected" : "disconnected"), get_connected_devices.data[0], get_connected_devices.data[1], get_connected_devices.data[2]); } - return test; + return(test); } else { - return true; + return(true); } } uint8_t logitech_device::getLED_count() { - return leds.size(); + return((uint8_t)leds.size()); } logitech_led logitech_device::getLED_info(uint8_t LED_num) @@ -263,14 +272,13 @@ logitech_led logitech_device::getLED_info(uint8_t LED_num) /*-----------------------------------------------------------------*\ | Get all info about the LEDs and Zones | \*-----------------------------------------------------------------*/ - if(!(LED_num > leds.size())) { - return leds[LED_num]; + return(leds[LED_num]); } else { - return leds[0]; + return(leds[0]); } } @@ -317,11 +325,11 @@ hid_device* logitech_device::getDevice(uint8_t usage_index) if (find_usage == device_usages.end()) { LOG_INFO("Unable add this device due to missing FAP Message usage %i", usage_index); - return nullptr; + return(nullptr); } else { - return find_usage->second; + return(find_usage->second); } } @@ -352,7 +360,7 @@ uint8_t logitech_device::getFeatureIndex(uint16_t feature_page) response.data[0], response.data[1], response.data[2], response.data[3], response.data[4], response.data[5], response.data[6], response.data[7]); } - return feature_index; + return(feature_index); } uint16_t logitech_device::getFeaturePage(uint8_t feature_index) @@ -370,11 +378,11 @@ uint16_t logitech_device::getFeaturePage(uint8_t feature_index) LOG_DEBUG("[%s] Feature index %02X not found!", device_name.c_str(), feature_index); //TODO: Handle cache miss - return 0; + return(0); } else { - return find_page->second; + return(find_page->second); } } @@ -414,11 +422,11 @@ int logitech_device::getDeviceFeatureList() get_features.init(device_index, feature_index, LOGITECH_CMD_FEATURE_SET_GET_ID); for(std::size_t i = 1; feature_list.size() < feature_count; i++ ) { - get_features.data[0] = i; + get_features.data[0] = (uint8_t)i; hid_write(dev_use2, get_features.buffer, get_features.size()); hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT); LOG_DEBUG("[%s] Feature %04X @ index: %02X", device_name.c_str(), (response.data[0] << 8) | response.data[1], i); - feature_list.emplace((response.data[0] << 8) | response.data[1], i); + feature_list.emplace((uint16_t)((response.data[0] << 8) | response.data[1]), (uint8_t)i); } } else @@ -426,7 +434,7 @@ int logitech_device::getDeviceFeatureList() LOG_INFO("[%s] Unable get the feature index list - missing FAP Long Message (0x11) usage", device_name.c_str()); } - return feature_list.size(); + return((int)feature_list.size()); } int logitech_device::getDeviceName() @@ -468,7 +476,7 @@ int logitech_device::getDeviceName() get_name.init(device_index, 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 + get_name.data[0] = (uint8_t)device_name.length(); //This sets the character index to get from the device hid_write(dev_use2, get_name.buffer, get_name.size()); hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT); std::string temp = (char *)&response.data; @@ -488,7 +496,7 @@ int logitech_device::getDeviceName() } } - return device_name.length(); + return((int)device_name.length()); } void logitech_device::getRGBconfig() @@ -530,7 +538,7 @@ void logitech_device::getRGBconfig() get_count.feature_command = LOGITECH_CMD_RGB_EFFECTS_GET_INFO; for(size_t i = 0; i < led_response; i++) { - get_count.data[0] = i; + get_count.data[0] = (uint8_t)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); LOG_DEBUG("[%s] FP8070 - LED %02i - %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", device_name.c_str(), get_count.data[0], @@ -588,20 +596,20 @@ void logitech_device::getRGBconfig() result = hid_write(dev_use2, get_count.buffer, get_count.size()); result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT); - LOG_DEBUG("[%s] FP8071 - LED Count - %02X : %02X %02X %04X %04X %04X %02X %02X %02X %02X %02X %02X %02X", device_name.c_str(), - response.data[2], response.data[0], response.data[1], (response.data[3] << 8 | response.data[4]), (response.data[5] << 8 | response.data[6]), + LOG_DEBUG("[%s] FP8071 - LED Count - %04X : %02X %04X %04X %04X %04X %02X %02X %02X %02X %02X %02X %02X", device_name.c_str(), + (response.data[1] << 8 | response.data[2]), response.data[0], (response.data[1] << 8 | response.data[2]), (response.data[3] << 8 | response.data[4]), (response.data[5] << 8 | response.data[6]), (response.data[7] << 8 | response.data[8]), response.data[9], response.data[10], response.data[11], response.data[12], response.data[13], response.data[14], response.data[15]); - led_response = response.data[2]; + led_response = (response.data[1] << 8 | response.data[2]); for(size_t i = 0; i < led_response; i++) { - get_count.data[0] = i; + get_count.data[0] = (uint8_t)i; get_count.data[1] = 0xFF; get_count.data[2] = 0; result = hid_write(dev_use2, get_count.buffer, get_count.size()); result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT); - LOG_DEBUG("[%s] FP8071 - LED %02i - %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", device_name.c_str(), led_counter, + LOG_DEBUG("[%s] FP8071 - LED %02i - %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", device_name.c_str(), i, response.data[0], response.data[1], response.data[2], response.data[3], response.data[4], response.data[5], response.data[6], response.data[7], response.data[8], response.data[9], response.data[10], response.data[11], response.data[12], response.data[13], response.data[14], response.data[15]); @@ -616,7 +624,7 @@ void logitech_device::getRGBconfig() fx_response.init(); longFAPrequest get_effect; - get_effect.init(device_index, RGB_feature_index, LOGITECH_CMD_RGB_EFFECTS_GET_INFO); + get_effect.init(device_index, RGB_feature_index, LOGITECH_CMD_RGB_EFFECTS_GET_COUNT); get_effect.data[0] = get_count.data[0]; get_effect.data[1] = i; @@ -637,6 +645,10 @@ void logitech_device::getRGBconfig() leds.emplace(response.data[0], new_led); } + /*-----------------------------------------------------------------*\ + | Set the config to SW control mode | + \*-----------------------------------------------------------------*/ + set8071Effects(5); } /*get_count.feature_command = LOGITECH_CMD_RGB_EFFECTS_GET_STATE; @@ -681,7 +693,7 @@ uint8_t logitech_device::setDirectMode(bool direct) | Turn the direct mode on or off via the RGB_feature_index | \*-----------------------------------------------------------------*/ longFAPrequest set_direct; - set_direct.init(device_index, RGB_feature_index, LOGITECH_CMD_RGB_EFFECTS_UNKNOWN); + set_direct.init(device_index, RGB_feature_index, LOGITECH_FP8070_SET_SW_CTL); set_direct.data[0] = (direct) ? 1 : 0; set_direct.data[1] = set_direct.data[0]; @@ -705,7 +717,8 @@ uint8_t logitech_device::setDirectMode(bool direct) result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT); } } - return result; + + 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) @@ -731,7 +744,13 @@ uint8_t logitech_device::setMode(uint8_t mode, uint16_t speed, uint8_t zone, uin | Set the mode via the RGB_feature_index | \*-----------------------------------------------------------------*/ longFAPrequest set_mode; - set_mode.init(device_index, RGB_feature_index, ((feature_page == LOGITECH_HIDPP_PAGE_RGB_EFFECTS1) ? LOGITECH_CMD_RGB_EFFECTS_SET_CONTROL : LOGITECH_CMD_RGB_EFFECTS_GET_INFO)); + bool fp8070 = (feature_page == LOGITECH_HIDPP_PAGE_RGB_EFFECTS1); + + set_mode.init( + device_index, + RGB_feature_index, + (fp8070 ? (uint8_t)LOGITECH_FP8070_SET_EFFECT : (uint8_t)LOGITECH_FP8071_SET_LED_EFFECT) + ); set_mode.data[0] = zone; set_mode.data[1] = mode; @@ -739,12 +758,13 @@ uint8_t logitech_device::setMode(uint8_t mode, uint16_t speed, uint8_t zone, uin set_mode.data[3] = green; set_mode.data[4] = blue; + set_mode.data[12] = fp8070 ? 0x00 : 0x01; //Bit 2-3 Power Mode : Bit 1-0 Persistence + speed *= 100; switch(fx) { case LOGITECH_DEVICE_LED_ON: - set_mode.data[5] = 0x02; //zone; - //set_mode.data[12] = 0x01; //Save to flash testing + //set_mode.data[5] = 0x02; //zone; break; case LOGITECH_DEVICE_LED_SPECTRUM: @@ -792,5 +812,109 @@ uint8_t logitech_device::setMode(uint8_t mode, uint16_t speed, uint8_t zone, uin result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT); } } + + return result; +} + +uint8_t logitech_device::set8071Effects(uint8_t control) +{ + int result = 0; + + /*-----------------------------------------------------------------*\ + | Check the usage map for usage2 (0x11 Long FAP Message) | + | then set the device into direct mode via register 0x80 | + \*-----------------------------------------------------------------*/ + hid_device* dev_use2 = getDevice(2); + + if(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_effects; + set_effects.init(device_index, RGB_feature_index); + set_effects.feature_command = LOGITECH_FP8071_CONTROL; + set_effects.data[0] = 1; + set_effects.data[1] = 3; //Disables all FW control for PWR (0x02) and RGB (0x01) + set_effects.data[2] = control; + + /*-----------------------------------------------------*\ + | 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 guard(*mutex); + + result = hid_write(dev_use2, set_effects.buffer, set_effects.size()); + result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT); + } + else + { + result = hid_write(dev_use2, set_effects.buffer, set_effects.size()); + result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT); + } + } return result; } + +uint8_t logitech_device::set8071TimeoutControl(uint8_t /*control*/) +{ + int result = 0; + + /*-----------------------------------------------------------------*\ + | Check the usage map for usage2 (0x11 Long FAP Message) | + | then set the device into direct mode via register 0x80 | + \*-----------------------------------------------------------------*/ + hid_device* dev_use2 = getDevice(2); + + if(dev_use2) + { + /*-----------------------------------------------------------------*\ + | Create a buffer for reads | + \*-----------------------------------------------------------------*/ + blankFAPmessage response; + response.init(); + + /*-----------------------------------------------------------------*\ + | Turn the direct mode on or off via the RGB_feature_index | + \*-----------------------------------------------------------------*/ + longFAPrequest set_control; + set_control.init(device_index, RGB_feature_index, LOGITECH_FP8071_PWR_CFG); + set_control.data[0] = 1; //1; + set_control.data[3] = 0; //0x3C; //Inactive Lighting timeout MSB + set_control.data[4] = 5; //0x3C; //Inactive Lighting timeout LSB + set_control.data[5] = 0; //1; //Lights off timeout MSB + set_control.data[6] = 20; //0x2C; //Lights off timeout LSB + + /*-----------------------------------------------------*\ + | 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 guard(*mutex); + + result = hid_write(dev_use2, set_control.buffer, set_control.size()); + result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT); + } + else + { + result = hid_write(dev_use2, set_control.buffer, set_control.size()); + result = hid_read_timeout(dev_use2, response.buffer, response.size(), LOGITECH_PROTOCOL_TIMEOUT); + } + } + return(result); +} diff --git a/Controllers/LogitechController/LogitechProtocolCommon.h b/Controllers/LogitechController/LogitechProtocolCommon.h index f6bc99fa..9a0383f3 100644 --- a/Controllers/LogitechController/LogitechProtocolCommon.h +++ b/Controllers/LogitechController/LogitechProtocolCommon.h @@ -1,19 +1,21 @@ -/*-------------------------------------------------------------------*\ -| LogitechProtocolCommon.h | -| | -| Common Logitech RAP and FAP protocol calls | -| | -| Chris M (Dr_No) 4th May 2021 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| LogitechProtocolCommon.h | +| | +| Common functionality for Logitech RAP and FAP protocols | +| | +| Chris M (Dr_No) 04 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include -#include +#include #include "LogManager.h" -#pragma once - #define LOGITECH_PROTOCOL_TIMEOUT 300 //Timeout in ms #define LOGITECH_HEADER_SIZE 3 #define LOGITECH_SHORT_MESSAGE 0x10 @@ -50,7 +52,6 @@ #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 { @@ -77,6 +78,51 @@ enum LOGITECH_DEVICE_MODE LOGITECH_DEVICE_LED_CUSTOM = 0x000C }; +enum LOGITECH_FP8070 +{ + LOGITECH_FP8070_INFO = 0x00, + LOGITECH_FP8070_ZONE_INFO = 0x10, + LOGITECH_FP8070_EFFECT_INFO = 0x20, + LOGITECH_FP8070_SET_EFFECT = 0x30, + LOGITECH_FP8070_SET_CFG = 0x40, + LOGITECH_FP8070_GET_CFG = 0x50, + LOGITECH_FP8070_GET_BIN_INFO = 0x60, + LOGITECH_FP8070_GET_SW_CTL = 0x70, + LOGITECH_FP8070_SET_SW_CTL = 0x80, + LOGITECH_FP8070_GET_STATUS = 0x90, + LOGITECH_FP8070_CLEAR_EFFECT = 0xA0, + LOGITECH_FP8070_SET_DIR = 0xB0, + LOGITECH_FP8070_GET_COLOUR = 0xC0, + LOGITECH_FP8070_SYNC_CFG = 0xD0, + LOGITECH_FP8070_GET_EFFECT = 0xE0, + LOGITECH_FP8070_SET_BIN_INFO = 0xF0, +}; + +enum LOGITECH_FP8071 +{ + LOGITECH_FP8071_INFO = 0x00, + LOGITECH_FP8071_SET_LED_EFFECT = 0x10, + LOGITECH_FP8071_ZONE_PATTERN = 0x20, + LOGITECH_FP8071_CONFIG = 0x30, + LOGITECH_FP8070_BIN_INFO = 0x40, + LOGITECH_FP8071_CONTROL = 0x50, + LOGITECH_FP8071_SYNC_CFG = 0x60, + LOGITECH_FP8071_PWR_CFG = 0x70, + LOGITECH_FP8071_PWR_MODE = 0x80, + LOGITECH_FP8071_SHUTDOWN = 0x90 +}; + +enum LOGITECH_FP8071_FLAGS +{ + FP8071_SUPPORTS_GET_STATUS = 0x01, + FP8071_RESERVED = 0x02, + FP8071_SUPPORTS_SET_BIN_INFO = 0x04, + FP8071_MONOCHROME_ONLY = 0x08, + FP8071_NO_SYNC_SUPPORT = 0x10, + FP8071_SUPPORTS_SHUTDOWN = 0x20, + FP8071_SUPPORTS_CLUSTER_CHANGED = 0x40, +}; + extern const char* logitech_led_locations[]; extern const int NUM_LOGITECH_LED_LOCATIONS; @@ -120,7 +166,7 @@ union shortFAPrequest this->report_id = LOGITECH_SHORT_MESSAGE; this->device_index = device_index; this->feature_index = feature_index; - this->feature_command = 0; + this->feature_command = feature_command; for(size_t i = 0; i < sizeof(data); i++) { this->data[i] = 0; @@ -256,6 +302,8 @@ public: logitech_led getLED_info(uint8_t LED_num); 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); + uint8_t set8071Effects(uint8_t control); + uint8_t set8071TimeoutControl(uint8_t control); int getDeviceName(); private: std::map leds; diff --git a/Controllers/LogitechController/LogitechX56Controller.h b/Controllers/LogitechController/LogitechX56Controller.h deleted file mode 100644 index 2d99f4dc..00000000 --- a/Controllers/LogitechController/LogitechX56Controller.h +++ /dev/null @@ -1,36 +0,0 @@ -/*-----------------------------------------*\ -| LogitechX56Controller.h | -| | -| Generic RGB Interface Logitech X56 | -| Class | -| | -| Edbgon 11/06/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include - -#pragma once - -#define X56_CONTROLLER_PACKET_SIZE 64 - -class LogitechX56Controller -{ -public: - LogitechX56Controller(hid_device* dev_handle, const char* path); - - ~LogitechX56Controller(); - - std::string GetDeviceLocation(); - char* GetDeviceName(); - std::string GetSerialString(); - - void SetColor(RGBColor colors, uint8_t brightness); - void Save(); - -private: - char device_name[32]; - hid_device* dev; - std::string location; -}; diff --git a/Controllers/LogitechController/LogitechX56Controller.cpp b/Controllers/LogitechController/LogitechX56Controller/LogitechX56Controller.cpp similarity index 75% rename from Controllers/LogitechController/LogitechX56Controller.cpp rename to Controllers/LogitechController/LogitechX56Controller/LogitechX56Controller.cpp index 40d4f802..46881582 100644 --- a/Controllers/LogitechController/LogitechX56Controller.cpp +++ b/Controllers/LogitechController/LogitechX56Controller/LogitechX56Controller.cpp @@ -1,19 +1,23 @@ -/*-----------------------------------------*\ -| LogitechX56Controller.cpp | -| | -| Generic RGB Interface Logitech X56 | -| Class | -| | -| Edbgon 11/06/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| LogitechX56Controller.cpp | +| | +| Driver for Logitech X56 | +| | +| Edbgon 11 Jun 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "LogitechX56Controller.h" #include +#include "LogitechX56Controller.h" +#include "StringUtils.h" -LogitechX56Controller::LogitechX56Controller(hid_device* dev_handle, const char* path) +LogitechX56Controller::LogitechX56Controller(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } LogitechX56Controller::~LogitechX56Controller() @@ -26,9 +30,9 @@ std::string LogitechX56Controller::GetDeviceLocation() return("HID: " + location); } -char* LogitechX56Controller::GetDeviceName() +std::string LogitechX56Controller::GetDeviceName() { - return device_name; + return(name); } std::string LogitechX56Controller::GetSerialString() @@ -41,10 +45,7 @@ std::string LogitechX56Controller::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void LogitechX56Controller::SetColor(RGBColor color, uint8_t brightness) diff --git a/Controllers/LogitechController/LogitechX56Controller/LogitechX56Controller.h b/Controllers/LogitechController/LogitechX56Controller/LogitechX56Controller.h new file mode 100644 index 00000000..ed4f81c9 --- /dev/null +++ b/Controllers/LogitechController/LogitechX56Controller/LogitechX56Controller.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------*\ +| LogitechX56Controller.h | +| | +| Driver for Logitech X56 | +| | +| Edbgon 11 Jun 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define X56_CONTROLLER_PACKET_SIZE 64 + +class LogitechX56Controller +{ +public: + LogitechX56Controller(hid_device* dev_handle, const char* path, std::string dev_name); + + ~LogitechX56Controller(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + std::string GetSerialString(); + + void SetColor(RGBColor colors, uint8_t brightness); + void Save(); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/LogitechController/RGBController_LogitechX56.cpp b/Controllers/LogitechController/LogitechX56Controller/RGBController_LogitechX56.cpp similarity index 83% rename from Controllers/LogitechController/RGBController_LogitechX56.cpp rename to Controllers/LogitechController/LogitechX56Controller/RGBController_LogitechX56.cpp index dd995aad..7689cc5a 100644 --- a/Controllers/LogitechController/RGBController_LogitechX56.cpp +++ b/Controllers/LogitechController/LogitechX56Controller/RGBController_LogitechX56.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_LogitechX56.cpp | -| | -| Generic RGB Interface Logitech X56 | -| Class | -| | -| Edbgon 11/06/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_LogitechX56.cpp | +| | +| RGBController for Logitech X56 | +| | +| Edbgon 11 Jun 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_LogitechX56.h" diff --git a/Controllers/LogitechController/LogitechX56Controller/RGBController_LogitechX56.h b/Controllers/LogitechController/LogitechX56Controller/RGBController_LogitechX56.h new file mode 100644 index 00000000..49fc5857 --- /dev/null +++ b/Controllers/LogitechController/LogitechX56Controller/RGBController_LogitechX56.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_LogitechX56.h | +| | +| RGBController for Logitech X56 | +| | +| Edbgon 11 Jun 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "LogitechX56Controller.h" + +class RGBController_LogitechX56 : public RGBController +{ +public: + RGBController_LogitechX56(LogitechX56Controller* controller_ptr); + ~RGBController_LogitechX56(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + LogitechX56Controller* controller; +}; diff --git a/Controllers/LogitechController/RGBController_LogitechG203L.h b/Controllers/LogitechController/RGBController_LogitechG203L.h deleted file mode 100644 index 654f6fde..00000000 --- a/Controllers/LogitechController/RGBController_LogitechG203L.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include "RGBController.h" -#include "LogitechG203LController.h" - -class RGBController_LogitechG203L : public RGBController -{ -public: - RGBController_LogitechG203L(LogitechG203LController* controller_ptr); - ~RGBController_LogitechG203L(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - LogitechG203LController* controller; -}; diff --git a/Controllers/LogitechController/RGBController_LogitechG213.h b/Controllers/LogitechController/RGBController_LogitechG213.h deleted file mode 100644 index ab09e7a9..00000000 --- a/Controllers/LogitechController/RGBController_LogitechG213.h +++ /dev/null @@ -1,31 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LogitechG213.h | -| | -| Generic RGB Interface for Logitech G213 | -| | -| Eric Samuelson (edbgon) 10/06/2020 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "LogitechG213Controller.h" - -class RGBController_LogitechG213 : public RGBController -{ -public: - RGBController_LogitechG213(LogitechG213Controller* controller_ptr); - ~RGBController_LogitechG213(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - LogitechG213Controller* controller; -}; diff --git a/Controllers/LogitechController/RGBController_LogitechG560.h b/Controllers/LogitechController/RGBController_LogitechG560.h deleted file mode 100644 index 54f3e726..00000000 --- a/Controllers/LogitechController/RGBController_LogitechG560.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LogitechG560.h | -| | -| Generic RGB Interface for | -| G560 RGB Speaker | -| | -| Cheerpipe 10/28/2020 | -| Based on | -| TheRogueZeta 8/31/2020 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "LogitechG560Controller.h" - -class RGBController_LogitechG560 : public RGBController -{ -public: - RGBController_LogitechG560(LogitechG560Controller* controller_ptr); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - LogitechG560Controller* controller; -}; diff --git a/Controllers/LogitechController/RGBController_LogitechG810.h b/Controllers/LogitechController/RGBController_LogitechG810.h deleted file mode 100644 index 3228cb21..00000000 --- a/Controllers/LogitechController/RGBController_LogitechG810.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LogitechG810.h | -| | -| Generic RGB Interface for Logitech G810 | -| Orion Spectrum keyboard | -| | -| Adam Honse (CalcProgrammer1) 6/12/2020 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "LogitechG810Controller.h" - -class RGBController_LogitechG810 : public RGBController -{ -public: - RGBController_LogitechG810(LogitechG810Controller* controller_ptr); - ~RGBController_LogitechG810(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - LogitechG810Controller* controller; -}; diff --git a/Controllers/LogitechController/RGBController_LogitechG815.h b/Controllers/LogitechController/RGBController_LogitechG815.h deleted file mode 100644 index 30e08bd5..00000000 --- a/Controllers/LogitechController/RGBController_LogitechG815.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LogitechG815.h | -| | -| Generic RGB Interface for Logitech G815 | -| RGB Mechanical Gaming Keyboard | -| | -| Cheerpipe 3/20/2021 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "LogitechG815Controller.h" - -class RGBController_LogitechG815 : public RGBController -{ -public: - RGBController_LogitechG815(LogitechG815Controller* controller_ptr); - ~RGBController_LogitechG815(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - LogitechG815Controller* controller; - std::vector current_colors; -}; diff --git a/Controllers/LogitechController/RGBController_LogitechG910.h b/Controllers/LogitechController/RGBController_LogitechG910.h deleted file mode 100644 index c9f463a0..00000000 --- a/Controllers/LogitechController/RGBController_LogitechG910.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LogitechG910.h | -| | -| Generic RGB Interface for Logitech G910 | -| Orion Spectrum keyboard | -| | -| Adam Honse (CalcProgrammer1) 6/12/2020 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "LogitechG910Controller.h" - -class RGBController_LogitechG910 : public RGBController -{ -public: - RGBController_LogitechG910(LogitechG910Controller* controller_ptr); - ~RGBController_LogitechG910(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - LogitechG910Controller* controller; -}; diff --git a/Controllers/LogitechController/RGBController_LogitechG915.h b/Controllers/LogitechController/RGBController_LogitechG915.h deleted file mode 100644 index fa74ce92..00000000 --- a/Controllers/LogitechController/RGBController_LogitechG915.h +++ /dev/null @@ -1,35 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LogitechG915.h | -| | -| Generic RGB Interface for Logitech G915 | -| RGB Mechanical Gaming Keyboard | -| | -| Cheerpipe 3/20/2021 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "LogitechG915Controller.h" - -class RGBController_LogitechG915 : public RGBController -{ -public: - RGBController_LogitechG915(LogitechG915Controller* controller_ptr, bool tkl); - ~RGBController_LogitechG915(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - bool is_tkl; - - LogitechG915Controller* controller; - std::vector current_colors; -}; diff --git a/Controllers/LogitechController/RGBController_LogitechG933.cpp b/Controllers/LogitechController/RGBController_LogitechG933.cpp deleted file mode 100644 index b2777106..00000000 --- a/Controllers/LogitechController/RGBController_LogitechG933.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LogitechG933.cpp | -| | -| Generic RGB Interface for | -| Logitech G933 RGB Headset | -| | -| Edbgon 06/21/2021 | -| Based on | -| TheRogueZeta 8/31/2020 | -\*-----------------------------------------*/ - -#include "RGBController_LogitechG933.h" - -/**------------------------------------------------------------------*\ - @name Logitech G933 - @category Headset - @type USB - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectLogitechG933 - @comment -\*-------------------------------------------------------------------*/ - -RGBController_LogitechG933::RGBController_LogitechG933(LogitechG933Controller* controller_ptr) -{ - controller = controller_ptr; - - name = "Logitech G933 Lightsync Headset"; - vendor = "Logitech"; - type = DEVICE_TYPE_HEADSET; - description = "Logitech G933 Lightsync Headset"; - location = controller->GetDeviceLocation(); - - mode Off; - Off.name = "Off"; - Off.value = LOGITECH_G933_MODE_OFF; - Off.flags = 0; - Off.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Off); - - mode Direct; - Direct.name = "Direct"; - Direct.value = LOGITECH_G933_MODE_DIRECT; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - - SetupZones(); -} - -void RGBController_LogitechG933::SetupZones() -{ - zone G933_logo; - G933_logo.name = "Logo"; - G933_logo.type = ZONE_TYPE_SINGLE; - G933_logo.leds_min = 1; - G933_logo.leds_max = 1; - G933_logo.leds_count = 1; - G933_logo.matrix_map = NULL; - zones.push_back(G933_logo); - - led G933_logo_led; - G933_logo_led.name = "Logo"; - G933_logo_led.value = 0x00; - leds.push_back(G933_logo_led); - - zone G933_strip; - G933_strip.name = "LED Strip"; - G933_strip.type = ZONE_TYPE_SINGLE; - G933_strip.leds_min = 1; - G933_strip.leds_max = 1; - G933_strip.leds_count = 1; - G933_strip.matrix_map = NULL; - zones.push_back(G933_strip); - - led G933_strip_led; - G933_strip_led.name = "Led Strip"; - G933_strip_led.value = 0x01; - leds.push_back(G933_strip_led); - - SetupColors(); -} - -void RGBController_LogitechG933::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_LogitechG933::DeviceUpdateLEDs() -{ - for(std::size_t led_idx = 0; led_idx < leds.size(); led_idx++) - { - unsigned char red = RGBGetRValue(colors[led_idx]); - unsigned char grn = RGBGetGValue(colors[led_idx]); - unsigned char blu = RGBGetBValue(colors[led_idx]); - - controller->SendHeadsetMode((unsigned char)leds[led_idx].value, modes[active_mode].value, red, grn, blu); - } -} - -void RGBController_LogitechG933::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_LogitechG933::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_LogitechG933::DeviceUpdateMode() -{ - for(std::size_t led_idx = 0; led_idx < leds.size(); led_idx++) - { - if(modes[active_mode].value == LOGITECH_G933_MODE_OFF) - { - controller->SetOffMode(leds[led_idx].value); - } - else - { - /*---------------------------------------------------------*\ - | Required to "reset" RGB controller and start receiving | - | color in direct mode | - \*---------------------------------------------------------*/ - controller->SetDirectMode(leds[led_idx].value); - } - - } - DeviceUpdateLEDs(); -} diff --git a/Controllers/LogitechController/RGBController_LogitechG933.h b/Controllers/LogitechController/RGBController_LogitechG933.h deleted file mode 100644 index 6a36e1a9..00000000 --- a/Controllers/LogitechController/RGBController_LogitechG933.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LogitechG933.h | -| | -| Generic RGB Interface for | -| G933 RGB Headset | -| | -| Edbgon 06/21/2021 | -| Based on | -| TheRogueZeta 8/31/2020 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "LogitechG933Controller.h" - -class RGBController_LogitechG933 : public RGBController -{ -public: - RGBController_LogitechG933(LogitechG933Controller* controller_ptr); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - LogitechG933Controller* controller; -}; diff --git a/Controllers/LogitechController/RGBController_LogitechGLightsync.h b/Controllers/LogitechController/RGBController_LogitechGLightsync.h deleted file mode 100644 index 00a48865..00000000 --- a/Controllers/LogitechController/RGBController_LogitechGLightsync.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LogitechGLightsync.h | -| | -| Generic RGB Interface for | -| Logitech G Lightsync Devices | -| | -| TheRogueZeta 04/21/2021 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "LogitechGLightsyncController.h" - -class RGBController_LogitechGLightsync : public RGBController -{ -public: - RGBController_LogitechGLightsync(LogitechGLightsyncController* controller_ptr); - ~RGBController_LogitechGLightsync(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - LogitechGLightsyncController* controller; -}; diff --git a/Controllers/LogitechController/RGBController_LogitechGLightsync1zone.h b/Controllers/LogitechController/RGBController_LogitechGLightsync1zone.h deleted file mode 100644 index 786dcccb..00000000 --- a/Controllers/LogitechController/RGBController_LogitechGLightsync1zone.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LogitechGLightsync1zone.h | -| | -| Generic RGB Interface for single zone | -| Logitech G Lightsync Devices | -| | -| TheRogueZeta 04/21/2021 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "LogitechGLightsyncController.h" - -class RGBController_LogitechGLightsync1zone : public RGBController -{ -public: - RGBController_LogitechGLightsync1zone(LogitechGLightsyncController* controller_ptr); - ~RGBController_LogitechGLightsync1zone(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - LogitechGLightsyncController* controller; -}; diff --git a/Controllers/LogitechController/RGBController_LogitechGPowerPlay.h b/Controllers/LogitechController/RGBController_LogitechGPowerPlay.h deleted file mode 100644 index a7ea95fa..00000000 --- a/Controllers/LogitechController/RGBController_LogitechGPowerPlay.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LogitechGPowerPlay.h | -| | -| Generic RGB Interface for | -| Logitech G PowerPlay Wireless Mousemat | -| | -| TheRogueZeta 8/31/2020 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "LogitechGLightsyncController.h" - -class RGBController_LogitechGPowerPlay : public RGBController -{ -public: - RGBController_LogitechGPowerPlay(LogitechGLightsyncController* controller_ptr); - ~RGBController_LogitechGPowerPlay(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - LogitechGLightsyncController* controller; -}; diff --git a/Controllers/LogitechController/RGBController_LogitechGProKeyboard.h b/Controllers/LogitechController/RGBController_LogitechGProKeyboard.h deleted file mode 100644 index 5b2cdd74..00000000 --- a/Controllers/LogitechController/RGBController_LogitechGProKeyboard.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LogitechGPro.h | -| | -| Generic RGB Interface for Logitech G Pro | -| keyboard | -| | -| sanchezzzs 20/10/2021 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "LogitechGProKeyboardController.h" - -class RGBController_LogitechGProKeyboard : public RGBController -{ -public: - RGBController_LogitechGProKeyboard(LogitechGProKeyboardController* controller_ptr); - ~RGBController_LogitechGProKeyboard(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - LogitechGProKeyboardController* controller; -}; diff --git a/Controllers/LogitechController/RGBController_LogitechLightspeed.h b/Controllers/LogitechController/RGBController_LogitechLightspeed.h deleted file mode 100644 index 0b3e325b..00000000 --- a/Controllers/LogitechController/RGBController_LogitechLightspeed.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| 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* controller_ptr); - ~RGBController_LogitechLightspeed(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - uint16_t pid; //This is a workaround fix for G502 mode breathing / spectrum cycle swap -private: - LogitechLightspeedController* controller; -}; diff --git a/Controllers/LogitechController/RGBController_LogitechX56.h b/Controllers/LogitechController/RGBController_LogitechX56.h deleted file mode 100644 index efc673f4..00000000 --- a/Controllers/LogitechController/RGBController_LogitechX56.h +++ /dev/null @@ -1,34 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_LogitechX56.h | -| | -| Generic RGB Interface Logitech X56 | -| Class | -| | -| Edbgon 11/06/2021 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "LogitechX56Controller.h" - -class RGBController_LogitechX56 : public RGBController -{ -public: - RGBController_LogitechX56(LogitechX56Controller* controller_ptr); - ~RGBController_LogitechX56(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - LogitechX56Controller* controller; -}; diff --git a/Controllers/LuxaforController/LuxaforController.cpp b/Controllers/LuxaforController/LuxaforController.cpp new file mode 100644 index 00000000..fca10f8e --- /dev/null +++ b/Controllers/LuxaforController/LuxaforController.cpp @@ -0,0 +1,135 @@ +/*---------------------------------------------------------*\ +| LuxaforController.cpp | +| | +| Driver for Luxafor devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 05 Sep 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "LuxaforController.h" +#include "StringUtils.h" + +LuxaforController::LuxaforController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; +} + +LuxaforController::~LuxaforController() +{ + hid_close(dev); +} + +std::string LuxaforController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string LuxaforController::GetNameString() +{ + return(name); +} + +std::string LuxaforController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void LuxaforController::SendPacket(unsigned char mode, unsigned char led, unsigned char red, unsigned char grn, unsigned char blu, unsigned char type) +{ + unsigned char usb_buf[9]; + + memset(usb_buf, 0, sizeof(usb_buf)); + + switch(mode) + { + /*-------------------------------------------------*\ + | For Direct, Fade, and Strobe, the packet format: | + | 0: Report ID (Always 0) | + | 1: Mode (1: Direct, 2: Fade, 3: Strobe) | + | 2: LED Index | + | 3: Red | + | 4: Green | + | 5: Blue | + | 6: Changing Time (Fade) / Speed (Strobe) | + | 7: Unused | + | 8: Repeat (Strobe) | + \*-------------------------------------------------*/ + case LUXAFOR_MODE_DIRECT: + case LUXAFOR_MODE_FADE: + case LUXAFOR_MODE_STROBE: + usb_buf[0] = 0x00; + usb_buf[1] = mode; + usb_buf[2] = led; + usb_buf[3] = red; + usb_buf[4] = grn; + usb_buf[5] = blu; + usb_buf[6] = 100; + usb_buf[7] = 0; + usb_buf[8] = (mode == LUXAFOR_MODE_STROBE) ? 255 : 0; + break; + + /*-------------------------------------------------*\ + | For Wave, the packet format: | + | 0: Report ID (Always 0) | + | 1: Mode (4: Wave) | + | 2: Wave Type (1-5) | + | 3: Red | + | 4: Green | + | 5: Blue | + | 6: Unused | + | 7: Repeat | + | 8: Speed | + \*-------------------------------------------------*/ + case LUXAFOR_MODE_WAVE: + usb_buf[0] = 0x00; + usb_buf[1] = mode; + usb_buf[2] = type; + usb_buf[3] = red; + usb_buf[4] = grn; + usb_buf[5] = blu; + usb_buf[6] = 0; + usb_buf[7] = 255; + usb_buf[8] = 100; + break; + + /*-------------------------------------------------*\ + | For Pattern, the packet format: | + | 0: Report ID (Always 0) | + | 1: Mode (6: Pattern) | + | 2: Pattern Number (1-8) | + | 3: Repeat | + | 4: Unused | + | 5: Unused | + | 6: Unused | + | 7: Unused | + | 8: Unused | + \*-------------------------------------------------*/ + case LUXAFOR_MODE_PATTERN: + usb_buf[0] = 0x00; + usb_buf[1] = mode; + usb_buf[2] = type; + usb_buf[3] = 255; + usb_buf[4] = 0; + usb_buf[5] = 0; + usb_buf[6] = 0; + usb_buf[7] = 0; + usb_buf[8] = 0; + break; + } + + hid_write(dev, usb_buf, sizeof(usb_buf)); +} diff --git a/Controllers/LuxaforController/LuxaforController.h b/Controllers/LuxaforController/LuxaforController.h new file mode 100644 index 00000000..8439a324 --- /dev/null +++ b/Controllers/LuxaforController/LuxaforController.h @@ -0,0 +1,60 @@ +/*---------------------------------------------------------*\ +| LuxaforController.h | +| | +| Driver for Luxafor devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 05 Sep 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include + +enum +{ + LUXAFOR_LED_FIRST = 1, + LUXAFOR_LED_ALL = 255, +}; + +enum +{ + LUXAFOR_MODE_DIRECT = 1, + LUXAFOR_MODE_FADE = 2, + LUXAFOR_MODE_STROBE = 3, + LUXAFOR_MODE_WAVE = 4, + LUXAFOR_MODE_PATTERN = 6, +}; + +enum +{ + LUXAFOR_PATTERN_TRAFFIC_LIGHTS = 1, + LUXAFOR_PATTERN_2 = 2, + LUXAFOR_PATTERN_3 = 3, + LUXAFOR_PATTERN_4 = 4, + LUXAFOR_PATTERN_POLICE = 5, + LUXAFOR_PATTERN_6 = 6, + LUXAFOR_PATTERN_7 = 7, + LUXAFOR_PATTERN_8 = 8, +}; + +class LuxaforController +{ +public: + LuxaforController(hid_device* dev_handle, const char* path, std::string dev_name); + ~LuxaforController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SendPacket(unsigned char mode, unsigned char led, unsigned char red, unsigned char grn, unsigned char blu, unsigned char type); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/LuxaforController/LuxaforControllerDetect.cpp b/Controllers/LuxaforController/LuxaforControllerDetect.cpp new file mode 100644 index 00000000..28ab4dbb --- /dev/null +++ b/Controllers/LuxaforController/LuxaforControllerDetect.cpp @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| LuxaforControllerDetect.cpp | +| | +| Detector for Luxafor devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 05 Sep 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "LuxaforController.h" +#include "RGBController_Luxafor.h" + +/*---------------------------------------------------------*\ +| Luxafor USB Vendor ID | +\*---------------------------------------------------------*/ +#define LUXAFOR_VID 0x04D8 + +/*---------------------------------------------------------*\ +| Luxafor USB Product ID | +\*---------------------------------------------------------*/ +#define LUXAFOR_FLAG_PID 0xF372 + +void DetectLuxaforControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + LuxaforController* controller = new LuxaforController(dev, info->path, name); + RGBController_Luxafor* rgb_controller = new RGBController_Luxafor(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR( "Luxafor Flag", DetectLuxaforControllers, LUXAFOR_VID, LUXAFOR_FLAG_PID ); diff --git a/Controllers/LuxaforController/RGBController_Luxafor.cpp b/Controllers/LuxaforController/RGBController_Luxafor.cpp new file mode 100644 index 00000000..c6ca497e --- /dev/null +++ b/Controllers/LuxaforController/RGBController_Luxafor.cpp @@ -0,0 +1,239 @@ +/*---------------------------------------------------------*\ +| RGBController_Luxafor.cpp | +| | +| RGBController for Luxafor devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 05 Sep 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_Luxafor.h" + +RGBController_Luxafor::RGBController_Luxafor(LuxaforController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + type = DEVICE_TYPE_ACCESSORY; + vendor = "Luxafor"; + description = "Luxafor Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = LUXAFOR_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + // mode Fade; + // Fade.name = "Fade"; + // Fade.value = LUXAFOR_MODE_FADE; + // Fade.flags = MODE_FLAG_HAS_PER_LED_COLOR; + // Fade.color_mode = MODE_COLORS_PER_LED; + // modes.push_back(Fade); + + // mode Strobe; + // Strobe.name = "Strobe"; + // Strobe.value = LUXAFOR_MODE_STROBE; + // Strobe.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + // Strobe.color_mode = MODE_COLORS_MODE_SPECIFIC; + // Strobe.colors_min = 1; + // Strobe.colors_max = 1; + // Strobe.colors.resize(1); + // modes.push_back(Strobe); + + // mode Wave; + // Wave.name = "Wave"; + // Wave.value = LUXAFOR_MODE_WAVE; + // Wave.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + // Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; + // Wave.colors_min = 1; + // Wave.colors_max = 1; + // Wave.colors.resize(1); + // modes.push_back(Wave); + + mode TrafficLights; + TrafficLights.name = "Traffic Lights"; + TrafficLights.value = LUXAFOR_MODE_PATTERN_TRAFFIC_LIGHTS; + TrafficLights.flags = 0; + TrafficLights.color_mode = MODE_COLORS_NONE; + modes.push_back(TrafficLights); + + mode Pattern2; + Pattern2.name = "Pattern 2"; + Pattern2.value = LUXAFOR_MODE_PATTERN_2; + Pattern2.flags = 0; + Pattern2.color_mode = MODE_COLORS_NONE; + modes.push_back(Pattern2); + + mode Pattern3; + Pattern3.name = "Pattern 3"; + Pattern3.value = LUXAFOR_MODE_PATTERN_3; + Pattern3.flags = 0; + Pattern3.color_mode = MODE_COLORS_NONE; + modes.push_back(Pattern3); + + mode Pattern4; + Pattern4.name = "Pattern 4"; + Pattern4.value = LUXAFOR_MODE_PATTERN_4; + Pattern4.flags = 0; + Pattern4.color_mode = MODE_COLORS_NONE; + modes.push_back(Pattern4); + + mode Police; + Police.name = "Police"; + Police.value = LUXAFOR_MODE_PATTERN_POLICE; + Police.flags = 0; + Police.color_mode = MODE_COLORS_NONE; + modes.push_back(Police); + + mode Pattern6; + Pattern6.name = "Pattern 6"; + Pattern6.value = LUXAFOR_MODE_PATTERN_6; + Pattern6.flags = 0; + Pattern6.color_mode = MODE_COLORS_NONE; + modes.push_back(Pattern6); + + mode Pattern7; + Pattern7.name = "Pattern 7"; + Pattern7.value = LUXAFOR_MODE_PATTERN_7; + Pattern7.flags = 0; + Pattern7.color_mode = MODE_COLORS_NONE; + modes.push_back(Pattern7); + + mode Pattern8; + Pattern8.name = "Pattern 8"; + Pattern8.value = LUXAFOR_MODE_PATTERN_8; + Pattern8.flags = 0; + Pattern8.color_mode = MODE_COLORS_NONE; + modes.push_back(Pattern8); + + SetupZones(); +} + +RGBController_Luxafor::~RGBController_Luxafor() +{ + +} + +void RGBController_Luxafor::SetupZones() +{ + /*-----------------------------------------------------*\ + | The Luxafor Flag has 2 zones | + | * Flag (3 LEDs) | + | * Rear (3 LEDs) | + | The LED index starts at 1. Sending 255 for the LED ID | + | sets all LEDs at once. | + \*-----------------------------------------------------*/ + unsigned int led_value = LUXAFOR_LED_FIRST; + + zone flag_zone; + flag_zone.name = "Flag"; + flag_zone.type = ZONE_TYPE_SINGLE; + flag_zone.leds_min = 3; + flag_zone.leds_max = 3; + flag_zone.leds_count = 3; + flag_zone.matrix_map = NULL; + zones.push_back(flag_zone); + + for(std::size_t led_idx = 0; led_idx < flag_zone.leds_count; led_idx++) + { + led luxafor_led; + luxafor_led.name = "Flag LED"; + luxafor_led.value = led_value; + leds.push_back(luxafor_led); + + led_value++; + } + + zone rear_zone; + rear_zone.name = "Rear"; + rear_zone.type = ZONE_TYPE_SINGLE; + rear_zone.leds_min = 3; + rear_zone.leds_max = 3; + rear_zone.leds_count = 3; + rear_zone.matrix_map = NULL; + zones.push_back(rear_zone); + + for(std::size_t led_idx = 0; led_idx < rear_zone.leds_count; led_idx++) + { + led luxafor_led; + luxafor_led.name = "Rear LED"; + luxafor_led.value = led_value; + leds.push_back(luxafor_led); + + led_value++; + } + + SetupColors(); +} + +void RGBController_Luxafor::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*-----------------------------------------------------*\ + | This device does not support resizing zones | + \*-----------------------------------------------------*/ +} + +void RGBController_Luxafor::DeviceUpdateLEDs() +{ + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + UpdateZoneLEDs((int)zone_idx); + } +} + +void RGBController_Luxafor::UpdateZoneLEDs(int zone) +{ + for(unsigned int led_idx = 0; led_idx < zones[zone].leds_count; led_idx++) + { + UpdateSingleLED((int)(zones[zone].start_idx + led_idx)); + } +} + +void RGBController_Luxafor::UpdateSingleLED(int led) +{ + if(modes[active_mode].color_mode == MODE_COLORS_PER_LED) + { + unsigned char red = RGBGetRValue(colors[led]); + unsigned char grn = RGBGetGValue(colors[led]); + unsigned char blu = RGBGetBValue(colors[led]); + + controller->SendPacket((modes[active_mode].value & 0xFF), leds[led].value, red, grn, blu, 0); + } +} + +void RGBController_Luxafor::DeviceUpdateMode() +{ + switch(modes[active_mode].color_mode) + { + case MODE_COLORS_PER_LED: + DeviceUpdateLEDs(); + break; + + case MODE_COLORS_MODE_SPECIFIC: + { + unsigned char red = RGBGetRValue(colors[modes[active_mode].colors[0]]); + unsigned char grn = RGBGetGValue(colors[modes[active_mode].colors[0]]); + unsigned char blu = RGBGetBValue(colors[modes[active_mode].colors[0]]); + + controller->SendPacket((modes[active_mode].value & 0xFF), LUXAFOR_LED_ALL, red, grn, blu, 0); + } + break; + + case MODE_COLORS_NONE: + controller->SendPacket((modes[active_mode].value & 0xFF), LUXAFOR_LED_ALL, 0, 0, 0, (modes[active_mode].value >> 8)); + break; + } +} + +void RGBController_Luxafor::DeviceSaveMode() +{ + /*-----------------------------------------------------*\ + | This device does not support saving | + \*-----------------------------------------------------*/ +} diff --git a/Controllers/LuxaforController/RGBController_Luxafor.h b/Controllers/LuxaforController/RGBController_Luxafor.h new file mode 100644 index 00000000..6bbb425a --- /dev/null +++ b/Controllers/LuxaforController/RGBController_Luxafor.h @@ -0,0 +1,52 @@ +/*---------------------------------------------------------*\ +| RGBController_Luxafor.h | +| | +| RGBController for Luxafor devices | +| | +| Adam Honse (calcprogrammer1@gmail.com) 05 Sep 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "LuxaforController.h" +#include "RGBController.h" + +/*---------------------------------------------------------*\ +| Additional "pseudo-modes" which combine pattern mode with | +| the pattern to use. | +\*---------------------------------------------------------*/ +enum +{ + LUXAFOR_MODE_PATTERN_TRAFFIC_LIGHTS = LUXAFOR_MODE_PATTERN + (LUXAFOR_PATTERN_TRAFFIC_LIGHTS << 8), + LUXAFOR_MODE_PATTERN_2 = LUXAFOR_MODE_PATTERN + (LUXAFOR_PATTERN_2 << 8), + LUXAFOR_MODE_PATTERN_3 = LUXAFOR_MODE_PATTERN + (LUXAFOR_PATTERN_3 << 8), + LUXAFOR_MODE_PATTERN_4 = LUXAFOR_MODE_PATTERN + (LUXAFOR_PATTERN_4 << 8), + LUXAFOR_MODE_PATTERN_POLICE = LUXAFOR_MODE_PATTERN + (LUXAFOR_PATTERN_POLICE << 8), + LUXAFOR_MODE_PATTERN_6 = LUXAFOR_MODE_PATTERN + (LUXAFOR_PATTERN_6 << 8), + LUXAFOR_MODE_PATTERN_7 = LUXAFOR_MODE_PATTERN + (LUXAFOR_PATTERN_7 << 8), + LUXAFOR_MODE_PATTERN_8 = LUXAFOR_MODE_PATTERN + (LUXAFOR_PATTERN_8 << 8), +}; + +class RGBController_Luxafor : public RGBController +{ +public: + RGBController_Luxafor(LuxaforController* controller_ptr); + ~RGBController_Luxafor(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + LuxaforController* controller; +}; diff --git a/Controllers/MSI3ZoneController/MSI3ZoneController.cpp b/Controllers/MSI3ZoneController/MSI3ZoneController.cpp index a7a0202b..5e8350ae 100644 --- a/Controllers/MSI3ZoneController/MSI3ZoneController.cpp +++ b/Controllers/MSI3ZoneController/MSI3ZoneController.cpp @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| MSI3ZoneController.cpp | -| | -| Driver for MSI/Steelseries 3-Zone | -| Keyboard lighting controller | -| | -| Adam Honse (CalcProgrammer1) 12/25/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| MSI3ZoneController.cpp | +| | +| Driver for MSI/SteelSeries 3-Zone keyboard | +| | +| Adam Honse (CalcProgrammer1) 25 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "MSI3ZoneController.h" +#include "StringUtils.h" MSI3ZoneController::MSI3ZoneController(hid_device* dev_handle, const char* path) { @@ -42,10 +45,7 @@ std::string MSI3ZoneController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void MSI3ZoneController::SetLEDs(std::vector colors) diff --git a/Controllers/MSI3ZoneController/MSI3ZoneController.h b/Controllers/MSI3ZoneController/MSI3ZoneController.h index 38fb619c..2ed1e9a2 100644 --- a/Controllers/MSI3ZoneController/MSI3ZoneController.h +++ b/Controllers/MSI3ZoneController/MSI3ZoneController.h @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| MSI3ZoneController.h | -| | -| Definitions and types for MSI/Steelseries| -| 3-Zone Keyboard lighting controller | -| | -| Adam Honse (CalcProgrammer1) 12/25/2019 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| MSI3ZoneController.h | +| | +| Driver for MSI/SteelSeries 3-Zone keyboard | +| | +| Adam Honse (CalcProgrammer1) 25 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + class MSI3ZoneController { public: @@ -25,7 +26,7 @@ public: std::string GetSerialString(); void SetLEDs(std::vector colors); - + private: char device_name[32]; hid_device* dev; diff --git a/Controllers/MSI3ZoneController/MSI3ZoneControllerDetect.cpp b/Controllers/MSI3ZoneController/MSI3ZoneControllerDetect.cpp index 78cdd154..3630d6f3 100644 --- a/Controllers/MSI3ZoneController/MSI3ZoneControllerDetect.cpp +++ b/Controllers/MSI3ZoneController/MSI3ZoneControllerDetect.cpp @@ -1,8 +1,18 @@ +/*---------------------------------------------------------*\ +| MSI3ZoneControllerDetect.cpp | +| | +| Detector for MSI/SteelSeries 3-Zone keyboard | +| | +| Adam Honse (CalcProgrammer1) 25 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "MSI3ZoneController.h" -#include "RGBController.h" #include "RGBController_MSI3Zone.h" -#include #define MSI_3_ZONE_KEYBOARD_VID 0x1770 #define MSI_3_ZONE_KEYBOARD_PID 0xFF00 @@ -25,7 +35,7 @@ void DetectMSI3ZoneControllers(hid_device_info* info, const std::string&) MSI3ZoneController* controller = new MSI3ZoneController(dev, info->path); RGBController_MSI3Zone* rgb_controller = new RGBController_MSI3Zone(controller); // Constructor sets the name - + ResourceManager::get()->RegisterRGBController(rgb_controller); } } /* DetectMSI3ZoneControllers() */ diff --git a/Controllers/MSI3ZoneController/RGBController_MSI3Zone.cpp b/Controllers/MSI3ZoneController/RGBController_MSI3Zone.cpp index 8d6d22ec..62328206 100644 --- a/Controllers/MSI3ZoneController/RGBController_MSI3Zone.cpp +++ b/Controllers/MSI3ZoneController/RGBController_MSI3Zone.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_MSI3Zone.cpp | -| | -| Generic RGB Interface for MSI/Steelseries| -| 3-Zone Keyboard | -| | -| Adam Honse (CalcProgrammer1) 12/25/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_MSI3Zone.cpp | +| | +| RGBController for MSI/SteelSeries 3-Zone keyboard | +| | +| Adam Honse (CalcProgrammer1) 25 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_MSI3Zone.h" @@ -26,7 +28,7 @@ RGBController_MSI3Zone::RGBController_MSI3Zone(MSI3ZoneController* controller_pt name = "MSI 3-Zone Keyboard"; vendor = "MSI"; - type = DEVICE_TYPE_KEYBOARD; + type = DEVICE_TYPE_LAPTOP; description = "MSI 3-Zone Keyboard Device"; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); diff --git a/Controllers/MSI3ZoneController/RGBController_MSI3Zone.h b/Controllers/MSI3ZoneController/RGBController_MSI3Zone.h index 9d61e659..c1f8dd3b 100644 --- a/Controllers/MSI3ZoneController/RGBController_MSI3Zone.h +++ b/Controllers/MSI3ZoneController/RGBController_MSI3Zone.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_MSI3Zone.h | -| | -| Generic RGB Interface for MSI/Steelseries| -| 3-Zone Keyboard | -| | -| Adam Honse (CalcProgrammer1) 12/25/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_MSI3Zone.h | +| | +| RGBController for MSI/SteelSeries 3-Zone keyboard | +| | +| Adam Honse (CalcProgrammer1) 25 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "MSI3ZoneController.h" diff --git a/Controllers/MSIGPUController/MSIGPUController.cpp b/Controllers/MSIGPUController/MSIGPUController.cpp deleted file mode 100644 index 13ab609d..00000000 --- a/Controllers/MSIGPUController/MSIGPUController.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/*-----------------------------------------*\ -| MSIGPUController.cpp | -| | -| Driver for MSI GPUs | -| | -\*-----------------------------------------*/ - -#include "MSIGPUController.h" -#include - -MSIGPUController::MSIGPUController(i2c_smbus_interface* bus, msi_gpu_dev_id dev) -{ - this->bus = bus; - this->dev = dev; -} - -MSIGPUController::~MSIGPUController() -{ - -} - -std::string MSIGPUController::GetDeviceLocation() -{ - std::string return_string(bus->device_name); - char addr[5]; - snprintf(addr, 5, "0x%02X", dev); - return_string.append(", address "); - return_string.append(addr); - return("I2C: " + return_string); -} - -void MSIGPUController::SetRGB1(unsigned char red, unsigned char green, unsigned char blue) -{ - MSIGPURegisterWrite(MSI_GPU_REG_R1, red); - MSIGPURegisterWrite(MSI_GPU_REG_G1, green); - MSIGPURegisterWrite(MSI_GPU_REG_B1, blue); -} - -void MSIGPUController::SetRGB2(unsigned char red, unsigned char green, unsigned char blue) -{ - MSIGPURegisterWrite(MSI_GPU_REG_R2, red); - MSIGPURegisterWrite(MSI_GPU_REG_G2, green); - MSIGPURegisterWrite(MSI_GPU_REG_B2, blue); -} - -void MSIGPUController::SetRGB3(unsigned char red, unsigned char green, unsigned char blue) -{ - MSIGPURegisterWrite(MSI_GPU_REG_R3, red); - MSIGPURegisterWrite(MSI_GPU_REG_G3, green); - MSIGPURegisterWrite(MSI_GPU_REG_B3, blue); -} - -void MSIGPUController::SetMode(unsigned char mode) -{ - MSIGPURegisterWrite(MSI_GPU_REG_MODE, mode); -} - -void MSIGPUController::Save() -{ - MSIGPURegisterWrite(MSI_GPU_REG_SAVE, 0x01); -} - -unsigned char MSIGPUController::MSIGPURegisterRead(unsigned char reg) -{ - return(bus->i2c_smbus_read_byte_data(dev, reg)); -} - -void MSIGPUController::MSIGPURegisterWrite(unsigned char reg, unsigned char val) -{ - bus->i2c_smbus_write_byte_data(dev, reg, val); -} diff --git a/Controllers/MSIGPUController/MSIGPUController/MSIGPUController.cpp b/Controllers/MSIGPUController/MSIGPUController/MSIGPUController.cpp new file mode 100644 index 00000000..35b034a3 --- /dev/null +++ b/Controllers/MSIGPUController/MSIGPUController/MSIGPUController.cpp @@ -0,0 +1,79 @@ +/*---------------------------------------------------------*\ +| MSIGPUController.cpp | +| | +| Driver for MSI GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "MSIGPUController.h" +#include + +MSIGPUController::MSIGPUController(i2c_smbus_interface* bus, msi_gpu_dev_id dev, std::string dev_name) +{ + this->bus = bus; + this->dev = dev; + this->name = dev_name; +} + +MSIGPUController::~MSIGPUController() +{ + +} + +std::string MSIGPUController::GetDeviceLocation() +{ + std::string return_string(bus->device_name); + char addr[5]; + snprintf(addr, 5, "0x%02X", dev); + return_string.append(", address "); + return_string.append(addr); + return("I2C: " + return_string); +} + +std::string MSIGPUController::GetDeviceName() +{ + return(name); +} + +void MSIGPUController::SetRGB1(unsigned char red, unsigned char green, unsigned char blue) +{ + MSIGPURegisterWrite(MSI_GPU_REG_R1, red); + MSIGPURegisterWrite(MSI_GPU_REG_G1, green); + MSIGPURegisterWrite(MSI_GPU_REG_B1, blue); +} + +void MSIGPUController::SetRGB2(unsigned char red, unsigned char green, unsigned char blue) +{ + MSIGPURegisterWrite(MSI_GPU_REG_R2, red); + MSIGPURegisterWrite(MSI_GPU_REG_G2, green); + MSIGPURegisterWrite(MSI_GPU_REG_B2, blue); +} + +void MSIGPUController::SetRGB3(unsigned char red, unsigned char green, unsigned char blue) +{ + MSIGPURegisterWrite(MSI_GPU_REG_R3, red); + MSIGPURegisterWrite(MSI_GPU_REG_G3, green); + MSIGPURegisterWrite(MSI_GPU_REG_B3, blue); +} + +void MSIGPUController::SetMode(unsigned char mode) +{ + MSIGPURegisterWrite(MSI_GPU_REG_MODE, mode); +} + +void MSIGPUController::Save() +{ + MSIGPURegisterWrite(MSI_GPU_REG_SAVE, 0x01); +} + +unsigned char MSIGPUController::MSIGPURegisterRead(unsigned char reg) +{ + return(bus->i2c_smbus_read_byte_data(dev, reg)); +} + +void MSIGPUController::MSIGPURegisterWrite(unsigned char reg, unsigned char val) +{ + bus->i2c_smbus_write_byte_data(dev, reg, val); +} diff --git a/Controllers/MSIGPUController/MSIGPUController.h b/Controllers/MSIGPUController/MSIGPUController/MSIGPUController.h similarity index 88% rename from Controllers/MSIGPUController/MSIGPUController.h rename to Controllers/MSIGPUController/MSIGPUController/MSIGPUController.h index d3be2e12..c4e5e01c 100644 --- a/Controllers/MSIGPUController/MSIGPUController.h +++ b/Controllers/MSIGPUController/MSIGPUController/MSIGPUController.h @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| MSIGPUController.h | -| | -| Definitions for MSI GPUs | -| | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| MSIGPUController.h | +| | +| Driver for MSI GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" -#pragma once - typedef unsigned char msi_gpu_dev_id; #define MSI_GPU_SPEED_MIN 0 @@ -64,10 +66,11 @@ enum class MSIGPUController { public: - MSIGPUController(i2c_smbus_interface* bus, msi_gpu_dev_id dev); + MSIGPUController(i2c_smbus_interface* bus, msi_gpu_dev_id dev, std::string dev_name); ~MSIGPUController(); std::string GetDeviceLocation(); + std::string GetDeviceName(); void SetRGB1(unsigned char red, unsigned char green, unsigned char blue); void SetRGB2(unsigned char red, unsigned char green, unsigned char blue); @@ -82,4 +85,5 @@ public: private: i2c_smbus_interface * bus; msi_gpu_dev_id dev; + std::string name; }; diff --git a/Controllers/MSIGPUController/MSIGPUController/MSIGPUControllerDetect.cpp b/Controllers/MSIGPUController/MSIGPUController/MSIGPUControllerDetect.cpp new file mode 100644 index 00000000..5ac9a8a1 --- /dev/null +++ b/Controllers/MSIGPUController/MSIGPUController/MSIGPUControllerDetect.cpp @@ -0,0 +1,127 @@ +/*---------------------------------------------------------*\ +| MSIGPUControllerDetect.cpp | +| | +| Detector for MSI GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "MSIGPUController.h" +#include "RGBController_MSIGPU.h" +#include "i2c_smbus.h" +#include "pci_ids.h" + +/******************************************************************************************\ +* * +* DetectMSIGPUControllers * +* * +* Detect MSI GPU controllers on the enumerated I2C busses. * +* * +\******************************************************************************************/ + +void DetectMSIGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name) +{ + if(bus->pci_vendor == NVIDIA_VEN && bus->port_id != 1) + { + return; + } + + MSIGPUController* controller = new MSIGPUController(bus, i2c_addr, name); + RGBController_MSIGPU* rgb_controller = new RGBController_MSIGPU(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + +} /* DetectMSIGPUControllers() */ + +/*-----------------------------------------*\ +| Nvidia GPUs | +\*-----------------------------------------*/ + +REGISTER_I2C_PCI_DETECTOR("MSI GeForce GTX 1070 Gaming X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, MSI_SUB_VEN, MSI_GTX1070_GAMING_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce GTX 1660 Gaming X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660_DEV, MSI_SUB_VEN, MSI_GTX1660_GAMING_X_6G_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce GTX 1660 Ti Gaming", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660TI_DEV, MSI_SUB_VEN, MSI_GTX1660TI_GAMING_6G_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce GTX 1660 Ti Gaming X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660TI_DEV, MSI_SUB_VEN, MSI_GTX1660TI_GAMING_X_6G_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce GTX 1660 SUPER Gaming", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660S_DEV, MSI_SUB_VEN, MSI_GTX1660S_GAMING_6G_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce GTX 1660 SUPER Gaming X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660S_DEV, MSI_SUB_VEN, MSI_GTX1660S_GAMING_X_6G_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2060 Gaming Z", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU104_DEV, MSI_SUB_VEN, MSI_RTX2060_GAMING_Z_6G_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2060 Gaming Z", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, MSI_SUB_VEN, MSI_RTX2060_GAMING_Z_6G_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2060 Gaming Z", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, MSI_SUB_VEN, MSI_RTX2060_GAMING_Z_6G_SUB_DEV_2, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2060 SUPER Gaming X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, MSI_SUB_VEN, MSI_RTX2060S_GAMING_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2060 SUPER ARMOR OC", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, MSI_SUB_VEN, MSI_RTX2060S_ARMOR_OC_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 Gaming Z", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, MSI_SUB_VEN, MSI_RTX2070_GAMING_Z_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 Gaming", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_DEV, MSI_SUB_VEN, MSI_RTX2070_GAMING_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 ARMOR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_DEV, MSI_SUB_VEN, MSI_RTX2070_ARMOR_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 ARMOR OC", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, MSI_SUB_VEN, MSI_RTX2070_ARMOR_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 SUPER ARMOR OC", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, MSI_SUB_VEN, MSI_RTX2070S_ARMOR_OC_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 SUPER Gaming", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, MSI_SUB_VEN, MSI_RTX2070S_GAMING_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 SUPER Gaming Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, MSI_SUB_VEN, MSI_RTX2070S_GAMING_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 SUPER Gaming X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, MSI_SUB_VEN, MSI_RTX2070S_GAMING_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 SUPER Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, MSI_SUB_VEN, MSI_RTX2070S_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 SUPER Gaming Z Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, MSI_SUB_VEN, MSI_RTX2070S_GAMING_Z_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080 Gaming Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_DEV, MSI_SUB_VEN, MSI_RTX2080_GAMING_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080 Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, MSI_SUB_VEN, MSI_RTX2080_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080 Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, MSI_SUB_VEN, MSI_RTX2080_GAMING_X_TRIO_SUB_DEV_2, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080 Sea Hawk EK X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, MSI_SUB_VEN, MSI_RTX2080_SEA_HAWK_EK_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080 Duke OC", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, MSI_SUB_VEN, MSI_RTX2080_DUKE_OC_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080 SUPER Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, MSI_SUB_VEN, MSI_RTX2080S_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080 Ti Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, MSI_SUB_VEN, MSI_RTX2080TI_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080 Ti Gaming Z Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, MSI_SUB_VEN, MSI_RTX2080TI_GAMING_Z_TRIO_SUB_DEV, 0X68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080 Ti Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, MSI_SUB_VEN, MSI_RTX2080TI_11G_GAMING_X_TRIO_SUB_DEV,0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080 Ti Sea Hawk EK X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, MSI_SUB_VEN, MSI_RTX2080TI_SEA_HAWK_EK_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3050 Gaming X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3050_DEV, MSI_SUB_VEN, MSI_RTX3060_GAMING_X_8G_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Gaming X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, MSI_SUB_VEN, MSI_RTX3060_GAMING_X_12G_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Gaming X LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, MSI_SUB_VEN, MSI_RTX3060_GAMING_X_12G_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Gaming X (GA104)", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, MSI_SUB_VEN, MSI_RTX3060_GAMING_X_12G_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Gaming X Trio LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, MSI_SUB_VEN, MSI_RTX3070_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, MSI_SUB_VEN, MSI_RTX3070_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Gaming Z Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, MSI_SUB_VEN, MSI_RTX3070_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Ti Gaming X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, MSI_SUB_VEN, MSI_RTX3060TI_GAMING_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Ti Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, MSI_SUB_VEN, MSI_RTX3070_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Ti Gaming X LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, MSI_SUB_VEN, MSI_RTX3060TI_GAMING_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Ti Gaming X Trio LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, MSI_SUB_VEN, MSI_RTX3070_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Ti SUPER 3X OC", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_GDDR6X_DEV,MSI_SUB_VEN, MSI_RTX3060TI_SUPER_3X_OC_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Ti Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_GDDR6X_DEV,MSI_SUB_VEN, MSI_RTX3060TI_GAMING_X_TRIO_8G_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3070 Gaming Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, MSI_SUB_VEN, MSI_RTX3070_GAMING_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3070 Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, MSI_SUB_VEN, MSI_RTX3070_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3070 Suprim", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, MSI_SUB_VEN, MSI_RTX3070_SUPRIM_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3070 Suprim LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, MSI_SUB_VEN, MSI_RTX3070_SUPRIM_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3070 Suprim X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, MSI_SUB_VEN, MSI_RTX3070_SUPRIM_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3070 Suprim X LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, MSI_SUB_VEN, MSI_RTX3070_SUPRIM_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3070 Suprim X GODZILLA LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, MSI_SUB_VEN, MSI_RTX3070_SUPRIM_X_GODZILLA_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3070 Ti Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, MSI_SUB_VEN, MSI_RTX3070TI_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3070 Ti Suprim X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, MSI_SUB_VEN, MSI_RTX3070TI_SUPRIM_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 Gaming Z Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, MSI_SUB_VEN, MSI_RTX3080_GAMING_Z_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 Gaming Z Trio LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, MSI_SUB_VEN, MSI_RTX3080_GAMING_Z_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, MSI_SUB_VEN, MSI_RTX3080_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 Suprim X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, MSI_SUB_VEN, MSI_RTX3080_SUPRIM_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 Suprim X LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, MSI_SUB_VEN, MSI_RTX3080_SUPRIM_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 12GB Suprim X LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, MSI_SUB_VEN, MSI_RTX3080_SUPRIM_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 12GB Gaming Z Trio LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, MSI_SUB_VEN, MSI_RTX3080_12G_GAMING_Z_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 Ti Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, MSI_SUB_VEN, MSI_RTX3080TI_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 Ti Suprim X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, MSI_SUB_VEN, MSI_RTX3080TI_SUPRIM_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3090 Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, MSI_SUB_VEN, MSI_RTX3090_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3090 Suprim", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, MSI_SUB_VEN, MSI_RTX3090_SUPRIM_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3090 Suprim X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, MSI_SUB_VEN, MSI_RTX3090_SUPRIM_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3090 Ti Suprim X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, MSI_SUB_VEN, MSI_RTX3090TI_SUPRIM_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3090 Ti Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, MSI_SUB_VEN, MSI_RTX3090TI_GAMING_X_TRIO_SUB_DEV, 0x68); + +/*-----------------------------------------*\ +| AMD GPUs | +\*-----------------------------------------*/ + +REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6600 XT Gaming X", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI23_DEV, MSI_SUB_VEN, MSI_RX6600XT_GAMING_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6650 XT Gaming X", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI23_DEV1, MSI_SUB_VEN, MSI_RX6650XT_GAMING_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6700 XT Gaming X", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, MSI_SUB_VEN, MSI_RX6700XT_GAMING_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6750 XT Gaming X Trio", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, MSI_SUB_VEN, MSI_RX6750XT_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6800 Gaming Z Trio v1", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, MSI_SUB_VEN, MSI_RX6800_GAMING_Z_TRIO_V1_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6800 Gaming X Trio", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, MSI_SUB_VEN, MSI_RX6800_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6800 XT Gaming X Trio", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, MSI_SUB_VEN, MSI_RX6800XT_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6800 XT Gaming Z Trio", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, MSI_SUB_VEN, MSI_RX6800XT_GAMING_Z_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6900 XT Gaming X Trio", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, MSI_SUB_VEN, MSI_RX6900XT_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6900 XT Gaming Z Trio", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV2, MSI_SUB_VEN, MSI_RX6950XT_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6950 XT Gaming X Trio", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, MSI_SUB_VEN, MSI_RX6950XT_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6950 XT Gaming X Trio", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV3, MSI_SUB_VEN, MSI_RX6950XT_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 7900 XTX Gaming X Trio", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, MSI_SUB_VEN, MSI_RX7900XTX_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 7900 XT Gaming Trio Classic", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI31_DEV, MSI_SUB_VEN, MSI_RX7900XT_GAMING_TRIO_CLASSIC_SUB_DEV,0x68); diff --git a/Controllers/MSIGPUController/RGBController_MSIGPU.cpp b/Controllers/MSIGPUController/MSIGPUController/RGBController_MSIGPU.cpp similarity index 86% rename from Controllers/MSIGPUController/RGBController_MSIGPU.cpp rename to Controllers/MSIGPUController/MSIGPUController/RGBController_MSIGPU.cpp index ae64e596..3f431fec 100644 --- a/Controllers/MSIGPUController/RGBController_MSIGPU.cpp +++ b/Controllers/MSIGPUController/MSIGPUController/RGBController_MSIGPU.cpp @@ -1,24 +1,26 @@ -/*-----------------------------------------*\ -| RGBController_MSIGPU.h | -| | -| Generic RGB Interface for MSI GPU | -| | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_MSIGPU.cpp | +| | +| RGBController for MSI GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_MSIGPU.h" #include +#include "RGBController_MSIGPU.h" static const std::array speed_values = { 0x04, 0x02, 0x01 }; int RGBController_MSIGPU::GetDeviceMode() { - unsigned char dev_mode = msi_gpu->MSIGPURegisterRead(MSI_GPU_REG_MODE); + unsigned char dev_mode = controller->MSIGPURegisterRead(MSI_GPU_REG_MODE); for(std::size_t mode = 0; mode < modes.size(); mode++) { - if (modes[mode].value == dev_mode) + if(modes[mode].value == dev_mode) { - active_mode = mode; + active_mode = (int)mode; break; } } @@ -28,17 +30,17 @@ int RGBController_MSIGPU::GetDeviceMode() int RGBController_MSIGPU::GetModeSpeed() { - unsigned char mode_speed = msi_gpu->MSIGPURegisterRead(MSI_GPU_REG_SPEED); + unsigned char mode_speed = controller->MSIGPURegisterRead(MSI_GPU_REG_SPEED); for(std::size_t speed = 0; speed < speed_values.size(); speed++) { if(speed_values[speed] == mode_speed) { - return speed; + return((int)speed); } } - return 0; + return(0); } /**------------------------------------------------------------------*\ @@ -52,15 +54,15 @@ int RGBController_MSIGPU::GetModeSpeed() @comment \*-------------------------------------------------------------------*/ -RGBController_MSIGPU::RGBController_MSIGPU(MSIGPUController * msi_gpu_ptr) +RGBController_MSIGPU::RGBController_MSIGPU(MSIGPUController * controller_ptr) { - msi_gpu = msi_gpu_ptr; + controller = controller_ptr; - name = "MSI GPU Device"; - vendor = "MSI"; - type = DEVICE_TYPE_GPU; - description = name; - location = msi_gpu->GetDeviceLocation(); + name = controller->GetDeviceName(); + vendor = "MSI"; + type = DEVICE_TYPE_GPU; + description = name; + location = controller->GetDeviceLocation(); mode Direct; Direct.name = "Direct"; @@ -317,12 +319,12 @@ RGBController_MSIGPU::RGBController_MSIGPU(MSIGPUController * msi_gpu_ptr) active_mode = GetDeviceMode(); modes[active_mode].speed = GetModeSpeed(); - modes[active_mode].brightness = msi_gpu->MSIGPURegisterRead(MSI_GPU_REG_BRIGHTNESS) / MSI_GPU_BRIGHTNESS_MULTI; + modes[active_mode].brightness = controller->MSIGPURegisterRead(MSI_GPU_REG_BRIGHTNESS) / MSI_GPU_BRIGHTNESS_MULTI; } RGBController_MSIGPU::~RGBController_MSIGPU() { - delete msi_gpu; + delete controller; } void RGBController_MSIGPU::SetupZones() @@ -357,15 +359,15 @@ void RGBController_MSIGPU::SetupZones() /*---------------------------------------------------------*\ | Initialize color | \*---------------------------------------------------------*/ - unsigned char r1 = msi_gpu->MSIGPURegisterRead(MSI_GPU_REG_R1); - unsigned char g1 = msi_gpu->MSIGPURegisterRead(MSI_GPU_REG_G1); - unsigned char b1 = msi_gpu->MSIGPURegisterRead(MSI_GPU_REG_B1); - unsigned char r2 = msi_gpu->MSIGPURegisterRead(MSI_GPU_REG_R2); - unsigned char g2 = msi_gpu->MSIGPURegisterRead(MSI_GPU_REG_G2); - unsigned char b2 = msi_gpu->MSIGPURegisterRead(MSI_GPU_REG_B2); - unsigned char r3 = msi_gpu->MSIGPURegisterRead(MSI_GPU_REG_R3); - unsigned char g3 = msi_gpu->MSIGPURegisterRead(MSI_GPU_REG_G3); - unsigned char b3 = msi_gpu->MSIGPURegisterRead(MSI_GPU_REG_B3); + unsigned char r1 = controller->MSIGPURegisterRead(MSI_GPU_REG_R1); + unsigned char g1 = controller->MSIGPURegisterRead(MSI_GPU_REG_G1); + unsigned char b1 = controller->MSIGPURegisterRead(MSI_GPU_REG_B1); + unsigned char r2 = controller->MSIGPURegisterRead(MSI_GPU_REG_R2); + unsigned char g2 = controller->MSIGPURegisterRead(MSI_GPU_REG_G2); + unsigned char b2 = controller->MSIGPURegisterRead(MSI_GPU_REG_B2); + unsigned char r3 = controller->MSIGPURegisterRead(MSI_GPU_REG_R3); + unsigned char g3 = controller->MSIGPURegisterRead(MSI_GPU_REG_G3); + unsigned char b3 = controller->MSIGPURegisterRead(MSI_GPU_REG_B3); colors[0] = ToRGBColor(r1, g1, b1); colors[1] = ToRGBColor(r2, g2, b2); @@ -392,16 +394,16 @@ void RGBController_MSIGPU::DeviceUpdateLEDs() { if(TimeToSend()) { - msi_gpu->MSIGPURegisterWrite(MSI_GPU_REG_UNKNOWN, 0x00); + controller->MSIGPURegisterWrite(MSI_GPU_REG_UNKNOWN, 0x00); if(modes[active_mode].value == MSI_GPU_MODE_FADEIN) { - msi_gpu->SetRGB2(RGBGetRValue(colors[1]), RGBGetGValue(colors[1]), RGBGetBValue(colors[1])); - msi_gpu->SetRGB3(RGBGetRValue(colors[2]), RGBGetGValue(colors[2]), RGBGetBValue(colors[2])); + controller->SetRGB2(RGBGetRValue(colors[1]), RGBGetGValue(colors[1]), RGBGetBValue(colors[1])); + controller->SetRGB3(RGBGetRValue(colors[2]), RGBGetGValue(colors[2]), RGBGetBValue(colors[2])); } else { - msi_gpu->SetRGB1(RGBGetRValue(colors[0]), RGBGetGValue(colors[0]), RGBGetBValue(colors[0])); + controller->SetRGB1(RGBGetRValue(colors[0]), RGBGetGValue(colors[0]), RGBGetBValue(colors[0])); } /*-----------------------------------------------------*\ @@ -424,17 +426,17 @@ void RGBController_MSIGPU::UpdateSingleLED(int /*led*/) void RGBController_MSIGPU::DeviceUpdateMode() { if(TimeToSend()) - { + { if(modes[active_mode].flags & MODE_FLAG_HAS_BRIGHTNESS) { - msi_gpu->MSIGPURegisterWrite(MSI_GPU_REG_BRIGHTNESS, modes[active_mode].brightness * MSI_GPU_BRIGHTNESS_MULTI); + controller->MSIGPURegisterWrite(MSI_GPU_REG_BRIGHTNESS, modes[active_mode].brightness * MSI_GPU_BRIGHTNESS_MULTI); if(modes[active_mode].flags & MODE_FLAG_HAS_SPEED) { - msi_gpu->MSIGPURegisterWrite(MSI_GPU_REG_SPEED, speed_values[modes[active_mode].speed]); + controller->MSIGPURegisterWrite(MSI_GPU_REG_SPEED, speed_values[modes[active_mode].speed]); } - msi_gpu->SetMode(modes[active_mode].value); + controller->SetMode(modes[active_mode].value); /*-----------------------------------------------------*\ | Update last commit time | @@ -446,5 +448,5 @@ void RGBController_MSIGPU::DeviceUpdateMode() void RGBController_MSIGPU::DeviceSaveMode() { - msi_gpu->Save(); + controller->Save(); } diff --git a/Controllers/MSIGPUController/MSIGPUController/RGBController_MSIGPU.h b/Controllers/MSIGPUController/MSIGPUController/RGBController_MSIGPU.h new file mode 100644 index 00000000..e4e59619 --- /dev/null +++ b/Controllers/MSIGPUController/MSIGPUController/RGBController_MSIGPU.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------*\ +| RGBController_MSIGPU.h | +| | +| RGBController for MSI GPU | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "MSIGPUController.h" + +class RGBController_MSIGPU : public RGBController +{ +public: + RGBController_MSIGPU(MSIGPUController* controller_ptr); + ~RGBController_MSIGPU(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + MSIGPUController* controller; + std::chrono::time_point last_commit_time; + + bool TimeToSend(); + int GetDeviceMode(); + int GetModeSpeed(); +}; diff --git a/Controllers/MSIGPUController/MSIGPUControllerDetect.cpp b/Controllers/MSIGPUController/MSIGPUControllerDetect.cpp deleted file mode 100644 index fcb93628..00000000 --- a/Controllers/MSIGPUController/MSIGPUControllerDetect.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/*-----------------------------------------*\ -| MSIGPUControllerDetect.cpp | -| | -| Driver for MSI GPUs | -| | -\*-----------------------------------------*/ - -#include "Detector.h" -#include "MSIGPUController.h" -#include "LogManager.h" -#include "RGBController.h" -#include "RGBController_MSIGPU.h" -#include "i2c_smbus.h" -#include "pci_ids.h" -#include -#include -#include - -/******************************************************************************************\ -* * -* DetectMSIGPUControllers * -* * -* Detect MSI GPU controllers on the enumerated I2C busses. * -* * -\******************************************************************************************/ - -void DetectMSIGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name) -{ - if(bus->pci_vendor == NVIDIA_VEN && bus->port_id != 1) - { - return; - } - - MSIGPUController* controller = new MSIGPUController(bus, i2c_addr); - RGBController_MSIGPU* rgb_controller = new RGBController_MSIGPU(controller); - rgb_controller->name = name; - - ResourceManager::get()->RegisterRGBController(rgb_controller); - -} /* DetectMSIGPUControllers() */ - -/*-----------------------------------------*\ -| NVidia GPUs | -\*-----------------------------------------*/ - -REGISTER_I2C_PCI_DETECTOR("MSI GeForce GTX 1070 Gaming X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, MSI_SUB_VEN, MSI_GTX1070_GAMING_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce GTX 1660 Gaming X 6G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660_DEV, MSI_SUB_VEN, MSI_GTX1660_GAMING_X_6G_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce GTX 1660Ti Gaming 6G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660TI_DEV, MSI_SUB_VEN, MSI_GTX1660TI_GAMING_6G_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce GTX 1660Ti Gaming X 6G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660TI_DEV, MSI_SUB_VEN, MSI_GTX1660TI_GAMING_X_6G_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce GTX 1660 Super Gaming 6G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660S_DEV, MSI_SUB_VEN, MSI_GTX1660S_GAMING_6G_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce GTX 1660 Super Gaming X 6G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_GTX1660S_DEV, MSI_SUB_VEN, MSI_GTX1660S_GAMING_X_6G_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2060 Gaming Z 6G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU104_DEV, MSI_SUB_VEN, MSI_RTX2060_GAMING_Z_6G_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2060 Gaming Z 6G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, MSI_SUB_VEN, MSI_RTX2060_GAMING_Z_6G_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2060 Gaming Z 6G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, MSI_SUB_VEN, MSI_RTX2060_GAMING_Z_6G_SUB_DEV_2, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2060 Super Gaming X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, MSI_SUB_VEN, MSI_RTX2060S_GAMING_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2060 Super ARMOR OC", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, MSI_SUB_VEN, MSI_RTX2060S_ARMOR_OC_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 Gaming Z", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, MSI_SUB_VEN, MSI_RTX2070_GAMING_Z_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 Gaming", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_DEV, MSI_SUB_VEN, MSI_RTX2070_GAMING_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 ARMOR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_DEV, MSI_SUB_VEN, MSI_RTX2070_ARMOR_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 ARMOR OC", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, MSI_SUB_VEN, MSI_RTX2070_ARMOR_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 SUPER ARMOR OC", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, MSI_SUB_VEN, MSI_RTX2070S_ARMOR_OC_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 Super Gaming", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, MSI_SUB_VEN, MSI_RTX2070S_GAMING_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 Super Gaming Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, MSI_SUB_VEN, MSI_RTX2070S_GAMING_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 Super Gaming X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, MSI_SUB_VEN, MSI_RTX2070S_GAMING_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 Super Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, MSI_SUB_VEN, MSI_RTX2070S_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2070 Super Gaming Z Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, MSI_SUB_VEN, MSI_RTX2070S_GAMING_Z_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080 Gaming Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_DEV, MSI_SUB_VEN, MSI_RTX2080_GAMING_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080 Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, MSI_SUB_VEN, MSI_RTX2080_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080 Sea Hawk EK X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, MSI_SUB_VEN, MSI_RTX2080_SEA_HAWK_EK_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080 Duke 8G OC", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, MSI_SUB_VEN, MSI_RTX2080_DUKE_OC_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080 Super Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, MSI_SUB_VEN, MSI_RTX2080S_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080Ti Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, MSI_SUB_VEN, MSI_RTX2080TI_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080Ti Gaming Z Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, MSI_SUB_VEN, MSI_RTX2080TI_GAMING_Z_TRIO_SUB_DEV, 0X68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080Ti 11G Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, MSI_SUB_VEN, MSI_RTX2080TI_11G_GAMING_X_TRIO_SUB_DEV,0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 2080Ti Sea Hawk EK X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, MSI_SUB_VEN, MSI_RTX2080TI_SEA_HAWK_EK_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3050 Gaming X 8G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3050_DEV, MSI_SUB_VEN, MSI_RTX3060_GAMING_X_8G_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Gaming X 12G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, MSI_SUB_VEN, MSI_RTX3060_GAMING_X_12G_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Gaming X 12G LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, MSI_SUB_VEN, MSI_RTX3060_GAMING_X_12G_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Gaming X 12G (GA104)", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, MSI_SUB_VEN, MSI_RTX3060_GAMING_X_12G_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 12G Gaming X Trio LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, MSI_SUB_VEN, MSI_RTX3070_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 12G Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, MSI_SUB_VEN, MSI_RTX3070_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 12G Gaming Z Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, MSI_SUB_VEN, MSI_RTX3070_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Ti 8GB Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, MSI_SUB_VEN, MSI_RTX3070_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Ti 8GB Gaming X LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, MSI_SUB_VEN, MSI_RTX3060TI_GAMING_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3060 Ti 8GB Gaming X Trio LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, MSI_SUB_VEN, MSI_RTX3070_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3070 8GB Gaming Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, MSI_SUB_VEN, MSI_RTX3070_GAMING_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3070 8GB Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, MSI_SUB_VEN, MSI_RTX3070_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3070 8GB Suprim", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, MSI_SUB_VEN, MSI_RTX3070_SUPRIM_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3070 8GB Suprim X", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, MSI_SUB_VEN, MSI_RTX3070_SUPRIM_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3070 8GB Suprim X LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, MSI_SUB_VEN, MSI_RTX3070_SUPRIM_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3070 Ti 8GB Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, MSI_SUB_VEN, MSI_RTX3070TI_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3070 Ti Suprim X 8G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, MSI_SUB_VEN, MSI_RTX3070TI_SUPRIM_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 10GB Gaming Z Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, MSI_SUB_VEN, MSI_RTX3080_GAMING_Z_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 10GB Gaming Z Trio LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, MSI_SUB_VEN, MSI_RTX3080_GAMING_Z_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 10GB Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, MSI_SUB_VEN, MSI_RTX3080_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 Suprim X 10G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, MSI_SUB_VEN, MSI_RTX3080_SUPRIM_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 Suprim X 10G LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, MSI_SUB_VEN, MSI_RTX3080_SUPRIM_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 Suprim X 12G LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, MSI_SUB_VEN, MSI_RTX3080_SUPRIM_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 12GB Gaming Z Trio LHR", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, MSI_SUB_VEN, MSI_RTX3080_12G_GAMING_Z_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 Ti Gaming X Trio 12G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, MSI_SUB_VEN, MSI_RTX3080TI_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3080 Ti Suprim X 12G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, MSI_SUB_VEN, MSI_RTX3080TI_SUPRIM_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3090 24GB Gaming X Trio", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, MSI_SUB_VEN, MSI_RTX3090_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3090 Suprim 24G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, MSI_SUB_VEN, MSI_RTX3090_SUPRIM_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3090 Suprim X 24G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, MSI_SUB_VEN, MSI_RTX3090_SUPRIM_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3090 Ti Suprim X 24G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, MSI_SUB_VEN, MSI_RTX3090TI_SUPRIM_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 3090 Ti Gaming X Trio 24G", DetectMSIGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, MSI_SUB_VEN, MSI_RTX3090TI_GAMING_X_TRIO_SUB_DEV, 0x68); - -/*-----------------------------------------*\ -| AMD GPUs | -\*-----------------------------------------*/ - -REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6600 XT Gaming X", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI23_DEV, MSI_SUB_VEN, MSI_RX6600XT_GAMING_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6700 XT Gaming X", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, MSI_SUB_VEN, MSI_RX6700XT_GAMING_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6750 XT Gaming X Trio 12G", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, MSI_SUB_VEN, MSI_RX6750XT_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6800 Gaming Z Trio v1", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, MSI_SUB_VEN, MSI_RX6800_GAMING_Z_TRIO_V1_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6800 Gaming X Trio", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, MSI_SUB_VEN, MSI_RX6800_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6800 XT Gaming X Trio", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, MSI_SUB_VEN, MSI_RX6800XT_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6800 XT Gaming Z Trio", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, MSI_SUB_VEN, MSI_RX6800XT_GAMING_Z_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6900 XT Gaming X Trio", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, MSI_SUB_VEN, MSI_RX6900XT_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6900 XT Gaming Z Trio", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV2, MSI_SUB_VEN, MSI_RX6950XT_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6950 XT Gaming X Trio", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, MSI_SUB_VEN, MSI_RX6950XT_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI Radeon RX 6950 XT Gaming X Trio", DetectMSIGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV3, MSI_SUB_VEN, MSI_RX6950XT_GAMING_X_TRIO_SUB_DEV, 0x68); diff --git a/Controllers/MSIGPUController/MSIGPUv2Controller.cpp b/Controllers/MSIGPUController/MSIGPUv2Controller.cpp deleted file mode 100644 index 7c73e697..00000000 --- a/Controllers/MSIGPUController/MSIGPUv2Controller.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/*-----------------------------------------*\ -| MSIGPUController.cpp | -| | -| Driver for MSI GPUs | -| Wojciech Lazarski 03/Jan/2023 | -| | -\*-----------------------------------------*/ - -#include "MSIGPUv2Controller.h" -#include - -using namespace std::chrono_literals; - -MSIGPUv2Controller::MSIGPUv2Controller(i2c_smbus_interface* bus, msi_gpu_dev_id dev) -{ - this->bus = bus; - this->dev = dev; -} - -MSIGPUv2Controller::~MSIGPUv2Controller() -{ - -} - -std::string MSIGPUv2Controller::GetDeviceLocation() -{ - std::string return_string(bus->device_name); - char addr[5]; - snprintf(addr, 5, "0x%02X", dev); - return_string.append(", address "); - return_string.append(addr); - return("I2C: " + return_string); -} - -void MSIGPUv2Controller::SetRGB1(unsigned char red, unsigned char green, unsigned char blue) -{ - MSIGPURegisterWrite(MSI_GPU_V2_REG_R1, red); - MSIGPURegisterWrite(MSI_GPU_V2_REG_G1, green); - MSIGPURegisterWrite(MSI_GPU_V2_REG_B1, blue); -} - -void MSIGPUv2Controller::SetRGB1V2(unsigned char red, unsigned char green, unsigned char blue) -{ - unsigned char buffer[3]; - buffer[2]=red; - buffer[1]=green; - buffer[0]=blue; - MSIGPUBlockWrite(MSI_GPU_V2_REG_COLOR_BLOCK1_BASE, &buffer[0], sizeof(buffer)); -} - -void MSIGPUv2Controller::SetRGB2V2(unsigned char red, unsigned char green, unsigned char blue) -{ - unsigned char buffer[3]; - buffer[2]=red; - buffer[1]=green; - buffer[0]=blue; - MSIGPUBlockWrite(MSI_GPU_V2_REG_COLOR_BLOCK2_BASE, &buffer[0], sizeof(buffer)); -} - -void MSIGPUv2Controller::SetRGB3V2(unsigned char red, unsigned char green, unsigned char blue) -{ - unsigned char buffer[3]; - buffer[2]=red; - buffer[1]=green; - buffer[0]=blue; - MSIGPUBlockWrite(MSI_GPU_V2_REG_COLOR_BLOCK3_BASE, &buffer[0], sizeof(buffer)); -} - -void MSIGPUv2Controller::SetMode(unsigned char mode) -{ - MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, mode); -} - -void MSIGPUv2Controller::Save() -{ - MSIGPURegisterWrite(MSI_GPU_V2_REG_SAVE, 0x00); -} - -unsigned char MSIGPUv2Controller::MSIGPURegisterRead(unsigned char reg) -{ - return bus->i2c_smbus_read_byte_data(dev, reg); -} - -void MSIGPUv2Controller::MSIGPURegisterWrite(unsigned char reg, unsigned char val) -{ - bus->i2c_smbus_write_byte_data(dev, reg, val); - std::this_thread::sleep_for(20ms); -} - -void MSIGPUv2Controller::MSIGPUBlockWrite(unsigned char reg, unsigned char *val, unsigned char len) -{ - bus->i2c_smbus_interface::i2c_smbus_write_i2c_block_data(dev, reg, len, val); - std::this_thread::sleep_for(20ms); -} diff --git a/Controllers/MSIGPUController/MSIGPUv2Controller/MSIGPUv2Controller.cpp b/Controllers/MSIGPUController/MSIGPUv2Controller/MSIGPUv2Controller.cpp new file mode 100644 index 00000000..a75cb361 --- /dev/null +++ b/Controllers/MSIGPUController/MSIGPUv2Controller/MSIGPUv2Controller.cpp @@ -0,0 +1,104 @@ +/*---------------------------------------------------------*\ +| MSIGPUv2Controller.cpp | +| | +| Driver for MSI V2 GPU (ITE9) | +| | +| Wojciech Lazarski 03 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "MSIGPUv2Controller.h" + +using namespace std::chrono_literals; + +MSIGPUv2Controller::MSIGPUv2Controller(i2c_smbus_interface* bus, msi_gpu_dev_id dev, std::string dev_name) +{ + this->bus = bus; + this->dev = dev; + this->name = dev_name; +} + +MSIGPUv2Controller::~MSIGPUv2Controller() +{ + +} + +std::string MSIGPUv2Controller::GetDeviceLocation() +{ + std::string return_string(bus->device_name); + char addr[5]; + snprintf(addr, 5, "0x%02X", dev); + return_string.append(", address "); + return_string.append(addr); + return("I2C: " + return_string); +} + +std::string MSIGPUv2Controller::GetDeviceName() +{ + return(name); +} + +void MSIGPUv2Controller::SetRGB1(unsigned char red, unsigned char green, unsigned char blue) +{ + MSIGPURegisterWrite(MSI_GPU_V2_REG_R1, red); + MSIGPURegisterWrite(MSI_GPU_V2_REG_G1, green); + MSIGPURegisterWrite(MSI_GPU_V2_REG_B1, blue); +} + +void MSIGPUv2Controller::SetRGB1V2(unsigned char red, unsigned char green, unsigned char blue) +{ + unsigned char buffer[3]; + buffer[2]=red; + buffer[1]=green; + buffer[0]=blue; + MSIGPUBlockWrite(MSI_GPU_V2_REG_COLOR_BLOCK1_BASE, &buffer[0], sizeof(buffer)); +} + +void MSIGPUv2Controller::SetRGB2V2(unsigned char red, unsigned char green, unsigned char blue) +{ + unsigned char buffer[3]; + buffer[2]=red; + buffer[1]=green; + buffer[0]=blue; + MSIGPUBlockWrite(MSI_GPU_V2_REG_COLOR_BLOCK2_BASE, &buffer[0], sizeof(buffer)); +} + +void MSIGPUv2Controller::SetRGB3V2(unsigned char red, unsigned char green, unsigned char blue) +{ + unsigned char buffer[3]; + buffer[2]=red; + buffer[1]=green; + buffer[0]=blue; + MSIGPUBlockWrite(MSI_GPU_V2_REG_COLOR_BLOCK3_BASE, &buffer[0], sizeof(buffer)); +} + +void MSIGPUv2Controller::SetMode(unsigned char mode) +{ + MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, mode); +} + +void MSIGPUv2Controller::Save() +{ + MSIGPURegisterWrite(MSI_GPU_V2_REG_SAVE, 0x00); +} + +unsigned char MSIGPUv2Controller::MSIGPURegisterRead(unsigned char reg) +{ + return bus->i2c_smbus_read_byte_data(dev, reg); +} + +void MSIGPUv2Controller::MSIGPURegisterWrite(unsigned char reg, unsigned char val) +{ + bus->i2c_smbus_write_byte_data(dev, reg, val); + std::this_thread::sleep_for(20ms); +} + +void MSIGPUv2Controller::MSIGPUBlockWrite(unsigned char reg, unsigned char *val, unsigned char len) +{ + bus->i2c_smbus_interface::i2c_smbus_write_i2c_block_data(dev, reg, len, val); + std::this_thread::sleep_for(20ms); +} diff --git a/Controllers/MSIGPUController/MSIGPUv2Controller.h b/Controllers/MSIGPUController/MSIGPUv2Controller/MSIGPUv2Controller.h similarity index 87% rename from Controllers/MSIGPUController/MSIGPUv2Controller.h rename to Controllers/MSIGPUController/MSIGPUv2Controller/MSIGPUv2Controller.h index 26f35239..bc1a7ad1 100644 --- a/Controllers/MSIGPUController/MSIGPUv2Controller.h +++ b/Controllers/MSIGPUController/MSIGPUv2Controller/MSIGPUv2Controller.h @@ -1,16 +1,19 @@ -/*-------------------------------------------------*\ -| MSIGPUControllerv2.h | -| | -| Definitions for MSI GPUs for new ITE9 controller | -| Wojciech Lazarski 03/Jan/2023 | -| | -\*-------------------------------------------------*/ +/*---------------------------------------------------------*\ +| MSIGPUv2Controller.h | +| | +| Driver for MSI V2 GPU (ITE9) | +| | +| Wojciech Lazarski 03 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" -#pragma once - typedef unsigned char msi_gpu_dev_id; #define MSI_GPU_V2_SPEED_MIN 0 @@ -72,10 +75,11 @@ enum class MSIGPUv2Controller { public: - MSIGPUv2Controller(i2c_smbus_interface* bus, msi_gpu_dev_id dev); + MSIGPUv2Controller(i2c_smbus_interface* bus, msi_gpu_dev_id dev, std::string dev_name); ~MSIGPUv2Controller(); std::string GetDeviceLocation(); + std::string GetDeviceName(); void SetRGB1(unsigned char red, unsigned char green, unsigned char blue); void SetRGB1V2(unsigned char red, unsigned char green, unsigned char blue); @@ -92,4 +96,5 @@ public: private: i2c_smbus_interface * bus; msi_gpu_dev_id dev; + std::string name; }; diff --git a/Controllers/MSIGPUController/MSIGPUv2Controller/MSIGPUv2ControllerDetect.cpp b/Controllers/MSIGPUController/MSIGPUv2Controller/MSIGPUv2ControllerDetect.cpp new file mode 100644 index 00000000..e33ca3b7 --- /dev/null +++ b/Controllers/MSIGPUController/MSIGPUv2Controller/MSIGPUv2ControllerDetect.cpp @@ -0,0 +1,73 @@ +/*---------------------------------------------------------*\ +| MSIGPUv2ControllerDetect.cpp | +| | +| Detector for MSI V2 GPU (ITE9) | +| | +| Wojciech Lazarski 03 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "LogManager.h" +#include "i2c_smbus.h" +#include "RGBController_MSIGPUv2.h" +#include "MSIGPUv2Controller.h" + +/*-----------------------------------------------------------------------------------------*\ +| | +| DetectMSI GPU V2 Controllers | +| | +| Detect MSI GPU v2 controllers on the enumerated I2C busses. | +| | +\*-----------------------------------------------------------------------------------------*/ + +void DetectMSIGPUv2Controllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name) +{ + if(bus->pci_vendor == NVIDIA_VEN && bus->port_id != 1) + { + return; + } + + int msi_gpu_id = bus->pci_subsystem_device | bus->pci_device << 16; + MSIGPUv2Controller* controller = new MSIGPUv2Controller(bus, i2c_addr, name); + RGBController_MSIGPUv2* rgb_controller = new RGBController_MSIGPUv2(controller, msi_gpu_id); + + ResourceManager::get()->RegisterRGBController(rgb_controller); +} /* DetectMSIGPUv2Controllers() */ + +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4060 Gaming X", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4060_DEV, MSI_SUB_VEN, MSI_RTX4060_GAMING_X_8G_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4060 Ti Gaming X", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4060TI_DEV, MSI_SUB_VEN, MSI_RTX4060TI_GAMING_X_8G_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4060 Ti 16GB Gaming X", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4060TI_16G_DEV, MSI_SUB_VEN, MSI_RTX4060TI_GAMING_X_16G_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4060 Ti 16GB Gaming X Slim White", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4060TI_16G_DEV, MSI_SUB_VEN, MSI_RTX4060TI_GAMING_X_16G_SLIM_WHITE_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Gaming X Trio", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, MSI_SUB_VEN, MSI_RTX4070_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Gaming X Slim", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, MSI_SUB_VEN, MSI_RTX4070S_GAMING_X_SLIM_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Gaming X Slim White", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, MSI_SUB_VEN, MSI_RTX4070S_GAMING_X_SLIM_WHITE_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 SUPER Gaming X Slim", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, MSI_SUB_VEN, MSI_RTX4070S_GAMING_X_SLIM_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 SUPER Gaming X Slim White", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070S_DEV, MSI_SUB_VEN, MSI_RTX4070S_GAMING_X_SLIM_WHITE_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Ti Gaming X Trio", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, MSI_SUB_VEN, MSI_RTX4070TI_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Ti Gaming X Trio White", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, MSI_SUB_VEN, MSI_RTX4070TI_GAMING_X_TRIO_WHITE_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Ti Gaming X Slim White", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, MSI_SUB_VEN, MSI_RTX4070TI_GAMING_X_SLIM_WHITE_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Ti Suprim X Trio", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, MSI_SUB_VEN, MSI_RTX4070TI_SUPRIM_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Ti SUPER Gaming X Trio White", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, MSI_SUB_VEN, MSI_RTX4070TI_GAMING_X_TRIO_WHITE_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Ti SUPER Gaming Slim", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, MSI_SUB_VEN, MSI_RTX4070TIS_GAMING_SLIM_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Ti SUPER Gaming X Slim", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, MSI_SUB_VEN, MSI_RTX4070TIS_GAMING_X_SLIM_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 Ti SUPER Gaming White X Slim", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, MSI_SUB_VEN, MSI_RTX4070TIS_GAMING_X_SLIM_WHITE_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4080 Gaming X Slim White", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, MSI_SUB_VEN, MSI_RTX4080S_GAMING_X_SLIM_WHITE_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4080 Gaming X Trio", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, MSI_SUB_VEN, MSI_RTX4080_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4080 Gaming X Trio White", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, MSI_SUB_VEN, MSI_RTX4080_GAMING_X_TRIO_WHITE_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4080 Suprim X", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, MSI_SUB_VEN, MSI_RTX4080_SUPRIM_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4080 SUPER Gaming X Slim", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4080S_DEV, MSI_SUB_VEN, MSI_RTX4080S_GAMING_X_SLIM_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4080 SUPER Gaming X Slim White", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4080S_DEV, MSI_SUB_VEN, MSI_RTX4080S_GAMING_X_SLIM_WHITE_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4080 SUPER Suprim X", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4080S_DEV, MSI_SUB_VEN, MSI_RTX4080_SUPRIM_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4080 SUPER Gaming X Trio", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4080S_DEV, MSI_SUB_VEN, MSI_RTX4080S_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4090 Gaming X Trio", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, MSI_SUB_VEN, MSI_RTX4090_GAMING_X_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4090 Gaming X Slim", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, MSI_SUB_VEN, MSI_RTX4090_GAMING_X_SLIM_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4090 Suprim Liquid X", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, MSI_SUB_VEN, MSI_RTX4090_SUPRIM_LIQUID_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4090 Suprim X", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, MSI_SUB_VEN, MSI_RTX4090_SUPRIM_X_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5070 Ti Gaming Trio OC Plus", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, MSI_SUB_VEN, MSI_RTX5070TI_GAMING_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5080 Gaming Trio OC", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, MSI_SUB_VEN, MSI_RTX5080_GAMING_TRIO_OC_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5080 SUPRIM SOC", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, MSI_SUB_VEN, MSI_RTX5080_SUPRIM_SOC_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5090 Gaming Trio OC", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, MSI_SUB_VEN, MSI_RTX5090_GAMING_TRIO_SUB_DEV, 0x68); +REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 5090 SUPRIM LIQUID SOC", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, MSI_SUB_VEN, MSI_RTX5090_SUPRIM_LIQUID_SOC_SUB_DEV, 0x68); diff --git a/Controllers/MSIGPUController/MSIGPUv2Controller/RGBController_MSIGPUv2.cpp b/Controllers/MSIGPUController/MSIGPUv2Controller/RGBController_MSIGPUv2.cpp new file mode 100644 index 00000000..17903a29 --- /dev/null +++ b/Controllers/MSIGPUController/MSIGPUv2Controller/RGBController_MSIGPUv2.cpp @@ -0,0 +1,488 @@ +/*---------------------------------------------------------*\ +| RGBController_MSIGPUv2.cpp | +| | +| RGBController for MSI V2 GPU (ITE9) | +| | +| Wojciech Lazarski 03 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RGBController_MSIGPUv2.h" + +static const unsigned char speed_values[3] = { 0x04, 0x02, 0x01 }; + +/**------------------------------------------------------------------*\ + @name MSI GPU v2 + @category GPU + @type I2C + @save :white_check_mark: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectMSIGPUv2Controllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_MSIGPUv2::RGBController_MSIGPUv2(MSIGPUv2Controller * controller_ptr, int msi_gpu_id) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "MSI"; + type = DEVICE_TYPE_GPU; + description = "MSI GPU V2 Device"; + location = controller->GetDeviceLocation(); + + mode Off; + Off.name = "Off"; + Off.value = MSI_GPU_V2_MODE_OFF; + Off.flags = MODE_FLAG_MANUAL_SAVE; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Direct; + Direct.name = "Direct"; + Direct.value = MSI_GPU_V2_MODE_STATIC; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; + Direct.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + Direct.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + Direct.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Rainbow; + Rainbow.name = "Rainbow Wave"; + Rainbow.value = MSI_GPU_V2_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_MANUAL_SAVE; + Rainbow.speed_min = MSI_GPU_V2_SPEED_MIN; + Rainbow.speed = MSI_GPU_V2_SPEED_MID; + Rainbow.speed_max = MSI_GPU_V2_SPEED_MAX; + Rainbow.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + Rainbow.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + Rainbow.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + Rainbow.color_mode = MODE_COLORS_RANDOM; + modes.push_back(Rainbow); + + mode Magic; + Magic.name = "Magic"; + Magic.value = MSI_GPU_V2_MODE_MAGIC; + Magic.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_MANUAL_SAVE; + Magic.speed_min = MSI_GPU_V2_SPEED_MIN; + Magic.speed = MSI_GPU_V2_SPEED_MID; + Magic.speed_max = MSI_GPU_V2_SPEED_MAX; + Magic.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + Magic.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + Magic.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + Magic.color_mode = MODE_COLORS_RANDOM; + modes.push_back(Magic); + + mode ColorCycle; + ColorCycle.name = "Color Cycle"; + ColorCycle.value = MSI_GPU_V2_MODE_MAGIC; + ColorCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_MANUAL_SAVE; + ColorCycle.speed_min = MSI_GPU_V2_SPEED_MIN; + ColorCycle.speed = MSI_GPU_V2_SPEED_MID; + ColorCycle.speed_max = MSI_GPU_V2_SPEED_MAX; + ColorCycle.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + ColorCycle.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + ColorCycle.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + ColorCycle.colors_min = 1; + ColorCycle.colors_max = 3; + ColorCycle.colors.resize(3); + ColorCycle.color_mode = MODE_COLORS_MODE_SPECIFIC; + modes.push_back(ColorCycle); + + + mode Patrolling; + Patrolling.name = "Patrolling"; + Patrolling.value = MSI_GPU_V2_MODE_PATROLLING; + Patrolling.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + Patrolling.speed_min = MSI_GPU_V2_SPEED_MIN; + Patrolling.speed = MSI_GPU_V2_SPEED_MID; + Patrolling.speed_max = MSI_GPU_V2_SPEED_MAX; + Patrolling.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + Patrolling.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + Patrolling.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + Patrolling.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Patrolling); + + mode Streaming; + Streaming.name = "Streaming"; + Streaming.value = MSI_GPU_V2_MODE_STREAMING; + Streaming.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_MANUAL_SAVE; + Streaming.speed_min = MSI_GPU_V2_SPEED_MIN; + Streaming.speed = MSI_GPU_V2_SPEED_MID; + Streaming.speed_max = MSI_GPU_V2_SPEED_MAX; + Streaming.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + Streaming.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + Streaming.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + Streaming.color_mode = MODE_COLORS_RANDOM; + modes.push_back(Streaming); + + mode Lightning; + Lightning.name = "Lightning"; + Lightning.value = MSI_GPU_V2_MODE_LIGHTNING; + Lightning.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_MANUAL_SAVE; + Lightning.speed_min = MSI_GPU_V2_SPEED_MIN; + Lightning.speed = MSI_GPU_V2_SPEED_MID; + Lightning.speed_max = MSI_GPU_V2_SPEED_MAX; + Lightning.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + Lightning.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + Lightning.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + Lightning.color_mode = MODE_COLORS_RANDOM; + modes.push_back(Lightning); + + mode Wave; + Wave.name = "Wave"; + Wave.value = MSI_GPU_V2_MODE_RAINBOW; //Rainbow has two modes now + Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_MANUAL_SAVE; + Wave.speed_min = MSI_GPU_V2_SPEED_MIN; + Wave.speed = MSI_GPU_V2_SPEED_MID; + Wave.speed_max = MSI_GPU_V2_SPEED_MAX; + Wave.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + Wave.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + Wave.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + Wave.colors_min = 1; + Wave.colors_max = 3; + Wave.colors.resize(3); + Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; + modes.push_back(Wave); + + mode Meteor; + Meteor.name = "Meteor"; + Meteor.value = MSI_GPU_V2_MODE_METEOR; + Meteor.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + Meteor.speed_min = MSI_GPU_V2_SPEED_MIN; + Meteor.speed = MSI_GPU_V2_SPEED_MID; + Meteor.speed_max = MSI_GPU_V2_SPEED_MAX; + Meteor.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + Meteor.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + Meteor.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + Meteor.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Meteor); + + switch(msi_gpu_id) + { + case MSI_RTX4060TI_GAMING_X_16G_SLIM_WHITE_SUB_DEV | NVIDIA_RTX4060TI_16G_DEV << 16: + case MSI_RTX4070S_GAMING_X_SLIM_SUB_DEV | NVIDIA_RTX4070S_DEV << 16: + case MSI_RTX4070TI_GAMING_X_TRIO_WHITE_SUB_DEV | NVIDIA_RTX4070TIS_DEV << 16: + case MSI_RTX4080S_GAMING_X_TRIO_SUB_DEV | NVIDIA_RTX4080S_DEV << 16: + case MSI_RTX4080S_GAMING_X_SLIM_WHITE_SUB_DEV | NVIDIA_RTX4080_DEV << 16: + case MSI_RTX4080S_GAMING_X_SLIM_WHITE_SUB_DEV | NVIDIA_RTX4080S_DEV << 16: + break; + + default: + mode Stack; + Stack.name = "Stack"; + Stack.value = MSI_GPU_V2_MODE_STACK; + Stack.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + Stack.speed_min = MSI_GPU_V2_SPEED_MIN; + Stack.speed = MSI_GPU_V2_SPEED_MID; + Stack.speed_max = MSI_GPU_V2_SPEED_MAX; + Stack.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + Stack.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + Stack.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + Stack.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Stack); + + mode Rhythm; + Rhythm.name = "Rhythm"; + Rhythm.value = MSI_GPU_V2_MODE_RHYTHM; + Rhythm.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + Rhythm.speed_min = MSI_GPU_V2_SPEED_MIN; + Rhythm.speed = MSI_GPU_V2_SPEED_MID; + Rhythm.speed_max = MSI_GPU_V2_SPEED_MAX; + Rhythm.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + Rhythm.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + Rhythm.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + Rhythm.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Rhythm); + } + + mode Flowing; + Flowing.name = "Flowing"; + Flowing.value = MSI_GPU_V2_MODE_FLOWING; + Flowing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + Flowing.speed_min = MSI_GPU_V2_SPEED_MIN; + Flowing.speed = MSI_GPU_V2_SPEED_MID; + Flowing.speed_max = MSI_GPU_V2_SPEED_MAX; + Flowing.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + Flowing.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + Flowing.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + Flowing.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Flowing); + + mode Whirling; + Whirling.name = "Whirling"; + Whirling.value = MSI_GPU_V2_MODE_WHIRLING; + Whirling.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + Whirling.speed_min = MSI_GPU_V2_SPEED_MIN; + Whirling.speed = MSI_GPU_V2_SPEED_MID; + Whirling.speed_max = MSI_GPU_V2_SPEED_MAX; + Whirling.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + Whirling.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + Whirling.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + Whirling.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Whirling); + + mode Fadein; + Fadein.name = "Fade In"; + Fadein.value = MSI_GPU_V2_MODE_FADEIN; + Fadein.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_MANUAL_SAVE; + Fadein.speed_min = MSI_GPU_V2_SPEED_MIN; + Fadein.speed = MSI_GPU_V2_SPEED_MID; + Fadein.speed_max = MSI_GPU_V2_SPEED_MAX; + Fadein.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + Fadein.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + Fadein.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + Fadein.colors_min = 1; + Fadein.colors_max = 2; + Fadein.colors.resize(2); + Fadein.color_mode = MODE_COLORS_MODE_SPECIFIC; + modes.push_back(Fadein); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = MSI_GPU_V2_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_MANUAL_SAVE; + Breathing.speed_min = MSI_GPU_V2_SPEED_MIN; + Breathing.speed = MSI_GPU_V2_SPEED_MID; + Breathing.speed_max = MSI_GPU_V2_SPEED_MAX; + Breathing.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + Breathing.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + Breathing.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + Breathing.colors_min = 1; + Breathing.colors_max = 2; + Breathing.colors.resize(2); + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + modes.push_back(Breathing); + + mode flashing; + flashing.name = "Flashing"; + flashing.value = MSI_GPU_V2_MODE_FLASHING; + flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + flashing.speed_min = MSI_GPU_V2_SPEED_MIN; + flashing.speed = MSI_GPU_V2_SPEED_MID; + flashing.speed_max = MSI_GPU_V2_SPEED_MAX; + flashing.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + flashing.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + flashing.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + flashing.color_mode = MODE_COLORS_PER_LED; + modes.push_back(flashing); + + mode doubleflashing; + doubleflashing.name = "Double Flashing"; + doubleflashing.value = MSI_GPU_V2_MODE_DOUBLEFLASHING; + doubleflashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + doubleflashing.speed_min = MSI_GPU_V2_SPEED_MIN; + doubleflashing.speed = MSI_GPU_V2_SPEED_MID; + doubleflashing.speed_max = MSI_GPU_V2_SPEED_MAX; + doubleflashing.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; + doubleflashing.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; + doubleflashing.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; + doubleflashing.color_mode = MODE_COLORS_PER_LED; + modes.push_back(doubleflashing); + + SetupZones(); + + modes[active_mode].speed = MSI_GPU_V2_SPEED_MID; + modes[active_mode].brightness = MSI_GPU_V2_BRIGHTNESS_MAX; +} + +RGBController_MSIGPUv2::~RGBController_MSIGPUv2() +{ + delete controller; +} + +void RGBController_MSIGPUv2::SetupZones() +{ + /*---------------------------------------------------------*\ + | Set up zone | + \*---------------------------------------------------------*/ + zone msi_gpu_zone; + msi_gpu_zone.name = "GPU"; + msi_gpu_zone.type = ZONE_TYPE_SINGLE; + msi_gpu_zone.leds_min = 1; + msi_gpu_zone.leds_max = 1; + msi_gpu_zone.leds_count = 1; + msi_gpu_zone.matrix_map = NULL; + zones.push_back(msi_gpu_zone); + + /*---------------------------------------------------------*\ + | Set up LED | + \*---------------------------------------------------------*/ + led led1; + led1.name = "Color"; + leds.push_back(led1); + + SetupColors(); + + /*-------------------------------------------------------------*\ + | Initialize colors | + | This controller doesn't support reading colors from device | + \*-------------------------------------------------------------*/ + colors[0] = ToRGBColor(0xFF, 0, 0); + + for(unsigned int mode_idx = 0; mode_idx < modes.size(); mode_idx++) + { + if(modes[mode_idx].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + if(modes[mode_idx].colors.size()>2) + { + modes[mode_idx].colors[2] = ToRGBColor(0, 0, 0xFF); + } + if(modes[mode_idx].colors.size()>1) + { + modes[mode_idx].colors[1] = ToRGBColor(0, 0xFF, 0); + } + modes[mode_idx].colors[0] = ToRGBColor(0xFF, 0, 0); + } + } + +} + +void RGBController_MSIGPUv2::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_MSIGPUv2::DeviceUpdateAll(const mode& current_mode) +{ + switch(current_mode.value) + { + case MSI_GPU_V2_MODE_RAINBOW: + if(current_mode.flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR) + { + if(current_mode.direction == MODE_DIRECTION_LEFT) + { + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_CONTROL, MSI_GPU_V2_CONTROL_DIRECTION_LEFT | MSI_GPU_V2_CONTROL_NON_RGBMODE); + } + else + { + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_CONTROL, MSI_GPU_V2_CONTROL_DIRECTION_RIGHT | MSI_GPU_V2_CONTROL_NON_RGBMODE); + } + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_UNKNOWN, 0x00); + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, MSI_GPU_V2_MODE_IDLE); + + controller->SetRGB1V2(RGBGetRValue(current_mode.colors[0]), RGBGetGValue(current_mode.colors[0]), RGBGetBValue(current_mode.colors[0])); + controller->SetRGB2V2(RGBGetRValue(current_mode.colors[1]), RGBGetGValue(current_mode.colors[1]), RGBGetBValue(current_mode.colors[1])); + controller->SetRGB3V2(RGBGetRValue(current_mode.colors[2]), RGBGetGValue(current_mode.colors[2]), RGBGetBValue(current_mode.colors[2])); + } + else + { + if(current_mode.direction == MODE_DIRECTION_LEFT) + { + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_CONTROL, MSI_GPU_V2_CONTROL_DIRECTION_LEFT); + } + else + { + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_CONTROL, MSI_GPU_V2_CONTROL_DIRECTION_RIGHT); + } + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_UNKNOWN, 0x00); + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, MSI_GPU_V2_MODE_IDLE); + } + break; + + case MSI_GPU_V2_MODE_MAGIC: + if(current_mode.flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR) + { + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_UNKNOWN, 0x00); + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, MSI_GPU_V2_MODE_IDLE); + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_CONTROL, MSI_GPU_V2_CONTROL_NON_RGBMODE); + + controller->SetRGB1V2(RGBGetRValue(current_mode.colors[0]), RGBGetGValue(current_mode.colors[0]), RGBGetBValue(current_mode.colors[0])); + controller->SetRGB2V2(RGBGetRValue(current_mode.colors[1]), RGBGetGValue(current_mode.colors[1]), RGBGetBValue(current_mode.colors[1])); + controller->SetRGB3V2(RGBGetRValue(current_mode.colors[2]), RGBGetGValue(current_mode.colors[2]), RGBGetBValue(current_mode.colors[2])); + } + else + { + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_UNKNOWN, 0x00); + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, MSI_GPU_V2_MODE_IDLE); + + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_CONTROL, MSI_GPU_V2_CONTROL_DIRECTION_RIGHT); + } + break; + + + case MSI_GPU_V2_MODE_BREATHING: + case MSI_GPU_V2_MODE_FADEIN: + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_UNKNOWN, 0x00); + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, MSI_GPU_V2_MODE_IDLE); + + controller->SetRGB1V2(RGBGetRValue(current_mode.colors[0]), RGBGetGValue(current_mode.colors[0]), RGBGetBValue(current_mode.colors[0])); + controller->SetRGB2V2(RGBGetRValue(current_mode.colors[1]), RGBGetGValue(current_mode.colors[1]), RGBGetBValue(current_mode.colors[1])); + break; + + case MSI_GPU_V2_MODE_FLOWING: + case MSI_GPU_V2_MODE_WHIRLING: + case MSI_GPU_V2_MODE_PATROLLING: + case MSI_GPU_V2_MODE_FLASHING: + case MSI_GPU_V2_MODE_DOUBLEFLASHING: + case MSI_GPU_V2_MODE_STATIC: + case MSI_GPU_V2_MODE_RHYTHM: + case MSI_GPU_V2_MODE_STACK: + case MSI_GPU_V2_MODE_METEOR: + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_UNKNOWN, 0x00); + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, MSI_GPU_V2_MODE_IDLE); + controller->SetRGB1(RGBGetRValue(colors[0]), RGBGetGValue(colors[0]), RGBGetBValue(colors[0])); + break; + + case MSI_GPU_V2_MODE_STREAMING: + case MSI_GPU_V2_MODE_LIGHTNING: + case MSI_GPU_V2_MODE_OFF: + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_UNKNOWN, 0x00); + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, MSI_GPU_V2_MODE_IDLE); + break; + + default: + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_UNKNOWN, 0x00); + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, MSI_GPU_V2_MODE_IDLE); + controller->SetMode(MSI_GPU_V2_MODE_OFF); + } + + + if(current_mode.flags & MODE_FLAG_HAS_BRIGHTNESS) + { + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_BRIGHTNESS, MSI_GPU_V2_BRIGHTNESS_MULTI * modes[active_mode].brightness); + if(modes[active_mode].flags & MODE_FLAG_HAS_SPEED) + { + controller->MSIGPURegisterWrite(MSI_GPU_V2_REG_SPEED, speed_values[current_mode.speed]); + } + + } + + controller->SetMode(current_mode.value); +} + + +void RGBController_MSIGPUv2::DeviceUpdateLEDs() +{ + DeviceUpdateAll(modes[active_mode]); +} + +void RGBController_MSIGPUv2::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateAll(modes[active_mode]); +} + + +void RGBController_MSIGPUv2::UpdateSingleLED(int /*led*/) +{ + /*---------------------------------------------------------*\ + | This device does not support updating single LEDs | + \*---------------------------------------------------------*/ +} + +void RGBController_MSIGPUv2::DeviceUpdateMode() +{ + DeviceUpdateAll(modes[active_mode]); +} + +void RGBController_MSIGPUv2::DeviceSaveMode() +{ + controller->Save(); +} diff --git a/Controllers/MSIGPUController/MSIGPUv2Controller/RGBController_MSIGPUv2.h b/Controllers/MSIGPUController/MSIGPUv2Controller/RGBController_MSIGPUv2.h new file mode 100644 index 00000000..39f98611 --- /dev/null +++ b/Controllers/MSIGPUController/MSIGPUv2Controller/RGBController_MSIGPUv2.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------*\ +| RGBController_MSIGPUv2.h | +| | +| RGBController for MSI V2 GPU (ITE9) | +| | +| Wojciech Lazarski 03 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "pci_ids.h" +#include "RGBController.h" +#include "MSIGPUv2Controller.h" + +class RGBController_MSIGPUv2 : public RGBController +{ +public: + RGBController_MSIGPUv2(MSIGPUv2Controller* controller_ptr, int msi_gpu_id); + ~RGBController_MSIGPUv2(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + MSIGPUv2Controller* controller; + + void DeviceUpdateAll(const mode& current_mode); +}; diff --git a/Controllers/MSIGPUController/MSIGPUv2ControllerDetect.cpp b/Controllers/MSIGPUController/MSIGPUv2ControllerDetect.cpp deleted file mode 100644 index ec9954cf..00000000 --- a/Controllers/MSIGPUController/MSIGPUv2ControllerDetect.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/*-----------------------------------------*\ -| MSIGPUControllerDetect.cpp | -| | -| Driver for MSI GPUs | -| | -\*-----------------------------------------*/ - -#include "Detector.h" -#include "LogManager.h" -#include "i2c_smbus.h" -#include "pci_ids.h" - -#include "RGBController_MSIGPUv2.h" -#include "MSIGPUv2Controller.h" - -/*-----------------------------------------------------------------------------------------*\ -| | -| DetectMSI GPU V2 Controllers | -| | -| Detect MSI GPU v2 controllers on the enumerated I2C busses. | -| | -\*-----------------------------------------------------------------------------------------*/ - -void DetectMSIGPUv2Controllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name) -{ - if(bus->pci_vendor == NVIDIA_VEN && bus->port_id != 1) - { - return; - } - - MSIGPUv2Controller* controller = new MSIGPUv2Controller(bus, i2c_addr); - RGBController_MSIGPUv2* rgb_controller = new RGBController_MSIGPUv2(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - LOG_TRACE("MSI GPU Controler using ITE9 chip"); - - -} /* DetectMSIGPUv2Controllers() */ - -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070 12GB Gaming X Trio", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070_DEV, MSI_SUB_VEN, MSI_RTX4070_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070Ti 12GB Gaming X Trio", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, MSI_SUB_VEN, MSI_RTX4070TI_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4070Ti 12GB Suprim X Trio", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, MSI_SUB_VEN, MSI_RTX4070TI_SUPRIM_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4080 16GB Gaming X Trio", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, MSI_SUB_VEN, MSI_RTX4080_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4080 16GB Suprim X", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, MSI_SUB_VEN, MSI_RTX4080_SUPRIM_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4090 24GB Gaming X Trio", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, MSI_SUB_VEN, MSI_RTX4090_GAMING_X_TRIO_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4090 24GB Suprim Liquid X", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, MSI_SUB_VEN, MSI_RTX4090_SUPRIM_LIQUID_X_SUB_DEV, 0x68); -REGISTER_I2C_PCI_DETECTOR("MSI GeForce RTX 4090 24GB Suprim X", DetectMSIGPUv2Controllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, MSI_SUB_VEN, MSI_RTX4090_SUPRIM_X_SUB_DEV, 0x68); diff --git a/Controllers/MSIGPUController/RGBController_MSIGPU.h b/Controllers/MSIGPUController/RGBController_MSIGPU.h deleted file mode 100644 index f305233f..00000000 --- a/Controllers/MSIGPUController/RGBController_MSIGPU.h +++ /dev/null @@ -1,36 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_MSIGPU.h | -| | -| Generic RGB Interface for MSI GPU | -| | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "MSIGPUController.h" - -class RGBController_MSIGPU : public RGBController -{ -public: - RGBController_MSIGPU(MSIGPUController* msi_gpu_ptr); - ~RGBController_MSIGPU(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - MSIGPUController* msi_gpu; - std::chrono::time_point last_commit_time; - - bool TimeToSend(); - int GetDeviceMode(); - int GetModeSpeed(); -}; diff --git a/Controllers/MSIGPUController/RGBController_MSIGPUv2.cpp b/Controllers/MSIGPUController/RGBController_MSIGPUv2.cpp deleted file mode 100644 index ca7c71c5..00000000 --- a/Controllers/MSIGPUController/RGBController_MSIGPUv2.cpp +++ /dev/null @@ -1,474 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_MSIGPUv2.cpp | -| | -| ITE9 RGB Interface for MSI GPU | -| Wojciech Lazarski 03/Jan/2023 | -| | -\*-----------------------------------------*/ - -#include "RGBController_MSIGPUv2.h" -#include - -static const unsigned char speed_values[3] = { 0x04, 0x02, 0x01 }; - -/**------------------------------------------------------------------*\ - @name MSI GPU v2 - @category GPU - @type I2C - @save :white_check_mark: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectMSIGPUv2Controllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_MSIGPUv2::RGBController_MSIGPUv2(MSIGPUv2Controller * msi_gpu_ptr) -{ - msi_gpu = msi_gpu_ptr; - - name = "MSI GPU Device"; - vendor = "MSI"; - type = DEVICE_TYPE_GPU; - description = name; - location = msi_gpu->GetDeviceLocation(); - - mode Off; - - Off.name = "Off"; - Off.value = MSI_GPU_V2_MODE_OFF; - Off.flags = MODE_FLAG_MANUAL_SAVE; - Off.color_mode = MODE_COLORS_NONE; - modes.push_back(Off); - - mode Direct; - Direct.name = "Direct"; - Direct.value = MSI_GPU_V2_MODE_STATIC; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_MANUAL_SAVE; - Direct.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - Direct.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - Direct.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - - mode Rainbow; - Rainbow.name = "Rainbow Wave"; - Rainbow.value = MSI_GPU_V2_MODE_RAINBOW; - Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_MANUAL_SAVE; - Rainbow.speed_min = MSI_GPU_V2_SPEED_MIN; - Rainbow.speed = MSI_GPU_V2_SPEED_MID; - Rainbow.speed_max = MSI_GPU_V2_SPEED_MAX; - Rainbow.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - Rainbow.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - Rainbow.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - Rainbow.color_mode = MODE_COLORS_RANDOM; - modes.push_back(Rainbow); - - mode Magic; - Magic.name = "Magic"; - Magic.value = MSI_GPU_V2_MODE_MAGIC; - Magic.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_MANUAL_SAVE; - Magic.speed_min = MSI_GPU_V2_SPEED_MIN; - Magic.speed = MSI_GPU_V2_SPEED_MID; - Magic.speed_max = MSI_GPU_V2_SPEED_MAX; - Magic.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - Magic.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - Magic.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - Magic.color_mode = MODE_COLORS_RANDOM; - modes.push_back(Magic); - - mode ColorCycle; - ColorCycle.name = "Color Cycle"; - ColorCycle.value = MSI_GPU_V2_MODE_MAGIC; - ColorCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_MANUAL_SAVE; - ColorCycle.speed_min = MSI_GPU_V2_SPEED_MIN; - ColorCycle.speed = MSI_GPU_V2_SPEED_MID; - ColorCycle.speed_max = MSI_GPU_V2_SPEED_MAX; - ColorCycle.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - ColorCycle.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - ColorCycle.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - ColorCycle.colors_min = 1; - ColorCycle.colors_max = 3; - ColorCycle.colors.resize(3); - ColorCycle.color_mode = MODE_COLORS_MODE_SPECIFIC; - modes.push_back(ColorCycle); - - - mode Patrolling; - Patrolling.name = "Patrolling"; - Patrolling.value = MSI_GPU_V2_MODE_PATROLLING; - Patrolling.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; - Patrolling.speed_min = MSI_GPU_V2_SPEED_MIN; - Patrolling.speed = MSI_GPU_V2_SPEED_MID; - Patrolling.speed_max = MSI_GPU_V2_SPEED_MAX; - Patrolling.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - Patrolling.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - Patrolling.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - Patrolling.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Patrolling); - - mode Streaming; - Streaming.name = "Streaming"; - Streaming.value = MSI_GPU_V2_MODE_STREAMING; - Streaming.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_MANUAL_SAVE; - Streaming.speed_min = MSI_GPU_V2_SPEED_MIN; - Streaming.speed = MSI_GPU_V2_SPEED_MID; - Streaming.speed_max = MSI_GPU_V2_SPEED_MAX; - Streaming.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - Streaming.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - Streaming.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - Streaming.color_mode = MODE_COLORS_RANDOM; - modes.push_back(Streaming); - - mode Lightning; - Lightning.name = "Lightning"; - Lightning.value = MSI_GPU_V2_MODE_LIGHTNING; - Lightning.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_MANUAL_SAVE; - Lightning.speed_min = MSI_GPU_V2_SPEED_MIN; - Lightning.speed = MSI_GPU_V2_SPEED_MID; - Lightning.speed_max = MSI_GPU_V2_SPEED_MAX; - Lightning.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - Lightning.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - Lightning.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - Lightning.color_mode = MODE_COLORS_RANDOM; - modes.push_back(Lightning); - - mode Wave; - Wave.name = "Wave"; - Wave.value = MSI_GPU_V2_MODE_RAINBOW; //Rainbow has two modes now - Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_MANUAL_SAVE; - Wave.speed_min = MSI_GPU_V2_SPEED_MIN; - Wave.speed = MSI_GPU_V2_SPEED_MID; - Wave.speed_max = MSI_GPU_V2_SPEED_MAX; - Wave.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - Wave.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - Wave.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - Wave.colors_min = 1; - Wave.colors_max = 3; - Wave.colors.resize(3); - Wave.color_mode = MODE_COLORS_MODE_SPECIFIC; - modes.push_back(Wave); - - mode Meteor; - Meteor.name = "Meteor"; - Meteor.value = MSI_GPU_V2_MODE_METEOR; - Meteor.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; - Meteor.speed_min = MSI_GPU_V2_SPEED_MIN; - Meteor.speed = MSI_GPU_V2_SPEED_MID; - Meteor.speed_max = MSI_GPU_V2_SPEED_MAX; - Meteor.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - Meteor.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - Meteor.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - Meteor.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Meteor); - - mode Stack; - Stack.name = "Stack"; - Stack.value = MSI_GPU_V2_MODE_STACK; - Stack.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; - Stack.speed_min = MSI_GPU_V2_SPEED_MIN; - Stack.speed = MSI_GPU_V2_SPEED_MID; - Stack.speed_max = MSI_GPU_V2_SPEED_MAX; - Stack.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - Stack.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - Stack.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - Stack.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Stack); - - mode Rhythm; - Rhythm.name = "Rhythm"; - Rhythm.value = MSI_GPU_V2_MODE_RHYTHM; - Rhythm.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; - Rhythm.speed_min = MSI_GPU_V2_SPEED_MIN; - Rhythm.speed = MSI_GPU_V2_SPEED_MID; - Rhythm.speed_max = MSI_GPU_V2_SPEED_MAX; - Rhythm.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - Rhythm.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - Rhythm.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - Rhythm.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Rhythm); - - mode Flowing; - Flowing.name = "Flowing"; - Flowing.value = MSI_GPU_V2_MODE_FLOWING; - Flowing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; - Flowing.speed_min = MSI_GPU_V2_SPEED_MIN; - Flowing.speed = MSI_GPU_V2_SPEED_MID; - Flowing.speed_max = MSI_GPU_V2_SPEED_MAX; - Flowing.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - Flowing.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - Flowing.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - Flowing.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Flowing); - - mode Whirling; - Whirling.name = "Whirling"; - Whirling.value = MSI_GPU_V2_MODE_WHIRLING; - Whirling.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; - Whirling.speed_min = MSI_GPU_V2_SPEED_MIN; - Whirling.speed = MSI_GPU_V2_SPEED_MID; - Whirling.speed_max = MSI_GPU_V2_SPEED_MAX; - Whirling.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - Whirling.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - Whirling.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - Whirling.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Whirling); - - mode Fadein; - Fadein.name = "Fade In"; - Fadein.value = MSI_GPU_V2_MODE_FADEIN; - Fadein.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_MANUAL_SAVE; - Fadein.speed_min = MSI_GPU_V2_SPEED_MIN; - Fadein.speed = MSI_GPU_V2_SPEED_MID; - Fadein.speed_max = MSI_GPU_V2_SPEED_MAX; - Fadein.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - Fadein.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - Fadein.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - Fadein.colors_min = 1; - Fadein.colors_max = 2; - Fadein.colors.resize(2); - Fadein.color_mode = MODE_COLORS_MODE_SPECIFIC; - modes.push_back(Fadein); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = MSI_GPU_V2_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_MANUAL_SAVE; - Breathing.speed_min = MSI_GPU_V2_SPEED_MIN; - Breathing.speed = MSI_GPU_V2_SPEED_MID; - Breathing.speed_max = MSI_GPU_V2_SPEED_MAX; - Breathing.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - Breathing.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - Breathing.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - Breathing.colors_min = 1; - Breathing.colors_max = 2; - Breathing.colors.resize(2); - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - modes.push_back(Breathing); - - mode flashing; - flashing.name = "Flashing"; - flashing.value = MSI_GPU_V2_MODE_FLASHING; - flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; - flashing.speed_min = MSI_GPU_V2_SPEED_MIN; - flashing.speed = MSI_GPU_V2_SPEED_MID; - flashing.speed_max = MSI_GPU_V2_SPEED_MAX; - flashing.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - flashing.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - flashing.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - flashing.color_mode = MODE_COLORS_PER_LED; - modes.push_back(flashing); - - mode doubleflashing; - doubleflashing.name = "Double Flashing"; - doubleflashing.value = MSI_GPU_V2_MODE_DOUBLEFLASHING; - doubleflashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; - doubleflashing.speed_min = MSI_GPU_V2_SPEED_MIN; - doubleflashing.speed = MSI_GPU_V2_SPEED_MID; - doubleflashing.speed_max = MSI_GPU_V2_SPEED_MAX; - doubleflashing.brightness_min = MSI_GPU_V2_BRIGHTNESS_MIN; - doubleflashing.brightness = MSI_GPU_V2_BRIGHTNESS_MAX; - doubleflashing.brightness_max = MSI_GPU_V2_BRIGHTNESS_MAX; - doubleflashing.color_mode = MODE_COLORS_PER_LED; - modes.push_back(doubleflashing); - - SetupZones(); - - modes[active_mode].speed = MSI_GPU_V2_SPEED_MID; - modes[active_mode].brightness = MSI_GPU_V2_BRIGHTNESS_MAX; -} - -RGBController_MSIGPUv2::~RGBController_MSIGPUv2() -{ - delete msi_gpu; -} - -void RGBController_MSIGPUv2::SetupZones() -{ - /*---------------------------------------------------------*\ - | Set up zone | - \*---------------------------------------------------------*/ - zone msi_gpu_zone; - msi_gpu_zone.name = "GPU"; - msi_gpu_zone.type = ZONE_TYPE_SINGLE; - msi_gpu_zone.leds_min = 1; - msi_gpu_zone.leds_max = 1; - msi_gpu_zone.leds_count = 1; - msi_gpu_zone.matrix_map = NULL; - zones.push_back(msi_gpu_zone); - - /*---------------------------------------------------------*\ - | Set up LED | - \*---------------------------------------------------------*/ - led led1; - led1.name = "Color"; - leds.push_back(led1); - - SetupColors(); - - /*-------------------------------------------------------------*\ - | Initialize colors | - | This controller doesn't support reading colors from device | - \*-------------------------------------------------------------*/ - colors[0] = ToRGBColor(0xFF, 0, 0); - - for(unsigned int mode_idx = 0; mode_idx < modes.size(); mode_idx++) - { - if(modes[mode_idx].color_mode == MODE_COLORS_MODE_SPECIFIC) - { - if(modes[mode_idx].colors.size()>2) - { - modes[mode_idx].colors[2] = ToRGBColor(0, 0, 0xFF); - } - if(modes[mode_idx].colors.size()>1) - { - modes[mode_idx].colors[1] = ToRGBColor(0, 0xFF, 0); - } - modes[mode_idx].colors[0] = ToRGBColor(0xFF, 0, 0); - } - } - -} - -void RGBController_MSIGPUv2::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_MSIGPUv2::DeviceUpdateAll(const mode& current_mode) -{ - switch(current_mode.value) - { - case MSI_GPU_V2_MODE_RAINBOW: - if(current_mode.flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR) - { - if(current_mode.direction == MODE_DIRECTION_LEFT) - { - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_CONTROL, MSI_GPU_V2_CONTROL_DIRECTION_LEFT | MSI_GPU_V2_CONTROL_NON_RGBMODE); - } - else - { - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_CONTROL, MSI_GPU_V2_CONTROL_DIRECTION_RIGHT | MSI_GPU_V2_CONTROL_NON_RGBMODE); - } - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_UNKNOWN, 0x00); - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, MSI_GPU_V2_MODE_IDLE); - - msi_gpu->SetRGB1V2(RGBGetRValue(current_mode.colors[0]), RGBGetGValue(current_mode.colors[0]), RGBGetBValue(current_mode.colors[0])); - msi_gpu->SetRGB2V2(RGBGetRValue(current_mode.colors[1]), RGBGetGValue(current_mode.colors[1]), RGBGetBValue(current_mode.colors[1])); - msi_gpu->SetRGB3V2(RGBGetRValue(current_mode.colors[2]), RGBGetGValue(current_mode.colors[2]), RGBGetBValue(current_mode.colors[2])); - } - else - { - if(current_mode.direction == MODE_DIRECTION_LEFT) - { - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_CONTROL, MSI_GPU_V2_CONTROL_DIRECTION_LEFT); - } - else - { - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_CONTROL, MSI_GPU_V2_CONTROL_DIRECTION_RIGHT); - } - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_UNKNOWN, 0x00); - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, MSI_GPU_V2_MODE_IDLE); - } - break; - - case MSI_GPU_V2_MODE_MAGIC: - if(current_mode.flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR) - { - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_UNKNOWN, 0x00); - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, MSI_GPU_V2_MODE_IDLE); - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_CONTROL, MSI_GPU_V2_CONTROL_NON_RGBMODE); - - msi_gpu->SetRGB1V2(RGBGetRValue(current_mode.colors[0]), RGBGetGValue(current_mode.colors[0]), RGBGetBValue(current_mode.colors[0])); - msi_gpu->SetRGB2V2(RGBGetRValue(current_mode.colors[1]), RGBGetGValue(current_mode.colors[1]), RGBGetBValue(current_mode.colors[1])); - msi_gpu->SetRGB3V2(RGBGetRValue(current_mode.colors[2]), RGBGetGValue(current_mode.colors[2]), RGBGetBValue(current_mode.colors[2])); - } - else - { - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_UNKNOWN, 0x00); - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, MSI_GPU_V2_MODE_IDLE); - - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_CONTROL, MSI_GPU_V2_CONTROL_DIRECTION_RIGHT); - } - break; - - - case MSI_GPU_V2_MODE_BREATHING: - case MSI_GPU_V2_MODE_FADEIN: - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_UNKNOWN, 0x00); - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, MSI_GPU_V2_MODE_IDLE); - - msi_gpu->SetRGB1V2(RGBGetRValue(current_mode.colors[0]), RGBGetGValue(current_mode.colors[0]), RGBGetBValue(current_mode.colors[0])); - msi_gpu->SetRGB2V2(RGBGetRValue(current_mode.colors[1]), RGBGetGValue(current_mode.colors[1]), RGBGetBValue(current_mode.colors[1])); - break; - - case MSI_GPU_V2_MODE_FLOWING: - case MSI_GPU_V2_MODE_WHIRLING: - case MSI_GPU_V2_MODE_PATROLLING: - case MSI_GPU_V2_MODE_FLASHING: - case MSI_GPU_V2_MODE_DOUBLEFLASHING: - case MSI_GPU_V2_MODE_STATIC: - case MSI_GPU_V2_MODE_RHYTHM: - case MSI_GPU_V2_MODE_STACK: - case MSI_GPU_V2_MODE_METEOR: - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_UNKNOWN, 0x00); - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, MSI_GPU_V2_MODE_IDLE); - msi_gpu->SetRGB1(RGBGetRValue(colors[0]), RGBGetGValue(colors[0]), RGBGetBValue(colors[0])); - break; - - case MSI_GPU_V2_MODE_STREAMING: - case MSI_GPU_V2_MODE_LIGHTNING: - case MSI_GPU_V2_MODE_OFF: - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_UNKNOWN, 0x00); - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, MSI_GPU_V2_MODE_IDLE); - break; - - default: - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_UNKNOWN, 0x00); - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_MODE, MSI_GPU_V2_MODE_IDLE); - msi_gpu->SetMode(MSI_GPU_V2_MODE_OFF); - } - - - if(current_mode.flags & MODE_FLAG_HAS_BRIGHTNESS) - { - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_BRIGHTNESS, MSI_GPU_V2_BRIGHTNESS_MULTI * modes[active_mode].brightness); - if(modes[active_mode].flags & MODE_FLAG_HAS_SPEED) - { - msi_gpu->MSIGPURegisterWrite(MSI_GPU_V2_REG_SPEED, speed_values[current_mode.speed]); - } - - } - - msi_gpu->SetMode(current_mode.value); -} - - -void RGBController_MSIGPUv2::DeviceUpdateLEDs() -{ - DeviceUpdateAll(modes[active_mode]); -} - -void RGBController_MSIGPUv2::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateAll(modes[active_mode]); -} - - -void RGBController_MSIGPUv2::UpdateSingleLED(int /*led*/) -{ - /*---------------------------------------------------------*\ - | This device does not support updating single LEDs | - \*---------------------------------------------------------*/ -} - -void RGBController_MSIGPUv2::DeviceUpdateMode() -{ - DeviceUpdateAll(modes[active_mode]); -} - -void RGBController_MSIGPUv2::DeviceSaveMode() -{ - msi_gpu->Save(); -} diff --git a/Controllers/MSIGPUController/RGBController_MSIGPUv2.h b/Controllers/MSIGPUController/RGBController_MSIGPUv2.h deleted file mode 100644 index 988dc310..00000000 --- a/Controllers/MSIGPUController/RGBController_MSIGPUv2.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_MSIGPUv2.h | -| | -| ITE9 RGB Interface for MSI GPU | -| Wojciech Lazarski 03/Jan/2023 | -| | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "MSIGPUv2Controller.h" - -class RGBController_MSIGPUv2 : public RGBController -{ -public: - RGBController_MSIGPUv2(MSIGPUv2Controller* msi_gpu_ptr); - ~RGBController_MSIGPUv2(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - MSIGPUv2Controller* msi_gpu; - void DeviceUpdateAll(const mode& current_mode); -}; diff --git a/Controllers/MSIKeyboardController/MSIKeyboardControllerDetect.cpp b/Controllers/MSIKeyboardController/MSIKeyboardControllerDetect.cpp new file mode 100644 index 00000000..e4f50806 --- /dev/null +++ b/Controllers/MSIKeyboardController/MSIKeyboardControllerDetect.cpp @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| MSIKeyboardControllerDetect.cpp | +| | +| Detector for MSI Mystic Light MS-1565 Keyboard | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "MSIMysticLightKBController.h" +#include "RGBController_MSIMysticLightKB.h" + +#define MSI_USB_VID 0x1462 + +/*----------------------------------------------------------*\ +| | +| DetectMSIKeyboardController | +| | +| Detect MSI Mystic Light MS-1565 keyboard | +| | +\*----------------------------------------------------------*/ + +void DetectMSIKeyboardController + ( + hid_device_info* info, + const std::string& /*name*/ + ) +{ + hid_device* dev = hid_open_path(info->path); + if(dev != nullptr) + { + MSIKeyboardController* controller = new MSIKeyboardController(dev, info->path); + RGBController_MSIKeyboard* rgb_controller = new RGBController_MSIKeyboard(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR_PU("MSI Keyboard MS_1565", DetectMSIKeyboardController, MSI_USB_VID, 0x1601, 0x00FF, 0x01); \ No newline at end of file diff --git a/Controllers/MSIKeyboardController/MSIMysticLightKBController/MSIMysticLightKBController.cpp b/Controllers/MSIKeyboardController/MSIMysticLightKBController/MSIMysticLightKBController.cpp new file mode 100644 index 00000000..c06f8f7c --- /dev/null +++ b/Controllers/MSIKeyboardController/MSIMysticLightKBController/MSIMysticLightKBController.cpp @@ -0,0 +1,128 @@ +/*---------------------------------------------------------*\ +| MSIMysticLightKBController.cpp | +| | +| Driver for MSI Mystic Light MS-1565 keyboard leds | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "MSIMysticLightKBController.h" + +#include "StringUtils.h" +#include "hidapi.h" +#include + +std::map zone_map = +{ + { MS_1565_ZONE_1, 1 }, + { MS_1565_ZONE_2, 2 }, + { MS_1565_ZONE_3, 4 }, + { MS_1565_ZONE_4, 8 }, + { MS_1565_ZONE_DEVICE, 15} +}; + +MSIKeyboardController::MSIKeyboardController +( + hid_device *handle, + const char *path +) +{ + dev = handle; + if(dev) + { + location = path; + } +} + +MSIKeyboardController::~MSIKeyboardController() +{ + hid_close(dev); +} + +void MSIKeyboardController::SetMode +( + MS_1565_MODE mode, + MS_1565_SPEED speed1, + MS_1565_SPEED speed2, + MS_1565_WAVE_DIRECTION wave_dir, + MS_1565_ZONE zone, + ColorKeyFrame color_keyframes[] +) +{ + unsigned char buf[64] = {}; + buf[0] = 0x02; + buf[1] = 0x01; + buf[2] = zone_map[zone]; + hid_send_feature_report(dev, buf, sizeof(buf)); + + FeaturePacket_MS1565 data; + data.mode = (unsigned char)(mode); + for(int i = 0; i < MAX_MS_1565_KEYFRAMES; i++) + { + data.color_keyframes[i] = color_keyframes[i]; + } + data.speed2 = speed2; + data.speed1 = speed1; + + data.wave_dir = (unsigned char)(wave_dir); + /*-----------------------------------------------------*\ + | Send packet to hardware, return true if successful | + \*-----------------------------------------------------*/ + hid_send_feature_report(dev, (unsigned char *)&data, sizeof(data)); + return; +} + +std::string MSIKeyboardController::GetDeviceName() +{ + wchar_t tname[256]; + + /*-----------------------------------------------------*\ + | Get the manufacturer string from HID | + \*-----------------------------------------------------*/ + hid_get_manufacturer_string(dev, tname, 256); + + /*-----------------------------------------------------*\ + | Convert to std::string | + \*-----------------------------------------------------*/ + std::string name = StringUtils::wstring_to_string(tname); + + /*-----------------------------------------------------*\ + | Get the product string from HID | + \*-----------------------------------------------------*/ + hid_get_product_string(dev, tname, 256); + + /*-----------------------------------------------------*\ + | Append the product string to the manufacturer string | + \*-----------------------------------------------------*/ + name.append(" ").append(StringUtils::wstring_to_string(tname)); + + return(name); +} + +std::string MSIKeyboardController::GetFWVersion() +{ + /*-----------------------------------------------------*\ + | This device doesn't support firmware version | + \*-----------------------------------------------------*/ + std::string firmware_version = ""; + return firmware_version; +} + +std::string MSIKeyboardController::GetDeviceLocation() +{ + return ("HID: " + location); +} + +std::string MSIKeyboardController::GetSerial() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} diff --git a/Controllers/MSIKeyboardController/MSIMysticLightKBController/MSIMysticLightKBController.h b/Controllers/MSIKeyboardController/MSIMysticLightKBController/MSIMysticLightKBController.h new file mode 100644 index 00000000..ddee81c4 --- /dev/null +++ b/Controllers/MSIKeyboardController/MSIMysticLightKBController/MSIMysticLightKBController.h @@ -0,0 +1,111 @@ +/*---------------------------------------------------------*\ +| MSIMysticLight1565Controller.h | +| | +| Driver for MSI Mystic Light MS-1565 keyboard leds | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#ifndef MSIMYSTICLIGHTKBCONTROLLER_H +#define MSIMYSTICLIGHTKBCONTROLLER_H + +#include +#include +#include +#include + +struct Color +{ + unsigned char R; + unsigned char G; + unsigned char B; +}; + +struct ColorKeyFrame +{ + unsigned char time_frame = 0x00; + Color color; +}; + +#define MAX_MS_1565_KEYFRAMES 10 + +typedef unsigned char MS_1565_SPEED; + +// 64 bytes long feature +struct FeaturePacket_MS1565 +{ + unsigned char report_id = 0x02; // Report ID + unsigned char packet_id = 0x02; + unsigned char mode = 0x00; + unsigned char speed2 = 0x00; // Seconds X 100 = duration of animation cycle + unsigned char speed1 = 0x00; // In little endian + // 1 second => 100 = 0x0064, speed2 = 0x64, speed1 = 0x00 + const unsigned char unused = 0x00; + const unsigned char unused2 = 0x00; + const unsigned char unused3 = 0x0F; + const unsigned char unused4 = 0x01; + unsigned char wave_dir = 0x00; + ColorKeyFrame color_keyframes[MAX_MS_1565_KEYFRAMES] = {}; + const unsigned char padding[14] = {}; //pad to make the packet size 64 bytes +}; + +enum MS_1565_MODE +{ + MS_1565_OFF = 0, + MS_1565_STEADY = 1, + MS_1565_BREATHING = 2, + MS_1565_CYCLE = 3, + MS_1565_WAVE = 4, +}; + +enum MS_1565_WAVE_DIRECTION +{ + MS_1565_WAVE_DIRECTION_RIGHT_TO_LEFT = 0, + MS_1565_WAVE_DIRECTION_LEFT_TO_RIGHT = 1 +}; + +enum MS_1565_ZONE +{ + MS_1565_ZONE_1 = 1, + MS_1565_ZONE_2, + MS_1565_ZONE_3, + MS_1565_ZONE_4, + MS_1565_ZONE_DEVICE +}; + +class MSIKeyboardController +{ +public: + MSIKeyboardController + ( + hid_device* handle, + const char* path + ); + ~MSIKeyboardController(); + + void SetMode + ( + MS_1565_MODE mode, + MS_1565_SPEED speed1, + MS_1565_SPEED speed2, + MS_1565_WAVE_DIRECTION wave_dir, + MS_1565_ZONE zone, + ColorKeyFrame color_keyframes[] + ); + + + std::string GetDeviceName(); + std::string GetDeviceLocation(); + std::string GetFWVersion(); + std::string GetSerial(); + + std::vector mode_zones; + +private: + hid_device* dev; + std::string location; +}; + + +#endif // MSIMYSTICLIGHTKBCONTROLLER_H diff --git a/Controllers/MSIKeyboardController/MSIMysticLightKBController/RGBController_MSIMysticLightKB.cpp b/Controllers/MSIKeyboardController/MSIMysticLightKBController/RGBController_MSIMysticLightKB.cpp new file mode 100644 index 00000000..9536e6cd --- /dev/null +++ b/Controllers/MSIKeyboardController/MSIMysticLightKBController/RGBController_MSIMysticLightKB.cpp @@ -0,0 +1,203 @@ +/*---------------------------------------------------------*\ +| RGBController_MSIMysticLightKB.cpp | +| | +| Driver for MSI Mystic Light MS-1565 keyboard leds | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_MSIMysticLightKB.h" +#include "MSIMysticLightKBController.h" +#include "RGBController.h" + +#include + +/**------------------------------------------------------------------*\ + @name MSI MS-1565 Mystic Light Keyboard (64 Byte) + @category Keyboard + @type USB + @save :robot: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectMSIMysticLight1565Controller + @comment +\*-------------------------------------------------------------------*/ + +RGBController_MSIKeyboard::RGBController_MSIKeyboard +( + MSIKeyboardController *controller_ptr +) +{ + controller = controller_ptr; + name = controller->GetDeviceName(); + vendor = "MSI"; + type = DEVICE_TYPE_KEYBOARD; + description = "MSI Mystic Light MS-1565"; + version = controller->GetFWVersion(); + location = controller->GetDeviceLocation(); + serial = controller->GetSerial(); + SetupModes(); + SetupColors(); +} + +RGBController_MSIKeyboard::~RGBController_MSIKeyboard() +{ + delete controller; +} + +void RGBController_MSIKeyboard::ResizeZone +( + int /*zone*/, + int /*new_size*/ +) +{ +} + +void RGBController_MSIKeyboard::SetupZones() +{ +} + +void RGBController_MSIKeyboard::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} + +void RGBController_MSIKeyboard::DeviceUpdateLEDs() +{ + mode &Mode = modes[active_mode]; + MS_1565_MODE msi_mode = (MS_1565_MODE)Mode.value; + MS_1565_ZONE zone = controller->mode_zones[active_mode]; + + /*----------------------------------*\ + | speed is cycle duration in 1/100s | + | Mode.speed = 0 % => speed = 12.00s | + | Mode.speed = 50 % => speed = 7.50s | + | Mode.speed = 100 % => speed = 3.00 | + \*--------------------------------- */ + + unsigned int speed = 1200 - 9 * Mode.speed; + unsigned char speed2 = (unsigned char)(speed & 0xFF); + unsigned char speed1 = (unsigned char)((speed & 0xFF00) >> 8); + + MS_1565_WAVE_DIRECTION wave_direction = (MS_1565_WAVE_DIRECTION)(Mode.direction); + + const size_t colors_size = Mode.colors.size(); + + ColorKeyFrame ck[MAX_MS_1565_KEYFRAMES] = {}; + + for(size_t idx = 0; idx < colors_size; idx++) + { + ck[idx].time_frame = idx * 100 / colors_size; + ck[idx].color.R = RGBGetRValue(Mode.colors[idx]) * Mode.brightness / 100; + ck[idx].color.G = RGBGetGValue(Mode.colors[idx]) * Mode.brightness / 100; + ck[idx].color.B = RGBGetBValue(Mode.colors[idx]) * Mode.brightness / 100; + } + ck[colors_size].time_frame = 100; + ck[colors_size].color.R = RGBGetRValue(Mode.colors[0]) * Mode.brightness / 100; + ck[colors_size].color.G = RGBGetGValue(Mode.colors[0]) * Mode.brightness / 100; + ck[colors_size].color.B = RGBGetBValue(Mode.colors[0]) * Mode.brightness / 100; + + controller->SetMode(msi_mode, speed1, speed2, wave_direction, zone, ck); +} + +void RGBController_MSIKeyboard::UpdateZoneLEDs(int /*zone*/) +{ +} + +void RGBController_MSIKeyboard::UpdateSingleLED(int /*led*/) +{ +} + +void RGBController_MSIKeyboard::SetupModes() +{ + SetupZonesMode("Off", MS_1565_MODE::MS_1565_OFF, 0); + SetupZonesMode("Static", MS_1565_MODE::MS_1565_STEADY, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_BRIGHTNESS); + SetupZonesMode("Breathing", MS_1565_MODE::MS_1565_BREATHING, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_SPEED | + MODE_FLAG_HAS_BRIGHTNESS); + SetupZonesMode("Color Cycle", MS_1565_MODE::MS_1565_CYCLE, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_SPEED | + MODE_FLAG_HAS_BRIGHTNESS); + SetupZonesMode("Wave", MS_1565_MODE::MS_1565_WAVE, MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | + MODE_FLAG_HAS_SPEED | + MODE_FLAG_HAS_BRIGHTNESS | + MODE_FLAG_HAS_DIRECTION_LR); +} + +void RGBController_MSIKeyboard::SetupMode +( + const std::string name, + MS_1565_MODE mod, + unsigned int flags, + MS_1565_ZONE zone +) +{ + mode Mode; + Mode.name = name; + Mode.value = mod; + Mode.flags = flags; + + if(Mode.value == MS_1565_MODE::MS_1565_OFF) + { + Mode.color_mode= MODE_COLORS_NONE; + Mode.colors_min = 0; + Mode.colors_max = 0; + Mode.colors.resize(1); + modes.push_back(Mode); + controller->mode_zones.push_back(zone); + return; + } + + if(flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR) + { + Mode.color_mode= MODE_COLORS_MODE_SPECIFIC; + Mode.colors_min = 1; + if(Mode.value == MS_1565_MODE::MS_1565_STEADY) + { + Mode.colors_max = 1; + } + else + { + Mode.colors_max = MAX_MS_1565_KEYFRAMES - 1; + } + Mode.colors.resize(Mode.colors_max); + } + + if(flags & MODE_FLAG_HAS_SPEED) + { + Mode.speed_min = 0; + Mode.speed_max = 100; + Mode.speed = 50; + } + + if(flags & MODE_FLAG_HAS_BRIGHTNESS) + { + Mode.brightness_min = 0; + Mode.brightness_max = 100; + } + Mode.brightness = 100; + + if(flags & MODE_FLAG_HAS_DIRECTION_LR) + { + Mode.direction = 0; + } + + modes.push_back(Mode); + controller->mode_zones.push_back(zone); +} + +void RGBController_MSIKeyboard::SetupZonesMode +( + const std::string name, + MS_1565_MODE mod, + unsigned int flags +) +{ + SetupMode(name, mod, flags, MS_1565_ZONE_DEVICE); + for(int idx = 0; idx < 4; idx++) + { + SetupMode(name + " zone " + std::to_string(idx + 1), mod, flags, MS_1565_ZONE(idx + 1)); + } +} diff --git a/Controllers/MSIKeyboardController/MSIMysticLightKBController/RGBController_MSIMysticLightKB.h b/Controllers/MSIKeyboardController/MSIMysticLightKBController/RGBController_MSIMysticLightKB.h new file mode 100644 index 00000000..6636e893 --- /dev/null +++ b/Controllers/MSIKeyboardController/MSIMysticLightKBController/RGBController_MSIMysticLightKB.h @@ -0,0 +1,50 @@ +/*---------------------------------------------------------*\ +| RGBController_MSIMysticLight1565.h | +| | +| Driver for MSI Mystic Light MS-1565 keyboard leds | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#ifndef RGBCONTROLLER_MSIMYSTICLIGHTKB_H +#define RGBCONTROLLER_MSIMYSTICLIGHTKB_H + +#include "RGBController.h" +#include "MSIMysticLightKBController.h" + +class RGBController_MSIKeyboard : public RGBController +{ +public: + RGBController_MSIKeyboard(MSIKeyboardController* controller_ptr); + ~RGBController_MSIKeyboard(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + MSIKeyboardController* controller; + + void SetupModes(); + void SetupMode + ( + const std::string name, + MS_1565_MODE mode, + unsigned int flags, + MS_1565_ZONE zone + ); + void SetupZonesMode + ( + const std::string name, + MS_1565_MODE mod, + unsigned int flags + ); +}; + +#endif // RGBCONTROLLER_MSIMYSTICLIGHTKB_H diff --git a/Controllers/MSIMysticLightController/MSIMysticLight112Controller.cpp b/Controllers/MSIMysticLightController/MSIMysticLight112Controller/MSIMysticLight112Controller.cpp similarity index 86% rename from Controllers/MSIMysticLightController/MSIMysticLight112Controller.cpp rename to Controllers/MSIMysticLightController/MSIMysticLight112Controller/MSIMysticLight112Controller.cpp index 35fa0ca0..699567df 100644 --- a/Controllers/MSIMysticLightController/MSIMysticLight112Controller.cpp +++ b/Controllers/MSIMysticLightController/MSIMysticLight112Controller/MSIMysticLight112Controller.cpp @@ -1,21 +1,22 @@ -/*-----------------------------------------*\ -| MSIMysticLight112Controller.cpp | -| | -| Driver for MSI Mystic Light (112-byte) | -| USB lighting controller | -| | -| thombo 12/17/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| MSIMysticLight112Controller.cpp | +| | +| Driver for MSI Mystic Light 112-byte motherboard | +| | +| thombo 17 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "MSIMysticLight112Controller.h" #include #include #include - +#include "MSIMysticLight112Controller.h" +#include "StringUtils.h" #define BITSET(val, bit, pos) ((unsigned char)std::bitset<8>(val).set((pos), (bit)).to_ulong()) - struct Config { unsigned short pid; // PID of the board @@ -31,21 +32,19 @@ const std::vector zones_set = MSI_ZONE_ON_BOARD_LED_0 }; - MSIMysticLight112Controller::MSIMysticLight112Controller ( hid_device* handle, - const char *path + const char* path, + std::string dev_name ) { - dev = handle; + dev = handle; + location = path; + name = dev_name; if(dev) { - location = path; - - ReadName(); - ReadSerial(); ReadFwVersion(); ReadSettings(); } @@ -158,7 +157,15 @@ std::string MSIMysticLight112Controller::GetDeviceLocation() std::string MSIMysticLight112Controller::GetSerial() { - return chip_id; + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } bool MSIMysticLight112Controller::ReadSettings() @@ -377,49 +384,6 @@ bool MSIMysticLight112Controller::ReadFwVersion() return(ret_val > 0); } -void MSIMysticLight112Controller::ReadSerial() -{ - wchar_t serial[256]; - - /*-----------------------------------------------------*\ - | Get the serial number string from HID | - \*-----------------------------------------------------*/ - hid_get_serial_number_string(dev, serial, 256); - - /*-----------------------------------------------------*\ - | Convert wchar_t into std::wstring into std::string | - \*-----------------------------------------------------*/ - std::wstring wserial = std::wstring(serial); - chip_id = std::string(wserial.begin(), wserial.end()); -} - -void MSIMysticLight112Controller::ReadName() -{ - wchar_t tname[256]; - - /*-----------------------------------------------------*\ - | Get the manufacturer string from HID | - \*-----------------------------------------------------*/ - hid_get_manufacturer_string(dev, tname, 256); - - /*-----------------------------------------------------*\ - | Convert wchar_t into std::wstring into std::string | - \*-----------------------------------------------------*/ - std::wstring wname = std::wstring(tname); - name = std::string(wname.begin(), wname.end()); - - /*-----------------------------------------------------*\ - | Get the product string from HID | - \*-----------------------------------------------------*/ - hid_get_product_string(dev, tname, 256); - - /*-----------------------------------------------------*\ - | Append the product string to the manufacturer string | - \*-----------------------------------------------------*/ - wname = std::wstring(tname); - name.append(" ").append(std::string(wname.begin(), wname.end())); -} - MSI_MODE MSIMysticLight112Controller::GetMode() { return (MSI_MODE)data.on_board_led.effect; diff --git a/Controllers/MSIMysticLightController/MSIMysticLight112Controller.h b/Controllers/MSIMysticLightController/MSIMysticLight112Controller/MSIMysticLight112Controller.h similarity index 78% rename from Controllers/MSIMysticLightController/MSIMysticLight112Controller.h rename to Controllers/MSIMysticLightController/MSIMysticLight112Controller/MSIMysticLight112Controller.h index 7997de7f..3e5e1ca7 100644 --- a/Controllers/MSIMysticLightController/MSIMysticLight112Controller.h +++ b/Controllers/MSIMysticLightController/MSIMysticLight112Controller/MSIMysticLight112Controller.h @@ -1,28 +1,32 @@ -/*-----------------------------------------*\ -| MSIMysticLight112Controller.h | -| | -| Definitions and types for MSI Mystic | -| Light (112-byte) USB lighting controllers| -| | -| thombo 12/17/2022 | -\*-----------------------------------------*/ - -#include "MSIMysticLightCommon.h" -#include "RGBController.h" -#include -#include -#include +/*---------------------------------------------------------*\ +| MSIMysticLight112Controller.h | +| | +| Driver for MSI Mystic Light 112-byte motherboard | +| | +| thombo 17 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include +#include "MSIMysticLightCommon.h" +#include "RGBController.h" + class MSIMysticLight112Controller { public: MSIMysticLight112Controller - ( - hid_device* handle, - const char *path - ); + ( + hid_device* handle, + const char* path, + std::string dev_name + ); + ~MSIMysticLight112Controller(); void SetMode @@ -75,37 +79,34 @@ public: std::string GetFWVersion(); std::string GetSerial(); - void SetDirectMode ( bool mode ); + bool IsDirectModeActive() { return direct_mode; } size_t GetMaxOnboardLeds(); const std::vector* GetSupportedZones() { return supported_zones; } private: - bool ReadSettings(); - bool ReadFwVersion(); - void ReadSerial(); - void ReadName(); - ZoneData* GetZoneData - ( - FeaturePacket_112& dataPacket, - MSI_ZONE zone - ); - hid_device* dev; std::string name; std::string location; std::string version_APROM; std::string version_LDROM; - std::string chip_id; FeaturePacket_112 data; FeaturePacket_112 zone_based_per_led_data; bool direct_mode; size_t numof_onboard_leds; const std::vector* supported_zones; + + bool ReadSettings(); + bool ReadFwVersion(); + ZoneData* GetZoneData + ( + FeaturePacket_112& dataPacket, + MSI_ZONE zone + ); }; diff --git a/Controllers/MSIMysticLightController/RGBController_MSIMysticLight112.cpp b/Controllers/MSIMysticLightController/MSIMysticLight112Controller/RGBController_MSIMysticLight112.cpp similarity index 94% rename from Controllers/MSIMysticLightController/RGBController_MSIMysticLight112.cpp rename to Controllers/MSIMysticLightController/MSIMysticLight112Controller/RGBController_MSIMysticLight112.cpp index d8d2bb7b..90424690 100644 --- a/Controllers/MSIMysticLightController/RGBController_MSIMysticLight112.cpp +++ b/Controllers/MSIMysticLightController/MSIMysticLight112Controller/RGBController_MSIMysticLight112.cpp @@ -1,15 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_MSIMysticLight112.cpp | -| | -| Generic RGB Interface for OpenRGB | -| MSI Mystic Light (112-byte) USB Driver | -| | -| thombo 12/17/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_MSIMysticLight112.cpp | +| | +| RGBController for MSI Mystic Light 112-byte motherboard | +| | +| thombo 17 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_MSIMysticLight112.h" - struct ZoneDescription { std::string name; @@ -26,11 +27,8 @@ const ZoneDescription led_zones[] = ZoneDescription{ "Onboard LEDs", MSI_ZONE_ON_BOARD_LED_0 } }; - static std::vector zone_description; - - /**------------------------------------------------------------------*\ @name MSI Mystic Light (112 Byte) @category Motherboard @@ -47,7 +45,7 @@ RGBController_MSIMysticLight112::RGBController_MSIMysticLight112 MSIMysticLight112Controller* controller_ptr ) { - controller = controller_ptr; + controller = controller_ptr; name = controller->GetDeviceName(); vendor = "MSI"; diff --git a/Controllers/MSIMysticLightController/MSIMysticLight112Controller/RGBController_MSIMysticLight112.h b/Controllers/MSIMysticLightController/MSIMysticLight112Controller/RGBController_MSIMysticLight112.h new file mode 100644 index 00000000..c8cac39a --- /dev/null +++ b/Controllers/MSIMysticLightController/MSIMysticLight112Controller/RGBController_MSIMysticLight112.h @@ -0,0 +1,50 @@ +/*---------------------------------------------------------*\ +| RGBController_MSIMysticLight112.h | +| | +| RGBController for MSI Mystic Light 112-byte motherboard | +| | +| thombo 17 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "MSIMysticLight112Controller.h" + +class RGBController_MSIMysticLight112: public RGBController +{ +public: + RGBController_MSIMysticLight112(MSIMysticLight112Controller* controller_ptr); + ~RGBController_MSIMysticLight112(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + MSIMysticLight112Controller* controller; + + void SetupModes(); + void UpdateLed + ( + int zone, + int led + ); + void SetupMode + ( + const char *name, + MSI_MODE mode, + unsigned int flags + ); + int GetDeviceMode(); + void GetDeviceConfig(); +}; diff --git a/Controllers/MSIMysticLightController/MSIMysticLight162Controller.cpp b/Controllers/MSIMysticLightController/MSIMysticLight162Controller.cpp deleted file mode 100644 index f58d03cb..00000000 --- a/Controllers/MSIMysticLightController/MSIMysticLight162Controller.cpp +++ /dev/null @@ -1,561 +0,0 @@ -/*-----------------------------------------*\ -| MSIMysticLight162Controller.cpp | -| | -| Driver for MSI Mystic Light (162-byte) | -| USB lighting controller | -| | -| T-bond 3/4/2020 | -| Adam Honse 3/6/2021 | -\*-----------------------------------------*/ - -#include "MSIMysticLight162Controller.h" -#include -#include -#include - - -#define BITSET(val, bit, pos) ((unsigned char)std::bitset<8>(val).set((pos), (bit)).to_ulong()) - - -struct Config -{ - unsigned short pid; // PID of the board - size_t numof_onboard_leds; // number of onboard leds - const std::vector* supported_zones; // pointer to vector of supported zones -}; - -const std::vector zones_set0 = -{ - MSI_ZONE_J_RGB_1, - MSI_ZONE_J_RGB_2, - MSI_ZONE_J_RAINBOW_1, - MSI_ZONE_J_CORSAIR, - MSI_ZONE_ON_BOARD_LED_0 -}; - -const std::vector zones_set1 = -{ - MSI_ZONE_J_RGB_1, - MSI_ZONE_J_RGB_2, - MSI_ZONE_J_RAINBOW_1, - MSI_ZONE_ON_BOARD_LED_0 -}; - -const std::vector zones_set2 = -{ - MSI_ZONE_J_RGB_1, - MSI_ZONE_J_RGB_2, - MSI_ZONE_J_RAINBOW_1, - MSI_ZONE_J_RAINBOW_2, - MSI_ZONE_ON_BOARD_LED_0 -}; - -const std::vector zones_set3 = -{ - MSI_ZONE_J_RAINBOW_1, - MSI_ZONE_ON_BOARD_LED_0 -}; - - -/*-----------------------------------------------------------------------------------------------------------------------------*\ -| Definition of the board sepcific configurations (number of onboard LEDs and supported zones). | -| | -| Only tested boards are listed here (refer to MSIMysticLightControllerDetect.cpp). If more boards | -| are tested the list must be extended here. Otherwise the default settings will be used (7 onboard LEDs, all zones supported). | -| Boards with yet unknown supported zones are configured to support all zones. | -\*-----------------------------------------------------------------------------------------------------------------------------*/ - -#define NUMOF_CONFIGS (sizeof(board_configs) / sizeof(Config)) - -static const Config board_configs[] = -{ - { 0x1720, 10, &zones_set0 }, // MPG Z390 GAMING EDGE AC - { 0x7B12, 10, &zones_set0 }, // MEG Z390 ACE - { 0x7B17, 10, &zones_set0 }, // MPG Z390 GAMING PRO CARBON - { 0x7B18, 6, &zones_set1 }, // MAG Z390 TOMAHAWK - { 0x7B50, 6, &zones_set2 }, // MPG Z390M GAMING EDGE AC - { 0x7B85, 7, &zones_set0 }, // B450 GAMING PRO CARBON - { 0xB926, 3, &zones_set3 }, // MPG B460 TRIDENT AS -}; - - -MSIMysticLight162Controller::MSIMysticLight162Controller - ( - hid_device* handle, - const char *path, - unsigned short pid - ) -{ - dev = handle; - - if(dev) - { - location = path; - - ReadName(); - ReadSerial(); - ReadFwVersion(); - ReadSettings(); - } - - /*-----------------------------------------*\ - | Initialize save flag | - \*-----------------------------------------*/ - data.save_data = 0; - data.on_board_led.colorFlags = 0x81; // force MS bit of color flags to 1 to have expectd zone control - - /*-----------------------------------------*\ - | Initialize zone based per LED data | - \*-----------------------------------------*/ - const Config* board_config = nullptr; - - for(std::size_t i = 0; i < NUMOF_CONFIGS; ++i) - { - if (board_configs[i].pid == pid) - { - board_config = &board_configs[i]; - break; - } - } - - if(board_config != nullptr) - { - numof_onboard_leds = board_config->numof_onboard_leds; - supported_zones = board_config->supported_zones; - } - else - { - numof_onboard_leds = 10; - supported_zones = &zones_set0; - } - - zone_based_per_led_data.j_rgb_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2; - zone_based_per_led_data.j_rgb_1.colorFlags = BITSET(zone_based_per_led_data.j_rgb_1.colorFlags, true, 7u); - zone_based_per_led_data.j_rainbow_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2; - zone_based_per_led_data.j_rainbow_1.colorFlags = BITSET(zone_based_per_led_data.j_rainbow_1.colorFlags, true, 7u); - zone_based_per_led_data.on_board_led.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2; - zone_based_per_led_data.on_board_led.colorFlags = BITSET(zone_based_per_led_data.on_board_led.colorFlags, true, 7u); - zone_based_per_led_data.on_board_led_1.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2; - zone_based_per_led_data.on_board_led_1.colorFlags = BITSET(zone_based_per_led_data.on_board_led_1.colorFlags, true, 7u); - zone_based_per_led_data.on_board_led_2.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2; - zone_based_per_led_data.on_board_led_2.colorFlags = BITSET(zone_based_per_led_data.on_board_led_2.colorFlags, true, 7u); - zone_based_per_led_data.on_board_led_3.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2; - zone_based_per_led_data.on_board_led_3.colorFlags = BITSET(zone_based_per_led_data.on_board_led_3.colorFlags, true, 7u); - zone_based_per_led_data.on_board_led_4.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2; - zone_based_per_led_data.on_board_led_4.colorFlags = BITSET(zone_based_per_led_data.on_board_led_4.colorFlags, true, 7u); - zone_based_per_led_data.on_board_led_5.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2; - zone_based_per_led_data.on_board_led_5.colorFlags = BITSET(zone_based_per_led_data.on_board_led_5.colorFlags, true, 7u); - zone_based_per_led_data.on_board_led_6.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2 << 2; - zone_based_per_led_data.on_board_led_6.colorFlags = BITSET(zone_based_per_led_data.on_board_led_6.colorFlags, true, 7u); - zone_based_per_led_data.on_board_led_7.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100; - zone_based_per_led_data.on_board_led_7.colorFlags = BITSET(zone_based_per_led_data.on_board_led_7.colorFlags, true, 7u); - zone_based_per_led_data.on_board_led_8.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2; - zone_based_per_led_data.on_board_led_8.colorFlags = BITSET(zone_based_per_led_data.on_board_led_8.colorFlags, true, 7u); - zone_based_per_led_data.on_board_led_9.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2; - zone_based_per_led_data.on_board_led_9.colorFlags = BITSET(zone_based_per_led_data.on_board_led_9.colorFlags, true, 7u); - zone_based_per_led_data.on_board_led_10.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2; - zone_based_per_led_data.on_board_led_10.colorFlags = BITSET(zone_based_per_led_data.on_board_led_9.colorFlags, true, 7u); - zone_based_per_led_data.j_rgb_2.speedAndBrightnessFlags = MSI_BRIGHTNESS_LEVEL_100 << 2; - zone_based_per_led_data.j_rgb_2.colorFlags = BITSET(zone_based_per_led_data.j_rgb_2.colorFlags, true, 7u); - zone_based_per_led_data.save_data = 0; - - direct_mode = false; -} - -MSIMysticLight162Controller::~MSIMysticLight162Controller() -{ - hid_close(dev); -} - -void MSIMysticLight162Controller::SetMode - ( - MSI_ZONE zone, - MSI_MODE mode, - MSI_SPEED speed, - MSI_BRIGHTNESS brightness, - bool rainbow_color - ) -{ - ZoneData* zone_data = GetZoneData(data, zone); - - if(zone_data == nullptr) - { - return; - } - - if (zone <= MSI_ZONE_ON_BOARD_LED_0) - { - zone_data->effect = mode; - zone_data->speedAndBrightnessFlags = (brightness << 2) | (speed & 0x03); - zone_data->colorFlags = BITSET(zone_data->colorFlags, !rainbow_color, 7u); - zone_data->padding = 0x00; - - if(mode > MSI_MODE_DOUBLE_FLASHING) - { - zone_data->speedAndBrightnessFlags |= SYNC_SETTING_JRGB; - zone_data->colorFlags |= SYNC_SETTING_ONBOARD; - } - else - { - zone_data->speedAndBrightnessFlags &= ~SYNC_SETTING_JRGB; - zone_data->colorFlags &= ~SYNC_SETTING_ONBOARD; - } - } - - if((zone >= MSI_ZONE_ON_BOARD_LED_0) && (mode <= MSI_MODE_DOUBLE_FLASHING)) - { - zone_data = GetZoneData(data, (MSI_ZONE)((int)zone + 1)); - - if(zone_data != nullptr) - { - zone_data->effect = mode; - zone_data->speedAndBrightnessFlags = (brightness << 2) | (speed & 0x03); - zone_data->colorFlags = BITSET(zone_data->colorFlags, !rainbow_color, 7u); - zone_data->padding = 0x00; - } - } -} - -std::string MSIMysticLight162Controller::GetDeviceName() -{ - return name; -} - -std::string MSIMysticLight162Controller::GetFWVersion() -{ - std::string firmware_version; - firmware_version = "APROM: " + version_APROM + ", LDROM: " + version_LDROM; - return firmware_version; -} - -std::string MSIMysticLight162Controller::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string MSIMysticLight162Controller::GetSerial() -{ - return chip_id; -} - -bool MSIMysticLight162Controller::ReadSettings() -{ - /*-----------------------------------------------------*\ - | Read packet from hardware, return true if successful | - \*-----------------------------------------------------*/ - return(hid_get_feature_report(dev, (unsigned char*)&data, sizeof(data)) == sizeof data); -} - -bool MSIMysticLight162Controller::Update - ( - bool save - ) -{ - /*-----------------------------------------------------*\ - | Send packet to hardware, return true if successful | - \*-----------------------------------------------------*/ - if(direct_mode) - { - return (hid_send_feature_report(dev, (unsigned char*)&zone_based_per_led_data, sizeof(zone_based_per_led_data)) == sizeof(zone_based_per_led_data)); - } - else - { - data.save_data = save; - return (hid_send_feature_report(dev, (unsigned char*)&data, sizeof(data)) == sizeof(data)); - } -} - -void MSIMysticLight162Controller::SetZoneColor - ( - MSI_ZONE zone, - unsigned char red1, - unsigned char grn1, - unsigned char blu1, - unsigned char red2, - unsigned char grn2, - unsigned char blu2 - ) -{ - ZoneData* zone_data = GetZoneData(data, zone); - - if(zone_data == nullptr) - { - return; - } - - if (zone <= MSI_ZONE_ON_BOARD_LED_0) - { - zone_data->color.R = red1; - zone_data->color.G = grn1; - zone_data->color.B = blu1; - zone_data->color2.R = red2; - zone_data->color2.G = grn2; - zone_data->color2.B = blu2; - } - - if(zone >= MSI_ZONE_ON_BOARD_LED_0) - { - zone_data = GetZoneData(data, (MSI_ZONE)((int)zone + 1)); - - if(zone_data != nullptr) - { - zone_data->color.R = red1; - zone_data->color.G = grn1; - zone_data->color.B = blu1; - zone_data->color2.R = red2; - zone_data->color2.G = grn2; - zone_data->color2.B = blu2; - } - } -} - -void MSIMysticLight162Controller::SetLedColor - ( - MSI_ZONE zone, - unsigned char red, - unsigned char grn, - unsigned char blu - ) -{ - if(zone >= MSI_ZONE_ON_BOARD_LED_0) - { - zone = (MSI_ZONE)((int)zone + 1); - } - - ZoneData *zone_data = GetZoneData(zone_based_per_led_data, zone); - - if(zone_data == nullptr) - { - return; - } - - zone_data->color.R = red; - zone_data->color.G = grn; - zone_data->color.B = blu; - zone_data->color2.R = red; - zone_data->color2.G = grn; - zone_data->color2.B = blu; -} - -ZoneData *MSIMysticLight162Controller::GetZoneData - ( - FeaturePacket_162& data_packet, - MSI_ZONE zone - ) -{ - switch(zone) - { - case MSI_ZONE_J_RGB_1: - return &data_packet.j_rgb_1; - case MSI_ZONE_J_RGB_2: - return &data_packet.j_rgb_2; - case MSI_ZONE_J_RAINBOW_1: - return &data_packet.j_rainbow_1; - case MSI_ZONE_J_RAINBOW_2: - return &data_packet.on_board_led_10; - case MSI_ZONE_ON_BOARD_LED_0: - return &data_packet.on_board_led; - case MSI_ZONE_ON_BOARD_LED_1: - return &data_packet.on_board_led_1; - case MSI_ZONE_ON_BOARD_LED_2: - return &data_packet.on_board_led_2; - case MSI_ZONE_ON_BOARD_LED_3: - return &data_packet.on_board_led_3; - case MSI_ZONE_ON_BOARD_LED_4: - return &data_packet.on_board_led_4; - case MSI_ZONE_ON_BOARD_LED_5: - return &data_packet.on_board_led_5; - case MSI_ZONE_ON_BOARD_LED_6: - return &data_packet.on_board_led_6; - case MSI_ZONE_ON_BOARD_LED_7: - return &data_packet.on_board_led_7; - case MSI_ZONE_ON_BOARD_LED_8: - return &data_packet.on_board_led_8; - case MSI_ZONE_ON_BOARD_LED_9: - return &data_packet.on_board_led_9; - case MSI_ZONE_ON_BOARD_LED_10: - return &data_packet.on_board_led_10; - case MSI_ZONE_J_CORSAIR: - return &data_packet.j_corsair_1; - default: - break; - } - - return nullptr; -} - -bool MSIMysticLight162Controller::ReadFwVersion() -{ - unsigned char request[64]; - unsigned char response[64]; - int ret_val = 64; - - /*-----------------------------------------------------*\ - | First read the APROM | - | Checksum also available at report ID 180, with MSB | - | stored at index 0x08 and LSB at 0x09 | - \*-----------------------------------------------------*/ - - /*-----------------------------------------------------*\ - | Zero out buffers | - \*-----------------------------------------------------*/ - memset(request, 0x00, sizeof(request)); - memset(response, 0x00, sizeof(response)); - - /*-----------------------------------------------------*\ - | Set up APROM Firmware Version Request packet | - \*-----------------------------------------------------*/ - request[0x00] = 0x01; - request[0x01] = 0xB0; - - /*-----------------------------------------------------*\ - | Fill request from 0x02 to 0x61 with 0xCC | - \*-----------------------------------------------------*/ - memset(&request[0x02], 0xCC, sizeof(request) - 2); - - /*-----------------------------------------------------*\ - | Send request and receive response packets | - \*-----------------------------------------------------*/ - ret_val &= hid_write(dev, request, 64); - ret_val &= hid_read(dev, response, 64); - - /*-----------------------------------------------------*\ - | Extract high and low values from response | - \*-----------------------------------------------------*/ - unsigned char highValue = response[2] >> 4; - unsigned char lowValue = response[2] & 0x0F; - - /*-----------------------------------------------------*\ - | Build firmware string . | - \*-----------------------------------------------------*/ - version_APROM = std::to_string((int)highValue).append(".").append(std::to_string((int)lowValue)); - - /*-----------------------------------------------------*\ - | First read the LDROM | - | Checksum also available at report ID 184, with MSB | - | stored at index 0x08 and LSB at 0x09 | - \*-----------------------------------------------------*/ - - /*-----------------------------------------------------*\ - | Set up LDROM Firmware Version Request packet | - \*-----------------------------------------------------*/ - request[0x00] = 0x01; - request[0x01] = 0xB6; - - /*-----------------------------------------------------*\ - | Send request and receive response packets | - \*-----------------------------------------------------*/ - ret_val &= hid_write(dev, request, 64); - ret_val &= hid_read(dev, response, 64); - - /*-----------------------------------------------------*\ - | Extract high and low values from response | - \*-----------------------------------------------------*/ - highValue = response[2] >> 4; - lowValue = response[2] & 0x0F; - - /*-----------------------------------------------------*\ - | Build firmware string . | - \*-----------------------------------------------------*/ - version_LDROM = std::to_string((int)highValue).append(".").append(std::to_string((int)lowValue)); - - /*-----------------------------------------------------*\ - | If return value is zero it means an HID transfer | - | failed | - \*-----------------------------------------------------*/ - return(ret_val > 0); -} - -void MSIMysticLight162Controller::ReadSerial() -{ - wchar_t serial[256]; - - /*-----------------------------------------------------*\ - | Get the serial number string from HID | - \*-----------------------------------------------------*/ - hid_get_serial_number_string(dev, serial, 256); - - /*-----------------------------------------------------*\ - | Convert wchar_t into std::wstring into std::string | - \*-----------------------------------------------------*/ - std::wstring wserial = std::wstring(serial); - chip_id = std::string(wserial.begin(), wserial.end()); -} - -void MSIMysticLight162Controller::ReadName() -{ - wchar_t tname[256]; - - /*-----------------------------------------------------*\ - | Get the manufacturer string from HID | - \*-----------------------------------------------------*/ - hid_get_manufacturer_string(dev, tname, 256); - - /*-----------------------------------------------------*\ - | Convert wchar_t into std::wstring into std::string | - \*-----------------------------------------------------*/ - std::wstring wname = std::wstring(tname); - name = std::string(wname.begin(), wname.end()); - - /*-----------------------------------------------------*\ - | Get the product string from HID | - \*-----------------------------------------------------*/ - hid_get_product_string(dev, tname, 256); - - /*-----------------------------------------------------*\ - | Append the product string to the manufacturer string | - \*-----------------------------------------------------*/ - wname = std::wstring(tname); - name.append(" ").append(std::string(wname.begin(), wname.end())); -} - -MSI_MODE MSIMysticLight162Controller::GetMode() -{ - return (MSI_MODE)data.on_board_led.effect; -} - -void MSIMysticLight162Controller::GetMode - ( - MSI_ZONE zone, - MSI_MODE &mode, - MSI_SPEED &speed, - MSI_BRIGHTNESS &brightness, - bool &rainbow_color, - unsigned int &color - ) -{ - /*-----------------------------------------------------*\ - | Get data for given zone | - \*-----------------------------------------------------*/ - ZoneData *zone_data = GetZoneData(data, zone); - - /*-----------------------------------------------------*\ - | Return if zone is invalid | - \*-----------------------------------------------------*/ - if(zone_data == nullptr) - { - return; - } - - /*-----------------------------------------------------*\ - | Update pointers with data | - \*-----------------------------------------------------*/ - mode = (MSI_MODE)zone_data->effect; - speed = (MSI_SPEED)(zone_data->speedAndBrightnessFlags & 0x03); - brightness = (MSI_BRIGHTNESS)((zone_data->speedAndBrightnessFlags >> 2) & 0x1F); - rainbow_color = (zone_data->colorFlags & 0x80) == 0 ? true : false; - color = ToRGBColor(zone_data->color.R, zone_data->color.G, zone_data->color.B); -} - -void MSIMysticLight162Controller::SetDirectMode - ( - bool mode - ) -{ - direct_mode = mode; -} - -size_t MSIMysticLight162Controller::GetMaxOnboardLeds() -{ - return numof_onboard_leds; -} diff --git a/Controllers/MSIMysticLightController/MSIMysticLight162Controller.h b/Controllers/MSIMysticLightController/MSIMysticLight162Controller.h deleted file mode 100644 index d3e5733d..00000000 --- a/Controllers/MSIMysticLightController/MSIMysticLight162Controller.h +++ /dev/null @@ -1,113 +0,0 @@ -/*-----------------------------------------*\ -| MSIMysticLight162Controller.h | -| | -| Definitions and types for MSI Mystic | -| Light (162-byte) USB lighting controllers| -| | -| T-bond 3/4/2020 | -| Adam Honse 3/6/2021 | -\*-----------------------------------------*/ - -#include "MSIMysticLightCommon.h" -#include "RGBController.h" -#include -#include -#include - -#pragma once - -class MSIMysticLight162Controller -{ -public: - MSIMysticLight162Controller - ( - hid_device* handle, - const char *path, - unsigned short pid - ); - ~MSIMysticLight162Controller(); - - void SetMode - ( - MSI_ZONE zone, - MSI_MODE mode, - MSI_SPEED speed, - MSI_BRIGHTNESS brightness, - bool rainbow_color - ); - - MSI_MODE GetMode(); - - void GetMode - ( - MSI_ZONE zone, - MSI_MODE &mode, - MSI_SPEED &speed, - MSI_BRIGHTNESS &brightness, - bool &rainbow_color, - unsigned int &color - ); - - void SetZoneColor - ( - MSI_ZONE zone, - unsigned char red1, - unsigned char grn1, - unsigned char blu1, - unsigned char red2, - unsigned char grn2, - unsigned char blu2 - ); - - void SetLedColor - ( - MSI_ZONE zone, - unsigned char red, - unsigned char grn, - unsigned char blu - ); - - bool Update - ( - bool save - ); - - std::string GetDeviceName(); - std::string GetDeviceLocation(); - std::string GetFWVersion(); - std::string GetSerial(); - - - void SetDirectMode - ( - bool mode - ); - bool IsDirectModeActive() { return direct_mode; } - size_t GetMaxOnboardLeds(); - const std::vector* - GetSupportedZones() { return supported_zones; } - -private: - bool ReadSettings(); - bool ReadFwVersion(); - void ReadSerial(); - void ReadName(); - ZoneData* GetZoneData - ( - FeaturePacket_162& dataPacket, - MSI_ZONE zone - ); - - hid_device* dev; - std::string name; - std::string location; - std::string version_APROM; - std::string version_LDROM; - std::string chip_id; - - FeaturePacket_162 data; - FeaturePacket_162 zone_based_per_led_data; - bool direct_mode; - size_t numof_onboard_leds; - const std::vector* supported_zones; -}; diff --git a/Controllers/MSIMysticLightController/MSIMysticLight162Controller/MSIMysticLight162Controller.cpp b/Controllers/MSIMysticLightController/MSIMysticLight162Controller/MSIMysticLight162Controller.cpp new file mode 100644 index 00000000..82bfb566 --- /dev/null +++ b/Controllers/MSIMysticLightController/MSIMysticLight162Controller/MSIMysticLight162Controller.cpp @@ -0,0 +1,451 @@ +/*---------------------------------------------------------*\ +| MSIMysticLight162Controller.cpp | +| | +| Driver for MSI Mystic Light 162-byte motherboard | +| | +| T-bond 03 Apr 2020 | +| Adam Honse 06 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include "MSIMysticLight162Controller.h" +#include "StringUtils.h" + +#define BITSET(val, bit, pos) ((unsigned char)std::bitset<8>(val).set((pos), (bit)).to_ulong()) + +struct mystic_light_162_config +{ + unsigned short pid; // PID of the board + size_t numof_onboard_leds; // number of onboard leds + const std::vector* supported_zones; // pointer to vector of supported zones +}; + +const std::vector zones_set0 = +{ + MSI_ZONE_J_RGB_1, + MSI_ZONE_J_RGB_2, + MSI_ZONE_J_RAINBOW_1, + MSI_ZONE_J_CORSAIR, + MSI_ZONE_ON_BOARD_LED_0 +}; + +const std::vector zones_set1 = +{ + MSI_ZONE_J_RGB_1, + MSI_ZONE_J_RGB_2, + MSI_ZONE_J_RAINBOW_1, + MSI_ZONE_ON_BOARD_LED_0 +}; + +const std::vector zones_set2 = +{ + MSI_ZONE_J_RGB_1, + MSI_ZONE_J_RGB_2, + MSI_ZONE_J_RAINBOW_1, + MSI_ZONE_J_RAINBOW_2, + MSI_ZONE_ON_BOARD_LED_0 +}; + +const std::vector zones_set3 = +{ + MSI_ZONE_J_RAINBOW_1, + MSI_ZONE_ON_BOARD_LED_0 +}; + +/*-----------------------------------------------------------------------------------------------------------------------------*\ +| Definition of the board sepcific configurations (number of onboard LEDs and supported zones). | +| | +| Only tested boards are listed here (refer to MSIMysticLightControllerDetect.cpp). If more boards | +| are tested the list must be extended here. Otherwise the default settings will be used (7 onboard LEDs, all zones supported). | +| Boards with yet unknown supported zones are configured to support all zones. | +\*-----------------------------------------------------------------------------------------------------------------------------*/ + +#define NUMOF_CONFIGS (sizeof(board_configs) / sizeof(mystic_light_162_config)) + +static const mystic_light_162_config board_configs[] = +{ + { 0x1720, 10, &zones_set0 }, // MPG Z390 GAMING EDGE AC + { 0x7B12, 10, &zones_set0 }, // MEG Z390 ACE + { 0x7B17, 10, &zones_set0 }, // MPG Z390 GAMING PRO CARBON + { 0x7B18, 6, &zones_set1 }, // MAG Z390 TOMAHAWK + { 0x7B50, 6, &zones_set2 }, // MPG Z390M GAMING EDGE AC + { 0x7B85, 7, &zones_set0 }, // B450 GAMING PRO CARBON + { 0xB926, 3, &zones_set3 }, // MPG B460 TRIDENT AS +}; + + +MSIMysticLight162Controller::MSIMysticLight162Controller + ( + hid_device* handle, + const char* path, + unsigned short pid, + std::string dev_name + ) +{ + dev = handle; + location = path; + name = dev_name; + + if(dev) + { + ReadFwVersion(); + ReadSettings(); + } + + /*-----------------------------------------*\ + | Initialize save flag | + \*-----------------------------------------*/ + data.save_data = 0; + data.on_board_led.colorFlags = 0x81; // force MS bit of color flags to 1 to have expectd zone control + + /*-----------------------------------------*\ + | Initialize zone based per LED data | + \*-----------------------------------------*/ + const mystic_light_162_config* board_config = nullptr; + + for(std::size_t i = 0; i < NUMOF_CONFIGS; ++i) + { + if (board_configs[i].pid == pid) + { + board_config = &board_configs[i]; + break; + } + } + + if(board_config != nullptr) + { + numof_onboard_leds = board_config->numof_onboard_leds; + supported_zones = board_config->supported_zones; + } + else + { + numof_onboard_leds = 10; + supported_zones = &zones_set0; + } + +} + +MSIMysticLight162Controller::~MSIMysticLight162Controller() +{ + hid_close(dev); +} + +void MSIMysticLight162Controller::SetMode + ( + MSI_ZONE zone, + MSI_MODE mode, + MSI_SPEED speed, + MSI_BRIGHTNESS brightness, + bool rainbow_color + ) +{ + ZoneData* zone_data = GetZoneData(data, zone); + + if(zone_data == nullptr) + { + return; + } + + if (zone <= MSI_ZONE_ON_BOARD_LED_0) + { + zone_data->effect = mode; + zone_data->speedAndBrightnessFlags = (brightness << 2) | (speed & 0x03); + zone_data->colorFlags = BITSET(zone_data->colorFlags, !rainbow_color, 7u); + zone_data->padding = 0x00; + + if(mode > MSI_MODE_DOUBLE_FLASHING) + { + zone_data->speedAndBrightnessFlags |= SYNC_SETTING_JRGB; + zone_data->colorFlags |= SYNC_SETTING_ONBOARD; + } + else + { + zone_data->speedAndBrightnessFlags &= ~SYNC_SETTING_JRGB; + zone_data->colorFlags &= ~SYNC_SETTING_ONBOARD; + } + } + + if((zone >= MSI_ZONE_ON_BOARD_LED_0) && (mode <= MSI_MODE_DOUBLE_FLASHING)) + { + zone_data = GetZoneData(data, (MSI_ZONE)((int)zone + 1)); + + if(zone_data != nullptr) + { + zone_data->effect = mode; + zone_data->speedAndBrightnessFlags = (brightness << 2) | (speed & 0x03); + zone_data->colorFlags = BITSET(zone_data->colorFlags, !rainbow_color, 7u); + zone_data->padding = 0x00; + } + } +} + +std::string MSIMysticLight162Controller::GetDeviceName() +{ + return name; +} + +std::string MSIMysticLight162Controller::GetFWVersion() +{ + std::string firmware_version; + firmware_version = "APROM: " + version_APROM + ", LDROM: " + version_LDROM; + return firmware_version; +} + +std::string MSIMysticLight162Controller::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string MSIMysticLight162Controller::GetSerial() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +bool MSIMysticLight162Controller::ReadSettings() +{ + /*-----------------------------------------------------*\ + | Read packet from hardware, return true if successful | + \*-----------------------------------------------------*/ + return(hid_get_feature_report(dev, (unsigned char*)&data, sizeof(data)) == sizeof data); +} + +bool MSIMysticLight162Controller::Update + ( + bool save + ) +{ + /*-----------------------------------------------------*\ + | Send packet to hardware, return true if successful | + \*-----------------------------------------------------*/ + data.save_data = save; + return (hid_send_feature_report(dev, (unsigned char*)&data, sizeof(data)) == sizeof(data)); +} + +void MSIMysticLight162Controller::SetZoneColor + ( + MSI_ZONE zone, + unsigned char red1, + unsigned char grn1, + unsigned char blu1, + unsigned char red2, + unsigned char grn2, + unsigned char blu2 + ) +{ + ZoneData* zone_data = GetZoneData(data, zone); + + if(zone_data == nullptr) + { + return; + } + + if (zone <= MSI_ZONE_ON_BOARD_LED_0) + { + zone_data->color.R = red1; + zone_data->color.G = grn1; + zone_data->color.B = blu1; + zone_data->color2.R = red2; + zone_data->color2.G = grn2; + zone_data->color2.B = blu2; + } + + if(zone >= MSI_ZONE_ON_BOARD_LED_0) + { + zone_data = GetZoneData(data, (MSI_ZONE)((int)zone + 1)); + + if(zone_data != nullptr) + { + zone_data->color.R = red1; + zone_data->color.G = grn1; + zone_data->color.B = blu1; + zone_data->color2.R = red2; + zone_data->color2.G = grn2; + zone_data->color2.B = blu2; + } + } +} + +ZoneData *MSIMysticLight162Controller::GetZoneData + ( + FeaturePacket_162& data_packet, + MSI_ZONE zone + ) +{ + switch(zone) + { + case MSI_ZONE_J_RGB_1: + return &data_packet.j_rgb_1; + case MSI_ZONE_J_RGB_2: + return &data_packet.j_rgb_2; + case MSI_ZONE_J_RAINBOW_1: + return &data_packet.j_rainbow_1; + case MSI_ZONE_J_RAINBOW_2: + return &data_packet.on_board_led_10; + case MSI_ZONE_ON_BOARD_LED_0: + return &data_packet.on_board_led; + case MSI_ZONE_ON_BOARD_LED_1: + return &data_packet.on_board_led_1; + case MSI_ZONE_ON_BOARD_LED_2: + return &data_packet.on_board_led_2; + case MSI_ZONE_ON_BOARD_LED_3: + return &data_packet.on_board_led_3; + case MSI_ZONE_ON_BOARD_LED_4: + return &data_packet.on_board_led_4; + case MSI_ZONE_ON_BOARD_LED_5: + return &data_packet.on_board_led_5; + case MSI_ZONE_ON_BOARD_LED_6: + return &data_packet.on_board_led_6; + case MSI_ZONE_ON_BOARD_LED_7: + return &data_packet.on_board_led_7; + case MSI_ZONE_ON_BOARD_LED_8: + return &data_packet.on_board_led_8; + case MSI_ZONE_ON_BOARD_LED_9: + return &data_packet.on_board_led_9; + case MSI_ZONE_ON_BOARD_LED_10: + return &data_packet.on_board_led_10; + case MSI_ZONE_J_CORSAIR: + return &data_packet.j_corsair_1; + default: + break; + } + + return nullptr; +} + +bool MSIMysticLight162Controller::ReadFwVersion() +{ + unsigned char request[64]; + unsigned char response[64]; + int ret_val = 64; + + /*-----------------------------------------------------*\ + | First read the APROM | + | Checksum also available at report ID 180, with MSB | + | stored at index 0x08 and LSB at 0x09 | + \*-----------------------------------------------------*/ + + /*-----------------------------------------------------*\ + | Zero out buffers | + \*-----------------------------------------------------*/ + memset(request, 0x00, sizeof(request)); + memset(response, 0x00, sizeof(response)); + + /*-----------------------------------------------------*\ + | Set up APROM Firmware Version Request packet | + \*-----------------------------------------------------*/ + request[0x00] = 0x01; + request[0x01] = 0xB0; + + /*-----------------------------------------------------*\ + | Fill request from 0x02 to 0x61 with 0xCC | + \*-----------------------------------------------------*/ + memset(&request[0x02], 0xCC, sizeof(request) - 2); + + /*-----------------------------------------------------*\ + | Send request and receive response packets | + \*-----------------------------------------------------*/ + ret_val &= hid_write(dev, request, 64); + ret_val &= hid_read(dev, response, 64); + + /*-----------------------------------------------------*\ + | Extract high and low values from response | + \*-----------------------------------------------------*/ + unsigned char highValue = response[2] >> 4; + unsigned char lowValue = response[2] & 0x0F; + + /*-----------------------------------------------------*\ + | Build firmware string . | + \*-----------------------------------------------------*/ + version_APROM = std::to_string((int)highValue).append(".").append(std::to_string((int)lowValue)); + + /*-----------------------------------------------------*\ + | First read the LDROM | + | Checksum also available at report ID 184, with MSB | + | stored at index 0x08 and LSB at 0x09 | + \*-----------------------------------------------------*/ + + /*-----------------------------------------------------*\ + | Set up LDROM Firmware Version Request packet | + \*-----------------------------------------------------*/ + request[0x00] = 0x01; + request[0x01] = 0xB6; + + /*-----------------------------------------------------*\ + | Send request and receive response packets | + \*-----------------------------------------------------*/ + ret_val &= hid_write(dev, request, 64); + ret_val &= hid_read(dev, response, 64); + + /*-----------------------------------------------------*\ + | Extract high and low values from response | + \*-----------------------------------------------------*/ + highValue = response[2] >> 4; + lowValue = response[2] & 0x0F; + + /*-----------------------------------------------------*\ + | Build firmware string . | + \*-----------------------------------------------------*/ + version_LDROM = std::to_string((int)highValue).append(".").append(std::to_string((int)lowValue)); + + /*-----------------------------------------------------*\ + | If return value is zero it means an HID transfer | + | failed | + \*-----------------------------------------------------*/ + return(ret_val > 0); +} + +MSI_MODE MSIMysticLight162Controller::GetMode() +{ + return (MSI_MODE)data.on_board_led.effect; +} + +void MSIMysticLight162Controller::GetMode + ( + MSI_ZONE zone, + MSI_MODE &mode, + MSI_SPEED &speed, + MSI_BRIGHTNESS &brightness, + bool &rainbow_color, + unsigned int &color + ) +{ + /*-----------------------------------------------------*\ + | Get data for given zone | + \*-----------------------------------------------------*/ + ZoneData *zone_data = GetZoneData(data, zone); + + /*-----------------------------------------------------*\ + | Return if zone is invalid | + \*-----------------------------------------------------*/ + if(zone_data == nullptr) + { + return; + } + + /*-----------------------------------------------------*\ + | Update pointers with data | + \*-----------------------------------------------------*/ + mode = (MSI_MODE)zone_data->effect; + speed = (MSI_SPEED)(zone_data->speedAndBrightnessFlags & 0x03); + brightness = (MSI_BRIGHTNESS)((zone_data->speedAndBrightnessFlags >> 2) & 0x1F); + rainbow_color = (zone_data->colorFlags & 0x80) == 0 ? true : false; + color = ToRGBColor(zone_data->color.R, zone_data->color.G, zone_data->color.B); +} + +size_t MSIMysticLight162Controller::GetMaxOnboardLeds() +{ + return numof_onboard_leds; +} diff --git a/Controllers/MSIMysticLightController/MSIMysticLight162Controller/MSIMysticLight162Controller.h b/Controllers/MSIMysticLightController/MSIMysticLight162Controller/MSIMysticLight162Controller.h new file mode 100644 index 00000000..67df42a6 --- /dev/null +++ b/Controllers/MSIMysticLightController/MSIMysticLight162Controller/MSIMysticLight162Controller.h @@ -0,0 +1,98 @@ +/*---------------------------------------------------------*\ +| MSIMysticLight162Controller.h | +| | +| Driver for MSI Mystic Light 162-byte motherboard | +| | +| T-bond 03 Apr 2020 | +| Adam Honse 06 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "MSIMysticLightCommon.h" +#include "RGBController.h" + +class MSIMysticLight162Controller +{ +public: + MSIMysticLight162Controller + ( + hid_device* handle, + const char* path, + unsigned short pid, + std::string dev_name + ); + + ~MSIMysticLight162Controller(); + + void SetMode + ( + MSI_ZONE zone, + MSI_MODE mode, + MSI_SPEED speed, + MSI_BRIGHTNESS brightness, + bool rainbow_color + ); + + MSI_MODE GetMode(); + + void GetMode + ( + MSI_ZONE zone, + MSI_MODE &mode, + MSI_SPEED &speed, + MSI_BRIGHTNESS &brightness, + bool &rainbow_color, + unsigned int &color + ); + + void SetZoneColor + ( + MSI_ZONE zone, + unsigned char red1, + unsigned char grn1, + unsigned char blu1, + unsigned char red2, + unsigned char grn2, + unsigned char blu2 + ); + + bool Update + ( + bool save + ); + + std::string GetDeviceName(); + std::string GetDeviceLocation(); + std::string GetFWVersion(); + std::string GetSerial(); + + size_t GetMaxOnboardLeds(); + const std::vector* + GetSupportedZones() { return supported_zones; } + +private: + hid_device* dev; + std::string name; + std::string location; + std::string version_APROM; + std::string version_LDROM; + + FeaturePacket_162 data; + size_t numof_onboard_leds; + const std::vector* supported_zones; + + bool ReadSettings(); + bool ReadFwVersion(); + ZoneData* GetZoneData + ( + FeaturePacket_162& dataPacket, + MSI_ZONE zone + ); +}; diff --git a/Controllers/MSIMysticLightController/RGBController_MSIMysticLight162.cpp b/Controllers/MSIMysticLightController/MSIMysticLight162Controller/RGBController_MSIMysticLight162.cpp similarity index 90% rename from Controllers/MSIMysticLightController/RGBController_MSIMysticLight162.cpp rename to Controllers/MSIMysticLightController/MSIMysticLight162Controller/RGBController_MSIMysticLight162.cpp index 48df18ea..ebe17417 100644 --- a/Controllers/MSIMysticLightController/RGBController_MSIMysticLight162.cpp +++ b/Controllers/MSIMysticLightController/MSIMysticLight162Controller/RGBController_MSIMysticLight162.cpp @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_MSIMysticLight162.cpp | -| | -| Generic RGB Interface for OpenRGB | -| MSI Mystic Light (162-byte) USB Driver | -| | -| T-bond 3/4/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_MSIMysticLight162.cpp | +| | +| RGBController for MSI Mystic Light 162-byte motherboard | +| | +| T-bond 03 Apr 2020 | +| Adam Honse 06 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_MSIMysticLight162.h" - struct ZoneDescription { std::string name; @@ -28,11 +30,8 @@ const ZoneDescription led_zones[] = ZoneDescription{ "Onboard LEDs", MSI_ZONE_ON_BOARD_LED_0 } }; - static std::vector zone_description; - - /**------------------------------------------------------------------*\ @name MSI Mystic Light (162 Byte) @category Motherboard @@ -49,7 +48,7 @@ RGBController_MSIMysticLight162::RGBController_MSIMysticLight162 MSIMysticLight162Controller* controller_ptr ) { - controller = controller_ptr; + controller = controller_ptr; name = controller->GetDeviceName(); vendor = "MSI"; @@ -211,15 +210,7 @@ void RGBController_MSIMysticLight162::UpdateSingleLED void RGBController_MSIMysticLight162::DeviceUpdateMode() { - if(modes[active_mode].value == MSI_MODE_DIRECT_DUMMY) - { - controller->SetDirectMode(true); - } - else - { - controller->SetDirectMode(false); - DeviceUpdateLEDs(); - } + DeviceUpdateLEDs(); } void RGBController_MSIMysticLight162::DeviceSaveMode() @@ -233,8 +224,7 @@ void RGBController_MSIMysticLight162::SetupModes() constexpr unsigned int RANDOM_ONLY = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_MANUAL_SAVE; constexpr unsigned int COMMON = RANDOM_ONLY | MODE_FLAG_HAS_PER_LED_COLOR; - SetupMode("Direct", MSI_MODE_DIRECT_DUMMY, MODE_FLAG_HAS_PER_LED_COLOR); - SetupMode("Static", MSI_MODE_STATIC, MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE); + SetupMode("Direct", MSI_MODE_STATIC, MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE); // SetupMode("Off", MSI_MODE_DISABLE, 0); SetupMode("Breathing", MSI_MODE_BREATHING, PER_LED_ONLY); SetupMode("Flashing", MSI_MODE_FLASHING, COMMON); @@ -286,20 +276,13 @@ void RGBController_MSIMysticLight162::UpdateLed unsigned char grn = RGBGetGValue(zones[zone].colors[led]); unsigned char blu = RGBGetBValue(zones[zone].colors[led]); - if(controller->IsDirectModeActive()) - { - controller->SetLedColor((MSI_ZONE)zones[zone].leds[led].value, red, grn, blu); - } - else - { - bool random = modes[active_mode].color_mode == MODE_COLORS_RANDOM; - MSI_MODE mode = (MSI_MODE)modes[active_mode].value; - MSI_SPEED speed = (MSI_SPEED)modes[active_mode].speed; - MSI_BRIGHTNESS brightness = (MSI_BRIGHTNESS)modes[active_mode].brightness; + bool random = modes[active_mode].color_mode == MODE_COLORS_RANDOM; + MSI_MODE mode = (MSI_MODE)modes[active_mode].value; + MSI_SPEED speed = (MSI_SPEED)modes[active_mode].speed; + MSI_BRIGHTNESS brightness = (MSI_BRIGHTNESS)modes[active_mode].brightness; - controller->SetMode((MSI_ZONE)zones[zone].leds[led].value, mode, speed, brightness, random); - controller->SetZoneColor((MSI_ZONE)zones[zone].leds[led].value, red, grn, blu, red, grn, blu); - } + controller->SetMode((MSI_ZONE)zones[zone].leds[led].value, mode, speed, brightness, random); + controller->SetZoneColor((MSI_ZONE)zones[zone].leds[led].value, red, grn, blu, red, grn, blu); } void RGBController_MSIMysticLight162::SetupMode diff --git a/Controllers/MSIMysticLightController/MSIMysticLight162Controller/RGBController_MSIMysticLight162.h b/Controllers/MSIMysticLightController/MSIMysticLight162Controller/RGBController_MSIMysticLight162.h new file mode 100644 index 00000000..9e2c1b38 --- /dev/null +++ b/Controllers/MSIMysticLightController/MSIMysticLight162Controller/RGBController_MSIMysticLight162.h @@ -0,0 +1,52 @@ +/*---------------------------------------------------------*\ +| RGBController_MSIMysticLight162.h | +| | +| RGBController for MSI Mystic Light 162-byte motherboard | +| | +| T-bond 03 Apr 2020 | +| Adam Honse 06 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "MSIMysticLight162Controller.h" + +class RGBController_MSIMysticLight162: public RGBController +{ +public: + RGBController_MSIMysticLight162(MSIMysticLight162Controller* controller_ptr); + ~RGBController_MSIMysticLight162(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + void SetupModes(); + void UpdateLed + ( + int zone, + int led + ); + void SetupMode + ( + const char *name, + MSI_MODE mode, + unsigned int flags + ); + int GetDeviceMode(); + void GetDeviceConfig(); + + MSIMysticLight162Controller* controller; +}; diff --git a/Controllers/MSIMysticLightController/MSIMysticLight185Controller.cpp b/Controllers/MSIMysticLightController/MSIMysticLight185Controller/MSIMysticLight185Controller.cpp similarity index 89% rename from Controllers/MSIMysticLightController/MSIMysticLight185Controller.cpp rename to Controllers/MSIMysticLightController/MSIMysticLight185Controller/MSIMysticLight185Controller.cpp index 3132f5b3..3d515f64 100644 --- a/Controllers/MSIMysticLightController/MSIMysticLight185Controller.cpp +++ b/Controllers/MSIMysticLightController/MSIMysticLight185Controller/MSIMysticLight185Controller.cpp @@ -1,22 +1,25 @@ -/*---------------------------------------------*\ -| MSIMysticLight185Controller.cpp | -| | -| Driver for MSI Mystic Light (185-byte) | -| USB lighting controller | -| | -| T-bond 3/4/2020 | -| Adam Honse 3/6/2021 | -| | -| The direct mode part has been implemented | -| based on the mystic-why project provided by | -| Aleksandr Garashchenko | -| (https://github.com/garashchenko/mystic-why) | -\*---------------------------------------------*/ +/*---------------------------------------------------------*\ +| MSIMysticLight185Controller.cpp | +| | +| Driver for MSI Mystic Light 185-byte motherboard | +| | +| Direct mode functionality has been implemented based on | +| the mystic-why project provided by Aleksandr | +| Garashchenko | +| (https://github.com/garashchenko/mystic-why) | +| | +| T-bond 03 Apr 2020 | +| Adam Honse 06 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "MSIMysticLight185Controller.h" #include #include #include +#include "MSIMysticLight185Controller.h" +#include "StringUtils.h" using namespace std::chrono_literals; @@ -33,8 +36,7 @@ using namespace std::chrono_literals; #define PER_LED_BASIC_SYNC_MODE (0x80 | SYNC_SETTING_ONBOARD | SYNC_SETTING_JPIPE1 | SYNC_SETTING_JPIPE2) #define PER_LED_FULL_SYNC_MODE (PER_LED_BASIC_SYNC_MODE | SYNC_SETTING_JRAINBOW1 | SYNC_SETTING_JRAINBOW2 | SYNC_SETTING_JCORSAIR) - -struct Config +struct mystic_light_185_config { unsigned short pid; // PID of the board int numof_onboard_leds; // number of onboard leds @@ -200,7 +202,23 @@ const std::vector zones_set16 = MSI_ZONE_J_PIPE_2 }; +const std::vector zones_set17 = +{ + MSI_ZONE_J_RGB_1, + MSI_ZONE_J_RGB_2, + MSI_ZONE_J_RAINBOW_1, + MSI_ZONE_J_RAINBOW_2, + MSI_ZONE_J_PIPE_1 +}; +const std::vector zones_set18 = +{ + MSI_ZONE_J_RGB_1, + MSI_ZONE_J_RAINBOW_1, + MSI_ZONE_J_RAINBOW_2, + MSI_ZONE_J_RAINBOW_3, + MSI_ZONE_J_PIPE_1 +}; /*---------------------------------------------------------------------------------------------------------------------------------*\ | Definition of the board sepcific configurations (number of onboard LEDs and supported zones). | @@ -210,9 +228,9 @@ const std::vector zones_set16 = | Boards with yet unknown supported zones are configured to support all zones. | \*---------------------------------------------------------------------------------------------------------------------------------*/ -#define NUMOF_CONFIGS (sizeof(board_configs) / sizeof(Config)) +#define NUMOF_CONFIGS (sizeof(board_configs) / sizeof(mystic_light_185_config)) -static const Config board_configs[] = +static const mystic_light_185_config board_configs[] = { { 0x7B93, 6, 1, 0, 1, &zones_set3, MSIMysticLight185Controller::DIRECT_MODE_ZONE_BASED }, // MPG X570 GAMING PRO CARBON WIFI { 0x7C34, 0, 1, 1, 1, &zones_set8, MSIMysticLight185Controller::DIRECT_MODE_ZONE_BASED }, // MEG X570 GODLIKE @@ -222,7 +240,7 @@ static const Config board_configs[] = { 0x7C56, 6, 0, 0, 1, &zones_set2, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG B550 GAMING PLUS { 0x7C59, 0, 8, 0, 1, &zones_set9, MSIMysticLight185Controller::DIRECT_MODE_DISABLED }, // CREATOR TRX40 { 0x7C60, 6, 0, 0, 1, &zones_set1, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // TRX40-A PRO - { 0x7C67, 6, 0, 0, 1, &zones_set5, MSIMysticLight185Controller::DIRECT_MODE_DISABLED }, // MAG B365M MORTAR + { 0x7C67, 6, 0, 0, 1, &zones_set5, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG B365M MORTAR { 0x7C71, 6, 6, 0, 1, &zones_set3, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MEG Z490 ACE { 0x7C73, 6, 4, 0, 1, &zones_set3, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG Z490 GAMING CARBON WIFI { 0x7C75, 6, 0, 0, 1, &zones_set2, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG Z490 GAMING PLUS @@ -243,11 +261,12 @@ static const Config board_configs[] = { 0x7C95, 6, 0, 0, 2, &zones_set0, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // B550M PRO-VDH WIFI { 0x7C98, 6, 0, 0, 1, &zones_set5, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // Z490 PLUS { 0x7D03, 0, 15, 18, 1, &zones_set8, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG Z590 GODLIKE - { 0x7D06, 4, 4, 0, 1, &zones_set3, MSIMysticLight185Controller::DIRECT_MODE_DISABLED }, // MPG Z590 GAMING FORCE + { 0x7D06, 4, 4, 0, 1, &zones_set3, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG Z590 GAMING FORCE { 0x7D07, 4, 5, 0, 2, &zones_set7, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG Z590 GAMING EDGE WIFI { 0x7D08, 6, 0, 0, 2, &zones_set0, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG Z590 TOMAHAWK { 0x7D09, 6, 0, 0, 2, &zones_set11, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // Z590-A PRO WIFI - { 0x7D13, 6, 0, 0, 1, &zones_set1, MSIMysticLight185Controller::DIRECT_MODE_DISABLED }, // MEG B550 UNIFY + { 0x7D13, 6, 0, 0, 1, &zones_set1, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MEG B550 UNIFY + { 0x7D14, 6, 0, 0, 1, &zones_set5, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // A520M PRO { 0x7D15, 6, 0, 0, 2, &zones_set0, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG B560 TOMAHAWK WIFI { 0x7D17, 6, 0, 0, 2, &zones_set11, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG B560M MORTAR { 0x7D18, 6, 0, 0, 2, &zones_set5, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG B560M PRO-VDH @@ -256,12 +275,14 @@ static const Config board_configs[] = { 0x7D25, 6, 0, 0, 2, &zones_set11, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO Z690-A WIFI DDR4 { 0x7D27, 6, 0, 0, 2, &zones_set1, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MEG Z690 ACE { 0x7D28, 6, 0, 0, 1, &zones_set1, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MEG Z690 UNIFY-X - { 0x7D29, 6, 0, 0, 0, &zones_set6, MSIMysticLight185Controller::DIRECT_MODE_DISABLED }, // MEG Z690I UNIFY + { 0x7D29, 6, 0, 0, 0, &zones_set6, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MEG Z690I UNIFY { 0x7D30, 6, 6, 0, 2, &zones_set3, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG Z690 CARBON WIFI { 0x7D31, 4, 8, 0, 2, &zones_set12, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG EDGE WIFI DDR4 { 0x7D32, 1, 0, 0, 1, &zones_set10, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG Z690 TOMAHAWK WIFI DDR4 + { 0x7D33, 6, 0, 0, 2, &zones_set5, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO Z790-VC WIFI { 0x7D36, 6, 0, 0, 2, &zones_set5, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO Z690-P DDR4 { 0x7D38, 0, 0, 0, 1, &zones_set1, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MEG Z590 UNIFY-X + { 0x7D40, 0, 0, 0, 1, &zones_set5, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG B760i EDGE WIFI DDR4 { 0x7D41, 6, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG B660M TOMAHAWK WIFI DDR4 { 0x7D42, 6, 0, 0, 2, &zones_set11, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG B660 MORTAR WIFI DDR4 { 0x7D43, 0, 0, 0, 2, &zones_set11, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO B660M-A WIFI DDR4 @@ -276,16 +297,31 @@ static const Config board_configs[] = { 0x7D69, 9, 2, 4, 1, &zones_set15, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MEG X670E ACE { 0x7D70, 0, 6, 0, 1, &zones_set4, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG X670E Carbon WIFI { 0x7D73, 1, 0, 0, 0, &zones_set6, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG B650I EDGE WIFI + { 0x7D74, 0, 6, 0, 1, &zones_set18, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG B650 CARBON WIFI { 0x7D75, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG B650 TOMAHAWK WIFI { 0x7D76, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG B650M MORTAR WIFI - { 0x7D77, 6, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO B650M-A WIFI - { 0x7D78, 6, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO B650-P WIFI + { 0x7D77, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO B650M-A WIFI + { 0x7D78, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO B650-P WIFI { 0x7D86, 0, 18, 4, 1, &zones_set16, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MEG Z790 ACE - { 0x7D89, 0, 6, 0, 1, &zones_set4, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG Z790 CARBON WIFI + { 0x7D89, 0, 6, 0, 1, &zones_set18, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG Z790 CARBON WIFI + { 0x7D90, 0, 0, 0, 1, &zones_set11, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // B760M BOMBER DDR4 { 0x7D91, 1, 0, 0, 1, &zones_set10, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG Z790 TOMAHAWK WIFI + { 0x7D93, 6, 0, 0, 1, &zones_set2, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // Z790 GAMING PRO WIFI + { 0x7D96, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG B760 TOMAHAWK WIFI DDR5 + { 0x7D97, 6, 0, 0, 2, &zones_set11, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG B660 MORTAR MAX WIFI DDR4 + { 0x7D98, 0, 0, 0, 1, &zones_set11, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO B760-P WIFI DDR4 + { 0x7D99, 6, 0, 0, 1, &zones_set11, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO B760M-A WIFI DDR4 { 0x7E01, 0, 0, 0, 1, &zones_set11, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG B760M MORTAR MAX + { 0x7E03, 6, 0, 0, 0, &zones_set6, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG Z790I EDGE WIFI { 0x7E06, 0, 0, 0, 2, &zones_set11, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO Z790-P WIFI DDR4 { 0x7E07, 0, 0, 0, 2, &zones_set10, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO Z790-A WIFI DDR4 + { 0x7E10, 0, 6, 0, 2, &zones_set17, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG B650 EDGE WIFI + { 0x7E12, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MAG X670E TOMAHAWK WIFI + { 0x7E16, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // X670E GAMING PLUS WIFI + { 0x7E24, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // B650M GAMING PLUS WIFI + { 0x7E26, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // B650 GAMING PLUS WIFI + { 0x7E27, 0, 0, 0, 2, &zones_set13, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // PRO B650M-P + { 0x7E49, 0, 6, 0, 1, &zones_set4, MSIMysticLight185Controller::DIRECT_MODE_PER_LED }, // MPG X870E CARBON WIFI }; @@ -299,33 +335,44 @@ Color* per_led_jrainbow1_sync; Color* per_led_jrainbow2_sync; Color* per_led_jcorsair_sync; - MSIMysticLight185Controller::MSIMysticLight185Controller ( hid_device* handle, - const char *path, - unsigned short pid + const char* path, + unsigned short pid, + std::string dev_name ) { - dev = handle; + dev = handle; + location = path; + name = dev_name; if(dev) { - location = path; - - ReadName(); - ReadSerial(); ReadFwVersion(); ReadSettings(); } + if(pid == MSI_USB_PID_COMMON) + { + std::string pidStr(GetSerial().substr(0, 4)); + pid = std::stoi(pidStr, nullptr, 16); + } + + mixed_mode_support = false; + + if(pid >= 0x7D03) + { + mixed_mode_support = true; + } + /*---------------------------------------------*\ | Initialize save flag and some static settings | \*---------------------------------------------*/ data.save_data = 0; data.on_board_led.colorFlags = 0x80 | SYNC_SETTING_ONBOARD; // always enable onboard sync flag to have expected zone control - const Config* board_config = nullptr; + const mystic_light_185_config* board_config = nullptr; for(std::size_t i = 0; i < NUMOF_CONFIGS; ++i) { @@ -526,7 +573,7 @@ void MSIMysticLight185Controller::SetMode ZoneData* on_board_zone = GetZoneData(data, MSI_ZONE_ON_BOARD_LED_0); - if(no_onboards && ((zone == MSI_ZONE_J_RGB_1) || (zone == MSI_ZONE_J_RGB_1) || (zone == MSI_ZONE_J_PIPE_1) || (zone == MSI_ZONE_J_PIPE_2))) + if(no_onboards && ((zone == MSI_ZONE_J_RGB_1) || (zone == MSI_ZONE_J_RGB_2) || (zone == MSI_ZONE_J_PIPE_1) || (zone == MSI_ZONE_J_PIPE_2))) { on_board_zone->effect = zone_data->effect; on_board_zone->speedAndBrightnessFlags = zone_data->speedAndBrightnessFlags; @@ -580,7 +627,15 @@ std::string MSIMysticLight185Controller::GetDeviceLocation() std::string MSIMysticLight185Controller::GetSerial() { - return chip_id; + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } bool MSIMysticLight185Controller::ReadSettings() @@ -669,7 +724,7 @@ void MSIMysticLight185Controller::SetZoneColor zone_data->color2.G = grn2; zone_data->color2.B = blu2; - if(no_onboards && ((zone == MSI_ZONE_J_RGB_1) || (zone == MSI_ZONE_J_RGB_1) || (zone == MSI_ZONE_J_PIPE_1) || (zone == MSI_ZONE_J_PIPE_2))) + if(no_onboards && ((zone == MSI_ZONE_J_RGB_1) || (zone == MSI_ZONE_J_RGB_2) || (zone == MSI_ZONE_J_PIPE_1) || (zone == MSI_ZONE_J_PIPE_2))) { ZoneData* on_board_zone = GetZoneData(data, MSI_ZONE_ON_BOARD_LED_0); @@ -783,7 +838,14 @@ ZoneData *MSIMysticLight185Controller::GetZoneData case MSI_ZONE_J_RGB_1: return &data_packet.j_rgb_1; case MSI_ZONE_J_RGB_2: - return &data_packet.j_rgb_2; + if(mixed_mode_support) + { + return &data_packet.on_board_led_6; + } + else + { + return &data_packet.j_rgb_2; + } case MSI_ZONE_J_RAINBOW_1: return &data_packet.j_rainbow_1; case MSI_ZONE_J_RAINBOW_2: @@ -807,7 +869,14 @@ ZoneData *MSIMysticLight185Controller::GetZoneData case MSI_ZONE_ON_BOARD_LED_5: return &data_packet.on_board_led_5; case MSI_ZONE_ON_BOARD_LED_6: - return &data_packet.on_board_led_6; + if(mixed_mode_support) + { + return &data_packet.j_corsair_outerll120; + } + else + { + return &data_packet.on_board_led_6; + } case MSI_ZONE_ON_BOARD_LED_7: return &data_packet.on_board_led_7; case MSI_ZONE_ON_BOARD_LED_8: @@ -978,49 +1047,6 @@ bool MSIMysticLight185Controller::ReadFwVersion() return (ret_val > 0); } -void MSIMysticLight185Controller::ReadSerial() -{ - wchar_t serial[256]; - - /*-----------------------------------------------------*\ - | Get the serial number string from HID | - \*-----------------------------------------------------*/ - hid_get_serial_number_string(dev, serial, 256); - - /*-----------------------------------------------------*\ - | Convert wchar_t into std::wstring into std::string | - \*-----------------------------------------------------*/ - std::wstring wserial = std::wstring(serial); - chip_id = std::string(wserial.begin(), wserial.end()); -} - -void MSIMysticLight185Controller::ReadName() -{ - wchar_t tname[256]; - - /*-----------------------------------------------------*\ - | Get the manufacturer string from HID | - \*-----------------------------------------------------*/ - hid_get_manufacturer_string(dev, tname, 256); - - /*-----------------------------------------------------*\ - | Convert wchar_t into std::wstring into std::string | - \*-----------------------------------------------------*/ - std::wstring wname = std::wstring(tname); - name = std::string(wname.begin(), wname.end()); - - /*-----------------------------------------------------*\ - | Get the product string from HID | - \*-----------------------------------------------------*/ - hid_get_product_string(dev, tname, 256); - - /*-----------------------------------------------------*\ - | Append the product string to the manufacturer string | - \*-----------------------------------------------------*/ - wname = std::wstring(tname); - name.append(" ").append(std::string(wname.begin(), wname.end())); -} - MSI_MODE MSIMysticLight185Controller::GetMode() { if(data.on_board_led.effect == MSI_DIRECT_MODE) diff --git a/Controllers/MSIMysticLightController/MSIMysticLight185Controller.h b/Controllers/MSIMysticLightController/MSIMysticLight185Controller/MSIMysticLight185Controller.h similarity index 79% rename from Controllers/MSIMysticLightController/MSIMysticLight185Controller.h rename to Controllers/MSIMysticLightController/MSIMysticLight185Controller/MSIMysticLight185Controller.h index ef7591fc..d8d9cea8 100644 --- a/Controllers/MSIMysticLightController/MSIMysticLight185Controller.h +++ b/Controllers/MSIMysticLightController/MSIMysticLight185Controller/MSIMysticLight185Controller.h @@ -1,31 +1,39 @@ -/*-----------------------------------------*\ -| MSIMysticLight185Controller.h | -| | -| Definitions and types for MSI Mystic | -| Light (185-byte) USB lighting | -| controllers | -| | -| T-bond 3/4/2020 | -| Adam Honse 3/6/2021 | -\*-----------------------------------------*/ - -#include "MSIMysticLightCommon.h" -#include "RGBController.h" -#include -#include -#include +/*---------------------------------------------------------*\ +| MSIMysticLight185Controller.h | +| | +| Driver for MSI Mystic Light 185-byte motherboard | +| | +| Direct mode functionality has been implemented based on | +| the mystic-why project provided by Aleksandr | +| Garashchenko | +| (https://github.com/garashchenko/mystic-why) | +| | +| T-bond 03 Apr 2020 | +| Adam Honse 06 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include +#include "MSIMysticLightCommon.h" +#include "RGBController.h" + class MSIMysticLight185Controller { public: MSIMysticLight185Controller ( hid_device* handle, - const char *path, - unsigned short pid + const char* path, + unsigned short pid, + std::string dev_name ); + ~MSIMysticLight185Controller(); void SetMode @@ -107,28 +115,11 @@ public: DIRECT_MODE GetSupportedDirectMode() { return per_led_mode; } private: - bool ReadSettings(); - bool ReadFwVersion(); - void ReadSerial(); - void ReadName(); - ZoneData* GetZoneData - ( - FeaturePacket_185& data_packet, - MSI_ZONE zone - ); - RainbowZoneData* GetRainbowZoneData(MSI_ZONE zone); - Color* GetPerLedZoneData - ( - MSI_ZONE zone - ); - void SelectPerLedProtocol(); - hid_device* dev; std::string name; std::string location; std::string version_APROM; std::string version_LDROM; - std::string chip_id; FeaturePacket_185 data; FeaturePacket_PerLED_185 per_led_data_onboard_and_sync; @@ -142,10 +133,25 @@ private: bool no_jrainbow1; bool no_jrainbow2; bool no_jcorsair; + bool mixed_mode_support; int numof_onboard_leds; int numof_pipe1_leds; int numof_pipe2_leds; int numof_JRGBs; const std::vector* supported_zones; DIRECT_MODE per_led_mode; + + bool ReadSettings(); + bool ReadFwVersion(); + ZoneData* GetZoneData + ( + FeaturePacket_185& data_packet, + MSI_ZONE zone + ); + RainbowZoneData* GetRainbowZoneData(MSI_ZONE zone); + Color* GetPerLedZoneData + ( + MSI_ZONE zone + ); + void SelectPerLedProtocol(); }; diff --git a/Controllers/MSIMysticLightController/RGBController_MSIMysticLight185.cpp b/Controllers/MSIMysticLightController/MSIMysticLight185Controller/RGBController_MSIMysticLight185.cpp similarity index 87% rename from Controllers/MSIMysticLightController/RGBController_MSIMysticLight185.cpp rename to Controllers/MSIMysticLightController/MSIMysticLight185Controller/RGBController_MSIMysticLight185.cpp index de1b07ed..9b7ef1ad 100644 --- a/Controllers/MSIMysticLightController/RGBController_MSIMysticLight185.cpp +++ b/Controllers/MSIMysticLightController/MSIMysticLight185Controller/RGBController_MSIMysticLight185.cpp @@ -1,17 +1,18 @@ -/*-----------------------------------------*\ -| RGBController_MSIMysticLight185.cpp | -| | -| Generic RGB Interface for OpenRGB | -| MSI Mystic Light (185-byte) USB Driver | -| | -| T-bond 3/4/2020 | -| Adam Honse 3/6/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_MSIMysticLight185.cpp | +| | +| RGBController for MSI Mystic Light 185-byte motherboard | +| | +| T-bond 03 Apr 2020 | +| Adam Honse 06 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_MSIMysticLight185.h" #include "LogManager.h" - struct ZoneDescription { std::string name; @@ -33,7 +34,6 @@ const ZoneDescription led_zones[] = ZoneDescription{ "ONBOARD", MSI_ZONE_ON_BOARD_LED_0 } }; - static std::vector zone_description; /*---------------------------------------------------------------------------------------------------------*\ @@ -53,7 +53,6 @@ static int IndexOfZoneForType(MSI_ZONE zone_type) return -1; } - /**------------------------------------------------------------------*\ @name MSI Mystic Light (185 Byte) @category Motherboard @@ -70,7 +69,7 @@ RGBController_MSIMysticLight185::RGBController_MSIMysticLight185 MSIMysticLight185Controller* controller_ptr ) { - controller = controller_ptr; + controller = controller_ptr; name = controller->GetDeviceName(); vendor = "MSI"; @@ -148,23 +147,37 @@ void RGBController_MSIMysticLight185::SetupZones() zone new_zone; new_zone.name = zd->name; + new_zone.flags = 0; int maxLeds = (int)controller->GetMaxDirectLeds(zd->zone_type); /*-------------------------------------------------*\ | This is a fixed size zone | - | Either this is a board which only supports zone | - | control or this is not an ARGB header zone | \*-------------------------------------------------*/ - if((controller->GetSupportedDirectMode() == MSIMysticLight185Controller::DIRECT_MODE_ZONE_BASED) - || ((zd->zone_type != MSI_ZONE_J_RAINBOW_1) && (zd->zone_type != MSI_ZONE_J_RAINBOW_2) && (zd->zone_type != MSI_ZONE_J_RAINBOW_3) && (zd->zone_type != MSI_ZONE_J_CORSAIR))) + if(((zd->zone_type != MSI_ZONE_J_RAINBOW_1) + && (zd->zone_type != MSI_ZONE_J_RAINBOW_2) + && (zd->zone_type != MSI_ZONE_J_RAINBOW_3) + && (zd->zone_type != MSI_ZONE_J_CORSAIR))) { new_zone.leds_min = maxLeds; new_zone.leds_max = maxLeds; new_zone.leds_count = maxLeds; } /*--------------------------------------------------\ - | This is a resizable zone on a per-LED board | + | This is a resizable zone on a board that does not | + | support per-LED direct mode | + \*-------------------------------------------------*/ + else if(controller->GetSupportedDirectMode() == MSIMysticLight185Controller::DIRECT_MODE_ZONE_BASED) + { + new_zone.leds_min = 0; + new_zone.leds_max = 30;//maxLeds; + new_zone.leds_count = 0; + last_resizable_zone = zd->zone_type; + new_zone.flags |= ZONE_FLAG_RESIZE_EFFECTS_ONLY; + } + /*--------------------------------------------------\ + | This is a resizable zone on a board that does | + | support per-LED direct mode | \*-------------------------------------------------*/ else { @@ -177,7 +190,7 @@ void RGBController_MSIMysticLight185::SetupZones() /*-------------------------------------------------*\ | Determine zone type based on max number of LEDs | \*-------------------------------------------------*/ - if(new_zone.leds_max == 1) + if((new_zone.leds_max == 1) || (new_zone.flags & ZONE_FLAG_RESIZE_EFFECTS_ONLY)) { new_zone.type = ZONE_TYPE_SINGLE; } @@ -200,16 +213,28 @@ void RGBController_MSIMysticLight185::SetupZones() { controller->SetCycleCount(zone_description[zone_idx]->zone_type, zones[zone_idx].leds_count); - for(std::size_t led_idx = 0; led_idx < zones[zone_idx].leds_count; ++led_idx) + if((zones[zone_idx].flags & ZONE_FLAG_RESIZE_EFFECTS_ONLY) == 0) + { + for(std::size_t led_idx = 0; led_idx < zones[zone_idx].leds_count; ++led_idx) + { + led new_led; + + new_led.name = zones[zone_idx].name; + + if(zones[zone_idx].leds_count > 1) + { + new_led.name.append(" LED " + std::to_string(led_idx + 1)); + } + + new_led.value = zone_description[zone_idx]->zone_type; + leds.push_back(new_led); + } + } + else if(zones[zone_idx].leds_count > 0) { led new_led; - new_led.name = zones[zone_idx].name + " LED "; - - if(zones[zone_idx].leds_count > 1) - { - new_led.name.append(std::to_string(led_idx + 1)); - } + new_led.name = zones[zone_idx].name; new_led.value = zone_description[zone_idx]->zone_type; leds.push_back(new_led); diff --git a/Controllers/MSIMysticLightController/MSIMysticLight185Controller/RGBController_MSIMysticLight185.h b/Controllers/MSIMysticLightController/MSIMysticLight185Controller/RGBController_MSIMysticLight185.h new file mode 100644 index 00000000..7f06c2cc --- /dev/null +++ b/Controllers/MSIMysticLightController/MSIMysticLight185Controller/RGBController_MSIMysticLight185.h @@ -0,0 +1,53 @@ +/*---------------------------------------------------------*\ +| RGBController_MSIMysticLight185.h | +| | +| RGBController for MSI Mystic Light 185-byte motherboard | +| | +| T-bond 03 Apr 2020 | +| Adam Honse 06 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "MSIMysticLight185Controller.h" + +class RGBController_MSIMysticLight185: public RGBController +{ +public: + RGBController_MSIMysticLight185(MSIMysticLight185Controller* controller_ptr); + ~RGBController_MSIMysticLight185(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + void SetupModes(); + void UpdateLed + ( + int zone, + int led + ); + void SetupMode + ( + const char *name, + MSI_MODE mode, + unsigned int flags + ); + int GetDeviceMode(); + void GetDeviceConfig(); + + MSIMysticLight185Controller* controller; + MSI_ZONE last_resizable_zone; +}; diff --git a/Controllers/MSIMysticLightController/MSIMysticLight64Controller.cpp b/Controllers/MSIMysticLightController/MSIMysticLight64Controller.cpp deleted file mode 100644 index 7966aad5..00000000 --- a/Controllers/MSIMysticLightController/MSIMysticLight64Controller.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/*-----------------------------------------*\ -| MSIMysticLight64Controller.cpp | -| | -| Driver for MSI Mystic Light (64-byte) | -| USB lighting controller | -| | -| T-bond 3/4/2020 | -| Adam Honse 3/6/2021 | -| Elchanan Haas 8/23/2022 | -\*-----------------------------------------*/ - -#include "MSIMysticLight64Controller.h" -#include -#include -#include - -MSIMysticLight64Controller::MSIMysticLight64Controller -( - hid_device *handle, - const char *path -) -{ - dev = handle; - if(dev) - { - location = path; - } -} - -MSIMysticLight64Controller::~MSIMysticLight64Controller() -{ - hid_close(dev); -} - -void MSIMysticLight64Controller::SetMode -( - MSI_64_MODE mode, - MSI_SPEED speed, - MSI_BRIGHTNESS brightness, - unsigned int num_colors, - Color colors[] -) -{ - FeaturePacket_64 data; - for(int i = 0; i < MSI_64_MAX_COLORS; i++) - { - data.colors[i] = colors[i]; - } - data.speed = speed; - data.brightness = brightness; - data.num_colors = num_colors; - data.mode = mode; - /*-----------------------------------------------------*\ - | Send packet to hardware, return true if successful | - \*-----------------------------------------------------*/ - hid_send_feature_report(dev, (unsigned char *)&data, sizeof(data)); - return; -} - -std::string MSIMysticLight64Controller::GetDeviceName() -{ - wchar_t tname[256]; - - /*-----------------------------------------------------*\ - | Get the manufacturer string from HID | - \*-----------------------------------------------------*/ - hid_get_manufacturer_string(dev, tname, 256); - - /*-----------------------------------------------------*\ - | Convert wchar_t into std::wstring into std::string | - \*-----------------------------------------------------*/ - std::wstring wname = std::wstring(tname); - std::string name = std::string(wname.begin(), wname.end()); - - /*-----------------------------------------------------*\ - | Get the product string from HID | - \*-----------------------------------------------------*/ - hid_get_product_string(dev, tname, 256); - - /*-----------------------------------------------------*\ - | Append the product string to the manufacturer string | - \*-----------------------------------------------------*/ - wname = std::wstring(tname); - name.append(" ").append(std::string(wname.begin(), wname.end())); - return name; -} - -std::string MSIMysticLight64Controller::GetFWVersion() -{ - /*-----------------------------------------------------*\ - | This device doesn't support firmware version | - \*-----------------------------------------------------*/ - std::string firmware_version = ""; - return firmware_version; -} - -std::string MSIMysticLight64Controller::GetDeviceLocation() -{ - return ("HID: " + location); -} - -std::string MSIMysticLight64Controller::GetSerial() -{ - wchar_t serial[256]; - - /*-----------------------------------------------------*\ - | Get the serial number string from HID | - \*-----------------------------------------------------*/ - hid_get_serial_number_string(dev, serial, 256); - - /*-----------------------------------------------------*\ - | Convert wchar_t into std::wstring into std::string | - \*-----------------------------------------------------*/ - std::wstring wserial = std::wstring(serial); - - return (std::string(wserial.begin(), wserial.end())); -} diff --git a/Controllers/MSIMysticLightController/MSIMysticLight64Controller.h b/Controllers/MSIMysticLightController/MSIMysticLight64Controller.h deleted file mode 100644 index 527f91b9..00000000 --- a/Controllers/MSIMysticLightController/MSIMysticLight64Controller.h +++ /dev/null @@ -1,59 +0,0 @@ -/*-----------------------------------------*\ -| MSIMysticLight64Controller.h | -| | -| Definitions and types for MSI Mystic | -| Light (64-byte) USB lighting controllers | -| | -| T-bond 3/4/2020 | -| Adam Honse 3/6/2021 | -\*-----------------------------------------*/ - -#include "MSIMysticLightCommon.h" -#include "RGBController.h" -#include -#include -#include - -#pragma once - -enum MSI_64_MODE -{ - MSI_64_OFF = 0, - MSI_64_STEADY = 1, - MSI_64_BREATHING = 2, - MSI_64_PULSE = 3, - MSI_64_DOUBLE_PULSE = 4, - MSI_64_CYCLE = 5, - MSI_64_SMOOTH_CYCLE = 6, -}; - -class MSIMysticLight64Controller -{ -public: - MSIMysticLight64Controller - ( - hid_device* handle, - const char *path - ); - ~MSIMysticLight64Controller(); - - void SetMode - ( - MSI_64_MODE mode, - MSI_SPEED speed, - MSI_BRIGHTNESS brightness, - unsigned int num_colors, - Color colors[] - ); - - - std::string GetDeviceName(); - std::string GetDeviceLocation(); - std::string GetFWVersion(); - std::string GetSerial(); - -private: - - hid_device* dev; - std::string location; -}; diff --git a/Controllers/MSIMysticLightController/MSIMysticLight64Controller/MSIMysticLight64Controller.cpp b/Controllers/MSIMysticLightController/MSIMysticLight64Controller/MSIMysticLight64Controller.cpp new file mode 100644 index 00000000..b3ace58a --- /dev/null +++ b/Controllers/MSIMysticLightController/MSIMysticLight64Controller/MSIMysticLight64Controller.cpp @@ -0,0 +1,115 @@ +/*---------------------------------------------------------*\ +| MSIMysticLight64Controller.cpp | +| | +| Driver for MSI Mystic Light 64-byte motherboard | +| | +| T-bond 03 Apr 2020 | +| Adam Honse 06 Mar 2021 | +| Elchanan Haas 23 Aug 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include "MSIMysticLight64Controller.h" +#include "StringUtils.h" + +MSIMysticLight64Controller::MSIMysticLight64Controller +( + hid_device *handle, + const char *path +) +{ + dev = handle; + if(dev) + { + location = path; + } +} + +MSIMysticLight64Controller::~MSIMysticLight64Controller() +{ + hid_close(dev); +} + +void MSIMysticLight64Controller::SetMode +( + MSI_64_MODE mode, + MSI_SPEED speed, + MSI_BRIGHTNESS brightness, + unsigned int num_colors, + Color colors[] +) +{ + FeaturePacket_64 data; + for(int i = 0; i < MSI_64_MAX_COLORS; i++) + { + data.colors[i] = colors[i]; + } + data.speed = speed; + data.brightness = brightness; + data.num_colors = num_colors; + data.mode = mode; + /*-----------------------------------------------------*\ + | Send packet to hardware, return true if successful | + \*-----------------------------------------------------*/ + hid_send_feature_report(dev, (unsigned char *)&data, sizeof(data)); + return; +} + +std::string MSIMysticLight64Controller::GetDeviceName() +{ + wchar_t tname[256]; + + /*-----------------------------------------------------*\ + | Get the manufacturer string from HID | + \*-----------------------------------------------------*/ + hid_get_manufacturer_string(dev, tname, 256); + + /*-----------------------------------------------------*\ + | Convert to std::string | + \*-----------------------------------------------------*/ + std::string name = StringUtils::wstring_to_string(tname); + + /*-----------------------------------------------------*\ + | Get the product string from HID | + \*-----------------------------------------------------*/ + hid_get_product_string(dev, tname, 256); + + /*-----------------------------------------------------*\ + | Append the product string to the manufacturer string | + \*-----------------------------------------------------*/ + name.append(" ").append(StringUtils::wstring_to_string(tname)); + + return(name); +} + +std::string MSIMysticLight64Controller::GetFWVersion() +{ + /*-----------------------------------------------------*\ + | This device doesn't support firmware version | + \*-----------------------------------------------------*/ + std::string firmware_version = ""; + return firmware_version; +} + +std::string MSIMysticLight64Controller::GetDeviceLocation() +{ + return ("HID: " + location); +} + +std::string MSIMysticLight64Controller::GetSerial() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} diff --git a/Controllers/MSIMysticLightController/MSIMysticLight64Controller/MSIMysticLight64Controller.h b/Controllers/MSIMysticLightController/MSIMysticLight64Controller/MSIMysticLight64Controller.h new file mode 100644 index 00000000..3536999c --- /dev/null +++ b/Controllers/MSIMysticLightController/MSIMysticLight64Controller/MSIMysticLight64Controller.h @@ -0,0 +1,62 @@ +/*---------------------------------------------------------*\ +| MSIMysticLight64Controller.h | +| | +| Driver for MSI Mystic Light 64-byte motherboard | +| | +| T-bond 03 Apr 2020 | +| Adam Honse 06 Mar 2021 | +| Elchanan Haas 23 Aug 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "MSIMysticLightCommon.h" +#include "RGBController.h" + +enum MSI_64_MODE +{ + MSI_64_OFF = 0, + MSI_64_STEADY = 1, + MSI_64_BREATHING = 2, + MSI_64_PULSE = 3, + MSI_64_DOUBLE_PULSE = 4, + MSI_64_CYCLE = 5, + MSI_64_SMOOTH_CYCLE = 6, +}; + +class MSIMysticLight64Controller +{ +public: + MSIMysticLight64Controller + ( + hid_device* handle, + const char *path + ); + ~MSIMysticLight64Controller(); + + void SetMode + ( + MSI_64_MODE mode, + MSI_SPEED speed, + MSI_BRIGHTNESS brightness, + unsigned int num_colors, + Color colors[] + ); + + + std::string GetDeviceName(); + std::string GetDeviceLocation(); + std::string GetFWVersion(); + std::string GetSerial(); + +private: + + hid_device* dev; + std::string location; +}; diff --git a/Controllers/MSIMysticLightController/RGBController_MSIMysticLight64.cpp b/Controllers/MSIMysticLightController/MSIMysticLight64Controller/RGBController_MSIMysticLight64.cpp similarity index 85% rename from Controllers/MSIMysticLightController/RGBController_MSIMysticLight64.cpp rename to Controllers/MSIMysticLightController/MSIMysticLight64Controller/RGBController_MSIMysticLight64.cpp index c7e04811..0d8911f4 100644 --- a/Controllers/MSIMysticLightController/RGBController_MSIMysticLight64.cpp +++ b/Controllers/MSIMysticLightController/MSIMysticLight64Controller/RGBController_MSIMysticLight64.cpp @@ -1,3 +1,16 @@ +/*---------------------------------------------------------*\ +| RGBController_MSIMysticLight64.cpp | +| | +| RGBController for MSI Mystic Light 64-byte motherboard | +| | +| T-bond 03 Apr 2020 | +| Adam Honse 06 Mar 2021 | +| Elchanan Haas 23 Aug 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "RGBController_MSIMysticLight64.h" /**------------------------------------------------------------------*\ @@ -72,7 +85,7 @@ void RGBController_MSIMysticLight64::DeviceUpdateLEDs() unsigned int num_colors = 0; if(Mode.flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR) { - num_colors = Mode.colors.size(); + num_colors = (unsigned int)Mode.colors.size(); for(unsigned int i = 0; i < num_colors; i++) { led_colors[i].R = RGBGetRValue(Mode.colors[i]); @@ -148,4 +161,4 @@ void RGBController_MSIMysticLight64::SetupMode Mode.colors.push_back(0x00FF00FF); } modes.push_back(Mode); -} \ No newline at end of file +} diff --git a/Controllers/MSIMysticLightController/MSIMysticLight64Controller/RGBController_MSIMysticLight64.h b/Controllers/MSIMysticLightController/MSIMysticLight64Controller/RGBController_MSIMysticLight64.h new file mode 100644 index 00000000..a23dc531 --- /dev/null +++ b/Controllers/MSIMysticLightController/MSIMysticLight64Controller/RGBController_MSIMysticLight64.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------*\ +| RGBController_MSIMysticLight64.h | +| | +| RGBController for MSI Mystic Light 64-byte motherboard | +| | +| T-bond 03 Apr 2020 | +| Adam Honse 06 Mar 2021 | +| Elchanan Haas 23 Aug 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "MSIMysticLight64Controller.h" + +class RGBController_MSIMysticLight64 : public RGBController +{ +public: + RGBController_MSIMysticLight64(MSIMysticLight64Controller* controller_ptr); + ~RGBController_MSIMysticLight64(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + MSIMysticLight64Controller* controller; + void SetupModes(); + void SetupMode + ( + const char *name, + MSI_64_MODE mode, + unsigned int flags + ); +}; diff --git a/Controllers/MSIMysticLightController/MSIMysticLight761Controller/MSIMysticLight761Controller.cpp b/Controllers/MSIMysticLightController/MSIMysticLight761Controller/MSIMysticLight761Controller.cpp new file mode 100644 index 00000000..5c8623af --- /dev/null +++ b/Controllers/MSIMysticLightController/MSIMysticLight761Controller/MSIMysticLight761Controller.cpp @@ -0,0 +1,418 @@ +/*---------------------------------------------------------*\ +| MSIMysticLight185Controller.cpp | +| | +| Driver for MSI Mystic Light 761-byte motherboard | +| | +| Direct mode functionality has been implemented based on | +| the SignalRGB project | +| (https://signalrgb.com/) | +| | +| rom4ster 11 Jun 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include +#include "MSIMysticLight761Controller.h" +#include "StringUtils.h" + + +#define NUM_CONFS sizeof(board_configs) / sizeof(mystic_light_761_config) +#define COLOR_BLACK {0, 0, 0} +#define IS_JARGB(X) (X == MSI_ZONE_JARGB_1 || X == MSI_ZONE_JARGB_2 || X == MSI_ZONE_JARGB_3) +#define GET_CHAR_PTR_REF(X) (unsigned char *) &(X) + +struct mystic_light_761_config +{ + unsigned short pid; // PID of the board + int numof_onboard_leds; // number of onboard leds + int numof_pipe1_leds; // number of pipe 1 leds (used in per LED mode only) + int numof_pipe2_leds; // number of pipe 2 leds (used in per LED mode only) + int numof_JRGBs; // number of supported JRGB headers (used in per LED mode only) + const std::vector* supported_zones; // pointer to vector of supported zones + MSIMysticLight761Controller::DIRECT_MODE per_led_mode; // type of direct mode support +}; + +const std::vector x870tomawhawk_zones = +{ + MSI_ZONE_JAF, + MSI_ZONE_JARGB_1, + MSI_ZONE_JARGB_2, + MSI_ZONE_JARGB_3, +}; + +static const mystic_light_761_config board_configs[] = +{ + { 0x0076, 0, 0, 0, 1, &x870tomawhawk_zones, MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED }, // MSI X870 TOMAHAWK WIFI +}; + +void init_packet(FeaturePacket_Zone_761 * packet) +{ + packet->packet.fixed1 = 0x09; + packet->packet.fixed2 = 0x00; + packet->packet.fixed3 = 0x00; + packet->packet.hdr2 = 240; + + for(int i = 0; i < NUM_LEDS_761; i++) + { + packet->packet.colors[i] = 0x0; + } + +} + +MSIMysticLight761Controller::MSIMysticLight761Controller + ( + hid_device* handle, + const char* path, + unsigned short pid, + std::string dev_name + ) +{ + dev = handle; + location = path; + name = dev_name; + + supported_zones = new std::vector; + + const mystic_light_761_config * board_config = nullptr; + + for(std::size_t i = 0; i < NUM_CONFS; i++) + { + if(board_configs[i].pid == pid) + { + board_config = &board_configs[i]; + break; + } + } + + if(board_config != nullptr) + { + supported_zones = (std::vector*) board_config->supported_zones; + unsigned int max = 0; + + for(std::size_t i = 0; i < board_config->supported_zones[0].size(); i++) + { + unsigned int curr_val = (unsigned int) (board_config->supported_zones[0][i]); + + if((unsigned int) curr_val > max) + { + max = curr_val; + } + } + } + + for(MSI_ZONE supp_zone : *supported_zones) + { + ZoneConfig conf; + + conf.msi_zone = supp_zone; + ZoneData * dat = new ZoneData; + conf.zone_data = dat; + + zone_configs.push_back(conf); + } + + if(dev) + { + ReadFwVersion(); + ReadSettings(); + data = new FeaturePacket_761; + + data->jaf.zone = MSI_ZONE_JAF; + data->jargb1.zone = MSI_ZONE_JARGB_1; + data->jargb2.zone = MSI_ZONE_JARGB_2; + data->jargb3.zone = MSI_ZONE_JARGB_3; + + data->jaf.packet.hdr0 = 0x08; + data->jargb1.packet.hdr0 = 0x04; + data->jargb2.packet.hdr0 = 0x04; + data->jargb3.packet.hdr0 = 0x04; + + data->jaf.packet.hdr1 = 0x00; + data->jargb1.packet.hdr1 = 0x00; + data->jargb2.packet.hdr1 = 0x01; + data->jargb3.packet.hdr1 = 0x02; + + init_packet(&data->jaf); + init_packet(&data->jargb1); + init_packet(&data->jargb2); + init_packet(&data->jargb3); + } + +} + +MSIMysticLight761Controller::~MSIMysticLight761Controller() +{ + hid_close(dev); +} + +void MSIMysticLight761Controller::SetMode + ( + MSI_ZONE /*zone*/, + MSI_MODE /*mode*/, + MSI_SPEED /*speed*/, + MSI_BRIGHTNESS /*brightness*/, + bool /*rainbow_color*/ + ) +{ + return; // Only supporting direct for now +} + +std::string MSIMysticLight761Controller::GetDeviceName() +{ + return name; +} + +std::string MSIMysticLight761Controller::GetFWVersion() +{ + return std::string("AP/LD ").append(version_APROM).append(" / ").append(version_LDROM); +} + +std::string MSIMysticLight761Controller::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string MSIMysticLight761Controller::GetSerial() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +bool MSIMysticLight761Controller::ReadSettings() +{ + /*-----------------------------------------------------*\ + | Read packet from hardware, return true if successful | + \*-----------------------------------------------------*/ + unsigned char buffer [500]; + buffer[0] = 0x51; + return (hid_get_feature_report(dev, buffer, 500)) > 0 ; +} + +bool MSIMysticLight761Controller::Update + ( + bool /*save*/ + ) +{ + + int ret = 0; + bool flag = true; + ret = hid_send_feature_report(dev, GET_CHAR_PTR_REF(data->jaf.packet) , sizeof(FeaturePacket_PerLED_761)); + if(ret < 0) { flag = false;} + ret = hid_send_feature_report(dev, GET_CHAR_PTR_REF(data->jargb1.packet) , sizeof(FeaturePacket_PerLED_761)); + if(ret < 0) { flag = false;} + ret = hid_send_feature_report(dev, GET_CHAR_PTR_REF(data->jargb2.packet) , sizeof(FeaturePacket_PerLED_761)); + if(ret < 0) { flag = false;} + ret = hid_send_feature_report(dev, GET_CHAR_PTR_REF(data->jargb3.packet) , sizeof(FeaturePacket_PerLED_761)); + if(ret < 0) { flag = false;} + + return flag; +} + +void MSIMysticLight761Controller::SetZoneColor + ( + MSI_ZONE zone, + unsigned char red1, + unsigned char grn1, + unsigned char blu1, + unsigned char red2, + unsigned char grn2, + unsigned char blu2 + ) +{ + for(std::size_t i = 0; i < zone_configs.size(); i++) + { + if(zone_configs[i].msi_zone == zone) + { + zone_configs[i].zone_data->color.R = red1; + zone_configs[i].zone_data->color.G = grn1; + zone_configs[i].zone_data->color.B = blu1; + zone_configs[i].zone_data->color2.R = red2; + zone_configs[i].zone_data->color2.G = grn2; + zone_configs[i].zone_data->color2.B = blu2; + } + } +} + +void set_data_color(FeaturePacket_Zone_761 * packet, int index, unsigned char color_val ) +{ + if(packet == nullptr) + { + return; + } + packet->packet.colors[index] = color_val; +} + +void MSIMysticLight761Controller::SetLedColor + ( + MSI_ZONE zone, + int index, + unsigned char red, + unsigned char grn, + unsigned char blu + ) +{ + + FeaturePacket_Zone_761 * ptr = nullptr; + switch(zone) + { + case MSI_ZONE_JAF: + ptr = &data->jaf; + break; + case MSI_ZONE_JARGB_1: + ptr = &data->jargb1; + break; + case MSI_ZONE_JARGB_2: + ptr = &data->jargb2; + break; + case MSI_ZONE_JARGB_3: + ptr = &data->jargb3; + break; + default: + break; + } + + if(index >= 0) + { + std::size_t candidate_index = (index * 3); + + if((candidate_index + 2) <= GetMaxDirectLeds(zone)) + { + set_data_color(ptr, (int)candidate_index, red); + set_data_color(ptr, (int)candidate_index + 1, grn); + set_data_color(ptr, (int)candidate_index + 2, blu); + } + } + +} + +ZoneData *MSIMysticLight761Controller::GetZoneData + ( + FeaturePacket_761& /*data_packet*/, + MSI_ZONE zone + ) +{ + for(ZoneConfig zd : zone_configs) + { + if(zd.msi_zone == zone) + { + return zd.zone_data; + } + } + + return nullptr; +} + +Color *MSIMysticLight761Controller::GetPerLedZoneData + ( + MSI_ZONE zone + ) +{ + return &(GetZoneData(*data, zone)->color); +} + +RainbowZoneData *MSIMysticLight761Controller::GetRainbowZoneData + ( + MSI_ZONE /*zone*/ + ) +{ + return nullptr; +} + +bool MSIMysticLight761Controller::ReadFwVersion() +{ + return true; +} + +MSI_MODE MSIMysticLight761Controller::GetMode() +{ + return MSI_MODE_DIRECT_DUMMY; +} + +void MSIMysticLight761Controller::GetMode + ( + MSI_ZONE zone, + MSI_MODE & mode, + MSI_SPEED & speed, + MSI_BRIGHTNESS & brightness, + bool & rainbow_color, + unsigned int & color + ) +{ + /*-----------------------------------------------------*\ + | Get data for given zone | + \*-----------------------------------------------------*/ + ZoneData *zone_data = GetZoneData(*data, zone); + + /*-----------------------------------------------------*\ + | Return if zone is invalid | + \*-----------------------------------------------------*/ + if(!zone_data) + { + return; + } + + /*-----------------------------------------------------*\ + | Update pointers with data | + \*-----------------------------------------------------*/ + + // Actual support of non direct modes needs to be further investigated + mode = (MSI_MODE)zone_data->effect; + speed = (MSI_SPEED)(zone_data->speedAndBrightnessFlags & 0x03); + brightness = (MSI_BRIGHTNESS)((zone_data->speedAndBrightnessFlags >> 2) & 0x1F); + rainbow_color = (zone_data->colorFlags & 0x80) == 0 ? true : false; + color = ToRGBColor(zone_data->color.R, zone_data->color.G, zone_data->color.B); +} + +void MSIMysticLight761Controller::SetCycleCount + ( + MSI_ZONE /*zone*/, + unsigned char /*cycle_num*/ + ) +{ + return; +} + +void MSIMysticLight761Controller::SetDirectMode + ( + bool /*mode*/ + ) +{ + SelectPerLedProtocol(); +} + + +size_t MSIMysticLight761Controller::GetMaxDirectLeds + ( + MSI_ZONE zone + ) +{ + switch(zone) + { + case MSI_ZONE_JAF: + case MSI_ZONE_JARGB_1: + case MSI_ZONE_JARGB_2: + case MSI_ZONE_JARGB_3: + return 240; + break; + default: + return 1; + } +} + + +void MSIMysticLight761Controller::SelectPerLedProtocol() +{ + return; +} diff --git a/Controllers/MSIMysticLightController/MSIMysticLight761Controller/MSIMysticLight761Controller.h b/Controllers/MSIMysticLightController/MSIMysticLight761Controller/MSIMysticLight761Controller.h new file mode 100644 index 00000000..6cfa6cc8 --- /dev/null +++ b/Controllers/MSIMysticLightController/MSIMysticLight761Controller/MSIMysticLight761Controller.h @@ -0,0 +1,145 @@ +/*---------------------------------------------------------*\ +| MSIMysticLight185Controller.cpp | +| | +| Driver for MSI Mystic Light 761-byte motherboard | +| | +| Direct mode functionality has been implemented based on | +| the SignalRGB project | +| (https://signalrgb.com/) | +| | +| rom4ster 11 Jun 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "MSIMysticLightCommon.h" +#include "RGBController.h" + +class MSIMysticLight761Controller +{ +public: + MSIMysticLight761Controller + ( + hid_device* handle, + const char* path, + unsigned short pid, + std::string dev_name + ); + + ~MSIMysticLight761Controller(); + + void SetMode + ( + MSI_ZONE zone, + MSI_MODE mode, + MSI_SPEED speed, + MSI_BRIGHTNESS brightness, + bool rainbow_color + ); + + MSI_MODE GetMode(); + + void GetMode + ( + MSI_ZONE zone, + MSI_MODE &mode, + MSI_SPEED &speed, + MSI_BRIGHTNESS &brightness, + bool &rainbow_color, + unsigned int &color + ); + + void SetZoneColor + ( + MSI_ZONE zone, + unsigned char red1, + unsigned char grn1, + unsigned char blu1, + unsigned char red2, + unsigned char grn2, + unsigned char blu2 + ); + + void SetLedColor + ( + MSI_ZONE zone, + int index, + unsigned char red, + unsigned char grn, + unsigned char blu + ); + + void SetCycleCount + ( + MSI_ZONE zone, + unsigned char cycle_num + ); + + bool Update + ( + bool save + ); + + std::string GetDeviceName(); + std::string GetDeviceLocation(); + std::string GetFWVersion(); + std::string GetSerial(); + + void SetDirectMode + ( + bool mode + ); + bool IsDirectModeActive() { return true; } + size_t GetMaxDirectLeds + ( + MSI_ZONE zone + ); + const std::vector* + GetSupportedZones() { return supported_zones; } + + enum DIRECT_MODE + { + DIRECT_MODE_DISABLED, + DIRECT_MODE_PER_LED, + DIRECT_MODE_ZONE_BASED + }; + + DIRECT_MODE GetSupportedDirectMode() { return DIRECT_MODE_PER_LED; } + + struct ZoneConfig + { + MSI_ZONE msi_zone; + ZoneData * zone_data; + }; + +private: + std::string name; + std::vector zone_configs; + std::vector* supported_zones; + hid_device* dev; + std::string location; + std::string version_APROM; + std::string version_LDROM; + FeaturePacket_761* data; + + bool ReadSettings(); + bool ReadFwVersion(); + + ZoneData* GetZoneData + ( + FeaturePacket_761& data_packet, + MSI_ZONE zone + ); + RainbowZoneData* GetRainbowZoneData(MSI_ZONE zone); + Color* GetPerLedZoneData + ( + MSI_ZONE zone + ); + void SelectPerLedProtocol(); +}; diff --git a/Controllers/MSIMysticLightController/MSIMysticLight761Controller/RGBController_MSIMysticLight761.cpp b/Controllers/MSIMysticLightController/MSIMysticLight761Controller/RGBController_MSIMysticLight761.cpp new file mode 100644 index 00000000..d860068f --- /dev/null +++ b/Controllers/MSIMysticLightController/MSIMysticLight761Controller/RGBController_MSIMysticLight761.cpp @@ -0,0 +1,459 @@ +/*---------------------------------------------------------*\ +| MSIMysticLight185Controller.cpp | +| | +| RGBController for MSI Mystic Light 761-byte motherboard | +| | +| | +| rom4ster 11 Jun 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_MSIMysticLight761.h" +#include "LogManager.h" + +struct ZoneDescription +{ + std::string name; + MSI_ZONE zone_type; +}; + +#define NUMOF_ZONES (sizeof(led_zones) / sizeof(ZoneDescription)) + +const ZoneDescription led_zones[] = +{ + ZoneDescription{ "JAF", MSI_ZONE_JAF }, + ZoneDescription{ "JARGB 1", MSI_ZONE_JARGB_1 }, + ZoneDescription{ "JARGB 2", MSI_ZONE_JARGB_2 }, + ZoneDescription{ "JARGB 3", MSI_ZONE_JARGB_3 }, +}; + +static std::vector zone_description; + +static int IndexOfZoneForType(MSI_ZONE zone_type) +{ + for(size_t i = 0; i < zone_description.size(); ++i) + { + if(zone_description[i]->zone_type == zone_type) + { + return (int)i; + } + } + + return -1; +} + +RGBController_MSIMysticLight761::RGBController_MSIMysticLight761 + ( + MSIMysticLight761Controller* controller_ptr + ) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "MSI"; + type = DEVICE_TYPE_MOTHERBOARD; + description = "MSI Mystic Light Device (761-byte)"; + version = controller->GetFWVersion(); + location = controller->GetDeviceLocation(); + serial = controller->GetSerial(); + + const std::vector* supported_zones = controller->GetSupportedZones(); + + for(std::size_t i = 0; i < supported_zones->size(); ++i) + { + for(std::size_t j = 0; j < NUMOF_ZONES; ++j) + { + if(led_zones[j].zone_type == (*supported_zones)[i]) + { + zone_description.push_back(&led_zones[j]); + break; + } + } + } + + last_resizable_zone = MSI_ZONE_NONE; + SetupModes(); + SetupZones(); + active_mode = GetDeviceMode(); +} + +RGBController_MSIMysticLight761::~RGBController_MSIMysticLight761() +{ + zone_description.clear(); + delete controller; +} + +int RGBController_MSIMysticLight761::GetDeviceMode() +{ + MSI_MODE mode = controller->GetMode(); + + for(unsigned int i = 0; i < modes.size(); ++i) + { + if(mode == modes[i].value) + { + return i; + } + } + + return 0; +} + +void RGBController_MSIMysticLight761::SetupZones() +{ + /*-------------------------------------------------*\ + | Clear any existing color/LED configuration | + \*-------------------------------------------------*/ + leds.clear(); + colors.clear(); + + bool first_run = false; + + if(zones.size() == 0) + { + first_run = true; + } + + if(first_run) + { + /*---------------------------------------------------------*\ + | Set up zones | + \*---------------------------------------------------------*/ + for(std::size_t zone_idx = 0; zone_idx < zone_description.size(); ++zone_idx) + { + const ZoneDescription* zd = zone_description[zone_idx]; + + zone new_zone; + + new_zone.name = zd->name; + new_zone.flags = 0; + + int maxLeds = (int)controller->GetMaxDirectLeds(zd->zone_type); + + /*-------------------------------------------------*\ + | This is a fixed size zone | + \*-------------------------------------------------*/ + if(((zd->zone_type != MSI_ZONE_J_RAINBOW_1) + && (zd->zone_type != MSI_ZONE_J_RAINBOW_2) + && (zd->zone_type != MSI_ZONE_J_RAINBOW_3) + && (zd->zone_type != MSI_ZONE_JAF) + && (zd->zone_type != MSI_ZONE_JARGB_1) + && (zd->zone_type != MSI_ZONE_JARGB_2) + && (zd->zone_type != MSI_ZONE_JARGB_3) + && (zd->zone_type != MSI_ZONE_J_CORSAIR))) + { + new_zone.leds_min = maxLeds; + new_zone.leds_max = maxLeds; + new_zone.leds_count = maxLeds; + } + /*--------------------------------------------------\ + | This is a resizable zone on a board that does not | + | support per-LED direct mode | + \*-------------------------------------------------*/ + else if(controller->GetSupportedDirectMode() == MSIMysticLight761Controller::DIRECT_MODE_ZONE_BASED) + { + new_zone.leds_min = 0; + new_zone.leds_max = 30;//maxLeds; + new_zone.leds_count = 0; + last_resizable_zone = zd->zone_type; + new_zone.flags |= ZONE_FLAG_RESIZE_EFFECTS_ONLY; + } + /*--------------------------------------------------\ + | This is a resizable zone on a board that does | + | support per-LED direct mode | + \*-------------------------------------------------*/ + else + { + new_zone.leds_min = 0; + new_zone.leds_max = maxLeds; + new_zone.leds_count = 0; + last_resizable_zone = zd->zone_type; + } + + /*-------------------------------------------------*\ + | Determine zone type based on max number of LEDs | + \*-------------------------------------------------*/ + if((new_zone.leds_max == 1) || (new_zone.flags & ZONE_FLAG_RESIZE_EFFECTS_ONLY)) + { + new_zone.type = ZONE_TYPE_SINGLE; + } + else + { + new_zone.type = ZONE_TYPE_LINEAR; + } + + new_zone.matrix_map = NULL; + + zones.push_back(new_zone); + } + } + + /*---------------------------------------------------------*\ + | Set up LEDs | + \*---------------------------------------------------------*/ + for(std::size_t zone_idx = 0; zone_idx < zone_description.size(); ++zone_idx) + { + controller->SetCycleCount(zone_description[zone_idx]->zone_type, zones[zone_idx].leds_count); + + if((zones[zone_idx].flags & ZONE_FLAG_RESIZE_EFFECTS_ONLY) == 0) + { + for(std::size_t led_idx = 0; led_idx < zones[zone_idx].leds_count; ++led_idx) + { + led new_led; + + new_led.name = zones[zone_idx].name; + + if(zones[zone_idx].leds_count > 1) + { + new_led.name.append(" LED " + std::to_string(led_idx + 1)); + } + + new_led.value = zone_description[zone_idx]->zone_type; + leds.push_back(new_led); + } + } + else if(zones[zone_idx].leds_count > 0) + { + led new_led; + + new_led.name = zones[zone_idx].name; + + new_led.value = zone_description[zone_idx]->zone_type; + leds.push_back(new_led); + } + } + + SetupColors(); +} + + +void RGBController_MSIMysticLight761::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(); + + if(zone_description[zone]->zone_type == last_resizable_zone) + { + GetDeviceConfig(); + last_resizable_zone = MSI_ZONE_NONE; + } + } +} + +void RGBController_MSIMysticLight761::DeviceUpdateLEDs() +{ + for(std::size_t zone_idx = 0; zone_idx < zones.size(); ++zone_idx) + { + for(int led_idx = zones[zone_idx].leds_count - 1; led_idx >= 0; led_idx--) + { + UpdateLed((int)zone_idx, led_idx); + } + } + controller->Update((modes[active_mode].flags & MODE_FLAG_AUTOMATIC_SAVE) != 0); +} + +void RGBController_MSIMysticLight761::UpdateZoneLEDs(int zone) +{ + for(int led_idx = zones[zone].leds_count - 1; led_idx >= 0; led_idx--) + { + UpdateLed(zone, led_idx); + } + controller->Update((modes[active_mode].flags & MODE_FLAG_AUTOMATIC_SAVE) != 0); +} + +void RGBController_MSIMysticLight761::UpdateSingleLED + ( + int led + ) +{ + int zone_index = IndexOfZoneForType((MSI_ZONE)leds[led].value); + + if(zone_index == -1) + { + LOG_DEBUG("[%s]: could not find zone for type %d", controller->GetDeviceName().c_str(), leds[led].value); + return; + } + + int led_index = led - zones[zone_index].start_idx; + UpdateLed(zone_index, led_index); + controller->Update((modes[active_mode].flags & MODE_FLAG_AUTOMATIC_SAVE) != 0); +} + +void RGBController_MSIMysticLight761::DeviceUpdateMode() +{ + if(modes[active_mode].value == MSI_MODE_DIRECT_DUMMY) + { + controller->SetDirectMode(true); + } + else + { + controller->SetDirectMode(false); + DeviceUpdateLEDs(); + } +} + +void RGBController_MSIMysticLight761::DeviceSaveMode() +{ + controller->Update(true); +} + +void RGBController_MSIMysticLight761::SetupModes() +{ + if(controller->GetSupportedDirectMode() != MSIMysticLight761Controller::DIRECT_MODE_DISABLED) + { + SetupMode("Direct", MSI_MODE_DIRECT_DUMMY, MODE_FLAG_HAS_PER_LED_COLOR); + } +} + +void RGBController_MSIMysticLight761::UpdateLed + ( + int zone, + int led + ) +{ + unsigned char red = RGBGetRValue(zones[zone].colors[led]); + unsigned char grn = RGBGetGValue(zones[zone].colors[led]); + unsigned char blu = RGBGetBValue(zones[zone].colors[led]); + + if(controller->IsDirectModeActive()) + { + controller->SetLedColor((MSI_ZONE)(zones[zone].leds[led].value), led, red, grn, blu); + } + else + { + if(led == 0) + { + bool random = modes[active_mode].color_mode == MODE_COLORS_RANDOM; + MSI_MODE mode = (MSI_MODE)modes[active_mode].value; + MSI_SPEED speed = (MSI_SPEED)modes[active_mode].speed; + MSI_BRIGHTNESS brightness = (MSI_BRIGHTNESS)modes[active_mode].brightness; + + controller->SetMode((MSI_ZONE)zones[zone].leds[led].value, mode, speed, brightness, random); + controller->SetZoneColor((MSI_ZONE)zones[zone].leds[led].value, red, grn, blu, red, grn, blu); + } + } +} + +void RGBController_MSIMysticLight761::SetupMode + ( + const char *name, + MSI_MODE mod, + unsigned int flags + ) +{ + mode Mode; + Mode.name = name; + Mode.value = mod; + Mode.flags = flags; + + if(flags & MODE_FLAG_HAS_PER_LED_COLOR) + { + Mode.color_mode = MODE_COLORS_PER_LED; + } + else + { + Mode.color_mode = MODE_COLORS_RANDOM; + } + + if(flags & MODE_FLAG_HAS_SPEED) + { + Mode.speed = MSI_SPEED_MEDIUM; + Mode.speed_max = MSI_SPEED_HIGH; + Mode.speed_min = MSI_SPEED_LOW; + } + else + { + /*---------------------------------------------------------*\ + | For modes without speed this needs to be set to avoid | + | bad values in the saved profile which in turn corrupts | + | the brightness calculation when loading the profile | + \*---------------------------------------------------------*/ + Mode.speed = 0; + Mode.speed_max = 0; + Mode.speed_min = 0; + } + + if(flags & MODE_FLAG_HAS_BRIGHTNESS) + { + Mode.brightness = MSI_BRIGHTNESS_LEVEL_100; + Mode.brightness_max = MSI_BRIGHTNESS_LEVEL_100; + Mode.brightness_min = MSI_BRIGHTNESS_OFF; + } + else + { + Mode.brightness = MSI_BRIGHTNESS_LEVEL_100; + Mode.brightness_max = MSI_BRIGHTNESS_LEVEL_100; + Mode.brightness_min = MSI_BRIGHTNESS_LEVEL_100; + } + + modes.push_back(Mode); +} + +void RGBController_MSIMysticLight761::GetDeviceConfig() +{ + if(controller->GetMode() != MSI_MODE_DIRECT_DUMMY) + { + MSI_MODE mode; + MSI_SPEED speed; + MSI_BRIGHTNESS brightness; + bool rainbow; + unsigned int color; + + for(size_t i = 0; i < zone_description.size(); ++i) + { + controller->GetMode(zone_description[i]->zone_type, mode, speed, brightness, rainbow, color); + + if(zones[i].colors != nullptr) + { + for(size_t j = 0; j < zones[i].leds_count; ++j) + { + zones[i].colors[j] = color; + } + } + } + + controller->GetMode(zone_description[0]->zone_type, mode, speed, brightness, rainbow, color); + + for(size_t i = 0; i < modes.size(); ++i) + { + if(mode == modes[i].value) + { + if(modes[i].flags & MODE_FLAG_HAS_SPEED) + { + modes[i].speed = speed; + } + if(modes[i].flags & MODE_FLAG_HAS_BRIGHTNESS) + { + modes[i].brightness = brightness; + } + if(rainbow) + { + if(modes[i].flags & (MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR)) + { + if(rainbow) + { + modes[i].color_mode = MODE_COLORS_RANDOM; + } + else + { + modes[i].color_mode = MODE_COLORS_PER_LED; + } + } + } + break; + } + } + } +} diff --git a/Controllers/MSIMysticLightController/MSIMysticLight761Controller/RGBController_MSIMysticLight761.h b/Controllers/MSIMysticLightController/MSIMysticLight761Controller/RGBController_MSIMysticLight761.h new file mode 100644 index 00000000..dfd1fd36 --- /dev/null +++ b/Controllers/MSIMysticLightController/MSIMysticLight761Controller/RGBController_MSIMysticLight761.h @@ -0,0 +1,53 @@ +/*---------------------------------------------------------*\ +| MSIMysticLight185Controller.cpp | +| | +| RGBController for MSI Mystic Light 761-byte motherboard | +| | +| | +| rom4ster 11 Jun 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "MSIMysticLight761Controller.h" + +class RGBController_MSIMysticLight761: public RGBController +{ +public: + RGBController_MSIMysticLight761(MSIMysticLight761Controller* controller_ptr); + ~RGBController_MSIMysticLight761(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + void SetupModes(); + void UpdateLed + ( + int zone, + int led + ); + void SetupMode + ( + const char *name, + MSI_MODE mode, + unsigned int flags + ); + int GetDeviceMode(); + void GetDeviceConfig(); + + MSIMysticLight761Controller* controller; + MSI_ZONE last_resizable_zone; +}; diff --git a/Controllers/MSIMysticLightController/MSIMysticLightCommon.h b/Controllers/MSIMysticLightController/MSIMysticLightCommon.h index 43b2a838..5a1aa860 100644 --- a/Controllers/MSIMysticLightController/MSIMysticLightCommon.h +++ b/Controllers/MSIMysticLightController/MSIMysticLightCommon.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| MSIMysticLightCommon.h | -| | -| Common definitions and types for all MSI | -| Mystic Light variants | -| | -| Adam Honse 3/6/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| MSIMysticLightCommon.h | +| | +| Common definitions for MSI Mystic Light motherboards | +| | +| Adam Honse 06 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once @@ -33,7 +35,11 @@ enum MSI_ZONE MSI_ZONE_ON_BOARD_LED_7 = 17, MSI_ZONE_ON_BOARD_LED_8 = 18, MSI_ZONE_ON_BOARD_LED_9 = 19, - MSI_ZONE_ON_BOARD_LED_10 = 20 + MSI_ZONE_ON_BOARD_LED_10 = 20, + MSI_ZONE_JAF = 21, + MSI_ZONE_JARGB_1 = 22, + MSI_ZONE_JARGB_2 = 23, + MSI_ZONE_JARGB_3 = 24, }; enum MSI_MODE @@ -107,10 +113,11 @@ enum MSI_BRIGHTNESS MSI_BRIGHTNESS_LEVEL_70 = 7, MSI_BRIGHTNESS_LEVEL_80 = 8, MSI_BRIGHTNESS_LEVEL_90 = 9, - MSI_BRIGHTNESS_LEVEL_100 = 10, + MSI_BRIGHTNESS_LEVEL_100 = 10, }; #define NUMOF_PER_LED_MODE_LEDS 240 +#define NUM_LEDS_761 720 #define SYNC_SETTING_ONBOARD 0x01 #define SYNC_SETTING_JRAINBOW1 0x02 @@ -157,7 +164,7 @@ struct RainbowZoneData : ZoneData struct FeaturePacket_64 { const unsigned char report_id = 0x02; // Report ID - const unsigned char second_byte = 0x00; + const unsigned char second_byte = 0x00; unsigned char mode = 0x00; unsigned char speed = 0x00; unsigned char brightness = 0x00; @@ -238,3 +245,31 @@ struct FeaturePacket_PerLED_185 unsigned char hdr3 = 0x00; // header byte 3 Color leds[NUMOF_PER_LED_MODE_LEDS]; }; + +struct FeaturePacket_PerLED_761 +{ + unsigned char report_id = 0x51; // Report ID + unsigned char fixed1 = 0x09; // Always 9? + unsigned char hdr0; // 0x08 for ez 0x04 for ARGB 0x06 for LED + unsigned char hdr1; // 0 for LED/EZ and argb num for ARGB? + unsigned char fixed2 = 0x00; // IDK what this is + unsigned char fixed3 = 0x00; // IDK what this is + unsigned char hdr2; // Led Count + unsigned char colors [NUM_LEDS_761]; +}; + +struct FeaturePacket_Zone_761 +{ + MSI_ZONE zone; + FeaturePacket_PerLED_761 packet; +}; + +struct FeaturePacket_761 +{ + FeaturePacket_Zone_761 jargb1; + FeaturePacket_Zone_761 jargb2; + FeaturePacket_Zone_761 jargb3; + FeaturePacket_Zone_761 jaf; +}; + +#define MSI_USB_PID_COMMON 0x0076 // Common PID for a certain set of 185-byte boards diff --git a/Controllers/MSIMysticLightController/MSIMysticLightControllerDetect.cpp b/Controllers/MSIMysticLightController/MSIMysticLightControllerDetect.cpp index 55e53f36..f2da8d58 100644 --- a/Controllers/MSIMysticLightController/MSIMysticLightControllerDetect.cpp +++ b/Controllers/MSIMysticLightController/MSIMysticLightControllerDetect.cpp @@ -1,17 +1,28 @@ +/*---------------------------------------------------------*\ +| MSIMysticLightControllerDetect.cpp | +| | +| Detector for MSI Mystic Light motherboards | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "MSIMysticLight64Controller.h" #include "MSIMysticLight112Controller.h" #include "MSIMysticLight162Controller.h" #include "MSIMysticLight185Controller.h" +#include "MSIMysticLight761Controller.h" #include "RGBController_MSIMysticLight64.h" #include "RGBController_MSIMysticLight112.h" #include "RGBController_MSIMysticLight162.h" #include "RGBController_MSIMysticLight185.h" -#include "dependencies/dmiinfo.h" +#include "RGBController_MSIMysticLight761.h" +#include "dmiinfo.h" #include "LogManager.h" - -#define MSI_USB_VID 0x1462 +#define MSI_USB_VID 0x1462 +#define MSI_USB_VID_COMMON 0x0DB0 /*---------------------------------------------------------------------------------*\ | WARNING! | @@ -28,7 +39,7 @@ | | | Detect MSI Mystic Light devices | | | -\*-----------------------------------------------------------------------------------------*/ +\*----------------------------------------------------------------------------------------*/ void DetectMSIMysticLightControllers ( hid_device_info* info, @@ -39,41 +50,63 @@ void DetectMSIMysticLightControllers if(dev != nullptr) { unsigned char temp_buffer[200]; - temp_buffer[0] = 0x52; - size_t packet_length = hid_get_feature_report(dev, temp_buffer, 200); - DMIInfo dmi; + temp_buffer[0] = 0x52; - if((packet_length >= sizeof(FeaturePacket_185)) && (packet_length <= (sizeof(FeaturePacket_185) + 1))) + size_t packet_length = hid_get_feature_report(dev, temp_buffer, 200); + + DMIInfo dmi; + std::string dmi_name = "MSI " + dmi.getMainboard(); + + if((packet_length >= sizeof(FeaturePacket_185)) && (packet_length <= (sizeof(FeaturePacket_185) + 1))) //WHY r we doing this ? why not == { - MSIMysticLight185Controller* controller = new MSIMysticLight185Controller(dev, info->path, info->product_id); + MSIMysticLight185Controller* controller = new MSIMysticLight185Controller(dev, info->path, info->product_id, dmi_name); RGBController_MSIMysticLight185* rgb_controller = new RGBController_MSIMysticLight185(controller); - rgb_controller->name = "MSI " + dmi.getMainboard(); + ResourceManager::get()->RegisterRGBController(rgb_controller); } else if((packet_length >= sizeof(FeaturePacket_162)) && (packet_length <= (sizeof(FeaturePacket_162) + 1))) { - MSIMysticLight162Controller* controller = new MSIMysticLight162Controller(dev, info->path, info->product_id); + MSIMysticLight162Controller* controller = new MSIMysticLight162Controller(dev, info->path, info->product_id, dmi_name); RGBController_MSIMysticLight162* rgb_controller = new RGBController_MSIMysticLight162(controller); - rgb_controller->name = "MSI " + dmi.getMainboard(); + ResourceManager::get()->RegisterRGBController(rgb_controller); } else if((packet_length >= sizeof(FeaturePacket_112)) && (packet_length <= (sizeof(FeaturePacket_112) + 1))) { - MSIMysticLight112Controller* controller = new MSIMysticLight112Controller(dev, info->path); + MSIMysticLight112Controller* controller = new MSIMysticLight112Controller(dev, info->path, dmi_name); RGBController_MSIMysticLight112* rgb_controller = new RGBController_MSIMysticLight112(controller); - rgb_controller->name = "MSI " + dmi.getMainboard(); + ResourceManager::get()->RegisterRGBController(rgb_controller); } else // no supported length returned { - std::string name = "MSI " + dmi.getMainboard(); - LOG_INFO("No matching driver found for %s, packet length = %d", name.c_str(), packet_length); - return; + unsigned char second_buffer[1000]; + second_buffer[0] = 0x51; + + for(int i = 1; i < 1000; i++) + { + second_buffer[i] = 0x0; + } + + size_t packet_length_new_attempt = hid_get_feature_report(dev, second_buffer, 1000); + + if(packet_length_new_attempt >=290 && packet_length_new_attempt <= 291) + { + MSIMysticLight761Controller* controller = new MSIMysticLight761Controller(dev, info->path, info->product_id, dmi_name); + RGBController_MSIMysticLight761* rgb_controller = new RGBController_MSIMysticLight761(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + + } + else + { + LOG_INFO("No matching driver found for %s, packet length = %d", dmi_name.c_str(), packet_length); + return; + } } } } - void DetectMSIMysticLight64Controllers ( hid_device_info* info, @@ -81,10 +114,12 @@ void DetectMSIMysticLight64Controllers ) { hid_device* dev = hid_open_path(info->path); + if(dev != nullptr) { MSIMysticLight64Controller* controller = new MSIMysticLight64Controller(dev, info->path); RGBController_MSIMysticLight64* rgb_controller = new RGBController_MSIMysticLight64(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -129,11 +164,13 @@ REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7C94", DetectMSIMysticLightCont REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7C95", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7C95, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7C98", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7C98, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D03", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D03, 0x0001, 0x00); +REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D04", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D04, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D06", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D06, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D07", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D07, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D08", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D08, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D09", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D09, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D13", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D13, 0x0001, 0x00); +REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D14", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D14, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D15", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D15, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D17", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D17, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D18", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D18, 0x0001, 0x00); @@ -146,8 +183,10 @@ REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D29", DetectMSIMysticLightCont REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D30", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D30, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D31", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D31, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D32", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D32, 0x0001, 0x00); +REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D33", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D33, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D36", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D36, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D38", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D38, 0x0001, 0x00); +REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D40", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D40, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D41", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D41, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D42", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D42, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D43", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D43, 0x0001, 0x00); @@ -162,17 +201,40 @@ REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D67", DetectMSIMysticLightCont REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D69", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D69, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D70", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D70, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D73", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D73, 0x0001, 0x00); +REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D74", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D74, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D75", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D75, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D76", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D76, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D77", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D77, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D78", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D78, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D86", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D86, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D89", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D89, 0x0001, 0x00); +REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D90", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D90, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D91", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D91, 0x0001, 0x00); +REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D93", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D93, 0x0001, 0x00); +REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D96", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D96, 0x0001, 0x00); +REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D97", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D97, 0x0001, 0x00); +REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D98", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D98, 0x0001, 0x00); +REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7D99", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7D99, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E01", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7E01, 0x0001, 0x00); +REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E03", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7E03, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E06", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7E06, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E07", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7E07, 0x0001, 0x00); +REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E10", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7E10, 0x0001, 0x00); +REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_7E49", DetectMSIMysticLightControllers, MSI_USB_VID, 0x7E49, 0x0001, 0x00); REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_B926", DetectMSIMysticLightControllers, MSI_USB_VID, 0xB926, 0x0001, 0x00); +// Detector for the set of common boards +REGISTER_HID_DETECTOR_PU("MSI Mystic Light Common", DetectMSIMysticLightControllers, MSI_USB_VID_COMMON, MSI_USB_PID_COMMON, 0x0001, 0x00); +REGISTER_HID_DETECTOR_PU("MSI Mystic Light X870", DetectMSIMysticLightControllers, MSI_USB_VID_COMMON, MSI_USB_PID_COMMON, 0xFF00, 0x01); +/*---------------------------------------------------------------------------------------------------------*\ +| Dummy entries for boards using commwn VID and PID | +| | +| DUMMY_DEVICE_DETECTOR("MSI Mystic Light MS_7E12", DetectMSIMysticLightControllers, 0x1462, 0x7E12 ) | +| DUMMY_DEVICE_DETECTOR("MSI Mystic Light MS_7E16", DetectMSIMysticLightControllers, 0x1462, 0x7E16 ) | +| DUMMY_DEVICE_DETECTOR("MSI Mystic Light MS_7E24", DetectMSIMysticLightControllers, 0x1462, 0x7E24 ) | +| DUMMY_DEVICE_DETECTOR("MSI Mystic Light MS_7E26", DetectMSIMysticLightControllers, 0x1462, 0x7E26 ) | +| DUMMY_DEVICE_DETECTOR("MSI Mystic Light MS_7E27", DetectMSIMysticLightControllers, 0x1462, 0x7E27 ) | +\*---------------------------------------------------------------------------------------------------------*/ + #ifdef ENABLE_UNTESTED_MYSTIC_LIGHT REGISTER_HID_DETECTOR_PU("MSI Mystic Light MS_3EA4", DetectMSIMysticLightControllers, MSI_USB_VID, 0x3EA4, 0x0001, 0x00); diff --git a/Controllers/MSIMysticLightController/RGBController_MSIMysticLight112.h b/Controllers/MSIMysticLightController/RGBController_MSIMysticLight112.h deleted file mode 100644 index cf1cabf1..00000000 --- a/Controllers/MSIMysticLightController/RGBController_MSIMysticLight112.h +++ /dev/null @@ -1,48 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_MSIMysticLight112.h | -| | -| Generic RGB Interface for OpenRGB | -| MSI Mystic Light (112-byte) USB Driver | -| | -| thombo 12/17/2022 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "MSIMysticLight112Controller.h" -#include - -class RGBController_MSIMysticLight112: public RGBController -{ -public: - RGBController_MSIMysticLight112(MSIMysticLight112Controller* controller_ptr); - ~RGBController_MSIMysticLight112(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - void SetupModes(); - void UpdateLed - ( - int zone, - int led - ); - void SetupMode - ( - const char *name, - MSI_MODE mode, - unsigned int flags - ); - int GetDeviceMode(); - void GetDeviceConfig(); - - MSIMysticLight112Controller* controller; -}; diff --git a/Controllers/MSIMysticLightController/RGBController_MSIMysticLight162.h b/Controllers/MSIMysticLightController/RGBController_MSIMysticLight162.h deleted file mode 100644 index dddd4d54..00000000 --- a/Controllers/MSIMysticLightController/RGBController_MSIMysticLight162.h +++ /dev/null @@ -1,48 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_MSIMysticLight162.h | -| | -| Generic RGB Interface for OpenRGB | -| MSI Mystic Light (162-byte) USB Driver | -| | -| T-bond 3/4/2020 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "MSIMysticLight162Controller.h" -#include - -class RGBController_MSIMysticLight162: public RGBController -{ -public: - RGBController_MSIMysticLight162(MSIMysticLight162Controller* controller_ptr); - ~RGBController_MSIMysticLight162(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - void SetupModes(); - void UpdateLed - ( - int zone, - int led - ); - void SetupMode - ( - const char *name, - MSI_MODE mode, - unsigned int flags - ); - int GetDeviceMode(); - void GetDeviceConfig(); - - MSIMysticLight162Controller* controller; -}; diff --git a/Controllers/MSIMysticLightController/RGBController_MSIMysticLight185.h b/Controllers/MSIMysticLightController/RGBController_MSIMysticLight185.h deleted file mode 100644 index 7a8ca18b..00000000 --- a/Controllers/MSIMysticLightController/RGBController_MSIMysticLight185.h +++ /dev/null @@ -1,50 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_MSIMysticLight185.h | -| | -| Generic RGB Interface for OpenRGB | -| MSI Mystic Light (185-byte) USB Driver | -| | -| T-bond 3/4/2020 | -| Adam Honse 3/6/2021 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "MSIMysticLight185Controller.h" -#include - -class RGBController_MSIMysticLight185: public RGBController -{ -public: - RGBController_MSIMysticLight185(MSIMysticLight185Controller* controller_ptr); - ~RGBController_MSIMysticLight185(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - void SetupModes(); - void UpdateLed - ( - int zone, - int led - ); - void SetupMode - ( - const char *name, - MSI_MODE mode, - unsigned int flags - ); - int GetDeviceMode(); - void GetDeviceConfig(); - - MSIMysticLight185Controller* controller; - MSI_ZONE last_resizable_zone; -}; diff --git a/Controllers/MSIMysticLightController/RGBController_MSIMysticLight64.h b/Controllers/MSIMysticLightController/RGBController_MSIMysticLight64.h deleted file mode 100644 index 75429a4b..00000000 --- a/Controllers/MSIMysticLightController/RGBController_MSIMysticLight64.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#include "RGBController.h" -#include "MSIMysticLight64Controller.h" - -class RGBController_MSIMysticLight64 : public RGBController -{ -public: - RGBController_MSIMysticLight64(MSIMysticLight64Controller* controller_ptr); - ~RGBController_MSIMysticLight64(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - MSIMysticLight64Controller* controller; - void SetupModes(); - void SetupMode - ( - const char *name, - MSI_64_MODE mode, - unsigned int flags - ); -}; \ No newline at end of file diff --git a/Controllers/MSIOptixController/MSIOptixController.cpp b/Controllers/MSIOptixController/MSIOptixController.cpp index ca00deba..68f4e097 100644 --- a/Controllers/MSIOptixController/MSIOptixController.cpp +++ b/Controllers/MSIOptixController/MSIOptixController.cpp @@ -1,33 +1,23 @@ -/*-----------------------------------------*\ -| MSIOptixController.cpp | -| | -| Driver for MSI Optix monitor lighting | -| controller | -| | -| Guimard Morgan (morg) 1/10/2022 | -\*-----------------------------------------*/ -#include "MSIOptixController.h" +/*---------------------------------------------------------*\ +| MSIOptixController.cpp | +| | +| Driver for MSI Optix | +| | +| Morgan Guimard (morg) 10 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include +#include "MSIOptixController.h" +#include "StringUtils.h" -MSIOptixController::MSIOptixController(hid_device* dev_handle, const hid_device_info& info) +MSIOptixController::MSIOptixController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) { - dev = dev_handle; - location = info.path; - version = ""; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } - + dev = dev_handle; + location = info.path; + name = dev_name; } MSIOptixController::~MSIOptixController() @@ -40,14 +30,22 @@ std::string MSIOptixController::GetDeviceLocation() return("HID: " + location); } -std::string MSIOptixController::GetSerialString() +std::string MSIOptixController::GetNameString() { - return(serial_number); + return(name); } -std::string MSIOptixController::GetFirmwareVersion() +std::string MSIOptixController::GetSerialString() { - return(version); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } unsigned char MSIOptixController::GetMysteriousFlag(unsigned char mode_value) @@ -205,7 +203,7 @@ void MSIOptixController::SetMode(std::vector colors, unsigned char bri } else if(mode_flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR) - { + { for(unsigned int i = 0; i < MSI_OPTIX_COLOR_PACKET_SIZE; i++) { usb_buf[++offset] = red; diff --git a/Controllers/MSIOptixController/MSIOptixController.h b/Controllers/MSIOptixController/MSIOptixController.h index 14b05364..9d84dde4 100644 --- a/Controllers/MSIOptixController/MSIOptixController.h +++ b/Controllers/MSIOptixController/MSIOptixController.h @@ -1,16 +1,19 @@ -/*-----------------------------------------*\ -| MSIOptixController.h | -| | -| Driver for MSI Optix monitor lighting | -| controller - header file | -| | -| Guimard Morgan (morg) 1/10/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| MSIOptixController.h | +| | +| Driver for MSI Optix | +| | +| Morgan Guimard (morg) 10 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once -#include "RGBController.h" #include -#include +#include +#include "RGBController.h" #define MSI_OPTIX_REPORT_SIZE 168 #define MSI_OPTIX_COLOR_PACKET_SIZE 48 @@ -64,12 +67,12 @@ enum class MSIOptixController { public: - MSIOptixController(hid_device* dev_handle, const hid_device_info& info); + MSIOptixController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); ~MSIOptixController(); - std::string GetSerialString(); std::string GetDeviceLocation(); - std::string GetFirmwareVersion(); + std::string GetNameString(); + std::string GetSerialString(); void SetDirect(std::vector colors, unsigned char brightness); void SetMode(std::vector colors, unsigned char brightness, unsigned char speed, unsigned char mode_value, unsigned int mode_flags); @@ -79,8 +82,7 @@ protected: private: std::string location; - std::string serial_number; - std::string version; + std::string name; unsigned char GetMysteriousFlag(unsigned char mode_value); }; diff --git a/Controllers/MSIOptixController/MSIOptixControllerDetect.cpp b/Controllers/MSIOptixController/MSIOptixControllerDetect.cpp index 61ffc553..5172720c 100644 --- a/Controllers/MSIOptixController/MSIOptixControllerDetect.cpp +++ b/Controllers/MSIOptixController/MSIOptixControllerDetect.cpp @@ -1,6 +1,16 @@ +/*---------------------------------------------------------*\ +| MSIOptixControllerDetect.cpp | +| | +| Detector for MSI Optix | +| | +| Morgan Guimard (morg) 10 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "MSIOptixController.h" -#include "RGBController.h" #include "RGBController_MSIOptix.h" /*---------------------------------------------------------*\ @@ -19,9 +29,9 @@ void DetectMSIOptixControllers(hid_device_info* info, const std::string& name) if(dev) { - MSIOptixController* controller = new MSIOptixController(dev, *info); + MSIOptixController* controller = new MSIOptixController(dev, *info, name); RGBController_MSIOptix* rgb_controller = new RGBController_MSIOptix(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } diff --git a/Controllers/MSIOptixController/RGBController_MSIOptix.cpp b/Controllers/MSIOptixController/RGBController_MSIOptix.cpp index 3b28106c..3fdc0933 100644 --- a/Controllers/MSIOptixController/RGBController_MSIOptix.cpp +++ b/Controllers/MSIOptixController/RGBController_MSIOptix.cpp @@ -1,16 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_MSIOptix.cpp | -| | -| Generic RGB Interface for OpenRGB | -| MSIOptix USB Driver | -| | -| Guimard Morgan (morg) 1/10/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_MSIOptix.cpp | +| | +| RGBController for MSI Optix | +| | +| Morgan Guimard (morg) 10 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_MSIOptix.h" - -#include #include +#include +#include "RGBController_MSIOptix.h" /**------------------------------------------------------------------*\ @name MSI Optix @@ -26,13 +27,12 @@ RGBController_MSIOptix::RGBController_MSIOptix(MSIOptixController* controller_ptr) { controller = controller_ptr; - name = "MSI Optix USB Device"; + name = controller->GetNameString(); vendor = "MSI"; type = DEVICE_TYPE_LEDSTRIP; - description = name; + description = "MSI Optix USB Device"; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); mode Direct; Direct.name = "Direct"; diff --git a/Controllers/MSIOptixController/RGBController_MSIOptix.h b/Controllers/MSIOptixController/RGBController_MSIOptix.h index 74f3ca01..11cb4610 100644 --- a/Controllers/MSIOptixController/RGBController_MSIOptix.h +++ b/Controllers/MSIOptixController/RGBController_MSIOptix.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_MSIOptix.h | -| | -| Generic RGB Interface for OpenRGB | -| MISOptix RGB USB Driver | -| | -| Guimard Morgan (morg) 1/10/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_MSIOptix.h | +| | +| RGBController for MSI Optix | +| | +| Morgan Guimard (morg) 10 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/MSIRGBController/MSIRGBController.cpp b/Controllers/MSIRGBController/MSIRGBController.cpp index 2c3dba38..bc1d60d0 100644 --- a/Controllers/MSIRGBController/MSIRGBController.cpp +++ b/Controllers/MSIRGBController/MSIRGBController.cpp @@ -1,21 +1,24 @@ -/*-----------------------------------------*\ -| MSIRGBController.cpp | -| | -| Driver for MSI-RGB lighting controller | -| | -| Logic adapted from: | -| https://github.com/nagisa/msi-rgb | -| | -| Adam Honse (CalcProgrammer1) 2/11/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| MSIRGBController.cpp | +| | +| Driver for MSI-RGB motherboard | +| | +| Logic adapted from https://github.com/nagisa/msi-rgb | +| | +| Adam Honse (CalcProgrammer1) 11 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "MSIRGBController.h" -#include "dependencies/dmiinfo.h" +#include "dmiinfo.h" #include "super_io.h" -MSIRGBController::MSIRGBController(int sioaddr, bool invert) +MSIRGBController::MSIRGBController(int sioaddr, bool invert, std::string dev_name) { msi_sioaddr = sioaddr; + name = dev_name; /*-----------------------------------------------------*\ | This setup step isn't well documented | @@ -29,7 +32,6 @@ MSIRGBController::MSIRGBController(int sioaddr, bool invert) val_at_2c |= 0b00010000; superio_outb(msi_sioaddr, 0x2C, val_at_2c); - /*-----------------------------------------------------*\ | Set logical device register to RGB controller | @@ -73,6 +75,18 @@ MSIRGBController::~MSIRGBController() } +std::string MSIRGBController::GetDeviceLocation() +{ + char hex[12]; + snprintf(hex, sizeof(hex), "0x%X", msi_sioaddr); + return("SIO: " + std::string(hex)); +} + +std::string MSIRGBController::GetDeviceName() +{ + return(name); +} + void MSIRGBController::SetColor(unsigned char red, unsigned char green, unsigned char blue) { /*-----------------------------------------------------*\ @@ -108,4 +122,4 @@ void MSIRGBController::SetColor(unsigned char red, unsigned char green, unsigned superio_outb(msi_sioaddr, MSI_SIO_RGB_REG_BLUE_3_2, (blue | (blue << 4))); superio_outb(msi_sioaddr, MSI_SIO_RGB_REG_BLUE_5_4, (blue | (blue << 4))); superio_outb(msi_sioaddr, MSI_SIO_RGB_REG_BLUE_7_6, (blue | (blue << 4))); -} \ No newline at end of file +} diff --git a/Controllers/MSIRGBController/MSIRGBController.h b/Controllers/MSIRGBController/MSIRGBController.h index f6d3b13e..86eb04d5 100644 --- a/Controllers/MSIRGBController/MSIRGBController.h +++ b/Controllers/MSIRGBController/MSIRGBController.h @@ -1,17 +1,19 @@ -/*-----------------------------------------*\ -| MSIRGBController.h | -| | -| Definitions and types for MSI-RGB | -| lighting controller | -| | -| Logic adapted from: | -| https://github.com/nagisa/msi-rgb | -| | -| Adam Honse (CalcProgrammer1) 2/11/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| MSIRGBController.h | +| | +| Driver for MSI-RGB motherboard | +| | +| Logic adapted from https://github.com/nagisa/msi-rgb | +| | +| Adam Honse (CalcProgrammer1) 11 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include -#pragma once #define MSI_SIO_LOGDEV_RGB 0x12 @@ -40,7 +42,7 @@ enum class MSIRGBController { public: - MSIRGBController(int sioaddr, bool invert); + MSIRGBController(int sioaddr, bool invert, std::string dev_name); ~MSIRGBController(); std::string GetDeviceName(); @@ -51,5 +53,6 @@ public: void SetColor(unsigned char red, unsigned char green, unsigned char blue); private: - int msi_sioaddr; -}; \ No newline at end of file + int msi_sioaddr; + std::string name; +}; diff --git a/Controllers/MSIRGBController/MSIRGBControllerDetect.cpp b/Controllers/MSIRGBController/MSIRGBControllerDetect.cpp index 756ca30e..befa5717 100644 --- a/Controllers/MSIRGBController/MSIRGBControllerDetect.cpp +++ b/Controllers/MSIRGBController/MSIRGBControllerDetect.cpp @@ -1,12 +1,19 @@ +/*---------------------------------------------------------*\ +| MSIRGBControllerDetect.cpp | +| | +| Detector for MSI-RGB motherboard | +| | +| Adam Honse (CalcProgrammer1) 11 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "MSIRGBController.h" -#include "RGBController.h" #include "RGBController_MSIRGB.h" #include "super_io.h" -#include "dependencies/dmiinfo.h" -#include -#include -#include +#include "dmiinfo.h" /******************************************************************************************\ * * @@ -75,6 +82,7 @@ static msi_device compatible_devices[] = {"7C39", true }, {"7B86", true }, {"7B87", true }, + {"7D95", false} }; void DetectMSIRGBControllers() @@ -106,9 +114,8 @@ void DetectMSIRGBControllers() { if (board_dmi.find(std::string(compatible_devices[i].name)) != std::string::npos) { - MSIRGBController* controller = new MSIRGBController(sioaddr, compatible_devices[i].invert); + MSIRGBController* controller = new MSIRGBController(sioaddr, compatible_devices[i].invert, "MSI " + board_dmi); RGBController_MSIRGB* rgb_controller = new RGBController_MSIRGB(controller); - rgb_controller->name = "MSI " + board_dmi; ResourceManager::get()->RegisterRGBController(rgb_controller); break; diff --git a/Controllers/MSIRGBController/RGBController_MSIRGB.cpp b/Controllers/MSIRGBController/RGBController_MSIRGB.cpp index b3bf9805..549787a1 100644 --- a/Controllers/MSIRGBController/RGBController_MSIRGB.cpp +++ b/Controllers/MSIRGBController/RGBController_MSIRGB.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_MSIRGB.cpp | -| | -| Generic RGB Interface for MSI-RGB | -| | -| Adam Honse (CalcProgrammer1) 2/14/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_MSIRGB.cpp | +| | +| RGBController for MSI-RGB motherboard | +| | +| Adam Honse (CalcProgrammer1) 14 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_MSIRGB.h" @@ -21,18 +24,19 @@ RGBController_MSIRGB::RGBController_MSIRGB(MSIRGBController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "MSI Motherboard"; - vendor = "MSI"; - type = DEVICE_TYPE_MOTHERBOARD; - description = "MSI-RGB Device"; + name = controller->GetDeviceName(); + vendor = "MSI"; + type = DEVICE_TYPE_MOTHERBOARD; + description = "MSI-RGB Device"; + location = controller->GetDeviceLocation(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + 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(); diff --git a/Controllers/MSIRGBController/RGBController_MSIRGB.h b/Controllers/MSIRGBController/RGBController_MSIRGB.h index ef77243c..19c030fd 100644 --- a/Controllers/MSIRGBController/RGBController_MSIRGB.h +++ b/Controllers/MSIRGBController/RGBController_MSIRGB.h @@ -1,12 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_MSIRGB.h | -| | -| Generic RGB Interface for MSI-RGB | -| | -| Adam Honse (CalcProgrammer1) 2/14/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_MSIRGB.h | +| | +| RGBController for MSI-RGB motherboard | +| | +| Adam Honse (CalcProgrammer1) 14 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "MSIRGBController.h" diff --git a/Controllers/MSIVigorController/MSIVigorControllerDetect.cpp b/Controllers/MSIVigorController/MSIVigorControllerDetect.cpp index f7b0dd98..e95380da 100644 --- a/Controllers/MSIVigorController/MSIVigorControllerDetect.cpp +++ b/Controllers/MSIVigorController/MSIVigorControllerDetect.cpp @@ -1,6 +1,16 @@ +/*---------------------------------------------------------*\ +| MSIVigorControllerDetect.cpp | +| | +| Detector for MSI Vigor | +| | +| Morgan Guimard (morg) 01 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "MSIVigorGK30Controller.h" -#include "RGBController.h" #include "RGBController_MSIVigorGK30.h" /*---------------------------------------------------------*\ @@ -19,9 +29,8 @@ void DetectMSIVigorGK30Controllers(hid_device_info* info, const std::string& nam if(dev) { - MSIVigorGK30Controller* controller = new MSIVigorGK30Controller(dev, *info); + MSIVigorGK30Controller* controller = new MSIVigorGK30Controller(dev, *info, name); RGBController_MSIVigorGK30* rgb_controller = new RGBController_MSIVigorGK30(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } diff --git a/Controllers/MSIVigorController/MSIVigorGK30Controller.cpp b/Controllers/MSIVigorController/MSIVigorGK30Controller.cpp index 3847eb55..ad53b0e8 100644 --- a/Controllers/MSIVigorController/MSIVigorGK30Controller.cpp +++ b/Controllers/MSIVigorController/MSIVigorGK30Controller.cpp @@ -1,14 +1,18 @@ -/*-----------------------------------------*\ -| MSIVigorGK30Controller.cpp | -| | -| Driver for MSI Vigor GK 30 keyboard | -| controller | -| | -| Guimard Morgan (morg) 6/01/2022 | -\*-----------------------------------------*/ -#include "MSIVigorGK30Controller.h" -#include +/*---------------------------------------------------------*\ +| MSIVigorGK30Controller.cpp | +| | +| Driver for MSI Vigor GK30 | +| | +| Morgan Guimard (morg) 01 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include +#include +#include "MSIVigorGK30Controller.h" +#include "StringUtils.h" static unsigned char argb_colour_index_data[2][2][2] = { //B0 B1 @@ -18,25 +22,11 @@ static unsigned char argb_colour_index_data[2][2][2] = { 0x01, 0x06 }, } //G1 R1 }; -MSIVigorGK30Controller::MSIVigorGK30Controller(hid_device* dev_handle, const hid_device_info& info) +MSIVigorGK30Controller::MSIVigorGK30Controller(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) { - dev = dev_handle; - location = info.path; - version = ""; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } - + dev = dev_handle; + location = info.path; + name = dev_name; } MSIVigorGK30Controller::~MSIVigorGK30Controller() @@ -49,14 +39,22 @@ std::string MSIVigorGK30Controller::GetDeviceLocation() return("HID: " + location); } -std::string MSIVigorGK30Controller::GetSerialString() +std::string MSIVigorGK30Controller::GetNameString() { - return(serial_number); + return(name); } -std::string MSIVigorGK30Controller::GetFirmwareVersion() +std::string MSIVigorGK30Controller::GetSerialString() { - return(version); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } unsigned int MSIVigorGK30Controller::GetLargestColour(unsigned int red, unsigned int green, unsigned int blue) @@ -89,9 +87,9 @@ unsigned char MSIVigorGK30Controller::GetColourIndex(unsigned char red, unsigned | 0x06 white | \*-----------------------------------------------------*/ unsigned int divisor = GetLargestColour( red, green, blue); - unsigned int r = round( red / divisor ); - unsigned int g = round( green / divisor ); - unsigned int b = round( blue / divisor ); + unsigned int r = (unsigned int)round( red / divisor ); + unsigned int g = (unsigned int)round( green / divisor ); + unsigned int b = (unsigned int)round( blue / divisor ); unsigned char idx = argb_colour_index_data[r][g][b]; return idx; } diff --git a/Controllers/MSIVigorController/MSIVigorGK30Controller.h b/Controllers/MSIVigorController/MSIVigorGK30Controller.h index f5c288f5..7d1670af 100644 --- a/Controllers/MSIVigorController/MSIVigorGK30Controller.h +++ b/Controllers/MSIVigorController/MSIVigorGK30Controller.h @@ -1,16 +1,19 @@ -/*-----------------------------------------*\ -| MSIVigorGK30Controller.h | -| | -| Driver for MSI Vigor GK 30 keyboard | -| controller - header file | -| | -| Guimard Morgan (morg) 6/01/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| MSIVigorGK30Controller.h | +| | +| Driver for MSI Vigor GK30 | +| | +| Morgan Guimard (morg) 01 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once -#include "RGBController.h" #include -#include +#include +#include "RGBController.h" #define MSI_VIGOR_GK30_REPORT_SIZE 8 #define MSI_VIGOR_GK30_LEDS_COUNT 6 @@ -43,12 +46,12 @@ enum class MSIVigorGK30Controller { public: - MSIVigorGK30Controller(hid_device* dev_handle, const hid_device_info& info); + MSIVigorGK30Controller(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); ~MSIVigorGK30Controller(); - std::string GetSerialString(); std::string GetDeviceLocation(); - std::string GetFirmwareVersion(); + std::string GetNameString(); + std::string GetSerialString(); void SetMode(std::vector colors, unsigned char brightness, @@ -68,8 +71,6 @@ private: unsigned char GetColourIndex(unsigned char red, unsigned char green, unsigned char blue); std::string location; + std::string name; std::string serial_number; - std::string version; - - unsigned char color_test = 0x00; }; diff --git a/Controllers/MSIVigorController/RGBController_MSIVigorGK30.cpp b/Controllers/MSIVigorController/RGBController_MSIVigorGK30.cpp index c9c969a3..d0b72361 100644 --- a/Controllers/MSIVigorController/RGBController_MSIVigorGK30.cpp +++ b/Controllers/MSIVigorController/RGBController_MSIVigorGK30.cpp @@ -1,16 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_MSIVigorGK30.cpp | -| | -| Generic RGB Interface for OpenRGB | -| MSI Vigor GK30 USB Driver | -| | -| Guimard Morgan (morg) 6/01/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_MSIVigorGK30.cpp | +| | +| RGBController for MSI Vigor GK30 | +| | +| Morgan Guimard (morg) 01 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_MSIVigorGK30.h" - -#include #include +#include +#include "RGBController_MSIVigorGK30.h" /**------------------------------------------------------------------*\ @name MSI Vigor GK30 @@ -26,13 +27,13 @@ RGBController_MSIVigorGK30::RGBController_MSIVigorGK30(MSIVigorGK30Controller* controller_ptr) { controller = controller_ptr; - name = "MSI VigorGK30 USB Device"; + + name = controller->GetNameString(); vendor = "MSI"; type = DEVICE_TYPE_KEYBOARD; - description = name; + description = "MSI VigorGK30 USB Device"; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); mode Custom; Custom.name = "Custom"; @@ -101,7 +102,7 @@ RGBController_MSIVigorGK30::RGBController_MSIVigorGK30(MSIVigorGK30Controller* c Meteor.speed = MSI_VIGOR_GK30_SPEED_MIN; Meteor.speed_min = MSI_VIGOR_GK30_SPEED_MIN; Meteor.speed_max = MSI_VIGOR_GK30_SPEED_MAX; - Rainbow.direction = MODE_DIRECTION_LEFT; + Meteor.direction = MODE_DIRECTION_LEFT; modes.push_back(Meteor); mode Ripple; diff --git a/Controllers/MSIVigorController/RGBController_MSIVigorGK30.h b/Controllers/MSIVigorController/RGBController_MSIVigorGK30.h index 8fdb60c7..bb234185 100644 --- a/Controllers/MSIVigorController/RGBController_MSIVigorGK30.h +++ b/Controllers/MSIVigorController/RGBController_MSIVigorGK30.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_MSIVigorGK30.h | -| | -| Generic RGB Interface for OpenRGB | -| MIS Vigor GK30 RGB USB Driver | -| | -| Guimard Morgan (morg) 6/01/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_MSIVigorGK30.h | +| | +| RGBController for MSI Vigor GK30 | +| | +| Morgan Guimard (morg) 01 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/MadCatzCyborgController/MadCatzCyborgController.cpp b/Controllers/MadCatzCyborgController/MadCatzCyborgController.cpp new file mode 100644 index 00000000..f507f3b1 --- /dev/null +++ b/Controllers/MadCatzCyborgController/MadCatzCyborgController.cpp @@ -0,0 +1,99 @@ +/*---------------------------------------------------------*\ +| MadCatzCyborgController.cpp | +| | +| Driver for MadCatz Cyborg Gaming Light | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "MadCatzCyborgController.h" +#include "StringUtils.h" +#include + +MadCatzCyborgController::MadCatzCyborgController(hid_device* dev_handle, const char* path) +{ + dev = dev_handle; + location = path; +} + +MadCatzCyborgController::~MadCatzCyborgController() +{ + if(dev != nullptr) + { + hid_close(dev); + dev = nullptr; + } +} + +std::string MadCatzCyborgController::GetDeviceLocation() +{ + return(location); +} + +std::string MadCatzCyborgController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void MadCatzCyborgController::Initialize() +{ + if(dev == nullptr) + { + return; + } + + // Enable the device + unsigned char enable_buf[2] = { CMD_ENABLE, 0x00 }; + hid_send_feature_report(dev, enable_buf, 2); +} + +void MadCatzCyborgController::SetLEDColor(unsigned char red, unsigned char green, unsigned char blue) +{ + if(dev == nullptr) + { + return; + } + + // Format: [CMD_COLOR][0x00][R][G][B][0x00][0x00][0x00][0x00] + unsigned char usb_buf[9] = + { + CMD_COLOR, + 0x00, + red, + green, + blue, + 0x00, + 0x00, + 0x00, + 0x00 + }; + + hid_send_feature_report(dev, usb_buf, 9); +} + +void MadCatzCyborgController::SetIntensity(unsigned char intensity) +{ + if(dev == nullptr) + { + return; + } + + // Clamp intensity to 0-100 + if(intensity > 100) + { + intensity = 100; + } + + // Format: [CMD_INTENSITY][0x00][intensity_value] + unsigned char usb_buf[3] = { CMD_INTENSITY, 0x00, intensity }; + hid_send_feature_report(dev, usb_buf, 3); +} diff --git a/Controllers/MadCatzCyborgController/MadCatzCyborgController.h b/Controllers/MadCatzCyborgController/MadCatzCyborgController.h new file mode 100644 index 00000000..348f7681 --- /dev/null +++ b/Controllers/MadCatzCyborgController/MadCatzCyborgController.h @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| MadCatzCyborgController.h | +| | +| Driver for MadCatz Cyborg Gaming Light | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include + +class MadCatzCyborgController +{ +public: + MadCatzCyborgController(hid_device* dev_handle, const char* path); + ~MadCatzCyborgController(); + + std::string GetDeviceLocation(); + std::string GetSerialString(); + + void Initialize(); + void SetLEDColor(unsigned char red, unsigned char green, unsigned char blue); + void SetIntensity(unsigned char intensity); + +private: + hid_device* dev; + std::string location; + + // Protocol constants + enum Commands + { + CMD_ENABLE = 0xA1, + CMD_COLOR = 0xA2, + CMD_INTENSITY = 0xA6 + }; +}; diff --git a/Controllers/MadCatzCyborgController/MadCatzCyborgControllerDetect.cpp b/Controllers/MadCatzCyborgController/MadCatzCyborgControllerDetect.cpp new file mode 100644 index 00000000..3b80f9a4 --- /dev/null +++ b/Controllers/MadCatzCyborgController/MadCatzCyborgControllerDetect.cpp @@ -0,0 +1,44 @@ +/*---------------------------------------------------------*\ +| MadCatzCyborgControllerDetect.cpp | +| | +| Detector for MadCatz Cyborg Gaming Light | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "MadCatzCyborgController.h" +#include "RGBController_MadCatzCyborg.h" +#include + +/*-----------------------------------------------------*\ +| MadCatz Cyborg VID/PID | +\*-----------------------------------------------------*/ +#define MADCATZ_VID 0x06A3 +#define MADCATZ_CYBORG_PID 0x0DC5 + +/******************************************************************************************\ +* * +* DetectMadCatzCyborgControllers * +* * +* Tests the USB address to find MadCatz Cyborg Gaming Light devices * +* * +\******************************************************************************************/ + +void DetectMadCatzCyborgControllers(hid_device_info* info, const std::string& /*name*/) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + MadCatzCyborgController* controller = new MadCatzCyborgController(dev, info->path); + controller->Initialize(); + + RGBController_MadCatzCyborg* rgb_controller = new RGBController_MadCatzCyborg(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR("MadCatz Cyborg Gaming Light", DetectMadCatzCyborgControllers, MADCATZ_VID, MADCATZ_CYBORG_PID); diff --git a/Controllers/MadCatzCyborgController/RGBController_MadCatzCyborg.cpp b/Controllers/MadCatzCyborgController/RGBController_MadCatzCyborg.cpp new file mode 100644 index 00000000..6ae71ea7 --- /dev/null +++ b/Controllers/MadCatzCyborgController/RGBController_MadCatzCyborg.cpp @@ -0,0 +1,104 @@ +/*---------------------------------------------------------*\ +| RGBController_MadCatzCyborg.cpp | +| | +| RGB Controller for MadCatz Cyborg Gaming Light | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_MadCatzCyborg.h" + +/**--------------------------------------------------------*\ + @name MadCatz Cyborg Gaming Light + @category Accessory + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectMadCatzCyborgControllers + @comment The MadCatz Cyborg Gaming Light is an ambient lighting device. +\*---------------------------------------------------------*/ + +RGBController_MadCatzCyborg::RGBController_MadCatzCyborg(MadCatzCyborgController* controller_ptr) +{ + controller = controller_ptr; + + name = "MadCatz Cyborg Gaming Light"; + vendor = "MadCatz"; + type = DEVICE_TYPE_ACCESSORY; + description = "MadCatz Cyborg Gaming Light"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = 0; + Direct.brightness_max = 100; + Direct.brightness = 100; + modes.push_back(Direct); + + SetupZones(); + + controller->SetIntensity(modes[active_mode].brightness); +} + +RGBController_MadCatzCyborg::~RGBController_MadCatzCyborg() +{ + delete controller; +} + +void RGBController_MadCatzCyborg::SetupZones() +{ + zone cyborg_zone; + + cyborg_zone.name = "Cyborg"; + cyborg_zone.type = ZONE_TYPE_SINGLE; + cyborg_zone.leds_min = 1; + cyborg_zone.leds_max = 1; + cyborg_zone.leds_count = 1; + cyborg_zone.matrix_map = NULL; + + zones.push_back(cyborg_zone); + + led cyborg_led; + cyborg_led.name = "LED"; + leds.push_back(cyborg_led); + + SetupColors(); +} + +void RGBController_MadCatzCyborg::ResizeZone(int /*zone*/, int /*new_size*/) +{ + // Single LED device - nothing to resize +} + +void RGBController_MadCatzCyborg::DeviceUpdateLEDs() +{ + if(colors.size() > 0) + { + RGBColor color = colors[0]; + controller->SetLEDColor(RGBGetRValue(color), RGBGetGValue(color), RGBGetBValue(color)); + } +} + +void RGBController_MadCatzCyborg::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_MadCatzCyborg::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_MadCatzCyborg::DeviceUpdateMode() +{ + if(modes[active_mode].flags & MODE_FLAG_HAS_BRIGHTNESS) + { + controller->SetIntensity(modes[active_mode].brightness); + } +} diff --git a/Controllers/MadCatzCyborgController/RGBController_MadCatzCyborg.h b/Controllers/MadCatzCyborgController/RGBController_MadCatzCyborg.h new file mode 100644 index 00000000..bfdaa866 --- /dev/null +++ b/Controllers/MadCatzCyborgController/RGBController_MadCatzCyborg.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------*\ +| RGBController_MadCatzCyborg.h | +| | +| RGB Controller for MadCatz Cyborg Gaming Light | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "MadCatzCyborgController.h" + +class RGBController_MadCatzCyborg : public RGBController +{ +public: + RGBController_MadCatzCyborg(MadCatzCyborgController* controller_ptr); + ~RGBController_MadCatzCyborg(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + MadCatzCyborgController* controller; +}; diff --git a/Controllers/MintakaKeyboardController/MintakaKeyboardController.cpp b/Controllers/MintakaKeyboardController/MintakaKeyboardController.cpp new file mode 100644 index 00000000..663c69a8 --- /dev/null +++ b/Controllers/MintakaKeyboardController/MintakaKeyboardController.cpp @@ -0,0 +1,302 @@ +/*---------------------------------------------------------*\ +| MintakaKeyboardController.cpp | +| | +| Driver for VSG Mintaka Devices keyboard lighting | +| Based on KeychronKeyboardController | +| | +| Federico Scodelaro (pudymody) 08 Oct 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "MintakaKeyboardController.h" +#include "StringUtils.h" + +using namespace std::chrono_literals; + +MintakaKeyboardController::MintakaKeyboardController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) +{ + dev = dev_handle; + location = info.path; + name = dev_name; + + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + serial_number = ""; + } + else + { + serial_number = StringUtils::wstring_to_string(serial_string); + } +} + +MintakaKeyboardController::~MintakaKeyboardController() +{ + hid_close(dev); +} + +std::string MintakaKeyboardController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string MintakaKeyboardController::GetNameString() +{ + return(name); +} + +std::string MintakaKeyboardController::GetSerialString() +{ + return(serial_number); +} + +void MintakaKeyboardController:: SetLedSequencePositions(std::vector positions) +{ + led_sequence_positions = positions; +} + +void MintakaKeyboardController::SetMode(std::vector modes, int active_mode, std::vector colors) +{ + /*-----------------------------------------*\ + | Turn customization on/off | + | Custom mode needs to turn it on | + \*-----------------------------------------*/ + SetCustomization(modes[active_mode].value == CUSTOM_MODE_VALUE); + + /*-----------------------------------------*\ + | Tells the device we're about to send the | + | pages (18 pages) | + \*-----------------------------------------*/ + StartEffectPage(); + + unsigned char usb_buf[PACKET_DATA_LENGTH]; + + /*-----------------------------------------*\ + | Configure the modes | + | LED Effect Page structure: | + | | + | OK.. this was from the original PDF | + | which appears to not be exact/up to date | + |-------------------------------------------| + | [0] Specialeffects mode1-32 | + | [1] colorFull color: 0x00 Monochrome:0x01 | + | [2] R Color ratio 0x00-0xFF | + | [3] G Color Ratio0x00-0xFF | + | [4] B Colour ratio0x00-0xFF | + | full color is 0,invalid | + | [5] dynamicdirection | + | left to right: 0x00 | + | right to left: 0x01 | + | down to up: 0x02 | + | up to down: 0x03 | + | [6] brightnesscontrol 0x00-0x0F | + | 0x0F brightest | + | [7] Periodiccontrol0x00-0x0F | + | 0x0F longest cycle | + | [8:13] Reserved | + | [14] Checkcode_L0xAA | + | [15] Checkcode_H0x55 | + |-------------------------------------------| + | Fixes: | + | color mode is 8th byte | + | brightness is 9th byte | + | speed is 10th byte | + | direction is 11th byte | + \*-----------------------------------------*/ + unsigned char selected_mode[EFFECT_PAGE_LENGTH]; + + for(unsigned int i = 0; i < 5; i++) // 5 packets + { + memset(usb_buf, 0x00, PACKET_DATA_LENGTH); + + for(unsigned int j = 0; j < 4; j++) // of 4 effects + { + const mode& m = modes[1 + j + i * 4]; // skip 1 first mode (Custom) + + int offset = j * EFFECT_PAGE_LENGTH; + + usb_buf[offset + 0] = m.value; // mode value + + if(m.flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR) + { + usb_buf[offset + 1] = RGBGetRValue(m.colors[0]); + usb_buf[offset + 2] = RGBGetGValue(m.colors[0]); + usb_buf[offset + 3] = RGBGetBValue(m.colors[0]); + } + + usb_buf[offset + 8] = m.color_mode == MODE_COLORS_RANDOM; // random switch + usb_buf[offset + 9] = m.brightness; + usb_buf[offset + 10] = m.speed; + usb_buf[offset + 11] = m.direction; + + usb_buf[offset + 14] = EFFECT_PAGE_CHECK_CODE_L; + usb_buf[offset + 15] = EFFECT_PAGE_CHECK_CODE_H; + + /*-----------------------------------------*\ + | Backup active mode values for later use | + | Custom and off share the same mode value | + \*-----------------------------------------*/ + if(m.value == modes[active_mode].value || (m.value == LIGHTS_OFF_MODE_VALUE && modes[active_mode].value == CUSTOM_MODE_VALUE)) + { + usb_buf[offset + 9] = modes[active_mode].brightness; + + for(unsigned int x = 0; x < EFFECT_PAGE_LENGTH; x++) + { + selected_mode[x] = usb_buf[offset+x]; + } + } + } + + Send(usb_buf); // Sends the packet + } + + // packets count sent: 5 + + /*-----------------------------------------*\ + | 3 times an empty packet - guess why... | + \*-----------------------------------------*/ + for(unsigned int i = 0; i < 3; i++) + { + memset(usb_buf, 0x00, PACKET_DATA_LENGTH); + Send(usb_buf); + } + + // packets count sent: 8 + + /*-----------------------------------------*\ + | Customization stuff | + | 9 times * 16 blocks 80 RR GG BB | + \*-----------------------------------------*/ + unsigned char color_buf[COLOR_BUF_SIZE]; + memset(color_buf, 0x00, COLOR_BUF_SIZE); + + for(unsigned int i = 0; i < COLOR_BUF_SIZE; i += 4) + { + color_buf[i] = 0x80; + } + + for(unsigned int c = 0; c < colors.size(); c++) + { + int offset = led_sequence_positions[c] * 4; + + color_buf[offset + 1] = RGBGetRValue(colors[c]); + color_buf[offset + 2] = RGBGetGValue(colors[c]); + color_buf[offset + 3] = RGBGetBValue(colors[c]); + } + + for(unsigned int p = 0; p < 9; p++) + { + memcpy(usb_buf, &color_buf[p * PACKET_DATA_LENGTH], PACKET_DATA_LENGTH); + Send(usb_buf); + } + + // packets count sent: 17 + + /*-----------------------------------------*\ + | Tells the device what the active mode is | + | This is the last packet | + \*-----------------------------------------*/ + memset(usb_buf, 0x00, PACKET_DATA_LENGTH); + memcpy(usb_buf, &selected_mode[0], EFFECT_PAGE_LENGTH); + Send(usb_buf); + + // packets count sent: 18 - let's hope the keyboard ACK in next frame + + /*-----------------------------------------*\ + | Tells the device that the pages are sent | + \*-----------------------------------------*/ + EndCommunication(); + + /*-----------------------------------------*\ + | Tells the device to apply what we've sent | + \*-----------------------------------------*/ + StartEffectCommand(); +} + +void MintakaKeyboardController::StartEffectCommand() +{ + unsigned char usb_buf[PACKET_DATA_LENGTH]; + memset(usb_buf, 0x00, PACKET_DATA_LENGTH); + + usb_buf[0x00] = PACKET_HEADER; + usb_buf[0x01] = LED_EFFECT_START_COMMAND; + + Send(usb_buf); +} + +void MintakaKeyboardController::StartEffectPage() +{ + /*-----------------------------------------*\ + | LED_SPECIAL_EFFECT_PACKETS: | + | Packet amount that will be sent in this | + | transaction | + \*-----------------------------------------*/ + unsigned char usb_buf[PACKET_DATA_LENGTH]; + memset(usb_buf, 0x00, PACKET_DATA_LENGTH); + + usb_buf[0x00] = PACKET_HEADER; + usb_buf[0x01] = WRITE_LED_SPECIAL_EFFECT_AREA_COMMAND; + usb_buf[0x08] = LED_SPECIAL_EFFECT_PACKETS; + + Send(usb_buf); + + Read(); +} + +void MintakaKeyboardController::SetCustomization(bool state) +{ + unsigned char usb_buf[PACKET_DATA_LENGTH]; + + memset(usb_buf, 0x00, PACKET_DATA_LENGTH); + usb_buf[0x00] = PACKET_HEADER; + usb_buf[0x01] = state ? TURN_ON_CUSTOMIZATION_COMMAND : TURN_OFF_CUSTOMIZATION_COMMAND; + Send(usb_buf); + + Read(); +} + +void MintakaKeyboardController::EndCommunication() +{ + unsigned char usb_buf[PACKET_DATA_LENGTH]; + memset(usb_buf, 0x00, PACKET_DATA_LENGTH); + + usb_buf[0x00] = PACKET_HEADER; + usb_buf[0x01] = COMMUNICATION_END_COMMAND; + + Send(usb_buf); + + Read(); +} + +void MintakaKeyboardController::Read() +{ + unsigned char usb_buf[PACKET_DATA_LENGTH+1]; + memset(usb_buf, 0x00, PACKET_DATA_LENGTH+1); + + usb_buf[0x00] = REPORT_ID; + + hid_get_feature_report(dev, usb_buf, PACKET_DATA_LENGTH+1); + + std::this_thread::sleep_for(10ms); +} + +void MintakaKeyboardController::Send(unsigned char data[PACKET_DATA_LENGTH]) +{ + unsigned char usb_buf[PACKET_DATA_LENGTH+1]; + + usb_buf[0] = REPORT_ID; + + for(unsigned int x = 0; x < PACKET_DATA_LENGTH; x++) + { + usb_buf[x+1] = data[x]; + } + + hid_send_feature_report(dev, usb_buf, PACKET_DATA_LENGTH+1); + + std::this_thread::sleep_for(10ms); +} diff --git a/Controllers/MintakaKeyboardController/MintakaKeyboardController.h b/Controllers/MintakaKeyboardController/MintakaKeyboardController.h new file mode 100644 index 00000000..1d9d949f --- /dev/null +++ b/Controllers/MintakaKeyboardController/MintakaKeyboardController.h @@ -0,0 +1,121 @@ +/*---------------------------------------------------------*\ +| MintakaKeyboardController.h | +| | +| Driver for VSG Mintaka Devices keyboard lighting | +| Based on KeychronKeyboardController | +| | +| Federico Scodelaro (pudymody) 08 Oct 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#pragma once + +#include "RGBController.h" +#include +#include + +#define REPORT_ID 0x00 +#define PACKET_DATA_LENGTH 64 +#define COLOR_BUF_SIZE 576 +#define EFFECT_PAGE_LENGTH 16 +#define LED_SPECIAL_EFFECT_PACKETS 0x12 +#define PACKET_HEADER 0x04 +#define EFFECT_PAGE_CHECK_CODE_L 0xAA +#define EFFECT_PAGE_CHECK_CODE_H 0x55 + +/*-----------------------------------------*\ +| Commands | +\*-----------------------------------------*/ +enum +{ + COMMUNICATION_END_COMMAND = 0x02, + GET_BASIC_INFO_COMMAND = 0x05, + READ_KEY_DEFINITION_AREA_COMMAND = 0x10, + WRITE_KEY_DEFINITION_AREA_COMMAND = 0x11, + READ_LED_EFFECT_DEFINITION_AREA_COMMAND = 0x12, + WRITE_LED_SPECIAL_EFFECT_AREA_COMMAND = 0x13, + READ_MACRO_DEFINITION_AREA_COMMAND = 0x14, + WRITE_MACRO_DEFINITION_AREA_COMMAND = 0x15, + READ_GAME_MODE_AREA_COMMAND = 0x16, + WRITE_GAME_MODE_AREA_COMMAND = 0x17, + TURN_ON_CUSTOMIZATION_COMMAND = 0x18, + TURN_OFF_CUSTOMIZATION_COMMAND = 0x19, + LED_EFFECT_START_COMMAND = 0xF0, + LED_SYNC_INITIAL_COMMAND = 0xF1, + LED_SYNC_START_COMMAND = 0xF2, + LED_SYNC_STOP_COMMAND = 0xF3, + RANDOM_PACKET_START_COMMAND = 0xAB, +}; + +/*-----------------------------------------*\ +| Modes | +\*-----------------------------------------*/ +enum +{ + CUSTOM_MODE_VALUE = 0x00, + STATIC_MODE_VALUE = 0x01, + KEYSTROKE_LIGHT_UP_MODE_VALUE = 0x02, + KEYSTROKE_DIM_MODE_VALUE = 0x03, + SPARKLE_MODE_VALUE = 0x04, + RAIN_MODE_VALUE = 0x05, + RANDOM_COLORS_MODE_VALUE = 0x06, + BREATHING_MODE_VALUE = 0x07, + SPECTRUM_CYCLE_MODE_VALUE = 0x08, + RING_GRADIENT_MODE_VALUE = 0x09, + VERTICAL_GRADIENT_MODE_VALUE = 0x0A, + HORIZONTAL_GRADIENT_WAVE_MODE_VALUE = 0x0B, + AROUND_EDGES_MODE_VALUE = 0x0C, + KEYSTROKE_HORIZONTAL_LINES_VALUE = 0x0D, + KEYSTROKE_TITLED_LINES_MODE_VALUE = 0x0E, + KEYSTROKE_RIPPLES_MODE_VALUE = 0x0F, + SEQUENCE_MODE_VALUE = 0x10, + WAVE_LINE_MODE_VALUE = 0x11, + TILTED_LINES_MODE_VALUE = 0x12, + BACK_AND_FORTH_MODE_VALUE = 0x13, + LIGHTS_OFF_MODE_VALUE = 0x80, +}; + +/*-----------------------------------------*\ +| Other settings | +\*-----------------------------------------*/ +enum +{ + MINTAKA_MIN_SPEED = 0x00, + MINTAKA_MAX_SPEED = 0x0F, + MINTAKA_MIN_BRIGHTNESS = 0x00, + MINTAKA_MAX_BRIGHTNESS = 0x0F, +}; + + +class MintakaKeyboardController +{ +public: + MintakaKeyboardController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~MintakaKeyboardController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SetLedSequencePositions(std::vector positions); + void SetMode(std::vector modes, int active_mode, std::vector colors); + +protected: + hid_device* dev; + +private: + std::string location; + std::string name; + std::string serial_number; + std::string version; + std::vector led_sequence_positions; + + void SetCustomization(bool state); + void StartEffectPage(); + void StartEffectCommand(); + void EndCommunication(); + + void Read(); + void Send(unsigned char data[PACKET_DATA_LENGTH]); +}; diff --git a/Controllers/MintakaKeyboardController/MintakaKeyboardControllerDetect.cpp b/Controllers/MintakaKeyboardController/MintakaKeyboardControllerDetect.cpp new file mode 100644 index 00000000..07d6c919 --- /dev/null +++ b/Controllers/MintakaKeyboardController/MintakaKeyboardControllerDetect.cpp @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| MintakaKeyboardControllerDetect.cpp | +| | +| Driver for VSG Mintaka Devices keyboard lighting | +| Based on KeychronKeyboardController | +| | +| Federico Scodelaro (pudymody) 08 Oct 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include "Detector.h" +#include "MintakaKeyboardController.h" +#include "RGBController_MintakaKeyboard.h" + +/*---------------------------------------------------------*\ +| MintakaKeyboard vendor ID | +\*---------------------------------------------------------*/ +#define MINTAKA_KEYBOARD_VID 0x05AC + +/*---------------------------------------------------------*\ +| Product ID | +\*---------------------------------------------------------*/ +#define VSG_MINTAKA_PID 0x0256 + +void DetectMintakaKeyboardControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + MintakaKeyboardController* controller = new MintakaKeyboardController(dev, *info, name); + RGBController_MintakaKeyboard* rgb_controller = new RGBController_MintakaKeyboard(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR_IPU("VSG Mintaka", DetectMintakaKeyboardControllers, MINTAKA_KEYBOARD_VID, VSG_MINTAKA_PID, 0, 0x0001, 0x06); diff --git a/Controllers/MintakaKeyboardController/RGBController_MintakaKeyboard.cpp b/Controllers/MintakaKeyboardController/RGBController_MintakaKeyboard.cpp new file mode 100644 index 00000000..d6d320ac --- /dev/null +++ b/Controllers/MintakaKeyboardController/RGBController_MintakaKeyboard.cpp @@ -0,0 +1,323 @@ +/*---------------------------------------------------------*\ +| RGBController_MintakaKeyboard.cpp | +| | +| Driver for VSG Mintaka Devices keyboard lighting | +| Based on KeychronKeyboardController | +| | +| Federico Scodelaro (pudymody) 08 Oct 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include +#include + +#include "KeyboardLayoutManager.h" +#include "RGBControllerKeyNames.h" +#include "RGBController_MintakaKeyboard.h" +/*---------------------------------------------------------------------*\ +| VSG Keyboard Mintaka Layout | +\*---------------------------------------------------------------------*/ +layout_values mintaka_offset_values = +{ + { + /* ESC 1 2 3 4 5 6 7 8 9 0 ' ¿ BSPC */ + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 103, + /* TAB Q W E R T Y U I O P ´ + */ + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + /* CPLK A S D F G H J K L Ñ { } ENTR */ + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 108, 85, + /* LSFT < Z X C V B N M , . - RSFT */ + 73, 109, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + /* LCTL LWIN LALT SPC RALT RMNU RCTL RFNC */ + 91, 92, 93, 94, 95, 96, 97, 98, + }, + { + { KEYBOARD_LAYOUT_ISO_QWERTY, { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 1, 11, 0, KEY_EN_QUOTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 1, 12, 0, KEY_ES_OPEN_QUESTION_MARK, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + + { 0, 2, 11, 0, KEY_ES_TILDE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 2, 12, 0, KEY_EN_PLUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + + { 0, 3, 10, 0, KEY_ES_ENIE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 3, 11, 0, KEY_EN_LEFT_BRACKET, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 3, 12, 0, KEY_EN_RIGHT_BRACKET, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + + { 0, 4, 1, 0, KEY_NORD_ANGLE_BRACKET, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 4, 11, 0, KEY_NORD_HYPHEN, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + + { 0, 5, 11, 0, KEY_EN_MENU, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 5, 12, 0, KEY_EN_RIGHT_CONTROL, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 5, 13, 0, KEY_EN_RIGHT_FUNCTION, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + }} + } +}; + +typedef struct +{ + std::string name; + int value; + int flags; +} mintaka_effect; + +/**------------------------------------------------------------------*\ + @name Mintaka Keyboard + @category Keyboard + @type USB + @save :x: + @direct :x: + @effects :white_check_mark: + @detectors DetectMintakaKeyboardControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_MintakaKeyboard::RGBController_MintakaKeyboard(MintakaKeyboardController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "VSG"; + type = DEVICE_TYPE_KEYBOARD; + description = name; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Custom; + Custom.name = "Custom"; + Custom.value = CUSTOM_MODE_VALUE; + Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Custom.color_mode = MODE_COLORS_PER_LED; + Custom.brightness_min = MINTAKA_MIN_BRIGHTNESS; + Custom.brightness_max = MINTAKA_MAX_BRIGHTNESS; + Custom.brightness = MINTAKA_MAX_BRIGHTNESS; + modes.push_back(Custom); + + mintaka_effect mintaka_effects[20] = + { + { + "Static", + STATIC_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Keystroke light up", + KEYSTROKE_LIGHT_UP_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Keystroke dim", + KEYSTROKE_DIM_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Sparkle", + SPARKLE_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Rain", + RAIN_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Random colors", + RANDOM_COLORS_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Breathing", + BREATHING_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Spectrum cycle", + SPECTRUM_CYCLE_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Ring gradient", + RING_GRADIENT_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Vertical gradient", + VERTICAL_GRADIENT_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Horizontal gradient / Rainbow wave", + HORIZONTAL_GRADIENT_WAVE_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Around edges", + AROUND_EDGES_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Keystroke horizontal lines", + KEYSTROKE_HORIZONTAL_LINES_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Keystroke tilted lines", + KEYSTROKE_TITLED_LINES_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Keystroke ripples", + KEYSTROKE_RIPPLES_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Sequence", + SEQUENCE_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Wave line", + WAVE_LINE_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Tilted lines", + TILTED_LINES_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Back and forth", + BACK_AND_FORTH_MODE_VALUE, + MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_AUTOMATIC_SAVE + }, + { + "Off", + LIGHTS_OFF_MODE_VALUE, + MODE_FLAG_AUTOMATIC_SAVE + } + }; + + for(const mintaka_effect& effect : mintaka_effects) + { + mode m; + m.name = effect.name; + m.value = effect.value; + m.flags = effect.flags; + + if(m.flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR) + { + m.color_mode = MODE_COLORS_MODE_SPECIFIC; + m.colors_min = 1; + m.colors_max = 1; + m.colors.resize(1); + } + else + { + m.color_mode = MODE_COLORS_NONE; + m.colors_min = 0; + m.colors_max = 0; + m.colors.resize(0); + } + + if(m.flags & MODE_FLAG_HAS_SPEED) + { + m.speed_min = MINTAKA_MIN_SPEED; + m.speed_max = MINTAKA_MAX_SPEED; + m.speed = m.speed_min; + } + + if(m.flags & MODE_FLAG_HAS_BRIGHTNESS) + { + m.brightness_min = MINTAKA_MIN_BRIGHTNESS; + m.brightness_max = MINTAKA_MAX_BRIGHTNESS; + m.brightness = m.brightness_max; + } + + modes.push_back(m); + } + + SetupZones(); +} + +RGBController_MintakaKeyboard::~RGBController_MintakaKeyboard() +{ + delete controller; +} + +void RGBController_MintakaKeyboard::SetupZones() +{ + + /*---------------------------------------------------------*\ + | Create the keyboard zone usiung Keyboard Layout Manager | + \*---------------------------------------------------------*/ + zone new_zone; + new_zone.name = ZONE_EN_KEYBOARD; + new_zone.type = ZONE_TYPE_MATRIX; + + KeyboardLayoutManager new_kb(KEYBOARD_LAYOUT_ISO_QWERTY, KEYBOARD_SIZE_SIXTY, mintaka_offset_values); + + matrix_map_type * new_map = new matrix_map_type; + new_zone.matrix_map = new_map; + new_zone.matrix_map->height = new_kb.GetRowCount(); + new_zone.matrix_map->width = new_kb.GetColumnCount(); + + new_zone.matrix_map->map = new unsigned int[new_map->height * new_map->width]; + new_zone.leds_count = new_kb.GetKeyCount(); + new_zone.leds_min = new_zone.leds_count; + new_zone.leds_max = new_zone.leds_count; + + /*---------------------------------------------------------*\ + | Matrix map still uses declared zone rows and columns | + | as the packet structure depends on the matrix map | + \*---------------------------------------------------------*/ + new_kb.GetKeyMap(new_map->map, KEYBOARD_MAP_FILL_TYPE_COUNT, new_map->height, new_map->width); + controller->SetLedSequencePositions(mintaka_offset_values.default_values); + + /*---------------------------------------------------------*\ + | Create LEDs for the Matrix zone | + | Place keys in the layout to populate the matrix | + \*---------------------------------------------------------*/ + for(unsigned int led_idx = 0; led_idx < new_zone.leds_count; led_idx++) + { + led new_led; + + new_led.name = new_kb.GetKeyNameAt(led_idx); + new_led.value = new_kb.GetKeyValueAt(led_idx); + leds.push_back(new_led); + } + + zones.push_back(new_zone); + + SetupColors(); +} + +void RGBController_MintakaKeyboard::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_MintakaKeyboard::DeviceUpdateLEDs() +{ + UpdateZoneLEDs(0); +} + +void RGBController_MintakaKeyboard::UpdateZoneLEDs(int /*zone*/) +{ + controller->SetMode(modes, active_mode, colors); +} + +void RGBController_MintakaKeyboard::UpdateSingleLED(int led) +{ + UpdateZoneLEDs(led); +} + +void RGBController_MintakaKeyboard::DeviceUpdateMode() +{ + UpdateZoneLEDs(0); +} diff --git a/Controllers/MintakaKeyboardController/RGBController_MintakaKeyboard.h b/Controllers/MintakaKeyboardController/RGBController_MintakaKeyboard.h new file mode 100644 index 00000000..10a27469 --- /dev/null +++ b/Controllers/MintakaKeyboardController/RGBController_MintakaKeyboard.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_MintakaKeyboard.h | +| | +| Driver for VSG Mintaka Devices keyboard lighting | +| Based on KeychronKeyboardController | +| | +| Federico Scodelaro (pudymody) 08 Oct 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#pragma once + +#include "RGBController.h" +#include "MintakaKeyboardController.h" + +class RGBController_MintakaKeyboard : public RGBController +{ +public: + RGBController_MintakaKeyboard(MintakaKeyboardController* controller_ptr); + ~RGBController_MintakaKeyboard(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + MintakaKeyboardController* controller; +}; diff --git a/Controllers/MountainKeyboardController/MountainKeyboardController.cpp b/Controllers/MountainKeyboardController/MountainKeyboardController.cpp index 83288d7e..f3d70c08 100644 --- a/Controllers/MountainKeyboardController/MountainKeyboardController.cpp +++ b/Controllers/MountainKeyboardController/MountainKeyboardController.cpp @@ -1,24 +1,27 @@ -/*------------------------------------------*\ -| MountainKeyboardController.cpp | -| | -| Driver for Mountain RGB keyboard lighting | -| controller | -| | -| Wojciech Lazarski 01/2023 | -| | -\*------------------------------------------*/ +/*---------------------------------------------------------*\ +| MountainKeyboardController.cpp | +| | +| Driver for Mountain keyboard | +| | +| Wojciech Lazarski Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "MountainKeyboardController.h" +#include #include #include -#include +#include "MountainKeyboardController.h" +#include "StringUtils.h" using namespace std::chrono_literals; -MountainKeyboardController::MountainKeyboardController(hid_device* dev_handle, const char* path) +MountainKeyboardController::MountainKeyboardController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } MountainKeyboardController::~MountainKeyboardController() @@ -31,6 +34,11 @@ std::string MountainKeyboardController::GetDeviceLocation() return("HID: " + location); } +std::string MountainKeyboardController::GetNameString() +{ + return(name); +} + std::string MountainKeyboardController::GetSerialString() { wchar_t serial_string[128]; @@ -41,10 +49,7 @@ std::string MountainKeyboardController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void MountainKeyboardController::SelectMode(unsigned char mode_idx) @@ -422,6 +427,54 @@ void MountainKeyboardController::SendColorPacketFinishCmd() } } +void MountainKeyboardController::SendWheelColorChange(unsigned char color_data [3]) +{ + + wheel_config * usb_buf = GetWheelConfig(); + if (usb_buf != nullptr) + { + usb_buf->fixed_byte_1 = 0x01; + usb_buf->fixed_byte_2 = 0x02; + usb_buf->zero_byte = 0x00; + usb_buf->r = color_data[0]; + usb_buf->g = color_data[1]; + usb_buf->b = color_data[2]; + hid_write(dev, (unsigned char *) usb_buf, MOUNTAIN_KEYBOARD_WHEEL_CONFIG_BUFFER_SIZE); + } + +} + +wheel_config * MountainKeyboardController::GetWheelConfig() +{ + + unsigned char * usb_buf = new unsigned char [MOUNTAIN_KEYBOARD_WHEEL_CONFIG_BUFFER_SIZE+1]; + unsigned char * recv_buf = &usb_buf[1]; + + + for (int i =0; i < 1000; i++) + { + + memset(usb_buf, 0x00, MOUNTAIN_KEYBOARD_WHEEL_CONFIG_BUFFER_SIZE+1); + wheel_config * usb_conf = (wheel_config *) usb_buf; + usb_conf->config_start_first = 0x11; + usb_conf->config_start_second = 0x14; + hid_write(dev, usb_buf, MOUNTAIN_KEYBOARD_WHEEL_CONFIG_BUFFER_SIZE); + memset(usb_buf, 0x00, MOUNTAIN_KEYBOARD_WHEEL_CONFIG_BUFFER_SIZE+1); + hid_read_timeout(dev, recv_buf, MOUNTAIN_KEYBOARD_WHEEL_CONFIG_BUFFER_SIZE, 1); + if (usb_conf->config_start_first == MOUNTAIN_KEYBOARD_WHEEL_CONFIG_FIRST_BYTE && + usb_conf->config_start_second == MOUNTAIN_KEYBOARD_WHEEL_CONFIG_SECOND_BYTE) + { + return usb_conf; + } + + } + + delete[] usb_buf; + return nullptr; + +} + + void MountainKeyboardController::SendDirectColorEdgeCmd(bool quick_mode, unsigned char brightness, unsigned char *color_data, unsigned int data_size) { static bool first_call = true; diff --git a/Controllers/MountainKeyboardController/MountainKeyboardController.h b/Controllers/MountainKeyboardController/MountainKeyboardController.h index 16b3d678..06dae22a 100644 --- a/Controllers/MountainKeyboardController/MountainKeyboardController.h +++ b/Controllers/MountainKeyboardController/MountainKeyboardController.h @@ -1,17 +1,19 @@ -/*-----------------------------------------*\ -| MountainKeyboardController.h | -| | -| Definitions and types for Mountain RGB | -| keyboard lighting controller | -| | -| Wojciech Lazarski 01/2023 | -\*-----------------------------------------*/ - - -#include -#include +/*---------------------------------------------------------*\ +| MountainKeyboardController.h | +| | +| Driver for Mountain keyboard | +| | +| Wojciech Lazarski Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + +#include +#include + /*-----------------------------------------------------*\ | Mountain vendor ID | \*-----------------------------------------------------*/ @@ -32,6 +34,11 @@ #define MOUNTAIN_KEYBOARD_USB_BUFFER_HEADER_SIZE 8 #define MOUNTAIN_KEYBOARD_USB_MAX_DIRECT_PAYLOAD_SIZE \ (MOUNTAIN_KEYBOARD_USB_BUFFER_SIZE-MOUNTAIN_KEYBOARD_USB_BUFFER_HEADER_SIZE) +#define MOUNTAIN_KEYBOARD_WHEEL_CONFIG_BUFFER_SIZE 65 +#define MOUNTAIN_KEYBOARD_WHEEL_CONFIG_FIRST_BYTE 0x11 +#define MOUNTAIN_KEYBOARD_WHEEL_CONFIG_SECOND_BYTE 0x14 +#define MOUNTAIN_KEYBOARD_WHEEL_CONFIG_FIXED_BYTE_1 0x01 +#define MOUNTAIN_KEYBOARD_WHEEL_CONFIG_FIXED_BYTE_2 0x02 enum { @@ -118,13 +125,31 @@ typedef struct } mode; } color_setup; + +typedef struct +{ + unsigned char report_size; + unsigned char config_start_first; + unsigned char config_start_second; + unsigned char zero_byte; + unsigned char fixed_byte_1; + unsigned char fixed_byte_2; + unsigned char config_intermediate_values [2]; + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char config_end_values [54]; + +} wheel_config; + class MountainKeyboardController { public: - MountainKeyboardController(hid_device* dev_handle, const char* path); + MountainKeyboardController(hid_device* dev_handle, const char* path, std::string dev_name); ~MountainKeyboardController(); std::string GetDeviceLocation(); + std::string GetNameString(); std::string GetSerialString(); void SendOffCmd(); @@ -138,16 +163,20 @@ public: void SendDirectColorCmd(bool quick_mode, unsigned char brightness, unsigned char *color_data, unsigned int color_count); void SendDirectColorEdgeCmd(bool quick_mode, unsigned char brightness, unsigned char *color_data, unsigned int data_size); + + void SendWheelColorChange(unsigned char color_data [3]); + wheel_config * GetWheelConfig(); + void SaveData(unsigned char mode_idx); void SelectMode(unsigned char mode_idx); private: + hid_device* dev; + std::string location; + std::string name; + void SendColorStartPacketCmd(unsigned char brightness); void SendColorPacketCmd(unsigned char pkt_no,unsigned char brightness, unsigned char *data, unsigned int data_size); void SendColorEdgePacketCmd(unsigned char pkt_no, unsigned char *data, unsigned int data_size); void SendColorPacketFinishCmd(); - - hid_device* dev; - std::string location; - unsigned short usb_pid; }; diff --git a/Controllers/MountainKeyboardController/MountainKeyboardControllerDetect.cpp b/Controllers/MountainKeyboardController/MountainKeyboardControllerDetect.cpp index 4a938623..19dd202e 100644 --- a/Controllers/MountainKeyboardController/MountainKeyboardControllerDetect.cpp +++ b/Controllers/MountainKeyboardController/MountainKeyboardControllerDetect.cpp @@ -1,8 +1,18 @@ +/*---------------------------------------------------------*\ +| MountainKeyboardControllerDetect.cpp | +| | +| Detector for Mountain keyboard | +| | +| Wojciech Lazarski Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "MountainKeyboardController.h" -#include "RGBController.h" #include "RGBController_MountainKeyboard.h" -#include /*----------------------------------------------------------------------------------------*\ | | @@ -18,12 +28,11 @@ void DetectMountainKeyboardControllers(hid_device_info* info, const std::string& if(dev) { - MountainKeyboardController* controller = new MountainKeyboardController(dev, info->path); + MountainKeyboardController* controller = new MountainKeyboardController(dev, info->path, name); RGBController_MountainKeyboard* rgb_controller = new RGBController_MountainKeyboard(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } /* DetectMountainKeyboardControllers() */ REGISTER_HID_DETECTOR_IPU("Mountain Everest", DetectMountainKeyboardControllers, MOUNTAIN_VID, MOUNTAIN_EVEREST_PID, 3, 0xFF00, 0x01); - diff --git a/Controllers/MountainKeyboardController/RGBController_MountainKeyboard.cpp b/Controllers/MountainKeyboardController/RGBController_MountainKeyboard.cpp index bf7dc0e9..0b923ae6 100644 --- a/Controllers/MountainKeyboardController/RGBController_MountainKeyboard.cpp +++ b/Controllers/MountainKeyboardController/RGBController_MountainKeyboard.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_MountainKeyboard.cpp | -| | -| Generic RGB Interface for Mountain RGB | -| keyboard devices | -| | -| Wojciech Lazarski 01/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_MountainKeyboard.cpp | +| | +| RGBController for Mountain keyboard | +| | +| Wojciech Lazarski Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_MountainKeyboard.h" @@ -220,6 +222,11 @@ enum IDX_KEY_EN_UP_ARROW, }; +enum +{ + IDX_WHEEL +}; + static unsigned int matrix_tkl_map[KEYBOARD_MATRIX_TKL_HEIGHT][KEYBOARD_MATRIX_TKL_WIDTH] = { { 0, NA, 8, 14, 19, 24, NA, 30, 36, 40, 45, NA, 53, 59, 65, 70, 74, 78, 83}, { 1, 6, 9, 15, 20, 25, 29, 31, 37, 41, 46, NA, 54, 60, 66, NA, 75, 79, 84}, @@ -267,7 +274,7 @@ static unsigned int matrix_num_map_lut[KEYBOARD_MATRIX_NUM_KEYS_NO] = IDX_KEY_EN_NUMPAD_MINUS, IDX_KEY_EN_NUMPAD_PLUS, IDX_KEY_EN_NUMPAD_ENTER }; -static unsigned int matrix_edge_tkl_map_lut[KEYBOARD_MATRIX_EDGE_TKL_KEYS_NO]= +static unsigned int matrix_edge_tkl_map_lut[KEYBOARD_MATRIX_EDGE_TKL_KEYS_NO] = { IDX_EDGE_16, IDX_EDGE_17, IDX_EDGE_18, IDX_EDGE_19, IDX_EDGE_13, IDX_EDGE_20, @@ -294,6 +301,11 @@ static unsigned int matrix_edge_numpad_map_lut[KEYBOARD_MATRIX_EDGE_NUMPAD_KEYS_ IDX_EDGE_41, IDX_EDGE_40, IDX_EDGE_39, IDX_EDGE_38 }; +static unsigned int single_wheel_lut[1]= +{ + IDX_WHEEL +}; + static unsigned int matrix_edge_tkl_map[KEYBOARD_MATRIX_EDGE_TKL_HEIGHT][KEYBOARD_MATRIX_EDGE_TKL_WIDTH] = { { NA, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, NA }, { 0, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 28 }, @@ -363,6 +375,15 @@ static const mountain_zone_t zone_definitions[] = KEYBOARD_MATRIX_EDGE_NUMPAD_KEYS_NO, KEYBOARD_MATRIX_EDGE_NUMPAD_HEIGHT, KEYBOARD_MATRIX_EDGE_NUMPAD_WIDTH + }, + { + "Wheel Selector", + ZONE_TYPE_SINGLE, + NULL, + (unsigned int *) &single_wheel_lut, + 1, + 1, + 1 } }; @@ -509,14 +530,25 @@ static const char *led_names[MOUNTAIN_KEYBOARD_MAX_TRANSFER_COLORS] = RGBController_MountainKeyboard::RGBController_MountainKeyboard(MountainKeyboardController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Mountain Everest Keyboard"; - vendor = "Mountain"; - type = DEVICE_TYPE_KEYBOARD; - description = "Mountain Everest Keyboard"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + memset(wheel_color, 0, 3); + + wheel_config * wheel_conf = controller->GetWheelConfig(); + + if(wheel_conf != nullptr) + { + wheel_color[0] = wheel_conf->r; + wheel_color[1] = wheel_conf->g; + wheel_color[2] = wheel_conf->b; + } + + name = controller->GetNameString(); + vendor = "Mountain"; + type = DEVICE_TYPE_KEYBOARD; + description = "Mountain Everest Keyboard"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; Direct.name = "Direct"; @@ -649,7 +681,6 @@ RGBController_MountainKeyboard::RGBController_MountainKeyboard(MountainKeyboardC modes.push_back(Matrix); SetupZones(); - } RGBController_MountainKeyboard::~RGBController_MountainKeyboard() @@ -682,10 +713,14 @@ void RGBController_MountainKeyboard::SetupZones() new_zone.leds_min = zone_definitions[zone_idx].size; new_zone.leds_max = zone_definitions[zone_idx].size; new_zone.leds_count = zone_definitions[zone_idx].size; - new_zone.matrix_map = new matrix_map_type; - new_zone.matrix_map->height = zone_definitions[zone_idx].height; - new_zone.matrix_map->width = zone_definitions[zone_idx].width; - new_zone.matrix_map->map = zone_definitions[zone_idx].ptr; + new_zone.matrix_map = NULL; + if (zone_definitions[zone_idx].type == ZONE_TYPE_MATRIX) + { + new_zone.matrix_map = new matrix_map_type; + new_zone.matrix_map->height = zone_definitions[zone_idx].height; + new_zone.matrix_map->width = zone_definitions[zone_idx].width; + new_zone.matrix_map->map = zone_definitions[zone_idx].ptr; + } zones.push_back(new_zone); } @@ -713,6 +748,11 @@ void RGBController_MountainKeyboard::SetupZones() } break; + case 4: + { + new_led->name = zones[zone_idx].name + " LED"; + } + break; default: break; } @@ -768,7 +808,7 @@ void RGBController_MountainKeyboard::DeviceUpdate(const mode& current_mode) color_edge_data[(3 * idx)+1] = RGBGetGValue(colors[led_idx]); color_edge_data[(3 * idx)+2] = RGBGetBValue(colors[led_idx]); } - else + else if (led_idx < zones[0].leds_count + zones[1].leds_count + zones[2].leds_count + zones[3].leds_count) { unsigned int zone_led_idx = led_idx - zones[0].leds_count - zones[1].leds_count - zones[2].leds_count; unsigned int idx = zone_definitions[3].ptr_lut[zone_led_idx]; @@ -776,6 +816,14 @@ void RGBController_MountainKeyboard::DeviceUpdate(const mode& current_mode) color_edge_data[(3 * idx)+1] = RGBGetGValue(colors[led_idx]); color_edge_data[(3 * idx)+2] = RGBGetBValue(colors[led_idx]); } + else + { + wheel_color[0] = RGBGetRValue(colors[led_idx]); + wheel_color[1] = RGBGetGValue(colors[led_idx]); + wheel_color[2] = RGBGetBValue(colors[led_idx]); + } + + } /*---------------------------------------------------------*\ @@ -809,7 +857,12 @@ void RGBController_MountainKeyboard::DeviceUpdate(const mode& current_mode) setup.mode.one_color.g = RGBGetGValue(current_mode.colors[0]); setup.mode.one_color.b = RGBGetBValue(current_mode.colors[0]); + unsigned char colors [3] = {setup.mode.one_color.r, setup.mode.one_color.g, setup.mode.one_color.b}; controller->SendColorStaticCmd(setup); + wheel_color[0] = colors[0]; + wheel_color[1] = colors[1]; + wheel_color[2] = colors[2]; + } break; @@ -1029,4 +1082,5 @@ unsigned char RGBController_MountainKeyboard::ConvertDirection(unsigned int dire void RGBController_MountainKeyboard::DeviceSaveMode() { controller->SaveData(modes[active_mode].value); + controller->SendWheelColorChange(wheel_color); } diff --git a/Controllers/MountainKeyboardController/RGBController_MountainKeyboard.h b/Controllers/MountainKeyboardController/RGBController_MountainKeyboard.h index febdcd5e..61364fe0 100644 --- a/Controllers/MountainKeyboardController/RGBController_MountainKeyboard.h +++ b/Controllers/MountainKeyboardController/RGBController_MountainKeyboard.h @@ -1,13 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_MountainKeyboard.h | -| | -| Generic RGB Interface for Mountain RGB | -| keyboard devices | -| | -| Wojciech Lazarski 01/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_MountainKeyboard.h | +| | +| RGBController for Mountain keyboard | +| | +| Wojciech Lazarski Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + +#include #include "RGBController.h" #include "MountainKeyboardController.h" @@ -39,7 +43,7 @@ public: void SetupZones(); void ResizeZone(int zone, int new_size); - + void DeviceUpdateLEDs(); void UpdateZoneLEDs(int zone); void UpdateSingleLED(int led); @@ -51,4 +55,6 @@ private: MountainKeyboardController* controller; unsigned char ConvertDirection(unsigned int direction, bool rotation); void DeviceUpdate(const mode& current_mode); + + unsigned char wheel_color [3]; }; diff --git a/Controllers/N5312AController/N5312AController.cpp b/Controllers/N5312AController/N5312AController.cpp index 405a4418..9695d341 100644 --- a/Controllers/N5312AController/N5312AController.cpp +++ b/Controllers/N5312AController/N5312AController.cpp @@ -1,33 +1,24 @@ -/*-----------------------------------------*\ -| N5312AController.cpp | -| | -| Driver for N5312A lighting | -| controller | -| | -| Guimard Morgan (morg) 4/02/2022 | -\*-----------------------------------------*/ -#include "N5312AController.h" +/*---------------------------------------------------------*\ +| N5312AController.cpp | +| | +| Driver for N5312A | +| | +| Morgan Guimard (morg) 02 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include #include "LogManager.h" +#include "N5312AController.h" +#include "StringUtils.h" -N5312AController::N5312AController(hid_device* dev_handle, const hid_device_info& info) +N5312AController::N5312AController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) { - dev = dev_handle; - location = info.path; - version = ""; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } + dev = dev_handle; + location = info.path; + name = dev_name; SendInit(); } @@ -42,14 +33,22 @@ std::string N5312AController::GetDeviceLocation() return("HID: " + location); } -std::string N5312AController::GetSerialString() +std::string N5312AController::GetNameString() { - return(serial_number); + return(name); } -std::string N5312AController::GetFirmwareVersion() +std::string N5312AController::GetSerialString() { - return(version); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } void N5312AController::SendInit() diff --git a/Controllers/N5312AController/N5312AController.h b/Controllers/N5312AController/N5312AController.h index 89efe23e..5a2adc60 100644 --- a/Controllers/N5312AController/N5312AController.h +++ b/Controllers/N5312AController/N5312AController.h @@ -1,16 +1,19 @@ -/*-----------------------------------------*\ -| N5312AController.h | -| | -| Driver for N5312A lighting | -| controller - header file | -| | -| Guimard Morgan (morg) 4/02/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| N5312AController.h | +| | +| Driver for N5312A | +| | +| Morgan Guimard (morg) 02 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once -#include "RGBController.h" #include -#include +#include +#include "RGBController.h" #define N5312A_REPORT_ID 0x07 #define N5312A_PACKET_DATA_LENGTH 8 @@ -38,12 +41,12 @@ enum class N5312AController { public: - N5312AController(hid_device* dev_handle, const hid_device_info& info); + N5312AController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); ~N5312AController(); - std::string GetSerialString(); std::string GetDeviceLocation(); - std::string GetFirmwareVersion(); + std::string GetNameString(); + std::string GetSerialString(); void SetColor(RGBColor color); void SetMode(RGBColor color, unsigned char mode_value, unsigned char brightness, unsigned char speed); @@ -52,7 +55,7 @@ private: hid_device* dev; std::string location; - std::string serial_number; + std::string name; std::string version; void SendInit(); diff --git a/Controllers/N5312AController/N5312AControllerDetect.cpp b/Controllers/N5312AController/N5312AControllerDetect.cpp index 9a48b0ff..ce9e74fb 100644 --- a/Controllers/N5312AController/N5312AControllerDetect.cpp +++ b/Controllers/N5312AController/N5312AControllerDetect.cpp @@ -1,6 +1,16 @@ +/*---------------------------------------------------------*\ +| N5312AControllerDetect.cpp | +| | +| Detector for N5312A | +| | +| Morgan Guimard (morg) 02 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "N5312AController.h" -#include "RGBController.h" #include "RGBController_N5312A.h" /*---------------------------------------------------------*\ @@ -19,9 +29,8 @@ void DetectN5312AControllers(hid_device_info* info, const std::string& name) if(dev) { - N5312AController* controller = new N5312AController(dev, *info); + N5312AController* controller = new N5312AController(dev, *info, name); RGBController_N5312A* rgb_controller = new RGBController_N5312A(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } diff --git a/Controllers/N5312AController/RGBController_N5312A.cpp b/Controllers/N5312AController/RGBController_N5312A.cpp index ce6621f1..ee5dfd86 100644 --- a/Controllers/N5312AController/RGBController_N5312A.cpp +++ b/Controllers/N5312AController/RGBController_N5312A.cpp @@ -1,16 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_N5312A.cpp | -| | -| Generic RGB Interface for OpenRGB | -| N5312A RGB USB Driver | -| | -| Guimard Morgan (morg) 4/02/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_N5312A.cpp | +| | +| RGBController for N5312A | +| | +| Morgan Guimard (morg) 02 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_N5312A.h" - -#include #include +#include +#include "RGBController_N5312A.h" /**------------------------------------------------------------------*\ @name N5312A mouse @@ -24,16 +25,17 @@ Identified devices that work with this controller: ANT Esports KM540 Mouse, Marvo M115 \*-------------------------------------------------------------------*/ + RGBController_N5312A::RGBController_N5312A(N5312AController* controller_ptr) { controller = controller_ptr; - name = "N5312A Device"; + + name = controller->GetNameString(); vendor = "Unknown"; type = DEVICE_TYPE_MOUSE; - description = name; + description = "N5312A Device"; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); mode Static; Static.name = "Direct"; @@ -132,7 +134,7 @@ void RGBController_N5312A::UpdateSingleLED(int led) } void RGBController_N5312A::DeviceUpdateMode() -{ +{ const RGBColor& color = modes[active_mode].value == N5312A_OFF_MODE_VALUE ? 0 : colors[0]; controller->SetMode(color, modes[active_mode].value, modes[active_mode].brightness, modes[active_mode].speed); } diff --git a/Controllers/N5312AController/RGBController_N5312A.h b/Controllers/N5312AController/RGBController_N5312A.h index e63f06de..470be919 100644 --- a/Controllers/N5312AController/RGBController_N5312A.h +++ b/Controllers/N5312AController/RGBController_N5312A.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_N5312A.h | -| | -| Generic RGB Interface for OpenRGB | -| N5312A RGB USB Driver | -| | -| Guimard Morgan (morg) 4/02/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_N5312A.h | +| | +| RGBController for N5312A | +| | +| Morgan Guimard (morg) 02 Apr 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationControllerDetect.cpp b/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationControllerDetect.cpp deleted file mode 100644 index 666e909e..00000000 --- a/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationControllerDetect.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/*----------------------------------------------*\ -| NVIDIAIlluminationControllerDetect.cpp | -| | -| Detect GPUS that are controlled by the direct | -| NVIDIA Illumination controller. | -| | -| Carter Miller (GingerRunner) 1/4/2022 | -\*----------------------------------------------*/ - -#include "Detector.h" - -#include "LogManager.h" -#include "RGBController.h" -#include "RGBController_NVIDIAIllumination.h" - -#include "pci_ids.h" -#include -#include -#include - -enum -{ - NVIDIA_ILLUMINATION_V1 -}; - -typedef struct -{ - int pci_vendor; - int pci_device; - int pci_subsystem_vendor; - int pci_subsystem_device; - int gpu_rgb_version; - bool treats_rgbw_as_rgb; - const char * name; -} gpu_pci_device; - - -#define GPU_NUM_DEVICES (sizeof(device_list) / sizeof(device_list[ 0 ])) - -/*-----------------------------------------------------------------------------------------------------*\ -| Certain devices seem to ignore the white value entirely, despite the zone being reported back by the | -| API as RGBW, so this boolean is passed at detection time via constructor inform the controller logic. | -\*-----------------------------------------------------------------------------------------------------*/ -#define TREATS_RGBW_AS_RGB true -#define TREATS_RGBW_AS_RGBW false - -static const gpu_pci_device device_list[] = -{ - {NVIDIA_VEN, NVIDIA_RTX2070S_DEV, NVIDIA_VEN, NVIDIA_RTX2070_FE_SUPER_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA 2070 SUPER FE" }, - {NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, NVIDIA_VEN, NVIDIA_RTX2080_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA 2080 FE" }, - {NVIDIA_VEN, NVIDIA_RTX2080S_DEV, NVIDIA_VEN, NVIDIA_RTX2080S_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA 2080 FE" }, - {NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, PNY_SUB_VEN, PNY_RTX_3060_XLR8_REVEL_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "PNY 3060 XLR8 REVEL EPIC-X" }, - {NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, PNY_SUB_VEN, PNY_RTX_3060_XLR8_REVEL_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "PNY 3060 XLR8 REVEL EPIC-X" }, - {NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, PNY_SUB_VEN, PNY_RTX_3060TI_XLR8_REVEL_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "PNY 3060TI XLR8 REVEL EPIC-X" }, - {NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, NVIDIA_VEN, PNY_RTX_3060TI_XLR8_REVEL_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "PNY 3060TI XLR8 REVEL EPIC-X" }, - {NVIDIA_VEN, NVIDIA_RTX3060TI_V1_LHR_DEV, NVIDIA_VEN, NVIDIA_RTX3060TI_V1_LHR_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "NVIDIA 3060TI V1 LHR" }, - {NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA 3060TI LHR" }, - {NVIDIA_VEN, NVIDIA_RTX3080_DEV, NVIDIA_VEN, NVIDIA_RTX3080_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA 3080 FE" }, - {NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, NVIDIA_VEN, NVIDIA_RTX3080TI_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA 3080TI FE" }, - {NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, NVIDIA_VEN, MANLI_RTX3080TI_GALLARDO_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "MANLI 3080TI GALLARDO" }, - {NVIDIA_VEN, NVIDIA_RTX3090_DEV, NVIDIA_VEN, NVIDIA_RTX3090_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA 3090 FE" }, - {NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, NVIDIA_VEN, NVIDIA_RTX3090TI_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA 3090TI FE" }, - {NVIDIA_VEN, NVIDIA_RTX4070_DEV, PALIT_SUB_VEN, PALIT_RTX4070_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Palit 4070" }, - {NVIDIA_VEN, NVIDIA_RTX4080_DEV, NVIDIA_VEN, NVIDIA_RTX4080_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA 4080 FE" }, - {NVIDIA_VEN, NVIDIA_RTX4080_DEV, NVIDIA_VEN, NVIDIA_RTX4080_FE_SUB_DEV2, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA 4080 FE" }, - {NVIDIA_VEN, NVIDIA_RTX4090_DEV, NVIDIA_VEN, NVIDIA_RTX4090_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA 4090 FE" }, - {NVIDIA_VEN, NVIDIA_RTX4090_DEV, NVIDIA_VEN, NVIDIA_RTX4090_FE_SUB_DEV2, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA 4090 FE" }, -}; - -void DetectNVIDIAIllumGPUs() -{ - static NV_PHYSICAL_GPU_HANDLE gpu_handles[64]; - static NV_S32 gpu_count = 0; - NV_U32 device_id; - NV_U32 ext_device_id; - NV_STATUS res; - NV_U32 revision_id; - NV_U32 sub_system_id; - - NvAPI_Initialize(); - - NvAPI_EnumPhysicalGPUs(gpu_handles, &gpu_count); - - for(NV_S32 gpu_idx = 0; gpu_idx < gpu_count; gpu_idx++) - { - res = NvAPI_GPU_GetPCIIdentifiers(gpu_handles[gpu_idx], &device_id, &sub_system_id, &revision_id, &ext_device_id); - if (res == 0) - { - uint16_t pci_device = device_id >> 16; - uint16_t pci_vendor = device_id & 0xffff; - uint16_t pci_subsystem_device = sub_system_id >> 16; - uint16_t pci_subsystem_vendor = sub_system_id & 0xffff; - for(unsigned int dev_idx = 0; dev_idx < GPU_NUM_DEVICES; dev_idx++) - { - if(pci_vendor == device_list[dev_idx].pci_vendor && - pci_device == device_list[dev_idx].pci_device && - pci_subsystem_vendor == device_list[dev_idx].pci_subsystem_vendor && - pci_subsystem_device == device_list[dev_idx].pci_subsystem_device) - { - LOG_DEBUG("[%s] NVidia NvAPI Illumination GPU found", device_list[dev_idx].name); - switch(device_list[dev_idx].gpu_rgb_version) - { - case NVIDIA_ILLUMINATION_V1: - { - nvapi_accessor* new_nvapi = new nvapi_accessor(gpu_handles[gpu_idx]); - NVIDIAIlluminationV1Controller* controller = new NVIDIAIlluminationV1Controller(new_nvapi, device_list[dev_idx].treats_rgbw_as_rgb); - RGBController_NVIDIAIlluminationV1* rgb_controller = new RGBController_NVIDIAIlluminationV1(controller); - rgb_controller->name = device_list[dev_idx].name; - - ResourceManager::get()->RegisterRGBController(rgb_controller); - } - break; - } - } - } - } - } -} - -REGISTER_DETECTOR("NVidia NvAPI Illumination", DetectNVIDIAIllumGPUs); diff --git a/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationControllerDetect_Windows_Linux.cpp b/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationControllerDetect_Windows_Linux.cpp new file mode 100644 index 00000000..cdd6f29f --- /dev/null +++ b/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationControllerDetect_Windows_Linux.cpp @@ -0,0 +1,132 @@ +/*---------------------------------------------------------*\ +| NVIDIAIlluminationControllerDetect_Windows_Linux.cpp | +| | +| Detector for NVIDIA Illumination GPU | +| | +| Carter Miller (GingerRunner) 04 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "LogManager.h" +#include "RGBController_NVIDIAIllumination_Windows_Linux.h" +#include "pci_ids.h" + +enum +{ + NVIDIA_ILLUMINATION_V1 +}; + +typedef struct +{ + int pci_vendor; + int pci_device; + int pci_subsystem_vendor; + int pci_subsystem_device; + int gpu_rgb_version; + bool treats_rgbw_as_rgb; + const char * name; +} nv_gpu_pci_device; + + +#define GPU_NUM_DEVICES (sizeof(device_list) / sizeof(device_list[ 0 ])) + +/*-----------------------------------------------------------------------------------------------------*\ +| Certain devices seem to ignore the white value entirely, despite the zone being reported back by the | +| API as RGBW, so this boolean is passed at detection time via constructor inform the controller logic. | +\*-----------------------------------------------------------------------------------------------------*/ +#define TREATS_RGBW_AS_RGB true +#define TREATS_RGBW_AS_RGBW false + +static const nv_gpu_pci_device device_list[] = +{ + {NVIDIA_VEN, NVIDIA_RTX2060_TU104_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2060_TU104_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "Palit GeForce RTX 2060" }, + {NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2060_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2060 FE" }, + {NVIDIA_VEN, NVIDIA_RTX2060S_OC_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2060S_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2060 SUPER FE" }, + {NVIDIA_VEN, NVIDIA_RTX2070_OC_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2070_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2070 FE" }, + {NVIDIA_VEN, NVIDIA_RTX2070S_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2070_FE_SUPER_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2070 SUPER FE" }, + {NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2080_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2080 FE" }, + {NVIDIA_VEN, NVIDIA_RTX2080S_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2080S_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2080 SUPER FE" }, + {NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2080TI_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 2080 Ti FE" }, + {NVIDIA_VEN, NVIDIA_TITANRTX_DEV, NVIDIA_SUB_VEN, NVIDIA_TITANRTX_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA TITAN RTX" }, + {NVIDIA_VEN, NVIDIA_RTX3050_DEV, NVIDIA_SUB_VEN, GAINWARD_RTX3050_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Gainward GeForce RTX 3050 LHR" }, + {NVIDIA_VEN, NVIDIA_RTX3060_8G_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3060_8G_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Gainward GeForce RTX 3060 Pegasus" }, + {NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3060_LHR_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Palit GeForce RTX 3060 LHR" }, + {NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, PNY_SUB_VEN, PNY_RTX_3060_XLR8_REVEL_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "PNY GeForce RTX 3060 XLR8 REVEL EPIC-X" }, + {NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, PNY_SUB_VEN, PNY_RTX_3060_XLR8_REVEL_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "PNY GeForce RTX 3060 XLR8 REVEL EPIC-X" }, + {NVIDIA_VEN, NVIDIA_RTX3060_GA104_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3060_GA104_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Palit GeForce RTX 3060 LHR" }, + {NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, PNY_SUB_VEN, PNY_RTX_3060TI_XLR8_REVEL_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "PNY GeForce RTX 3060 Ti XLR8 REVEL EPIC-X" }, + {NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, NVIDIA_SUB_VEN, PNY_RTX_3060TI_XLR8_REVEL_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "PNY GeForce RTX 3060 Ti XLR8 REVEL EPIC-X" }, + {NVIDIA_VEN, NVIDIA_RTX3060TI_V1_LHR_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3060TI_V1_LHR_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "NVIDIA GeForce RTX 3060 Ti V1 LHR" }, + {NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3060TI_LHR_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "NVIDIA GeForce RTX 3060 Ti LHR" }, + {NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, PNY_SUB_VEN, PNY_RTX_3070TI_XLR8_UPRISING_EPIC_X_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "PNY GeForce RTX 3070 Ti XLR8 Uprising EPIC-X"}, + {NVIDIA_VEN, NVIDIA_RTX3080_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3080_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 3080 FE" }, + {NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3080TI_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 3080 Ti FE" }, + {NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, NVIDIA_SUB_VEN, MANLI_RTX3080TI_GALLARDO_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "MANLI GeForce RTX 3080 Ti GALLARDO" }, + {NVIDIA_VEN, NVIDIA_RTX3090_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3090_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 3090 FE" }, + {NVIDIA_VEN, NVIDIA_RTX3090TI_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX3090TI_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 3090 Ti FE" }, + {NVIDIA_VEN, NVIDIA_RTX4060_DEV, PALIT_SUB_VEN, PALIT_RTX4060_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Palit GeForce RTX 4060 Dual" }, + {NVIDIA_VEN, NVIDIA_RTX4070_DEV, PALIT_SUB_VEN, PALIT_RTX4070_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Palit GeForce RTX 4070" }, + {NVIDIA_VEN, NVIDIA_RTX4070S_DEV, PALIT_SUB_VEN, PALIT_RTX4070S_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGB, "Palit GeForce RTX 4070 SUPER Dual" }, + {NVIDIA_VEN, NVIDIA_RTX4070_DEV, GAINWARD_SUB_VEN, GAINWARD_RTX_4070_GHOST_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "Gainward GeForce RTX 4070 Ghost" }, + {NVIDIA_VEN, NVIDIA_RTX4080_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX4080_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 4080 FE" }, + {NVIDIA_VEN, NVIDIA_RTX4080_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX4080_FE_SUB_DEV2, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 4080 FE" }, + {NVIDIA_VEN, NVIDIA_RTX4080S_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX4080S_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 4080 SUPER FE" }, + {NVIDIA_VEN, NVIDIA_RTX4090_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX4090_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 4090 FE" }, + {NVIDIA_VEN, NVIDIA_RTX4090_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX4090_FE_SUB_DEV2, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 4090 FE" }, + {NVIDIA_VEN, NVIDIA_RTX5080_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX5080_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 5080 FE" }, + {NVIDIA_VEN, NVIDIA_RTX5090_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX5090_FE_SUB_DEV, NVIDIA_ILLUMINATION_V1, TREATS_RGBW_AS_RGBW, "NVIDIA GeForce RTX 5090 FE" }, +}; + +void DetectNVIDIAIllumGPUs() +{ + static NV_PHYSICAL_GPU_HANDLE gpu_handles[64]; + static NV_S32 gpu_count = 0; + NV_U32 device_id; + NV_U32 ext_device_id; + NV_STATUS res; + NV_U32 revision_id; + NV_U32 sub_system_id; + + NvAPI_Initialize(); + + NvAPI_EnumPhysicalGPUs(gpu_handles, &gpu_count); + + for(NV_S32 gpu_idx = 0; gpu_idx < gpu_count; gpu_idx++) + { + res = NvAPI_GPU_GetPCIIdentifiers(gpu_handles[gpu_idx], &device_id, &sub_system_id, &revision_id, &ext_device_id); + if (res == 0) + { + uint16_t pci_device = device_id >> 16; + uint16_t pci_vendor = device_id & 0xffff; + uint16_t pci_subsystem_device = sub_system_id >> 16; + uint16_t pci_subsystem_vendor = sub_system_id & 0xffff; + for(unsigned int dev_idx = 0; dev_idx < GPU_NUM_DEVICES; dev_idx++) + { + if(pci_vendor == device_list[dev_idx].pci_vendor && + pci_device == device_list[dev_idx].pci_device && + pci_subsystem_vendor == device_list[dev_idx].pci_subsystem_vendor && + pci_subsystem_device == device_list[dev_idx].pci_subsystem_device) + { + LOG_DEBUG("[%s] Nvidia NvAPI Illumination GPU found", device_list[dev_idx].name); + switch(device_list[dev_idx].gpu_rgb_version) + { + case NVIDIA_ILLUMINATION_V1: + { + nvapi_accessor* new_nvapi = new nvapi_accessor(gpu_handles[gpu_idx]); + NVIDIAIlluminationV1Controller* controller = new NVIDIAIlluminationV1Controller(new_nvapi, device_list[dev_idx].treats_rgbw_as_rgb, device_list[dev_idx].name); + RGBController_NVIDIAIlluminationV1* rgb_controller = new RGBController_NVIDIAIlluminationV1(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + break; + } + } + } + } + } +} + +REGISTER_DETECTOR("Nvidia NvAPI Illumination", DetectNVIDIAIllumGPUs); diff --git a/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationV1Controller.cpp b/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationV1Controller.cpp deleted file mode 100644 index ae8b4be9..00000000 --- a/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationV1Controller.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/*-----------------------------------------------*\ -| NVIDIAIlluminationV1Controller.cpp | -| | -| Driver for NVIDIA Illumination controlled GPUs | -| | -| Carter Miller (GingerRunner) 1/5/2022 | -\*-----------------------------------------------*/ - -#include "NVIDIAIlluminationV1Controller.h" - -NVIDIAIlluminationV1Controller::NVIDIAIlluminationV1Controller(nvapi_accessor* nvapi_ptr, bool treats_rgbw_as_rgb) -{ - nvapi = nvapi_ptr; - _treats_rgbw_as_rgb = treats_rgbw_as_rgb; -} - -NVIDIAIlluminationV1Controller::~NVIDIAIlluminationV1Controller() -{ -} - -void NVIDIAIlluminationV1Controller::checkNVAPIreturn() -{ - if (nvapi_return != NVAPI_OK) - { - LOG_DEBUG("NVAPI return code not NVAPI_OK: %d", nvapi_return); - } -} - -void NVIDIAIlluminationV1Controller::getControl() -{ - /*------------------------------------------------------------------------------------------------*\ - | This was previously memset(&zone_params, 0, sizeof(zone_params)) | - | But this kind of zero initialization is more up-to-date and safer in the event of non-primitive | - | data types | - \*------------------------------------------------------------------------------------------------*/ - zone_params = {}; - /*---------------------------------------------------------------------------------------------------*\ - | Hardcoded value found via sniffing, this may be different for other cards, once that is | - | found, may be best to simply if/else this based on the card detected or map it out in the detector | - | and then pass via constructor to here. | - \*---------------------------------------------------------------------------------------------------*/ - zone_params.version = 72012; - zone_params.bDefault = 0; - /*---------------------------------------------------------------------------------------------------*\ - | As far as I can tell, this pre-populates the zone type value, as well as the number of zones | - | able to be controlled, and their existing settings, very useful for extending this controller. | - \*---------------------------------------------------------------------------------------------------*/ - nvapi_return = nvapi->nvapi_zone_control(NVAPI_ZONE_GET_CONTROL, &zone_params); - checkNVAPIreturn(); -} - -void NVIDIAIlluminationV1Controller::setControl() -{ - nvapi_return = nvapi->nvapi_zone_control(NVAPI_ZONE_SET_CONTROL, &zone_params); - checkNVAPIreturn(); -} - -/*----------------------------------------------------------------------------------------------------*\ -| This function exists to check if RGB colors are all set to zero, and if so, to take the brightness | -| down to zero. This was done to comply with functionality in OpenRGB such as "Lights Off" which | -| sends RGB values of all zeroes, but doesn't seem to send a brightness of zero at this time (6/2022). | -\*----------------------------------------------------------------------------------------------------*/ -bool NVIDIAIlluminationV1Controller::allZero(std::array colors) -{ - return colors == all_zeros; -} - -void NVIDIAIlluminationV1Controller::setZoneRGBW(uint8_t zone, uint8_t red, uint8_t green, uint8_t blue, uint8_t white, uint8_t brightness) -{ - zone_params.zones[zone].data.rgbw.data.manualRGBW.rgbwParams.colorR = red; - zone_params.zones[zone].data.rgbw.data.manualRGBW.rgbwParams.colorG = green; - zone_params.zones[zone].data.rgbw.data.manualRGBW.rgbwParams.colorB = blue; - zone_params.zones[zone].data.rgbw.data.manualRGBW.rgbwParams.colorW = white; - zone_params.zones[zone].data.rgbw.data.manualRGBW.rgbwParams.brightnessPct = brightness; -} - -void NVIDIAIlluminationV1Controller::setZoneRGB(uint8_t zone, uint8_t red, uint8_t green, uint8_t blue, uint8_t brightness) -{ - zone_params.zones[zone].data.rgb.data.manualRGB.rgbParams.colorR = red; - zone_params.zones[zone].data.rgb.data.manualRGB.rgbParams.colorG = green; - zone_params.zones[zone].data.rgb.data.manualRGB.rgbParams.colorB = blue; - zone_params.zones[zone].data.rgb.data.manualRGB.rgbParams.brightnessPct = brightness; -} - - -void NVIDIAIlluminationV1Controller::setZone(uint8_t zone, uint8_t mode, NVIDIAIllumination_Config zone_config) -{ - getControl(); - uint8_t red = RGBGetRValue(zone_config.colors[0]); - uint8_t green = RGBGetGValue(zone_config.colors[0]); - uint8_t blue = RGBGetBValue(zone_config.colors[0]); - uint8_t white = 0; - switch(mode) - { - case NVIDIA_ILLUMINATION_OFF: - zone_params.zones[zone].ctrlMode = NV_GPU_CLIENT_ILLUM_CTRL_MODE_MANUAL_RGB; - if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGB) - { - setZoneRGB(zone, 0, 0, 0, 0); - } - else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGBW) - { - setZoneRGBW(zone, 0, 0, 0, 0, 0); - } - else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_SINGLE_COLOR) - { - zone_params.zones[zone].data.singleColor.data.manualSingleColor.singleColorParams.brightnessPct = 0; - } - else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_COLOR_FIXED) - { - zone_params.zones[zone].data.colorFixed.data.manualColorFixed.colorFixedParams.brightnessPct = 0; - } - break; - case NVIDIA_ILLUMINATION_DIRECT: - zone_params.zones[zone].ctrlMode = NV_GPU_CLIENT_ILLUM_CTRL_MODE_MANUAL_RGB; - if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGB) - { - setZoneRGB(zone, red, green, blue, zone_config.brightness); - } - else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGBW) - { - /*----------------------------------------------------------------------------------------------------*\ - | Certain devices seem to ignore the white value entirely, despite the zone being reported back by the | - | API as RGBW, as such, this if statement was added to conduct a different course of action based | - | on definitions placed in the controller page | - \*----------------------------------------------------------------------------------------------------*/ - if(!_treats_rgbw_as_rgb) - { - uint8_t min_rgb_value = 0xFF; - uint8_t max_rgb_value = 0; - min_rgb_value = ((red < 0xFF) ? red : min_rgb_value); - min_rgb_value = ((green < min_rgb_value) ? green : min_rgb_value); - min_rgb_value = ((blue < min_rgb_value) ? blue : min_rgb_value); - max_rgb_value = ((red > 0) ? red : max_rgb_value); - max_rgb_value = ((green > max_rgb_value) ? green : max_rgb_value); - max_rgb_value = ((blue > max_rgb_value) ? blue : max_rgb_value); - /*---------------------------------------------------------------------------------------------------*\ - | If difference between the highest and lowest RGB values is 10 or lower, set the white value only, | - | zero out the rest, this logic was found via tedious examination | - \*---------------------------------------------------------------------------------------------------*/ - if (max_rgb_value - min_rgb_value <= 10) - { - red = 0; - green = 0; - blue = 0; - white = (max_rgb_value + min_rgb_value)/2; - } - } - setZoneRGBW(zone, red, green, blue, white, zone_config.brightness); - } - else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_SINGLE_COLOR) - { - zone_params.zones[zone].data.singleColor.data.manualSingleColor.singleColorParams.brightnessPct = allZero({red, green, blue, white}) ? 0 : zone_config.brightness; - } - else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_COLOR_FIXED) - { - zone_params.zones[zone].data.colorFixed.data.manualColorFixed.colorFixedParams.brightnessPct = allZero({red, green, blue, white}) ? 0 : zone_config.brightness; - } - break; - } - setControl(); -} - -int NVIDIAIlluminationV1Controller::getZoneColor(uint8_t zone_index) -{ - return ToRGBColor(zone_params.zones[zone_index].data.rgb.data.manualRGB.rgbParams.colorR, - zone_params.zones[zone_index].data.rgb.data.manualRGB.rgbParams.colorG, - zone_params.zones[zone_index].data.rgb.data.manualRGB.rgbParams.colorB); -} - -std::vector NVIDIAIlluminationV1Controller::getInfo() -{ - std::vector zone_types; - getControl(); - for(unsigned int i = 0; i < zone_params.numIllumZonesControl; i++) - { - zone_types.push_back(zone_params.zones[i].type); - } - return zone_types; -} diff --git a/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationV1Controller.h b/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationV1Controller.h deleted file mode 100644 index 3ea81e46..00000000 --- a/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationV1Controller.h +++ /dev/null @@ -1,60 +0,0 @@ -/*-----------------------------------------*\ -| NVIDIAIlluminationV1Controller.h | -| | -| Definitions and types for direct NVIDIA | -| Illumination-based NVIDIA GPUs' RGB | -| controller | -| | -| Carter Miller (GingerRunner) 1/4/2022 | -\*-----------------------------------------*/ - - -#include -#include -#include -#include "nvapi_accessor.h" -#include "RGBController.h" -#include "LogManager.h" - -#pragma once - -#define NVIDIA_ILLUMINATION_V1_CONTROLLER_NAME "NVIDIA_ILLUMINATION_V1" -#define NVAPI_OK 0 - -struct NVIDIAIllumination_Config -{ - uint8_t brightness; - RGBColor colors[7]; -}; - -enum -{ - NVIDIA_ILLUMINATION_OFF = 0, - NVIDIA_ILLUMINATION_DIRECT = 1 -}; - -class NVIDIAIlluminationV1Controller -{ - public: - NVIDIAIlluminationV1Controller(nvapi_accessor* nvapi_ptr, bool treats_rgbw_as_rgb); - ~NVIDIAIlluminationV1Controller(); - - void getControl(); - void setControl(); - bool allZero(std::array colors); - void setZoneRGBW(uint8_t zone, uint8_t red, uint8_t green, uint8_t blue, uint8_t white, uint8_t brightness); - void setZoneRGB(uint8_t zone, uint8_t red, uint8_t green, uint8_t blue, uint8_t brightness); - void setZone(uint8_t zone, uint8_t mode, NVIDIAIllumination_Config zone_config); - int getZoneColor(uint8_t zone_index); - std::vector getInfo(); - - private: - void checkNVAPIreturn(); - - nvapi_accessor* nvapi; - bool _treats_rgbw_as_rgb; - NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS zone_params; - NV_STATUS nvapi_return = 0; - const std::array all_zeros = {0, 0, 0, 0}; - -}; diff --git a/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationV1Controller_Windows_Linux.cpp b/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationV1Controller_Windows_Linux.cpp new file mode 100644 index 00000000..ca9d2402 --- /dev/null +++ b/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationV1Controller_Windows_Linux.cpp @@ -0,0 +1,190 @@ +/*---------------------------------------------------------*\ +| NVIDIAIlluminationV1Controller_Windows_Linux.cpp | +| | +| Driver for NVIDIA Illumination V1 GPU | +| | +| Carter Miller (GingerRunner) 05 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "NVIDIAIlluminationV1Controller_Windows_Linux.h" + +NVIDIAIlluminationV1Controller::NVIDIAIlluminationV1Controller(nvapi_accessor* nvapi_ptr, bool treats_rgbw_as_rgb, std::string dev_name) +{ + nvapi = nvapi_ptr; + _treats_rgbw_as_rgb = treats_rgbw_as_rgb; + name = dev_name; +} + +NVIDIAIlluminationV1Controller::~NVIDIAIlluminationV1Controller() +{ + +} + +std::string NVIDIAIlluminationV1Controller::GetName() +{ + return(name); +} + +void NVIDIAIlluminationV1Controller::checkNVAPIreturn() +{ + if (nvapi_return != NVAPI_OK) + { + LOG_DEBUG("NVAPI return code not NVAPI_OK: %d", nvapi_return); + } +} + +void NVIDIAIlluminationV1Controller::getControl() +{ + /*------------------------------------------------------------------------------------------------*\ + | This was previously memset(&zone_params, 0, sizeof(zone_params)) | + | But this kind of zero initialization is more up-to-date and safer in the event of non-primitive | + | data types | + \*------------------------------------------------------------------------------------------------*/ + zone_params = {}; + /*---------------------------------------------------------------------------------------------------*\ + | Hardcoded value found via sniffing, this may be different for other cards, once that is | + | found, may be best to simply if/else this based on the card detected or map it out in the detector | + | and then pass via constructor to here. | + \*---------------------------------------------------------------------------------------------------*/ + zone_params.version = 72012; + zone_params.bDefault = 0; + /*---------------------------------------------------------------------------------------------------*\ + | As far as I can tell, this pre-populates the zone type value, as well as the number of zones | + | able to be controlled, and their existing settings, very useful for extending this controller. | + \*---------------------------------------------------------------------------------------------------*/ + nvapi_return = nvapi->nvapi_zone_control(NVAPI_ZONE_GET_CONTROL, &zone_params); + checkNVAPIreturn(); +} + +void NVIDIAIlluminationV1Controller::setControl() +{ + nvapi_return = nvapi->nvapi_zone_control(NVAPI_ZONE_SET_CONTROL, &zone_params); + checkNVAPIreturn(); +} + +/*----------------------------------------------------------------------------------------------------*\ +| This function exists to check if RGB colors are all set to zero, and if so, to take the brightness | +| down to zero. This was done to comply with functionality in OpenRGB such as "Lights Off" which | +| sends RGB values of all zeroes, but doesn't seem to send a brightness of zero at this time (6/2022). | +\*----------------------------------------------------------------------------------------------------*/ +bool NVIDIAIlluminationV1Controller::allZero(std::array colors) +{ + return colors == all_zeros; +} + +void NVIDIAIlluminationV1Controller::setZoneRGBW(uint8_t zone, uint8_t red, uint8_t green, uint8_t blue, uint8_t white, uint8_t brightness) +{ + zone_params.zones[zone].data.rgbw.data.manualRGBW.rgbwParams.colorR = red; + zone_params.zones[zone].data.rgbw.data.manualRGBW.rgbwParams.colorG = green; + zone_params.zones[zone].data.rgbw.data.manualRGBW.rgbwParams.colorB = blue; + zone_params.zones[zone].data.rgbw.data.manualRGBW.rgbwParams.colorW = white; + zone_params.zones[zone].data.rgbw.data.manualRGBW.rgbwParams.brightnessPct = brightness; +} + +void NVIDIAIlluminationV1Controller::setZoneRGB(uint8_t zone, uint8_t red, uint8_t green, uint8_t blue, uint8_t brightness) +{ + zone_params.zones[zone].data.rgb.data.manualRGB.rgbParams.colorR = red; + zone_params.zones[zone].data.rgb.data.manualRGB.rgbParams.colorG = green; + zone_params.zones[zone].data.rgb.data.manualRGB.rgbParams.colorB = blue; + zone_params.zones[zone].data.rgb.data.manualRGB.rgbParams.brightnessPct = brightness; +} + + +void NVIDIAIlluminationV1Controller::setZone(uint8_t zone, uint8_t mode, NVIDIAIllumination_Config zone_config) +{ + getControl(); + uint8_t red = RGBGetRValue(zone_config.colors[0]); + uint8_t green = RGBGetGValue(zone_config.colors[0]); + uint8_t blue = RGBGetBValue(zone_config.colors[0]); + uint8_t white = 0; + switch(mode) + { + case NVIDIA_ILLUMINATION_OFF: + zone_params.zones[zone].ctrlMode = NV_GPU_CLIENT_ILLUM_CTRL_MODE_MANUAL_RGB; + if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGB) + { + setZoneRGB(zone, 0, 0, 0, 0); + } + else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGBW) + { + setZoneRGBW(zone, 0, 0, 0, 0, 0); + } + else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_SINGLE_COLOR) + { + zone_params.zones[zone].data.singleColor.data.manualSingleColor.singleColorParams.brightnessPct = 0; + } + else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_COLOR_FIXED) + { + zone_params.zones[zone].data.colorFixed.data.manualColorFixed.colorFixedParams.brightnessPct = 0; + } + break; + case NVIDIA_ILLUMINATION_DIRECT: + zone_params.zones[zone].ctrlMode = NV_GPU_CLIENT_ILLUM_CTRL_MODE_MANUAL_RGB; + if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGB) + { + setZoneRGB(zone, red, green, blue, zone_config.brightness); + } + else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGBW) + { + /*----------------------------------------------------------------------------------------------------*\ + | Certain devices seem to ignore the white value entirely, despite the zone being reported back by the | + | API as RGBW, as such, this if statement was added to conduct a different course of action based | + | on definitions placed in the controller page | + \*----------------------------------------------------------------------------------------------------*/ + if(!_treats_rgbw_as_rgb) + { + uint8_t min_rgb_value = 0xFF; + uint8_t max_rgb_value = 0; + min_rgb_value = ((red < 0xFF) ? red : min_rgb_value); + min_rgb_value = ((green < min_rgb_value) ? green : min_rgb_value); + min_rgb_value = ((blue < min_rgb_value) ? blue : min_rgb_value); + max_rgb_value = ((red > 0) ? red : max_rgb_value); + max_rgb_value = ((green > max_rgb_value) ? green : max_rgb_value); + max_rgb_value = ((blue > max_rgb_value) ? blue : max_rgb_value); + /*---------------------------------------------------------------------------------------------------*\ + | If difference between the highest and lowest RGB values is 10 or lower, set the white value only, | + | zero out the rest, this logic was found via tedious examination | + \*---------------------------------------------------------------------------------------------------*/ + if (max_rgb_value - min_rgb_value <= 10) + { + red = 0; + green = 0; + blue = 0; + white = (max_rgb_value + min_rgb_value)/2; + } + } + setZoneRGBW(zone, red, green, blue, white, zone_config.brightness); + } + else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_SINGLE_COLOR) + { + zone_params.zones[zone].data.singleColor.data.manualSingleColor.singleColorParams.brightnessPct = allZero({red, green, blue, white}) ? 0 : zone_config.brightness; + } + else if(zone_params.zones[zone].type == NV_GPU_CLIENT_ILLUM_ZONE_TYPE_COLOR_FIXED) + { + zone_params.zones[zone].data.colorFixed.data.manualColorFixed.colorFixedParams.brightnessPct = allZero({red, green, blue, white}) ? 0 : zone_config.brightness; + } + break; + } + setControl(); +} + +int NVIDIAIlluminationV1Controller::getZoneColor(uint8_t zone_index) +{ + return ToRGBColor(zone_params.zones[zone_index].data.rgb.data.manualRGB.rgbParams.colorR, + zone_params.zones[zone_index].data.rgb.data.manualRGB.rgbParams.colorG, + zone_params.zones[zone_index].data.rgb.data.manualRGB.rgbParams.colorB); +} + +std::vector NVIDIAIlluminationV1Controller::getInfo() +{ + std::vector zone_types; + getControl(); + for(unsigned int i = 0; i < zone_params.numIllumZonesControl; i++) + { + zone_types.push_back(zone_params.zones[i].type); + } + return zone_types; +} diff --git a/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationV1Controller_Windows_Linux.h b/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationV1Controller_Windows_Linux.h new file mode 100644 index 00000000..708c78ee --- /dev/null +++ b/Controllers/NVIDIAIlluminationController/NVIDIAIlluminationV1Controller_Windows_Linux.h @@ -0,0 +1,62 @@ +/*---------------------------------------------------------*\ +| NVIDIAIlluminationV1Controller_Windows_Linux.h | +| | +| Driver for NVIDIA Illumination V1 GPU | +| | +| Carter Miller (GingerRunner) 04 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "nvapi_accessor_Windows_Linux.h" +#include "RGBController.h" +#include "LogManager.h" + +#define NVIDIA_ILLUMINATION_V1_CONTROLLER_NAME "NVIDIA_ILLUMINATION_V1" +#define NVAPI_OK 0 + +struct NVIDIAIllumination_Config +{ + uint8_t brightness; + RGBColor colors[7]; +}; + +enum +{ + NVIDIA_ILLUMINATION_OFF = 0, + NVIDIA_ILLUMINATION_DIRECT = 1 +}; + +class NVIDIAIlluminationV1Controller +{ +public: + NVIDIAIlluminationV1Controller(nvapi_accessor* nvapi_ptr, bool treats_rgbw_as_rgb, std::string dev_name); + ~NVIDIAIlluminationV1Controller(); + + std::string GetName(); + + void getControl(); + void setControl(); + bool allZero(std::array colors); + void setZoneRGBW(uint8_t zone, uint8_t red, uint8_t green, uint8_t blue, uint8_t white, uint8_t brightness); + void setZoneRGB(uint8_t zone, uint8_t red, uint8_t green, uint8_t blue, uint8_t brightness); + void setZone(uint8_t zone, uint8_t mode, NVIDIAIllumination_Config zone_config); + int getZoneColor(uint8_t zone_index); + std::vector getInfo(); + +private: + nvapi_accessor* nvapi; + bool _treats_rgbw_as_rgb; + NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS zone_params; + NV_STATUS nvapi_return = 0; + const std::array all_zeros = {0, 0, 0, 0}; + std::string name; + + void checkNVAPIreturn(); +}; diff --git a/Controllers/NVIDIAIlluminationController/RGBController_NVIDIAIllumination.cpp b/Controllers/NVIDIAIlluminationController/RGBController_NVIDIAIllumination.cpp deleted file mode 100644 index ba57f48f..00000000 --- a/Controllers/NVIDIAIlluminationController/RGBController_NVIDIAIllumination.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/*--------------------------------------------*\ -| RGBController_NVIDIAIllumination.cpp | -| | -| Generic RGB Interface for OpenRGB direct | -| NVIDIA Illumination controller NVIDIA GPUs. | -| Note that this works for Windows only. | -| | -| Carter Miller (GingerRunner) 1/4/2022 | -\*--------------------------------------------*/ - -/**------------------------------------------------------------------*\ - @name NVIDIA Illumination - @category GPU - @type PCI - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectNVIDIAIllumGPUs - @comment Tested on various 30 series GPUs and a Founders Edition 2070 Super - If you want to see if your card should also use this controller, download the DLLs from the release of [this](https://gitlab.com/OpenRGBDevelopers/NvAPISpy). - - Perform the global replacement technique, which is specified in the README of NvAPI spy. Once this is complete, use an RGB program of your choice and make some basic - lighting changes. - - Check the C:\NvAPISpy\ folder and see if the logs created are filled with calls like this: - ``` - NvAPI_GPU_ClientIllumZonesGetControl: version: 72012 numIllumZones: 2 bDefault: 0 rsvdField: 0 - ZoneIdx: 0 ---------------------------------------- - **ZoneType: RGBW ControlMode: MANUAL - **DATA_RGBW:: Red: 255 Green: 0 Blue: 0 White: 0 Brightness%: 36 - ZoneIdx: 1 ---------------------------------------- - **ZoneType: SINGLE_COLOR ControlMode: MANUAL - **DATA_SINGLE_COLOR:: Brightness% 100 - NvAPI_GPU_ClientIllumZonesSetControl: version: 72012 numIllumZones: 2 bDefault: 0 rsvdField: 0 - ZoneIdx: 0 ---------------------------------------- - **ZoneType: RGBW ControlMode: MANUAL - **DATA_RGBW:: Red: 255 Green: 0 Blue: 0 White: 0 Brightness%: 36 - ZoneIdx: 1 ---------------------------------------- - **ZoneType: SINGLE_COLOR ControlMode: MANUAL - **DATA_SINGLE_COLOR:: Brightness% 44 - ``` - If you see Get/Set Calls above for zone control, please create a [new device issue](https://gitlab.com/CalcProgrammer1/OpenRGB/-/issues/new?issuable_template=New%20Device#) - and attach the relevant details to request support for your device (try various modes in each color, especially white and shades around it, since some cards treat RGBW as - standard RGB). -\*-------------------------------------------------------------------*/ - - -#include "RGBController_NVIDIAIllumination.h" -#include "NVIDIAIlluminationV1Controller.h" -#include - -RGBController_NVIDIAIlluminationV1::RGBController_NVIDIAIlluminationV1(NVIDIAIlluminationV1Controller* controller_ptr) -{ - controller = controller_ptr; - - name = "NVIDIA Illumination GPU"; - vendor = "NVIDIA"; - description = "NVIDIA Illumination RGB GPU Device"; - - type = DEVICE_TYPE_GPU; - - mode Off; - Off.name = "Off"; - Off.value = NVIDIA_ILLUMINATION_OFF; - Off.color_mode = MODE_COLORS_NONE; - modes.push_back(Off); - - mode Static; - Static.name = "Direct"; - Static.value = NVIDIA_ILLUMINATION_DIRECT; - Static.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR; - Static.color_mode = MODE_COLORS_PER_LED; - Static.colors_min = 1; - Static.colors_max = 1; - Static.brightness_min = 0; - Static.brightness = 100; - Static.brightness_max = 100; - modes.push_back(Static); - - SetupZones(); - - for(unsigned int i = 0; i < zones.size(); i++) - { - zones[i].colors[0] = controller->getZoneColor(i); - } -} - -RGBController_NVIDIAIlluminationV1::~RGBController_NVIDIAIlluminationV1() -{ - delete controller; -} - -void RGBController_NVIDIAIlluminationV1::UpdateSingleLED(int) -{ - DeviceUpdateLEDs(); -} - -void RGBController_NVIDIAIlluminationV1::SetupZones() -{ - /*--------------------------------------------------------------------------*\ - | Use the NvAPI to gather existing zones on the card and their capabilities, | - | populate available zones accordingly. | - \*--------------------------------------------------------------------------*/ - zoneTypes = controller->getInfo(); - nvidia_illum_zone_names[NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGB] = "RGB"; - nvidia_illum_zone_names[NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGBW] = "RGBW"; - nvidia_illum_zone_names[NV_GPU_CLIENT_ILLUM_ZONE_TYPE_COLOR_FIXED] = "FIXED COLOR"; - nvidia_illum_zone_names[NV_GPU_CLIENT_ILLUM_ZONE_TYPE_SINGLE_COLOR] = "SINGLE COLOR"; - for(uint8_t zone_idx = 0; zone_idx < zoneTypes.size(); zone_idx++) - { - zone* new_zone = new zone(); - led* new_led = new led(); - - new_zone->name = std::to_string(zone_idx) + " - " + (std::string)nvidia_illum_zone_names[zoneTypes[zone_idx]]; - new_zone->type = ZONE_TYPE_SINGLE; - new_zone->leds_min = 1; - new_zone->leds_max = 1; - new_zone->leds_count = 1; - new_zone->matrix_map = NULL; - new_led->name = "Entire Zone"; - leds.push_back(*new_led); - zones.push_back(*new_zone); - zoneIndexMap.push_back(zone_idx); - } - SetupColors(); - -} - -void RGBController_NVIDIAIlluminationV1::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_NVIDIAIlluminationV1::DeviceUpdateLEDs() -{ - NVIDIAIllumination_Config nv_zone_config; - for(uint8_t zone_idx = 0; zone_idx < zoneIndexMap.size(); zone_idx++) - { - nv_zone_config.colors[0] = colors[zone_idx]; - nv_zone_config.brightness = modes[active_mode].brightness; - controller->setZone(zone_idx, modes[active_mode].value, nv_zone_config); - } -} - -void RGBController_NVIDIAIlluminationV1::UpdateZoneLEDs(int zone) -{ - NVIDIAIllumination_Config nv_zone_config; - nv_zone_config.colors[0] = colors[zone]; - nv_zone_config.brightness = modes[active_mode].brightness; - controller->setZone(zone, modes[active_mode].value, nv_zone_config); -} - -uint8_t RGBController_NVIDIAIlluminationV1::getModeIndex(uint8_t mode_value) -{ - for(uint8_t mode_index = 0; mode_index < modes.size(); mode_index++) - { - if(modes[mode_index].value == mode_value) - { - return mode_index; - } - } - return 0; -} - -void RGBController_NVIDIAIlluminationV1::DeviceUpdateMode() -{ - DeviceUpdateLEDs(); -} diff --git a/Controllers/NVIDIAIlluminationController/RGBController_NVIDIAIllumination.h b/Controllers/NVIDIAIlluminationController/RGBController_NVIDIAIllumination.h deleted file mode 100644 index ba7d7160..00000000 --- a/Controllers/NVIDIAIlluminationController/RGBController_NVIDIAIllumination.h +++ /dev/null @@ -1,40 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_NVIDIAIllumination.h | -| | -| NVIDIA Illumination Generic RGB Interface| -| for OpenRGB | -| | -| Carter Miller (GingerRunner) 1/4/2022 | -\*-----------------------------------------*/ - - -#pragma once - -#include "RGBController.h" -#include "NVIDIAIlluminationV1Controller.h" -#include - -#define NVIDIA_FOUNDERS_V1_CONTROLLER_NAME "NVIDIA_FOUNDERS_V1" - -class RGBController_NVIDIAIlluminationV1 : public RGBController -{ - public: - RGBController_NVIDIAIlluminationV1(NVIDIAIlluminationV1Controller* nvidia_founders_ptr); - ~RGBController_NVIDIAIlluminationV1(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - private: - uint8_t getModeIndex(uint8_t mode_value); - NVIDIAIlluminationV1Controller* controller; - std::vector zoneIndexMap; - std::vector zoneTypes; - std::map nvidia_illum_zone_names; -}; \ No newline at end of file diff --git a/Controllers/NVIDIAIlluminationController/RGBController_NVIDIAIllumination_Windows_Linux.cpp b/Controllers/NVIDIAIlluminationController/RGBController_NVIDIAIllumination_Windows_Linux.cpp new file mode 100644 index 00000000..c7200881 --- /dev/null +++ b/Controllers/NVIDIAIlluminationController/RGBController_NVIDIAIllumination_Windows_Linux.cpp @@ -0,0 +1,168 @@ +/*---------------------------------------------------------*\ +| RGBController_NVIDIAIllumination_Windows_Linux.cpp | +| | +| RGBController for NVIDIA Illumination GPU | +| | +| Carter Miller (GingerRunner) 04 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RGBController_NVIDIAIllumination_Windows_Linux.h" + +/**------------------------------------------------------------------*\ + @name NVIDIA Illumination + @category GPU + @type PCI + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectNVIDIAIllumGPUs + @comment Tested on various 30 series GPUs and a Founders Edition 2070 Super + If you want to see if your card should also use this controller, download the DLLs from the release of [this](https://gitlab.com/OpenRGBDevelopers/NvAPISpy). + + Perform the global replacement technique, which is specified in the README of NvAPI spy. Once this is complete, use an RGB program of your choice and make some basic + lighting changes. + + Check the C:\NvAPISpy\ folder and see if the logs created are filled with calls like this: + ``` + NvAPI_GPU_ClientIllumZonesGetControl: version: 72012 numIllumZones: 2 bDefault: 0 rsvdField: 0 + ZoneIdx: 0 ---------------------------------------- + **ZoneType: RGBW ControlMode: MANUAL + **DATA_RGBW:: Red: 255 Green: 0 Blue: 0 White: 0 Brightness%: 36 + ZoneIdx: 1 ---------------------------------------- + **ZoneType: SINGLE_COLOR ControlMode: MANUAL + **DATA_SINGLE_COLOR:: Brightness% 100 + NvAPI_GPU_ClientIllumZonesSetControl: version: 72012 numIllumZones: 2 bDefault: 0 rsvdField: 0 + ZoneIdx: 0 ---------------------------------------- + **ZoneType: RGBW ControlMode: MANUAL + **DATA_RGBW:: Red: 255 Green: 0 Blue: 0 White: 0 Brightness%: 36 + ZoneIdx: 1 ---------------------------------------- + **ZoneType: SINGLE_COLOR ControlMode: MANUAL + **DATA_SINGLE_COLOR:: Brightness% 44 + ``` + If you see Get/Set Calls above for zone control, please create a [new device issue](https://gitlab.com/CalcProgrammer1/OpenRGB/-/issues/new?issuable_template=New%20Device#) + and attach the relevant details to request support for your device (try various modes in each color, especially white and shades around it, since some cards treat RGBW as + standard RGB). +\*-------------------------------------------------------------------*/ + +RGBController_NVIDIAIlluminationV1::RGBController_NVIDIAIlluminationV1(NVIDIAIlluminationV1Controller* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = "NVIDIA"; + description = "NVIDIA Illumination RGB GPU Device"; + type = DEVICE_TYPE_GPU; + + mode Off; + Off.name = "Off"; + Off.value = NVIDIA_ILLUMINATION_OFF; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Static; + Static.name = "Direct"; + Static.value = NVIDIA_ILLUMINATION_DIRECT; + Static.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_PER_LED_COLOR; + Static.color_mode = MODE_COLORS_PER_LED; + Static.colors_min = 1; + Static.colors_max = 1; + Static.brightness_min = 0; + Static.brightness = 100; + Static.brightness_max = 100; + modes.push_back(Static); + + SetupZones(); + + for(unsigned int i = 0; i < zones.size(); i++) + { + zones[i].colors[0] = controller->getZoneColor(i); + } +} + +RGBController_NVIDIAIlluminationV1::~RGBController_NVIDIAIlluminationV1() +{ + delete controller; +} + +void RGBController_NVIDIAIlluminationV1::UpdateSingleLED(int) +{ + DeviceUpdateLEDs(); +} + +void RGBController_NVIDIAIlluminationV1::SetupZones() +{ + /*--------------------------------------------------------------------------*\ + | Use the NvAPI to gather existing zones on the card and their capabilities, | + | populate available zones accordingly. | + \*--------------------------------------------------------------------------*/ + zoneTypes = controller->getInfo(); + nvidia_illum_zone_names[NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGB] = "RGB"; + nvidia_illum_zone_names[NV_GPU_CLIENT_ILLUM_ZONE_TYPE_RGBW] = "RGBW"; + nvidia_illum_zone_names[NV_GPU_CLIENT_ILLUM_ZONE_TYPE_COLOR_FIXED] = "FIXED COLOR"; + nvidia_illum_zone_names[NV_GPU_CLIENT_ILLUM_ZONE_TYPE_SINGLE_COLOR] = "SINGLE COLOR"; + for(uint8_t zone_idx = 0; zone_idx < zoneTypes.size(); zone_idx++) + { + zone* new_zone = new zone(); + led* new_led = new led(); + + new_zone->name = std::to_string(zone_idx) + " - " + (std::string)nvidia_illum_zone_names[zoneTypes[zone_idx]]; + new_zone->type = ZONE_TYPE_SINGLE; + new_zone->leds_min = 1; + new_zone->leds_max = 1; + new_zone->leds_count = 1; + new_zone->matrix_map = NULL; + new_led->name = "Entire Zone"; + leds.push_back(*new_led); + zones.push_back(*new_zone); + zoneIndexMap.push_back(zone_idx); + } + SetupColors(); + +} + +void RGBController_NVIDIAIlluminationV1::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_NVIDIAIlluminationV1::DeviceUpdateLEDs() +{ + NVIDIAIllumination_Config nv_zone_config; + for(uint8_t zone_idx = 0; zone_idx < zoneIndexMap.size(); zone_idx++) + { + nv_zone_config.colors[0] = colors[zone_idx]; + nv_zone_config.brightness = modes[active_mode].brightness; + controller->setZone(zone_idx, modes[active_mode].value, nv_zone_config); + } +} + +void RGBController_NVIDIAIlluminationV1::UpdateZoneLEDs(int zone) +{ + NVIDIAIllumination_Config nv_zone_config; + nv_zone_config.colors[0] = colors[zone]; + nv_zone_config.brightness = modes[active_mode].brightness; + controller->setZone(zone, modes[active_mode].value, nv_zone_config); +} + +uint8_t RGBController_NVIDIAIlluminationV1::getModeIndex(uint8_t mode_value) +{ + for(uint8_t mode_index = 0; mode_index < modes.size(); mode_index++) + { + if(modes[mode_index].value == mode_value) + { + return mode_index; + } + } + return 0; +} + +void RGBController_NVIDIAIlluminationV1::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} diff --git a/Controllers/NVIDIAIlluminationController/RGBController_NVIDIAIllumination_Windows_Linux.h b/Controllers/NVIDIAIlluminationController/RGBController_NVIDIAIllumination_Windows_Linux.h new file mode 100644 index 00000000..fb78064c --- /dev/null +++ b/Controllers/NVIDIAIlluminationController/RGBController_NVIDIAIllumination_Windows_Linux.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------*\ +| RGBController_NVIDIAIllumination_Windows_Linux.h | +| | +| RGBController for NVIDIA Illumination GPU | +| | +| Carter Miller (GingerRunner) 04 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "NVIDIAIlluminationV1Controller_Windows_Linux.h" + +#define NVIDIA_FOUNDERS_V1_CONTROLLER_NAME "NVIDIA_FOUNDERS_V1" + +class RGBController_NVIDIAIlluminationV1 : public RGBController +{ + public: + RGBController_NVIDIAIlluminationV1(NVIDIAIlluminationV1Controller* nvidia_founders_ptr); + ~RGBController_NVIDIAIlluminationV1(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + private: + uint8_t getModeIndex(uint8_t mode_value); + NVIDIAIlluminationV1Controller* controller; + std::vector zoneIndexMap; + std::vector zoneTypes; + std::map nvidia_illum_zone_names; +}; diff --git a/Controllers/NVIDIAIlluminationController/nvapi_accessor.cpp b/Controllers/NVIDIAIlluminationController/nvapi_accessor.cpp deleted file mode 100644 index cd2152bf..00000000 --- a/Controllers/NVIDIAIlluminationController/nvapi_accessor.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/*-----------------------------------------*\ -| nvapi_accessor.cpp | -| | -| Definitions and for Nvidia NvAPI | -| direct access class | -| | -| Carter Miller (GingerRunner) 6/20/2022 | -\*-----------------------------------------*/ - -#include "nvapi_accessor.h" -#include -#include - -nvapi_accessor::nvapi_accessor(NV_PHYSICAL_GPU_HANDLE handle) -{ - this->handle = handle; -} - -NV_STATUS nvapi_accessor::nvapi_zone_control(char nvapi_call, NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS* zone_control_struct) -{ - NV_STATUS ret = -1; - - if(nvapi_call == NVAPI_ZONE_SET_CONTROL) - { - ret = NvAPI_GPU_ClientIllumZonesSetControl(handle, zone_control_struct); - } - else if(nvapi_call == NVAPI_ZONE_GET_CONTROL) - { - ret = NvAPI_GPU_ClientIllumZonesGetControl(handle, zone_control_struct); - } - /*----------------------------------------------------------------------------------*\ - | Based off experimentation, the NvAPI doesn't like to be spammed calls | - | or else it just ignores them, this applies to both get/set control (GingerRunner) | - \*----------------------------------------------------------------------------------*/ - std::this_thread::sleep_for(std::chrono::milliseconds(NVAPI_CONTROL_BUFFER_TIME_MS)); - - return(ret); -} diff --git a/Controllers/NVIDIAIlluminationController/nvapi_accessor.h b/Controllers/NVIDIAIlluminationController/nvapi_accessor.h deleted file mode 100644 index 57f6c713..00000000 --- a/Controllers/NVIDIAIlluminationController/nvapi_accessor.h +++ /dev/null @@ -1,25 +0,0 @@ -/*-----------------------------------------*\ -| nvapi_accessor.h | -| | -| Definitions and types for Nvidia NvAPI | -| direct access class | -| | -| Carter Miller (GingerRunner) 6/20/2022 | -\*-----------------------------------------*/ - -#include "nvapi.h" - -// NVAPI Direct Calls -#define NVAPI_ZONE_GET_CONTROL 0 -#define NVAPI_ZONE_SET_CONTROL 1 -#define NVAPI_CONTROL_BUFFER_TIME_MS 30 - -class nvapi_accessor -{ -public: - nvapi_accessor(NV_PHYSICAL_GPU_HANDLE handle); - NV_STATUS nvapi_zone_control(char nvapi_call, NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS* zone_control_struct); - -private: - NV_PHYSICAL_GPU_HANDLE handle; -}; diff --git a/Controllers/NVIDIAIlluminationController/nvapi_accessor_Windows_Linux.cpp b/Controllers/NVIDIAIlluminationController/nvapi_accessor_Windows_Linux.cpp new file mode 100644 index 00000000..af9c96fb --- /dev/null +++ b/Controllers/NVIDIAIlluminationController/nvapi_accessor_Windows_Linux.cpp @@ -0,0 +1,40 @@ +/*---------------------------------------------------------*\ +| nvapi_accessor_Windows_Linux.cpp | +| | +| NVAPI accessor for NVIDIA NVAPI illumination API | +| | +| Carter Miller (GingerRunner) 20 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "nvapi_accessor_Windows_Linux.h" + +nvapi_accessor::nvapi_accessor(NV_PHYSICAL_GPU_HANDLE handle) +{ + this->handle = handle; +} + +NV_STATUS nvapi_accessor::nvapi_zone_control(char nvapi_call, NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS* zone_control_struct) +{ + NV_STATUS ret = -1; + + if(nvapi_call == NVAPI_ZONE_SET_CONTROL) + { + ret = NvAPI_GPU_ClientIllumZonesSetControl(handle, zone_control_struct); + } + else if(nvapi_call == NVAPI_ZONE_GET_CONTROL) + { + ret = NvAPI_GPU_ClientIllumZonesGetControl(handle, zone_control_struct); + } + /*----------------------------------------------------------------------------------*\ + | Based off experimentation, the NvAPI doesn't like to be spammed calls | + | or else it just ignores them, this applies to both get/set control (GingerRunner) | + \*----------------------------------------------------------------------------------*/ + std::this_thread::sleep_for(std::chrono::milliseconds(NVAPI_CONTROL_BUFFER_TIME_MS)); + + return(ret); +} diff --git a/Controllers/NVIDIAIlluminationController/nvapi_accessor_Windows_Linux.h b/Controllers/NVIDIAIlluminationController/nvapi_accessor_Windows_Linux.h new file mode 100644 index 00000000..8ff70b6b --- /dev/null +++ b/Controllers/NVIDIAIlluminationController/nvapi_accessor_Windows_Linux.h @@ -0,0 +1,27 @@ +/*---------------------------------------------------------*\ +| nvapi_accessor_Windows_Linux.h | +| | +| NVAPI accessor for NVIDIA NVAPI illumination API | +| | +| Carter Miller (GingerRunner) 20 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "nvapi.h" + +// NVAPI Direct Calls +#define NVAPI_ZONE_GET_CONTROL 0 +#define NVAPI_ZONE_SET_CONTROL 1 +#define NVAPI_CONTROL_BUFFER_TIME_MS 30 + +class nvapi_accessor +{ +public: + nvapi_accessor(NV_PHYSICAL_GPU_HANDLE handle); + NV_STATUS nvapi_zone_control(char nvapi_call, NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS* zone_control_struct); + +private: + NV_PHYSICAL_GPU_HANDLE handle; +}; diff --git a/Controllers/NZXTHue1Controller/NZXTHue1Controller.cpp b/Controllers/NZXTHue1Controller/NZXTHue1Controller.cpp index 07d6a851..801ec7d5 100644 --- a/Controllers/NZXTHue1Controller/NZXTHue1Controller.cpp +++ b/Controllers/NZXTHue1Controller/NZXTHue1Controller.cpp @@ -1,16 +1,23 @@ /*---------------------------------------------------------*\ -| Processing Code for NZXT Hue 1 (Smart Device V1) | +| NZXTHue1Controller.cpp | | | -| Adam Honse (calcprogrammer1@gmail.com), 4/16/2023 | +| Driver for NZXT Hue 1 (Smart Device V1) | +| | +| Adam Honse (calcprogrammer1@gmail.com) 16 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "NZXTHue1Controller.h" #include +#include "NZXTHue1Controller.h" +#include "StringUtils.h" -NZXTHue1Controller::NZXTHue1Controller(hid_device* dev_handle, unsigned int /*fan_channels*/, const char* path) +NZXTHue1Controller::NZXTHue1Controller(hid_device* dev_handle, unsigned int /*fan_channels*/, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; Initialize(); } @@ -30,6 +37,11 @@ std::string NZXTHue1Controller::GetLocation() return("HID: " + location); } +std::string NZXTHue1Controller::GetName() +{ + return(name); +} + std::string NZXTHue1Controller::GetSerialString() { wchar_t serial_string[128]; @@ -40,10 +52,7 @@ std::string NZXTHue1Controller::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } unsigned int NZXTHue1Controller::GetAccessoryType() @@ -85,7 +94,7 @@ void NZXTHue1Controller::SetEffect \*-----------------------------------------------------*/ for (std::size_t idx = 0; idx < 40; idx++) { - int pixel_idx = idx * 3; + int pixel_idx = (int)idx * 3; RGBColor color = colors[color_idx]; color_data[pixel_idx + 0x00] = RGBGetGValue(color); color_data[pixel_idx + 0x01] = RGBGetRValue(color); @@ -95,7 +104,7 @@ void NZXTHue1Controller::SetEffect /*-----------------------------------------------------*\ | Send mode and color data | \*-----------------------------------------------------*/ - SendPacket(mode, direction, color_idx, speed, 40, &color_data[0]); + SendPacket(mode, direction, (unsigned char)color_idx, speed, 40, &color_data[0]); } } /*-----------------------------------------------------*\ @@ -108,7 +117,7 @@ void NZXTHue1Controller::SetEffect \*-----------------------------------------------------*/ for (std::size_t idx = 0; idx < num_colors; idx++) { - int pixel_idx = idx * 3; + int pixel_idx = (int)idx * 3; RGBColor color = colors[idx]; color_data[pixel_idx + 0x00] = RGBGetGValue(color); color_data[pixel_idx + 0x01] = RGBGetRValue(color); @@ -135,7 +144,7 @@ void NZXTHue1Controller::SetLEDs \*-----------------------------------------------------*/ for (std::size_t idx = 0; idx < num_colors; idx++) { - int pixel_idx = idx * 3; + int pixel_idx = (int)idx * 3; RGBColor color = colors[idx]; color_data[pixel_idx + 0x00] = RGBGetGValue(color); color_data[pixel_idx + 0x01] = RGBGetRValue(color); diff --git a/Controllers/NZXTHue1Controller/NZXTHue1Controller.h b/Controllers/NZXTHue1Controller/NZXTHue1Controller.h index 971634ba..b96e3b8d 100644 --- a/Controllers/NZXTHue1Controller/NZXTHue1Controller.h +++ b/Controllers/NZXTHue1Controller/NZXTHue1Controller.h @@ -1,14 +1,19 @@ /*---------------------------------------------------------*\ -| Definitions for NZXT Hue 1 (Smart Device V1) | +| NZXTHue1Controller.h | | | -| Adam Honse (calcprogrammer1@gmail.com), 4/16/2023 | +| Driver for NZXT Hue 1 (Smart Device V1) | +| | +| Adam Honse (calcprogrammer1@gmail.com) 16 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "RGBController.h" -#include - #pragma once +#include +#include "RGBController.h" + enum { HUE_1_ACCESSORY_STRIP = 0x00, /* NZXT Hue+ LED Strip (10 LEDs)*/ @@ -43,11 +48,12 @@ enum class NZXTHue1Controller { public: - NZXTHue1Controller(hid_device* dev_handle, unsigned int fan_channels, const char* path); + NZXTHue1Controller(hid_device* dev_handle, unsigned int fan_channels, const char* path, std::string dev_name); ~NZXTHue1Controller(); std::string GetFirmwareVersion(); std::string GetLocation(); + std::string GetName(); std::string GetSerialString(); unsigned int GetAccessoryType(); @@ -74,6 +80,7 @@ private: char firmware_version[16]; std::string location; + std::string name; unsigned int accessory_type; void Initialize(); diff --git a/Controllers/NZXTHue1Controller/NZXTHue1ControllerDetect.cpp b/Controllers/NZXTHue1Controller/NZXTHue1ControllerDetect.cpp index 8ddd9e9d..e6a37607 100644 --- a/Controllers/NZXTHue1Controller/NZXTHue1ControllerDetect.cpp +++ b/Controllers/NZXTHue1Controller/NZXTHue1ControllerDetect.cpp @@ -1,8 +1,18 @@ +/*---------------------------------------------------------*\ +| NZXTHue1ControllerDetect.cpp | +| | +| Detector for NZXT Hue 1 (Smart Device V1) | +| | +| Adam Honse (calcprogrammer1@gmail.com) 16 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "NZXTHue1Controller.h" -#include "RGBController.h" #include "RGBController_NZXTHue1.h" -#include /*-----------------------------------------------------*\ | NZXT USB IDs | @@ -24,9 +34,8 @@ void DetectNZXTHue1Controllers(hid_device_info* info, const std::string& name) if(dev) { - NZXTHue1Controller* controller = new NZXTHue1Controller(dev, 3, info->path); + NZXTHue1Controller* controller = new NZXTHue1Controller(dev, 3, info->path, name); RGBController_NZXTHue1* rgb_controller = new RGBController_NZXTHue1(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } diff --git a/Controllers/NZXTHue1Controller/RGBController_NZXTHue1.cpp b/Controllers/NZXTHue1Controller/RGBController_NZXTHue1.cpp index 41131a84..493edafe 100644 --- a/Controllers/NZXTHue1Controller/RGBController_NZXTHue1.cpp +++ b/Controllers/NZXTHue1Controller/RGBController_NZXTHue1.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_NZXTHue1.cpp | -| | -| Generic RGB Interface for NZXT Hue1 | -| | -| Adam Honse (CalcProgrammer1) 4/16/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_NZXTHue1.cpp | +| | +| RGBController for NZXT Hue 1 (Smart Device V1) | +| | +| Adam Honse (calcprogrammer1@gmail.com) 16 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_NZXTHue1.h" @@ -21,153 +24,153 @@ RGBController_NZXTHue1::RGBController_NZXTHue1(NZXTHue1Controller* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "NZXT Hue 1"; - vendor = "NZXT"; - type = DEVICE_TYPE_LEDSTRIP; - description = "NZXT Hue 1 Device"; - version = controller->GetFirmwareVersion(); - location = controller->GetLocation(); - serial = controller->GetSerialString(); + name = controller->GetName(); + vendor = "NZXT"; + type = DEVICE_TYPE_LEDSTRIP; + description = "NZXT Hue 1 Device"; + version = controller->GetFirmwareVersion(); + location = controller->GetLocation(); + serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = HUE_1_MODE_FIXED; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = HUE_1_MODE_FIXED; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); mode Fading; - Fading.name = "Fading"; - Fading.value = HUE_1_MODE_FADING; - Fading.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Fading.speed_min = HUE_1_SPEED_SLOWEST; - Fading.speed_max = HUE_1_SPEED_FASTEST; - Fading.colors_min = 1; - Fading.colors_max = 8; - Fading.speed = HUE_1_SPEED_NORMAL; - Fading.color_mode = MODE_COLORS_MODE_SPECIFIC; + Fading.name = "Fading"; + Fading.value = HUE_1_MODE_FADING; + Fading.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Fading.speed_min = HUE_1_SPEED_SLOWEST; + Fading.speed_max = HUE_1_SPEED_FASTEST; + Fading.colors_min = 1; + Fading.colors_max = 8; + Fading.speed = HUE_1_SPEED_NORMAL; + Fading.color_mode = MODE_COLORS_MODE_SPECIFIC; Fading.colors.resize(2); modes.push_back(Fading); mode SpectrumCycle; - SpectrumCycle.name = "Rainbow Wave"; - SpectrumCycle.value = HUE_1_MODE_SPECTRUM; - SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; - SpectrumCycle.speed_min = HUE_1_SPEED_SLOWEST; - SpectrumCycle.speed_max = HUE_1_SPEED_FASTEST; - SpectrumCycle.speed = HUE_1_SPEED_NORMAL; - SpectrumCycle.direction = MODE_DIRECTION_RIGHT; - SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.name = "Rainbow Wave"; + SpectrumCycle.value = HUE_1_MODE_SPECTRUM; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + SpectrumCycle.speed_min = HUE_1_SPEED_SLOWEST; + SpectrumCycle.speed_max = HUE_1_SPEED_FASTEST; + SpectrumCycle.speed = HUE_1_SPEED_NORMAL; + SpectrumCycle.direction = MODE_DIRECTION_RIGHT; + SpectrumCycle.color_mode = MODE_COLORS_NONE; modes.push_back(SpectrumCycle); mode Marquee; - Marquee.name = "Marquee"; - Marquee.value = HUE_1_MODE_MARQUEE; - Marquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Marquee.speed_min = HUE_1_SPEED_SLOWEST; - Marquee.speed_max = HUE_1_SPEED_FASTEST; - Marquee.colors_min = 1; - Marquee.colors_max = 1; - Marquee.speed = HUE_1_SPEED_NORMAL; - Marquee.direction = MODE_DIRECTION_RIGHT; - Marquee.color_mode = MODE_COLORS_MODE_SPECIFIC; + Marquee.name = "Marquee"; + Marquee.value = HUE_1_MODE_MARQUEE; + Marquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Marquee.speed_min = HUE_1_SPEED_SLOWEST; + Marquee.speed_max = HUE_1_SPEED_FASTEST; + Marquee.colors_min = 1; + Marquee.colors_max = 1; + Marquee.speed = HUE_1_SPEED_NORMAL; + Marquee.direction = MODE_DIRECTION_RIGHT; + Marquee.color_mode = MODE_COLORS_MODE_SPECIFIC; Marquee.colors.resize(1); modes.push_back(Marquee); mode CoverMarquee; - CoverMarquee.name = "Cover Marquee"; - CoverMarquee.value = HUE_1_MODE_COVER_MARQUEE; - CoverMarquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - CoverMarquee.speed_min = HUE_1_SPEED_SLOWEST; - CoverMarquee.speed_max = HUE_1_SPEED_FASTEST; - CoverMarquee.colors_min = 1; - CoverMarquee.colors_max = 8; - CoverMarquee.speed = HUE_1_SPEED_NORMAL; - CoverMarquee.direction = MODE_DIRECTION_RIGHT; - CoverMarquee.color_mode = MODE_COLORS_MODE_SPECIFIC; + CoverMarquee.name = "Cover Marquee"; + CoverMarquee.value = HUE_1_MODE_COVER_MARQUEE; + CoverMarquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + CoverMarquee.speed_min = HUE_1_SPEED_SLOWEST; + CoverMarquee.speed_max = HUE_1_SPEED_FASTEST; + CoverMarquee.colors_min = 1; + CoverMarquee.colors_max = 8; + CoverMarquee.speed = HUE_1_SPEED_NORMAL; + CoverMarquee.direction = MODE_DIRECTION_RIGHT; + CoverMarquee.color_mode = MODE_COLORS_MODE_SPECIFIC; CoverMarquee.colors.resize(2); modes.push_back(CoverMarquee); mode Alternating; - Alternating.name = "Alternating"; - Alternating.value = HUE_1_MODE_ALTERNATING; - Alternating.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Alternating.speed_min = HUE_1_SPEED_SLOWEST; - Alternating.speed_max = HUE_1_SPEED_FASTEST; - Alternating.colors_min = 1; - Alternating.colors_max = 2; - Alternating.speed = HUE_1_SPEED_NORMAL; - Alternating.direction = MODE_DIRECTION_RIGHT; - Alternating.color_mode = MODE_COLORS_MODE_SPECIFIC; + Alternating.name = "Alternating"; + Alternating.value = HUE_1_MODE_ALTERNATING; + Alternating.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Alternating.speed_min = HUE_1_SPEED_SLOWEST; + Alternating.speed_max = HUE_1_SPEED_FASTEST; + Alternating.colors_min = 1; + Alternating.colors_max = 2; + Alternating.speed = HUE_1_SPEED_NORMAL; + Alternating.direction = MODE_DIRECTION_RIGHT; + Alternating.color_mode = MODE_COLORS_MODE_SPECIFIC; Alternating.colors.resize(2); modes.push_back(Alternating); mode Pulsing; - Pulsing.name = "Pulsing"; - Pulsing.value = HUE_1_MODE_PULSING; - Pulsing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Pulsing.speed_min = HUE_1_SPEED_SLOWEST; - Pulsing.speed_max = HUE_1_SPEED_FASTEST; - Pulsing.colors_min = 1; - Pulsing.colors_max = 8; - Pulsing.speed = HUE_1_SPEED_NORMAL; - Pulsing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Pulsing.name = "Pulsing"; + Pulsing.value = HUE_1_MODE_PULSING; + Pulsing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Pulsing.speed_min = HUE_1_SPEED_SLOWEST; + Pulsing.speed_max = HUE_1_SPEED_FASTEST; + Pulsing.colors_min = 1; + Pulsing.colors_max = 8; + Pulsing.speed = HUE_1_SPEED_NORMAL; + Pulsing.color_mode = MODE_COLORS_MODE_SPECIFIC; Pulsing.colors.resize(2); modes.push_back(Pulsing); mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = HUE_1_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_PER_LED_COLOR; - Breathing.speed_min = HUE_1_SPEED_SLOWEST; - Breathing.speed_max = HUE_1_SPEED_FASTEST; - Breathing.colors_min = 1; - Breathing.colors_max = 8; - Breathing.speed = HUE_1_SPEED_NORMAL; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.name = "Breathing"; + Breathing.value = HUE_1_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_PER_LED_COLOR; + Breathing.speed_min = HUE_1_SPEED_SLOWEST; + Breathing.speed_max = HUE_1_SPEED_FASTEST; + Breathing.colors_min = 1; + Breathing.colors_max = 8; + Breathing.speed = HUE_1_SPEED_NORMAL; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; Breathing.colors.resize(2); modes.push_back(Breathing); mode Alert; - Alert.name = "Alert"; - Alert.value = HUE_1_MODE_ALERT; - Alert.flags = 0; - Alert.color_mode = MODE_COLORS_NONE; + Alert.name = "Alert"; + Alert.value = HUE_1_MODE_ALERT; + Alert.flags = 0; + Alert.color_mode = MODE_COLORS_NONE; modes.push_back(Alert); mode Candlelight; - Candlelight.name = "Candlelight"; - Candlelight.value = HUE_1_MODE_CANDLELIGHT; - Candlelight.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Candlelight.colors_min = 1; - Candlelight.colors_max = 1; - Candlelight.color_mode = MODE_COLORS_MODE_SPECIFIC; + Candlelight.name = "Candlelight"; + Candlelight.value = HUE_1_MODE_CANDLELIGHT; + Candlelight.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Candlelight.colors_min = 1; + Candlelight.colors_max = 1; + Candlelight.color_mode = MODE_COLORS_MODE_SPECIFIC; Candlelight.colors.resize(1); modes.push_back(Candlelight); mode Wings; - Wings.name = "Wings"; - Wings.value = HUE_1_MODE_WINGS; - Wings.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Wings.speed_min = HUE_1_SPEED_SLOWEST; - Wings.speed_max = HUE_1_SPEED_FASTEST; - Wings.colors_min = 1; - Wings.colors_max = 1; - Wings.speed = HUE_1_SPEED_NORMAL; - Wings.color_mode = MODE_COLORS_MODE_SPECIFIC; + Wings.name = "Wings"; + Wings.value = HUE_1_MODE_WINGS; + Wings.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Wings.speed_min = HUE_1_SPEED_SLOWEST; + Wings.speed_max = HUE_1_SPEED_FASTEST; + Wings.colors_min = 1; + Wings.colors_max = 1; + Wings.speed = HUE_1_SPEED_NORMAL; + Wings.color_mode = MODE_COLORS_MODE_SPECIFIC; Wings.colors.resize(1); modes.push_back(Wings); mode Wave; - Wave.name = "Wave"; - Wave.value = HUE_1_MODE_WAVE; - Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR; - Wave.speed_min = HUE_1_SPEED_SLOWEST; - Wave.speed_max = HUE_1_SPEED_FASTEST; - Wave.speed = HUE_1_SPEED_NORMAL; - Wave.color_mode = MODE_COLORS_PER_LED; + Wave.name = "Wave"; + Wave.value = HUE_1_MODE_WAVE; + Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR; + Wave.speed_min = HUE_1_SPEED_SLOWEST; + Wave.speed_max = HUE_1_SPEED_FASTEST; + Wave.speed = HUE_1_SPEED_NORMAL; + Wave.color_mode = MODE_COLORS_PER_LED; modes.push_back(Wave); SetupZones(); @@ -292,7 +295,7 @@ void RGBController_NZXTHue1::DeviceUpdateMode() modes[active_mode].speed, direction, colors, - modes[active_mode].colors.size() + (unsigned int)modes[active_mode].colors.size() ); } } diff --git a/Controllers/NZXTHue1Controller/RGBController_NZXTHue1.h b/Controllers/NZXTHue1Controller/RGBController_NZXTHue1.h index 60024222..c19ffdb3 100644 --- a/Controllers/NZXTHue1Controller/RGBController_NZXTHue1.h +++ b/Controllers/NZXTHue1Controller/RGBController_NZXTHue1.h @@ -1,12 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_NZXTHue1.h | -| | -| Generic RGB Interface for NZXT Hue+ | -| | -| Adam Honse (CalcProgrammer1) 6/20/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_NZXTHue1.h | +| | +| RGBController for NZXT Hue 1 (Smart Device V1) | +| | +| Adam Honse (calcprogrammer1@gmail.com) 16 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "NZXTHue1Controller.h" diff --git a/Controllers/NZXTHue2Controller/NZXTHue2Controller.cpp b/Controllers/NZXTHue2Controller/NZXTHue2Controller.cpp index fe86ab79..50bead5f 100644 --- a/Controllers/NZXTHue2Controller/NZXTHue2Controller.cpp +++ b/Controllers/NZXTHue2Controller/NZXTHue2Controller.cpp @@ -1,21 +1,27 @@ /*---------------------------------------------------------*\ -| Processing Code for NZXT Hue 2 | +| NZXTHue2Controller.cpp | | | -| Adam Honse (calcprogrammer1@gmail.com), 12/29/2016 | +| Driver for NZXT Hue 2 | +| | +| Adam Honse (calcprogrammer1@gmail.com) 29 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "NZXTHue2Controller.h" -#include "LogManager.h" - +#include #include #include #include -#include +#include "LogManager.h" +#include "NZXTHue2Controller.h" +#include "StringUtils.h" -NZXTHue2Controller::NZXTHue2Controller(hid_device* dev_handle, unsigned int rgb_channels, unsigned int fan_channels, const char* path) +NZXTHue2Controller::NZXTHue2Controller(hid_device* dev_handle, unsigned int rgb_channels, unsigned int fan_channels, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; num_fan_channels = fan_channels; num_rgb_channels = rgb_channels; @@ -54,6 +60,11 @@ std::string NZXTHue2Controller::GetLocation() return("HID: " + location); } +std::string NZXTHue2Controller::GetName() +{ + return(name); +} + unsigned int NZXTHue2Controller::GetNumFanChannels() { return(num_fan_channels); @@ -79,10 +90,7 @@ std::string NZXTHue2Controller::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void NZXTHue2Controller::SendFan @@ -202,6 +210,10 @@ void NZXTHue2Controller::UpdateDeviceList() num_leds_in_device = 1; break; + case 0x13: //F120 RGB fan (120mm) + num_leds_in_device = 18; + break; + case 0x14: //F140 RGB fan (140mm) num_leds_in_device = 18; break; @@ -210,10 +222,30 @@ void NZXTHue2Controller::UpdateDeviceList() num_leds_in_device = 20; break; + case 0x16: //F140 RGB Duo fan (140mm) + num_leds_in_device = 20; + break; + case 0x17: //F120 RGB Core fan (120mm) num_leds_in_device = 8; break; + case 0x18: //F140 RGB Core fan (140mm) + num_leds_in_device = 8; + break; + + case 0x19: //F120 RGB Core fan case version (120mm) + num_leds_in_device = 8; + break; + + case 0x1D: //F360 RGB Core Fan Case Version (360mm) + num_leds_in_device = 24; + break; + + case 0x1E: //Kraken Elite Ring + num_leds_in_device = 24; + break; + default: break; } @@ -284,7 +316,7 @@ void NZXTHue2Controller::SetChannelEffect \*-----------------------------------------------------*/ for (std::size_t idx = 0; idx < num_colors; idx++) { - int pixel_idx = idx * 3; + int pixel_idx = (int)idx * 3; RGBColor color = colors[idx]; color_data[pixel_idx + 0x00] = RGBGetGValue(color); color_data[pixel_idx + 0x01] = RGBGetRValue(color); @@ -311,7 +343,7 @@ void NZXTHue2Controller::SetChannelLEDs \*-----------------------------------------------------*/ for (std::size_t idx = 0; idx < num_colors; idx++) { - int pixel_idx = idx * 3; + int pixel_idx = (int)idx * 3; RGBColor color = colors[idx]; color_data[pixel_idx + 0x00] = RGBGetGValue(color); color_data[pixel_idx + 0x01] = RGBGetRValue(color); diff --git a/Controllers/NZXTHue2Controller/NZXTHue2Controller.h b/Controllers/NZXTHue2Controller/NZXTHue2Controller.h index 324beb3b..4ad12402 100644 --- a/Controllers/NZXTHue2Controller/NZXTHue2Controller.h +++ b/Controllers/NZXTHue2Controller/NZXTHue2Controller.h @@ -1,15 +1,20 @@ /*---------------------------------------------------------*\ -| Definitions for NZXT Hue 2 | +| NZXTHue2Controller.h | | | -| Adam Honse (calcprogrammer1@gmail.com), 12/29/2016 | +| Driver for NZXT Hue 2 | +| | +| Adam Honse (calcprogrammer1@gmail.com) 29 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "RGBController.h" +#pragma once + #include #include -#include - -#pragma once +#include +#include "RGBController.h" enum { @@ -61,11 +66,12 @@ enum class NZXTHue2Controller { public: - NZXTHue2Controller(hid_device* dev_handle, unsigned int rgb_channels, unsigned int fan_channels, const char* path); + NZXTHue2Controller(hid_device* dev_handle, unsigned int rgb_channels, unsigned int fan_channels, const char* path, std::string dev_name); ~NZXTHue2Controller(); std::string GetFirmwareVersion(); std::string GetLocation(); + std::string GetName(); std::string GetSerialString(); unsigned char GetFanCommand @@ -122,6 +128,7 @@ private: char firmware_version[16]; std::string location; + std::string name; unsigned int num_fan_channels; unsigned int num_rgb_channels; diff --git a/Controllers/NZXTHue2Controller/NZXTHue2ControllerDetect.cpp b/Controllers/NZXTHue2Controller/NZXTHue2ControllerDetect.cpp index 5216f0f6..9699196a 100644 --- a/Controllers/NZXTHue2Controller/NZXTHue2ControllerDetect.cpp +++ b/Controllers/NZXTHue2Controller/NZXTHue2ControllerDetect.cpp @@ -1,24 +1,42 @@ -#include "Detector.h" -#include "NZXTHue2Controller.h" -#include "RGBController.h" -#include "RGBController_NZXTHue2.h" -#include +/*---------------------------------------------------------*\ +| NZXTHue2ControllerDetect.cpp | +| | +| Detector for NZXT Hue 2 | +| | +| Adam Honse (calcprogrammer1@gmail.com) 29 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#define NZXT_VID 0x1E71 -#define NZXT_HUE_2_PID 0x2001 -#define NZXT_HUE_2_AMBIENT_PID 0x2002 -#define NZXT_MOTHERBOARD_DEVICE_PID 0x2005 -#define NZXT_MOTHERBOARD_DEVICE_2_PID 0x200B -#define NZXT_SMART_DEVICE_V2_PID 0x2006 -#define NZXT_KRAKEN_X3_SERIES_PID 0x2007 -#define NZXT_KRAKEN_X3_SERIES_RGB_PID 0x2014 -#define NZXT_RGB_FAN_CONTROLLER_PID 0x2009 -#define NZXT_RGB_FAN_CONTROLLER2_PID 0x2010 -#define NZXT_RGB_FAN_CONTROLLER3_PID 0x200E -#define NZXT_RGB_FAN_CONTROLLER4_PID 0x2011 -#define NZXT_RGB_CONTROLLER_PID 0x2012 -#define NZXT_SMART_DEVICE_V2_1_PID 0x200D -#define NZXT_SMART_DEVICE_V2_2_PID 0x200F +#include +#include "Detector.h" +#include "LogManager.h" +#include "NZXTHue2Controller.h" +#include "RGBController_NZXTHue2.h" + +#define NZXT_VID 0x1E71 +#define NZXT_HUE_2_PID 0x2001 +#define NZXT_HUE_2_AMBIENT_PID 0x2002 +#define NZXT_MOTHERBOARD_DEVICE_PID 0x2005 +#define NZXT_MOTHERBOARD_DEVICE_2_PID 0x200B +#define NZXT_SMART_DEVICE_V2_PID 0x2006 +#define NZXT_KRAKEN_X3_SERIES_PID 0x2007 +#define NZXT_KRAKEN_X3_SERIES_RGB_PID 0x2014 +#define NZXT_KRAKEN_2024_ELITE_SERIES_RGB_PID 0x3012 +#define NZXT_RGB_FAN_CONTROLLER_PID 0x2009 +#define NZXT_RGB_FAN_CONTROLLER2_PID 0x2010 +#define NZXT_RGB_FAN_CONTROLLER3_PID 0x200E +#define NZXT_RGB_FAN_CONTROLLER4_PID 0x2011 +#define NZXT_RGB_FAN_CONTROLLER5_PID 0x2019 +#define NZXT_RGB_FAN_CONTROLLER6_PID 0x2020 +#define NZXT_RGB_FAN_CONTROLLER7_PID 0x201F +#define NZXT_RGB_FAN_CONTROLLER8_PID 0x2022 +#define NZXT_RGB_FAN_CONTROLLER9_PID 0x201B +#define NZXT_RGB_CONTROLLER_1_PID 0x2012 +#define NZXT_RGB_CONTROLLER_2_PID 0x2021 +#define NZXT_SMART_DEVICE_V2_1_PID 0x200D +#define NZXT_SMART_DEVICE_V2_2_PID 0x200F static void spawn_hue(hid_device_info* info, const std::string& name, int rgb_channels, int fan_channels) { @@ -26,11 +44,15 @@ static void spawn_hue(hid_device_info* info, const std::string& name, int rgb_ch if(dev) { - NZXTHue2Controller* controller = new NZXTHue2Controller(dev, rgb_channels, fan_channels, info->path); + NZXTHue2Controller* controller = new NZXTHue2Controller(dev, rgb_channels, fan_channels, info->path, name); RGBController_NZXTHue2* rgb_controller = new RGBController_NZXTHue2(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); + LOG_TRACE("[NZXTHue2Controller] NZXT Controller setup: %s", info->path); + } + else + { + LOG_DEBUG("[NZXTHue2Controller] Failed to load device: %s!", info->path); } } @@ -59,6 +81,11 @@ void DetectNZXTKrakenX3(hid_device_info* info, const std::string& name) spawn_hue(info, name, 3, 0); } +void DetectNZXTKrakenElite(hid_device_info* info, const std::string& name) +{ + spawn_hue(info, name, 2, 2); +} + void DetectNZXTFanController(hid_device_info* info, const std::string& name) { spawn_hue(info, name, 2, 3); @@ -74,17 +101,24 @@ void DetectNZXTRGBController(hid_device_info* info, const std::string& name) spawn_hue(info, name, 3, 0); } -REGISTER_HID_DETECTOR("NZXT Hue 2", DetectNZXTHue2, NZXT_VID, NZXT_HUE_2_PID); -REGISTER_HID_DETECTOR("NZXT Hue 2 Ambient", DetectNZXTHue2Ambient, NZXT_VID, NZXT_HUE_2_AMBIENT_PID); -REGISTER_HID_DETECTOR("NZXT Hue 2 Motherboard", DetectNZXTHue2Motherboard, NZXT_VID, NZXT_MOTHERBOARD_DEVICE_PID); -REGISTER_HID_DETECTOR("NZXT Hue 2 Motherboard", DetectNZXTHue2Motherboard, NZXT_VID, NZXT_MOTHERBOARD_DEVICE_2_PID); -REGISTER_HID_DETECTOR("NZXT Smart Device V2", DetectNZXTSmartDeviceV2, NZXT_VID, NZXT_SMART_DEVICE_V2_PID); -REGISTER_HID_DETECTOR("NZXT Kraken X3 Series", DetectNZXTKrakenX3, NZXT_VID, NZXT_KRAKEN_X3_SERIES_PID); -REGISTER_HID_DETECTOR("NZXT Kraken X3 Series RGB", DetectNZXTKrakenX3, NZXT_VID, NZXT_KRAKEN_X3_SERIES_RGB_PID); -REGISTER_HID_DETECTOR("NZXT RGB & Fan Controller", DetectNZXTFanController, NZXT_VID, NZXT_RGB_FAN_CONTROLLER_PID); -REGISTER_HID_DETECTOR("NZXT RGB & Fan Controller", DetectNZXTFanController, NZXT_VID, NZXT_RGB_FAN_CONTROLLER2_PID); -REGISTER_HID_DETECTOR("NZXT RGB & Fan Controller", DetectNZXTFanController, NZXT_VID, NZXT_RGB_FAN_CONTROLLER3_PID); -REGISTER_HID_DETECTOR("NZXT RGB & Fan Controller", DetectNZXTFanController6Channel, NZXT_VID, NZXT_RGB_FAN_CONTROLLER4_PID); -REGISTER_HID_DETECTOR("NZXT RGB Controller", DetectNZXTRGBController, NZXT_VID, NZXT_RGB_CONTROLLER_PID); -REGISTER_HID_DETECTOR("NZXT Smart Device V2", DetectNZXTSmartDeviceV2, NZXT_VID, NZXT_SMART_DEVICE_V2_1_PID); -REGISTER_HID_DETECTOR("NZXT Smart Device V2", DetectNZXTSmartDeviceV2, NZXT_VID, NZXT_SMART_DEVICE_V2_2_PID); +REGISTER_HID_DETECTOR("NZXT RGB & Fan Controller", DetectNZXTFanController, NZXT_VID, NZXT_RGB_FAN_CONTROLLER_PID); +REGISTER_HID_DETECTOR("NZXT RGB & Fan Controller", DetectNZXTFanController, NZXT_VID, NZXT_RGB_FAN_CONTROLLER2_PID); +REGISTER_HID_DETECTOR("NZXT RGB & Fan Controller", DetectNZXTFanController, NZXT_VID, NZXT_RGB_FAN_CONTROLLER3_PID); +REGISTER_HID_DETECTOR("NZXT RGB & Fan Controller", DetectNZXTFanController6Channel, NZXT_VID, NZXT_RGB_FAN_CONTROLLER4_PID); +REGISTER_HID_DETECTOR("NZXT RGB & Fan Controller", DetectNZXTFanController6Channel, NZXT_VID, NZXT_RGB_FAN_CONTROLLER5_PID); +REGISTER_HID_DETECTOR("NZXT RGB & Fan Controller", DetectNZXTFanController6Channel, NZXT_VID, NZXT_RGB_FAN_CONTROLLER6_PID); +REGISTER_HID_DETECTOR("NZXT RGB & Fan Controller", DetectNZXTFanController6Channel, NZXT_VID, NZXT_RGB_FAN_CONTROLLER7_PID); +REGISTER_HID_DETECTOR("NZXT RGB & Fan Controller 2024", DetectNZXTFanController6Channel, NZXT_VID, NZXT_RGB_FAN_CONTROLLER8_PID); +REGISTER_HID_DETECTOR("NZXT B650E Motherboard", DetectNZXTFanController6Channel, NZXT_VID, NZXT_RGB_FAN_CONTROLLER9_PID); +REGISTER_HID_DETECTOR("NZXT Hue 2", DetectNZXTHue2, NZXT_VID, NZXT_HUE_2_PID); +REGISTER_HID_DETECTOR("NZXT Hue 2 Ambient", DetectNZXTHue2Ambient, NZXT_VID, NZXT_HUE_2_AMBIENT_PID); +REGISTER_HID_DETECTOR("NZXT Hue 2 Motherboard", DetectNZXTHue2Motherboard, NZXT_VID, NZXT_MOTHERBOARD_DEVICE_PID); +REGISTER_HID_DETECTOR("NZXT Hue 2 Motherboard", DetectNZXTHue2Motherboard, NZXT_VID, NZXT_MOTHERBOARD_DEVICE_2_PID); +REGISTER_HID_DETECTOR("NZXT Kraken X3 Series", DetectNZXTKrakenX3, NZXT_VID, NZXT_KRAKEN_X3_SERIES_PID); +REGISTER_HID_DETECTOR("NZXT Kraken X3 Series RGB", DetectNZXTKrakenX3, NZXT_VID, NZXT_KRAKEN_X3_SERIES_RGB_PID); +REGISTER_HID_DETECTOR("NZXT Kraken 2024 ELITE Series RGB", DetectNZXTKrakenElite, NZXT_VID, NZXT_KRAKEN_2024_ELITE_SERIES_RGB_PID); +REGISTER_HID_DETECTOR("NZXT RGB Controller", DetectNZXTRGBController, NZXT_VID, NZXT_RGB_CONTROLLER_1_PID); +REGISTER_HID_DETECTOR("NZXT RGB Controller", DetectNZXTRGBController, NZXT_VID, NZXT_RGB_CONTROLLER_2_PID); +REGISTER_HID_DETECTOR("NZXT Smart Device V2", DetectNZXTSmartDeviceV2, NZXT_VID, NZXT_SMART_DEVICE_V2_PID); +REGISTER_HID_DETECTOR("NZXT Smart Device V2", DetectNZXTSmartDeviceV2, NZXT_VID, NZXT_SMART_DEVICE_V2_1_PID); +REGISTER_HID_DETECTOR("NZXT Smart Device V2", DetectNZXTSmartDeviceV2, NZXT_VID, NZXT_SMART_DEVICE_V2_2_PID); diff --git a/Controllers/NZXTHue2Controller/RGBController_NZXTHue2.cpp b/Controllers/NZXTHue2Controller/RGBController_NZXTHue2.cpp index ea864fd3..d98bbb9a 100644 --- a/Controllers/NZXTHue2Controller/RGBController_NZXTHue2.cpp +++ b/Controllers/NZXTHue2Controller/RGBController_NZXTHue2.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_NZXTHue2.cpp | -| | -| Generic RGB Interface for NZXT Hue 2 | -| | -| Adam Honse (CalcProgrammer1) 12/29/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_NZXTHue2.cpp | +| | +| RGBController for NZXT Hue 2 | +| | +| Adam Honse (calcprogrammer1@gmail.com) 29 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_NZXTHue2.h" @@ -15,188 +18,188 @@ @save :robot: @direct :white_check_mark: @effects :white_check_mark: - @detectors DetectNZXTHue2,DetectNZXTHue2Ambient,DetectNZXTHue2Motherboard,DetectNZXTSmartDeviceV2,DetectNZXTKrakenX3,DetectNZXTFanController + @detectors DetectNZXTFanController,DetectNZXTFanController6Channel,DetectNZXTHue2,DetectNZXTHue2Ambient,DetectNZXTHue2Motherboard,DetectNZXTKrakenX3,DetectNZXTRGBController,DetectNZXTSmartDeviceV2,DetectNZXTKrakenElite @comment \*-------------------------------------------------------------------*/ RGBController_NZXTHue2::RGBController_NZXTHue2(NZXTHue2Controller* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "NZXT Hue 2"; - vendor = "NZXT"; - type = DEVICE_TYPE_LEDSTRIP; - description = "NZXT Hue 2 Device"; - version = controller->GetFirmwareVersion(); - location = controller->GetLocation(); - serial = controller->GetSerialString(); + name = controller->GetName(); + vendor = "NZXT"; + type = DEVICE_TYPE_LEDSTRIP; + description = "NZXT Hue 2 Device"; + version = controller->GetFirmwareVersion(); + location = controller->GetLocation(); + serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0xFFFF; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + 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 = HUE_2_MODE_FIXED; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Static.colors_min = 1; - Static.colors_max = 1; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.name = "Static"; + Static.value = HUE_2_MODE_FIXED; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Static.colors_min = 1; + Static.colors_max = 1; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; Static.colors.resize(1); modes.push_back(Static); mode Fading; - Fading.name = "Fading"; - Fading.value = HUE_2_MODE_FADING; - Fading.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Fading.speed_min = HUE_2_SPEED_SLOWEST; - Fading.speed_max = HUE_2_SPEED_FASTEST; - Fading.colors_min = 1; - Fading.colors_max = 8; - Fading.speed = HUE_2_SPEED_NORMAL; - Fading.color_mode = MODE_COLORS_MODE_SPECIFIC; + Fading.name = "Fading"; + Fading.value = HUE_2_MODE_FADING; + Fading.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Fading.speed_min = HUE_2_SPEED_SLOWEST; + Fading.speed_max = HUE_2_SPEED_FASTEST; + Fading.colors_min = 1; + Fading.colors_max = 8; + Fading.speed = HUE_2_SPEED_NORMAL; + Fading.color_mode = MODE_COLORS_MODE_SPECIFIC; Fading.colors.resize(1); modes.push_back(Fading); mode SpectrumCycle; - SpectrumCycle.name = "Spectrum Cycle"; - SpectrumCycle.value = HUE_2_MODE_SPECTRUM; - SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; - SpectrumCycle.speed_min = HUE_2_SPEED_SLOWEST; - SpectrumCycle.speed_max = HUE_2_SPEED_FASTEST; - SpectrumCycle.speed = HUE_2_SPEED_NORMAL; - SpectrumCycle.direction = MODE_DIRECTION_RIGHT; - SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = HUE_2_MODE_SPECTRUM; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + SpectrumCycle.speed_min = HUE_2_SPEED_SLOWEST; + SpectrumCycle.speed_max = HUE_2_SPEED_FASTEST; + SpectrumCycle.speed = HUE_2_SPEED_NORMAL; + SpectrumCycle.direction = MODE_DIRECTION_RIGHT; + SpectrumCycle.color_mode = MODE_COLORS_NONE; modes.push_back(SpectrumCycle); mode Marquee; - Marquee.name = "Marquee"; - Marquee.value = HUE_2_MODE_MARQUEE; - Marquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Marquee.speed_min = HUE_2_SPEED_SLOWEST; - Marquee.speed_max = HUE_2_SPEED_FASTEST; - Marquee.colors_min = 1; - Marquee.colors_max = 1; - Marquee.speed = HUE_2_SPEED_NORMAL; - Marquee.direction = MODE_DIRECTION_RIGHT; - Marquee.color_mode = MODE_COLORS_MODE_SPECIFIC; + Marquee.name = "Marquee"; + Marquee.value = HUE_2_MODE_MARQUEE; + Marquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Marquee.speed_min = HUE_2_SPEED_SLOWEST; + Marquee.speed_max = HUE_2_SPEED_FASTEST; + Marquee.colors_min = 1; + Marquee.colors_max = 1; + Marquee.speed = HUE_2_SPEED_NORMAL; + Marquee.direction = MODE_DIRECTION_RIGHT; + Marquee.color_mode = MODE_COLORS_MODE_SPECIFIC; Marquee.colors.resize(1); modes.push_back(Marquee); mode CoverMarquee; - CoverMarquee.name = "Cover Marquee"; - CoverMarquee.value = HUE_2_MODE_COVER_MARQUEE; - CoverMarquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - CoverMarquee.speed_min = HUE_2_SPEED_SLOWEST; - CoverMarquee.speed_max = HUE_2_SPEED_FASTEST; - CoverMarquee.colors_min = 1; - CoverMarquee.colors_max = 8; - CoverMarquee.speed = HUE_2_SPEED_NORMAL; - CoverMarquee.direction = MODE_DIRECTION_RIGHT; - CoverMarquee.color_mode = MODE_COLORS_MODE_SPECIFIC; + CoverMarquee.name = "Cover Marquee"; + CoverMarquee.value = HUE_2_MODE_COVER_MARQUEE; + CoverMarquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + CoverMarquee.speed_min = HUE_2_SPEED_SLOWEST; + CoverMarquee.speed_max = HUE_2_SPEED_FASTEST; + CoverMarquee.colors_min = 1; + CoverMarquee.colors_max = 8; + CoverMarquee.speed = HUE_2_SPEED_NORMAL; + CoverMarquee.direction = MODE_DIRECTION_RIGHT; + CoverMarquee.color_mode = MODE_COLORS_MODE_SPECIFIC; CoverMarquee.colors.resize(1); modes.push_back(CoverMarquee); mode Alternating; - Alternating.name = "Alternating"; - Alternating.value = HUE_2_MODE_ALTERNATING; - Alternating.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Alternating.speed_min = HUE_2_SPEED_SLOWEST; - Alternating.speed_max = HUE_2_SPEED_FASTEST; - Alternating.colors_min = 1; - Alternating.colors_max = 2; - Alternating.speed = HUE_2_SPEED_NORMAL; - Alternating.direction = MODE_DIRECTION_RIGHT; - Alternating.color_mode = MODE_COLORS_MODE_SPECIFIC; + Alternating.name = "Alternating"; + Alternating.value = HUE_2_MODE_ALTERNATING; + Alternating.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Alternating.speed_min = HUE_2_SPEED_SLOWEST; + Alternating.speed_max = HUE_2_SPEED_FASTEST; + Alternating.colors_min = 1; + Alternating.colors_max = 2; + Alternating.speed = HUE_2_SPEED_NORMAL; + Alternating.direction = MODE_DIRECTION_RIGHT; + Alternating.color_mode = MODE_COLORS_MODE_SPECIFIC; Alternating.colors.resize(1); modes.push_back(Alternating); mode Pulsing; - Pulsing.name = "Pulsing"; - Pulsing.value = HUE_2_MODE_PULSING; - Pulsing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Pulsing.speed_min = HUE_2_SPEED_SLOWEST; - Pulsing.speed_max = HUE_2_SPEED_FASTEST; - Pulsing.colors_min = 1; - Pulsing.colors_max = 8; - Pulsing.speed = HUE_2_SPEED_NORMAL; - Pulsing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Pulsing.name = "Pulsing"; + Pulsing.value = HUE_2_MODE_PULSING; + Pulsing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Pulsing.speed_min = HUE_2_SPEED_SLOWEST; + Pulsing.speed_max = HUE_2_SPEED_FASTEST; + Pulsing.colors_min = 1; + Pulsing.colors_max = 8; + Pulsing.speed = HUE_2_SPEED_NORMAL; + Pulsing.color_mode = MODE_COLORS_MODE_SPECIFIC; Pulsing.colors.resize(1) ; modes.push_back(Pulsing); mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = HUE_2_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_PER_LED_COLOR; - Breathing.speed_min = HUE_2_SPEED_SLOWEST; - Breathing.speed_max = HUE_2_SPEED_FASTEST; - Breathing.colors_min = 1; - Breathing.colors_max = 8; - Breathing.speed = HUE_2_SPEED_NORMAL; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.name = "Breathing"; + Breathing.value = HUE_2_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_PER_LED_COLOR; + Breathing.speed_min = HUE_2_SPEED_SLOWEST; + Breathing.speed_max = HUE_2_SPEED_FASTEST; + Breathing.colors_min = 1; + Breathing.colors_max = 8; + Breathing.speed = HUE_2_SPEED_NORMAL; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; Breathing.colors.resize( 1); modes.push_back(Breathing); mode Candle; - Candle.name = "Candle"; - Candle.value = HUE_2_MODE_CANDLE; - Candle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Candle.speed_min = HUE_2_SPEED_SLOWEST; - Candle.speed_max = HUE_2_SPEED_FASTEST; - Candle.colors_min = 1; - Candle.colors_max = 8; - Candle.speed = HUE_2_SPEED_NORMAL; - Candle.color_mode = MODE_COLORS_MODE_SPECIFIC; + Candle.name = "Candle"; + Candle.value = HUE_2_MODE_CANDLE; + Candle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Candle.speed_min = HUE_2_SPEED_SLOWEST; + Candle.speed_max = HUE_2_SPEED_FASTEST; + Candle.colors_min = 1; + Candle.colors_max = 8; + Candle.speed = HUE_2_SPEED_NORMAL; + Candle.color_mode = MODE_COLORS_MODE_SPECIFIC; Candle.colors.resize(1) ; modes.push_back(Candle); mode StarryNight; - StarryNight.name = "Starry Night"; - StarryNight.value = HUE_2_MODE_STARRY_NIGHT; - StarryNight.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - StarryNight.speed_min = HUE_2_SPEED_SLOWEST; - StarryNight.speed_max = HUE_2_SPEED_FASTEST; - StarryNight.colors_min = 1; - StarryNight.colors_max = 1; - StarryNight.speed = HUE_2_SPEED_NORMAL; - StarryNight.color_mode = MODE_COLORS_MODE_SPECIFIC; + StarryNight.name = "Starry Night"; + StarryNight.value = HUE_2_MODE_STARRY_NIGHT; + StarryNight.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + StarryNight.speed_min = HUE_2_SPEED_SLOWEST; + StarryNight.speed_max = HUE_2_SPEED_FASTEST; + StarryNight.colors_min = 1; + StarryNight.colors_max = 1; + StarryNight.speed = HUE_2_SPEED_NORMAL; + StarryNight.color_mode = MODE_COLORS_MODE_SPECIFIC; StarryNight.colors.resize(1); modes.push_back(StarryNight); mode SuperRainbow; - SuperRainbow.name = "Super Rainbow"; - SuperRainbow.value = HUE_2_MODE_SUPER_RAINBOW; - SuperRainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; - SuperRainbow.speed_min = HUE_2_SPEED_SLOWEST; - SuperRainbow.speed_max = HUE_2_SPEED_FASTEST; - SuperRainbow.speed = HUE_2_SPEED_NORMAL; - SuperRainbow.direction = MODE_DIRECTION_RIGHT; - SuperRainbow.color_mode = MODE_COLORS_NONE; + SuperRainbow.name = "Super Rainbow"; + SuperRainbow.value = HUE_2_MODE_SUPER_RAINBOW; + SuperRainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + SuperRainbow.speed_min = HUE_2_SPEED_SLOWEST; + SuperRainbow.speed_max = HUE_2_SPEED_FASTEST; + SuperRainbow.speed = HUE_2_SPEED_NORMAL; + SuperRainbow.direction = MODE_DIRECTION_RIGHT; + SuperRainbow.color_mode = MODE_COLORS_NONE; modes.push_back(SuperRainbow); mode RainbowPulse; - RainbowPulse.name = "Rainbow Pulse"; - RainbowPulse.value = HUE_2_MODE_RAINBOW_PULSE; - RainbowPulse.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; - RainbowPulse.speed_min = HUE_2_SPEED_SLOWEST; - RainbowPulse.speed_max = HUE_2_SPEED_FASTEST; - RainbowPulse.speed = HUE_2_SPEED_NORMAL; - RainbowPulse.direction = MODE_DIRECTION_RIGHT; - RainbowPulse.color_mode = MODE_COLORS_NONE; + RainbowPulse.name = "Rainbow Pulse"; + RainbowPulse.value = HUE_2_MODE_RAINBOW_PULSE; + RainbowPulse.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + RainbowPulse.speed_min = HUE_2_SPEED_SLOWEST; + RainbowPulse.speed_max = HUE_2_SPEED_FASTEST; + RainbowPulse.speed = HUE_2_SPEED_NORMAL; + RainbowPulse.direction = MODE_DIRECTION_RIGHT; + RainbowPulse.color_mode = MODE_COLORS_NONE; modes.push_back(RainbowPulse); mode RainbowFlow; - RainbowFlow.name = "Rainbow Flow"; - RainbowFlow.value = HUE_2_MODE_RAINBOW_FLOW; - RainbowFlow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; - RainbowFlow.speed_min = HUE_2_SPEED_SLOWEST; - RainbowFlow.speed_max = HUE_2_SPEED_FASTEST; - RainbowFlow.speed = HUE_2_SPEED_NORMAL; - RainbowFlow.direction = MODE_DIRECTION_RIGHT; - RainbowFlow.color_mode = MODE_COLORS_NONE; + RainbowFlow.name = "Rainbow Flow"; + RainbowFlow.value = HUE_2_MODE_RAINBOW_FLOW; + RainbowFlow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + RainbowFlow.speed_min = HUE_2_SPEED_SLOWEST; + RainbowFlow.speed_max = HUE_2_SPEED_FASTEST; + RainbowFlow.speed = HUE_2_SPEED_NORMAL; + RainbowFlow.direction = MODE_DIRECTION_RIGHT; + RainbowFlow.color_mode = MODE_COLORS_NONE; modes.push_back(RainbowFlow); SetupZones(); @@ -305,6 +308,10 @@ void RGBController_NZXTHue2::SetupZones() device_name = "Kraken X3 logo"; break; + case 0x13: //F120 RGB fan (120mm) + device_name = "F120 fan (120mm)"; + break; + case 0x14: //F140 RGB fan (140mm) device_name = "F140 fan (140mm)"; break; @@ -313,10 +320,30 @@ void RGBController_NZXTHue2::SetupZones() device_name = "F120 Duo fan (120mm)"; break; + case 0x16: //F140 RGB Duo fan (140mm) + device_name = "F140 Duo fan (140mm)"; + break; + case 0x17: //F120 RGB Core fan (120mm) device_name = "F120 Core fan (120mm)"; break; + case 0x18: //F140 RGB Core fan (140mm) + device_name = "F140 Core fan (140mm)"; + break; + + case 0x19: //F120 RGB Core fan case version (120mm) + device_name = "F120 Core fan case version (120mm)"; + break; + + case 0x1D: //F360 Core fan case version (360mm) + device_name = "F360 Core fan case version (360mm)"; + break; + + case 0x1E: //Kraken Elite Ring + device_name = "Kraken Elite Ring"; + break; + default: break; } @@ -339,8 +366,19 @@ void RGBController_NZXTHue2::SetupZones() SetupColors(); } -void RGBController_NZXTHue2::ResizeZone(int /*zone*/, int /*new_size*/) +void RGBController_NZXTHue2::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(); + } } @@ -348,7 +386,7 @@ void RGBController_NZXTHue2::DeviceUpdateLEDs() { for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) { - controller->SetChannelLEDs(zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); + controller->SetChannelLEDs((unsigned char)zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); } } @@ -389,12 +427,12 @@ void RGBController_NZXTHue2::DeviceUpdateMode() controller->SetChannelEffect ( - zone_idx, + (unsigned char)zone_idx, modes[active_mode].value, modes[active_mode].speed, direction, colors, - modes[active_mode].colors.size() + (unsigned int)modes[active_mode].colors.size() ); } } diff --git a/Controllers/NZXTHue2Controller/RGBController_NZXTHue2.h b/Controllers/NZXTHue2Controller/RGBController_NZXTHue2.h index 0a9b0a21..3fe6fcf7 100644 --- a/Controllers/NZXTHue2Controller/RGBController_NZXTHue2.h +++ b/Controllers/NZXTHue2Controller/RGBController_NZXTHue2.h @@ -1,12 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_NZXTHue2.h | -| | -| Generic RGB Interface for NZXT Hue 2 | -| | -| Adam Honse (CalcProgrammer1) 12/29/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_NZXTHue2.h | +| | +| RGBController for NZXT Hue 2 | +| | +| Adam Honse (calcprogrammer1@gmail.com) 29 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "NZXTHue2Controller.h" diff --git a/Controllers/NZXTHuePlusController/NZXTHuePlusController.cpp b/Controllers/NZXTHuePlusController/NZXTHuePlusController.cpp index f54dfff0..9989b92f 100644 --- a/Controllers/NZXTHuePlusController/NZXTHuePlusController.cpp +++ b/Controllers/NZXTHuePlusController/NZXTHuePlusController.cpp @@ -1,15 +1,19 @@ /*---------------------------------------------------------*\ -| Processing Code for NZXT Hue+ | +| NZXTHuePlusController.cpp | | | -| Adam Honse (calcprogrammer1@gmail.com), 12/11/2016 | +| Driver for NZXT Hue Plus | +| | +| Adam Honse (calcprogrammer1@gmail.com) 27 Aug 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "NZXTHuePlusController.h" - +#include #include #include #include -#include +#include "NZXTHuePlusController.h" using namespace std::chrono_literals; @@ -26,7 +30,7 @@ HuePlusController::~HuePlusController() void HuePlusController::Initialize(char* port) { port_name = port; - + serialport = new serial_port(port_name.c_str(), HUE_PLUS_BAUD); channel_leds[HUE_PLUS_CHANNEL_1_IDX] = GetLEDsOnChannel(HUE_PLUS_CHANNEL_1); @@ -109,7 +113,7 @@ void HuePlusController::SetChannelEffect \*-----------------------------------------------------*/ for (std::size_t idx = 0; idx < 40; idx++) { - int pixel_idx = idx * 3; + int pixel_idx = (int)idx * 3; RGBColor color = colors[color_idx]; color_data[pixel_idx + 0x00] = RGBGetGValue(color); color_data[pixel_idx + 0x01] = RGBGetRValue(color); @@ -119,7 +123,7 @@ void HuePlusController::SetChannelEffect /*-----------------------------------------------------*\ | Send mode and color data | \*-----------------------------------------------------*/ - SendPacket(channel, mode, direction, color_idx, speed, 40, &color_data[0]); + SendPacket(channel, mode, direction, (unsigned char)color_idx, speed, 40, &color_data[0]); } } /*-----------------------------------------------------*\ @@ -132,7 +136,7 @@ void HuePlusController::SetChannelEffect \*-----------------------------------------------------*/ for (std::size_t idx = 0; idx < num_colors; idx++) { - int pixel_idx = idx * 3; + int pixel_idx = (int)idx * 3; RGBColor color = colors[idx]; color_data[pixel_idx + 0x00] = RGBGetGValue(color); color_data[pixel_idx + 0x01] = RGBGetRValue(color); @@ -160,7 +164,7 @@ void HuePlusController::SetChannelLEDs \*-----------------------------------------------------*/ for (std::size_t idx = 0; idx < num_colors; idx++) { - int pixel_idx = idx * 3; + int pixel_idx = (int)idx * 3; RGBColor color = colors[idx]; color_data[pixel_idx + 0x00] = RGBGetGValue(color); color_data[pixel_idx + 0x01] = RGBGetRValue(color); diff --git a/Controllers/NZXTHuePlusController/NZXTHuePlusController.h b/Controllers/NZXTHuePlusController/NZXTHuePlusController.h index 35a711e0..71555b96 100644 --- a/Controllers/NZXTHuePlusController/NZXTHuePlusController.h +++ b/Controllers/NZXTHuePlusController/NZXTHuePlusController.h @@ -1,16 +1,19 @@ /*---------------------------------------------------------*\ -| Definitions for NZXT Hue+ | +| NZXTHuePlusController.h | | | -| Adam Honse (calcprogrammer1@gmail.com), 12/11/2016 | +| Driver for NZXT Hue Plus | +| | +| Adam Honse (calcprogrammer1@gmail.com) 27 Aug 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#ifndef LED_STRIP_H -#define LED_STRIP_H +#pragma once +#include #include "RGBController.h" #include "serial_port.h" -#include - #ifndef TRUE #define TRUE true @@ -109,5 +112,3 @@ private: unsigned char* color_data ); }; - -#endif diff --git a/Controllers/NZXTHuePlusController/NZXTHuePlusControllerDetect.cpp b/Controllers/NZXTHuePlusController/NZXTHuePlusControllerDetect.cpp index 6bc2ae0d..e4985f66 100644 --- a/Controllers/NZXTHuePlusController/NZXTHuePlusControllerDetect.cpp +++ b/Controllers/NZXTHuePlusController/NZXTHuePlusControllerDetect.cpp @@ -1,9 +1,19 @@ +/*---------------------------------------------------------*\ +| NZXTHuePlusControllerDetect.cpp | +| | +| Detector for NZXT Hue Plus | +| | +| Adam Honse (calcprogrammer1@gmail.com) 27 Aug 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "NZXTHuePlusController.h" -#include "RGBController.h" #include "RGBController_NZXTHuePlus.h" #include "find_usb_serial_port.h" -#include #define NZXT_HUE_PLUS_VID 0x04D8 #define NZXT_HUE_PLUS_PID 0x00DF diff --git a/Controllers/NZXTHuePlusController/RGBController_NZXTHuePlus.cpp b/Controllers/NZXTHuePlusController/RGBController_NZXTHuePlus.cpp index 0ce79f40..7e613075 100644 --- a/Controllers/NZXTHuePlusController/RGBController_NZXTHuePlus.cpp +++ b/Controllers/NZXTHuePlusController/RGBController_NZXTHuePlus.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_NZXTHuePlus.cpp | -| | -| Generic RGB Interface for NZXT Hue+ | -| | -| Adam Honse (CalcProgrammer1) 6/20/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_NZXTHuePlus.cpp | +| | +| RGBController for NZXT Hue Plus | +| | +| Adam Honse (calcprogrammer1@gmail.com) 20 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_NZXTHuePlus.h" @@ -253,7 +256,7 @@ void RGBController_HuePlus::DeviceUpdateLEDs() { for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) { - controller->SetChannelLEDs(zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); + controller->SetChannelLEDs((unsigned char)zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); } } @@ -294,12 +297,12 @@ void RGBController_HuePlus::DeviceUpdateMode() controller->SetChannelEffect ( - zone_idx, + (unsigned char)zone_idx, modes[active_mode].value, modes[active_mode].speed, direction, colors, - modes[active_mode].colors.size() + (unsigned int)modes[active_mode].colors.size() ); } } diff --git a/Controllers/NZXTHuePlusController/RGBController_NZXTHuePlus.h b/Controllers/NZXTHuePlusController/RGBController_NZXTHuePlus.h index f5a530c8..b814935e 100644 --- a/Controllers/NZXTHuePlusController/RGBController_NZXTHuePlus.h +++ b/Controllers/NZXTHuePlusController/RGBController_NZXTHuePlus.h @@ -1,12 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_NZXTHuePlus.h | -| | -| Generic RGB Interface for NZXT Hue+ | -| | -| Adam Honse (CalcProgrammer1) 6/20/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_NZXTHuePlus.h | +| | +| RGBController for NZXT Hue Plus | +| | +| Adam Honse (calcprogrammer1@gmail.com) 20 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "serial_port.h" #include "NZXTHuePlusController.h" diff --git a/Controllers/NZXTKrakenController/NZXTKrakenController.cpp b/Controllers/NZXTKrakenController/NZXTKrakenController.cpp index 2d25272d..f1d8979c 100644 --- a/Controllers/NZXTKrakenController/NZXTKrakenController.cpp +++ b/Controllers/NZXTKrakenController/NZXTKrakenController.cpp @@ -1,20 +1,25 @@ /*---------------------------------------------------------*\ -| Driver for NZXT Kraken | +| NZXTKrakenController.cpp | | | -| Martin Hartl (inlart), 04/04/2020 | +| Driver for NZXT Kraken | +| | +| Martin Hartl (inlart) 04 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "NZXTKrakenController.h" - +#include #include #include -#include +#include "NZXTKrakenController.h" +#include "StringUtils.h" static void SetColor(const std::vector& colors, unsigned char* color_data) { - for (std::size_t idx = 0; idx < colors.size(); idx++) + for(std::size_t idx = 0; idx < colors.size(); idx++) { - int pixel_idx = idx * 3; + int pixel_idx = (int)idx * 3; RGBColor color = colors[idx]; color_data[pixel_idx + 0x00] = RGBGetRValue(color); color_data[pixel_idx + 0x01] = RGBGetGValue(color); @@ -27,10 +32,11 @@ static RGBColor ToLogoColor(RGBColor rgb) return ToRGBColor(RGBGetGValue(rgb), RGBGetRValue(rgb), RGBGetBValue(rgb)); } -NZXTKrakenController::NZXTKrakenController(hid_device* dev_handle, const char* path) +NZXTKrakenController::NZXTKrakenController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; /*-----------------------------------------------------*\ | Get the firmware version | @@ -53,6 +59,11 @@ std::string NZXTKrakenController::GetLocation() return("HID: " + location); } +std::string NZXTKrakenController::GetName() +{ + return(name); +} + std::string NZXTKrakenController::GetSerialString() { wchar_t serial_string[128]; @@ -63,10 +74,7 @@ std::string NZXTKrakenController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void NZXTKrakenController::UpdateStatus() diff --git a/Controllers/NZXTKrakenController/NZXTKrakenController.h b/Controllers/NZXTKrakenController/NZXTKrakenController.h index b63cc2c3..5b286a9d 100644 --- a/Controllers/NZXTKrakenController/NZXTKrakenController.h +++ b/Controllers/NZXTKrakenController/NZXTKrakenController.h @@ -1,15 +1,20 @@ /*---------------------------------------------------------*\ -| Definitions for NZXT Kraken | +| NZXTKrakenController.h | | | -| Martin Hartl (inlart), 04/04/2020 | +| Driver for NZXT Kraken | +| | +| Martin Hartl (inlart) 04 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ #pragma once -#include "RGBController.h" -#include #include -#include +#include +#include +#include "RGBController.h" enum NZXTKrakenChannel_t { @@ -46,11 +51,12 @@ enum class NZXTKrakenController { public: - NZXTKrakenController(hid_device* dev_handle, const char* path); + NZXTKrakenController(hid_device* dev_handle, const char* path, std::string dev_name); ~NZXTKrakenController(); std::string GetFirmwareVersion(); std::string GetLocation(); + std::string GetName(); std::string GetSerialString(); void UpdateEffect @@ -84,6 +90,7 @@ private: std::string firmware_version; double liquid_temperature; std::string location; + std::string name; unsigned int fan_speed; unsigned int pump_speed; }; diff --git a/Controllers/NZXTKrakenController/NZXTKrakenControllerDetect.cpp b/Controllers/NZXTKrakenController/NZXTKrakenControllerDetect.cpp index d5f09880..eb6ca5e1 100644 --- a/Controllers/NZXTKrakenController/NZXTKrakenControllerDetect.cpp +++ b/Controllers/NZXTKrakenController/NZXTKrakenControllerDetect.cpp @@ -1,9 +1,18 @@ +/*---------------------------------------------------------*\ +| NZXTKrakenControllerDetect.cpp | +| | +| Detector for NZXT Kraken | +| | +| Martin Hartl (inlart) 04 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "NZXTKrakenController.h" -#include "RGBController.h" #include "RGBController_NZXTKraken.h" -#include -#include #define NZXT_KRAKEN_VID 0x1E71 #define NZXT_KRAKEN_X2_PID 0x170E @@ -20,11 +29,12 @@ void DetectNZXTKrakenControllers(hid_device_info* info, const std::string& name) { hid_device* dev = hid_open_path(info->path); - if( dev ) + + if(dev) { - NZXTKrakenController* controller = new NZXTKrakenController(dev, info->path); + NZXTKrakenController* controller = new NZXTKrakenController(dev, info->path, name); RGBController_NZXTKraken* rgb_controller = new RGBController_NZXTKraken(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } /* DetectNZXTKrakenControllers() */ diff --git a/Controllers/NZXTKrakenController/RGBController_NZXTKraken.cpp b/Controllers/NZXTKrakenController/RGBController_NZXTKraken.cpp index 60cd5d8d..37cc8a51 100644 --- a/Controllers/NZXTKrakenController/RGBController_NZXTKraken.cpp +++ b/Controllers/NZXTKrakenController/RGBController_NZXTKraken.cpp @@ -1,14 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_NZXTKraken.cpp | -| | -| Generic RGB Interface for NZXT Kraken | -| | -| Martin Hartl (inlart) 04/04/2020 | -\*-----------------------------------------*/ - -#include "RGBController_NZXTKraken.h" +/*---------------------------------------------------------*\ +| RGBController_NZXTKraken.cpp | +| | +| RGBController for NZXT Kraken | +| | +| Martin Hartl (inlart) 04 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "RGBController_NZXTKraken.h" /**------------------------------------------------------------------*\ @name NZXT Kraken @@ -23,158 +25,158 @@ RGBController_NZXTKraken::RGBController_NZXTKraken(NZXTKrakenController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "NZXT Kraken X/M"; - vendor = "NZXT"; - type = DEVICE_TYPE_COOLER; - description = "NZXT Kraken X42/X52/X62/X72/M22"; - version = controller->GetFirmwareVersion(); - location = controller->GetLocation(); - serial = controller->GetSerialString(); + name = controller->GetName(); + vendor = "NZXT"; + type = DEVICE_TYPE_COOLER; + description = "NZXT Kraken X42/X52/X62/X72/M22"; + version = controller->GetFirmwareVersion(); + location = controller->GetLocation(); + serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = NZXT_KRAKEN_MODE_FIXED; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = NZXT_KRAKEN_MODE_FIXED; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); mode Fading; - Fading.name = "Fading"; - Fading.value = NZXT_KRAKEN_MODE_FADING; - Fading.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Fading.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; - Fading.speed_max = NZXT_KRAKEN_SPEED_FASTEST; - Fading.colors_min = 2; - Fading.colors_max = 8; - Fading.speed = NZXT_KRAKEN_SPEED_NORMAL; - Fading.color_mode = MODE_COLORS_MODE_SPECIFIC; + Fading.name = "Fading"; + Fading.value = NZXT_KRAKEN_MODE_FADING; + Fading.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Fading.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; + Fading.speed_max = NZXT_KRAKEN_SPEED_FASTEST; + Fading.colors_min = 2; + Fading.colors_max = 8; + Fading.speed = NZXT_KRAKEN_SPEED_NORMAL; + Fading.color_mode = MODE_COLORS_MODE_SPECIFIC; Fading.colors.resize(2); modes.push_back(Fading); mode SpectrumCycle; - SpectrumCycle.name = "Spectrum Cycle"; - SpectrumCycle.value = NZXT_KRAKEN_MODE_SPECTRUM; - SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; - SpectrumCycle.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; - SpectrumCycle.speed_max = NZXT_KRAKEN_SPEED_FASTEST; - SpectrumCycle.speed = NZXT_KRAKEN_SPEED_NORMAL; - SpectrumCycle.direction = MODE_DIRECTION_RIGHT; - SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = NZXT_KRAKEN_MODE_SPECTRUM; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + SpectrumCycle.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; + SpectrumCycle.speed_max = NZXT_KRAKEN_SPEED_FASTEST; + SpectrumCycle.speed = NZXT_KRAKEN_SPEED_NORMAL; + SpectrumCycle.direction = MODE_DIRECTION_RIGHT; + SpectrumCycle.color_mode = MODE_COLORS_NONE; modes.push_back(SpectrumCycle); mode Marquee; - Marquee.name = "Marquee"; - Marquee.value = NZXT_KRAKEN_MODE_MARQUEE; - Marquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Marquee.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; - Marquee.speed_max = NZXT_KRAKEN_SPEED_FASTEST; - Marquee.colors_min = 1; - Marquee.colors_max = 1; - Marquee.speed = NZXT_KRAKEN_SPEED_NORMAL; - Marquee.direction = MODE_DIRECTION_RIGHT; - Marquee.color_mode = MODE_COLORS_MODE_SPECIFIC; + Marquee.name = "Marquee"; + Marquee.value = NZXT_KRAKEN_MODE_MARQUEE; + Marquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Marquee.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; + Marquee.speed_max = NZXT_KRAKEN_SPEED_FASTEST; + Marquee.colors_min = 1; + Marquee.colors_max = 1; + Marquee.speed = NZXT_KRAKEN_SPEED_NORMAL; + Marquee.direction = MODE_DIRECTION_RIGHT; + Marquee.color_mode = MODE_COLORS_MODE_SPECIFIC; Marquee.colors.resize(1); modes.push_back(Marquee); mode CoverMarquee; - CoverMarquee.name = "Cover Marquee"; - CoverMarquee.value = NZXT_KRAKEN_MODE_COVER_MARQUEE; - CoverMarquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - CoverMarquee.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; - CoverMarquee.speed_max = NZXT_KRAKEN_SPEED_FASTEST; - CoverMarquee.colors_min = 1; - CoverMarquee.colors_max = 8; - CoverMarquee.speed = NZXT_KRAKEN_SPEED_NORMAL; - CoverMarquee.direction = MODE_DIRECTION_RIGHT; - CoverMarquee.color_mode = MODE_COLORS_MODE_SPECIFIC; + CoverMarquee.name = "Cover Marquee"; + CoverMarquee.value = NZXT_KRAKEN_MODE_COVER_MARQUEE; + CoverMarquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + CoverMarquee.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; + CoverMarquee.speed_max = NZXT_KRAKEN_SPEED_FASTEST; + CoverMarquee.colors_min = 1; + CoverMarquee.colors_max = 8; + CoverMarquee.speed = NZXT_KRAKEN_SPEED_NORMAL; + CoverMarquee.direction = MODE_DIRECTION_RIGHT; + CoverMarquee.color_mode = MODE_COLORS_MODE_SPECIFIC; CoverMarquee.colors.resize(2); modes.push_back(CoverMarquee); mode Alternating; - Alternating.name = "Alternating"; - Alternating.value = NZXT_KRAKEN_MODE_ALTERNATING; - Alternating.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Alternating.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; - Alternating.speed_max = NZXT_KRAKEN_SPEED_FASTEST; - Alternating.colors_min = 2; - Alternating.colors_max = 2; - Alternating.speed = NZXT_KRAKEN_SPEED_NORMAL; - Alternating.direction = MODE_DIRECTION_RIGHT; - Alternating.color_mode = MODE_COLORS_MODE_SPECIFIC; + Alternating.name = "Alternating"; + Alternating.value = NZXT_KRAKEN_MODE_ALTERNATING; + Alternating.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Alternating.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; + Alternating.speed_max = NZXT_KRAKEN_SPEED_FASTEST; + Alternating.colors_min = 2; + Alternating.colors_max = 2; + Alternating.speed = NZXT_KRAKEN_SPEED_NORMAL; + Alternating.direction = MODE_DIRECTION_RIGHT; + Alternating.color_mode = MODE_COLORS_MODE_SPECIFIC; Alternating.colors.resize(2); modes.push_back(Alternating); mode Pulse; - Pulse.name = "Pulse"; - Pulse.value = NZXT_KRAKEN_MODE_PULSE; - Pulse.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Pulse.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; - Pulse.speed_max = NZXT_KRAKEN_SPEED_FASTEST; - Pulse.colors_min = 1; - Pulse.colors_max = 8; - Pulse.speed = NZXT_KRAKEN_SPEED_NORMAL; - Pulse.color_mode = MODE_COLORS_MODE_SPECIFIC; + Pulse.name = "Pulse"; + Pulse.value = NZXT_KRAKEN_MODE_PULSE; + Pulse.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Pulse.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; + Pulse.speed_max = NZXT_KRAKEN_SPEED_FASTEST; + Pulse.colors_min = 1; + Pulse.colors_max = 8; + Pulse.speed = NZXT_KRAKEN_SPEED_NORMAL; + Pulse.color_mode = MODE_COLORS_MODE_SPECIFIC; Pulse.colors.resize(1); modes.push_back(Pulse); mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = NZXT_KRAKEN_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_PER_LED_COLOR; - Breathing.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; - Breathing.speed_max = NZXT_KRAKEN_SPEED_FASTEST; - Breathing.colors_min = 1; - Breathing.colors_max = 8; - Breathing.speed = NZXT_KRAKEN_SPEED_NORMAL; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.name = "Breathing"; + Breathing.value = NZXT_KRAKEN_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_PER_LED_COLOR; + Breathing.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; + Breathing.speed_max = NZXT_KRAKEN_SPEED_FASTEST; + Breathing.colors_min = 1; + Breathing.colors_max = 8; + Breathing.speed = NZXT_KRAKEN_SPEED_NORMAL; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; Breathing.colors.resize(1); modes.push_back(Breathing); mode ThaiChi; - ThaiChi.name = "Thai Chi"; - ThaiChi.value = NZXT_KRAKEN_MODE_TAI_CHI; - ThaiChi.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - ThaiChi.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; - ThaiChi.speed_max = NZXT_KRAKEN_SPEED_FASTEST; - ThaiChi.speed = NZXT_KRAKEN_SPEED_NORMAL; - ThaiChi.colors_min = 2; - ThaiChi.colors_max = 2; - ThaiChi.color_mode = MODE_COLORS_MODE_SPECIFIC; + ThaiChi.name = "Thai Chi"; + ThaiChi.value = NZXT_KRAKEN_MODE_TAI_CHI; + ThaiChi.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + ThaiChi.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; + ThaiChi.speed_max = NZXT_KRAKEN_SPEED_FASTEST; + ThaiChi.speed = NZXT_KRAKEN_SPEED_NORMAL; + ThaiChi.colors_min = 2; + ThaiChi.colors_max = 2; + ThaiChi.color_mode = MODE_COLORS_MODE_SPECIFIC; ThaiChi.colors.resize(2); modes.push_back(ThaiChi); mode WaterCooler; - WaterCooler.name = "Water Cooler"; - WaterCooler.value = NZXT_KRAKEN_MODE_WATER_COOLER; - WaterCooler.flags = MODE_FLAG_HAS_SPEED; - WaterCooler.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; - WaterCooler.speed_max = NZXT_KRAKEN_SPEED_FASTEST; - WaterCooler.speed = NZXT_KRAKEN_SPEED_NORMAL; - WaterCooler.color_mode = MODE_COLORS_NONE; + WaterCooler.name = "Water Cooler"; + WaterCooler.value = NZXT_KRAKEN_MODE_WATER_COOLER; + WaterCooler.flags = MODE_FLAG_HAS_SPEED; + WaterCooler.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; + WaterCooler.speed_max = NZXT_KRAKEN_SPEED_FASTEST; + WaterCooler.speed = NZXT_KRAKEN_SPEED_NORMAL; + WaterCooler.color_mode = MODE_COLORS_NONE; modes.push_back(WaterCooler); mode Loading; - Loading.name = "Loading"; - Loading.value = NZXT_KRAKEN_MODE_LOADING; - Loading.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Loading.colors_min = 1; - Loading.colors_max = 1; - Loading.color_mode = MODE_COLORS_MODE_SPECIFIC; + Loading.name = "Loading"; + Loading.value = NZXT_KRAKEN_MODE_LOADING; + Loading.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Loading.colors_min = 1; + Loading.colors_max = 1; + Loading.color_mode = MODE_COLORS_MODE_SPECIFIC; Loading.colors.resize(1); modes.push_back(Loading); mode Wings; - Wings.name = "Wings"; - Wings.value = NZXT_KRAKEN_MODE_WINGS; - Wings.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Wings.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; - Wings.speed_max = NZXT_KRAKEN_SPEED_FASTEST; - Wings.speed = NZXT_KRAKEN_SPEED_NORMAL; - Wings.colors_min = 1; - Wings.colors_max = 1; - Wings.color_mode = MODE_COLORS_MODE_SPECIFIC; + Wings.name = "Wings"; + Wings.value = NZXT_KRAKEN_MODE_WINGS; + Wings.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Wings.speed_min = NZXT_KRAKEN_SPEED_SLOWEST; + Wings.speed_max = NZXT_KRAKEN_SPEED_FASTEST; + Wings.speed = NZXT_KRAKEN_SPEED_NORMAL; + Wings.colors_min = 1; + Wings.colors_max = 1; + Wings.color_mode = MODE_COLORS_MODE_SPECIFIC; Wings.colors.resize(1); modes.push_back(Wings); @@ -195,7 +197,6 @@ RGBController_NZXTKraken::RGBController_NZXTKraken(NZXTKrakenController* control NZXT_KRAKEN_MODE_PULSE }; - SetupZones(); } @@ -254,7 +255,7 @@ void RGBController_NZXTKraken::ResizeZone(int /*zone*/, int /*new_size*/) std::vector> RGBController_NZXTKraken::GetColors(int zone, const mode& channel_mode) { std::vector> result; - int length = zone < 0 ? leds.size() : zones[zone].leds_count; + int length = zone < 0 ? (int)leds.size() : (int)zones[zone].leds_count; if(channel_mode.color_mode == MODE_COLORS_NONE) { @@ -311,7 +312,7 @@ void RGBController_NZXTKraken::UpdateChannel(NZXTKrakenChannel_t channel, int zo channel_mode.value, direction, speed, - idx, + (int)idx, update_colors[idx] ); } diff --git a/Controllers/NZXTKrakenController/RGBController_NZXTKraken.h b/Controllers/NZXTKrakenController/RGBController_NZXTKraken.h index d7c92fcc..8490a48f 100644 --- a/Controllers/NZXTKrakenController/RGBController_NZXTKraken.h +++ b/Controllers/NZXTKrakenController/RGBController_NZXTKraken.h @@ -1,16 +1,19 @@ -/*-----------------------------------------*\ -| RGBController_NZXTKraken.h | -| | -| Generic RGB Interface for NZXT Kraken | -| | -| Martin Hartl (inlart) 04/04/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_NZXTKraken.h | +| | +| RGBController for NZXT Kraken | +| | +| Martin Hartl (inlart) 04 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include "RGBController.h" -#include "NZXTKrakenController.h" #include +#include "RGBController.h" +#include "NZXTKrakenController.h" class RGBController_NZXTKraken : public RGBController { diff --git a/Controllers/NZXTMouseController/NZXTMouseController.cpp b/Controllers/NZXTMouseController/NZXTMouseController.cpp new file mode 100644 index 00000000..1d197e3a --- /dev/null +++ b/Controllers/NZXTMouseController/NZXTMouseController.cpp @@ -0,0 +1,144 @@ +/*---------------------------------------------------------*\ +| NZXTMouseController.cpp | +| | +| Driver for NZXT Mouse | +| | +| Adam Honse (calcprogrammer1@gmail.com) 13 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "NZXTMouseController.h" +#include "StringUtils.h" + +NZXTMouseController::NZXTMouseController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + + /*-----------------------------------------------------*\ + | Request firmware version | + \*-----------------------------------------------------*/ + SendFirmwareRequest(); +} + +NZXTMouseController::~NZXTMouseController() +{ + hid_close(dev); +} + +std::string NZXTMouseController::GetFirmwareVersion() +{ + return(firmware_version); +} + +std::string NZXTMouseController::GetLocation() +{ + return("HID: " + location); +} + +std::string NZXTMouseController::GetName() +{ + return(name); +} + +std::string NZXTMouseController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void NZXTMouseController::SetLEDs + ( + RGBColor * colors + ) +{ + unsigned char usb_buf[64]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Direct packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x43; + usb_buf[0x01] = 0xAE; + usb_buf[0x03] = 0x10; + usb_buf[0x04] = 0x02; + usb_buf[0x05] = 0x3F; + + usb_buf[24] = 0x06; + + usb_buf[25] = RGBGetRValue(colors[2]); + usb_buf[26] = RGBGetGValue(colors[2]); + usb_buf[27] = RGBGetBValue(colors[2]); + + usb_buf[29] = RGBGetRValue(colors[1]); + usb_buf[30] = RGBGetGValue(colors[1]); + usb_buf[31] = RGBGetBValue(colors[1]); + + usb_buf[33] = RGBGetRValue(colors[0]); + usb_buf[34] = RGBGetGValue(colors[0]); + usb_buf[35] = RGBGetBValue(colors[0]); + + usb_buf[37] = RGBGetRValue(colors[3]); + usb_buf[38] = RGBGetGValue(colors[3]); + usb_buf[39] = RGBGetBValue(colors[3]); + + usb_buf[41] = RGBGetRValue(colors[4]); + usb_buf[42] = RGBGetGValue(colors[4]); + usb_buf[43] = RGBGetBValue(colors[4]); + + usb_buf[45] = RGBGetRValue(colors[5]); + usb_buf[46] = RGBGetGValue(colors[5]); + usb_buf[47] = RGBGetBValue(colors[5]); + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, sizeof(usb_buf)); +} + +void NZXTMouseController::SendFirmwareRequest() +{ + unsigned char usb_buf[64]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Firmware Request packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x43; + usb_buf[0x01] = 0x81; + usb_buf[0x03] = 0x01; + + hid_write(dev, usb_buf, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Receive packets until 0x43 0x86 is received | + \*-----------------------------------------------------*/ + do + { + hid_read(dev, usb_buf, sizeof(usb_buf)); + } while( (usb_buf[0] != 0x43) || (usb_buf[1] != 0x86) ); + + /*-----------------------------------------------------*\ + | Format firmware version string | + \*-----------------------------------------------------*/ + snprintf(firmware_version, 16, "%u.%u.%u", usb_buf[0x03], usb_buf[0x04], usb_buf[0x05]); +} diff --git a/Controllers/NZXTMouseController/NZXTMouseController.h b/Controllers/NZXTMouseController/NZXTMouseController.h new file mode 100644 index 00000000..c4f8edc5 --- /dev/null +++ b/Controllers/NZXTMouseController/NZXTMouseController.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------*\ +| NZXTMouseController.h | +| | +| Driver for NZXT Mouse | +| | +| Adam Honse (calcprogrammer1@gmail.com) 13 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" + +class NZXTMouseController +{ +public: + NZXTMouseController(hid_device* dev_handle, const char* path, std::string dev_name); + ~NZXTMouseController(); + + std::string GetFirmwareVersion(); + std::string GetLocation(); + std::string GetName(); + std::string GetSerialString(); + + void SetLEDs + ( + RGBColor * colors + ); + +private: + hid_device* dev; + + char firmware_version[16]; + std::string location; + std::string name; + + void SendFirmwareRequest(); +}; diff --git a/Controllers/NZXTMouseController/NZXTMouseControllerDetect.cpp b/Controllers/NZXTMouseController/NZXTMouseControllerDetect.cpp new file mode 100644 index 00000000..8c92a916 --- /dev/null +++ b/Controllers/NZXTMouseController/NZXTMouseControllerDetect.cpp @@ -0,0 +1,44 @@ +/*---------------------------------------------------------*\ +| NZXTMouseControllerDetect.cpp | +| | +| Detector for NZXT Mouse | +| | +| Adam Honse (calcprogrammer1@gmail.com) 13 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "NZXTMouseController.h" +#include "RGBController_NZXTMouse.h" + +/*-----------------------------------------------------*\ +| NZXT USB IDs | +\*-----------------------------------------------------*/ +#define NZXT_VID 0x1E71 +#define NZXT_LIFT_PID 0x2100 + +/******************************************************************************************\ +* * +* DetectNZXTMouseControllers * +* * +* Detect devices supported by the NZXTMouse driver * +* * +\******************************************************************************************/ + +static void DetectNZXTMouseControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + NZXTMouseController* controller = new NZXTMouseController(dev, info->path, name); + RGBController_NZXTMouse* rgb_controller = new RGBController_NZXTMouse(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR_IPU("NZXT Lift", DetectNZXTMouseControllers, NZXT_VID, NZXT_LIFT_PID, 0, 0xFFCA, 1); diff --git a/Controllers/NZXTMouseController/RGBController_NZXTMouse.cpp b/Controllers/NZXTMouseController/RGBController_NZXTMouse.cpp new file mode 100644 index 00000000..dd25756e --- /dev/null +++ b/Controllers/NZXTMouseController/RGBController_NZXTMouse.cpp @@ -0,0 +1,118 @@ +/*---------------------------------------------------------*\ +| RGBController_NZXTMouse.cpp | +| | +| RGBController for NZXT Mouse | +| | +| Adam Honse (calcprogrammer1@gmail.com) 16 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_NZXTMouse.h" + +/**------------------------------------------------------------------*\ + @name NZXT Mouse + @category Mouse + @type USB + @save :x: + @direct :white_check_mark: + @effects :tools: + @detectors DetectNZXTMouseControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_NZXTMouse::RGBController_NZXTMouse(NZXTMouseController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = "NZXT"; + type = DEVICE_TYPE_MOUSE; + description = "NZXT Mouse Device"; + version = controller->GetFirmwareVersion(); + location = controller->GetLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + SetupZones(); +} + +RGBController_NZXTMouse::~RGBController_NZXTMouse() +{ + +} + +void RGBController_NZXTMouse::SetupZones() +{ + zone left; + + left.name = "Left"; + left.type = ZONE_TYPE_LINEAR; + left.leds_min = 3; + left.leds_max = 3; + left.leds_count = 3; + left.matrix_map = NULL; + + zones.push_back( left ); + + for(unsigned int led_idx = 0; led_idx < left.leds_count; led_idx++) + { + led left_led; + left_led.name = "Left LED " + std::to_string(led_idx); + + leds.push_back(left_led); + } + + zone right; + + right.name = "Right"; + right.type = ZONE_TYPE_LINEAR; + right.leds_min = 3; + right.leds_max = 3; + right.leds_count = 3; + right.matrix_map = NULL; + + zones.push_back( right ); + + for(unsigned int led_idx = 0; led_idx < right.leds_count; led_idx++) + { + led right_led; + right_led.name = "Right LED " + std::to_string(led_idx); + + leds.push_back(right_led); + } + + SetupColors(); +} + +void RGBController_NZXTMouse::ResizeZone(int /*zone*/, int /*new_size*/) +{ + +} + +void RGBController_NZXTMouse::DeviceUpdateLEDs() +{ +controller->SetLEDs(&colors[0]); +} + +void RGBController_NZXTMouse::UpdateZoneLEDs(int /*zone*/) +{ +DeviceUpdateLEDs(); +} + +void RGBController_NZXTMouse::UpdateSingleLED(int /*led*/) +{ +DeviceUpdateLEDs(); +} + +void RGBController_NZXTMouse::DeviceUpdateMode() +{ +DeviceUpdateLEDs(); +} diff --git a/Controllers/NZXTMouseController/RGBController_NZXTMouse.h b/Controllers/NZXTMouseController/RGBController_NZXTMouse.h new file mode 100644 index 00000000..0f6b4bcf --- /dev/null +++ b/Controllers/NZXTMouseController/RGBController_NZXTMouse.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_NZXTMouse.h | +| | +| RGBController for NZXT Mouse | +| | +| Adam Honse (calcprogrammer1@gmail.com) 16 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "NZXTMouseController.h" + +class RGBController_NZXTMouse : public RGBController +{ +public: + RGBController_NZXTMouse(NZXTMouseController* controller_ptr); + ~RGBController_NZXTMouse(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + NZXTMouseController* controller; + std::vector leds_channel; + std::vector zones_channel; +}; diff --git a/Controllers/NanoleafController/NanoleafController.cpp b/Controllers/NanoleafController/NanoleafController.cpp index f6f9ac7a..1a747ffc 100644 --- a/Controllers/NanoleafController/NanoleafController.cpp +++ b/Controllers/NanoleafController/NanoleafController.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| NanoleafController.cpp | -| | -| API Interface for Nanoleaf devices | -| | -| Nikita Rushmanov 01/13/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| NanoleafController.cpp | +| | +| Driver for Nanoleaf | +| | +| Nikita Rushmanov 13 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "NanoleafController.h" #include "LogManager.h" @@ -31,8 +34,11 @@ long APIRequest(std::string method, std::string location, std::string URI, json* { httplib::Result result = client.Get(URI.c_str()); - status = result->status; - body = result->body; + if(httplib::Error::Success == result.error()) + { + status = result->status; + body = result->body; + } } else if(method == "PUT") { @@ -40,30 +46,42 @@ long APIRequest(std::string method, std::string location, std::string URI, json* { httplib::Result result = client.Put(URI.c_str(), request_data->dump(), "application/json"); - status = result->status; - body = result->body; + if(httplib::Error::Success == result.error()) + { + status = result->status; + body = result->body; + } } else { httplib::Result result = client.Put(URI.c_str()); - status = result->status; - body = result->body; + if(httplib::Error::Success == result.error()) + { + status = result->status; + body = result->body; + } } } else if(method == "DELETE") { httplib::Result result = client.Delete(URI.c_str()); - status = result->status; - body = result->body; + if(httplib::Error::Success == result.error()) + { + status = result->status; + body = result->body; + } } else if(method == "POST") { httplib::Result result = client.Post(URI.c_str()); - status = result->status; - body = result->body; + if(httplib::Error::Success == result.error()) + { + status = result->status; + body = result->body; + } } /*-------------------------------------------------------------*\ @@ -167,13 +185,13 @@ void NanoleafController::UpdateLEDs(std::vector& colors) | 1 W White channel (ignored) | | 1 transitionTime Transition time (x 100ms) | \*---------------------------------------------------------*/ - uint8_t size = panel_ids.size(); + std::size_t size = panel_ids.size(); uint8_t* message = (uint8_t*)malloc((size * 7) + 1); message[0] = (uint8_t)size; /* nPanels */ - for(int i = 0; i < size; i++) + for(unsigned int i = 0; i < size; i++) { message[(7 * i) + 0 + 1] = (uint8_t)panel_ids[i]; /* panelId */ message[(7 * i) + 1 + 1] = (uint8_t)1; /* nFrames */ @@ -184,7 +202,7 @@ void NanoleafController::UpdateLEDs(std::vector& colors) message[(7 * i) + 6 + 1] = (uint8_t)0; /* transitionTime */ } - external_control_socket.udp_write((char*)message, (size * 7) + 1); + external_control_socket.udp_write((char*)message, ((int)size * 7) + 1); free(message); } @@ -205,14 +223,14 @@ void NanoleafController::UpdateLEDs(std::vector& colors) | 1 W White channel (ignored) | | 2 transitionTime Transition time (x 100ms) | \*---------------------------------------------------------*/ - uint8_t size = panel_ids.size(); + std::size_t size = panel_ids.size(); uint8_t* message = (uint8_t*)malloc((size * 8) + 2); message[0] = (uint8_t)(size >> 8); /* nPanels H */ message[1] = (uint8_t)(size & 0xFF); /* nPanels L */ - for(int i = 0; i < size; i++) + for(unsigned int i = 0; i < size; i++) { message[(8 * i) + 0 + 2] = (uint8_t)(panel_ids[i] >> 8); /* panelId H */ message[(8 * i) + 1 + 2] = (uint8_t)(panel_ids[i] & 0xFF); /* panelId L */ @@ -224,7 +242,7 @@ void NanoleafController::UpdateLEDs(std::vector& colors) message[(8 * i) + 7 + 2] = (uint8_t)0; /* transitionTime L */ } - external_control_socket.udp_write((char *)message, (size * 8) + 2); + external_control_socket.udp_write((char *)message, ((int)size * 8) + 2); free(message); } diff --git a/Controllers/NanoleafController/NanoleafController.h b/Controllers/NanoleafController/NanoleafController.h index 6e8fd91a..d7a47573 100644 --- a/Controllers/NanoleafController/NanoleafController.h +++ b/Controllers/NanoleafController/NanoleafController.h @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| NanoleafController.h | -| | -| API Interface for Nanoleaf devices | -| | -| Nikita Rushmanov 01/13/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| NanoleafController.h | +| | +| Driver for Nanoleaf | +| | +| Nikita Rushmanov 13 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/NanoleafController/NanoleafControllerDetect.cpp b/Controllers/NanoleafController/NanoleafControllerDetect.cpp index 5f7ae49f..7fc579a2 100644 --- a/Controllers/NanoleafController/NanoleafControllerDetect.cpp +++ b/Controllers/NanoleafController/NanoleafControllerDetect.cpp @@ -1,3 +1,14 @@ +/*---------------------------------------------------------*\ +| NanoleafControllerDetect.cpp | +| | +| Detector for Nanoleaf | +| | +| Nikita Rushmanov 13 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "RGBController_Nanoleaf.h" #include "SettingsManager.h" @@ -30,7 +41,7 @@ void DetectNanoleafControllers() } catch(...) { - LOG_DEBUG("[Nanoleaf] Could not connect to device at %s:%s using auth_token %s", device["ip"].get().c_str(), device["port"].get().c_str(), device["auth_token"].get().c_str()); + LOG_DEBUG("[Nanoleaf] Could not connect to device at %s:%d using auth_token %s", device["ip"].get().c_str(), device["port"].get(), device["auth_token"].get().c_str()); } } } diff --git a/Controllers/NanoleafController/RGBController_Nanoleaf.cpp b/Controllers/NanoleafController/RGBController_Nanoleaf.cpp index 98fd6ad6..de414183 100644 --- a/Controllers/NanoleafController/RGBController_Nanoleaf.cpp +++ b/Controllers/NanoleafController/RGBController_Nanoleaf.cpp @@ -1,15 +1,19 @@ -/*-----------------------------------------*\ -| RGBController_Nanoleaf.cpp | -| | -| Generic RGB Interface for Nanoleaf | -| | -| Nikita Rushmanov 01/13/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Nanoleaf.cpp | +| | +| RGBController for Nanoleaf | +| | +| Nikita Rushmanov 13 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_Nanoleaf.h" #include "ResourceManager.h" #include "LogManager.h" -#include "json.hpp" +#include + using json = nlohmann::json; /**------------------------------------------------------------------*\ @@ -76,7 +80,7 @@ RGBController_Nanoleaf::RGBController_Nanoleaf(std::string a_address, int a_port \*---------------------------------------------------------*/ if(controller.GetSelectedEffect() == effect.name) { - active_mode = modes.size() - 1; + active_mode = (int)modes.size() - 1; } } @@ -88,7 +92,7 @@ void RGBController_Nanoleaf::SetupZones() zone led_zone; led_zone.name = "Nanoleaf Layout"; led_zone.type = ZONE_TYPE_LINEAR; - led_zone.leds_count = controller.GetPanelIds().size(); + led_zone.leds_count = (unsigned int)controller.GetPanelIds().size(); led_zone.leds_min = led_zone.leds_count; led_zone.leds_max = led_zone.leds_count; led_zone.matrix_map = NULL; diff --git a/Controllers/NanoleafController/RGBController_Nanoleaf.h b/Controllers/NanoleafController/RGBController_Nanoleaf.h index 82133149..af317d08 100644 --- a/Controllers/NanoleafController/RGBController_Nanoleaf.h +++ b/Controllers/NanoleafController/RGBController_Nanoleaf.h @@ -1,12 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_Nanoleaf.h | -| | -| Generic RGB Interface for Nanoleaf | -| | -| Nikita Rushmanov 01/13/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Nanoleaf.h | +| | +| RGBController for Nanoleaf | +| | +| Nikita Rushmanov 13 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "NanoleafController.h" diff --git a/Controllers/NollieController/NollieController.cpp b/Controllers/NollieController/NollieController.cpp index 1a615768..b6a4184e 100644 --- a/Controllers/NollieController/NollieController.cpp +++ b/Controllers/NollieController/NollieController.cpp @@ -1,24 +1,27 @@ -/*-----------------------------------------*\ -| NollieController.cpp | -| | -| Driver for Nollie32 LED strip controller | -| | -| Name (cnn1236661) 25th Jun 2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| NollieController.cpp | +| | +| Driver for Nollie | +| | +| Name (cnn1236661) 25 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "NollieController.h" #include +#include "NollieController.h" +#include "StringUtils.h" using namespace std::chrono_literals; -NollieController::NollieController(hid_device* dev_handle, const char* path, unsigned short /*pid*/) +NollieController::NollieController(hid_device* dev_handle, const char* path, unsigned short vid, unsigned short pid, std::string dev_name) { dev = dev_handle; location = path; - /*-----------------------------------------------------*\ - | PID may be used in the future, here is to pass | - | arguments not to do storage | - \*-----------------------------------------------------*/ + name = dev_name; + usb_vid = vid; + usb_pid = pid; } std::string NollieController::GetLocationString() @@ -26,6 +29,11 @@ std::string NollieController::GetLocationString() return("HID: " + location); } +std::string NollieController::GetNameString() +{ + return(name); +} + std::string NollieController::GetSerialString() { wchar_t serial_string[128]; @@ -36,10 +44,31 @@ std::string NollieController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); + return(StringUtils::wstring_to_string(serial_string)); +} - return(return_string); +unsigned short NollieController::GetUSBPID() +{ + return(usb_pid); +} + +unsigned short NollieController::GetUSBVID() +{ + return(usb_vid); +} + +void NollieController::InitChLEDs(int *led_num_list,int ch_num) +{ + unsigned char usb_buf[65]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + usb_buf[1] = 0xFE; + usb_buf[2] = 0x03; + for(int i = 0; i < ch_num; i++) + { + usb_buf[3+(i*2)] = led_num_list[i]& 0xFF; + usb_buf[4+(i*2)] = (led_num_list[i] >> 8) & 0xFF; + } + hid_write(dev, usb_buf, 65); } void NollieController::SetMos(bool mos) @@ -53,32 +82,108 @@ void NollieController::SetMos(bool mos) void NollieController::SetChannelLEDs(unsigned char channel, RGBColor* colors, unsigned int num_colors) { - SendPacket(channel,&colors[0], num_colors); + if(usb_pid == NOLLIE32_PID || usb_pid == NOLLIE16_PID) + { + SendPacket(channel,&colors[0], num_colors); + } + else + { + unsigned int num_packets = (num_colors / 21) + ((num_colors % 21) > 0); + unsigned int color_idx = 0; + + for(unsigned int packet_idx = 0; packet_idx < num_packets; packet_idx++) + { + unsigned int colors_in_packet = 21; + if(num_colors - color_idx < colors_in_packet) + { + colors_in_packet = num_colors - color_idx; + } + SendPacketFS(channel,packet_idx,&colors[color_idx], colors_in_packet); + color_idx += colors_in_packet; + } + } +} + +void NollieController::SendUpdate() +{ + unsigned char usb_buf[65] ; + memset(usb_buf, 0x00, sizeof(usb_buf)); + usb_buf[1] = 0xff; + hid_write(dev, usb_buf, 65); } void NollieController::SendPacket(unsigned char channel,RGBColor* colors,unsigned int num_colors) { - unsigned char usb_buf[1025]; memset(usb_buf, 0x00, sizeof(usb_buf)); usb_buf[1] = channel; usb_buf[2] = 0; usb_buf[3] = num_colors / 256; usb_buf[4] = num_colors % 256; - if(!num_colors) + if(num_colors) { - hid_write(dev, usb_buf, 1025); - return; - } - for(unsigned int color_idx = 0; color_idx < num_colors; color_idx++) - { - usb_buf[0x05 + (color_idx * 3)] = RGBGetGValue(colors[color_idx]); - usb_buf[0x06 + (color_idx * 3)] = RGBGetRValue(colors[color_idx]); - usb_buf[0x07 + (color_idx * 3)] = RGBGetBValue(colors[color_idx]); + for(unsigned int color_idx = 0; color_idx < num_colors; color_idx++) + { + usb_buf[0x05 + (color_idx * 3)] = RGBGetGValue(colors[color_idx]); + usb_buf[0x06 + (color_idx * 3)] = RGBGetRValue(colors[color_idx]); + usb_buf[0x07 + (color_idx * 3)] = RGBGetBValue(colors[color_idx]); + } } + /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 1025); + if(channel == NOLLIE32_FLAG1_CHANNEL) + { + usb_buf[2] = 1; + hid_write(dev, usb_buf, 1025); + std::this_thread::sleep_for(std::chrono::milliseconds(8)); + } + else if(channel == NOLLIE32_FLAG2_CHANNEL) + { + usb_buf[2] = 2; + hid_write(dev, usb_buf, 1025); + std::this_thread::sleep_for(std::chrono::milliseconds(8)); + } + else + { + hid_write(dev, usb_buf, 1025); + } } +void NollieController::SendPacketFS(unsigned char channel,unsigned char packet_id,RGBColor* colors,unsigned int num_colors) +{ + unsigned char usb_buf[65]; + unsigned int packet_interval; + unsigned int dev_pid = GetUSBPID(); + switch(dev_pid) + { + case NOLLIE28_12_PID: + packet_interval = 2; + break; + case NOLLIE8_PID: + packet_interval = 6; + break; + case NOLLIE1_PID: + packet_interval = 30; + break; + default: + packet_interval = 25; + break; + } + memset(usb_buf, 0x00, sizeof(usb_buf)); + usb_buf[0x00] = 0x00; + usb_buf[0x01] = packet_id + channel * packet_interval; + for(unsigned int color_idx = 0; color_idx < num_colors; color_idx++) + { + usb_buf[0x02 + (color_idx * 3)] = RGBGetRValue(colors[color_idx]); + usb_buf[0x03 + (color_idx * 3)] = RGBGetGValue(colors[color_idx]); + usb_buf[0x04 + (color_idx * 3)] = RGBGetBValue(colors[color_idx]); + if(dev_pid == NOLLIE8_PID || dev_pid == NOLLIE1_PID ) + { + usb_buf[0x02 + (color_idx * 3)] = RGBGetGValue(colors[color_idx]); + usb_buf[0x03 + (color_idx * 3)] = RGBGetRValue(colors[color_idx]); + } + } + hid_write(dev, usb_buf, 65); +} diff --git a/Controllers/NollieController/NollieController.h b/Controllers/NollieController/NollieController.h index e46c159b..12149d97 100644 --- a/Controllers/NollieController/NollieController.h +++ b/Controllers/NollieController/NollieController.h @@ -1,28 +1,79 @@ -/*-----------------------------------------*\ -| RGBController.h | -| | -| Driver for Nollie32 LED strip controller | -| | -| Name (cnn1236661) 25th Jun 2023 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include -#include +/*---------------------------------------------------------*\ +| NollieController.h | +| | +| Driver for Nollie | +| | +| Name (cnn1236661) 25 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include +#include "RGBController.h" + +#define NOLLIE_12_CH_LED_NUM 42 +#define NOLLIE_8_CH_LED_NUM 126 +#define NOLLIE_1_CH_LED_NUM 630 +#define NOLLIE_HS_CH_LED_NUM 256 +#define NOLLIE_FS_CH_LED_NUM 525 + +#define NOLLIERGBOS_2_VID 0x16D5 + +#define NOLLIE32_CHANNELS_NUM 32 +#define NOLLIE32_PID 0x4714 +#define NOLLIE32_VID 0x3061 + +#define NOLLIE16_CHANNELS_NUM 16 +#define NOLLIE16_PID 0x4716 +#define NOLLIE16_VID 0x3061 + +#define NOLLIE8_CHANNELS_NUM 8 +#define NOLLIE8_PID 0x1F01 +#define NOLLIE8_VID 0x16D2 + +#define NOLLIE1_CHANNELS_NUM 1 +#define NOLLIE1_PID 0x1F11 +#define NOLLIE1_VID 0x16D2 + +#define NOLLIE28_12_CHANNELS_NUM 12 +#define NOLLIE28_12_VID 0x16D2 +#define NOLLIE28_12_PID 0x1616 +#define NOLLIE28_L1_PID 0x1617 +#define NOLLIE28_L2_PID 0x1618 + +#define NOLLIE32_MOS_TRIGGER_CH 26 +#define NOLLIE32_MOS_TRIGGER_LED 20 +#define NOLLIE32_FLAG1_CHANNEL 15 +#define NOLLIE32_FLAG2_CHANNEL 31 + class NollieController { public: - NollieController(hid_device* dev_handle, const char* path, unsigned short pid); + NollieController(hid_device* dev_handle, const char* path, unsigned short vid, unsigned short pid, std::string dev_name); + std::string GetLocationString(); + std::string GetNameString(); std::string GetSerialString(); + unsigned short GetUSBVID(); + unsigned short GetUSBPID(); + void SetMos(bool mos); + void InitChLEDs(int *led_num_list,int ch_num); + void SendUpdate(); void SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors); + private: hid_device* dev; std::string location; + std::string name; + unsigned short usb_vid; + unsigned short usb_pid; + void SendPacket(unsigned char channel,RGBColor * colors,unsigned int num_colors); + void SendPacketFS(unsigned char channel,unsigned char packet_id,RGBColor * colors,unsigned int num_colors); }; diff --git a/Controllers/NollieController/NollieControllerDetect.cpp b/Controllers/NollieController/NollieControllerDetect.cpp index bc563759..ac8e5ecc 100644 --- a/Controllers/NollieController/NollieControllerDetect.cpp +++ b/Controllers/NollieController/NollieControllerDetect.cpp @@ -1,18 +1,18 @@ -/*-----------------------------------------*\ -| NollieControllerDetect.cpp | -| | -| Driver for Nollie32 LED strip controller | -| | -| Name (cnn1236661) 25th Jun 2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| NollieControllerDetect.cpp | +| | +| Detector for Nollie | +| | +| Name (cnn1236661) 25 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include "Detector.h" #include "NollieController.h" -#include "RGBController.h" #include "RGBController_Nollie.h" -#include -#include - void DetectNollieControllers(hid_device_info* info, const std::string& name) { @@ -25,13 +25,23 @@ void DetectNollieControllers(hid_device_info* info, const std::string& name) std::wstring product_str(product); - NollieController* controller = new NollieController(dev, info->path,info->product_id); + NollieController* controller = new NollieController(dev, info->path, info->vendor_id, info->product_id, name); RGBController_Nollie* rgb_controller = new RGBController_Nollie(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } -REGISTER_HID_DETECTOR("Nollie 32CH", DetectNollieControllers, NOLLIE_32_VID, NOLLIE_32_PID); +REGISTER_HID_DETECTOR("Nollie 32CH", DetectNollieControllers, NOLLIE32_VID, NOLLIE32_PID); +REGISTER_HID_DETECTOR("Nollie 16CH", DetectNollieControllers, NOLLIE16_VID, NOLLIE16_PID); +REGISTER_HID_DETECTOR("Nollie 8CH", DetectNollieControllers, NOLLIE8_VID, NOLLIE8_PID); +REGISTER_HID_DETECTOR("Nollie 1CH", DetectNollieControllers, NOLLIE1_VID, NOLLIE1_PID); +REGISTER_HID_DETECTOR("Nollie 28 12", DetectNollieControllers, NOLLIE28_12_VID, NOLLIE28_12_PID); +REGISTER_HID_DETECTOR("Nollie 28 L1", DetectNollieControllers, NOLLIE28_12_VID, NOLLIE28_L1_PID); +REGISTER_HID_DETECTOR("Nollie 28 L2", DetectNollieControllers, NOLLIE28_12_VID, NOLLIE28_L2_PID); +//Nollie OS2 Firmware +REGISTER_HID_DETECTOR("Nollie 32_OS2", DetectNollieControllers, NOLLIERGBOS_2_VID, NOLLIE32_PID); +REGISTER_HID_DETECTOR("Nollie 16_OS2", DetectNollieControllers, NOLLIERGBOS_2_VID, NOLLIE16_PID); +REGISTER_HID_DETECTOR("Nollie 8_OS2", DetectNollieControllers, NOLLIERGBOS_2_VID, NOLLIE8_PID); +REGISTER_HID_DETECTOR("Nollie 1_OS2", DetectNollieControllers, NOLLIERGBOS_2_VID, NOLLIE1_PID); diff --git a/Controllers/NollieController/RGBController_Nollie.cpp b/Controllers/NollieController/RGBController_Nollie.cpp index 03c43ce9..61dcb44e 100644 --- a/Controllers/NollieController/RGBController_Nollie.cpp +++ b/Controllers/NollieController/RGBController_Nollie.cpp @@ -1,4 +1,19 @@ -/**------------------------------------------------------------------*\ +/*---------------------------------------------------------*\ +| RGBController_Nollie.cpp | +| | +| RGBController for Nollie | +| | +| Name (cnn1236661) 25 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "RGBController_Nollie.h" + +/**------------------------------------------------------------------*\ @name Nollie Controller @category LEDStrip @type USB @@ -9,28 +24,22 @@ @comment \*-------------------------------------------------------------------*/ -#include "RGBController_Nollie.h" -#include -#include - -int channel_index[32] = {5, 4, 3, 2, 1, 0, 15, 14, 26, 27, 28, 29, 30, 31, 8, 9, 19, 18, 17, 16, 7, 6, 25, 24, 23, 22, 21, 20, 13, 12, 11, 10}; - RGBController_Nollie::RGBController_Nollie(NollieController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Nollie Device"; - vendor = "Nollie"; - description = "Nollie Controller Device"; - type = DEVICE_TYPE_LEDSTRIP; - location = controller->GetLocationString(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "Nollie"; + description = "Nollie Controller Device"; + type = DEVICE_TYPE_LEDSTRIP; + location = controller->GetLocationString(); + serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0xFFFF; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); SetupZones(); @@ -44,14 +53,47 @@ RGBController_Nollie::~RGBController_Nollie() void RGBController_Nollie::SetupZones() { bool first_run = false; + unsigned int channels_num = 0; + unsigned int ch_led_num = 0; if(zones.size() == 0) { first_run = true; } leds.clear(); colors.clear(); - zones.resize(NOLLIE_CHANNELS_NUM); - for(unsigned int channel_idx = 0; channel_idx < NOLLIE_CHANNELS_NUM; channel_idx++) + switch(controller->GetUSBPID()) + { + case NOLLIE32_PID: + channels_num = NOLLIE32_CHANNELS_NUM; + ch_led_num = NOLLIE_HS_CH_LED_NUM; + channel_index = ch32; + break; + case NOLLIE16_PID: + channels_num = NOLLIE16_CHANNELS_NUM; + ch_led_num = NOLLIE_HS_CH_LED_NUM; + channel_index = ch16; + if (controller->GetUSBVID() == NOLLIERGBOS_2_VID) + channel_index = n16; + break; + case NOLLIE28_12_PID: + channels_num = NOLLIE28_12_CHANNELS_NUM; + ch_led_num = NOLLIE_12_CH_LED_NUM; + break; + case NOLLIE8_PID: + channels_num = NOLLIE8_CHANNELS_NUM; + ch_led_num = NOLLIE_8_CH_LED_NUM; + break; + case NOLLIE1_PID: + channels_num = NOLLIE1_CHANNELS_NUM; + ch_led_num = NOLLIE_1_CH_LED_NUM; + break; + default: + channels_num = NOLLIE8_CHANNELS_NUM; + ch_led_num = NOLLIE_FS_CH_LED_NUM; + break; + } + zones.resize(channels_num); + for(unsigned int channel_idx = 0; channel_idx < channels_num; channel_idx++) { if(channel_idx > 27 ) { @@ -83,7 +125,7 @@ void RGBController_Nollie::SetupZones() } zones[channel_idx].type = ZONE_TYPE_LINEAR; zones[channel_idx].leds_min = 0; - zones[channel_idx].leds_max = NOLLIE_CHANNELS_LED_NUM; + zones[channel_idx].leds_max = ch_led_num; if(first_run) { @@ -112,15 +154,26 @@ void RGBController_Nollie::SetupZones() void RGBController_Nollie::ResizeZone(int zone, int new_size) { /*-----------------------------------------------------*\ - | Set whether MOS is enabled or not | + | Set whether MOS is enabled or not | \*-----------------------------------------------------*/ - if(zone == 26 && new_size >20) + if(controller->GetUSBVID() == NOLLIE32_VID && NOLLIE32_PID == controller->GetUSBPID()) { - controller->SetMos(false); + if(zone == NOLLIE32_MOS_TRIGGER_CH && new_size > NOLLIE32_MOS_TRIGGER_LED) + { + controller->SetMos(false); + } + else if(zone == NOLLIE32_MOS_TRIGGER_CH) + { + controller->SetMos(true); + } } - else if(zone == 26) + + /*-----------------------------------------------------*\ + | Nollie1 needs to report the number of LEDs | + \*-----------------------------------------------------*/ + if(controller->GetUSBVID() == NOLLIE1_VID && controller->GetUSBPID() == NOLLIE1_PID) { - controller->SetMos(true); + controller->InitChLEDs(&new_size,NOLLIE1_CHANNELS_NUM); } if((size_t) zone >= zones.size()) @@ -138,26 +191,42 @@ void RGBController_Nollie::ResizeZone(int zone, int new_size) void RGBController_Nollie::DeviceUpdateLEDs() { - std::vector ChSort; - for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + unsigned int DevPid = controller->GetUSBPID(); + if(DevPid == NOLLIE32_PID || DevPid == NOLLIE16_PID) { - unsigned int channel = channel_index[zone_idx]; - if(zones[zone_idx].leds_count > 0) + std::vector ChSort; + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) { - ChSort.push_back(channel); + unsigned int channel = channel_index[zone_idx]; + if(zones[zone_idx].leds_count > 0) + { + ChSort.push_back(channel); + } + else if(channel == NOLLIE32_FLAG1_CHANNEL || channel == NOLLIE32_FLAG2_CHANNEL) + { + ChSort.push_back(channel); + } } - else if(channel == 15 || channel == 31) + std::sort(ChSort.begin(), ChSort.end()); + for(std::size_t i = 0; i < ChSort.size(); i++) { - ChSort.push_back(channel); + int* ptr = std::find(channel_index, channel_index + 32, ChSort[i]); + int zone_idx = (int)(ptr - channel_index); + controller->SetChannelLEDs(ChSort[i], zones[zone_idx].colors, zones[zone_idx].leds_count); } } - std::sort(ChSort.begin(), ChSort.end()); - for (std::size_t i = 0; i < ChSort.size(); i++) + else { - int* ptr = std::find(channel_index, channel_index + 32, ChSort[i]); - int zone_idx = ptr - channel_index; - controller->SetChannelLEDs(ChSort[i], zones[zone_idx].colors, zones[zone_idx].leds_count); + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + if(zones[zone_idx].leds_count > 0) + { + controller->SetChannelLEDs((unsigned char)zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); + } + } + controller->SendUpdate(); } + } void RGBController_Nollie::UpdateZoneLEDs(int zone) @@ -168,7 +237,6 @@ void RGBController_Nollie::UpdateZoneLEDs(int zone) void RGBController_Nollie::UpdateSingleLED(int led) { unsigned int channel = leds_channel[led]; - controller->SetChannelLEDs(channel_index[channel], zones[channel].colors, zones[channel].leds_count); } diff --git a/Controllers/NollieController/RGBController_Nollie.h b/Controllers/NollieController/RGBController_Nollie.h index d2f30387..5fbafa7a 100644 --- a/Controllers/NollieController/RGBController_Nollie.h +++ b/Controllers/NollieController/RGBController_Nollie.h @@ -1,21 +1,19 @@ -/*-----------------------------------------*\ -| RGBController_Nollie.h | -| | -| Driver for Nollie32 LED strip controller | -| | -| Name (cnn1236661) 25th Jun 2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Nollie.h | +| | +| RGBController for Nollie | +| | +| Name (cnn1236661) 25 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once #include "RGBController.h" #include "NollieController.h" -#define NOLLIE_CHANNELS_LED_NUM 256 -#define NOLLIE_CHANNELS_NUM 32 -#define NOLLIE_32_PID 0x4714 -#define NOLLIE_32_VID 0x3061 - class RGBController_Nollie : public RGBController { public: @@ -35,4 +33,10 @@ private: NollieController* controller; std::vector leds_channel; std::vector zones_channel; + + int* channel_index; + + int ch32[32] = {5, 4, 3, 2, 1, 0, 15, 14, 26, 27, 28, 29, 30, 31, 8, 9, 19, 18, 17, 16, 7, 6, 25, 24, 23, 22, 21, 20, 13, 12, 11, 10}; + int ch16[32] = {19, 18, 17, 16, 24, 25, 26, 27, 20, 21, 22, 23, 31, 30, 29, 28, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; + int n16[16] = {3, 2, 1, 0, 8, 9, 10, 11, 4, 5, 6, 7, 15, 14, 13, 12}; }; diff --git a/Controllers/NvidiaESAController/NvidiaESAController.cpp b/Controllers/NvidiaESAController/NvidiaESAController.cpp index d879699d..46d1129c 100644 --- a/Controllers/NvidiaESAController/NvidiaESAController.cpp +++ b/Controllers/NvidiaESAController/NvidiaESAController.cpp @@ -1,33 +1,23 @@ -/*-----------------------------------------*\ -| NvidiaESAController.cpp | -| | -| Driver for Nvidia ESA lighting | -| controller | -| | -| Guimard Morgan (morg) 2/18/2022 | -\*-----------------------------------------*/ -#include "NvidiaESAController.h" +/*---------------------------------------------------------*\ +| NvidiaESAController.cpp | +| | +| Driver for NVIDIA ESA | +| | +| Morgan Guimard (morg) 18 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include +#include "NvidiaESAController.h" +#include "StringUtils.h" -NvidiaESAController::NvidiaESAController(hid_device* dev_handle, const hid_device_info& info) +NvidiaESAController::NvidiaESAController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) { - dev = dev_handle; - location = info.path; - version = ""; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } - + dev = dev_handle; + location = info.path; + name = dev_name; } NvidiaESAController::~NvidiaESAController() @@ -40,21 +30,29 @@ std::string NvidiaESAController::GetDeviceLocation() return("HID: " + location); } -std::string NvidiaESAController::GetSerialString() +std::string NvidiaESAController::GetNameString() { - return(serial_number); + return(name); } -std::string NvidiaESAController::GetFirmwareVersion() +std::string NvidiaESAController::GetSerialString() { - return(version); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } void NvidiaESAController::SetZoneColor(unsigned int zone_idx, RGBColor color) { - unsigned char red = 0x0F - 0x0F * RGBGetRValue(color) / 255.0; - unsigned char grn = 0x0F - 0x0F * RGBGetGValue(color) / 255.0; - unsigned char blu = 0x0F - 0x0F * RGBGetBValue(color) / 255.0; + unsigned char red = (unsigned char)(0x0F - 0x0F * RGBGetRValue(color) / 255.0f); + unsigned char grn = (unsigned char)(0x0F - 0x0F * RGBGetGValue(color) / 255.0f); + unsigned char blu = (unsigned char)(0x0F - 0x0F * RGBGetBValue(color) / 255.0f); unsigned char usb_buf[4]; diff --git a/Controllers/NvidiaESAController/NvidiaESAController.h b/Controllers/NvidiaESAController/NvidiaESAController.h index 73f45619..1be886fa 100644 --- a/Controllers/NvidiaESAController/NvidiaESAController.h +++ b/Controllers/NvidiaESAController/NvidiaESAController.h @@ -1,27 +1,29 @@ -/*-----------------------------------------*\ -| NvidiaESAController.h | -| | -| Driver for Nvidia ESA lighting | -| controller - header file | -| | -| Guimard Morgan (morg) 2/18/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| NvidiaESAController.h | +| | +| Driver for NVIDIA ESA | +| | +| Morgan Guimard (morg) 18 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once -#include "RGBController.h" #include -#include - +#include +#include "RGBController.h" class NvidiaESAController { public: - NvidiaESAController(hid_device* dev_handle, const hid_device_info& info); + NvidiaESAController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); ~NvidiaESAController(); - std::string GetSerialString(); std::string GetDeviceLocation(); - std::string GetFirmwareVersion(); + std::string GetNameString(); + std::string GetSerialString(); void SetZoneColor(unsigned int zone_idx, RGBColor color); @@ -30,6 +32,5 @@ protected: private: std::string location; - std::string serial_number; - std::string version; + std::string name; }; diff --git a/Controllers/NvidiaESAController/NvidiaESAControllerDetect.cpp b/Controllers/NvidiaESAController/NvidiaESAControllerDetect.cpp index edc36b41..38699636 100644 --- a/Controllers/NvidiaESAController/NvidiaESAControllerDetect.cpp +++ b/Controllers/NvidiaESAController/NvidiaESAControllerDetect.cpp @@ -1,6 +1,16 @@ +/*---------------------------------------------------------*\ +| NvidiaESAControllerDetect.cpp | +| | +| Detector for NVIDIA ESA | +| | +| Morgan Guimard (morg) 18 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "NvidiaESAController.h" -#include "RGBController.h" #include "RGBController_NvidiaESA.h" /*---------------------------------------------------------*\ @@ -19,9 +29,9 @@ void DetectNvidiaESAControllers(hid_device_info* info, const std::string& name) if(dev) { - NvidiaESAController* controller = new NvidiaESAController(dev, *info); + NvidiaESAController* controller = new NvidiaESAController(dev, *info, name); RGBController_NvidiaESA* rgb_controller = new RGBController_NvidiaESA(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } diff --git a/Controllers/NvidiaESAController/RGBController_NvidiaESA.cpp b/Controllers/NvidiaESAController/RGBController_NvidiaESA.cpp index 48efeb98..f7cb0fdf 100644 --- a/Controllers/NvidiaESAController/RGBController_NvidiaESA.cpp +++ b/Controllers/NvidiaESAController/RGBController_NvidiaESA.cpp @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| RGBController_NvidiaESA.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Nvidia ESA USB Driver | -| | -| Guimard Morgan (morg) 2/18/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_NvidiaESA.cpp | +| | +| RGBController for NVIDIA ESA | +| | +| Morgan Guimard (morg) 18 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include +#include #include "RGBController_NvidiaESA.h" -#include -#include - /**------------------------------------------------------------------*\ - @name NVidia ESA + @name Nvidia ESA @category Case @type USB @save :x: @@ -26,13 +27,13 @@ RGBController_NvidiaESA::RGBController_NvidiaESA(NvidiaESAController* controller_ptr) { controller = controller_ptr; - name = "Nvidia ESA USB Device"; + + name = controller->GetNameString(); vendor = "NVIDIA"; type = DEVICE_TYPE_CASE; - description = name; + description = "Nvidia ESA USB Device";; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); mode Static; Static.name = "Static"; diff --git a/Controllers/NvidiaESAController/RGBController_NvidiaESA.h b/Controllers/NvidiaESAController/RGBController_NvidiaESA.h index 1fd8d8d7..c490b407 100644 --- a/Controllers/NvidiaESAController/RGBController_NvidiaESA.h +++ b/Controllers/NvidiaESAController/RGBController_NvidiaESA.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_NvidiaESA.h | -| | -| Generic RGB Interface for OpenRGB | -| Nvidia ESA RGB USB Driver | -| | -| Guimard Morgan (morg) 2/18/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_NvidiaESA.h | +| | +| RGBController for NVIDIA ESA | +| | +| Morgan Guimard (morg) 18 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/OKSController/OKSKeyboardController.cpp b/Controllers/OKSController/OKSKeyboardController.cpp index f5819bb2..b6c9d541 100644 --- a/Controllers/OKSController/OKSKeyboardController.cpp +++ b/Controllers/OKSController/OKSKeyboardController.cpp @@ -1,19 +1,23 @@ -/*-----------------------------------------*\ -| OKSKeyboardController.cpp | -| | -| Driver for OKS RGB keyboardlighting | -| controller | -| | -| Merafour (OKS) 2/24/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| OKSKeyboardController.cpp | +| | +| Driver for OKS keyboard | +| | +| Merafour (OKS) 24 Feb 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include #include "OKSKeyboardController.h" +#include "StringUtils.h" -OKSKeyboardController::OKSKeyboardController(hid_device* dev_handle, const char* path, const unsigned short pid) +OKSKeyboardController::OKSKeyboardController(hid_device* dev_handle, const char* path, const unsigned short pid, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; usb_pid = pid; SendInitialize(); @@ -29,6 +33,11 @@ std::string OKSKeyboardController::GetDeviceLocation() return("HID: " + location); } +std::string OKSKeyboardController::GetNameString() +{ + return(name); +} + std::string OKSKeyboardController::GetSerialString() { wchar_t serial_string[128]; @@ -39,10 +48,7 @@ std::string OKSKeyboardController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } unsigned short OKSKeyboardController::GetUSBPID() diff --git a/Controllers/OKSController/OKSKeyboardController.h b/Controllers/OKSController/OKSKeyboardController.h index b701790b..5a24ba7f 100644 --- a/Controllers/OKSController/OKSKeyboardController.h +++ b/Controllers/OKSController/OKSKeyboardController.h @@ -1,37 +1,38 @@ -/*-----------------------------------------*\ -| OKSKeyboardController.h | -| | -| Definitions and types for OKS RGB | -| keyboard lighting controller | -| | -| Merafour (OKS) 2/24/2023 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include -#include +/*---------------------------------------------------------*\ +| OKSKeyboardController.h | +| | +| Driver for OKS keyboard | +| | +| Merafour (OKS) 24 Feb 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include +#include "RGBController.h" + /*-----------------------------------------------------*\ -| OKS vendor ID | +| OKS vendor ID | \*-----------------------------------------------------*/ -#define OKS_VID 0x1C4F +#define OKS_VID 0x1C4F /*-----------------------------------------------------*\ | Keyboard product IDs | \*-----------------------------------------------------*/ -#define OKS_OPTICAL_RGB_PID 0xEE88 +#define OKS_OPTICAL_RGB_PID 0xEE88 /*-----------------------------------------------------*\ -| communication protocol | +| Communication protocol | \*-----------------------------------------------------*/ -#define KB2_PACK_HEAD (0x5C&0xFF) -#define KB2_HEAD_SIZE 4 -#define KB2_PORT_SIZE (64*4) -#define KB2_DATA_SIZE (KB2_PORT_SIZE-KB2_HEAD_SIZE) +#define KB2_PACK_HEAD (0x5C&0xFF) +#define KB2_HEAD_SIZE 4 +#define KB2_PORT_SIZE (64*4) +#define KB2_DATA_SIZE (KB2_PORT_SIZE-KB2_HEAD_SIZE) union kb2_port_t { uint8_t bin[KB2_PORT_SIZE]; @@ -66,27 +67,28 @@ union uint32_kb2 class OKSKeyboardController { public: - OKSKeyboardController(hid_device* dev_handle, const char* path, const unsigned short pid); + OKSKeyboardController(hid_device* dev_handle, const char* path, const unsigned short pid, std::string dev_name); ~OKSKeyboardController(); std::string GetDeviceLocation(); + std::string GetNameString(); std::string GetSerialString(); unsigned short GetUSBPID(); - - void SendColors(unsigned char* color_data, unsigned int color_data_size); - void SendKeyboardModeEx(const mode &m, unsigned char red, unsigned char green, unsigned char blue); + void SendColors(unsigned char* color_data, unsigned int color_data_size); + void SendKeyboardModeEx(const mode &m, unsigned char red, unsigned char green, unsigned char blue); private: - hid_device* dev; - std::string location; - unsigned short usb_pid; + hid_device* dev; + std::string location; + std::string name; + unsigned short usb_pid; - void Send(const uint8_t bin[64], const uint16_t len); - void SendInitialize(); - uint8_t kb2_ComputeChecksum(const union kb2_port_t* const Pack); - int kb2_add_32b(union kb2_port_t* const Pack, const uint32_t value); - void kb2M_init(union kb2_port_t* const Pack, const enum kb2_cmd cmd); - void kb2M_wrgb(union kb2_port_t* const Pack, const uint8_t bright, const uint8_t mode, const uint8_t speed, const uint8_t dir); - void kb2M_wled(union kb2_port_t* const Pack, const uint32_t irgb[14]); + void Send(const uint8_t bin[64], const uint16_t len); + void SendInitialize(); + uint8_t kb2_ComputeChecksum(const union kb2_port_t* const Pack); + int kb2_add_32b(union kb2_port_t* const Pack, const uint32_t value); + void kb2M_init(union kb2_port_t* const Pack, const enum kb2_cmd cmd); + void kb2M_wrgb(union kb2_port_t* const Pack, const uint8_t bright, const uint8_t mode, const uint8_t speed, const uint8_t dir); + void kb2M_wled(union kb2_port_t* const Pack, const uint32_t irgb[14]); }; diff --git a/Controllers/OKSController/OKSKeyboardControllerDetect.cpp b/Controllers/OKSController/OKSKeyboardControllerDetect.cpp index c5870bfd..9a77f0ee 100644 --- a/Controllers/OKSController/OKSKeyboardControllerDetect.cpp +++ b/Controllers/OKSController/OKSKeyboardControllerDetect.cpp @@ -1,10 +1,20 @@ +/*---------------------------------------------------------*\ +| OKSKeyboardControllerDetect.cpp | +| | +| Detector for OKS keyboard | +| | +| Merafour (OKS) 24 Feb 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "OKSKeyboardController.h" -#include "RGBController.h" #include "RGBController_OKSKeyboard.h" -#include + /******************************************************************************************\ -* * * DetectOKSKeyboardControllers * * Reference: DuckyKeyboardController * * Tests the USB address to see if a OKS Optical Axis RGB Keyboard controller exists there.* @@ -17,9 +27,9 @@ void DetectOKSKeyboardControllers(hid_device_info* info, const std::string& name if(dev) { - OKSKeyboardController* controller = new OKSKeyboardController(dev, info->path, info->product_id); + OKSKeyboardController* controller = new OKSKeyboardController(dev, info->path, info->product_id, name); RGBController_OKSKeyboard* rgb_controller = new RGBController_OKSKeyboard(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } /* DetectOKSKeyboardControllers() */ diff --git a/Controllers/OKSController/RGBController_OKSKeyboard.cpp b/Controllers/OKSController/RGBController_OKSKeyboard.cpp index 844b894a..f9c7c4be 100644 --- a/Controllers/OKSController/RGBController_OKSKeyboard.cpp +++ b/Controllers/OKSController/RGBController_OKSKeyboard.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_OKSKeyboard.cpp | -| | -| Generic RGB Interface for OKS RGB | -| keyboard devices | -| | -| Merafour (OKS) 2/24/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_OKSKeyboard.cpp | +| | +| RGBController for OKS keyboard | +| | +| Merafour (OKS) 24 Feb 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_OKSKeyboard.h" @@ -107,47 +109,46 @@ enum RGBController_OKSKeyboard::RGBController_OKSKeyboard(OKSKeyboardController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - - name = "OKS Keyboard Device"; - vendor = "OKS"; - type = DEVICE_TYPE_KEYBOARD; - description = "OKS Keyboard Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "OKS"; + type = DEVICE_TYPE_KEYBOARD; + description = "OKS Keyboard Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = UP_RGB_MODES_DIRECT; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS ; - Direct.brightness_min = 0; - Direct.brightness_max = 5; - Direct.brightness = 2; - Direct.color_mode = MODE_COLORS_PER_LED; - Direct.speed_min = OKS_SPEED_FASTEST; - Direct.speed_max = OKS_SPEED_SLOWEST; - Direct.speed = OKS_SPEED_NORMAL; - Direct.direction = MODE_DIRECTION_RIGHT; + Direct.name = "Direct"; + Direct.value = UP_RGB_MODES_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS ; + Direct.brightness_min = 0; + Direct.brightness_max = 5; + Direct.brightness = 2; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.speed_min = OKS_SPEED_FASTEST; + Direct.speed_max = OKS_SPEED_SLOWEST; + Direct.speed = OKS_SPEED_NORMAL; + Direct.direction = MODE_DIRECTION_RIGHT; modes.push_back(Direct); mode udef = Direct; - udef.name = "User mode1"; - udef.value = UP_RGB_MODES_UDEF1; - udef.direction = MODE_DIRECTION_LEFT; - udef.speed = 0; + udef.name = "User mode1"; + udef.value = UP_RGB_MODES_UDEF1; + udef.direction = MODE_DIRECTION_LEFT; + udef.speed = 0; modes.push_back(udef); - udef.name = "User mode2"; - udef.value = UP_RGB_MODES_UDEF2; + udef.name = "User mode2"; + udef.value = UP_RGB_MODES_UDEF2; modes.push_back(udef); - udef.name = "User mode3"; - udef.value = UP_RGB_MODES_UDEF3; + udef.name = "User mode3"; + udef.value = UP_RGB_MODES_UDEF3; modes.push_back(udef); - udef.name = "User mode4"; - udef.value = UP_RGB_MODES_UDEF4; + udef.name = "User mode4"; + udef.value = UP_RGB_MODES_UDEF4; modes.push_back(udef); - udef.name = "User mode5"; - udef.value = UP_RGB_MODES_UDEF5; + udef.name = "User mode5"; + udef.value = UP_RGB_MODES_UDEF5; modes.push_back(udef); /*---------------------------------------------------------*\ | Delete the "Horse race lamp","Breathing"... mode | @@ -258,15 +259,15 @@ void RGBController_OKSKeyboard::DeviceUpdateLEDs() \*---------------------------------------------------------*/ for(std::size_t color_idx = 0; color_idx < colors.size(); color_idx++) { - row_idx = color_idx/width; - col_idx = color_idx%width; + row_idx = (unsigned int)(color_idx) / width; + col_idx = (unsigned int)(color_idx) % width; kb_idx = row_idx*21+col_idx; colordata[(kb_idx*3)+0] = RGBGetRValue(colors[color_idx]); colordata[(kb_idx*3)+1] = RGBGetGValue(colors[color_idx]); colordata[(kb_idx*3)+2] = RGBGetBValue(colors[color_idx]); } - controller->SendColors(colordata, colors.size()*3); + controller->SendColors(colordata, (unsigned int)colors.size() * 3); } void RGBController_OKSKeyboard::UpdateZoneLEDs(int /*zone*/) @@ -279,11 +280,6 @@ void RGBController_OKSKeyboard::UpdateSingleLED(int led) UpdateZoneLEDs(led); } -void RGBController_OKSKeyboard::SetCustomMode() -{ - active_mode = 0; -} - void RGBController_OKSKeyboard::DeviceUpdateMode() { mode m = modes[active_mode]; diff --git a/Controllers/OKSController/RGBController_OKSKeyboard.h b/Controllers/OKSController/RGBController_OKSKeyboard.h index 71560c0a..2733b58a 100644 --- a/Controllers/OKSController/RGBController_OKSKeyboard.h +++ b/Controllers/OKSController/RGBController_OKSKeyboard.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_OKSKeyboard.h | -| | -| Generic RGB Interface for OKS RGB | -| keyboard devices | -| | -| Merafour (OKS) 2/24/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_OKSKeyboard.h | +| | +| RGBController for OKS keyboard | +| | +| Merafour (OKS) 24 Feb 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "OKSKeyboardController.h" @@ -58,12 +61,11 @@ public: void SetupZones(); void ResizeZone(int zone, int new_size); - + void DeviceUpdateLEDs(); void UpdateZoneLEDs(int zone); void UpdateSingleLED(int led); - void SetCustomMode(); void DeviceUpdateMode(); private: diff --git a/Controllers/OpenRazerController/OpenRazerDetect.cpp b/Controllers/OpenRazerController/OpenRazerDetect.cpp deleted file mode 100644 index 9c02f1af..00000000 --- a/Controllers/OpenRazerController/OpenRazerDetect.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include "Detector.h" -#include "LogManager.h" -#include "RGBController.h" -#include "RGBController_OpenRazer.h" -#include -#include -#include - -#include -#include -#include -#include - -/******************************************************************************************\ -* * -* DetectOpenRazerControllers * -* * -* Detect devices supported by the OpenRazer kernel drivers * -* * -\******************************************************************************************/ - -void DetectOpenRazerControllers() -{ - char driver_path[512]; - DIR *dir; - struct dirent *ent; - bool done = false; - int driver_to_read = 0; - - while(driver_to_read < 8) - { - switch(driver_to_read) - { - case 0: - strcpy(driver_path, "/sys/bus/hid/drivers/razerkbd/"); - break; - - case 1: - strcpy(driver_path, "/sys/bus/hid/drivers/razermouse/"); - break; - - case 2: - strcpy(driver_path, "/sys/bus/hid/drivers/razerfirefly/"); - break; - - case 3: - strcpy(driver_path, "/sys/bus/hid/drivers/razermug/"); - break; - - case 4: - strcpy(driver_path, "/sys/bus/hid/drivers/razercore/"); - break; - - case 5: - strcpy(driver_path, "/sys/bus/hid/drivers/razerkraken/"); - break; - - case 6: - strcpy(driver_path, "/sys/bus/hid/drivers/razermousemat/"); - break; - - case 7: - strcpy(driver_path, "/sys/bus/hid/drivers/razeraccessory/"); - break; - } - - done = false; - - dir = opendir(driver_path); - - LOG_DEBUG("[OpenRazer] Folder %s is %s", driver_path, (dir == NULL)?"not found":"found look for driver..." ); - - if(dir == NULL) - { - driver_to_read++; - continue; - } - - ent = readdir(dir); - - while(ent != NULL) - { - if(ent->d_type == DT_DIR || ent->d_type == DT_LNK) - { - if(!strcmp(ent->d_name, ".")) - { - if(done == false) - { - done = true; - } - else - { - break; - } - } - else if(!strcmp(ent->d_name, "..") || !strcmp(ent->d_name, "module")) - { - } - else - { - char device_string[1024]; - strcpy(device_string, driver_path); - strcat(device_string, ent->d_name); - - RGBController_OpenRazer * razer_rgb = new RGBController_OpenRazer(device_string); - - if(razer_rgb->device_index != -1) - { - ResourceManager::get()->RegisterRGBController(razer_rgb); - } - else - { - LOG_DEBUG("[OpenRazer] Device index is not -1 delete controller"); - delete razer_rgb; - } - - } - } - - ent = readdir(dir); - } - - closedir(dir); - - driver_to_read++; - } - -} /* DetectOpenRazerControllers() */ - -REGISTER_DETECTOR("OpenRazer", DetectOpenRazerControllers); diff --git a/Controllers/OpenRazerController/OpenRazerDevices.h b/Controllers/OpenRazerController/OpenRazerDevices.h deleted file mode 100644 index 713c6585..00000000 --- a/Controllers/OpenRazerController/OpenRazerDevices.h +++ /dev/null @@ -1,4922 +0,0 @@ -#define RAZER_MAX_ZONES 6 - -#include -#include "RGBController.h" -#include "RGBControllerKeyNames.h" - -typedef struct -{ - std::string name; - unsigned int type; - unsigned int rows; - unsigned int cols; -} razer_zone; - -typedef struct -{ - unsigned int zone; - unsigned int row; - unsigned int col; - const char* name; -} razer_key; - -typedef struct -{ - std::string name; - device_type type; - bool matrix_type; - unsigned int rows; - unsigned int cols; - const razer_zone* zones[RAZER_MAX_ZONES]; - const razer_key* keymap; - unsigned int keymap_size; -} razer_device; - -/*-------------------------------------------------------------------------*\ -| KEYMAPS | -\*-------------------------------------------------------------------------*/ -#define BLACKWIDOW_CHROMA_KEYMAP_SIZE (sizeof(blackwidow_chroma_keymap) / sizeof(blackwidow_chroma_keymap[0])) - -static const razer_key blackwidow_chroma_keymap[] = -{ - /*---------------------------------------------------------------------*\ - | Zone, Row, Column, Key | - \*---------------------------------------------------------------------*/ - { 0, 0, 1, KEY_EN_ESCAPE }, - { 0, 0, 3, KEY_EN_F1 }, - { 0, 0, 4, KEY_EN_F2 }, - { 0, 0, 5, KEY_EN_F3 }, - { 0, 0, 6, KEY_EN_F4 }, - { 0, 0, 7, KEY_EN_F5 }, - { 0, 0, 8, KEY_EN_F6 }, - { 0, 0, 9, KEY_EN_F7 }, - { 0, 0, 10, KEY_EN_F8 }, - { 0, 0, 11, KEY_EN_F9 }, - { 0, 0, 12, KEY_EN_F10 }, - { 0, 0, 13, KEY_EN_F11 }, - { 0, 0, 14, KEY_EN_F12 }, - { 0, 0, 15, KEY_EN_PRINT_SCREEN }, - { 0, 0, 16, KEY_EN_SCROLL_LOCK }, - { 0, 0, 17, KEY_EN_PAUSE_BREAK }, - { 0, 0, 20, "Logo" }, - { 0, 1, 0, "Key: M1" }, - { 0, 1, 1, KEY_EN_BACK_TICK }, - { 0, 1, 2, KEY_EN_1 }, - { 0, 1, 3, KEY_EN_2 }, - { 0, 1, 4, KEY_EN_3 }, - { 0, 1, 5, KEY_EN_4 }, - { 0, 1, 6, KEY_EN_5 }, - { 0, 1, 7, KEY_EN_6 }, - { 0, 1, 8, KEY_EN_7 }, - { 0, 1, 9, KEY_EN_8 }, - { 0, 1, 10, KEY_EN_9 }, - { 0, 1, 11, KEY_EN_0 }, - { 0, 1, 12, KEY_EN_MINUS }, - { 0, 1, 13, KEY_EN_EQUALS }, - { 0, 1, 14, KEY_EN_BACKSPACE }, - { 0, 1, 15, KEY_EN_INSERT }, - { 0, 1, 16, KEY_EN_HOME }, - { 0, 1, 17, KEY_EN_PAGE_UP }, - { 0, 1, 18, KEY_EN_NUMPAD_LOCK }, - { 0, 1, 19, KEY_EN_NUMPAD_DIVIDE }, - { 0, 1, 20, KEY_EN_NUMPAD_TIMES }, - { 0, 1, 21, KEY_EN_NUMPAD_MINUS }, - { 0, 2, 0, "Key: M2" }, - { 0, 2, 1, KEY_EN_TAB }, - { 0, 2, 2, KEY_EN_Q }, - { 0, 2, 3, KEY_EN_W }, - { 0, 2, 4, KEY_EN_E }, - { 0, 2, 5, KEY_EN_R }, - { 0, 2, 6, KEY_EN_T }, - { 0, 2, 7, KEY_EN_Y }, - { 0, 2, 8, KEY_EN_U }, - { 0, 2, 9, KEY_EN_I }, - { 0, 2, 10, KEY_EN_O }, - { 0, 2, 11, KEY_EN_P }, - { 0, 2, 12, KEY_EN_LEFT_BRACKET }, - { 0, 2, 13, KEY_EN_RIGHT_BRACKET }, - { 0, 2, 14, KEY_EN_ANSI_BACK_SLASH }, - { 0, 2, 15, KEY_EN_DELETE }, - { 0, 2, 16, KEY_EN_END }, - { 0, 2, 17, KEY_EN_PAGE_DOWN }, - { 0, 2, 18, KEY_EN_NUMPAD_7 }, - { 0, 2, 19, KEY_EN_NUMPAD_8 }, - { 0, 2, 20, KEY_EN_NUMPAD_9 }, - { 0, 2, 21, KEY_EN_NUMPAD_PLUS }, - { 0, 3, 0, "Key: M3" }, - { 0, 3, 1, KEY_EN_CAPS_LOCK }, - { 0, 3, 2, KEY_EN_A }, - { 0, 3, 3, KEY_EN_S }, - { 0, 3, 4, KEY_EN_D }, - { 0, 3, 5, KEY_EN_F }, - { 0, 3, 6, KEY_EN_G }, - { 0, 3, 7, KEY_EN_H }, - { 0, 3, 8, KEY_EN_J }, - { 0, 3, 9, KEY_EN_K }, - { 0, 3, 10, KEY_EN_L }, - { 0, 3, 11, KEY_EN_SEMICOLON }, - { 0, 3, 12, KEY_EN_QUOTE }, - { 0, 3, 13, KEY_EN_POUND }, - { 0, 3, 14, KEY_EN_ANSI_ENTER }, - { 0, 3, 18, KEY_EN_NUMPAD_4 }, - { 0, 3, 19, KEY_EN_NUMPAD_5 }, - { 0, 3, 20, KEY_EN_NUMPAD_6 }, - { 0, 4, 0, "Key: M4" }, - { 0, 4, 1, KEY_EN_LEFT_SHIFT }, - { 0, 4, 2, KEY_EN_ISO_BACK_SLASH }, - { 0, 4, 3, KEY_EN_Z }, - { 0, 4, 4, KEY_EN_X }, - { 0, 4, 5, KEY_EN_C }, - { 0, 4, 6, KEY_EN_V }, - { 0, 4, 7, KEY_EN_B }, - { 0, 4, 8, KEY_EN_N }, - { 0, 4, 9, KEY_EN_M }, - { 0, 4, 10, KEY_EN_COMMA }, - { 0, 4, 11, KEY_EN_PERIOD }, - { 0, 4, 12, KEY_EN_FORWARD_SLASH }, - { 0, 4, 14, KEY_EN_RIGHT_SHIFT }, - { 0, 4, 16, KEY_EN_UP_ARROW }, - { 0, 4, 18, KEY_EN_NUMPAD_1 }, - { 0, 4, 19, KEY_EN_NUMPAD_2 }, - { 0, 4, 20, KEY_EN_NUMPAD_3 }, - { 0, 4, 21, KEY_EN_NUMPAD_ENTER }, - { 0, 5, 0, "Key: M5" }, - { 0, 5, 1, KEY_EN_LEFT_CONTROL }, - { 0, 5, 2, KEY_EN_LEFT_WINDOWS }, - { 0, 5, 3, KEY_EN_LEFT_ALT }, - { 0, 5, 11, KEY_EN_RIGHT_ALT }, - { 0, 5, 13, KEY_EN_MENU }, - { 0, 5, 14, KEY_EN_RIGHT_CONTROL }, - { 0, 5, 15, KEY_EN_LEFT_ARROW }, - { 0, 5, 16, KEY_EN_DOWN_ARROW }, - { 0, 5, 17, KEY_EN_RIGHT_ARROW }, - { 0, 5, 19, KEY_EN_NUMPAD_0 }, - { 0, 5, 20, KEY_EN_NUMPAD_PERIOD }, -}; - -#define BLACKWIDOW_CHROMA_TE_KEYMAP_SIZE (sizeof(blackwidow_chroma_te_keymap) / sizeof(blackwidow_chroma_te_keymap[0])) - -static const razer_key blackwidow_chroma_te_keymap[] = -{ - /*---------------------------------------------------------------------*\ - | Zone, Row, Column, Key | - \*---------------------------------------------------------------------*/ - { 0, 0, 1, KEY_EN_ESCAPE }, - { 0, 0, 3, KEY_EN_F1 }, - { 0, 0, 4, KEY_EN_F2 }, - { 0, 0, 5, KEY_EN_F3 }, - { 0, 0, 6, KEY_EN_F4 }, - { 0, 0, 7, KEY_EN_F5 }, - { 0, 0, 8, KEY_EN_F6 }, - { 0, 0, 9, KEY_EN_F7 }, - { 0, 0, 10, KEY_EN_F8 }, - { 0, 0, 11, KEY_EN_F9 }, - { 0, 0, 12, KEY_EN_F10 }, - { 0, 0, 13, KEY_EN_F11 }, - { 0, 0, 14, KEY_EN_F12 }, - { 0, 0, 15, KEY_EN_PRINT_SCREEN }, - { 0, 0, 16, KEY_EN_SCROLL_LOCK }, - { 0, 0, 17, KEY_EN_PAUSE_BREAK }, - { 0, 0, 20, "Logo" }, - { 0, 1, 1, KEY_EN_BACK_TICK }, - { 0, 1, 2, KEY_EN_1 }, - { 0, 1, 3, KEY_EN_2 }, - { 0, 1, 4, KEY_EN_3 }, - { 0, 1, 5, KEY_EN_4 }, - { 0, 1, 6, KEY_EN_5 }, - { 0, 1, 7, KEY_EN_6 }, - { 0, 1, 8, KEY_EN_7 }, - { 0, 1, 9, KEY_EN_8 }, - { 0, 1, 10, KEY_EN_9 }, - { 0, 1, 11, KEY_EN_0 }, - { 0, 1, 12, KEY_EN_MINUS }, - { 0, 1, 13, KEY_EN_EQUALS }, - { 0, 1, 14, KEY_EN_BACKSPACE }, - { 0, 1, 15, KEY_EN_INSERT }, - { 0, 1, 16, KEY_EN_HOME }, - { 0, 1, 17, KEY_EN_PAGE_UP }, - { 0, 2, 1, KEY_EN_TAB }, - { 0, 2, 2, KEY_EN_Q }, - { 0, 2, 3, KEY_EN_W }, - { 0, 2, 4, KEY_EN_E }, - { 0, 2, 5, KEY_EN_R }, - { 0, 2, 6, KEY_EN_T }, - { 0, 2, 7, KEY_EN_Y }, - { 0, 2, 8, KEY_EN_U }, - { 0, 2, 9, KEY_EN_I }, - { 0, 2, 10, KEY_EN_O }, - { 0, 2, 11, KEY_EN_P }, - { 0, 2, 12, KEY_EN_LEFT_BRACKET }, - { 0, 2, 13, KEY_EN_RIGHT_BRACKET }, - { 0, 2, 14, KEY_EN_ANSI_BACK_SLASH }, - { 0, 2, 15, KEY_EN_DELETE }, - { 0, 2, 16, KEY_EN_END }, - { 0, 2, 17, KEY_EN_PAGE_DOWN }, - { 0, 3, 1, KEY_EN_CAPS_LOCK }, - { 0, 3, 2, KEY_EN_A }, - { 0, 3, 3, KEY_EN_S }, - { 0, 3, 4, KEY_EN_D }, - { 0, 3, 5, KEY_EN_F }, - { 0, 3, 6, KEY_EN_G }, - { 0, 3, 7, KEY_EN_H }, - { 0, 3, 8, KEY_EN_J }, - { 0, 3, 9, KEY_EN_K }, - { 0, 3, 10, KEY_EN_L }, - { 0, 3, 11, KEY_EN_SEMICOLON }, - { 0, 3, 12, KEY_EN_QUOTE }, - { 0, 3, 13, KEY_EN_POUND }, - { 0, 3, 14, KEY_EN_ANSI_ENTER }, - { 0, 4, 1, KEY_EN_LEFT_SHIFT }, - { 0, 4, 2, KEY_EN_ISO_BACK_SLASH }, - { 0, 4, 3, KEY_EN_Z }, - { 0, 4, 4, KEY_EN_X }, - { 0, 4, 5, KEY_EN_C }, - { 0, 4, 6, KEY_EN_V }, - { 0, 4, 7, KEY_EN_B }, - { 0, 4, 8, KEY_EN_N }, - { 0, 4, 9, KEY_EN_M }, - { 0, 4, 10, KEY_EN_COMMA }, - { 0, 4, 11, KEY_EN_PERIOD }, - { 0, 4, 12, KEY_EN_FORWARD_SLASH }, - { 0, 4, 14, KEY_EN_RIGHT_SHIFT }, - { 0, 4, 16, KEY_EN_UP_ARROW }, - { 0, 5, 1, KEY_EN_LEFT_CONTROL }, - { 0, 5, 2, KEY_EN_LEFT_WINDOWS }, - { 0, 5, 3, KEY_EN_LEFT_ALT }, - { 0, 5, 11, KEY_EN_RIGHT_ALT }, - { 0, 5, 13, KEY_EN_MENU }, - { 0, 5, 14, KEY_EN_RIGHT_CONTROL }, - { 0, 5, 15, KEY_EN_LEFT_ARROW }, - { 0, 5, 16, KEY_EN_DOWN_ARROW }, - { 0, 5, 17, KEY_EN_RIGHT_ARROW }, -}; - -#define BLADE_PRO_2017_KEYMAP_SIZE (sizeof(blade_pro_2017_keymap) / sizeof(blade_pro_2017_keymap[0])) - -static const razer_key blade_pro_2017_keymap[] = -{ - /*---------------------------------------------------------------------*\ - | Zone, Row, Column, Key | - \*---------------------------------------------------------------------*/ - { 0, 0, 2, KEY_EN_ESCAPE }, - { 0, 0, 3, KEY_EN_F1 }, - { 0, 0, 4, KEY_EN_F2 }, - { 0, 0, 5, KEY_EN_F3 }, - { 0, 0, 6, KEY_EN_F4 }, - { 0, 0, 7, KEY_EN_F5 }, - { 0, 0, 8, KEY_EN_F6 }, - { 0, 0, 9, KEY_EN_F7 }, - { 0, 0, 10, KEY_EN_F8 }, - { 0, 0, 11, KEY_EN_F9 }, - { 0, 0, 12, KEY_EN_F10 }, - { 0, 0, 13, KEY_EN_F11 }, - { 0, 0, 14, KEY_EN_F12 }, - { 0, 0, 15, KEY_EN_INSERT }, - { 0, 0, 17, KEY_EN_DELETE }, - { 0, 0, 19, KEY_EN_MEDIA_PREVIOUS }, - { 0, 0, 20, KEY_EN_MEDIA_NEXT }, - { 0, 0, 21, "Key: Media Volume" }, - { 0, 0, 23, KEY_EN_MEDIA_PLAY_PAUSE }, - { 0, 0, 24, KEY_EN_MEDIA_MUTE }, - { 0, 1, 2, KEY_EN_BACK_TICK }, - { 0, 1, 3, KEY_EN_1 }, - { 0, 1, 4, KEY_EN_2 }, - { 0, 1, 5, KEY_EN_3 }, - { 0, 1, 6, KEY_EN_4 }, - { 0, 1, 7, KEY_EN_5 }, - { 0, 1, 8, KEY_EN_6 }, - { 0, 1, 9, KEY_EN_7 }, - { 0, 1, 10, KEY_EN_8 }, - { 0, 1, 11, KEY_EN_9 }, - { 0, 1, 12, KEY_EN_0 }, - { 0, 1, 13, KEY_EN_MINUS }, - { 0, 1, 14, KEY_EN_EQUALS }, - { 0, 1, 15, KEY_EN_BACKSPACE }, - { 0, 2, 2, KEY_EN_TAB }, - { 0, 2, 4, KEY_EN_Q }, - { 0, 2, 5, KEY_EN_W }, - { 0, 2, 6, KEY_EN_E }, - { 0, 2, 7, KEY_EN_R }, - { 0, 2, 8, KEY_EN_T }, - { 0, 2, 9, KEY_EN_Y }, - { 0, 2, 10, KEY_EN_U }, - { 0, 2, 11, KEY_EN_I }, - { 0, 2, 12, KEY_EN_O }, - { 0, 2, 13, KEY_EN_P }, - { 0, 2, 14, KEY_EN_LEFT_BRACKET }, - { 0, 2, 15, KEY_EN_RIGHT_BRACKET }, - { 0, 2, 17, KEY_EN_ANSI_BACK_SLASH }, - { 0, 3, 1, KEY_EN_CAPS_LOCK }, - { 0, 3, 4, KEY_EN_A }, - { 0, 3, 5, KEY_EN_S }, - { 0, 3, 6, KEY_EN_D }, - { 0, 3, 7, KEY_EN_F }, - { 0, 3, 8, KEY_EN_G }, - { 0, 3, 9, KEY_EN_H }, - { 0, 3, 10, KEY_EN_J }, - { 0, 3, 11, KEY_EN_K }, - { 0, 3, 12, KEY_EN_L }, - { 0, 3, 13, KEY_EN_SEMICOLON }, - { 0, 3, 14, KEY_EN_QUOTE }, - { 0, 3, 18, KEY_EN_ANSI_ENTER }, - { 0, 4, 0, KEY_EN_LEFT_SHIFT }, - { 0, 4, 4, KEY_EN_Z }, - { 0, 4, 5, KEY_EN_X }, - { 0, 4, 6, KEY_EN_C }, - { 0, 4, 7, KEY_EN_V }, - { 0, 4, 8, KEY_EN_B }, - { 0, 4, 9, KEY_EN_N }, - { 0, 4, 10, KEY_EN_M }, - { 0, 4, 11, KEY_EN_COMMA }, - { 0, 4, 12, KEY_EN_PERIOD }, - { 0, 4, 13, KEY_EN_FORWARD_SLASH }, - { 0, 4, 14, KEY_EN_UP_ARROW }, - { 0, 4, 18, KEY_EN_RIGHT_SHIFT }, - { 0, 5, 0, KEY_EN_LEFT_CONTROL }, - { 0, 5, 2, KEY_EN_LEFT_FUNCTION }, - { 0, 5, 3, KEY_EN_LEFT_WINDOWS }, - { 0, 5, 5, KEY_EN_LEFT_ALT }, - { 0, 5, 7, KEY_EN_SPACE }, - { 0, 5, 10, KEY_EN_RIGHT_ALT }, - { 0, 5, 12, KEY_EN_RIGHT_CONTROL }, - { 0, 5, 13, KEY_EN_LEFT_ARROW }, - { 0, 5, 14, KEY_EN_DOWN_ARROW }, - { 0, 5, 15, KEY_EN_RIGHT_ARROW }, - { 0, 5, 16, KEY_EN_RIGHT_FUNCTION }, -}; - -#define BLADE_STEALTH_KEYMAP_SIZE (sizeof(blade_stealth_keymap) / sizeof(blade_stealth_keymap[0])) - -static const razer_key blade_stealth_keymap[] = -{ - /*---------------------------------------------------------------------*\ - | Zone, Row, Column, Key | - \*---------------------------------------------------------------------*/ - { 0, 0, 1, KEY_EN_ESCAPE }, - { 0, 0, 2, KEY_EN_F1 }, - { 0, 0, 3, KEY_EN_F2 }, - { 0, 0, 4, KEY_EN_F3 }, - { 0, 0, 5, KEY_EN_F4 }, - { 0, 0, 6, KEY_EN_F5 }, - { 0, 0, 7, KEY_EN_F6 }, - { 0, 0, 8, KEY_EN_F7 }, - { 0, 0, 9, KEY_EN_F8 }, - { 0, 0, 10, KEY_EN_F9 }, - { 0, 0, 11, KEY_EN_F10 }, - { 0, 0, 12, KEY_EN_F11 }, - { 0, 0, 13, KEY_EN_F12 }, - { 0, 0, 14, KEY_EN_INSERT }, - { 0, 0, 15, KEY_EN_DELETE }, - { 0, 1, 1, KEY_EN_BACK_TICK }, - { 0, 1, 2, KEY_EN_1 }, - { 0, 1, 3, KEY_EN_2 }, - { 0, 1, 4, KEY_EN_3 }, - { 0, 1, 5, KEY_EN_4 }, - { 0, 1, 6, KEY_EN_5 }, - { 0, 1, 7, KEY_EN_6 }, - { 0, 1, 8, KEY_EN_7 }, - { 0, 1, 9, KEY_EN_8 }, - { 0, 1, 10, KEY_EN_9 }, - { 0, 1, 11, KEY_EN_0 }, - { 0, 1, 12, KEY_EN_MINUS }, - { 0, 1, 13, KEY_EN_EQUALS }, - { 0, 1, 14, KEY_EN_BACKSPACE }, - { 0, 1, 15, KEY_EN_BACKSPACE }, - { 0, 2, 0, KEY_EN_TAB }, - { 0, 2, 2, KEY_EN_Q }, - { 0, 2, 3, KEY_EN_W }, - { 0, 2, 4, KEY_EN_E }, - { 0, 2, 5, KEY_EN_R }, - { 0, 2, 6, KEY_EN_T }, - { 0, 2, 7, KEY_EN_Y }, - { 0, 2, 8, KEY_EN_U }, - { 0, 2, 9, KEY_EN_I }, - { 0, 2, 10, KEY_EN_O }, - { 0, 2, 11, KEY_EN_P }, - { 0, 2, 12, KEY_EN_LEFT_BRACKET }, - { 0, 2, 13, KEY_EN_RIGHT_BRACKET }, - { 0, 2, 14, KEY_EN_ANSI_BACK_SLASH }, - { 0, 2, 15, KEY_EN_ANSI_BACK_SLASH }, - { 0, 3, 0, KEY_EN_CAPS_LOCK }, - { 0, 3, 2, KEY_EN_A }, - { 0, 3, 3, KEY_EN_S }, - { 0, 3, 4, KEY_EN_D }, - { 0, 3, 5, KEY_EN_F }, - { 0, 3, 6, KEY_EN_G }, - { 0, 3, 7, KEY_EN_H }, - { 0, 3, 8, KEY_EN_J }, - { 0, 3, 9, KEY_EN_K }, - { 0, 3, 10, KEY_EN_L }, - { 0, 3, 11, KEY_EN_SEMICOLON }, - { 0, 3, 12, KEY_EN_QUOTE }, - { 0, 3, 14, KEY_EN_ANSI_ENTER }, - { 0, 3, 15, KEY_EN_ANSI_ENTER }, - { 0, 4, 0, KEY_EN_LEFT_SHIFT }, - { 0, 4, 2, KEY_EN_Z }, - { 0, 4, 3, KEY_EN_X }, - { 0, 4, 4, KEY_EN_C }, - { 0, 4, 5, KEY_EN_V }, - { 0, 4, 6, KEY_EN_B }, - { 0, 4, 7, KEY_EN_N }, - { 0, 4, 8, KEY_EN_M }, - { 0, 4, 9, KEY_EN_COMMA }, - { 0, 4, 10, KEY_EN_PERIOD }, - { 0, 4, 11, KEY_EN_FORWARD_SLASH }, - { 0, 4, 12, KEY_EN_RIGHT_SHIFT }, - { 0, 4, 13, KEY_EN_RIGHT_SHIFT }, - { 0, 4, 14, KEY_EN_RIGHT_SHIFT }, - { 0, 5, 0, KEY_EN_LEFT_CONTROL }, - { 0, 5, 1, KEY_EN_LEFT_FUNCTION }, - { 0, 5, 2, KEY_EN_LEFT_WINDOWS }, - { 0, 5, 3, KEY_EN_LEFT_ALT }, - { 0, 5, 5, KEY_EN_SPACE }, - { 0, 5, 6, KEY_EN_SPACE }, - { 0, 5, 8, KEY_EN_SPACE }, - { 0, 5, 9, KEY_EN_RIGHT_ALT }, - { 0, 5, 10, KEY_EN_RIGHT_FUNCTION }, - { 0, 5, 11, KEY_EN_RIGHT_CONTROL }, - { 0, 5, 12, KEY_EN_LEFT_ARROW }, - { 0, 5, 13, KEY_EN_UP_ARROW }, - { 0, 5, 14, KEY_EN_RIGHT_ARROW }, - { 0, 5, 15, KEY_EN_DOWN_ARROW }, -}; - -#define CYNOSA_CHROMA_KEYMAP_SIZE (sizeof(cynosa_chroma_keymap) / sizeof(cynosa_chroma_keymap[0])) - -static const razer_key cynosa_chroma_keymap[] = -{ - /*---------------------------------------------------------------------*\ - | Zone, Row, Column, Key | - \*---------------------------------------------------------------------*/ - { 0, 0, 1, KEY_EN_ESCAPE }, - { 0, 0, 3, KEY_EN_F1 }, - { 0, 0, 4, KEY_EN_F2 }, - { 0, 0, 5, KEY_EN_F3 }, - { 0, 0, 6, KEY_EN_F4 }, - { 0, 0, 7, KEY_EN_F5 }, - { 0, 0, 8, KEY_EN_F6 }, - { 0, 0, 9, KEY_EN_F7 }, - { 0, 0, 10, KEY_EN_F8 }, - { 0, 0, 11, KEY_EN_F9 }, - { 0, 0, 12, KEY_EN_F10 }, - { 0, 0, 13, KEY_EN_F11 }, - { 0, 0, 14, KEY_EN_F12 }, - { 0, 0, 15, KEY_EN_PRINT_SCREEN }, - { 0, 0, 16, KEY_EN_SCROLL_LOCK }, - { 0, 0, 17, KEY_EN_PAUSE_BREAK }, - { 0, 0, 20, "Logo" }, - { 0, 1, 1, KEY_EN_BACK_TICK }, - { 0, 1, 2, KEY_EN_1 }, - { 0, 1, 3, KEY_EN_2 }, - { 0, 1, 4, KEY_EN_3 }, - { 0, 1, 5, KEY_EN_4 }, - { 0, 1, 6, KEY_EN_5 }, - { 0, 1, 7, KEY_EN_6 }, - { 0, 1, 8, KEY_EN_7 }, - { 0, 1, 9, KEY_EN_8 }, - { 0, 1, 10, KEY_EN_9 }, - { 0, 1, 11, KEY_EN_0 }, - { 0, 1, 12, KEY_EN_MINUS }, - { 0, 1, 13, KEY_EN_EQUALS }, - { 0, 1, 14, KEY_EN_BACKSPACE }, - { 0, 1, 15, KEY_EN_INSERT }, - { 0, 1, 16, KEY_EN_HOME }, - { 0, 1, 17, KEY_EN_PAGE_UP }, - { 0, 1, 18, KEY_EN_NUMPAD_LOCK }, - { 0, 1, 19, KEY_EN_NUMPAD_DIVIDE }, - { 0, 1, 20, KEY_EN_NUMPAD_TIMES }, - { 0, 1, 21, KEY_EN_NUMPAD_MINUS }, - { 0, 2, 1, KEY_EN_TAB }, - { 0, 2, 2, KEY_EN_Q }, - { 0, 2, 3, KEY_EN_W }, - { 0, 2, 4, KEY_EN_E }, - { 0, 2, 5, KEY_EN_R }, - { 0, 2, 6, KEY_EN_T }, - { 0, 2, 7, KEY_EN_Y }, - { 0, 2, 8, KEY_EN_U }, - { 0, 2, 9, KEY_EN_I }, - { 0, 2, 10, KEY_EN_O }, - { 0, 2, 11, KEY_EN_P }, - { 0, 2, 12, KEY_EN_LEFT_BRACKET }, - { 0, 2, 13, KEY_EN_RIGHT_BRACKET }, - { 0, 2, 14, KEY_EN_ANSI_BACK_SLASH }, - { 0, 2, 15, KEY_EN_DELETE }, - { 0, 2, 16, KEY_EN_END }, - { 0, 2, 17, KEY_EN_PAGE_DOWN }, - { 0, 2, 18, KEY_EN_NUMPAD_7 }, - { 0, 2, 19, KEY_EN_NUMPAD_8 }, - { 0, 2, 20, KEY_EN_NUMPAD_9 }, - { 0, 2, 21, KEY_EN_NUMPAD_PLUS }, - { 0, 3, 1, KEY_EN_CAPS_LOCK }, - { 0, 3, 2, KEY_EN_A }, - { 0, 3, 3, KEY_EN_S }, - { 0, 3, 4, KEY_EN_D }, - { 0, 3, 5, KEY_EN_F }, - { 0, 3, 6, KEY_EN_G }, - { 0, 3, 7, KEY_EN_H }, - { 0, 3, 8, KEY_EN_J }, - { 0, 3, 9, KEY_EN_K }, - { 0, 3, 10, KEY_EN_L }, - { 0, 3, 11, KEY_EN_SEMICOLON }, - { 0, 3, 12, KEY_EN_QUOTE }, - { 0, 3, 13, KEY_EN_POUND }, - { 0, 3, 14, KEY_EN_ANSI_ENTER }, - { 0, 3, 18, KEY_EN_NUMPAD_4 }, - { 0, 3, 19, KEY_EN_NUMPAD_5 }, - { 0, 3, 20, KEY_EN_NUMPAD_6 }, - { 0, 4, 1, KEY_EN_LEFT_SHIFT }, - { 0, 4, 2, KEY_EN_ISO_BACK_SLASH }, - { 0, 4, 3, KEY_EN_Z }, - { 0, 4, 4, KEY_EN_X }, - { 0, 4, 5, KEY_EN_C }, - { 0, 4, 6, KEY_EN_V }, - { 0, 4, 7, KEY_EN_B }, - { 0, 4, 8, KEY_EN_N }, - { 0, 4, 9, KEY_EN_M }, - { 0, 4, 10, KEY_EN_COMMA }, - { 0, 4, 11, KEY_EN_PERIOD }, - { 0, 4, 12, KEY_EN_FORWARD_SLASH }, - { 0, 4, 14, KEY_EN_RIGHT_SHIFT }, - { 0, 4, 16, KEY_EN_UP_ARROW }, - { 0, 4, 18, KEY_EN_NUMPAD_1 }, - { 0, 4, 19, KEY_EN_NUMPAD_2 }, - { 0, 4, 20, KEY_EN_NUMPAD_3 }, - { 0, 4, 21, KEY_EN_NUMPAD_ENTER }, - { 0, 5, 1, KEY_EN_LEFT_CONTROL }, - { 0, 5, 2, KEY_EN_LEFT_WINDOWS }, - { 0, 5, 3, KEY_EN_LEFT_ALT }, - { 0, 5, 7, KEY_EN_SPACE }, - { 0, 5, 11, KEY_EN_RIGHT_ALT }, - { 0, 5, 12, KEY_EN_RIGHT_FUNCTION }, - { 0, 5, 13, KEY_EN_MENU }, - { 0, 5, 14, KEY_EN_RIGHT_CONTROL }, - { 0, 5, 15, KEY_EN_LEFT_ARROW }, - { 0, 5, 16, KEY_EN_DOWN_ARROW }, - { 0, 5, 17, KEY_EN_RIGHT_ARROW }, - { 0, 5, 19, KEY_EN_NUMPAD_0 }, - { 0, 5, 20, KEY_EN_NUMPAD_PERIOD }, -}; - -#define HUNTSMAN_ELITE_KEYMAP_SIZE (sizeof(huntsman_elite_keymap) / sizeof(huntsman_elite_keymap[0])) - -static const razer_key huntsman_elite_keymap[] = -{ - /*---------------------------------------------------------------------*\ - | Zone, Row, Column, Key | - \*---------------------------------------------------------------------*/ - { 0, 0, 1, KEY_EN_ESCAPE }, - { 0, 0, 3, KEY_EN_F1 }, - { 0, 0, 4, KEY_EN_F2 }, - { 0, 0, 5, KEY_EN_F3 }, - { 0, 0, 6, KEY_EN_F4 }, - { 0, 0, 7, KEY_EN_F5 }, - { 0, 0, 8, KEY_EN_F6 }, - { 0, 0, 9, KEY_EN_F7 }, - { 0, 0, 10, KEY_EN_F8 }, - { 0, 0, 11, KEY_EN_F9 }, - { 0, 0, 12, KEY_EN_F10 }, - { 0, 0, 13, KEY_EN_F11 }, - { 0, 0, 14, KEY_EN_F12 }, - { 0, 0, 15, KEY_EN_PRINT_SCREEN }, - { 0, 0, 16, KEY_EN_SCROLL_LOCK }, - { 0, 0, 17, KEY_EN_PAUSE_BREAK }, - { 0, 0, 18, KEY_EN_MEDIA_PREVIOUS }, - { 0, 0, 19, KEY_EN_MEDIA_PLAY_PAUSE }, - { 0, 0, 20, KEY_EN_MEDIA_NEXT }, - { 0, 0, 21, KEY_EN_MEDIA_MUTE }, - { 0, 1, 1, KEY_EN_BACK_TICK }, - { 0, 1, 2, KEY_EN_1 }, - { 0, 1, 3, KEY_EN_2 }, - { 0, 1, 4, KEY_EN_3 }, - { 0, 1, 5, KEY_EN_4 }, - { 0, 1, 6, KEY_EN_5 }, - { 0, 1, 7, KEY_EN_6 }, - { 0, 1, 8, KEY_EN_7 }, - { 0, 1, 9, KEY_EN_8 }, - { 0, 1, 10, KEY_EN_9 }, - { 0, 1, 11, KEY_EN_0 }, - { 0, 1, 12, KEY_EN_MINUS }, - { 0, 1, 13, KEY_EN_EQUALS }, - { 0, 1, 14, KEY_EN_BACKSPACE }, - { 0, 1, 15, KEY_EN_INSERT }, - { 0, 1, 16, KEY_EN_HOME }, - { 0, 1, 17, KEY_EN_PAGE_UP }, - { 0, 1, 18, KEY_EN_NUMPAD_LOCK }, - { 0, 1, 19, KEY_EN_NUMPAD_DIVIDE }, - { 0, 1, 20, KEY_EN_NUMPAD_TIMES }, - { 0, 1, 21, KEY_EN_NUMPAD_MINUS }, - { 0, 2, 1, KEY_EN_TAB }, - { 0, 2, 2, KEY_EN_Q }, - { 0, 2, 3, KEY_EN_W }, - { 0, 2, 4, KEY_EN_E }, - { 0, 2, 5, KEY_EN_R }, - { 0, 2, 6, KEY_EN_T }, - { 0, 2, 7, KEY_EN_Y }, - { 0, 2, 8, KEY_EN_U }, - { 0, 2, 9, KEY_EN_I }, - { 0, 2, 10, KEY_EN_O }, - { 0, 2, 11, KEY_EN_P }, - { 0, 2, 12, KEY_EN_LEFT_BRACKET }, - { 0, 2, 13, KEY_EN_RIGHT_BRACKET }, - { 0, 2, 14, KEY_EN_ANSI_BACK_SLASH }, - { 0, 2, 15, KEY_EN_DELETE }, - { 0, 2, 16, KEY_EN_END }, - { 0, 2, 17, KEY_EN_PAGE_DOWN }, - { 0, 2, 18, KEY_EN_NUMPAD_7 }, - { 0, 2, 19, KEY_EN_NUMPAD_8 }, - { 0, 2, 20, KEY_EN_NUMPAD_9 }, - { 0, 2, 21, KEY_EN_NUMPAD_PLUS }, - { 0, 3, 1, KEY_EN_CAPS_LOCK }, - { 0, 3, 2, KEY_EN_A }, - { 0, 3, 3, KEY_EN_S }, - { 0, 3, 4, KEY_EN_D }, - { 0, 3, 5, KEY_EN_F }, - { 0, 3, 6, KEY_EN_G }, - { 0, 3, 7, KEY_EN_H }, - { 0, 3, 8, KEY_EN_J }, - { 0, 3, 9, KEY_EN_K }, - { 0, 3, 10, KEY_EN_L }, - { 0, 3, 11, KEY_EN_SEMICOLON }, - { 0, 3, 12, KEY_EN_QUOTE }, - { 0, 3, 13, KEY_EN_POUND }, - { 0, 3, 14, KEY_EN_ANSI_ENTER }, - { 0, 3, 18, KEY_EN_NUMPAD_4 }, - { 0, 3, 19, KEY_EN_NUMPAD_5 }, - { 0, 3, 20, KEY_EN_NUMPAD_6 }, - { 0, 4, 1, KEY_EN_LEFT_SHIFT }, - { 0, 4, 2, KEY_EN_ISO_BACK_SLASH }, - { 0, 4, 3, KEY_EN_Z }, - { 0, 4, 4, KEY_EN_X }, - { 0, 4, 5, KEY_EN_C }, - { 0, 4, 6, KEY_EN_V }, - { 0, 4, 7, KEY_EN_B }, - { 0, 4, 8, KEY_EN_N }, - { 0, 4, 9, KEY_EN_M }, - { 0, 4, 10, KEY_EN_COMMA }, - { 0, 4, 11, KEY_EN_PERIOD }, - { 0, 4, 12, KEY_EN_FORWARD_SLASH }, - { 0, 4, 14, KEY_EN_RIGHT_SHIFT }, - { 0, 4, 16, KEY_EN_UP_ARROW }, - { 0, 4, 18, KEY_EN_NUMPAD_1 }, - { 0, 4, 19, KEY_EN_NUMPAD_2 }, - { 0, 4, 20, KEY_EN_NUMPAD_3 }, - { 0, 4, 21, KEY_EN_NUMPAD_ENTER }, - { 0, 5, 1, KEY_EN_LEFT_CONTROL }, - { 0, 5, 2, KEY_EN_LEFT_WINDOWS }, - { 0, 5, 3, KEY_EN_LEFT_ALT }, - { 0, 5, 7, KEY_EN_SPACE }, - { 0, 5, 11, KEY_EN_RIGHT_ALT }, - { 0, 5, 12, KEY_EN_RIGHT_FUNCTION }, - { 0, 5, 13, KEY_EN_MENU }, - { 0, 5, 14, KEY_EN_RIGHT_CONTROL }, - { 0, 5, 15, KEY_EN_LEFT_ARROW }, - { 0, 5, 16, KEY_EN_DOWN_ARROW }, - { 0, 5, 17, KEY_EN_RIGHT_ARROW }, - { 0, 5, 19, KEY_EN_NUMPAD_0 }, - { 0, 5, 20, KEY_EN_NUMPAD_PERIOD }, -}; - -#define HUNTSMAN_KEYMAP_SIZE (sizeof(huntsman_keymap) / sizeof(huntsman_keymap[0])) - -static const razer_key huntsman_keymap[] = -{ - /*---------------------------------------------------------------------*\ - | Zone, Row, Column, Key | - \*---------------------------------------------------------------------*/ - { 0, 0, 1, KEY_EN_ESCAPE }, - { 0, 0, 3, KEY_EN_F1 }, - { 0, 0, 4, KEY_EN_F2 }, - { 0, 0, 5, KEY_EN_F3 }, - { 0, 0, 6, KEY_EN_F4 }, - { 0, 0, 7, KEY_EN_F5 }, - { 0, 0, 8, KEY_EN_F6 }, - { 0, 0, 9, KEY_EN_F7 }, - { 0, 0, 10, KEY_EN_F8 }, - { 0, 0, 11, KEY_EN_F9 }, - { 0, 0, 12, KEY_EN_F10 }, - { 0, 0, 13, KEY_EN_F11 }, - { 0, 0, 14, KEY_EN_F12 }, - { 0, 0, 15, KEY_EN_PRINT_SCREEN }, - { 0, 0, 16, KEY_EN_SCROLL_LOCK }, - { 0, 0, 17, KEY_EN_PAUSE_BREAK }, - { 0, 1, 1, KEY_EN_BACK_TICK }, - { 0, 1, 2, KEY_EN_1 }, - { 0, 1, 3, KEY_EN_2 }, - { 0, 1, 4, KEY_EN_3 }, - { 0, 1, 5, KEY_EN_4 }, - { 0, 1, 6, KEY_EN_5 }, - { 0, 1, 7, KEY_EN_6 }, - { 0, 1, 8, KEY_EN_7 }, - { 0, 1, 9, KEY_EN_8 }, - { 0, 1, 10, KEY_EN_9 }, - { 0, 1, 11, KEY_EN_0 }, - { 0, 1, 12, KEY_EN_MINUS }, - { 0, 1, 13, KEY_EN_EQUALS }, - { 0, 1, 14, KEY_EN_BACKSPACE }, - { 0, 1, 15, KEY_EN_INSERT }, - { 0, 1, 16, KEY_EN_HOME }, - { 0, 1, 17, KEY_EN_PAGE_UP }, - { 0, 1, 18, KEY_EN_NUMPAD_LOCK }, - { 0, 1, 19, KEY_EN_NUMPAD_DIVIDE }, - { 0, 1, 20, KEY_EN_NUMPAD_TIMES }, - { 0, 1, 21, KEY_EN_NUMPAD_MINUS }, - { 0, 2, 1, KEY_EN_TAB }, - { 0, 2, 2, KEY_EN_Q }, - { 0, 2, 3, KEY_EN_W }, - { 0, 2, 4, KEY_EN_E }, - { 0, 2, 5, KEY_EN_R }, - { 0, 2, 6, KEY_EN_T }, - { 0, 2, 7, KEY_EN_Y }, - { 0, 2, 8, KEY_EN_U }, - { 0, 2, 9, KEY_EN_I }, - { 0, 2, 10, KEY_EN_O }, - { 0, 2, 11, KEY_EN_P }, - { 0, 2, 12, KEY_EN_LEFT_BRACKET }, - { 0, 2, 13, KEY_EN_RIGHT_BRACKET }, - { 0, 2, 14, KEY_EN_ANSI_BACK_SLASH }, - { 0, 2, 15, KEY_EN_DELETE }, - { 0, 2, 16, KEY_EN_END }, - { 0, 2, 17, KEY_EN_PAGE_DOWN }, - { 0, 2, 18, KEY_EN_NUMPAD_7 }, - { 0, 2, 19, KEY_EN_NUMPAD_8 }, - { 0, 2, 20, KEY_EN_NUMPAD_9 }, - { 0, 2, 21, KEY_EN_NUMPAD_PLUS }, - { 0, 3, 1, KEY_EN_CAPS_LOCK }, - { 0, 3, 2, KEY_EN_A }, - { 0, 3, 3, KEY_EN_S }, - { 0, 3, 4, KEY_EN_D }, - { 0, 3, 5, KEY_EN_F }, - { 0, 3, 6, KEY_EN_G }, - { 0, 3, 7, KEY_EN_H }, - { 0, 3, 8, KEY_EN_J }, - { 0, 3, 9, KEY_EN_K }, - { 0, 3, 10, KEY_EN_L }, - { 0, 3, 11, KEY_EN_SEMICOLON }, - { 0, 3, 12, KEY_EN_QUOTE }, - { 0, 3, 13, KEY_EN_POUND }, - { 0, 3, 14, KEY_EN_ANSI_ENTER }, - { 0, 3, 18, KEY_EN_NUMPAD_4 }, - { 0, 3, 19, KEY_EN_NUMPAD_5 }, - { 0, 3, 20, KEY_EN_NUMPAD_6 }, - { 0, 4, 1, KEY_EN_LEFT_SHIFT }, - { 0, 4, 2, KEY_EN_ISO_BACK_SLASH }, - { 0, 4, 3, KEY_EN_Z }, - { 0, 4, 4, KEY_EN_X }, - { 0, 4, 5, KEY_EN_C }, - { 0, 4, 6, KEY_EN_V }, - { 0, 4, 7, KEY_EN_B }, - { 0, 4, 8, KEY_EN_N }, - { 0, 4, 9, KEY_EN_M }, - { 0, 4, 10, KEY_EN_COMMA }, - { 0, 4, 11, KEY_EN_PERIOD }, - { 0, 4, 12, KEY_EN_FORWARD_SLASH }, - { 0, 4, 14, KEY_EN_RIGHT_SHIFT }, - { 0, 4, 16, KEY_EN_UP_ARROW }, - { 0, 4, 18, KEY_EN_NUMPAD_1 }, - { 0, 4, 19, KEY_EN_NUMPAD_2 }, - { 0, 4, 20, KEY_EN_NUMPAD_3 }, - { 0, 4, 21, KEY_EN_NUMPAD_ENTER }, - { 0, 5, 1, KEY_EN_LEFT_CONTROL }, - { 0, 5, 2, KEY_EN_LEFT_WINDOWS }, - { 0, 5, 3, KEY_EN_LEFT_ALT }, - { 0, 5, 7, KEY_EN_SPACE }, - { 0, 5, 11, KEY_EN_RIGHT_ALT }, - { 0, 5, 12, KEY_EN_RIGHT_FUNCTION }, - { 0, 5, 13, KEY_EN_MENU }, - { 0, 5, 14, KEY_EN_RIGHT_CONTROL }, - { 0, 5, 15, KEY_EN_LEFT_ARROW }, - { 0, 5, 16, KEY_EN_DOWN_ARROW }, - { 0, 5, 17, KEY_EN_RIGHT_ARROW }, - { 0, 5, 19, KEY_EN_NUMPAD_0 }, - { 0, 5, 20, KEY_EN_NUMPAD_PERIOD }, -}; - -#define HUNTSMAN_TE_KEYMAP_SIZE (sizeof(huntsman_te_keymap) / sizeof(huntsman_te_keymap[0])) - -static const razer_key huntsman_te_keymap[] = -{ - /*---------------------------------------------------------------------*\ - | Zone, Row, Column, Key | - \*---------------------------------------------------------------------*/ - { 0, 0, 1, KEY_EN_ESCAPE }, - { 0, 0, 3, KEY_EN_F1 }, - { 0, 0, 4, KEY_EN_F2 }, - { 0, 0, 5, KEY_EN_F3 }, - { 0, 0, 6, KEY_EN_F4 }, - { 0, 0, 7, KEY_EN_F5 }, - { 0, 0, 8, KEY_EN_F6 }, - { 0, 0, 9, KEY_EN_F7 }, - { 0, 0, 10, KEY_EN_F8 }, - { 0, 0, 11, KEY_EN_F9 }, - { 0, 0, 12, KEY_EN_F10 }, - { 0, 0, 13, KEY_EN_F11 }, - { 0, 0, 14, KEY_EN_F12 }, - { 0, 0, 15, KEY_EN_PRINT_SCREEN }, - { 0, 0, 16, KEY_EN_SCROLL_LOCK }, - { 0, 0, 17, KEY_EN_PAUSE_BREAK }, - { 0, 1, 1, KEY_EN_BACK_TICK }, - { 0, 1, 2, KEY_EN_1 }, - { 0, 1, 3, KEY_EN_2 }, - { 0, 1, 4, KEY_EN_3 }, - { 0, 1, 5, KEY_EN_4 }, - { 0, 1, 6, KEY_EN_5 }, - { 0, 1, 7, KEY_EN_6 }, - { 0, 1, 8, KEY_EN_7 }, - { 0, 1, 9, KEY_EN_8 }, - { 0, 1, 10, KEY_EN_9 }, - { 0, 1, 11, KEY_EN_0 }, - { 0, 1, 12, KEY_EN_MINUS }, - { 0, 1, 13, KEY_EN_EQUALS }, - { 0, 1, 14, KEY_EN_BACKSPACE }, - { 0, 1, 15, KEY_EN_INSERT }, - { 0, 1, 16, KEY_EN_HOME }, - { 0, 1, 17, KEY_EN_PAGE_UP }, - { 0, 2, 1, KEY_EN_TAB }, - { 0, 2, 2, KEY_EN_Q }, - { 0, 2, 3, KEY_EN_W }, - { 0, 2, 4, KEY_EN_E }, - { 0, 2, 5, KEY_EN_R }, - { 0, 2, 6, KEY_EN_T }, - { 0, 2, 7, KEY_EN_Y }, - { 0, 2, 8, KEY_EN_U }, - { 0, 2, 9, KEY_EN_I }, - { 0, 2, 10, KEY_EN_O }, - { 0, 2, 11, KEY_EN_P }, - { 0, 2, 12, KEY_EN_LEFT_BRACKET }, - { 0, 2, 13, KEY_EN_RIGHT_BRACKET }, - { 0, 2, 14, KEY_EN_ANSI_BACK_SLASH }, - { 0, 2, 15, KEY_EN_DELETE }, - { 0, 2, 16, KEY_EN_END }, - { 0, 2, 17, KEY_EN_PAGE_DOWN }, - { 0, 3, 1, KEY_EN_CAPS_LOCK }, - { 0, 3, 2, KEY_EN_A }, - { 0, 3, 3, KEY_EN_S }, - { 0, 3, 4, KEY_EN_D }, - { 0, 3, 5, KEY_EN_F }, - { 0, 3, 6, KEY_EN_G }, - { 0, 3, 7, KEY_EN_H }, - { 0, 3, 8, KEY_EN_J }, - { 0, 3, 9, KEY_EN_K }, - { 0, 3, 10, KEY_EN_L }, - { 0, 3, 11, KEY_EN_SEMICOLON }, - { 0, 3, 12, KEY_EN_QUOTE }, - { 0, 3, 13, KEY_EN_POUND }, - { 0, 3, 14, KEY_EN_ANSI_ENTER }, - { 0, 4, 1, KEY_EN_LEFT_SHIFT }, - { 0, 4, 2, KEY_EN_ISO_BACK_SLASH }, - { 0, 4, 3, KEY_EN_Z }, - { 0, 4, 4, KEY_EN_X }, - { 0, 4, 5, KEY_EN_C }, - { 0, 4, 6, KEY_EN_V }, - { 0, 4, 7, KEY_EN_B }, - { 0, 4, 8, KEY_EN_N }, - { 0, 4, 9, KEY_EN_M }, - { 0, 4, 10, KEY_EN_COMMA }, - { 0, 4, 11, KEY_EN_PERIOD }, - { 0, 4, 12, KEY_EN_FORWARD_SLASH }, - { 0, 4, 14, KEY_EN_RIGHT_SHIFT }, - { 0, 4, 16, KEY_EN_UP_ARROW }, - { 0, 5, 1, KEY_EN_LEFT_CONTROL }, - { 0, 5, 2, KEY_EN_LEFT_WINDOWS }, - { 0, 5, 3, KEY_EN_LEFT_ALT }, - { 0, 5, 7, KEY_EN_SPACE }, - { 0, 5, 11, KEY_EN_RIGHT_ALT }, - { 0, 5, 12, KEY_EN_RIGHT_FUNCTION }, - { 0, 5, 13, KEY_EN_MENU }, - { 0, 5, 14, KEY_EN_RIGHT_CONTROL }, - { 0, 5, 15, KEY_EN_LEFT_ARROW }, - { 0, 5, 16, KEY_EN_DOWN_ARROW }, - { 0, 5, 17, KEY_EN_RIGHT_ARROW }, -}; - -#define BLACKWIDOW_ELITE_KEYMAP_SIZE (sizeof(blackwidow_elite_keymap) / sizeof(blackwidow_elite_keymap[0])) - -static const razer_key blackwidow_elite_keymap[] = -{ - /*---------------------------------------------------------------------*\ - | Zone, Row, Column, Key | - \*---------------------------------------------------------------------*/ - { 0, 0, 1, KEY_EN_ESCAPE }, - { 0, 0, 3, KEY_EN_F1 }, - { 0, 0, 4, KEY_EN_F2 }, - { 0, 0, 5, KEY_EN_F3 }, - { 0, 0, 6, KEY_EN_F4 }, - { 0, 0, 7, KEY_EN_F5 }, - { 0, 0, 8, KEY_EN_F6 }, - { 0, 0, 9, KEY_EN_F7 }, - { 0, 0, 10, KEY_EN_F8 }, - { 0, 0, 11, KEY_EN_F9 }, - { 0, 0, 12, KEY_EN_F10 }, - { 0, 0, 13, KEY_EN_F11 }, - { 0, 0, 14, KEY_EN_F12 }, - { 0, 0, 15, KEY_EN_PRINT_SCREEN }, - { 0, 0, 16, KEY_EN_SCROLL_LOCK }, - { 0, 0, 17, KEY_EN_PAUSE_BREAK }, - { 0, 0, 18, KEY_EN_MEDIA_PREVIOUS }, - { 0, 0, 19, KEY_EN_MEDIA_PLAY_PAUSE }, - { 0, 0, 20, KEY_EN_MEDIA_NEXT }, - { 0, 0, 21, KEY_EN_MEDIA_MUTE }, - { 0, 1, 1, KEY_EN_BACK_TICK }, - { 0, 1, 2, KEY_EN_1 }, - { 0, 1, 3, KEY_EN_2 }, - { 0, 1, 4, KEY_EN_3 }, - { 0, 1, 5, KEY_EN_4 }, - { 0, 1, 6, KEY_EN_5 }, - { 0, 1, 7, KEY_EN_6 }, - { 0, 1, 8, KEY_EN_7 }, - { 0, 1, 9, KEY_EN_8 }, - { 0, 1, 10, KEY_EN_9 }, - { 0, 1, 11, KEY_EN_0 }, - { 0, 1, 12, KEY_EN_MINUS }, - { 0, 1, 13, KEY_EN_EQUALS }, - { 0, 1, 14, KEY_EN_BACKSPACE }, - { 0, 1, 15, KEY_EN_INSERT }, - { 0, 1, 16, KEY_EN_HOME }, - { 0, 1, 17, KEY_EN_PAGE_UP }, - { 0, 1, 18, KEY_EN_NUMPAD_LOCK }, - { 0, 1, 19, KEY_EN_NUMPAD_DIVIDE }, - { 0, 1, 20, KEY_EN_NUMPAD_TIMES }, - { 0, 1, 21, KEY_EN_NUMPAD_MINUS }, - { 0, 2, 1, KEY_EN_TAB }, - { 0, 2, 2, KEY_EN_Q }, - { 0, 2, 3, KEY_EN_W }, - { 0, 2, 4, KEY_EN_E }, - { 0, 2, 5, KEY_EN_R }, - { 0, 2, 6, KEY_EN_T }, - { 0, 2, 7, KEY_EN_Y }, - { 0, 2, 8, KEY_EN_U }, - { 0, 2, 9, KEY_EN_I }, - { 0, 2, 10, KEY_EN_O }, - { 0, 2, 11, KEY_EN_P }, - { 0, 2, 12, KEY_EN_LEFT_BRACKET }, - { 0, 2, 13, KEY_EN_RIGHT_BRACKET }, - { 0, 2, 14, KEY_EN_ANSI_BACK_SLASH }, - { 0, 2, 15, KEY_EN_DELETE }, - { 0, 2, 16, KEY_EN_END }, - { 0, 2, 17, KEY_EN_PAGE_DOWN }, - { 0, 2, 18, KEY_EN_NUMPAD_7 }, - { 0, 2, 19, KEY_EN_NUMPAD_8 }, - { 0, 2, 20, KEY_EN_NUMPAD_9 }, - { 0, 2, 21, KEY_EN_NUMPAD_PLUS }, - { 0, 3, 1, KEY_EN_CAPS_LOCK }, - { 0, 3, 2, KEY_EN_A }, - { 0, 3, 3, KEY_EN_S }, - { 0, 3, 4, KEY_EN_D }, - { 0, 3, 5, KEY_EN_F }, - { 0, 3, 6, KEY_EN_G }, - { 0, 3, 7, KEY_EN_H }, - { 0, 3, 8, KEY_EN_J }, - { 0, 3, 9, KEY_EN_K }, - { 0, 3, 10, KEY_EN_L }, - { 0, 3, 11, KEY_EN_SEMICOLON }, - { 0, 3, 12, KEY_EN_QUOTE }, - { 0, 3, 13, KEY_EN_POUND }, - { 0, 3, 14, KEY_EN_ANSI_ENTER }, - { 0, 3, 18, KEY_EN_NUMPAD_4 }, - { 0, 3, 19, KEY_EN_NUMPAD_5 }, - { 0, 3, 20, KEY_EN_NUMPAD_6 }, - { 0, 4, 1, KEY_EN_LEFT_SHIFT }, - { 0, 4, 2, KEY_EN_ISO_BACK_SLASH }, - { 0, 4, 3, KEY_EN_Z }, - { 0, 4, 4, KEY_EN_X }, - { 0, 4, 5, KEY_EN_C }, - { 0, 4, 6, KEY_EN_V }, - { 0, 4, 7, KEY_EN_B }, - { 0, 4, 8, KEY_EN_N }, - { 0, 4, 9, KEY_EN_M }, - { 0, 4, 10, KEY_EN_COMMA }, - { 0, 4, 11, KEY_EN_PERIOD }, - { 0, 4, 12, KEY_EN_FORWARD_SLASH }, - { 0, 4, 14, KEY_EN_RIGHT_SHIFT }, - { 0, 4, 16, KEY_EN_UP_ARROW }, - { 0, 4, 18, KEY_EN_NUMPAD_1 }, - { 0, 4, 19, KEY_EN_NUMPAD_2 }, - { 0, 4, 20, KEY_EN_NUMPAD_3 }, - { 0, 4, 21, KEY_EN_NUMPAD_ENTER }, - { 0, 5, 1, KEY_EN_LEFT_CONTROL }, - { 0, 5, 2, KEY_EN_LEFT_WINDOWS }, - { 0, 5, 3, KEY_EN_LEFT_ALT }, - { 0, 5, 6, KEY_EN_SPACE }, - { 0, 5, 10, KEY_EN_RIGHT_ALT }, - { 0, 5, 11, "Logo" }, - { 0, 5, 12, KEY_EN_RIGHT_FUNCTION }, - { 0, 5, 13, KEY_EN_MENU }, - { 0, 5, 14, KEY_EN_RIGHT_CONTROL }, - { 0, 5, 15, KEY_EN_LEFT_ARROW }, - { 0, 5, 16, KEY_EN_DOWN_ARROW }, - { 0, 5, 17, KEY_EN_RIGHT_ARROW }, - { 0, 5, 19, KEY_EN_NUMPAD_0 }, - { 0, 5, 20, KEY_EN_NUMPAD_PERIOD }, -}; - -#define BLACKWIDOW_2019_KEYMAP_SIZE (sizeof(blackwidow_2019_keymap) / sizeof(blackwidow_2019_keymap[0])) - -static const razer_key blackwidow_2019_keymap[] = -{ - /*---------------------------------------------------------------------*\ - | Zone, Row, Column, Key | - \*---------------------------------------------------------------------*/ - { 0, 0, 1, KEY_EN_ESCAPE }, - { 0, 0, 3, KEY_EN_F1 }, - { 0, 0, 4, KEY_EN_F2 }, - { 0, 0, 5, KEY_EN_F3 }, - { 0, 0, 6, KEY_EN_F4 }, - { 0, 0, 7, KEY_EN_F5 }, - { 0, 0, 8, KEY_EN_F6 }, - { 0, 0, 9, KEY_EN_F7 }, - { 0, 0, 10, KEY_EN_F8 }, - { 0, 0, 11, KEY_EN_F9 }, - { 0, 0, 12, KEY_EN_F10 }, - { 0, 0, 13, KEY_EN_F11 }, - { 0, 0, 14, KEY_EN_F12 }, - { 0, 0, 15, KEY_EN_PRINT_SCREEN }, - { 0, 0, 16, KEY_EN_SCROLL_LOCK }, - { 0, 0, 17, KEY_EN_PAUSE_BREAK }, - { 0, 1, 1, KEY_EN_BACK_TICK }, - { 0, 1, 2, KEY_EN_1 }, - { 0, 1, 3, KEY_EN_2 }, - { 0, 1, 4, KEY_EN_3 }, - { 0, 1, 5, KEY_EN_4 }, - { 0, 1, 6, KEY_EN_5 }, - { 0, 1, 7, KEY_EN_6 }, - { 0, 1, 8, KEY_EN_7 }, - { 0, 1, 9, KEY_EN_8 }, - { 0, 1, 10, KEY_EN_9 }, - { 0, 1, 11, KEY_EN_0 }, - { 0, 1, 12, KEY_EN_MINUS }, - { 0, 1, 13, KEY_EN_EQUALS }, - { 0, 1, 14, KEY_EN_BACKSPACE }, - { 0, 1, 15, KEY_EN_INSERT }, - { 0, 1, 16, KEY_EN_HOME }, - { 0, 1, 17, KEY_EN_PAGE_UP }, - { 0, 1, 18, KEY_EN_NUMPAD_LOCK }, - { 0, 1, 19, KEY_EN_NUMPAD_DIVIDE }, - { 0, 1, 20, KEY_EN_NUMPAD_TIMES }, - { 0, 1, 21, KEY_EN_NUMPAD_MINUS }, - { 0, 2, 1, KEY_EN_TAB }, - { 0, 2, 2, KEY_EN_Q }, - { 0, 2, 3, KEY_EN_W }, - { 0, 2, 4, KEY_EN_E }, - { 0, 2, 5, KEY_EN_R }, - { 0, 2, 6, KEY_EN_T }, - { 0, 2, 7, KEY_EN_Y }, - { 0, 2, 8, KEY_EN_U }, - { 0, 2, 9, KEY_EN_I }, - { 0, 2, 10, KEY_EN_O }, - { 0, 2, 11, KEY_EN_P }, - { 0, 2, 12, KEY_EN_LEFT_BRACKET }, - { 0, 2, 13, KEY_EN_RIGHT_BRACKET }, - { 0, 2, 14, KEY_EN_ANSI_BACK_SLASH }, - { 0, 2, 15, KEY_EN_DELETE }, - { 0, 2, 16, KEY_EN_END }, - { 0, 2, 17, KEY_EN_PAGE_DOWN }, - { 0, 2, 18, KEY_EN_NUMPAD_7 }, - { 0, 2, 19, KEY_EN_NUMPAD_8 }, - { 0, 2, 20, KEY_EN_NUMPAD_9 }, - { 0, 2, 21, KEY_EN_NUMPAD_PLUS }, - { 0, 3, 1, KEY_EN_CAPS_LOCK }, - { 0, 3, 2, KEY_EN_A }, - { 0, 3, 3, KEY_EN_S }, - { 0, 3, 4, KEY_EN_D }, - { 0, 3, 5, KEY_EN_F }, - { 0, 3, 6, KEY_EN_G }, - { 0, 3, 7, KEY_EN_H }, - { 0, 3, 8, KEY_EN_J }, - { 0, 3, 9, KEY_EN_K }, - { 0, 3, 10, KEY_EN_L }, - { 0, 3, 11, KEY_EN_SEMICOLON }, - { 0, 3, 12, KEY_EN_QUOTE }, - { 0, 3, 13, KEY_EN_POUND }, - { 0, 3, 14, KEY_EN_ANSI_ENTER }, - { 0, 3, 18, KEY_EN_NUMPAD_4 }, - { 0, 3, 19, KEY_EN_NUMPAD_5 }, - { 0, 3, 20, KEY_EN_NUMPAD_6 }, - { 0, 4, 1, KEY_EN_LEFT_SHIFT }, - { 0, 4, 2, KEY_EN_ISO_BACK_SLASH }, - { 0, 4, 3, KEY_EN_Z }, - { 0, 4, 4, KEY_EN_X }, - { 0, 4, 5, KEY_EN_C }, - { 0, 4, 6, KEY_EN_V }, - { 0, 4, 7, KEY_EN_B }, - { 0, 4, 8, KEY_EN_N }, - { 0, 4, 9, KEY_EN_M }, - { 0, 4, 10, KEY_EN_COMMA }, - { 0, 4, 11, KEY_EN_PERIOD }, - { 0, 4, 12, KEY_EN_FORWARD_SLASH }, - { 0, 4, 14, KEY_EN_RIGHT_SHIFT }, - { 0, 4, 16, KEY_EN_UP_ARROW }, - { 0, 4, 18, KEY_EN_NUMPAD_1 }, - { 0, 4, 19, KEY_EN_NUMPAD_2 }, - { 0, 4, 20, KEY_EN_NUMPAD_3 }, - { 0, 4, 21, KEY_EN_NUMPAD_ENTER }, - { 0, 5, 1, KEY_EN_LEFT_CONTROL }, - { 0, 5, 2, KEY_EN_LEFT_WINDOWS }, - { 0, 5, 3, KEY_EN_LEFT_ALT }, - { 0, 5, 6, KEY_EN_SPACE }, - { 0, 5, 10, KEY_EN_RIGHT_ALT }, - { 0, 5, 11, "Logo" }, - { 0, 5, 12, KEY_EN_RIGHT_FUNCTION }, - { 0, 5, 13, KEY_EN_MENU }, - { 0, 5, 14, KEY_EN_RIGHT_CONTROL }, - { 0, 5, 15, KEY_EN_LEFT_ARROW }, - { 0, 5, 16, KEY_EN_DOWN_ARROW }, - { 0, 5, 17, KEY_EN_RIGHT_ARROW }, - { 0, 5, 19, KEY_EN_NUMPAD_0 }, - { 0, 5, 20, "Key: Number Pad ," }, -}; - -#define ORNATA_CHROMA_KEYMAP_SIZE (sizeof(ornata_chroma_keymap) / sizeof(ornata_chroma_keymap[0])) - -static const razer_key ornata_chroma_keymap[] = -{ - /*---------------------------------------------------------------------*\ - | Zone, Row, Column, Key | - \*---------------------------------------------------------------------*/ - { 0, 0, 1, KEY_EN_ESCAPE }, - { 0, 0, 3, KEY_EN_F1 }, - { 0, 0, 4, KEY_EN_F2 }, - { 0, 0, 5, KEY_EN_F3 }, - { 0, 0, 6, KEY_EN_F4 }, - { 0, 0, 7, KEY_EN_F5 }, - { 0, 0, 8, KEY_EN_F6 }, - { 0, 0, 9, KEY_EN_F7 }, - { 0, 0, 10, KEY_EN_F8 }, - { 0, 0, 11, KEY_EN_F9 }, - { 0, 0, 12, KEY_EN_F10 }, - { 0, 0, 13, KEY_EN_F11 }, - { 0, 0, 14, KEY_EN_F12 }, - { 0, 0, 15, KEY_EN_PRINT_SCREEN }, - { 0, 0, 16, KEY_EN_SCROLL_LOCK }, - { 0, 0, 17, KEY_EN_PAUSE_BREAK }, - { 0, 1, 1, KEY_EN_BACK_TICK }, - { 0, 1, 2, KEY_EN_1 }, - { 0, 1, 3, KEY_EN_2 }, - { 0, 1, 4, KEY_EN_3 }, - { 0, 1, 5, KEY_EN_4 }, - { 0, 1, 6, KEY_EN_5 }, - { 0, 1, 7, KEY_EN_6 }, - { 0, 1, 8, KEY_EN_7 }, - { 0, 1, 9, KEY_EN_8 }, - { 0, 1, 10, KEY_EN_9 }, - { 0, 1, 11, KEY_EN_0 }, - { 0, 1, 12, KEY_EN_MINUS }, - { 0, 1, 13, KEY_EN_EQUALS }, - { 0, 1, 14, KEY_EN_BACKSPACE }, - { 0, 1, 15, KEY_EN_INSERT }, - { 0, 1, 16, KEY_EN_HOME }, - { 0, 1, 17, KEY_EN_PAGE_UP }, - { 0, 1, 18, KEY_EN_NUMPAD_LOCK }, - { 0, 1, 19, KEY_EN_NUMPAD_DIVIDE }, - { 0, 1, 20, KEY_EN_NUMPAD_TIMES }, - { 0, 1, 21, KEY_EN_NUMPAD_MINUS }, - { 0, 2, 1, KEY_EN_TAB }, - { 0, 2, 2, KEY_EN_Q }, - { 0, 2, 3, KEY_EN_W }, - { 0, 2, 4, KEY_EN_E }, - { 0, 2, 5, KEY_EN_R }, - { 0, 2, 6, KEY_EN_T }, - { 0, 2, 7, KEY_EN_Y }, - { 0, 2, 8, KEY_EN_U }, - { 0, 2, 9, KEY_EN_I }, - { 0, 2, 10, KEY_EN_O }, - { 0, 2, 11, KEY_EN_P }, - { 0, 2, 12, KEY_EN_LEFT_BRACKET }, - { 0, 2, 13, KEY_EN_RIGHT_BRACKET }, - { 0, 2, 14, KEY_EN_ANSI_BACK_SLASH }, - { 0, 2, 15, KEY_EN_DELETE }, - { 0, 2, 16, KEY_EN_END }, - { 0, 2, 17, KEY_EN_PAGE_DOWN }, - { 0, 2, 18, KEY_EN_NUMPAD_7 }, - { 0, 2, 19, KEY_EN_NUMPAD_8 }, - { 0, 2, 20, KEY_EN_NUMPAD_9 }, - { 0, 2, 21, KEY_EN_NUMPAD_PLUS }, - { 0, 3, 1, KEY_EN_CAPS_LOCK }, - { 0, 3, 2, KEY_EN_A }, - { 0, 3, 3, KEY_EN_S }, - { 0, 3, 4, KEY_EN_D }, - { 0, 3, 5, KEY_EN_F }, - { 0, 3, 6, KEY_EN_G }, - { 0, 3, 7, KEY_EN_H }, - { 0, 3, 8, KEY_EN_J }, - { 0, 3, 9, KEY_EN_K }, - { 0, 3, 10, KEY_EN_L }, - { 0, 3, 11, KEY_EN_SEMICOLON }, - { 0, 3, 12, KEY_EN_QUOTE }, - { 0, 3, 13, KEY_EN_POUND }, - { 0, 3, 14, KEY_EN_ANSI_ENTER }, - { 0, 3, 18, KEY_EN_NUMPAD_4 }, - { 0, 3, 19, KEY_EN_NUMPAD_5 }, - { 0, 3, 20, KEY_EN_NUMPAD_6 }, - { 0, 4, 1, KEY_EN_LEFT_SHIFT }, - { 0, 4, 2, KEY_EN_ISO_BACK_SLASH }, - { 0, 4, 3, KEY_EN_Z }, - { 0, 4, 4, KEY_EN_X }, - { 0, 4, 5, KEY_EN_C }, - { 0, 4, 6, KEY_EN_V }, - { 0, 4, 7, KEY_EN_B }, - { 0, 4, 8, KEY_EN_N }, - { 0, 4, 9, KEY_EN_M }, - { 0, 4, 10, KEY_EN_COMMA }, - { 0, 4, 11, KEY_EN_PERIOD }, - { 0, 4, 12, KEY_EN_FORWARD_SLASH }, - { 0, 4, 14, KEY_EN_RIGHT_SHIFT }, - { 0, 4, 16, KEY_EN_UP_ARROW }, - { 0, 4, 18, KEY_EN_NUMPAD_1 }, - { 0, 4, 19, KEY_EN_NUMPAD_2 }, - { 0, 4, 20, KEY_EN_NUMPAD_3 }, - { 0, 4, 21, KEY_EN_NUMPAD_ENTER }, - { 0, 5, 1, KEY_EN_LEFT_CONTROL }, - { 0, 5, 2, KEY_EN_LEFT_WINDOWS }, - { 0, 5, 3, KEY_EN_LEFT_ALT }, - { 0, 5, 7, KEY_EN_SPACE }, - { 0, 5, 11, KEY_EN_RIGHT_ALT }, - { 0, 5, 12, KEY_EN_RIGHT_FUNCTION }, - { 0, 5, 13, KEY_EN_MENU }, - { 0, 5, 14, KEY_EN_RIGHT_CONTROL }, - { 0, 5, 15, KEY_EN_LEFT_ARROW }, - { 0, 5, 16, KEY_EN_DOWN_ARROW }, - { 0, 5, 17, KEY_EN_RIGHT_ARROW }, - { 0, 5, 19, KEY_EN_NUMPAD_0 }, - { 0, 5, 20, KEY_EN_NUMPAD_PERIOD }, -}; - -#define BLACKWIDOW_CHROMA_V2_KEYMAP_SIZE (sizeof(blackwidow_chroma_v2_keymap) / sizeof(blackwidow_chroma_v2_keymap[0])) - -static const razer_key blackwidow_chroma_v2_keymap[] = -{ - /*---------------------------------------------------------------------*\ - | Zone, Row, Column, Key | - \*---------------------------------------------------------------------*/ - { 0, 0, 1, KEY_EN_ESCAPE }, - { 0, 0, 3, KEY_EN_F1 }, - { 0, 0, 4, KEY_EN_F2 }, - { 0, 0, 5, KEY_EN_F3 }, - { 0, 0, 6, KEY_EN_F4 }, - { 0, 0, 7, KEY_EN_F5 }, - { 0, 0, 8, KEY_EN_F6 }, - { 0, 0, 9, KEY_EN_F7 }, - { 0, 0, 10, KEY_EN_F8 }, - { 0, 0, 11, KEY_EN_F9 }, - { 0, 0, 12, KEY_EN_F10 }, - { 0, 0, 13, KEY_EN_F11 }, - { 0, 0, 14, KEY_EN_F12 }, - { 0, 0, 15, KEY_EN_PRINT_SCREEN }, - { 0, 0, 16, KEY_EN_SCROLL_LOCK }, - { 0, 0, 17, KEY_EN_PAUSE_BREAK }, - { 0, 0, 20, "Logo" }, - { 0, 1, 0, "Key: M1" }, - { 0, 1, 1, KEY_EN_BACK_TICK }, - { 0, 1, 2, KEY_EN_1 }, - { 0, 1, 3, KEY_EN_2 }, - { 0, 1, 4, KEY_EN_3 }, - { 0, 1, 5, KEY_EN_4 }, - { 0, 1, 6, KEY_EN_5 }, - { 0, 1, 7, KEY_EN_6 }, - { 0, 1, 8, KEY_EN_7 }, - { 0, 1, 9, KEY_EN_8 }, - { 0, 1, 10, KEY_EN_9 }, - { 0, 1, 11, KEY_EN_0 }, - { 0, 1, 12, KEY_EN_MINUS }, - { 0, 1, 13, KEY_EN_EQUALS }, - { 0, 1, 14, KEY_EN_BACKSPACE }, - { 0, 1, 15, KEY_EN_INSERT }, - { 0, 1, 16, KEY_EN_HOME }, - { 0, 1, 17, KEY_EN_PAGE_UP }, - { 0, 1, 18, KEY_EN_NUMPAD_LOCK }, - { 0, 1, 19, KEY_EN_NUMPAD_DIVIDE }, - { 0, 1, 20, KEY_EN_NUMPAD_TIMES }, - { 0, 1, 21, KEY_EN_NUMPAD_MINUS }, - { 0, 2, 0, "Key: M2" }, - { 0, 2, 1, KEY_EN_TAB }, - { 0, 2, 2, KEY_EN_Q }, - { 0, 2, 3, KEY_EN_W }, - { 0, 2, 4, KEY_EN_E }, - { 0, 2, 5, KEY_EN_R }, - { 0, 2, 6, KEY_EN_T }, - { 0, 2, 7, KEY_EN_Y }, - { 0, 2, 8, KEY_EN_U }, - { 0, 2, 9, KEY_EN_I }, - { 0, 2, 10, KEY_EN_O }, - { 0, 2, 11, KEY_EN_P }, - { 0, 2, 12, KEY_EN_LEFT_BRACKET }, - { 0, 2, 13, KEY_EN_RIGHT_BRACKET }, - { 0, 2, 14, KEY_EN_ANSI_BACK_SLASH }, - { 0, 2, 15, KEY_EN_DELETE }, - { 0, 2, 16, KEY_EN_END }, - { 0, 2, 17, KEY_EN_PAGE_DOWN }, - { 0, 2, 18, KEY_EN_NUMPAD_7 }, - { 0, 2, 19, KEY_EN_NUMPAD_8 }, - { 0, 2, 20, KEY_EN_NUMPAD_9 }, - { 0, 2, 21, KEY_EN_NUMPAD_PLUS }, - { 0, 3, 0, "Key: M3" }, - { 0, 3, 1, KEY_EN_CAPS_LOCK }, - { 0, 3, 2, KEY_EN_A }, - { 0, 3, 3, KEY_EN_S }, - { 0, 3, 4, KEY_EN_D }, - { 0, 3, 5, KEY_EN_F }, - { 0, 3, 6, KEY_EN_G }, - { 0, 3, 7, KEY_EN_H }, - { 0, 3, 8, KEY_EN_J }, - { 0, 3, 9, KEY_EN_K }, - { 0, 3, 10, KEY_EN_L }, - { 0, 3, 11, KEY_EN_SEMICOLON }, - { 0, 3, 12, KEY_EN_QUOTE }, - { 0, 3, 13, KEY_EN_POUND }, - { 0, 3, 14, KEY_EN_ANSI_ENTER }, - { 0, 3, 18, KEY_EN_NUMPAD_4 }, - { 0, 3, 19, KEY_EN_NUMPAD_5 }, - { 0, 3, 20, KEY_EN_NUMPAD_6 }, - { 0, 4, 0, "Key: M4" }, - { 0, 4, 1, KEY_EN_LEFT_SHIFT }, - { 0, 4, 2, KEY_EN_ISO_BACK_SLASH }, - { 0, 4, 3, KEY_EN_Z }, - { 0, 4, 4, KEY_EN_X }, - { 0, 4, 5, KEY_EN_C }, - { 0, 4, 6, KEY_EN_V }, - { 0, 4, 7, KEY_EN_B }, - { 0, 4, 8, KEY_EN_N }, - { 0, 4, 9, KEY_EN_M }, - { 0, 4, 10, KEY_EN_COMMA }, - { 0, 4, 11, KEY_EN_PERIOD }, - { 0, 4, 12, KEY_EN_FORWARD_SLASH }, - { 0, 4, 14, KEY_EN_RIGHT_SHIFT }, - { 0, 4, 16, KEY_EN_UP_ARROW }, - { 0, 4, 18, KEY_EN_NUMPAD_1 }, - { 0, 4, 19, KEY_EN_NUMPAD_2 }, - { 0, 4, 20, KEY_EN_NUMPAD_3 }, - { 0, 4, 21, KEY_EN_NUMPAD_ENTER }, - { 0, 5, 0, "Key: M5" }, - { 0, 5, 1, KEY_EN_LEFT_CONTROL }, - { 0, 5, 2, KEY_EN_LEFT_WINDOWS }, - { 0, 5, 3, KEY_EN_LEFT_ALT }, - { 0, 5, 11, KEY_EN_RIGHT_ALT }, - { 0, 5, 13, KEY_EN_MENU }, - { 0, 5, 14, KEY_EN_RIGHT_CONTROL }, - { 0, 5, 15, KEY_EN_LEFT_ARROW }, - { 0, 5, 16, KEY_EN_DOWN_ARROW }, - { 0, 5, 17, KEY_EN_RIGHT_ARROW }, - { 0, 5, 19, KEY_EN_NUMPAD_0 }, - { 0, 5, 20, KEY_EN_NUMPAD_PERIOD }, -}; - -/*-------------------------------------------------------------------------*\ -| KEYBOARDS | -\*-------------------------------------------------------------------------*/ - -/*-------------------------------------------------------------*\ -| Razer Blackwidow 2019 1532:0241 | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 22 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blackwidow_2019_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 22 -}; - -static const razer_device blackwidow_2019_device = -{ - "Razer BlackWidow 2019", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 22, - { - &blackwidow_2019_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - blackwidow_2019_keymap, - BLACKWIDOW_2019_KEYMAP_SIZE -}; - -/*-------------------------------------------------------------*\ -| Razer BlackWidow Chroma | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 22 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blackwidow_chroma_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 22 -}; - -static const razer_device blackwidow_chroma_device = -{ - "Razer BlackWidow Chroma", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 22, - { - &blackwidow_chroma_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - blackwidow_chroma_keymap, - BLACKWIDOW_CHROMA_KEYMAP_SIZE -}; - -/*-------------------------------------------------------------*\ -| Razer Blackwidow Chroma Overwatch 1532:0211 | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 22 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blackwidow_chroma_overwatch_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 22 -}; - -static const razer_device blackwidow_chroma_overwatch_device = -{ - "Razer Blackwidow Chroma Overwatch", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 22, - { - &blackwidow_chroma_overwatch_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer BlackWidow Chroma Tournament Edition | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 22 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blackwidow_chroma_te_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 22 -}; - -static const razer_device blackwidow_chroma_te_device = -{ - "Razer BlackWidow Chroma Tournament Edition", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 22, - { - &blackwidow_chroma_te_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - blackwidow_chroma_te_keymap, - BLACKWIDOW_CHROMA_TE_KEYMAP_SIZE -}; - -/*-------------------------------------------------------------*\ -| Razer Blackwidow Elite 1532:0228 | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 22 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blackwidow_elite_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 22 -}; - -static const razer_device blackwidow_elite_device = -{ - "Razer BlackWidow Elite", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 22, - { - &blackwidow_elite_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - blackwidow_elite_keymap, - BLACKWIDOW_ELITE_KEYMAP_SIZE -}; - -/*-------------------------------------------------------------*\ -| Razer Blackwidow Chroma V2 1532:0221 | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 22 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blackwidow_chroma_v2_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 22 -}; - -static const razer_device blackwidow_chroma_v2_device = -{ - "Razer BlackWidow Chroma V2", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 22, - { - &blackwidow_chroma_v2_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - blackwidow_chroma_v2_keymap, - BLACKWIDOW_CHROMA_V2_KEYMAP_SIZE -}; - -/*-------------------------------------------------------------*\ -| Razer Blackwidow X Chroma 1532:0216 | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 22 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blackwidow_x_chroma_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 22 -}; - -static const razer_device blackwidow_x_chroma_device = -{ - "Razer BlackWidow X Chroma", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 22, - { - &blackwidow_x_chroma_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer BlackWidow X Chroma Tournament Edition 1532:021A | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 22 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blackwidow_x_chroma_te_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 22 -}; - -static const razer_device blackwidow_x_chroma_te_device = -{ - "Razer BlackWidow X Chroma Tournament Edition", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 22, - { - &blackwidow_x_chroma_te_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Cynosa Chroma 1532:022A | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 22 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone cynosa_chroma_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 22 -}; - -static const razer_device cynosa_chroma_device = -{ - "Razer Cynosa Chroma", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 22, - { - &cynosa_chroma_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - cynosa_chroma_keymap, - CYNOSA_CHROMA_KEYMAP_SIZE -}; - -/*-------------------------------------------------------------*\ -| Razer Cynosa v2 1532:025E | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 22 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone cynosa_v2_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 22 -}; - -static const razer_device cynosa_v2_device = -{ - "Razer Cynosa V2", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 22, - { - &cynosa_v2_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Cynosa Lite 1532:023F | -| | -| Zone "Keyboard" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone cynosa_lite_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device cynosa_lite_device = -{ - "Razer Cynosa Lite", - DEVICE_TYPE_KEYBOARD, - true, - 1, - 1, - { - &cynosa_lite_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Ornata Chroma | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 22 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone ornata_chroma_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 22 -}; - -static const razer_device ornata_chroma_device = -{ - "Razer Ornata Chroma", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 22, - { - &ornata_chroma_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - ornata_chroma_keymap, - ORNATA_CHROMA_KEYMAP_SIZE -}; - -/*-------------------------------------------------------------*\ -| Razer DeathStalker Chroma | -| | -| Zone "Keyboard" | -| Linear | -| 12 LEDs | -\*-------------------------------------------------------------*/ -static const razer_zone deathstalker_chroma_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_LINEAR, - 1, - 12 -}; - -static const razer_device deathstalker_chroma_device = -{ - "Razer DeathStalker Chroma", - DEVICE_TYPE_KEYBOARD, - true, - 1, - 12, - { - &deathstalker_chroma_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Huntsman 1532:0227 | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 22 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone huntsman_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 22 -}; - -static const razer_device huntsman_device = -{ - "Razer Huntsman", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 22, - { - &huntsman_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - huntsman_keymap, - HUNTSMAN_KEYMAP_SIZE -}; - -/*-------------------------------------------------------------*\ -| Razer Huntsman Elite | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 22 Columns | -| | -| Zone "Underglow" | -| Matrix | -| 3 Rows, 22 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone huntsman_elite_keyboard_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 22 -}; - -static const razer_zone huntsman_elite_underglow_zone = -{ - "Underglow", - ZONE_TYPE_MATRIX, - 3, - 22 -}; - -static const razer_device huntsman_elite_device = -{ - "Razer Huntsman Elite", - DEVICE_TYPE_KEYBOARD, - true, - 9, - 22, - { - &huntsman_elite_keyboard_zone, - &huntsman_elite_underglow_zone, - NULL, - NULL, - NULL, - NULL - }, - huntsman_elite_keymap, - HUNTSMAN_ELITE_KEYMAP_SIZE -}; - -/*-------------------------------------------------------------*\ -| Razer Huntsman TE 1532:0243 | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 18 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone huntsman_te_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 18 -}; - -static const razer_device huntsman_te_device = -{ - "Razer Huntsman Tournament Edition", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 18, - { - &huntsman_te_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - huntsman_te_keymap, - HUNTSMAN_TE_KEYMAP_SIZE -}; - -/*-------------------------------------------------------------------------*\ -| LAPTOPS | -\*-------------------------------------------------------------------------*/ - -/*-------------------------------------------------------------*\ -| Razer Blade Stealth | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_stealth_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 16 -}; - -static const razer_device blade_stealth_device = -{ - "Razer Blade Stealth", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 16, - { - &blade_stealth_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - blade_stealth_keymap, - BLADE_STEALTH_KEYMAP_SIZE -}; - -/*-------------------------------------------------------------*\ -| Razer Blade Stealth (Late 2016) | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_stealth_late_2016_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 16 -}; - -static const razer_device blade_stealth_late_2016_device = -{ - "Razer Blade Stealth (Late 2016)", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 16, - { - &blade_stealth_late_2016_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade Stealth (Mid 2017) | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_stealth_mid_2017_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 16 -}; - -static const razer_device blade_stealth_mid_2017_device = -{ - "Razer Blade Stealth (Mid 2017)", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 16, - { - &blade_stealth_mid_2017_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade Stealth (Late 2017) | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_stealth_late_2017_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 16 -}; - -static const razer_device blade_stealth_late_2017_device = -{ - "Razer Blade Stealth (Late 2017)", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 16, - { - &blade_stealth_late_2017_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade Stealth (2019) | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_stealth_2019_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 16 -}; - -static const razer_device blade_stealth_2019_device = -{ - "Razer Blade Stealth (2019)", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 16, - { - &blade_stealth_2019_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade Stealth (Late 2019) | -| | -| Zone "Keyboard" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone blade_stealth_late_2019_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device blade_stealth_late_2019_device = -{ - "Razer Blade Stealth (Late 2019)", - DEVICE_TYPE_KEYBOARD, - false, - 1, - 1, - { - &blade_stealth_late_2019_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; -/*-------------------------------------------------------------*\ -| Razer Blade Stealth (Early 2020) 1532:0252 | -| | -| Zone "Keyboard" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone blade_stealth_early_2020_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device blade_stealth_early_2020_device = -{ - "Razer Blade Stealth (Early 2020)", - DEVICE_TYPE_KEYBOARD, - false, - 1, - 1, - { - &blade_stealth_late_2019_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade (Late 2016) | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_late_2016_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 16 -}; - -static const razer_device blade_late_2016_device = -{ - "Razer Blade (Late 2016)", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 16, - { - &blade_late_2016_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade (QHD) | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_qhd_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 16 -}; - -static const razer_device blade_qhd_device = -{ - "Razer Blade (QHD)", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 16, - { - &blade_qhd_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade 15 (2018) | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_15_2018_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 16 -}; - -static const razer_device blade_15_2018_device = -{ - "Razer Blade 15 (2018)", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 16, - { - &blade_15_2018_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade 15 (2018) Mercury | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_15_2018_mercury_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 16 -}; - -static const razer_device blade_15_2018_mercury_device = -{ - "Razer Blade 15 (2018) Mercury", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 16, - { - &blade_15_2018_mercury_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade 15 (2018) Base Model | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_15_2018_base_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 16 -}; - -static const razer_device blade_15_2018_base_device = -{ - "Razer Blade 15 (2018) Base Model", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 16, - { - &blade_15_2018_base_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade 15 (2019) Advanced | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_15_2019_advanced_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 16 -}; - -static const razer_device blade_15_2019_advanced_device = -{ - "Razer Blade 15 (2019) Advanced", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 16, - { - &blade_15_2019_advanced_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade 15 (Mid 2019) Mercury | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_15_mid_2019_mercury_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 16 -}; - -static const razer_device blade_15_mid_2019_mercury_device = -{ - "Razer Blade 15 (Mid 2019) Mercury White", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 16, - { - &blade_15_mid_2019_mercury_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade 15 (Mid 2019) Base Model | -| | -| Zone "Keyboard" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone blade_15_mid_2019_base_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device blade_15_mid_2019_base_device = -{ - "Razer Blade 15 (Mid 2019) Base Model", - DEVICE_TYPE_KEYBOARD, - false, - 1, - 1, - { - &blade_15_mid_2019_base_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade 15 (Early 2020) Base Model 1532:0255 | -| | -| Zone "Keyboard" | -| Linear | -| 1 Row, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_15_early_2020_base_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_LINEAR, - 1, - 16 -}; - -static const razer_device blade_15_early_2020_base_device = -{ - "Razer Blade 15 Base (Early 2020)", - DEVICE_TYPE_KEYBOARD, - true, - 1, - 16, - { - &blade_15_early_2020_base_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade 15 Studio Edition (2019) | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_15_studio_2019_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 16 -}; - -static const razer_device blade_15_studio_2019_device = -{ - "Razer Blade 15 Studio Edition (2019)", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 16, - { - &blade_15_studio_2019_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade Pro (Late 2016) | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 25 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_pro_late_2016_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 25 -}; - -static const razer_device blade_pro_late_2016_device = -{ - "Razer Blade Pro (Late 2016)", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 25, - { - &blade_pro_late_2016_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade Pro (2017) | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 25 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_pro_2017_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 25 -}; - -static const razer_device blade_pro_2017_device = -{ - "Razer Blade Pro (2017)", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 25, - { - &blade_pro_2017_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - blade_pro_2017_keymap, - BLADE_PRO_2017_KEYMAP_SIZE -}; - -/*-------------------------------------------------------------*\ -| Razer Blade Pro FullHD (2017) | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 25 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_pro_2017_fullhd_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 25 -}; - -static const razer_device blade_pro_2017_fullhd_device = -{ - "Razer Blade Pro FullHD (2017)", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 25, - { - &blade_pro_2017_fullhd_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade Pro 17 (2019) | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_pro_17_2019_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 16 -}; - -static const razer_device blade_pro_17_2019_device = -{ - "Razer Blade Pro 17 (2019)", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 16, - { - &blade_pro_17_2019_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade Pro (Late 2019) | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_pro_late_2019_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 16 -}; - -static const razer_device blade_pro_late_2019_device = -{ - "Razer Blade Pro (Late 2019)", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 16, - { - &blade_pro_late_2019_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Blade Advanced (2020) 1532:0253 | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 16 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blade_15_advanced_2020_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 16 -}; - -static const razer_device blade_15_advanced_2020_device = -{ - "Razer Blade 15 Advanced (2020)", - DEVICE_TYPE_KEYBOARD, - true, - 6, - 16, - { - &blade_15_advanced_2020_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------------------*\ -| MICE | -\*-------------------------------------------------------------------------*/ - -/*-------------------------------------------------------------*\ -| Razer Abyssus Elite DVa Edition 1532:006A | -| | -| Zone "Logo" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone abyssus_elite_dva_edition_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device abyssus_elite_dva_edition_device = -{ - "Razer Abyssus Elite DVa Edition", - DEVICE_TYPE_MOUSE, - false, - 1, - 1, - { - &abyssus_elite_dva_edition_logo_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Abyssus Essential 1532:006B | -| | -| Zone "Logo" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone abyssus_essential_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device abyssus_essential_device = -{ - "Razer Abyssus Essential", - DEVICE_TYPE_MOUSE, - false, - 1, - 1, - { - &abyssus_essential_logo_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Basilisk 1532:0064 | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone basilisk_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone basilisk_scroll_wheel_zone = -{ - "Scroll Wheel", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device basilisk_device = -{ - "Razer Basilisk", - DEVICE_TYPE_MOUSE, - false, - 1, - 2, - { - &basilisk_logo_zone, - &basilisk_scroll_wheel_zone, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer DeathAdder Chroma | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone deathadder_chroma_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone deathadder_chroma_scroll_wheel_zone = -{ - "Scroll Wheel", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device deathadder_chroma_device = -{ - "Razer DeathAdder Chroma", - DEVICE_TYPE_MOUSE, - false, - 1, - 2, - { - &deathadder_chroma_logo_zone, - &deathadder_chroma_scroll_wheel_zone, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Deathadder Elite | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone deathadder_elite_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone deathadder_elite_scroll_wheel_zone = -{ - "Scroll Wheel", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device deathadder_elite_device = -{ - "Razer DeathAdder Elite", - DEVICE_TYPE_MOUSE, - false, - 1, - 2, - { - &deathadder_elite_logo_zone, - &deathadder_elite_scroll_wheel_zone, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Deathadder Essential 1532:006E | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone deathadder_essential_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone deathadder_essential_scroll_wheel_zone = -{ - "Scroll Wheel", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device deathadder_essential_device = -{ - "Razer DeathAdder Essential", - DEVICE_TYPE_MOUSE, - false, - 1, - 2, - { - &deathadder_essential_logo_zone, - &deathadder_essential_scroll_wheel_zone, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Deathadder Essential White Edition 1532:0071 | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone deathadder_essential_white_edition_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone deathadder_essential_white_edition_scroll_wheel_zone = -{ - "Scroll Wheel", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device deathadder_essential_white_edition_device = -{ - "Razer DeathAdder Essential (White Edition)", - DEVICE_TYPE_MOUSE, - false, - 1, - 2, - { - &deathadder_essential_white_edition_logo_zone, - &deathadder_essential_white_edition_scroll_wheel_zone, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer DeathAdder V2 1532:0084 | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone deathadder_v2_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone deathadder_v2_scroll_wheel_zone = -{ - "Scroll Wheel", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device deathadder_v2_device = -{ - "Razer DeathAdder V2", - DEVICE_TYPE_MOUSE, - false, - 1, - 2, - { - &deathadder_v2_logo_zone, - &deathadder_v2_scroll_wheel_zone, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Diamondback Chroma | -| | -| Zone "LED Strip" | -| Linear | -| 19 LEDs | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone diamondback_chroma_led_strip_zone = -{ - "LED Strip", - ZONE_TYPE_LINEAR, - 1, - 19 -}; - -static const razer_zone diamondback_chroma_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone diamondback_chroma_scroll_wheel_zone = -{ - "Scroll Wheel", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device diamondback_chroma_device = -{ - "Razer Diamondback Chroma", - DEVICE_TYPE_MOUSE, - true, - 1, - 21, - { - &diamondback_chroma_led_strip_zone, - &diamondback_chroma_logo_zone, - &diamondback_chroma_scroll_wheel_zone, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Lancehead Tournament Edition 1532:0060 | -| | -| Zone "Right" | -| Linear | -| 7 LEDs | -| | -| Zone "Left" | -| Linear | -| 7 LEDs | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone lancehead_te_right_zone = -{ - "Right LED Strip", - ZONE_TYPE_LINEAR, - 1, - 7 -}; - -static const razer_zone lancehead_te_left_zone = -{ - "Left LED Strip", - ZONE_TYPE_LINEAR, - 1, - 7 -}; - -static const razer_zone lancehead_te_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone lancehead_te_scroll_wheel_zone = -{ - "Scroll Wheel", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device lancehead_te_device = -{ - "Razer Lancehead Tournament Edition", - DEVICE_TYPE_MOUSE, - true, - 1, - 16, - { - &lancehead_te_right_zone, - &lancehead_te_left_zone, - &lancehead_te_logo_zone, - &lancehead_te_scroll_wheel_zone, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Lancehead V2 (Wired) 1532:0070 | -| | -| Zone "Right" | -| Linear | -| 7 LEDs | -| | -| Zone "Left" | -| Linear | -| 7 LEDs | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone lancehead_v2_wired_right_zone = -{ - "Right LED Strip", - ZONE_TYPE_LINEAR, - 1, - 7 -}; - -static const razer_zone lancehead_v2_wired_left_zone = -{ - "Left LED Strip", - ZONE_TYPE_LINEAR, - 1, - 7 -}; - -static const razer_zone lancehead_v2_wired_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone lancehead_v2_wired_scroll_wheel_zone = -{ - "Scroll Wheel", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device lancehead_v2_wired_device = -{ - "Razer Lancehead Wireless (Wired)", - DEVICE_TYPE_MOUSE, - true, - 1, - 16, - { - &lancehead_v2_wired_right_zone, - &lancehead_v2_wired_left_zone, - &lancehead_v2_wired_logo_zone, - &lancehead_v2_wired_scroll_wheel_zone, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Lancehead V2 (Wireless) 1532:006F | -| | -| Zone "Right" | -| Linear | -| 7 LEDs | -| | -| Zone "Left" | -| Linear | -| 7 LEDs | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone lancehead_v2_wireless_right_zone = -{ - "Right LED Strip", - ZONE_TYPE_LINEAR, - 1, - 7 -}; - -static const razer_zone lancehead_v2_wireless_left_zone = -{ - "Left LED Strip", - ZONE_TYPE_LINEAR, - 1, - 7 -}; - -static const razer_zone lancehead_v2_wireless_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone lancehead_v2_wireless_scroll_wheel_zone = -{ - "Scroll Wheel", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device lancehead_v2_wireless_device = -{ - "Razer Lancehead Wireless (Receiver)", - DEVICE_TYPE_MOUSE, - true, - 1, - 16, - { - &lancehead_v2_wireless_right_zone, - &lancehead_v2_wireless_left_zone, - &lancehead_v2_wireless_logo_zone, - &lancehead_v2_wireless_scroll_wheel_zone, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Mamba 2012 (Wired) | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone mamba_2012_wired_zone = -{ - "Scroll Wheel", - ZONE_TYPE_LINEAR, - 1, - 1 -}; - -static const razer_device mamba_2012_wired_device = -{ - "Razer Mamba 2012 (Wired)", - DEVICE_TYPE_MOUSE, - false, - 1, - 15, - { - &mamba_2012_wired_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Mamba 2012 (Wireless) | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone mamba_2012_wireless_zone = -{ - "Scroll Wheel", - ZONE_TYPE_LINEAR, - 1, - 1 -}; - -static const razer_device mamba_2012_wireless_device = -{ - "Razer Mamba 2012 (Wireless)", - DEVICE_TYPE_MOUSE, - false, - 1, - 15, - { - &mamba_2012_wireless_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Mamba (Wired) | -| | -| Zone "Chroma Zone" | -| Single | -| 15 LEDs | -\*-------------------------------------------------------------*/ -static const razer_zone mamba_wired_zone = -{ - "Chroma Zone", - ZONE_TYPE_LINEAR, - 1, - 15 -}; - -static const razer_device mamba_wired_device = -{ - "Razer Mamba (Wired)", - DEVICE_TYPE_MOUSE, - false, - 1, - 15, - { - &mamba_wired_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Mamba (Wireless) | -| | -| Zone "Chroma Zone" | -| Single | -| 15 LED | -\*-------------------------------------------------------------*/ -static const razer_zone mamba_wireless_zone = -{ - "Chroma Zone", - ZONE_TYPE_LINEAR, - 1, - 15 -}; - -static const razer_device mamba_wireless_device = -{ - "Razer Mamba (Wireless)", - DEVICE_TYPE_MOUSE, - false, - 1, - 15, - { - &mamba_wireless_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Mamba Elite | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Left" | -| Linear | -| 9 LEDs | -| | -| Zone "Right" | -| Linear | -| 9 LEDs | -| | -\*-------------------------------------------------------------*/ -static const razer_zone mamba_elite_scroll_wheel_zone = -{ - "Scroll Wheel", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone mamba_elite_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone mamba_elite_left_zone = -{ - "Left LED Strip", - ZONE_TYPE_LINEAR, - 1, - 9 -}; - -static const razer_zone mamba_elite_right_zone = -{ - "Right LED Strip", - ZONE_TYPE_LINEAR, - 1, - 9 -}; - -static const razer_device mamba_elite_device = -{ - "Razer Mamba Elite", - DEVICE_TYPE_MOUSE, - true, - 1, - 20, - { - &mamba_elite_scroll_wheel_zone, - &mamba_elite_logo_zone, - &mamba_elite_left_zone, - &mamba_elite_right_zone, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Mamba Tournament Edition | -| | -| Zone "Left" | -| Linear | -| 7 LEDs | -| | -| Zone "Right" | -| Linear | -| 7 LEDs | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone mamba_te_left_zone = -{ - "Left LED Strip", - ZONE_TYPE_LINEAR, - 1, - 7 -}; - -static const razer_zone mamba_te_right_zone = -{ - "Right LED Strip", - ZONE_TYPE_LINEAR, - 1, - 7 -}; - -static const razer_zone mamba_te_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone mamba_te_scroll_wheel_zone = -{ - "Scroll Wheel", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device mamba_te_device = -{ - "Razer Mamba Tournament Edition", - DEVICE_TYPE_MOUSE, - true, - 1, - 16, - { - &mamba_te_left_zone, - &mamba_te_right_zone, - &mamba_te_logo_zone, - &mamba_te_scroll_wheel_zone, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Mamba Wireless (2018) Wired 1532:0073 | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone mamba_wireless_2018_wired_logo_zone = -{ - "Logo Zone", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone mamba_wireless_2018_wired_scroll_wheel_zone = -{ - "Scroll Wheel Zone", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device mamba_wireless_2018_wired_device = -{ - "Razer Mamba Wireless (Wired)", - DEVICE_TYPE_MOUSE, - true, - 1, - 2, - { - &mamba_wireless_2018_wired_scroll_wheel_zone, - &mamba_wireless_2018_wired_logo_zone, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Mamba Wireless (2018) Wireless 1532:0072 | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ - -static const razer_zone mamba_wireless_2018_wireless_logo_zone = -{ - "Logo Zone", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone mamba_wireless_2018_wireless_scroll_wheel_zone = -{ - "Scroll Wheel Zone", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device mamba_wireless_2018_wireless_device = -{ - "Razer Mamba Wireless (Receiver)", - DEVICE_TYPE_MOUSE, - true, - 1, - 2, - { - &mamba_wireless_2018_wireless_scroll_wheel_zone, - &mamba_wireless_2018_wireless_logo_zone, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Naga Chroma | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -| | -| Zone "Numpad" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone naga_chroma_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone naga_chroma_scroll_wheel_zone = -{ - "Scroll Wheel", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone naga_chroma_numpad_zone = -{ - "Numpad", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device naga_chroma_device = -{ - "Razer Naga Chroma", - DEVICE_TYPE_MOUSE, - false, - 1, - 3, - { - &naga_chroma_logo_zone, - &naga_chroma_scroll_wheel_zone, - &naga_chroma_numpad_zone, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Naga Hex V2 1532:0050 | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -| | -| Zone "Numpad" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone naga_hex_v2_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone naga_hex_v2_scroll_wheel_zone = -{ - "Scroll Wheel", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone naga_hex_v2_numpad_zone = -{ - "Numpad", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device naga_hex_v2_device = -{ - "Razer Naga Hex V2", - DEVICE_TYPE_MOUSE, - false, - 1, - 3, - { - &naga_hex_v2_logo_zone, - &naga_hex_v2_scroll_wheel_zone, - &naga_hex_v2_numpad_zone, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Naga Trinity 1532:0067 | -| | -| Zone "Logo" | -| Single | -| 1 LED | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -| | -| Zone "Numpad" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone naga_trinity_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone naga_trinity_scroll_wheel_zone = -{ - "Scroll Wheel", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone naga_trinity_numpad_zone = -{ - "Numpad", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device naga_trinity_device = -{ - "Razer Naga Trinity", - DEVICE_TYPE_MOUSE, - false, - 1, - 3, - { - &naga_trinity_logo_zone, - &naga_trinity_scroll_wheel_zone, - &naga_trinity_numpad_zone, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Viper Mini 1532:008A | -| | -| Zone "Logo" | -| Matrix | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone viper_mini_logo_zone = -{ - "Logo", //Matrix of one as per https://github.com/openrazer/openrazer/blob/master/daemon/openrazer_daemon/hardware/mouse.py#L27 - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device viper_mini_device = -{ - "Razer Viper Mini", - DEVICE_TYPE_MOUSE, - true, - 1, - 1, - { - &viper_mini_logo_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Viper Ultimate Wired 1532:007A | -| | -| Zone "Logo" | -| Matrix | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone viper_ultimate_wired_logo_zone = -{ - "Logo", //Matrix of one as per https://github.com/openrazer/openrazer/blob/master/daemon/openrazer_daemon/hardware/mouse.py#L1690 - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device viper_ultimate_wired_device = -{ - "Razer Viper Ultimate (Wired)", - DEVICE_TYPE_MOUSE, - true, - 1, - 1, - { - &viper_ultimate_wired_logo_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Viper Ultimate Wireless 1532:007B | -| | -| Zone "Logo" | -| Matrix | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone viper_ultimate_wireless_logo_zone = -{ - "Logo", //Matrix of one as per https://github.com/openrazer/openrazer/blob/master/daemon/openrazer_daemon/hardware/mouse.py#L1690 - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device viper_ultimate_wireless_device = -{ - "Razer Viper Ultimate (Wireless)", - DEVICE_TYPE_MOUSE, - true, - 1, - 1, - { - &viper_ultimate_wireless_logo_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Viper 1532:0078 | -| | -| Zone "Logo" | -| Matrix | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone viper_logo_zone = -{ - "Logo", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device viper_device = -{ - "Razer Viper", - DEVICE_TYPE_MOUSE, - true, - 1, - 1, - { - &viper_logo_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Naga Epic Chroma | -| | -| Zone "Scroll Wheel" | -| Single | -| 1 LED | -| | -| Zone "Numpad" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone naga_epic_chroma_scroll_wheel_zone = -{ - "Scroll Wheel", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone naga_epic_chroma_numpad_zone = -{ - "Numpad", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device naga_epic_chroma_device = -{ - "Razer Naga Epic Chroma", - DEVICE_TYPE_MOUSE, - false, - 1, - 2, - { - &naga_epic_chroma_scroll_wheel_zone, - &naga_epic_chroma_numpad_zone, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------------------*\ -| KEYPADS | -\*-------------------------------------------------------------------------*/ - -/*-------------------------------------------------------------*\ -| Razer Orbweaver Chroma | -| | -| Zone "Keypad" | -| Matrix | -| 4 Rows, 5 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone orbweaver_chroma_zone = -{ - "Keypad", - ZONE_TYPE_MATRIX, - 4, - 5 -}; - -static const razer_device orbweaver_chroma_device = -{ - "Razer Orbweaver Chroma", - DEVICE_TYPE_KEYBOARD, - true, - 4, - 5, - { - &orbweaver_chroma_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Tartarus Chroma | -| | -| Zone "Keypad" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone tartarus_chroma_zone = -{ - "Keypad", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device tartarus_chroma_device = -{ - "Razer Tartarus Chroma", - DEVICE_TYPE_KEYBOARD, - true, - 1, - 1, - { - &tartarus_chroma_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Tartarus V2 1532:0208 | -| | -| Zone "Keypad" | -| Matrix | -| 4 Rows, 5 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone tartarus_v2_zone = -{ - "Keypad", - ZONE_TYPE_MATRIX, - 4, - 5 -}; - -static const razer_device tartarus_v2_device = -{ - "Razer Tartarus V2", - DEVICE_TYPE_KEYBOARD, - true, - 4, - 5, - { - &tartarus_v2_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------------------*\ -| MOUSEMATS | -\*-------------------------------------------------------------------------*/ - -/*-------------------------------------------------------------*\ -| Razer Firefly | -| | -| Zone "LED Strip" | -| Linear | -| 15 LEDs | -\*-------------------------------------------------------------*/ -static const razer_zone firefly_zone = -{ - "LED Strip", - ZONE_TYPE_LINEAR, - 1, - 15 -}; - -static const razer_device firefly_device = -{ - "Razer Firefly", - DEVICE_TYPE_MOUSEMAT, - true, - 1, - 15, - { - &firefly_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Firefly Hyperflux | -| | -| Zone "LED Strip" | -| Linear | -| 1 LEDs | -\*-------------------------------------------------------------*/ -static const razer_zone firefly_hyperflux_zone = -{ - "LED Strip", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device firefly_hyperflux_device = -{ - "Razer Firefly Hyperflux", - DEVICE_TYPE_MOUSEMAT, - true, - 1, - 1, - { - &firefly_hyperflux_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Firefly V2 | -| | -| Zone "LED Strip" | -| Matrix | -| 19 LEDs | -\*-------------------------------------------------------------*/ -static const razer_zone firefly_v2_zone = -{ - "LED Strip", - ZONE_TYPE_LINEAR, - 1, - 19 -}; - -static const razer_device firefly_v2_device = -{ - "Razer Firefly V2", - DEVICE_TYPE_MOUSEMAT, - true, - 1, - 19, - { - &firefly_v2_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Goliathus | -| | -| Zone "LED Strip" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone goliathus_zone = -{ - "LED Strip", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device goliathus_device = -{ - "Razer Goliathus", - DEVICE_TYPE_MOUSEMAT, - true, - 1, - 1, - { - &goliathus_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Goliathus Extended | -| | -| Zone "LED Strip" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone goliathus_extended_zone = -{ - "LED Strip", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device goliathus_extended_device = -{ - "Razer Goliathus Extended", - DEVICE_TYPE_MOUSEMAT, - true, - 1, - 1, - { - &goliathus_extended_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------------------*\ -| HEADSETS | -\*-------------------------------------------------------------------------*/ - -/*-------------------------------------------------------------*\ -| Razer Kraken 7.1 Chroma | -| | -| Zone "Headset" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone kraken_chroma_zone = -{ - "Headset", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device kraken_chroma_device = -{ - "Razer Kraken 7.1 Chroma", - DEVICE_TYPE_HEADSET, - true, - 1, - 1, - { - &kraken_chroma_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Kraken 7.1 V2 | -| | -| Zone "Headset" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone kraken_v2_zone = -{ - "Headset", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device kraken_v2_device = -{ - "Razer Kraken 7.1 V2", - DEVICE_TYPE_HEADSET, - true, - 1, - 1, - { - &kraken_v2_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Kraken Ultimate 1532:0527 | -| | -| Zone "Headset" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone kraken_ultimate_zone = -{ - "Headset", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device kraken_ultimate_device = -{ - "Razer Kraken Ultimate", - DEVICE_TYPE_HEADSET, - true, - 1, - 1, - { - &kraken_ultimate_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Kraken Kitty Edition 1532:0F19 | -| | -| Zone "Headset" | -| Matrix | -| 4 LED | -\*-------------------------------------------------------------*/ -static const razer_zone kraken_kitty_zone = -{ - "Headset", - ZONE_TYPE_LINEAR, - 1, - 4 -}; - -static const razer_device kraken_kitty_device = -{ - "Razer Kraken Kitty Edition", - DEVICE_TYPE_HEADSET, - true, - 1, - 4, - { - &kraken_kitty_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Tiamat 7.1 V2 | -| | -| Zone "Controller" | -| Linear | -| 15 LEDs | -| | -| Zone "Headset Left" | -| Single | -| 1 LED | -| | -| Zone "Headset Right" | -| Single | -| 1 LED | -\*-------------------------------------------------------------*/ -static const razer_zone tiamat_71_v2_controller_zone = -{ - "Controller", - ZONE_TYPE_LINEAR, - 1, - 15 -}; - -static const razer_zone tiamat_71_v2_headset_left_zone = -{ - "Headset Left", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone tiamat_71_v2_headset_right_zone = -{ - "Headset Right", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_device tiamat_71_v2_device = -{ - "Razer Tiamat 7.1 V2", - DEVICE_TYPE_HEADSET, - true, - 1, - 17, - { - &tiamat_71_v2_controller_zone, - &tiamat_71_v2_headset_left_zone, - &tiamat_71_v2_headset_right_zone, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------------------*\ -| OTHER | -\*-------------------------------------------------------------------------*/ - -/*-------------------------------------------------------------*\ -| Razer Core | -| | -| Zone "Side Window Lights" | -| Single | -| 1 LED | -| | -| Zone "LED Strip" | -| Linear | -| 8 LEDs | -\*-------------------------------------------------------------*/ -static const razer_zone core_side_zone = -{ - "Side Window Lights", - ZONE_TYPE_SINGLE, - 1, - 1 -}; - -static const razer_zone core_led_strip_zone = -{ - "LED Strip", - ZONE_TYPE_LINEAR, - 1, - 8 -}; - -static const razer_device core_device = -{ - "Razer Core", - DEVICE_TYPE_UNKNOWN, - true, - 1, - 9, - { - &core_side_zone, - &core_led_strip_zone, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Chroma Mug Holder | -| | -| Zone "LED Strip" | -| Linear | -| 15 LEDs | -\*-------------------------------------------------------------*/ -static const razer_zone mug_holder_zone = -{ - "LED Strip", - ZONE_TYPE_LINEAR, - 1, - 15 -}; - -static const razer_device mug_holder_device = -{ - "Razer Chroma Mug Holder", - DEVICE_TYPE_UNKNOWN, - true, - 1, - 15, - { - &mug_holder_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Chroma HDK | -| | -| Zone "LED Strip" | -| Linear | -| 16 LEDs | -| | -| Zone "LED Strip" | -| Linear | -| 16 LEDs | -| | -| Zone "LED Strip" | -| Linear | -| 16 LEDs | -| | -| Zone "LED Strip" | -| Linear | -| 16 LEDs | -\*-------------------------------------------------------------*/ -static const razer_zone chromahdk_zone_1 = -{ - "Channel 1", - ZONE_TYPE_LINEAR, - 1, - 16 -}; - -static const razer_zone chromahdk_zone_2 = -{ - "Channel 2", - ZONE_TYPE_LINEAR, - 1, - 16 -}; - -static const razer_zone chromahdk_zone_3 = -{ - "Channel 3", - ZONE_TYPE_LINEAR, - 1, - 16 -}; - -static const razer_zone chromahdk_zone_4 = -{ - "Channel 4", - ZONE_TYPE_LINEAR, - 1, - 16 -}; - -static const razer_device chromahdk_device = -{ - "Razer Chroma HDK", - DEVICE_TYPE_LEDSTRIP, - true, - 4, - 16, - { - &chromahdk_zone_1, - &chromahdk_zone_2, - &chromahdk_zone_3, - &chromahdk_zone_4, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Base Station Chroma | -| | -| Zone "LED Strip" | -| Linear | -| 15 LEDs | -\*-------------------------------------------------------------*/ -static const razer_zone base_station_zone = -{ - "LED Strip", - ZONE_TYPE_LINEAR, - 1, - 15 -}; - -static const razer_device base_station_device = -{ - "Razer Base Station Chroma", - DEVICE_TYPE_HEADSET_STAND, - true, - 1, - 15, - { - &base_station_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Nommo Pro | -| | -| Zone "Left Speaker" | -| Linear | -| 8 LEDs | -| | -| Zone "Right Speaker" | -| Linear | -| 8 LEDs | -| | -\*-------------------------------------------------------------*/ -static const razer_zone nommo_pro_left_zone = -{ - "Left Speaker", - ZONE_TYPE_LINEAR, - 1, - 8 -}; - -static const razer_zone nommo_pro_right_zone = -{ - "Right Speaker", - ZONE_TYPE_LINEAR, - 1, - 8 -}; - -static const razer_device nommo_pro_device = -{ - "Razer Nommo Pro", - DEVICE_TYPE_SPEAKER, - true, - 2, - 8, - { - &nommo_pro_left_zone, - &nommo_pro_right_zone, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------*\ -| Razer Nommo Chroma | -| | -| Zone "Right Speaker" | -| Linear | -| 8 LEDs | -| | -| Zone "Left Speaker" | -| Linear | -| 8 LEDs | -| | -\*-------------------------------------------------------------*/ -static const razer_zone nommo_chroma_right_zone = -{ - "Right Speaker", - ZONE_TYPE_LINEAR, - 1, - 24 -}; - -static const razer_zone nommo_chroma_left_zone = -{ - "Left Speaker", - ZONE_TYPE_LINEAR, - 1, - 24 -}; - -static const razer_device nommo_chroma_device = -{ - "Razer Nommo Chroma", - DEVICE_TYPE_SPEAKER, - true, - 2, - 24, - { - &nommo_chroma_right_zone, - &nommo_chroma_left_zone, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0 -}; - -/*-------------------------------------------------------------------------*\ -| DEVICE MASTER LIST | -\*-------------------------------------------------------------------------*/ -#define RAZER_NUM_DEVICES (sizeof(device_list) / sizeof(device_list[ 0 ])) - -static const razer_device* device_list[] = -{ -/*-----------------------------------------------------------------*\ -| KEYBOARDS | -\*-----------------------------------------------------------------*/ - &blackwidow_2019_device, - &blackwidow_chroma_device, - &blackwidow_chroma_overwatch_device, - &blackwidow_chroma_te_device, - &blackwidow_chroma_v2_device, - &blackwidow_elite_device, - &blackwidow_x_chroma_device, - &blackwidow_x_chroma_te_device, - &cynosa_chroma_device, - &cynosa_v2_device, - &cynosa_lite_device, - &deathstalker_chroma_device, - &huntsman_device, - &huntsman_elite_device, - &huntsman_te_device, - &ornata_chroma_device, -/*-----------------------------------------------------------------*\ -| LAPTOPS | -\*-----------------------------------------------------------------*/ - &blade_stealth_device, - &blade_stealth_late_2016_device, - &blade_stealth_mid_2017_device, - &blade_stealth_late_2017_device, - &blade_stealth_2019_device, - &blade_stealth_late_2019_device, - &blade_stealth_early_2020_device, - &blade_late_2016_device, - &blade_qhd_device, - &blade_15_2018_device, - &blade_15_2018_mercury_device, - &blade_15_2018_base_device, - &blade_15_2019_advanced_device, - &blade_15_mid_2019_mercury_device, - &blade_15_mid_2019_base_device, - &blade_15_early_2020_base_device, - &blade_15_studio_2019_device, - &blade_pro_late_2016_device, - &blade_pro_2017_device, - &blade_pro_2017_fullhd_device, - &blade_pro_17_2019_device, - &blade_pro_late_2019_device, - &blade_15_advanced_2020_device, -/*-----------------------------------------------------------------*\ -| MICE | -\*-----------------------------------------------------------------*/ - &abyssus_elite_dva_edition_device, - &abyssus_essential_device, - &basilisk_device, - &deathadder_chroma_device, - &deathadder_elite_device, - &deathadder_essential_device, - &deathadder_essential_white_edition_device, - &deathadder_v2_device, - &diamondback_chroma_device, - &lancehead_te_device, - &lancehead_v2_wired_device, - &lancehead_v2_wireless_device, - &mamba_2012_wired_device, - &mamba_2012_wireless_device, - &mamba_wired_device, - &mamba_wireless_device, - &mamba_te_device, - &mamba_elite_device, - &mamba_wireless_2018_wired_device, - &mamba_wireless_2018_wireless_device, - &naga_chroma_device, - &naga_epic_chroma_device, - &naga_hex_v2_device, - &naga_trinity_device, - &viper_mini_device, - &viper_ultimate_wired_device, - &viper_ultimate_wireless_device, - &viper_device, -/*-----------------------------------------------------------------*\ -| KEYPADS | -\*-----------------------------------------------------------------*/ - &orbweaver_chroma_device, - &tartarus_chroma_device, - &tartarus_v2_device, -/*-----------------------------------------------------------------*\ -| MOUSEMATS | -\*-----------------------------------------------------------------*/ - &firefly_device, - &firefly_hyperflux_device, - &firefly_v2_device, - &goliathus_device, - &goliathus_extended_device, -/*-----------------------------------------------------------------*\ -| HEADSETS | -\*-----------------------------------------------------------------*/ - &kraken_chroma_device, - &kraken_v2_device, - &kraken_ultimate_device, - &kraken_kitty_device, - &tiamat_71_v2_device, -/*-----------------------------------------------------------------*\ -| OTHER | -\*-----------------------------------------------------------------*/ - &core_device, - &mug_holder_device, - &chromahdk_device, - &base_station_device, - &nommo_pro_device, - &nommo_chroma_device -}; diff --git a/Controllers/OpenRazerController/OpenRazerWindowsDetect.cpp b/Controllers/OpenRazerController/OpenRazerWindowsDetect.cpp deleted file mode 100644 index bc092bf5..00000000 --- a/Controllers/OpenRazerController/OpenRazerWindowsDetect.cpp +++ /dev/null @@ -1,293 +0,0 @@ -#include "Detector.h" -#include "LogManager.h" -#include "RGBController.h" -#include "RGBController_OpenRazerWindows.h" -#include -#include -#include -#include - -#include -#include -#include - -#ifdef _WIN64 -#define OPENRAZERDLL "OpenRazer64.dll" -#elif WIN32 -#define OPENRAZERDLL "OpenRazer.dll" -#endif - -typedef struct -{ - struct device_attribute* dev_attr_list[44]; -} device_fn_list_type; - -/*---------------------------------------------------------*\ -| This is a table of device attribute names. It should | -| always match the order of the entries in the structure | -\*---------------------------------------------------------*/ -static const char* device_fn_names[] = -{ - "device_type", - "device_serial", - "firmware_version", - - "matrix_custom_frame", - "matrix_brightness", - - "matrix_effect_custom", - "matrix_effect_none", - "matrix_effect_static", - "matrix_effect_breath", - "matrix_effect_spectrum", - "matrix_effect_reactive", - "matrix_effect_wave", - - "logo_led_brightness", - "logo_matrix_effect_none", - "logo_matrix_effect_static", - "logo_matrix_effect_breath", - "logo_matrix_effect_spectrum", - "logo_matrix_effect_reactive", - - "scroll_led_brightness", - "scroll_matrix_effect_none", - "scroll_matrix_effect_static", - "scroll_matrix_effect_breath", - "scroll_matrix_effect_spectrum", - "scroll_matrix_effect_reactive", - - "left_led_brightness", - "left_matrix_effect_none", - "left_matrix_effect_static", - "left_matrix_effect_breath", - "left_matrix_effect_spectrum", - "left_matrix_effect_reactive", - "left_matrix_effect_wave", - - "right_led_brightness", - "right_matrix_effect_none", - "right_matrix_effect_static", - "right_matrix_effect_breath", - "right_matrix_effect_spectrum", - "right_matrix_effect_reactive", - "right_matrix_effect_wave", - - "logo_led_effect", - "logo_led_rgb", - "logo_led_state", - - "scroll_led_effect", - "scroll_led_rgb", - "scroll_led_state" -}; - -/*---------------------------------------------------------*\ -| This function searches the device attribute list of a | -| given device to fill in a device_fn_type structure | -\*---------------------------------------------------------*/ -static void load_device_fn(device_fn_type* device_fn, device* dev) -{ - memset(device_fn, 0, sizeof(device_fn_type)); - - for (int table_idx = 0; table_idx < 44; table_idx++) - { - for (int list_idx = 0; list_idx < dev->attr_count; list_idx++) - { - if (strcmp(device_fn_names[table_idx], dev->attr_list[list_idx]->name) == 0) - { - ((device_fn_list_type*)device_fn)->dev_attr_list[table_idx] = dev->attr_list[list_idx]; - } - } - } -} - -/******************************************************************************************\ -* * -* DetectOpenRazerControllers * -* * -* Detect devices supported by the OpenRazer kernel drivers * -* * -\******************************************************************************************/ - -void DetectOpenRazerControllers() -{ - static HMODULE module = LoadLibrary(OPENRAZERDLL); - - LOG_DEBUG("[OpenRazerWindows] The %s is %s", OPENRAZERDLL, (module == nullptr)?"not found":"found" ); - - if(module == nullptr) - { - return; - } - - /*---------------------------------------------------------*\ - | Map DLL functions | - \*---------------------------------------------------------*/ - typedef unsigned int(*INITRAZERDRIVER)(struct hid_device** hdev); - - INITRAZERDRIVER init_razer_kbd_driver = reinterpret_cast(GetProcAddress(module, "init_razer_kbd_driver")); - INITRAZERDRIVER init_razer_mousemat_driver = reinterpret_cast(GetProcAddress(module, "init_razer_mousemat_driver")); - INITRAZERDRIVER init_razer_mouse_driver = reinterpret_cast(GetProcAddress(module, "init_razer_mouse_driver")); - INITRAZERDRIVER init_razer_accessory_driver = reinterpret_cast(GetProcAddress(module, "init_razer_accessory_driver")); - INITRAZERDRIVER init_razer_kraken_driver = reinterpret_cast(GetProcAddress(module, "init_razer_kraken_driver")); - INITRAZERDRIVER init_razer_core_driver = reinterpret_cast(GetProcAddress(module, "init_razer_core_driver")); - - /*---------------------------------------------------------*\ - | Initialize all OpenRazer driver modules and store devices | - \*---------------------------------------------------------*/ - struct hid_device* hdev; - unsigned int num; - - if(init_razer_kbd_driver != NULL) - { - hdev = NULL; - num = init_razer_kbd_driver(&hdev); - for (unsigned int i = 0; i < num; i++) - { - if (hdev[i].dev.attr_count < 1) continue; - - device_fn_type* device_fn = new device_fn_type; - load_device_fn(device_fn, &hdev[i].dev); - - RGBController_OpenRazer * razer_rgb = new RGBController_OpenRazer(&hdev[i].dev, device_fn); - - if(razer_rgb->device_index != -1) - { - ResourceManager::get()->RegisterRGBController(razer_rgb); - } - else - { - delete razer_rgb; - } - } - } - - if(init_razer_mouse_driver != NULL) - { - hdev = NULL; - num = init_razer_mouse_driver(&hdev); - for (unsigned int i = 0; i < num; i++) - { - if (hdev[i].dev.attr_count < 1) continue; - - device_fn_type* device_fn = new device_fn_type; - load_device_fn(device_fn, &hdev[i].dev); - - RGBController_OpenRazer * razer_rgb = new RGBController_OpenRazer(&hdev[i].dev, device_fn); - - if(razer_rgb->device_index != -1) - { - ResourceManager::get()->RegisterRGBController(razer_rgb); - } - else - { - LOG_DEBUG("[OpenRazerWindows] Device index is not -1 delete controller"); - delete razer_rgb; - } - } - } - - if(init_razer_mousemat_driver != NULL) - { - hdev = NULL; - num = init_razer_mousemat_driver(&hdev); - for (unsigned int i = 0; i < num; i++) - { - if (hdev[i].dev.attr_count < 1) continue; - - device_fn_type* device_fn = new device_fn_type; - load_device_fn(device_fn, &hdev[i].dev); - - RGBController_OpenRazer * razer_rgb = new RGBController_OpenRazer(&hdev[i].dev, device_fn); - - if(razer_rgb->device_index != -1) - { - ResourceManager::get()->RegisterRGBController(razer_rgb); - } - else - { - LOG_DEBUG("[OpenRazerWindows] Device index is not -1 delete controller"); - delete razer_rgb; - } - } - } - - if(init_razer_accessory_driver != NULL) - { - hdev = NULL; - num = init_razer_accessory_driver(&hdev); - for (unsigned int i = 0; i < num; i++) - { - if (hdev[i].dev.attr_count < 1) continue; - - device_fn_type* device_fn = new device_fn_type; - load_device_fn(device_fn, &hdev[i].dev); - - RGBController_OpenRazer * razer_rgb = new RGBController_OpenRazer(&hdev[i].dev, device_fn); - - if(razer_rgb->device_index != -1) - { - ResourceManager::get()->RegisterRGBController(razer_rgb); - } - else - { - LOG_DEBUG("[OpenRazerWindows] Device index is not -1 delete controller"); - delete razer_rgb; - } - } - } - - if(init_razer_kraken_driver != NULL) - { - hdev = NULL; - num = init_razer_kraken_driver(&hdev); - for (unsigned int i = 0; i < num; i++) - { - if (hdev[i].dev.attr_count < 1) continue; - - device_fn_type* device_fn = new device_fn_type; - load_device_fn(device_fn, &hdev[i].dev); - - RGBController_OpenRazer * razer_rgb = new RGBController_OpenRazer(&hdev[i].dev, device_fn); - - if(razer_rgb->device_index != -1) - { - ResourceManager::get()->RegisterRGBController(razer_rgb); - } - else - { - LOG_DEBUG("[OpenRazerWindows] Device index is not -1 delete controller"); - delete razer_rgb; - } - } - } - - if(init_razer_core_driver != NULL) - { - hdev = NULL; - num = init_razer_core_driver(&hdev); - for (unsigned int i = 0; i < num; i++) - { - if (hdev[i].dev.attr_count < 1) continue; - - device_fn_type* device_fn = new device_fn_type; - load_device_fn(device_fn, &hdev[i].dev); - - RGBController_OpenRazer * razer_rgb = new RGBController_OpenRazer(&hdev[i].dev, device_fn); - - if(razer_rgb->device_index != -1) - { - ResourceManager::get()->RegisterRGBController(razer_rgb); - } - else - { - LOG_DEBUG("[OpenRazerWindows] Device index is not -1 delete controller"); - delete razer_rgb; - } - } - } - -} /* DetectOpenRazerControllers() */ - -REGISTER_DETECTOR("OpenRazer-Win32", DetectOpenRazerControllers); diff --git a/Controllers/OpenRazerController/RGBController_OpenRazer.cpp b/Controllers/OpenRazerController/RGBController_OpenRazer.cpp deleted file mode 100644 index 23392cf6..00000000 --- a/Controllers/OpenRazerController/RGBController_OpenRazer.cpp +++ /dev/null @@ -1,1106 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_OpenRazer.cpp | -| | -| Generic RGB Interface for OpenRazer | -| kernel drivers for Chroma peripherals | -| | -| Adam Honse (CalcProgrammer1) 6/15/2019 | -\*-----------------------------------------*/ - -#include "RGBController_OpenRazer.h" -#include "OpenRazerDevices.h" - -#include -#include - -using namespace std::chrono_literals; - -void RGBController_OpenRazer::DeviceUpdateLEDs() -{ - - switch(matrix_type) - { - case RAZER_TYPE_MATRIX_FRAME: - case RAZER_TYPE_MATRIX_NOFRAME: - case RAZER_TYPE_MATRIX_STATIC: - { - char update_value = 1; - - for (unsigned int row = 0; row < matrix_rows; row++) - { - unsigned int output_array_size; - unsigned int output_offset; - unsigned int row_offset = (row * matrix_cols); - - if(matrix_type == RAZER_TYPE_MATRIX_FRAME) - { - output_array_size = 3 + (matrix_cols* 3); - output_offset = 3; - } - else - { - output_array_size = 3; - output_offset = 0; - } - - char* output_array = new char[output_array_size]; - - if(matrix_type == RAZER_TYPE_MATRIX_FRAME) - { - output_array[0] = row; - output_array[1] = 0; - output_array[2] = matrix_cols - 1; - } - - for(unsigned int col = 0; col < matrix_cols; col++) - { - unsigned int color_idx = col + row_offset; - output_array[(col * 3) + 0 + output_offset] = (char)RGBGetRValue(colors[color_idx]); - output_array[(col * 3) + 1 + output_offset] = (char)RGBGetGValue(colors[color_idx]); - output_array[(col * 3) + 2 + output_offset] = (char)RGBGetBValue(colors[color_idx]); - } - - if(matrix_type == RAZER_TYPE_MATRIX_FRAME) - { - matrix_custom_frame.write(output_array, output_array_size); - matrix_custom_frame.flush(); - } - else if(matrix_type == RAZER_TYPE_MATRIX_NOFRAME) - { - matrix_effect_custom.write(output_array, output_array_size); - matrix_effect_custom.flush(); - } - else - { - matrix_effect_static.write(output_array, output_array_size); - matrix_effect_static.flush(); - } - - delete[] output_array; - - std::this_thread::sleep_for(1ms); - } - - if(matrix_type == RAZER_TYPE_MATRIX_FRAME) - { - matrix_effect_custom.write(&update_value, 1); - matrix_effect_custom.flush(); - } - } - break; - - case RAZER_TYPE_NOMATRIX: - { - DeviceUpdateMode(); - } - break; - } -} - -void RGBController_OpenRazer::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_OpenRazer::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_OpenRazer::SetupMatrixDevice(unsigned int rows, unsigned int cols) -{ - if(!matrix_custom_frame) - { - if(!matrix_effect_custom) - { - matrix_type = RAZER_TYPE_MATRIX_STATIC; - } - else - { - matrix_type = RAZER_TYPE_MATRIX_NOFRAME; - } - - matrix_rows = 1; - matrix_cols = 1; - } - else - { - matrix_type = RAZER_TYPE_MATRIX_FRAME; - - matrix_rows = rows; - matrix_cols = cols; - } -} - -void RGBController_OpenRazer::SetupNonMatrixDevice() -{ - matrix_type = RAZER_TYPE_NOMATRIX; -} - -void RGBController_OpenRazer::OpenFunctions(std::string dev_path) -{ - device_type.open( dev_path + "/device_type"); - device_serial.open( dev_path + "/device_serial"); - firmware_version.open( dev_path + "/firmware_version"); - - matrix_custom_frame.open( dev_path + "/matrix_custom_frame"); - matrix_brightness.open( dev_path + "/matrix_brightness"); - - matrix_effect_custom.open( dev_path + "/matrix_effect_custom"); - matrix_effect_none.open( dev_path + "/matrix_effect_none"); - matrix_effect_static.open( dev_path + "/matrix_effect_static"); - matrix_effect_breath.open( dev_path + "/matrix_effect_breath"); - matrix_effect_spectrum.open( dev_path + "/matrix_effect_spectrum"); - matrix_effect_reactive.open( dev_path + "/matrix_effect_reactive"); - matrix_effect_wave.open( dev_path + "/matrix_effect_wave"); - - logo_led_brightness.open( dev_path + "/logo_led_brightness"); - logo_matrix_effect_none.open( dev_path + "/logo_matrix_effect_none"); - logo_matrix_effect_static.open( dev_path + "/logo_matrix_effect_static"); - logo_matrix_effect_breath.open( dev_path + "/logo_matrix_effect_breath"); - logo_matrix_effect_spectrum.open( dev_path + "/logo_matrix_effect_spectrum"); - logo_matrix_effect_reactive.open( dev_path + "/logo_matrix_effect_reactive"); - - scroll_led_brightness.open( dev_path + "/scroll_led_brightness"); - scroll_matrix_effect_none.open( dev_path + "/scroll_matrix_effect_none"); - scroll_matrix_effect_static.open( dev_path + "/scroll_matrix_effect_static"); - scroll_matrix_effect_breath.open( dev_path + "/scroll_matrix_effect_breath"); - scroll_matrix_effect_spectrum.open(dev_path + "/scroll_matrix_effect_spectrum"); - scroll_matrix_effect_reactive.open(dev_path + "/scroll_matrix_effect_reactive"); - - left_led_brightness.open( dev_path + "/left_led_brightness"); - left_matrix_effect_none.open( dev_path + "/left_matrix_effect_none"); - left_matrix_effect_static.open( dev_path + "/left_matrix_effect_static"); - left_matrix_effect_breath.open( dev_path + "/left_matrix_effect_breath"); - left_matrix_effect_spectrum.open( dev_path + "/left_matrix_effect_spectrum"); - left_matrix_effect_reactive.open( dev_path + "/left_matrix_effect_reactive"); - left_matrix_effect_wave.open( dev_path + "/left_matrix_effect_wave"); - - right_led_brightness.open( dev_path + "/right_led_brightness"); - right_matrix_effect_none.open( dev_path + "/right_matrix_effect_none"); - right_matrix_effect_static.open( dev_path + "/right_matrix_effect_static"); - right_matrix_effect_breath.open( dev_path + "/right_matrix_effect_breath"); - right_matrix_effect_spectrum.open( dev_path + "/right_matrix_effect_spectrum"); - right_matrix_effect_reactive.open( dev_path + "/right_matrix_effect_reactive"); - right_matrix_effect_wave.open( dev_path + "/right_matrix_effect_wave"); - - backlight_led_effect.open( dev_path + "/backlight_led_effect"); - backlight_led_rgb.open( dev_path + "/backlight_led_rgb"); - backlight_led_state.open( dev_path + "/backlight_led_state"); - - logo_led_effect.open( dev_path + "/logo_led_effect"); - logo_led_rgb.open( dev_path + "/logo_led_rgb"); - logo_led_state.open( dev_path + "/logo_led_state"); - - scroll_led_effect.open( dev_path + "/scroll_led_effect"); - scroll_led_rgb.open( dev_path + "/scroll_led_rgb"); - scroll_led_state.open( dev_path + "/scroll_led_state"); - - /*-----------------------------------------------------------------*\ - | The Naga Chroma (and possibly others) expose a useless | - | matrix_effect_custom interface because they use the matrix_ name | - | for the keypad LED. Close this useless interface in this case. | - | We can detect this when there is a logo matrix or scroll matrix | - | at the same time as matrix_effect_custom. | - \*-----------------------------------------------------------------*/ - if((logo_matrix_effect_none || scroll_matrix_effect_none) && matrix_effect_custom) - { - matrix_effect_custom.close(); - matrix_effect_custom.setstate(std::ios::failbit); - } -} - -/**------------------------------------------------------------------*\ - @name Openrazer - @category Keyboard,Mouse,Mousemat,HeadsetStand - @type USB - @save :x: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectOpenRazerControllers - @comment The Openrazer controller has been deprecated in favour of - the in built Razer controller. -\*-------------------------------------------------------------------*/ - -RGBController_OpenRazer::RGBController_OpenRazer(std::string dev_path) -{ - /*-----------------------------------------------------------------*\ - | Open the OpenRazer device functions | - \*-----------------------------------------------------------------*/ - OpenFunctions(dev_path); - - /*-----------------------------------------------------------------*\ - | Start device at -1. This indicates the device was not detected | - \*-----------------------------------------------------------------*/ - device_index = -1; - - /*-----------------------------------------------------------------*\ - | Get the device name from the OpenRazer driver | - \*-----------------------------------------------------------------*/ - std::getline(device_type, name); - - /*-----------------------------------------------------------------*\ - | Set the description to indicate this is an OpenRazer device | - \*-----------------------------------------------------------------*/ - description = "OpenRazer Device"; - - /*-----------------------------------------------------------------*\ - | Set the device path as the location | - \*-----------------------------------------------------------------*/ - location = dev_path; - - /*-----------------------------------------------------------------*\ - | Get the serial number from the dev path | - \*-----------------------------------------------------------------*/ - std::getline(device_serial, serial); - - /*-----------------------------------------------------------------*\ - | Get the firmware version from the dev path | - \*-----------------------------------------------------------------*/ - std::getline(firmware_version, version); - - /*-----------------------------------------------------------------*\ - | Vendor is always Razer | - \*-----------------------------------------------------------------*/ - vendor = "Razer"; - - /*-----------------------------------------------------------------*\ - | Loop through all known devices to look for a name match | - \*-----------------------------------------------------------------*/ - for (std::size_t i = 0; i < RAZER_NUM_DEVICES; i++) - { - if (device_list[i]->name == name) - { - /*---------------------------------------------------------*\ - | Set device ID | - \*---------------------------------------------------------*/ - device_index = i; - - /*---------------------------------------------------------*\ - | Set device type | - \*---------------------------------------------------------*/ - type = device_list[i]->type; - - /*---------------------------------------------------------*\ - | Device has Direct mode if matrix_custom_frame exists | - \*---------------------------------------------------------*/ - if(matrix_effect_custom) - { - mode Direct; - Direct.name = "Direct"; - Direct.value = RAZER_MODE_CUSTOM; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - } - - /*---------------------------------------------------------*\ - | Device has Off mode if any _effect_none or any _state | - | exists | - \*---------------------------------------------------------*/ - if( matrix_effect_none - || logo_matrix_effect_none - || scroll_matrix_effect_none - || left_matrix_effect_none - || right_matrix_effect_none - || backlight_led_state - || logo_led_state - || scroll_led_state) - { - mode Off; - Off.name = "Off"; - Off.value = RAZER_MODE_OFF; - Off.flags = 0; - Off.color_mode = MODE_COLORS_NONE; - modes.push_back(Off); - } - - /*---------------------------------------------------------*\ - | Device has Static mode if any _effect_static or any | - | _effect exists | - \*---------------------------------------------------------*/ - if( matrix_effect_static - || logo_matrix_effect_static - || scroll_matrix_effect_static - || left_matrix_effect_static - || right_matrix_effect_static - || backlight_led_effect - || logo_led_effect - || scroll_led_effect) - { - mode Static; - Static.name = "Static"; - Static.value = RAZER_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Static.colors_min = 1; - Static.colors_max = 1; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; - Static.colors.resize(1); - modes.push_back(Static); - } - - /*---------------------------------------------------------*\ - | Device has Breathing mode if any _effect_breath exists | - \*---------------------------------------------------------*/ - if( matrix_effect_breath - || logo_matrix_effect_breath - || scroll_matrix_effect_breath - || left_matrix_effect_breath - || right_matrix_effect_breath) - { - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = RAZER_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; - Breathing.colors_min = 1; - Breathing.colors_max = 2; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.colors.resize(1); - modes.push_back(Breathing); - } - - /*---------------------------------------------------------*\ - | Device has limited Breathing mode if any _effect exists | - \*---------------------------------------------------------*/ - if( backlight_led_effect - || logo_led_effect - || scroll_led_effect) - { - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = RAZER_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Breathing.colors_min = 1; - Breathing.colors_max = 1; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.colors.resize(1); - modes.push_back(Breathing); - } - - /*---------------------------------------------------------*\ - | Device has Flashing mode if any _effect exists | - \*---------------------------------------------------------*/ - if( backlight_led_effect - || logo_led_effect - || scroll_led_effect) - { - mode Flashing; - Flashing.name = "Flashing"; - Flashing.value = RAZER_MODE_FLASHING; - Flashing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Flashing.colors_min = 1; - Flashing.colors_max = 1; - Flashing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Flashing.colors.resize(1); - modes.push_back(Flashing); - } - - /*---------------------------------------------------------*\ - | Device has Spectrum Cycle mode if any _effect_spectrum or | - | _effect exists | - \*---------------------------------------------------------*/ - if( matrix_effect_spectrum - || logo_matrix_effect_spectrum - || scroll_matrix_effect_spectrum - || left_matrix_effect_spectrum - || right_matrix_effect_spectrum - || backlight_led_effect - || logo_led_effect - || scroll_led_effect) - { - mode SpectrumCycle; - SpectrumCycle.name = "Spectrum Cycle"; - SpectrumCycle.value = RAZER_MODE_SPECTRUM_CYCLE; - SpectrumCycle.flags = 0; - SpectrumCycle.color_mode = MODE_COLORS_NONE; - modes.push_back(SpectrumCycle); - } - - /*---------------------------------------------------------*\ - | Device has Wave mode if any _effect_wave exists | - \*---------------------------------------------------------*/ - if( matrix_effect_wave - || left_matrix_effect_wave - || right_matrix_effect_wave) - { - mode Wave; - Wave.name = "Wave"; - Wave.value = RAZER_MODE_WAVE; - Wave.flags = MODE_FLAG_HAS_DIRECTION_LR; - Wave.direction = MODE_DIRECTION_RIGHT; - Wave.color_mode = MODE_COLORS_NONE; - modes.push_back(Wave); - } - - /*---------------------------------------------------------*\ - | Device has Reactive mode if any _effect_reactive exists | - \*---------------------------------------------------------*/ - if( matrix_effect_reactive - || logo_matrix_effect_reactive - || scroll_matrix_effect_reactive - || left_matrix_effect_reactive - || right_matrix_effect_reactive) - { - mode Reactive; - Reactive.name = "Reactive"; - Reactive.value = RAZER_MODE_REACTIVE; - Reactive.flags = 0; - Reactive.color_mode = MODE_COLORS_NONE; - modes.push_back(Reactive); - } - - /*---------------------------------------------------------*\ - | Initialize file descriptors | - \*---------------------------------------------------------*/ - if(device_list[i]->matrix_type == true) - { - SetupMatrixDevice(device_list[i]->rows, device_list[i]->cols); - } - else - { - SetupNonMatrixDevice(); - } - - SetupZones(); - } - } -} - -RGBController_OpenRazer::~RGBController_OpenRazer() -{ - /*---------------------------------------------------------*\ - | Delete the matrix map | - \*---------------------------------------------------------*/ - for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++) - { - if(zones[zone_index].matrix_map != NULL) - { - if(zones[zone_index].matrix_map->map != NULL) - { - delete zones[zone_index].matrix_map->map; - } - - delete zones[zone_index].matrix_map; - } - } -} - -void RGBController_OpenRazer::SetupZones() -{ - /*---------------------------------------------------------*\ - | Fill in zone information based on device table | - \*---------------------------------------------------------*/ - for(unsigned int zone_id = 0; zone_id < RAZER_MAX_ZONES; zone_id++) - { - if(device_list[device_index]->zones[zone_id] != NULL) - { - zone new_zone; - - new_zone.name = device_list[device_index]->zones[zone_id]->name; - new_zone.type = device_list[device_index]->zones[zone_id]->type; - - new_zone.leds_count = device_list[device_index]->zones[zone_id]->rows * device_list[device_index]->zones[zone_id]->cols; - new_zone.leds_min = new_zone.leds_count; - new_zone.leds_max = new_zone.leds_count; - - if(new_zone.type == ZONE_TYPE_MATRIX) - { - matrix_map_type * new_map = new matrix_map_type; - new_zone.matrix_map = new_map; - - new_map->height = device_list[device_index]->zones[zone_id]->rows; - new_map->width = device_list[device_index]->zones[zone_id]->cols; - - new_map->map = new unsigned int[new_map->height * new_map->width]; - - for(unsigned int y = 0; y < new_map->height; y++) - { - for(unsigned int x = 0; x < new_map->width; x++) - { - new_map->map[(y * new_map->width) + x] = (y * new_map->width) + x; - } - } - } - else - { - new_zone.matrix_map = NULL; - } - - zones.push_back(new_zone); - } - } - - for(unsigned int zone_id = 0; zone_id < zones.size(); zone_id++) - { - for (unsigned int row_id = 0; row_id < device_list[device_index]->zones[zone_id]->rows; row_id++) - { - for (unsigned int col_id = 0; col_id < device_list[device_index]->zones[zone_id]->cols; col_id++) - { - led* new_led = new led(); - - new_led->name = device_list[device_index]->zones[zone_id]->name; - - if(zones[zone_id].leds_count > 1) - { - new_led->name.append(" LED "); - new_led->name.append(std::to_string(col_id + 1)); - } - - if(device_list[device_index]->keymap != NULL) - { - for(unsigned int i = 0; i < device_list[device_index]->keymap_size; i++) - { - if(zone_id == device_list[device_index]->keymap[i].zone && - row_id == device_list[device_index]->keymap[i].row && - col_id == device_list[device_index]->keymap[i].col) - { - new_led->name = device_list[device_index]->keymap[i].name; - } - } - } - - leds.push_back(*new_led); - } - } - } - - SetupColors(); -} - -void RGBController_OpenRazer::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_OpenRazer::SetCustomMode() -{ - /*---------------------------------------------------------*\ - | If device supports custom mode, it will be mode index 0 | - \*---------------------------------------------------------*/ - if(modes[0].value == RAZER_MODE_CUSTOM) - { - active_mode = 0; - } - /*---------------------------------------------------------*\ - | If not, use static mode. | - \*---------------------------------------------------------*/ - else - { - for(unsigned int i = 0; i < modes.size(); i++) - { - if(modes[i].value == RAZER_MODE_STATIC) - { - active_mode = i; - break; - } - } - } -} - -void RGBController_OpenRazer::DeviceUpdateMode() -{ - char update_value[6]; - char effect_value[1]; - - update_value[0] = 1; - - switch(modes[active_mode].value) - { - case RAZER_MODE_CUSTOM: - if(matrix_effect_custom) - { - matrix_effect_custom.write(update_value, 1); - matrix_effect_custom.flush(); - } - break; - - case RAZER_MODE_OFF: - if(matrix_effect_none) - { - matrix_effect_none.write(update_value, 1); - matrix_effect_none.flush(); - } - - if(logo_matrix_effect_none) - { - logo_matrix_effect_none.write(update_value, 1); - logo_matrix_effect_none.flush(); - } - - if(scroll_matrix_effect_none) - { - scroll_matrix_effect_none.write(update_value, 1); - scroll_matrix_effect_none.flush(); - } - - if(left_matrix_effect_none) - { - left_matrix_effect_none.write(update_value, 1); - left_matrix_effect_none.flush(); - } - - if(right_matrix_effect_none) - { - right_matrix_effect_none.write(update_value, 1); - right_matrix_effect_none.flush(); - } - - if(backlight_led_state) - { - update_value[0] = '0'; - backlight_led_state.write(update_value, 1); - backlight_led_state.flush(); - } - - if(logo_led_state) - { - update_value[0] = '0'; - logo_led_state.write(update_value, 1); - logo_led_state.flush(); - } - - if(scroll_led_state) - { - update_value[0] = '0'; - scroll_led_state.write(update_value, 1); - scroll_led_state.flush(); - } - break; - - case RAZER_MODE_STATIC: - effect_value[0] = '0'; - - if(backlight_led_state) - { - update_value[0] = '1'; - backlight_led_state.write(update_value, 1); - backlight_led_state.flush(); - } - - if(logo_led_state) - { - update_value[0] = '1'; - logo_led_state.write(update_value, 1); - logo_led_state.flush(); - } - - if(scroll_led_state) - { - update_value[0] = '1'; - scroll_led_state.write(update_value, 1); - scroll_led_state.flush(); - } - - update_value[0] = RGBGetRValue(modes[active_mode].colors[0]); - update_value[1] = RGBGetGValue(modes[active_mode].colors[0]); - update_value[2] = RGBGetBValue(modes[active_mode].colors[0]); - - if(matrix_effect_static) - { - matrix_effect_static.write(update_value, 3); - matrix_effect_static.flush(); - } - - if(logo_matrix_effect_static) - { - logo_matrix_effect_static.write(update_value, 3); - logo_matrix_effect_static.flush(); - } - - if(scroll_matrix_effect_static) - { - scroll_matrix_effect_static.write(update_value, 3); - scroll_matrix_effect_static.flush(); - } - - if(left_matrix_effect_static) - { - left_matrix_effect_static.write(update_value, 3); - left_matrix_effect_static.flush(); - } - - if(right_matrix_effect_static) - { - right_matrix_effect_static.write(update_value, 3); - right_matrix_effect_static.flush(); - } - - if(backlight_led_effect && backlight_led_rgb) - { - backlight_led_rgb.write(update_value, 3); - backlight_led_rgb.flush(); - backlight_led_effect.write(effect_value, 1); - backlight_led_effect.flush(); - } - - if(logo_led_effect && logo_led_rgb) - { - logo_led_rgb.write(update_value, 3); - logo_led_rgb.flush(); - logo_led_effect.write(effect_value, 1); - logo_led_effect.flush(); - } - - if(scroll_led_effect && scroll_led_rgb) - { - scroll_led_rgb.write(update_value, 3); - scroll_led_rgb.flush(); - scroll_led_effect.write(effect_value, 1); - scroll_led_effect.flush(); - } - break; - - case RAZER_MODE_FLASHING: - effect_value[0] = '1'; - - if(backlight_led_state) - { - update_value[0] = '1'; - backlight_led_state.write(update_value, 1); - backlight_led_state.flush(); - } - - if(logo_led_state) - { - update_value[0] = '1'; - logo_led_state.write(update_value, 1); - logo_led_state.flush(); - } - - if(scroll_led_state) - { - update_value[0] = '1'; - scroll_led_state.write(update_value, 1); - scroll_led_state.flush(); - } - - update_value[0] = RGBGetRValue(modes[active_mode].colors[0]); - update_value[1] = RGBGetGValue(modes[active_mode].colors[0]); - update_value[2] = RGBGetBValue(modes[active_mode].colors[0]); - - if(backlight_led_effect && backlight_led_rgb) - { - backlight_led_rgb.write(update_value, 3); - backlight_led_rgb.flush(); - backlight_led_effect.write(effect_value, 1); - backlight_led_effect.flush(); - } - - if(logo_led_effect && logo_led_rgb) - { - logo_led_rgb.write(update_value, 3); - logo_led_rgb.flush(); - logo_led_effect.write(effect_value, 1); - logo_led_effect.flush(); - } - - if(scroll_led_effect && scroll_led_rgb) - { - scroll_led_rgb.write(update_value, 3); - scroll_led_rgb.flush(); - scroll_led_effect.write(effect_value, 1); - scroll_led_effect.flush(); - } - break; - - case RAZER_MODE_BREATHING: - effect_value[0] = '2'; - - switch(modes[active_mode].color_mode) - { - case MODE_COLORS_MODE_SPECIFIC: - if(backlight_led_state) - { - update_value[0] = '1'; - backlight_led_state.write(update_value, 1); - backlight_led_state.flush(); - } - - if(logo_led_state) - { - update_value[0] = '1'; - logo_led_state.write(update_value, 1); - logo_led_state.flush(); - } - - if(scroll_led_state) - { - update_value[0] = '1'; - scroll_led_state.write(update_value, 1); - scroll_led_state.flush(); - } - - update_value[0] = RGBGetRValue(modes[active_mode].colors[0]); - update_value[1] = RGBGetGValue(modes[active_mode].colors[0]); - update_value[2] = RGBGetBValue(modes[active_mode].colors[0]); - - if(modes[active_mode].colors.size() == 2) - { - update_value[3] = RGBGetRValue(modes[active_mode].colors[1]); - update_value[4] = RGBGetGValue(modes[active_mode].colors[1]); - update_value[5] = RGBGetBValue(modes[active_mode].colors[1]); - - if(matrix_effect_breath) - { - matrix_effect_breath.write(update_value, 6); - matrix_effect_breath.flush(); - } - - if(logo_matrix_effect_breath) - { - logo_matrix_effect_breath.write(update_value, 6); - logo_matrix_effect_breath.flush(); - } - - if(scroll_matrix_effect_breath) - { - scroll_matrix_effect_breath.write(update_value, 6); - scroll_matrix_effect_breath.flush(); - } - - if(left_matrix_effect_breath) - { - left_matrix_effect_breath.write(update_value, 6); - left_matrix_effect_breath.flush(); - } - - if(right_matrix_effect_breath) - { - right_matrix_effect_breath.write(update_value, 6); - right_matrix_effect_breath.flush(); - } - } - else - { - if(matrix_effect_breath) - { - matrix_effect_breath.write(update_value, 3); - matrix_effect_breath.flush(); - } - - if(logo_matrix_effect_breath) - { - logo_matrix_effect_breath.write(update_value, 3); - logo_matrix_effect_breath.flush(); - } - - if(scroll_matrix_effect_breath) - { - scroll_matrix_effect_breath.write(update_value, 3); - scroll_matrix_effect_breath.flush(); - } - - if(left_matrix_effect_breath) - { - left_matrix_effect_breath.write(update_value, 3); - left_matrix_effect_breath.flush(); - } - - if(right_matrix_effect_breath) - { - right_matrix_effect_breath.write(update_value, 3); - right_matrix_effect_breath.flush(); - } - - if(backlight_led_effect && backlight_led_rgb) - { - backlight_led_rgb.write(update_value, 3); - backlight_led_rgb.flush(); - backlight_led_effect.write(effect_value, 1); - backlight_led_effect.flush(); - } - - if(logo_led_effect && logo_led_rgb) - { - logo_led_rgb.write(update_value, 3); - logo_led_rgb.flush(); - logo_led_effect.write(effect_value, 1); - logo_led_effect.flush(); - } - - if(scroll_led_effect && scroll_led_rgb) - { - scroll_led_rgb.write(update_value, 3); - scroll_led_rgb.flush(); - scroll_led_effect.write(effect_value, 1); - scroll_led_effect.flush(); - } - } - break; - - case MODE_COLORS_RANDOM: - if(matrix_effect_breath) - { - matrix_effect_breath.write(update_value, 1); - matrix_effect_breath.flush(); - } - - if(logo_matrix_effect_breath) - { - logo_matrix_effect_breath.write(update_value, 1); - logo_matrix_effect_breath.flush(); - } - - if(scroll_matrix_effect_breath) - { - scroll_matrix_effect_breath.write(update_value, 1); - scroll_matrix_effect_breath.flush(); - } - - if(left_matrix_effect_breath) - { - left_matrix_effect_breath.write(update_value, 1); - left_matrix_effect_breath.flush(); - } - - if(right_matrix_effect_breath) - { - right_matrix_effect_breath.write(update_value, 1); - right_matrix_effect_breath.flush(); - } - - break; - } - break; - - case RAZER_MODE_SPECTRUM_CYCLE: - effect_value[0] = '4'; - - if(backlight_led_state) - { - update_value[0] = '1'; - backlight_led_state.write(update_value, 1); - backlight_led_state.flush(); - } - - if(logo_led_state) - { - update_value[0] = '1'; - logo_led_state.write(update_value, 1); - logo_led_state.flush(); - } - - if(scroll_led_state) - { - update_value[0] = '1'; - scroll_led_state.write(update_value, 1); - scroll_led_state.flush(); - } - - if(matrix_effect_spectrum) - { - matrix_effect_spectrum.write(update_value, 1); - matrix_effect_spectrum.flush(); - } - - if(logo_matrix_effect_spectrum) - { - logo_matrix_effect_spectrum.write(update_value, 1); - logo_matrix_effect_spectrum.flush(); - } - - if(scroll_matrix_effect_spectrum) - { - scroll_matrix_effect_spectrum.write(update_value, 1); - scroll_matrix_effect_spectrum.flush(); - } - - if(left_matrix_effect_spectrum) - { - left_matrix_effect_spectrum.write(update_value, 1); - left_matrix_effect_spectrum.flush(); - } - - if(right_matrix_effect_spectrum) - { - right_matrix_effect_spectrum.write(update_value, 1); - right_matrix_effect_spectrum.flush(); - } - - if(backlight_led_effect) - { - backlight_led_effect.write(effect_value, 1); - backlight_led_effect.flush(); - } - - if(logo_led_effect) - { - logo_led_effect.write(effect_value, 1); - logo_led_effect.flush(); - } - - if(scroll_led_effect) - { - scroll_led_effect.write(effect_value, 1); - scroll_led_effect.flush(); - } - break; - - case RAZER_MODE_WAVE: - switch(modes[active_mode].direction) - { - case MODE_DIRECTION_LEFT: - update_value[0] = '2'; - break; - - default: - update_value[0] = '1'; - break; - } - - if(matrix_effect_wave) - { - matrix_effect_wave.write(update_value, 1); - matrix_effect_wave.flush(); - } - - if(left_matrix_effect_wave) - { - left_matrix_effect_wave.write(update_value, 1); - left_matrix_effect_wave.flush(); - } - - if(right_matrix_effect_wave) - { - right_matrix_effect_wave.write(update_value, 1); - right_matrix_effect_wave.flush(); - } - break; - - case RAZER_MODE_REACTIVE: - if(matrix_effect_reactive) - { - matrix_effect_reactive.write(update_value, 1); - matrix_effect_reactive.flush(); - } - - if(logo_matrix_effect_reactive) - { - logo_matrix_effect_reactive.write(update_value, 1); - logo_matrix_effect_reactive.flush(); - } - - if(scroll_matrix_effect_reactive) - { - scroll_matrix_effect_reactive.write(update_value, 1); - scroll_matrix_effect_reactive.flush(); - } - - if(left_matrix_effect_reactive) - { - left_matrix_effect_reactive.write(update_value, 1); - left_matrix_effect_reactive.flush(); - } - - if(right_matrix_effect_reactive) - { - right_matrix_effect_reactive.write(update_value, 1); - right_matrix_effect_reactive.flush(); - } - break; - } - - std::this_thread::sleep_for(20ms); -} diff --git a/Controllers/OpenRazerController/RGBController_OpenRazer.h b/Controllers/OpenRazerController/RGBController_OpenRazer.h deleted file mode 100644 index 01ba9e1f..00000000 --- a/Controllers/OpenRazerController/RGBController_OpenRazer.h +++ /dev/null @@ -1,124 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_OpenRazer.h | -| | -| Generic RGB Interface for OpenRazer | -| kernel drivers for Chroma peripherals | -| | -| Adam Honse (CalcProgrammer1) 6/15/2019 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" - -#include - -class RGBController_OpenRazer : public RGBController -{ -public: - enum - { - RAZER_MODE_CUSTOM, - RAZER_MODE_OFF, - RAZER_MODE_STATIC, - RAZER_MODE_BREATHING, - RAZER_MODE_SPECTRUM_CYCLE, - RAZER_MODE_WAVE, - RAZER_MODE_REACTIVE, - RAZER_MODE_FLASHING, - RAZER_NUM_MODES - }; - - enum - { - RAZER_TYPE_MATRIX_FRAME, - RAZER_TYPE_MATRIX_NOFRAME, - RAZER_TYPE_MATRIX_STATIC, - RAZER_TYPE_NOMATRIX, - RAZER_NUM_TYPES - }; - -public: - RGBController_OpenRazer(std::string dev_path); - ~RGBController_OpenRazer(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void SetCustomMode(); - void DeviceUpdateMode(); - - int device_index; - -private: - void SetupMatrixDevice(unsigned int rows, unsigned int cols); - void SetupNonMatrixDevice(); - - unsigned int matrix_type; - unsigned int matrix_rows; - unsigned int matrix_cols; - - void OpenFunctions(std::string dev_path); - - std::ifstream device_type; - std::ifstream device_serial; - std::ifstream firmware_version; - - std::ofstream matrix_custom_frame; - std::ofstream matrix_brightness; - - std::ofstream matrix_effect_custom; - std::ofstream matrix_effect_none; - std::ofstream matrix_effect_static; - std::ofstream matrix_effect_breath; - std::ofstream matrix_effect_spectrum; - std::ofstream matrix_effect_reactive; - std::ofstream matrix_effect_wave; - - std::ofstream logo_led_brightness; - std::ofstream logo_matrix_effect_none; - std::ofstream logo_matrix_effect_static; - std::ofstream logo_matrix_effect_breath; - std::ofstream logo_matrix_effect_spectrum; - std::ofstream logo_matrix_effect_reactive; - - std::ofstream scroll_led_brightness; - std::ofstream scroll_matrix_effect_none; - std::ofstream scroll_matrix_effect_static; - std::ofstream scroll_matrix_effect_breath; - std::ofstream scroll_matrix_effect_spectrum; - std::ofstream scroll_matrix_effect_reactive; - - std::ofstream left_led_brightness; - std::ofstream left_matrix_effect_none; - std::ofstream left_matrix_effect_static; - std::ofstream left_matrix_effect_breath; - std::ofstream left_matrix_effect_spectrum; - std::ofstream left_matrix_effect_reactive; - std::ofstream left_matrix_effect_wave; - - std::ofstream right_led_brightness; - std::ofstream right_matrix_effect_none; - std::ofstream right_matrix_effect_static; - std::ofstream right_matrix_effect_breath; - std::ofstream right_matrix_effect_spectrum; - std::ofstream right_matrix_effect_reactive; - std::ofstream right_matrix_effect_wave; - - std::ofstream backlight_led_effect; - std::ofstream backlight_led_rgb; - std::ofstream backlight_led_state; - - std::ofstream logo_led_effect; - std::ofstream logo_led_rgb; - std::ofstream logo_led_state; - - std::ofstream scroll_led_effect; - std::ofstream scroll_led_rgb; - std::ofstream scroll_led_state; -}; diff --git a/Controllers/OpenRazerController/RGBController_OpenRazerWindows.cpp b/Controllers/OpenRazerController/RGBController_OpenRazerWindows.cpp deleted file mode 100644 index 6c3e7bae..00000000 --- a/Controllers/OpenRazerController/RGBController_OpenRazerWindows.cpp +++ /dev/null @@ -1,965 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_OpenRazer.cpp | -| | -| Generic RGB Interface for OpenRazer | -| kernel drivers for Chroma peripherals | -| | -| Adam Honse (CalcProgrammer1) 6/15/2019 | -\*-----------------------------------------*/ - -#include "RGBController_OpenRazerWindows.h" - -#include -#include -#include -#include -#include -#include - -using namespace std::chrono_literals; - -void RGBController_OpenRazer::DeviceUpdateLEDs() -{ - switch(matrix_type) - { - case RAZER_TYPE_MATRIX_FRAME: - case RAZER_TYPE_MATRIX_NOFRAME: - case RAZER_TYPE_MATRIX_STATIC: - { - char update_value = 1; - - for (unsigned int row = 0; row < matrix_rows; row++) - { - unsigned int output_array_size; - unsigned int output_offset; - unsigned int row_offset = (row * matrix_cols); - - if(matrix_type == RAZER_TYPE_MATRIX_FRAME) - { - output_array_size = 3 + (matrix_cols* 3); - output_offset = 3; - } - else - { - output_array_size = 3; - output_offset = 0; - } - - char* output_array = new char[output_array_size]; - - if(matrix_type == RAZER_TYPE_MATRIX_FRAME) - { - output_array[0] = row; - output_array[1] = 0; - output_array[2] = matrix_cols - 1; - } - - for(unsigned int col = 0; col < matrix_cols; col++) - { - unsigned int color_idx = col + row_offset; - output_array[(col * 3) + 0 + output_offset] = (char)RGBGetRValue(colors[color_idx]); - output_array[(col * 3) + 1 + output_offset] = (char)RGBGetGValue(colors[color_idx]); - output_array[(col * 3) + 2 + output_offset] = (char)RGBGetBValue(colors[color_idx]); - } - - if(matrix_type == RAZER_TYPE_MATRIX_FRAME) - { - razer_functions->matrix_custom_frame->store(razer_device, NULL, output_array, output_array_size); - } - else if(matrix_type == RAZER_TYPE_MATRIX_NOFRAME) - { - razer_functions->matrix_effect_custom->store(razer_device, NULL, output_array, output_array_size); - } - else - { - razer_functions->matrix_effect_static->store(razer_device, NULL, output_array, output_array_size); - } - - delete[] output_array; - - std::this_thread::sleep_for(1ms); - } - - if(matrix_type == RAZER_TYPE_MATRIX_FRAME) - { - razer_functions->matrix_effect_custom->store(razer_device, NULL, &update_value, 1); - } - } - break; - - case RAZER_TYPE_NOMATRIX: - { - DeviceUpdateMode(); - } - break; - } -} - -void RGBController_OpenRazer::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_OpenRazer::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_OpenRazer::SetupMatrixDevice(device_fn_type* razer_functions, unsigned int rows, unsigned int cols) -{ - if(!razer_functions->matrix_custom_frame) - { - if(!razer_functions->matrix_effect_custom) - { - matrix_type = RAZER_TYPE_MATRIX_STATIC; - } - else - { - matrix_type = RAZER_TYPE_MATRIX_NOFRAME; - } - - matrix_rows = 1; - matrix_cols = 1; - } - else - { - matrix_type = RAZER_TYPE_MATRIX_FRAME; - - matrix_rows = rows; - matrix_cols = cols; - } -} - -void RGBController_OpenRazer::SetupNonMatrixDevice() -{ - matrix_type = RAZER_TYPE_NOMATRIX; -} - -/**------------------------------------------------------------------*\ - @name Openrazer Windows - @category Keyboard,Mouse,Mousemat,HeadsetStand - @type USB - @save :x: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectOpenRazerControllers - @comment The Openrazer controller has been deprecated in favour of - the in built Razer controller. -\*-------------------------------------------------------------------*/ - -RGBController_OpenRazer::RGBController_OpenRazer(device * razer_device, device_fn_type* razer_functions) -{ - char string_buf[1024]; - - this->razer_device = razer_device; - this->razer_functions = razer_functions; - - /*-----------------------------------------------------------------*\ - | Start device at -1. This indicates the device was not detected | - \*-----------------------------------------------------------------*/ - device_index = -1; - - /*-----------------------------------------------------------------*\ - | Get the device name from the OpenRazer driver | - \*-----------------------------------------------------------------*/ - razer_functions->device_type->show(razer_device, NULL, string_buf); - name = string_buf; - name.erase(std::remove(name.begin(), name.end(), '\n'), name.end()); - name.erase(std::remove(name.begin(), name.end(), '\r'), name.end()); - - /*-----------------------------------------------------------------*\ - | Set the description to indicate this is an OpenRazer device | - \*-----------------------------------------------------------------*/ - description = "OpenRazer Device"; - - /*-----------------------------------------------------------------*\ - | Set the device path as the location | - \*-----------------------------------------------------------------*/ - location = ""; - - /*-----------------------------------------------------------------*\ - | Get the serial number from the dev path | - \*-----------------------------------------------------------------*/ - razer_functions->device_serial->show(razer_device, NULL, string_buf); - serial = string_buf; - serial.erase(std::remove(serial.begin(), serial.end(), '\n'), serial.end()); - serial.erase(std::remove(serial.begin(), serial.end(), '\r'), serial.end()); - - /*-----------------------------------------------------------------*\ - | Get the firmware version from the dev path | - \*-----------------------------------------------------------------*/ - razer_functions->firmware_version->show(razer_device, NULL, string_buf); - version = string_buf; - version.erase(std::remove(version.begin(), version.end(), '\n'), version.end()); - version.erase(std::remove(version.begin(), version.end(), '\r'), version.end()); - - /*-----------------------------------------------------------------*\ - | Vendor is always Razer | - \*-----------------------------------------------------------------*/ - vendor = "Razer"; - - /*-----------------------------------------------------------------*\ - | Loop through all known devices to look for a name match | - \*-----------------------------------------------------------------*/ - for (unsigned int i = 0; i < RAZER_NUM_DEVICES; i++) - { - if (device_list[i]->name == name) - { - /*---------------------------------------------------------*\ - | Set device ID | - \*---------------------------------------------------------*/ - device_index = i; - - /*---------------------------------------------------------*\ - | Set device type | - \*---------------------------------------------------------*/ - type = device_list[i]->type; - - /*---------------------------------------------------------*\ - | Device has Direct mode if matrix_custom_frame exists | - \*---------------------------------------------------------*/ - if(razer_functions->matrix_effect_custom) - { - mode Direct; - Direct.name = "Direct"; - Direct.value = RAZER_MODE_CUSTOM; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - } - - /*---------------------------------------------------------*\ - | Device has Off mode if any _effect_none or any _state | - | exists | - \*---------------------------------------------------------*/ - if( razer_functions->matrix_effect_none - || razer_functions->logo_matrix_effect_none - || razer_functions->scroll_matrix_effect_none - || razer_functions->left_matrix_effect_none - || razer_functions->right_matrix_effect_none - /*|| razer_functions->backlight_led_state*/ - || razer_functions->logo_led_state - || razer_functions->scroll_led_state) - { - mode Off; - Off.name = "Off"; - Off.value = RAZER_MODE_OFF; - Off.flags = 0; - Off.color_mode = MODE_COLORS_NONE; - modes.push_back(Off); - } - - /*---------------------------------------------------------*\ - | Device has Static mode if any _effect_static or any | - | _effect exists | - \*---------------------------------------------------------*/ - if( razer_functions->matrix_effect_static - || razer_functions->logo_matrix_effect_static - || razer_functions->scroll_matrix_effect_static - || razer_functions->left_matrix_effect_static - || razer_functions->right_matrix_effect_static - /*|| razer_functions->backlight_led_effect*/ - || razer_functions->logo_led_effect - || razer_functions->scroll_led_effect) - { - mode Static; - Static.name = "Static"; - Static.value = RAZER_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Static.colors_min = 1; - Static.colors_max = 1; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; - Static.colors.resize(1); - modes.push_back(Static); - } - - /*---------------------------------------------------------*\ - | Device has Breathing mode if any _effect_breath exists | - \*---------------------------------------------------------*/ - if( razer_functions->matrix_effect_breath - || razer_functions->logo_matrix_effect_breath - || razer_functions->scroll_matrix_effect_breath - || razer_functions->left_matrix_effect_breath - || razer_functions->right_matrix_effect_breath) - { - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = RAZER_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; - Breathing.colors_min = 1; - Breathing.colors_max = 2; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.colors.resize(2); - modes.push_back(Breathing); - } - - /*---------------------------------------------------------*\ - | Device has limited Breathing mode if any _effect exists | - \*---------------------------------------------------------*/ - if( /*razer_functions->backlight_led_effect ||*/ - razer_functions->logo_led_effect - || razer_functions->scroll_led_effect) - { - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = RAZER_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Breathing.colors_min = 1; - Breathing.colors_max = 1; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.colors.resize(1); - modes.push_back(Breathing); - } - - /*---------------------------------------------------------*\ - | Device has Flashing mode if any _effect exists | - \*---------------------------------------------------------*/ - if( /*razer_functions->backlight_led_effect ||*/ - razer_functions->logo_led_effect - || razer_functions->scroll_led_effect) - { - mode Flashing; - Flashing.name = "Flashing"; - Flashing.value = RAZER_MODE_FLASHING; - Flashing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Flashing.colors_min = 1; - Flashing.colors_max = 1; - Flashing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Flashing.colors.resize(1); - modes.push_back(Flashing); - } - - /*---------------------------------------------------------*\ - | Device has Spectrum Cycle mode if any _effect_spectrum or | - | _effect exists | - \*---------------------------------------------------------*/ - if( razer_functions->matrix_effect_spectrum - || razer_functions->logo_matrix_effect_spectrum - || razer_functions->scroll_matrix_effect_spectrum - || razer_functions->left_matrix_effect_spectrum - || razer_functions->right_matrix_effect_spectrum - /*|| razer_functions->backlight_led_effect*/ - || razer_functions->logo_led_effect - || razer_functions->scroll_led_effect) - { - mode SpectrumCycle; - SpectrumCycle.name = "Spectrum Cycle"; - SpectrumCycle.value = RAZER_MODE_SPECTRUM_CYCLE; - SpectrumCycle.flags = 0; - SpectrumCycle.color_mode = MODE_COLORS_NONE; - modes.push_back(SpectrumCycle); - } - - /*---------------------------------------------------------*\ - | Device has Wave mode if any _effect_wave exists | - \*---------------------------------------------------------*/ - if( razer_functions->matrix_effect_wave - || razer_functions->left_matrix_effect_wave - || razer_functions->right_matrix_effect_wave) - { - mode Wave; - Wave.name = "Wave"; - Wave.value = RAZER_MODE_WAVE; - Wave.flags = MODE_FLAG_HAS_DIRECTION_LR; - Wave.direction = MODE_DIRECTION_RIGHT; - Wave.color_mode = MODE_COLORS_NONE; - modes.push_back(Wave); - } - - /*---------------------------------------------------------*\ - | Device has Reactive mode if any _effect_reactive exists | - \*---------------------------------------------------------*/ - if( razer_functions->matrix_effect_reactive - || razer_functions->logo_matrix_effect_reactive - || razer_functions->scroll_matrix_effect_reactive - || razer_functions->left_matrix_effect_reactive - || razer_functions->right_matrix_effect_reactive) - { - mode Reactive; - Reactive.name = "Reactive"; - Reactive.value = RAZER_MODE_REACTIVE; - Reactive.flags = 0; - Reactive.color_mode = MODE_COLORS_NONE; - modes.push_back(Reactive); - } - - /*---------------------------------------------------------*\ - | Initialize file descriptors | - \*---------------------------------------------------------*/ - if(device_list[i]->matrix_type == true) - { - SetupMatrixDevice(razer_functions, device_list[i]->rows, device_list[i]->cols); - } - else - { - SetupNonMatrixDevice(); - } - - SetupZones(); - } - } - -} - -RGBController_OpenRazer::~RGBController_OpenRazer() -{ - /*---------------------------------------------------------*\ - | Delete the matrix map | - \*---------------------------------------------------------*/ - for(unsigned int zone_index = 0; zone_index < zones.size(); zone_index++) - { - if(zones[zone_index].matrix_map != NULL) - { - if(zones[zone_index].matrix_map->map != NULL) - { - delete zones[zone_index].matrix_map->map; - } - - delete zones[zone_index].matrix_map; - } - } -} - -void RGBController_OpenRazer::SetupZones() -{ - /*---------------------------------------------------------*\ - | Fill in zone information based on device table | - \*---------------------------------------------------------*/ - for(unsigned int zone_id = 0; zone_id < RAZER_MAX_ZONES; zone_id++) - { - if(device_list[device_index]->zones[zone_id] != NULL) - { - zone new_zone; - - new_zone.name = device_list[device_index]->zones[zone_id]->name; - new_zone.type = device_list[device_index]->zones[zone_id]->type; - - new_zone.leds_count = device_list[device_index]->zones[zone_id]->rows * device_list[device_index]->zones[zone_id]->cols; - new_zone.leds_min = new_zone.leds_count; - new_zone.leds_max = new_zone.leds_count; - - if(new_zone.type == ZONE_TYPE_MATRIX) - { - matrix_map_type * new_map = new matrix_map_type; - new_zone.matrix_map = new_map; - - new_map->height = device_list[device_index]->zones[zone_id]->rows; - new_map->width = device_list[device_index]->zones[zone_id]->cols; - - new_map->map = new unsigned int[new_map->height * new_map->width]; - - for(unsigned int y = 0; y < new_map->height; y++) - { - for(unsigned int x = 0; x < new_map->width; x++) - { - new_map->map[(y * new_map->width) + x] = (y * new_map->width) + x; - } - } - } - else - { - new_zone.matrix_map = NULL; - } - - zones.push_back(new_zone); - } - } - - for(unsigned int zone_id = 0; zone_id < zones.size(); zone_id++) - { - for (unsigned int row_id = 0; row_id < device_list[device_index]->zones[zone_id]->rows; row_id++) - { - for (unsigned int col_id = 0; col_id < device_list[device_index]->zones[zone_id]->cols; col_id++) - { - led* new_led = new led(); - - new_led->name = device_list[device_index]->zones[zone_id]->name; - - if(zones[zone_id].leds_count > 1) - { - new_led->name.append(" LED "); - new_led->name.append(std::to_string(col_id + 1)); - } - - if(device_list[device_index]->keymap != NULL) - { - for(unsigned int i = 0; i < device_list[device_index]->keymap_size; i++) - { - if(zone_id == device_list[device_index]->keymap[i].zone && - row_id == device_list[device_index]->keymap[i].row && - col_id == device_list[device_index]->keymap[i].col) - { - new_led->name = device_list[device_index]->keymap[i].name; - } - } - } - - leds.push_back(*new_led); - } - } - } - - SetupColors(); -} - -void RGBController_OpenRazer::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_OpenRazer::SetCustomMode() -{ - /*---------------------------------------------------------*\ - | If device supports custom mode, it will be mode index 0 | - \*---------------------------------------------------------*/ - if(modes[0].value == RAZER_MODE_CUSTOM) - { - active_mode = 0; - } - /*---------------------------------------------------------*\ - | If not, use static mode. | - \*---------------------------------------------------------*/ - else - { - for(unsigned int i = 0; i < modes.size(); i++) - { - if(modes[i].value == RAZER_MODE_STATIC) - { - active_mode = i; - break; - } - } - } -} - -void RGBController_OpenRazer::DeviceUpdateMode() -{ - char update_value[6]; - char effect_value[1]; - - update_value[0] = 1; - - switch(modes[active_mode].value) - { - case RAZER_MODE_CUSTOM: - if(razer_functions->matrix_effect_custom) - { - razer_functions->matrix_effect_custom->store(razer_device, NULL, update_value, 1); - } - break; - - case RAZER_MODE_OFF: - if(razer_functions->matrix_effect_none) - { - razer_functions->matrix_effect_none->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->logo_matrix_effect_none) - { - razer_functions->logo_matrix_effect_none->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->scroll_matrix_effect_none) - { - razer_functions->scroll_matrix_effect_none->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->left_matrix_effect_none) - { - razer_functions->left_matrix_effect_none->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->right_matrix_effect_none) - { - razer_functions->right_matrix_effect_none->store(razer_device, NULL, update_value, 1); - } - - //if(razer_functions->backlight_led_state) - //{ - // update_value[0] = '0'; - // razer_functions->backlight_led_state->store(razer_device, NULL, update_value, 1); - //} - - if(razer_functions->logo_led_state) - { - update_value[0] = '0'; - razer_functions->logo_led_state->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->scroll_led_state) - { - update_value[0] = '0'; - razer_functions->scroll_led_state->store(razer_device, NULL, update_value, 1); - } - break; - - case RAZER_MODE_STATIC: - effect_value[0] = '0'; - - //if(razer_functions->backlight_led_state) - //{ - // update_value[0] = '1'; - // razer_functions->backlight_led_state->store(razer_device, NULL, update_value, 1); - //} - - if(razer_functions->logo_led_state) - { - update_value[0] = '1'; - razer_functions->logo_led_state->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->scroll_led_state) - { - update_value[0] = '1'; - razer_functions->scroll_led_state->store(razer_device, NULL, update_value, 1); - } - - update_value[0] = RGBGetRValue(modes[active_mode].colors[0]); - update_value[1] = RGBGetGValue(modes[active_mode].colors[0]); - update_value[2] = RGBGetBValue(modes[active_mode].colors[0]); - - if(razer_functions->matrix_effect_static) - { - razer_functions->matrix_effect_static->store(razer_device, NULL, update_value, 3); - } - - if(razer_functions->logo_matrix_effect_static) - { - razer_functions->logo_matrix_effect_static->store(razer_device, NULL, update_value, 3); - } - - if(razer_functions->scroll_matrix_effect_static) - { - razer_functions->scroll_matrix_effect_static->store(razer_device, NULL, update_value, 3); - } - - if(razer_functions->left_matrix_effect_static) - { - razer_functions->left_matrix_effect_static->store(razer_device, NULL, update_value, 3); - } - - if(razer_functions->right_matrix_effect_static) - { - razer_functions->right_matrix_effect_static->store(razer_device, NULL, update_value, 3); - } - - //if(razer_functions->backlight_led_effect && razer_functions->backlight_led_rgb) - //{ - // razer_functions->backlight_led_rgb->store(razer_device, NULL, update_value, 3); - // razer_functions->backlight_led_effect->store(razer_device, NULL, effect_value, 1); - //} - - if(razer_functions->logo_led_effect && razer_functions->logo_led_rgb) - { - razer_functions->logo_led_rgb->store(razer_device, NULL, update_value, 3); - razer_functions->logo_led_effect->store(razer_device, NULL, effect_value, 1); - } - - if(razer_functions->scroll_led_effect && razer_functions->scroll_led_rgb) - { - razer_functions->scroll_led_rgb->store(razer_device, NULL, update_value, 3); - razer_functions->scroll_led_effect->store(razer_device, NULL, effect_value, 1); - } - break; - - case RAZER_MODE_FLASHING: - effect_value[0] = '1'; - - //if(razer_functions->backlight_led_state) - //{ - // update_value[0] = '1'; - // razer_functions->backlight_led_state->store(razer_device, NULL, update_value, 1); - //} - - if(razer_functions->logo_led_state) - { - update_value[0] = '1'; - razer_functions->logo_led_state->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->scroll_led_state) - { - update_value[0] = '1'; - razer_functions->scroll_led_state->store(razer_device, NULL, update_value, 1); - } - - update_value[0] = RGBGetRValue(modes[active_mode].colors[0]); - update_value[1] = RGBGetGValue(modes[active_mode].colors[0]); - update_value[2] = RGBGetBValue(modes[active_mode].colors[0]); - - //if(razer_functions->backlight_led_effect && razer_functions->backlight_led_rgb) - //{ - // razer_functions->backlight_led_rgb->store(razer_device, NULL, update_value, 3); - // razer_functions->backlight_led_effect->store(razer_device, NULL, effect_value, 1); - //} - - if(razer_functions->logo_led_effect && razer_functions->logo_led_rgb) - { - razer_functions->logo_led_rgb->store(razer_device, NULL, update_value, 3); - razer_functions->logo_led_effect->store(razer_device, NULL, effect_value, 1); - } - - if(razer_functions->scroll_led_effect && razer_functions->scroll_led_rgb) - { - razer_functions->scroll_led_rgb->store(razer_device, NULL, update_value, 3); - razer_functions->scroll_led_effect->store(razer_device, NULL, effect_value, 1); - } - break; - - case RAZER_MODE_BREATHING: - effect_value[0] = '2'; - - switch(modes[active_mode].color_mode) - { - case MODE_COLORS_MODE_SPECIFIC: - //if(razer_functions->backlight_led_state) - //{ - // update_value[0] = '1'; - // razer_functions->backlight_led_state->store(razer_device, NULL, update_value, 1); - //} - - if(razer_functions->logo_led_state) - { - update_value[0] = '1'; - razer_functions->logo_led_state->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->scroll_led_state) - { - update_value[0] = '1'; - razer_functions->scroll_led_state->store(razer_device, NULL, update_value, 1); - } - - update_value[0] = RGBGetRValue(modes[active_mode].colors[0]); - update_value[1] = RGBGetGValue(modes[active_mode].colors[0]); - update_value[2] = RGBGetBValue(modes[active_mode].colors[0]); - - if(modes[active_mode].colors.size() == 2) - { - update_value[3] = RGBGetRValue(modes[active_mode].colors[1]); - update_value[4] = RGBGetGValue(modes[active_mode].colors[1]); - update_value[5] = RGBGetBValue(modes[active_mode].colors[1]); - - if(razer_functions->matrix_effect_breath) - { - razer_functions->matrix_effect_breath->store(razer_device, NULL, update_value, 6); - } - - if(razer_functions->logo_matrix_effect_breath) - { - razer_functions->logo_matrix_effect_breath->store(razer_device, NULL, update_value, 6); - } - - if(razer_functions->scroll_matrix_effect_breath) - { - razer_functions->scroll_matrix_effect_breath->store(razer_device, NULL, update_value, 6); - } - - if(razer_functions->left_matrix_effect_breath) - { - razer_functions->left_matrix_effect_breath->store(razer_device, NULL, update_value, 6); - } - - if(razer_functions->right_matrix_effect_breath) - { - razer_functions->right_matrix_effect_breath->store(razer_device, NULL, update_value, 6); - } - } - else - { - if(razer_functions->matrix_effect_breath) - { - razer_functions->matrix_effect_breath->store(razer_device, NULL, update_value, 3); - } - - if(razer_functions->logo_matrix_effect_breath) - { - razer_functions->logo_matrix_effect_breath->store(razer_device, NULL, update_value, 3); - } - - if(razer_functions->scroll_matrix_effect_breath) - { - razer_functions->scroll_matrix_effect_breath->store(razer_device, NULL, update_value, 3); - } - - if(razer_functions->left_matrix_effect_breath) - { - razer_functions->left_matrix_effect_breath->store(razer_device, NULL, update_value, 3); - } - - if(razer_functions->right_matrix_effect_breath) - { - razer_functions->right_matrix_effect_breath->store(razer_device, NULL, update_value, 3); - } - - //if(razer_functions->backlight_led_effect && razer_functions->backlight_led_rgb) - //{ - // razer_functions->backlight_led_rgb->store(razer_device, NULL, update_value, 3); - // razer_functions->backlight_led_effect->store(razer_device, NULL, effect_value, 1); - //} - - if(razer_functions->logo_led_effect && razer_functions->logo_led_rgb) - { - razer_functions->logo_led_rgb->store(razer_device, NULL, update_value, 3); - razer_functions->logo_led_effect->store(razer_device, NULL, effect_value, 1); - } - - if(razer_functions->scroll_led_effect && razer_functions->scroll_led_rgb) - { - razer_functions->scroll_led_rgb->store(razer_device, NULL, update_value, 3); - razer_functions->scroll_led_effect->store(razer_device, NULL, effect_value, 1); - } - } - break; - - case MODE_COLORS_RANDOM: - if(razer_functions->matrix_effect_breath) - { - razer_functions->matrix_effect_breath->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->logo_matrix_effect_breath) - { - razer_functions->logo_matrix_effect_breath->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->scroll_matrix_effect_breath) - { - razer_functions->scroll_matrix_effect_breath->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->left_matrix_effect_breath) - { - razer_functions->left_matrix_effect_breath->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->right_matrix_effect_breath) - { - razer_functions->right_matrix_effect_breath->store(razer_device, NULL, update_value, 1); - } - break; - } - break; - - case RAZER_MODE_SPECTRUM_CYCLE: - effect_value[0] = '4'; - - //if(razer_functions->backlight_led_state) - //{ - // update_value[0] = '1'; - // razer_functions->backlight_led_state->store(razer_device, NULL, update_value, 1); - //} - - if(razer_functions->logo_led_state) - { - update_value[0] = '1'; - razer_functions->logo_led_state->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->scroll_led_state) - { - update_value[0] = '1'; - razer_functions->scroll_led_state->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->matrix_effect_spectrum) - { - razer_functions->matrix_effect_spectrum->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->logo_matrix_effect_spectrum) - { - razer_functions->logo_matrix_effect_spectrum->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->scroll_matrix_effect_spectrum) - { - razer_functions->scroll_matrix_effect_spectrum->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->left_matrix_effect_spectrum) - { - razer_functions->left_matrix_effect_spectrum->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->right_matrix_effect_spectrum) - { - razer_functions->right_matrix_effect_spectrum->store(razer_device, NULL, update_value, 1); - } - - //if(razer_functions->backlight_led_effect) - //{ - // razer_functions->backlight_led_effect->store(razer_device, NULL, effect_value, 1); - //} - - if(razer_functions->logo_led_effect) - { - razer_functions->logo_led_effect->store(razer_device, NULL, effect_value, 1); - } - - if(razer_functions->scroll_led_effect) - { - razer_functions->scroll_led_effect->store(razer_device, NULL, effect_value, 1); - } - break; - - case RAZER_MODE_WAVE: - switch(modes[active_mode].direction) - { - case MODE_DIRECTION_LEFT: - update_value[0] = '2'; - break; - - default: - update_value[0] = '1'; - break; - } - - if(razer_functions->matrix_effect_wave) - { - razer_functions->matrix_effect_wave->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->left_matrix_effect_wave) - { - razer_functions->left_matrix_effect_wave->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->right_matrix_effect_wave) - { - razer_functions->right_matrix_effect_wave->store(razer_device, NULL, update_value, 1); - } - break; - - case RAZER_MODE_REACTIVE: - if(razer_functions->matrix_effect_reactive) - { - razer_functions->matrix_effect_reactive->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->logo_matrix_effect_reactive) - { - razer_functions->logo_matrix_effect_reactive->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->scroll_matrix_effect_reactive) - { - razer_functions->scroll_matrix_effect_reactive->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->left_matrix_effect_reactive) - { - razer_functions->left_matrix_effect_reactive->store(razer_device, NULL, update_value, 1); - } - - if(razer_functions->right_matrix_effect_reactive) - { - razer_functions->right_matrix_effect_reactive->store(razer_device, NULL, update_value, 1); - } - break; - } - - std::this_thread::sleep_for(20ms); -} diff --git a/Controllers/OpenRazerController/RGBController_OpenRazerWindows.h b/Controllers/OpenRazerController/RGBController_OpenRazerWindows.h deleted file mode 100644 index be7eea2e..00000000 --- a/Controllers/OpenRazerController/RGBController_OpenRazerWindows.h +++ /dev/null @@ -1,142 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_OpenRazerWindows.h | -| | -| Generic RGB Interface for OpenRazer | -| kernel drivers for Chroma peripherals | -| | -| Adam Honse (CalcProgrammer1) 6/15/2019 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include "OpenRazerDevices.h" - -#include -#include -#include -#include - -typedef struct -{ - struct device_attribute* device_type; - struct device_attribute* device_serial; - struct device_attribute* firmware_version; - - struct device_attribute* matrix_custom_frame; - struct device_attribute* matrix_brightness; - - struct device_attribute* matrix_effect_custom; - struct device_attribute* matrix_effect_none; - struct device_attribute* matrix_effect_static; - struct device_attribute* matrix_effect_breath; - struct device_attribute* matrix_effect_spectrum; - struct device_attribute* matrix_effect_reactive; - struct device_attribute* matrix_effect_wave; - - struct device_attribute* logo_led_brightness; - struct device_attribute* logo_matrix_effect_none; - struct device_attribute* logo_matrix_effect_static; - struct device_attribute* logo_matrix_effect_breath; - struct device_attribute* logo_matrix_effect_spectrum; - struct device_attribute* logo_matrix_effect_reactive; - - struct device_attribute* scroll_led_brightness; - struct device_attribute* scroll_matrix_effect_none; - struct device_attribute* scroll_matrix_effect_static; - struct device_attribute* scroll_matrix_effect_breath; - struct device_attribute* scroll_matrix_effect_spectrum; - struct device_attribute* scroll_matrix_effect_reactive; - - struct device_attribute* left_led_brightness; - struct device_attribute* left_matrix_effect_none; - struct device_attribute* left_matrix_effect_static; - struct device_attribute* left_matrix_effect_breath; - struct device_attribute* left_matrix_effect_spectrum; - struct device_attribute* left_matrix_effect_reactive; - struct device_attribute* left_matrix_effect_wave; - - struct device_attribute* right_led_brightness; - struct device_attribute* right_matrix_effect_none; - struct device_attribute* right_matrix_effect_static; - struct device_attribute* right_matrix_effect_breath; - struct device_attribute* right_matrix_effect_spectrum; - struct device_attribute* right_matrix_effect_reactive; - struct device_attribute* right_matrix_effect_wave; - - struct device_attribute* logo_led_effect; - struct device_attribute* logo_led_rgb; - struct device_attribute* logo_led_state; - - struct device_attribute* scroll_led_effect; - struct device_attribute* scroll_led_rgb; - struct device_attribute* scroll_led_state; -} device_fn_type; - -class RGBController_OpenRazer : public RGBController -{ -public: - enum - { - RAZER_MODE_CUSTOM, - RAZER_MODE_OFF, - RAZER_MODE_STATIC, - RAZER_MODE_BREATHING, - RAZER_MODE_SPECTRUM_CYCLE, - RAZER_MODE_WAVE, - RAZER_MODE_REACTIVE, - RAZER_MODE_FLASHING, - RAZER_NUM_MODES - }; - - enum - { - RAZER_TYPE_MATRIX_FRAME, - RAZER_TYPE_MATRIX_NOFRAME, - RAZER_TYPE_MATRIX_STATIC, - RAZER_TYPE_NOMATRIX, - RAZER_NUM_TYPES - }; - -public: - RGBController_OpenRazer(device * razer_device, device_fn_type* razer_functions); - ~RGBController_OpenRazer(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void SetCustomMode(); - void DeviceUpdateMode(); - - int device_index; - -private: - void SetupMatrixDevice(device_fn_type* razer_functions, unsigned int rows, unsigned int cols); - void SetupNonMatrixDevice(); - - unsigned int matrix_type; - unsigned int matrix_rows; - unsigned int matrix_cols; - - device* razer_device; - device_fn_type* razer_functions; - - //OpenRazer Sysfs Entries for Matrix Devices - std::ofstream matrix_custom_frame; - std::ofstream matrix_effect_custom; - std::ofstream matrix_effect_breath; - std::ofstream matrix_effect_none; - std::ofstream matrix_effect_reactive; - std::ofstream matrix_effect_spectrum; - std::ofstream matrix_effect_static; - std::ofstream matrix_effect_wave; - - //OpenRazer Sysfs Entries for Non-Matrix Devices - std::ofstream logo_led_effect; - std::ofstream logo_led_rgb; - std::ofstream scroll_led_effect; - std::ofstream scroll_led_rgb; -}; diff --git a/Controllers/PNYARGBEpicXGPUController/PNYARGBEpicXGPUController.cpp b/Controllers/PNYARGBEpicXGPUController/PNYARGBEpicXGPUController.cpp new file mode 100644 index 00000000..090f9790 --- /dev/null +++ b/Controllers/PNYARGBEpicXGPUController/PNYARGBEpicXGPUController.cpp @@ -0,0 +1,72 @@ +/*---------------------------------------------------------*\ +| PNYARGBEpicXGPUController.cpp | +| | +| Driver for PNY ARGB Epic-X GPU | +| | +| Peter Berendi 27 Apr 2025 | +| Adam Honse 01 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "PNYARGBEpicXGPUController.h" + +PNYARGBEpicXGPUController::PNYARGBEpicXGPUController(i2c_smbus_interface* bus, unsigned char init_i2c_addr, std::string name) +{ + this->bus = bus; + this->i2c_addr = init_i2c_addr; + this->name = name; +} + +PNYARGBEpicXGPUController::~PNYARGBEpicXGPUController() +{ + +} + +std::string PNYARGBEpicXGPUController::GetDeviceLocation() +{ + std::string return_string(bus->device_name); + char addr[5]; + snprintf(addr, 5, "0x%02X", i2c_addr); + return_string.append(", address "); + return_string.append(addr); + return("I2C: " + return_string); +} + +std::string PNYARGBEpicXGPUController::GetDeviceName() +{ + return(name); +} + +void PNYARGBEpicXGPUController::SetZoneMode(unsigned char zone, unsigned char mode, unsigned char speed, unsigned char brightness, unsigned char subcmd, RGBColor color) +{ + unsigned char data[7] = + { + mode, + brightness, + speed, + subcmd, + (unsigned char)RGBGetRValue(color), + (unsigned char)RGBGetGValue(color), + (unsigned char)RGBGetBValue(color) + }; + + bus->i2c_smbus_write_i2c_block_data(i2c_addr, zone, sizeof(data), data); +} + +void PNYARGBEpicXGPUController::SetLEDDirect(unsigned char zone, unsigned char led, unsigned char mode, RGBColor color) +{ + unsigned char data[7] = + { + mode, + 0xFF, + led, + 0x00, + (unsigned char)RGBGetRValue(color), + (unsigned char)RGBGetGValue(color), + (unsigned char)RGBGetBValue(color) + }; + + bus->i2c_smbus_write_i2c_block_data(i2c_addr, zone, sizeof(data), data); +} \ No newline at end of file diff --git a/Controllers/PNYARGBEpicXGPUController/PNYARGBEpicXGPUController.h b/Controllers/PNYARGBEpicXGPUController/PNYARGBEpicXGPUController.h new file mode 100644 index 00000000..411d8136 --- /dev/null +++ b/Controllers/PNYARGBEpicXGPUController/PNYARGBEpicXGPUController.h @@ -0,0 +1,61 @@ +/*---------------------------------------------------------*\ +| PNYARGBEpicXGPUController.h | +| | +| Driver for PNY ARGB Epic-X GPU | +| | +| Peter Berendi 27 Apr 2025 | +| Adam Honse 01 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "i2c_smbus.h" +#include "RGBController.h" + +enum +{ + PNY_GPU_MODE_ARGB_OFF = 0x00, + PNY_GPU_MODE_ARGB_BREATH = 0x0302, + PNY_GPU_MODE_ARGB_CYCLE = 0x03, + PNY_GPU_MODE_ARGB_NEON = 0x04, + PNY_GPU_MODE_ARGB_EXPLOSION = 0x05, + PNY_GPU_MODE_ARGB_SUPERNOVA = 0x06, + PNY_GPU_MODE_ARGB_INFINITY = 0x07, + PNY_GPU_MODE_ARGB_STREAMER = 0x08, + PNY_GPU_MODE_ARGB_DIRECT = 0x09, + PNY_GPU_MODE_ARGB_WAVE = 0x0A, +}; + +/*---------------------------------------------------------*\ +| The 5070Ti only uses FRONT and ARROW, the LOGO zone is | +| used by the 5090 | +\*---------------------------------------------------------*/ +enum +{ + PNY_GPU_REG_ZONE_ARROW = 0x02, + PNY_GPU_REG_ZONE_FRONT = 0x04, + PNY_GPU_REG_ZONE_LOGO = 0x0F, + PNY_GPU_REG_DETECT = 0x81, +}; + +class PNYARGBEpicXGPUController +{ +public: + PNYARGBEpicXGPUController(i2c_smbus_interface* bus, unsigned char init_i2c_addr, std::string name); + ~PNYARGBEpicXGPUController(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + + void SetZoneMode(unsigned char zone, unsigned char mode, unsigned char speed, unsigned char brightness, unsigned char subcmd, RGBColor color); + void SetLEDDirect(unsigned char zone, unsigned char led, unsigned char mode, RGBColor color); + +private: + i2c_smbus_interface* bus; + unsigned char i2c_addr; + std::string name; +}; diff --git a/Controllers/PNYARGBEpicXGPUController/PNYARGBEpicXGPUControllerDetect.cpp b/Controllers/PNYARGBEpicXGPUController/PNYARGBEpicXGPUControllerDetect.cpp new file mode 100644 index 00000000..fbe70776 --- /dev/null +++ b/Controllers/PNYARGBEpicXGPUController/PNYARGBEpicXGPUControllerDetect.cpp @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| PNYARGBEpicXGPUControllerDetect.cpp | +| | +| Detector for PNY ARGB Epic-X GPU | +| | +| Peter Berendi 27 Apr 2025 | +| Adam Honse 01 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "LogManager.h" +#include "PNYARGBEpicXGPUController.h" +#include "RGBController_PNYARGBEpicXGPU.h" +#include "i2c_smbus.h" +#include "pci_ids.h" + +/*-----------------------------------------------------------------------------------------*\ +| DetectPNYARGBEpicXGPUControllers | +| | +| Detect PNY ARGB Epic X GPU controllers on the enumerated I2C busses at address 0x60. | +| | +| bus - pointer to i2c_smbus_interface where PNY GPU device is connected | +| dev - I2C address of PNY GPU device | +\*-----------------------------------------------------------------------------------------*/ + +void DetectPNYARGBEpicXGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name) +{ + PNYARGBEpicXGPUController* controller = new PNYARGBEpicXGPUController(bus, i2c_addr, name); + RGBController_PNYARGBEpicXGPU* rgb_controller = new RGBController_PNYARGBEpicXGPU(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); +} /* DetectPNYARGBEpicXGPUControllers() */ + +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 5070Ti ARGB Epic-X OC", DetectPNYARGBEpicXGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070TI_DEV, PNY_SUB_VEN, PNY_RTX_5070TI_ARGB_EPIC_X_OC_SUB_DEV, 0x60); +//REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 5080 ARGB Epic-X OC", DetectPNYARGBEpicXGPUControllers, NVIDIA_VEN, NVIDIA_RTX5080_DEV, PNY_SUB_VEN, PNY_RTX_5080_ARGB_EPIC_X_OC_SUB_DEV, 0x60); +//REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 5090 ARGB Epic-X OC", DetectPNYARGBEpicXGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, PNY_SUB_VEN, PNY_RTX_5090_ARGB_EPIC_X_OC_SUB_DEV, 0x60); diff --git a/Controllers/PNYARGBEpicXGPUController/RGBController_PNYARGBEpicXGPU.cpp b/Controllers/PNYARGBEpicXGPUController/RGBController_PNYARGBEpicXGPU.cpp new file mode 100644 index 00000000..0cb81fb4 --- /dev/null +++ b/Controllers/PNYARGBEpicXGPUController/RGBController_PNYARGBEpicXGPU.cpp @@ -0,0 +1,176 @@ +/*---------------------------------------------------------*\ +| RGBController_PNYARGBEpicXGPU.cpp | +| | +| RGBController for PNY ARGB Epic-X GPU | +| | +| Peter Berendi 27 Apr 2025 | +| Adam Honse 01 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "pci_ids.h" +#include "RGBController_PNYARGBEpicXGPU.h" + +#define __ 0xFFFFFFFF + +/**------------------------------------------------------------------*\ + @name PNY ARGB Epic-X GPU + @category GPU + @type I2C + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectPNYARGBEpicXGPUControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_PNYARGBEpicXGPU::RGBController_PNYARGBEpicXGPU(PNYARGBEpicXGPUController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "PNY"; + description = "PNY ARGB Epic-X GPU Device"; + location = controller->GetDeviceLocation(); + type = DEVICE_TYPE_GPU; + + mode Direct; + Direct.name = "Direct"; + Direct.value = PNY_GPU_MODE_ARGB_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness = 0xFF; + Direct.brightness_min = 0; + Direct.brightness_max = 0xFF; + modes.push_back(Direct); + + SetupZones(); + + active_mode = 0; +} + +RGBController_PNYARGBEpicXGPU::~RGBController_PNYARGBEpicXGPU() +{ + delete controller; +} + +void RGBController_PNYARGBEpicXGPU::SetupZones() +{ + /*-----------------------------------------------------*\ + | The logo zone has 4 LEDs, but they are part of the | + | FRONT register zone | + \*-----------------------------------------------------*/ + zone logo; + logo.name = "Logo"; + logo.type = ZONE_TYPE_LINEAR; + logo.leds_min = 4; + logo.leds_max = 4; + logo.leds_count = 4; + logo.matrix_map = NULL; + zones.push_back(logo); + + for(std::size_t led_idx = 0; led_idx < logo.leds_count; led_idx++) + { + led logo_led; + + logo_led.name = "Logo LED " + std::to_string(led_idx); + logo_led.value = PNY_GPU_REG_ZONE_FRONT; + + leds.push_back(logo_led); + zone_led_idx.push_back((unsigned char)(led_idx + 20)); + } + + /*-----------------------------------------------------*\ + | The front zone has 20 LEDs in a figure 8 pattern, the | + | FRONT register has these 20 and then the 4 log LEDs | + \*-----------------------------------------------------*/ + zone front; + front.name = "Front"; + front.type = ZONE_TYPE_LINEAR; + front.leds_min = 20; + front.leds_max = 20; + front.leds_count = 20; + front.matrix_map = NULL; + zones.push_back(front); + + for(std::size_t led_idx = 0; led_idx < front.leds_count; led_idx++) + { + led front_led; + + front_led.name = "Front LED " + std::to_string(led_idx); + front_led.value = PNY_GPU_REG_ZONE_FRONT; + + leds.push_back(front_led); + zone_led_idx.push_back((unsigned char)led_idx); + } + + /*-----------------------------------------------------*\ + | The arrow zone has 17 LEDs | + \*-----------------------------------------------------*/ + zone arrow; + arrow.name = "Arrow"; + arrow.type = ZONE_TYPE_LINEAR; + arrow.leds_min = 17; + arrow.leds_max = 17; + arrow.leds_count = 17; + arrow.matrix_map = NULL; + zones.push_back(arrow); + + for(std::size_t led_idx = 0; led_idx < arrow.leds_count; led_idx++) + { + led arrow_led; + + arrow_led.name = "Arrow LED " + std::to_string(led_idx); + arrow_led.value = PNY_GPU_REG_ZONE_ARROW; + + leds.push_back(arrow_led); + zone_led_idx.push_back((unsigned char)led_idx); + } + + SetupColors(); +} + +void RGBController_PNYARGBEpicXGPU::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_PNYARGBEpicXGPU::DeviceUpdateLEDs() +{ + for(std::size_t i = 0; i < leds.size(); i++) + { + UpdateSingleLED(i); + } +} + +void RGBController_PNYARGBEpicXGPU::UpdateZoneLEDs(int zone) +{ + for(unsigned int i = 0; i < zones[zone].leds_count; i++) + { + UpdateSingleLED(zones[zone].start_idx + i); + } +} + +void RGBController_PNYARGBEpicXGPU::UpdateSingleLED(int led) +{ + controller->SetLEDDirect(leds[led].value, zone_led_idx[led], PNY_GPU_MODE_ARGB_DIRECT, colors[led]); +} + +void RGBController_PNYARGBEpicXGPU::DeviceUpdateMode() +{ + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + controller->SetZoneMode(PNY_GPU_REG_ZONE_FRONT, modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, 0, modes[active_mode].colors[0]); + controller->SetZoneMode(PNY_GPU_REG_ZONE_ARROW, modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, 0, modes[active_mode].colors[0]); + } + else if(modes[active_mode].color_mode == MODE_COLORS_PER_LED) + { + controller->SetZoneMode(PNY_GPU_REG_ZONE_FRONT, modes[active_mode].value, 0, 0xFF, 0, 0); + controller->SetZoneMode(PNY_GPU_REG_ZONE_ARROW, modes[active_mode].value, 0, 0xFF, 0, 0); + DeviceUpdateLEDs(); + } +} \ No newline at end of file diff --git a/Controllers/PNYARGBEpicXGPUController/RGBController_PNYARGBEpicXGPU.h b/Controllers/PNYARGBEpicXGPUController/RGBController_PNYARGBEpicXGPU.h new file mode 100644 index 00000000..1a88be7a --- /dev/null +++ b/Controllers/PNYARGBEpicXGPUController/RGBController_PNYARGBEpicXGPU.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------*\ +| RGBController_PNYARGBEpicXGPU.h | +| | +| RGBController for PNY ARGB Epic-X GPU | +| | +| Peter Berendi 27 Apr 2025 | +| Adam Honse 01 Aug 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "PNYARGBEpicXGPUController.h" + +class RGBController_PNYARGBEpicXGPU : public RGBController +{ +public: + RGBController_PNYARGBEpicXGPU(PNYARGBEpicXGPUController* controller_ptr); + ~RGBController_PNYARGBEpicXGPU(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +protected: + PNYARGBEpicXGPUController* controller; + std::vector zone_led_idx; +}; diff --git a/Controllers/PNYGPUController/PNYGPUController.cpp b/Controllers/PNYGPUController/PNYGPUController.cpp index 296deb36..cc2ab6d5 100644 --- a/Controllers/PNYGPUController/PNYGPUController.cpp +++ b/Controllers/PNYGPUController/PNYGPUController.cpp @@ -1,18 +1,21 @@ -/*-----------------------------------------*\ -| PNYGPUController.cpp | -| | -| Driver for PNY GPU RGB (Turing) | -| lighting controller | -| | -| KendallMorgan 10/17/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| PNYGPUController.cpp | +| | +| Driver for PNY Turing GPU | +| | +| KendallMorgan 17 Oct 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "PNYGPUController.h" -PNYGPUController::PNYGPUController(i2c_smbus_interface* bus, pny_dev_id dev) +PNYGPUController::PNYGPUController(i2c_smbus_interface* bus, pny_dev_id dev, std::string name) { - this->bus = bus; - this->dev = dev; + this->bus = bus; + this->dev = dev; + this->name = name; } PNYGPUController::~PNYGPUController() @@ -20,6 +23,11 @@ PNYGPUController::~PNYGPUController() } +std::string PNYGPUController::GetDeviceName() +{ + return(name); +} + std::string PNYGPUController::GetDeviceLocation() { std::string return_string(bus->device_name); diff --git a/Controllers/PNYGPUController/PNYGPUController.h b/Controllers/PNYGPUController/PNYGPUController.h index b1b3a024..d32f9693 100644 --- a/Controllers/PNYGPUController/PNYGPUController.h +++ b/Controllers/PNYGPUController/PNYGPUController.h @@ -1,17 +1,19 @@ -/*-----------------------------------------*\ -| PNYGPUController.h | -| | -| Definitions and types for PNY GPU RGB | -| (Turing) lighting controller | -| | -| KendallMorgan 10/17/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| PNYGPUController.h | +| | +| Driver for PNY Turing GPU | +| | +| KendallMorgan 17 Oct 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" -#pragma once - typedef unsigned char pny_dev_id; enum @@ -35,9 +37,10 @@ enum class PNYGPUController { public: - PNYGPUController(i2c_smbus_interface* bus, pny_dev_id dev); + PNYGPUController(i2c_smbus_interface* bus, pny_dev_id dev, std::string name); ~PNYGPUController(); + std::string GetDeviceName(); std::string GetDeviceLocation(); void SetOff(); @@ -48,6 +51,7 @@ public: private: i2c_smbus_interface* bus; pny_dev_id dev; + std::string name; void WriteI2CData(u8 command, u8 length, u8* data); unsigned char GetMode(); diff --git a/Controllers/PNYGPUController/PNYGPUControllerDetect.cpp b/Controllers/PNYGPUController/PNYGPUControllerDetect.cpp index 93906a70..f82d3cb2 100644 --- a/Controllers/PNYGPUController/PNYGPUControllerDetect.cpp +++ b/Controllers/PNYGPUController/PNYGPUControllerDetect.cpp @@ -1,13 +1,19 @@ +/*---------------------------------------------------------*\ +| PNYGPUControllerDetect.cpp | +| | +| Detector for PNY Turing GPU | +| | +| KendallMorgan 17 Oct 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" -#include "LogManager.h" #include "PNYGPUController.h" -#include "RGBController.h" #include "RGBController_PNYGPU.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include /******************************************************************************************\ * * @@ -27,39 +33,46 @@ void DetectPNYGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const s return; } - PNYGPUController* controller = new PNYGPUController(bus, i2c_addr); + PNYGPUController* controller = new PNYGPUController(bus, i2c_addr, name); RGBController_PNYGPU* rgb_controller = new RGBController_PNYGPU(controller); - rgb_controller->name = name; - rgb_controller->vendor = name.substr(0, name.find(' ')); ResourceManager::get()->RegisterRGBController(rgb_controller); } /* DetectPNYGPUControllers() */ -REGISTER_I2C_PCI_DETECTOR("PNY XLR8 Revel EPIC-X RTX 3060", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, PNY_SUB_VEN, PNY_RTX_3060_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("PNY XLR8 Revel EPIC-X RTX 3070", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, PNY_SUB_VEN, PNY_RTX_3070_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("PNY XLR8 Revel EPIC-X RTX 3070 LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, PNY_SUB_VEN, PNY_RTX_3070_XLR8_REVEL_EPIC_X_LHR_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("PNY XLR8 Revel EPIC-X RTX 3080", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, PNY_SUB_VEN, PNY_RTX_3080_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("PNY XLR8 Revel EPIC-X RTX 3090", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, PNY_SUB_VEN, PNY_RTX_3090_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("PNY XLR8 OC EDITION RTX 2060", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU104_DEV, PNY_SUB_VEN, PNY_RTX_2060_XLR8_OC_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3060", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, PALIT_SUB_VEN, PALIT_RTX3060_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3060 LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3060_LHR_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3060Ti", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, PALIT_SUB_VEN, PALIT_RTX3060TI_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3060TI LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, PALIT_SUB_VEN, NVIDIA_RTX3060TI_LHR_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3070", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, PALIT_SUB_VEN, PALIT_RTX3070_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3070 LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3070_LHR_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3070Ti GamingPro", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, PALIT_SUB_VEN, PALIT_RTX3070TI_GAMING_PRO_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3070Ti", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, PALIT_SUB_VEN, PALIT_RTX3070TI_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3080", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, PALIT_SUB_VEN, PALIT_RTX3080_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3080 Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, PALIT_SUB_VEN, PALIT_RTX3080_GAMEROCK_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3080 Gamerock LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3080_GAMEROCK_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3080 LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3080_LHR_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3080 GamingPro 12G", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3080_GAMINGPRO_12G_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3080Ti", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, PALIT_SUB_VEN, PALIT_RTX3080TI_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3080Ti Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, PALIT_SUB_VEN, PALIT_RTX3080TI_GAMEROCK_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3090", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, PALIT_SUB_VEN, PALIT_RTX3090_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 3090 Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, PALIT_SUB_VEN, PALIT_RTX3090_GAMEROCK_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3060 Ti Dual", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, NVIDIA_SUB_VEN, PALIT_RTX3060TI_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 4070Ti Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, PALIT_SUB_VEN, PALIT_RTX4070TI_GAMEROCK_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("Palit 4090 Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, PALIT_SUB_VEN, PALIT_RTX4090_GAMEROCK_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("NVIDIA RTX2080S", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2080S_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("NVIDIA RTX2060S", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2060_TU106_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 2060 XLR8 OC EDITION", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU104_DEV, PNY_SUB_VEN, PNY_RTX_2060_XLR8_OC_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3060 XLR8 Revel EPIC-X", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, PNY_SUB_VEN, PNY_RTX_3060_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3070 XLR8 Revel EPIC-X", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, PNY_SUB_VEN, PNY_RTX_3070_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3070 XLR8 Revel EPIC-X LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, PNY_SUB_VEN, PNY_RTX_3070_XLR8_REVEL_EPIC_X_LHR_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3080 XLR8 Revel EPIC-X", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, PNY_SUB_VEN, PNY_RTX_3080_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3080 Ti XLR8 Revel EPIC-X", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, PNY_SUB_VEN, PNY_RTX_3080TI_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 3090 XLR8 Revel EPIC-X", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, PNY_SUB_VEN, PNY_RTX_3090_XLR8_REVEL_EPIC_X_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 2070 SUPER Jetstream", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2070S_OC_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3060", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_DEV, PALIT_SUB_VEN, PALIT_RTX3060_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3060 LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3060_LHR_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3060 Ti", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, PALIT_SUB_VEN, PALIT_RTX3060TI_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3060 Ti LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_LHR_DEV, PALIT_SUB_VEN, NVIDIA_RTX3060TI_LHR_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3060 Ti Dual", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3060TI_DEV, NVIDIA_SUB_VEN, PALIT_RTX3060TI_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3070", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_DEV, PALIT_SUB_VEN, PALIT_RTX3070_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3070 LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3070_LHR_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3070 Gamerock LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3070_GAMEROCK_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3070 Ti", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, PALIT_SUB_VEN, PALIT_RTX3070TI_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3070 Ti GamingPro", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, PALIT_SUB_VEN, PALIT_RTX3070TI_GAMING_PRO_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, PALIT_SUB_VEN, PALIT_RTX3080_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080 LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3080_LHR_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080 Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, PALIT_SUB_VEN, PALIT_RTX3080_GAMEROCK_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080 Gamerock LHR", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3080_GAMEROCK_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080 12GB GamingPro", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, PALIT_SUB_VEN, PALIT_RTX3080_GAMINGPRO_12G_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080 Ti", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, PALIT_SUB_VEN, PALIT_RTX3080TI_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3080 Ti Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, PALIT_SUB_VEN, PALIT_RTX3080TI_GAMEROCK_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3090", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, PALIT_SUB_VEN, PALIT_RTX3090_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 3090 Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, PALIT_SUB_VEN, PALIT_RTX3090_GAMEROCK_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4070 Ti", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, PALIT_SUB_VEN, PALIT_RTX4070TI_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4070 Ti Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, PALIT_SUB_VEN, PALIT_RTX4070TI_GAMEROCK_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4070 Ti SUPER GamingPro", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, PALIT_SUB_VEN, PALIT_RTX4080_GAMINGPRO_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4080 GamingPro", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, PALIT_SUB_VEN, PALIT_RTX4080_GAMINGPRO_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4080 SUPER GamingPro", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080S_DEV, PALIT_SUB_VEN, PALIT_RTX4080_GAMINGPRO_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 4090 Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, PALIT_SUB_VEN, PALIT_RTX4090_GAMEROCK_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5070 GamingPro", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX5070_DEV, PALIT_SUB_VEN, PALIT_RTX5070_GAMINGPRO_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce RTX 5090 Gamerock", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX5090_DEV, PALIT_SUB_VEN, PALIT_RTX5090_GAMEROCK_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("NVIDIA GeForce RTX 2060 SUPER", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX2060_TU106_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2060_TU106_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("NVIDIA GeForce RTX 2080 SUPER", DetectPNYGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, NVIDIA_SUB_VEN, NVIDIA_RTX2080S_DEV, 0x49); diff --git a/Controllers/PNYGPUController/RGBController_PNYGPU.cpp b/Controllers/PNYGPUController/RGBController_PNYGPU.cpp index 54527743..46013786 100644 --- a/Controllers/PNYGPUController/RGBController_PNYGPU.cpp +++ b/Controllers/PNYGPUController/RGBController_PNYGPU.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_PNYGPU.cpp | -| | -| Generic RGB Interface for OpenRGB PNY | -| GPU (Turing) Driver | -| | -| KendallMorgan 10/17/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_PNYGPU.cpp | +| | +| RGBController for PNY Turing GPU | +| | +| KendallMorgan 17 Oct 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_PNYGPU.h" @@ -24,8 +26,8 @@ RGBController_PNYGPU::RGBController_PNYGPU(PNYGPUController* controller_ptr) { controller = controller_ptr; - name = "PNY/Palit GPU"; - vendor = "PNY/Palit"; + name = controller->GetDeviceName(); + vendor = name.substr(0, name.find(' ')); description = "PNY/Palit RGB GPU Device"; location = controller->GetDeviceLocation(); diff --git a/Controllers/PNYGPUController/RGBController_PNYGPU.h b/Controllers/PNYGPUController/RGBController_PNYGPU.h index 966823d8..a268eb92 100644 --- a/Controllers/PNYGPUController/RGBController_PNYGPU.h +++ b/Controllers/PNYGPUController/RGBController_PNYGPU.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_PNYGPU.h | -| | -| Generic RGB Interface for OpenRGB | -| PNY GPU RGB (Turing) Driver | -| | -| KendallMorgan 10/17/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_PNYGPU.h | +| | +| RGBController for PNY Turing GPU | +| | +| KendallMorgan 17 Oct 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/PNYLovelaceGPUController/PNYLovelaceGPUController.cpp b/Controllers/PNYLovelaceGPUController/PNYLovelaceGPUController.cpp new file mode 100644 index 00000000..8f4c51a8 --- /dev/null +++ b/Controllers/PNYLovelaceGPUController/PNYLovelaceGPUController.cpp @@ -0,0 +1,79 @@ +/*---------------------------------------------------------*\ +| PNYLovelaceGPUController.cpp | +| | +| Driver for PNY Lovelace GPU | +| | +| yufan 01 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "PNYLovelaceGPUController.h" + +PNYLovelaceGPUController::PNYLovelaceGPUController(i2c_smbus_interface* bus, pny_dev_id dev, std::string dev_name) +{ + this->bus = bus; + this->dev = dev; + this->name = dev_name; +} + +PNYLovelaceGPUController::~PNYLovelaceGPUController() +{ + +} + +std::string PNYLovelaceGPUController::GetDeviceLocation() +{ + std::string return_string(bus->device_name); + char addr[5]; + snprintf(addr, 5, "0x%02X", dev); + return_string.append(", address "); + return_string.append(addr); + return("I2C: " + return_string); +} + +std::string PNYLovelaceGPUController::GetDeviceName() +{ + return(name); +} + +void PNYLovelaceGPUController::SetOff() +{ + unsigned char data[7] = {}; + bus->i2c_smbus_write_i2c_block_data(dev, PNY_GPU_REG_LIGHTING, sizeof(data), data); +} + +void PNYLovelaceGPUController::SetDirect(unsigned char led, unsigned char red, unsigned char green, unsigned char blue) +{ + unsigned char data[7] = {PNY_GPU_MODE_STATIC, 0xFF, led, 0x00, red, green, blue}; + bus->i2c_smbus_write_i2c_block_data(dev, PNY_GPU_REG_LIGHTING, sizeof(data), data); +} + +void PNYLovelaceGPUController::SetCycle(unsigned char speed, unsigned char brightness) +{ + speed = 0xB2 - speed; + unsigned char data[7] = {PNY_GPU_MODE_CYCLE, brightness, speed, 0x00, 0xAA, 0x00, 0x00}; + bus->i2c_smbus_write_i2c_block_data(dev, PNY_GPU_REG_LIGHTING, sizeof(data), data); +} + +void PNYLovelaceGPUController::SetBreath(unsigned char speed, unsigned char red, unsigned char green, unsigned char blue) +{ + speed = 0x19 - speed; + unsigned char data[7] = {PNY_GPU_MODE_BREATH, 0xFF, speed, 0x01, red, green, blue}; + bus->i2c_smbus_write_i2c_block_data(dev, PNY_GPU_REG_LIGHTING, sizeof(data), data); +} + +void PNYLovelaceGPUController::SetWave(unsigned char speed, unsigned char brightness) +{ + speed = 0xBF - speed; + unsigned char data[7] = {PNY_GPU_MODE_WAVE, brightness, speed, 0x00, 0xAA, 0x00, 0x00}; + bus->i2c_smbus_write_i2c_block_data(dev, PNY_GPU_REG_LIGHTING, sizeof(data), data); +} + +void PNYLovelaceGPUController::SetFlash(unsigned char speed, unsigned char brightness, unsigned char red, unsigned char green, unsigned char blue) +{ + speed = 0x4D - speed; + unsigned char data[7] = {PNY_GPU_MODE_FLASH, brightness, speed, 0x00, red, green, blue}; + bus->i2c_smbus_write_i2c_block_data(dev, PNY_GPU_REG_LIGHTING, sizeof(data), data); +} diff --git a/Controllers/PNYLovelaceGPUController/PNYLovelaceGPUController.h b/Controllers/PNYLovelaceGPUController/PNYLovelaceGPUController.h new file mode 100644 index 00000000..f9d10804 --- /dev/null +++ b/Controllers/PNYLovelaceGPUController/PNYLovelaceGPUController.h @@ -0,0 +1,55 @@ +/*---------------------------------------------------------*\ +| PNYLovelaceGPUController.h | +| | +| Driver for PNY Lovelace GPU | +| | +| yufan 01 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "i2c_smbus.h" + +typedef unsigned char pny_dev_id; + +enum +{ + PNY_GPU_MODE_OFF = 0x00, + PNY_GPU_MODE_BREATH = 0x02, + PNY_GPU_MODE_CYCLE = 0x03, + PNY_GPU_MODE_WAVE = 0x04, + PNY_GPU_MODE_FLASH = 0x05, + PNY_GPU_MODE_STATIC = 0x06, +}; + +enum +{ + PNY_GPU_REG_LIGHTING = 0x02, +}; + +class PNYLovelaceGPUController +{ +public: + PNYLovelaceGPUController(i2c_smbus_interface* bus, pny_dev_id dev, std::string dev_name); + ~PNYLovelaceGPUController(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + + void SetOff(); + void SetBreath(unsigned char speed, unsigned char red, unsigned char green, unsigned char blue); + void SetCycle(unsigned char speed, unsigned char brightness); + void SetWave(unsigned char speed, unsigned char brightness); + void SetFlash(unsigned char speed, unsigned char brightness, unsigned char red, unsigned char green, unsigned char blue); + void SetDirect(unsigned char led, unsigned char red, unsigned char green, unsigned char blue); + +private: + i2c_smbus_interface* bus; + pny_dev_id dev; + std::string name; +}; + diff --git a/Controllers/PNYLovelaceGPUController/PNYLovelaceGPUControllerDetect.cpp b/Controllers/PNYLovelaceGPUController/PNYLovelaceGPUControllerDetect.cpp new file mode 100644 index 00000000..f197678d --- /dev/null +++ b/Controllers/PNYLovelaceGPUController/PNYLovelaceGPUControllerDetect.cpp @@ -0,0 +1,51 @@ +/*---------------------------------------------------------*\ +| PNYLovelaceGPUControllerDetect.cpp | +| | +| Detector for PNY Lovelace GPU | +| | +| yufan 01 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "PNYLovelaceGPUController.h" +#include "RGBController_PNYLovelaceGPU.h" +#include "i2c_smbus.h" +#include "pci_ids.h" + +/*-----------------------------------------------------------------------------------------*\ +| DetectPNYLovelaceGPUControllers | +| | +| Detect PNY 40xx GPU controllers on the enumerated I2C busses at address 0x60. | +| | +| bus - pointer to i2c_smbus_interface where PNY GPU device is connected | +| dev - I2C address of PNY GPU device | +\*-----------------------------------------------------------------------------------------*/ + +void DetectPNYLovelaceGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name) +{ + if(bus->port_id != 1) + { + return; + } + + PNYLovelaceGPUController* controller = new PNYLovelaceGPUController(bus, i2c_addr, name); + RGBController_PNYLovelaceGPU* rgb_controller = new RGBController_PNYLovelaceGPU(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); +} /* DetectPNYLovelaceGPUControllers() */ + +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 4070 Ti XLR8 VERTO Epic-X", DetectPNYLovelaceGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, PNY_SUB_VEN, PNY_RTX_4070TI_XLR8_VERTO_EPIC_X_SUB_DEV, 0x60); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 4070 Ti XLR8 VERTO REV1", DetectPNYLovelaceGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, PNY_SUB_VEN, PNY_RTX_4070TI_XLR8_VERTO_REV1_SUB_DEV, 0x60); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 4070 Ti XLR8 VERTO REV2", DetectPNYLovelaceGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, PNY_SUB_VEN, PNY_RTX_4070TI_XLR8_VERTO_REV2_SUB_DEV, 0x60); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 4070 Ti XLR8 VERTO OC", DetectPNYLovelaceGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, PNY_SUB_VEN, PNY_RTX_4070TI_XLR8_VERTO_OC_SUB_DEV, 0x60); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 4070 Ti Super XLR8 VERTO OC", DetectPNYLovelaceGPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TIS_DEV, PNY_SUB_VEN, PNY_RTX_4070TIS_XLR8_VERTO_OC_SUB_DEV, 0x60); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 4080 XLR8 UPRISING", DetectPNYLovelaceGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, PNY_SUB_VEN, PNY_RTX_4080_XLR8_UPRISING_SUB_DEV, 0x60); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 4080 XLR8 VERTO", DetectPNYLovelaceGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, PNY_SUB_VEN, PNY_RTX_4080_XLR8_VERTO_SUB_DEV, 0x60); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 4080 SUPER XLR8 VERTO", DetectPNYLovelaceGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080S_DEV, PNY_SUB_VEN, PNY_RTX_4080S_XLR8_VERTO_SUB_DEV, 0x60); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 4080 XLR8 Verto Epic-X", DetectPNYLovelaceGPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, PNY_SUB_VEN, PNY_RTX_4080_XLR8_VERTO_EPIC_X_SUB_DEV, 0x60); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 4090 XLR8 VERTO", DetectPNYLovelaceGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, PNY_SUB_VEN, PNY_RTX_4090_XLR8_VERTO_SUB_DEV, 0x60); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 4090 XLR8 Verto Epic-X", DetectPNYLovelaceGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, PNY_SUB_VEN, PNY_RTX_4090_VERTO_EPIC_X_SUB_DEV, 0x60); +REGISTER_I2C_PCI_DETECTOR("PNY GeForce RTX 4090 XLR8 Verto Epic-X OC", DetectPNYLovelaceGPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, PNY_SUB_VEN, PNY_RTX_4090_VERTO_EPIC_X_OC_SUB_DEV, 0x60); diff --git a/Controllers/PNYLovelaceGPUController/RGBController_PNYLovelaceGPU.cpp b/Controllers/PNYLovelaceGPUController/RGBController_PNYLovelaceGPU.cpp new file mode 100644 index 00000000..be22e956 --- /dev/null +++ b/Controllers/PNYLovelaceGPUController/RGBController_PNYLovelaceGPU.cpp @@ -0,0 +1,199 @@ +/*---------------------------------------------------------*\ +| RGBController_PNYLovelaceGPU.cpp | +| | +| RGBController for PNY Lovelace GPU | +| | +| yufan 01 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_PNYLovelaceGPU.h" + +/**------------------------------------------------------------------*\ + @name PNY GPU 40xx + @category GPU + @type I2C + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectPNYLovelaceGPUControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_PNYLovelaceGPU::RGBController_PNYLovelaceGPU(PNYLovelaceGPUController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "PNY"; + description = "PNY RGB GPU Device"; + location = controller->GetDeviceLocation(); + type = DEVICE_TYPE_GPU; + + mode Direct; + Direct.name = "Direct"; + Direct.value = PNY_GPU_MODE_STATIC; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Cycle; + Cycle.name = "Cycle"; + Cycle.value = PNY_GPU_MODE_CYCLE; + Cycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Cycle.speed = 0x89; + Cycle.speed_min = 0; + Cycle.speed_max = 0xB2; + Cycle.brightness = 0xFF; + Cycle.brightness_min = 0; + Cycle.brightness_max = 0xFF; + Cycle.color_mode = MODE_COLORS_NONE; + modes.push_back(Cycle); + + mode Breath; + Breath.name = "Breath"; + Breath.value = PNY_GPU_MODE_BREATH; + Breath.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Breath.speed = 0x09; + Breath.speed_min = 0; + Breath.speed_max = 0x19; + Breath.colors_min = 1; + Breath.colors_max = 1; + Breath.colors.resize(1); + Breath.color_mode = MODE_COLORS_MODE_SPECIFIC; + modes.push_back(Breath); + + mode Wave; + Wave.name = "Wave"; + Wave.value = PNY_GPU_MODE_WAVE; + Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Wave.speed = 0x60; + Wave.speed_min = 0; + Wave.speed_max = 0xBF; + Wave.brightness = 0xFF; + Wave.brightness_min = 0; + Wave.brightness_max = 0xFF; + Wave.color_mode = MODE_COLORS_NONE; + modes.push_back(Wave); + + mode Flash; + Flash.name = "Flash"; + Flash.value = PNY_GPU_MODE_FLASH; + Flash.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Flash.speed = 0x27; + Flash.speed_min = 0; + Flash.speed_max = 0x4D; + Flash.brightness = 0xFF; + Flash.brightness_min = 0; + Flash.brightness_max = 0xFF; + Flash.colors_min = 1; + Flash.colors_max = 1; + Flash.colors.resize(1); + Flash.color_mode = MODE_COLORS_MODE_SPECIFIC; + modes.push_back(Flash); + + mode Off; + Off.name = "Off"; + Off.value = PNY_GPU_MODE_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + SetupZones(); + + // Initialize active mode + active_mode = 0; +} + +void RGBController_PNYLovelaceGPU::SetupZones() +{ + /*---------------------------------------------------------*\ + | This device only has 3 LED, so create a single zone. | + \*---------------------------------------------------------*/ + zone* new_zone = new zone(); + + new_zone->name = "GPU Zone"; + new_zone->type = ZONE_TYPE_SINGLE; + new_zone->leds_min = 3; + new_zone->leds_max = 3; + new_zone->leds_count = 3; + new_zone->matrix_map = NULL; + + led* new_led = new led(); + new_led->name = "Fan LED"; + leds.push_back(*new_led); + + new_led = new led(); + new_led->name = "Right LED"; + leds.push_back(*new_led); + + new_led = new led(); + new_led->name = "Left LED"; + leds.push_back(*new_led); + + zones.push_back(*new_zone); + SetupColors(); +} + +void RGBController_PNYLovelaceGPU::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_PNYLovelaceGPU::DeviceUpdateLEDs() +{ + DeviceUpdateMode(); +} + +void RGBController_PNYLovelaceGPU::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateMode(); +} + +void RGBController_PNYLovelaceGPU::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateMode(); +} + +void RGBController_PNYLovelaceGPU::DeviceUpdateMode() +{ + switch(modes[active_mode].value) + { + case PNY_GPU_MODE_OFF: + controller->SetOff(); + break; + + case PNY_GPU_MODE_STATIC: + for (int i = 0; i < 3; i++) + { + RGBColor color = GetLED(i); + controller->SetDirect(i, RGBGetRValue(color), RGBGetGValue(color), RGBGetBValue(color)); + } + break; + case PNY_GPU_MODE_CYCLE: + controller->SetCycle(modes[active_mode].speed, modes[active_mode].brightness); + break; + case PNY_GPU_MODE_BREATH: + { + RGBColor color = modes[active_mode].colors[0]; + controller->SetBreath(modes[active_mode].speed, RGBGetRValue(color), RGBGetGValue(color), RGBGetBValue(color)); + break; + } + case PNY_GPU_MODE_WAVE: + controller->SetWave(modes[active_mode].speed, modes[active_mode].brightness); + break; + case PNY_GPU_MODE_FLASH: + { + RGBColor color = modes[active_mode].colors[0]; + controller->SetFlash(modes[active_mode].speed, modes[active_mode].brightness, + RGBGetRValue(color), RGBGetGValue(color), RGBGetBValue(color)); + break; + } + default: + break; + } +} diff --git a/Controllers/PNYLovelaceGPUController/RGBController_PNYLovelaceGPU.h b/Controllers/PNYLovelaceGPUController/RGBController_PNYLovelaceGPU.h new file mode 100644 index 00000000..9cba26c7 --- /dev/null +++ b/Controllers/PNYLovelaceGPUController/RGBController_PNYLovelaceGPU.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------*\ +| RGBController_PNYLovelaceGPU.h | +| | +| RGBController for PNY Lovelace GPU | +| | +| yufan 01 Oct 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "PNYLovelaceGPUController.h" + +class RGBController_PNYLovelaceGPU : public RGBController +{ +public: + RGBController_PNYLovelaceGPU(PNYLovelaceGPUController* controller_ptr); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + PNYLovelaceGPUController* controller; +}; diff --git a/Controllers/PalitGPUController/PalitGPUController.cpp b/Controllers/PalitGPUController/PalitGPUController.cpp index 630e5b9f..5fd7d794 100644 --- a/Controllers/PalitGPUController/PalitGPUController.cpp +++ b/Controllers/PalitGPUController/PalitGPUController.cpp @@ -1,18 +1,21 @@ -/*-----------------------------------------*\ -| PalitGPUController.cpp | -| | -| Driver for Palit GPU RGB | -| lighting controller | -| | -| Manatsawin Hanmongkolchai 04/11/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| PalitGPUController.cpp | +| | +| Driver for Palit GPU | +| | +| Manatsawin Hanmongkolchai 11 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "PalitGPUController.h" -PalitGPUController::PalitGPUController(i2c_smbus_interface* bus, palit_dev_id dev) +PalitGPUController::PalitGPUController(i2c_smbus_interface* bus, palit_dev_id dev, std::string dev_name) { - this->bus = bus; - this->dev = dev; + this->bus = bus; + this->dev = dev; + this->name = dev_name; } PalitGPUController::~PalitGPUController() @@ -30,6 +33,11 @@ std::string PalitGPUController::GetDeviceLocation() return("I2C: " + return_string); } +std::string PalitGPUController::GetName() +{ + return(name); +} + void PalitGPUController::SetDirect(unsigned char red, unsigned char green, unsigned char blue) { // NvAPI_I2CWriteEx: Dev: 0x08 RegSize: 0x01 Reg: 0x03 Size: 0x04 Data: 0xFF 0x00 0x00 0xFF diff --git a/Controllers/PalitGPUController/PalitGPUController.h b/Controllers/PalitGPUController/PalitGPUController.h index 2d3cf342..1d8bad95 100644 --- a/Controllers/PalitGPUController/PalitGPUController.h +++ b/Controllers/PalitGPUController/PalitGPUController.h @@ -1,41 +1,44 @@ -/*-----------------------------------------*\ -| PalitGPUController.h | -| | -| Definitions and types for Palit GPU RGB | -| lighting controller | -| | -| Manatsawin Hanmongkolchai 04/11/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| PalitGPUController.h | +| | +| Driver for Palit GPU | +| | +| Manatsawin Hanmongkolchai 11 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" -#pragma once - -typedef unsigned char palit_dev_id; +typedef unsigned char palit_dev_id; enum { - PALIT_GPU_MODE_DIRECT = 0x00, + PALIT_GPU_MODE_DIRECT = 0x00, }; enum { - PALIT_GPU_REG_LED = 0x03, + PALIT_GPU_REG_LED = 0x03, }; class PalitGPUController { public: - PalitGPUController(i2c_smbus_interface* bus, palit_dev_id dev); + PalitGPUController(i2c_smbus_interface* bus, palit_dev_id dev, std::string dev_name); ~PalitGPUController(); - std::string GetDeviceLocation(); + std::string GetDeviceLocation(); + std::string GetName(); - void SetDirect(unsigned char red, unsigned char green, unsigned char blue); + void SetDirect(unsigned char red, unsigned char green, unsigned char blue); private: i2c_smbus_interface* bus; - palit_dev_id dev; - + palit_dev_id dev; + std::string name; }; diff --git a/Controllers/PalitGPUController/PalitGPUControllerDetect.cpp b/Controllers/PalitGPUController/PalitGPUControllerDetect.cpp index a6b44f7a..653ea666 100644 --- a/Controllers/PalitGPUController/PalitGPUControllerDetect.cpp +++ b/Controllers/PalitGPUController/PalitGPUControllerDetect.cpp @@ -1,13 +1,21 @@ +/*---------------------------------------------------------*\ +| PalitGPUControllerDetect.cpp | +| | +| Detector for Palit GPU | +| | +| Manatsawin Hanmongkolchai 11 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include #include "Detector.h" -#include "LogManager.h" #include "PalitGPUController.h" -#include "RGBController.h" #include "RGBController_PalitGPU.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include /******************************************************************************************\ * * @@ -17,7 +25,8 @@ * * * bus - pointer to i2c_smbus_interface where Palit GPU device is connected * * dev - I2C address of Palit GPU device * - * * + * * * + * Ligolas Neo Malicdem - Added 1060, 1070, 1070ti support * \******************************************************************************************/ void DetectPalitGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name) @@ -27,22 +36,29 @@ void DetectPalitGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const return; } + /*-----------------------------------------------------*\ + | Check for PALIT string | + \*-----------------------------------------------------*/ const uint8_t palit[] = {'P', 'A', 'L', 'I', 'T'}; - for (size_t i = 0; i < sizeof(palit); i++) + + for(size_t i = 0; i < sizeof(palit); i++) { - int32_t letter = bus->i2c_smbus_read_byte_data(i2c_addr, 0x07 + i); - if (palit[i] != letter) + int32_t letter = bus->i2c_smbus_read_byte_data(i2c_addr, 0x07 + (u8)i); + + if(palit[i] != letter) { return; } } - PalitGPUController* controller = new PalitGPUController(bus, i2c_addr); + PalitGPUController* controller = new PalitGPUController(bus, i2c_addr, name); RGBController_PalitGPU* rgb_controller = new RGBController_PalitGPU(controller); - rgb_controller->name = name; - rgb_controller->vendor = name.substr(0, name.find(' ')); ResourceManager::get()->RegisterRGBController(rgb_controller); } /* DetectPalitGPUControllers() */ -REGISTER_I2C_PCI_DETECTOR("Palit 1080", DetectPalitGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1080_DEV, 0x08); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce GTX 1060", DetectPalitGPUControllers, NVIDIA_VEN, NVIDIA_GTX1060_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1060_DEV, 0x08); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce GTX 1070", DetectPalitGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1070_DEV, 0x08); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce GTX 1070 Ti", DetectPalitGPUControllers, NVIDIA_VEN, NVIDIA_GTX1070TI_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1070TI_DEV, 0x08); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce GTX 1080", DetectPalitGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1080_DEV, 0x08); +REGISTER_I2C_PCI_DETECTOR("Palit GeForce GTX 1080 Ti", DetectPalitGPUControllers, NVIDIA_VEN, NVIDIA_GTX1080TI_DEV, NVIDIA_SUB_VEN, NVIDIA_GTX1080TI_DEV, 0x08); diff --git a/Controllers/PalitGPUController/RGBController_PalitGPU.cpp b/Controllers/PalitGPUController/RGBController_PalitGPU.cpp index 0522bd8f..3b07009b 100644 --- a/Controllers/PalitGPUController/RGBController_PalitGPU.cpp +++ b/Controllers/PalitGPUController/RGBController_PalitGPU.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_PalitGPU.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Palit GPU RGB Driver | -| | -| Manatsawin Hanmongkolchai 04/11/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_PalitGPU.cpp | +| | +| RGBController for Palit GPU | +| | +| Manatsawin Hanmongkolchai 11 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_PalitGPU.h" @@ -24,7 +26,7 @@ RGBController_PalitGPU::RGBController_PalitGPU(PalitGPUController* controller_pt { controller = controller_ptr; - name = "Palit GPU"; + name = controller->GetName(); vendor = "Palit"; description = "Legacy Palit RGB GPU Device"; location = controller->GetDeviceLocation(); @@ -50,8 +52,8 @@ void RGBController_PalitGPU::SetupZones() | This device only has one LED, so create a single zone and | | LED for it | \*---------------------------------------------------------*/ - zone* new_zone = new zone(); - led* new_led = new led(); + zone* new_zone = new zone(); + led* new_led = new led(); new_zone->name = "GPU Zone"; new_zone->type = ZONE_TYPE_SINGLE; diff --git a/Controllers/PalitGPUController/RGBController_PalitGPU.h b/Controllers/PalitGPUController/RGBController_PalitGPU.h index 3c2a6e6b..7b327364 100644 --- a/Controllers/PalitGPUController/RGBController_PalitGPU.h +++ b/Controllers/PalitGPUController/RGBController_PalitGPU.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_PalitGPU.h | -| | -| Generic RGB Interface for OpenRGB | -| Palit GPU RGB Driver | -| | -| Manatsawin Hanmongkolchai 04/11/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_PalitGPU.h | +| | +| RGBController for Palit GPU | +| | +| Manatsawin Hanmongkolchai 11 Apr 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/PatriotViperController/PatriotViperController.cpp b/Controllers/PatriotViperController/PatriotViperController.cpp index 5eff69fc..f12b7529 100644 --- a/Controllers/PatriotViperController/PatriotViperController.cpp +++ b/Controllers/PatriotViperController/PatriotViperController.cpp @@ -1,14 +1,16 @@ -/*-----------------------------------------*\ -| PatriotViperController.cpp | -| | -| Definitions and types for Patriot Viper | -| RGB RAM lighting controller | -| | -| Adam Honse (CalcProgrammer1) 1/1/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| PatriotViperController.cpp | +| | +| Driver for Patriot Viper RAM | +| | +| Adam Honse (CalcProgrammer1) 01 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "PatriotViperController.h" #include +#include "PatriotViperController.h" PatriotViperController::PatriotViperController(i2c_smbus_interface* bus, viper_dev_id dev, unsigned char slots) { diff --git a/Controllers/PatriotViperController/PatriotViperController.h b/Controllers/PatriotViperController/PatriotViperController.h index 57d8dcc0..88f886e1 100644 --- a/Controllers/PatriotViperController/PatriotViperController.h +++ b/Controllers/PatriotViperController/PatriotViperController.h @@ -1,20 +1,22 @@ -/*-----------------------------------------*\ -| PatriotViperController.h | -| | -| Definitions and types for Patriot Viper | -| RGB RAM lighting controller | -| | -| Adam Honse (CalcProgrammer1) 1/1/2020 | -\*-----------------------------------------*/ - -#include -#include -#include "i2c_smbus.h" +/*---------------------------------------------------------*\ +| PatriotViperController.h | +| | +| Driver for Patriot Viper RAM | +| | +| Adam Honse (CalcProgrammer1) 01 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -typedef unsigned char viper_dev_id; -typedef unsigned short viper_register; +#include +#include +#include "i2c_smbus.h" + +typedef unsigned char viper_dev_id; +typedef unsigned char viper_register; enum { @@ -94,7 +96,7 @@ private: viper_dev_id dev; unsigned char mode; unsigned char speed; - + std::thread* keepalive_thread; std::atomic keepalive_thread_run; std::atomic step; @@ -108,7 +110,7 @@ private: | and the Keepalive thread is not needed | \*-------------------------------------------------------*/ - std::map mode_steps = + std::map mode_steps = { {VIPER_MODE_DARK, -1}, {VIPER_MODE_BREATHING, 4}, @@ -120,7 +122,7 @@ private: {VIPER_MODE_NEON, 0}, }; - std::map mode_sub_steps = + std::map mode_sub_steps = { {VIPER_MODE_DARK, -1}, {VIPER_MODE_BREATHING, 1}, @@ -132,7 +134,7 @@ private: {VIPER_MODE_NEON, 5}, }; - std::map mode_speed = + std::map mode_speed = { {VIPER_MODE_DARK, -1}, {VIPER_MODE_BREATHING, 0x06}, diff --git a/Controllers/PatriotViperController/PatriotViperControllerDetect.cpp b/Controllers/PatriotViperController/PatriotViperControllerDetect.cpp index 21a6171d..b34d439b 100644 --- a/Controllers/PatriotViperController/PatriotViperControllerDetect.cpp +++ b/Controllers/PatriotViperController/PatriotViperControllerDetect.cpp @@ -1,13 +1,21 @@ +/*---------------------------------------------------------*\ +| PatriotViperControllerDetect.cpp | +| | +| Detector for Patriot Viper RAM | +| | +| Adam Honse (CalcProgrammer1) 01 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "PatriotViperController.h" #include "LogManager.h" -#include "RGBController.h" #include "RGBController_PatriotViper.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include using namespace std::chrono_literals; #define PATRIOT_CONTROLLER_NAME "Patriot Viper" @@ -49,67 +57,40 @@ bool TestForPatriotViperController(i2c_smbus_interface* bus, unsigned char addre * * \******************************************************************************************/ -void DetectPatriotViperControllers(std::vector &busses) +void DetectPatriotViperControllers(i2c_smbus_interface* bus, std::vector &slots, const std::string &/*name*/) { - for(unsigned int bus = 0; bus < busses.size(); bus++) + unsigned char slots_valid = 0x00; + + // Check for Patriot Viper controller at 0x77 + LOG_DEBUG("[%s] Testing bus %d at address 0x77", PATRIOT_CONTROLLER_NAME, bus->port_id); + + if(TestForPatriotViperController(bus, 0x77)) { - unsigned char slots_valid = 0x00; - - IF_DRAM_SMBUS(busses[bus]->pci_vendor, busses[bus]->pci_device) + for(SPDWrapper *slot : slots) { - // Check for Patriot Viper controller at 0x77 - LOG_DEBUG("[%s] Testing bus %d at address 0x77", PATRIOT_CONTROLLER_NAME, bus); - - if(TestForPatriotViperController(busses[bus], 0x77)) + if((slot->manufacturer_data(0x00) == 0x4D) + &&(slot->manufacturer_data(0x01) == 0x49) + &&(slot->manufacturer_data(0x02) == 0x43) + &&(slot->manufacturer_data(0x03) == 0x53) + &&(slot->manufacturer_data(0x04) == 0x59) + &&(slot->manufacturer_data(0x05) == 0x53) + &&(slot->manufacturer_data(0x06) == 0x5f) + &&(slot->manufacturer_data(0x07) == 0x44)) { - for(int slot_addr = 0x50; slot_addr <= 0x57; slot_addr++) - { - // Test for Patriot Viper RGB SPD at slot_addr - // This test was copied from Viper RGB software - // Tests SPD addresses in order: 0x00, 0x40, 0x41, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68 - - busses[bus]->i2c_smbus_write_byte_data(0x36, 0x00, 0xFF); - - std::this_thread::sleep_for(1ms); - - int res = busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x00); - - LOG_DEBUG("[%s] Trying to read 0x%02X RAM module data at 0x00 expect: 0x23 res: %02X", PATRIOT_CONTROLLER_NAME, slot_addr, res); - if(res == 0x23) - { - busses[bus]->i2c_smbus_write_byte_data(0x37, 0x00, 0xFF); - - std::this_thread::sleep_for(1ms); - - if((busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x40) == 0x85) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x41) == 0x02) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x61) == 0x4D) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x62) == 0x49) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x63) == 0x43) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x64) == 0x53) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x65) == 0x59) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x66) == 0x53) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x67) == 0x5f) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x68) == 0x44)) - { - LOG_DEBUG("[%s] The 0x%02X RAM module detected", PATRIOT_CONTROLLER_NAME, slot_addr); - slots_valid |= (1 << (slot_addr - 0x50)); - } - } - - std::this_thread::sleep_for(1ms); - } - - if(slots_valid != 0) - { - PatriotViperController* controller = new PatriotViperController(busses[bus], 0x77, slots_valid); - RGBController_PatriotViper* rgb_controller = new RGBController_PatriotViper(controller); - ResourceManager::get()->RegisterRGBController(rgb_controller); - } + LOG_DEBUG("[%s] The RAM module detected in slot %d", PATRIOT_CONTROLLER_NAME, slot->index()); + slots_valid |= (1 << (slot->index())); } } + + if(slots_valid != 0) + { + PatriotViperController* controller = new PatriotViperController(bus, 0x77, slots_valid); + RGBController_PatriotViper* rgb_controller = new RGBController_PatriotViper(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); + } } } /* DetectPatriotViperControllers() */ -REGISTER_I2C_DETECTOR(PATRIOT_CONTROLLER_NAME, DetectPatriotViperControllers); +REGISTER_I2C_DIMM_DETECTOR(PATRIOT_CONTROLLER_NAME, DetectPatriotViperControllers, JEDEC_PATRIOT, SPD_DDR4_SDRAM); + diff --git a/Controllers/PatriotViperController/RGBController_PatriotViper.cpp b/Controllers/PatriotViperController/RGBController_PatriotViper.cpp index 9d11c8f8..e154f0b8 100644 --- a/Controllers/PatriotViperController/RGBController_PatriotViper.cpp +++ b/Controllers/PatriotViperController/RGBController_PatriotViper.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_PatriotViper.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Patriot Viper RGB interface | -| | -| Adam Honse (CalcProgrammer1) 1/1/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_PatriotViper.cpp | +| | +| RGBController for Patriot Viper RAM | +| | +| Adam Honse (CalcProgrammer1) 01 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_PatriotViper.h" diff --git a/Controllers/PatriotViperController/RGBController_PatriotViper.h b/Controllers/PatriotViperController/RGBController_PatriotViper.h index f1dd766d..6896c14a 100644 --- a/Controllers/PatriotViperController/RGBController_PatriotViper.h +++ b/Controllers/PatriotViperController/RGBController_PatriotViper.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_PatriotViper.h | -| | -| Generic RGB Interface for OpenRGB | -| Patriot Viper RGB interface | -| | -| Adam Honse (CalcProgrammer1) 1/1/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_PatriotViper.h | +| | +| RGBController for Patriot Viper RAM | +| | +| Adam Honse (CalcProgrammer1) 01 Jan 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once @@ -20,7 +22,7 @@ public: void SetupZones(); void ResizeZone(int zone, int new_size); - + void DeviceUpdateLEDs(); void UpdateZoneLEDs(int zone); void UpdateSingleLED(int led); diff --git a/Controllers/PatriotViperMouseController/PatriotViperMouseController.cpp b/Controllers/PatriotViperMouseController/PatriotViperMouseController.cpp new file mode 100644 index 00000000..98b0fdda --- /dev/null +++ b/Controllers/PatriotViperMouseController/PatriotViperMouseController.cpp @@ -0,0 +1,85 @@ +/*---------------------------------------------------------*\ +| PatriotViperMouseController.cpp | +| | +| Detector for Patriot Viper Mouse | +| | +| mi4code 23 May 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include + +PatriotViperMouseController::PatriotViperMouseController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + + const unsigned char init_packet[64] = {0x01, 0x00, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x50, 0xDE, 0x8D, 0x77, 0x09, 0xDF, 0x8D, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x58, 0x7C, 0x77, 0x78, 0x81, 0x43, 0x00, 0x30, 0x58, 0x7C, 0x77, 0x8C, 0x5D, 0x9B, 0x77, 0x00, 0x00, 0x3D, 0x00, 0x98, 0xF5, 0x19, 0x08, 0x00, 0x00, 0x00, 0xEE}; + hid_send_feature_report(dev, init_packet, 64); +} + +PatriotViperMouseController::~PatriotViperMouseController() +{ + hid_close(dev); +} + +std::string PatriotViperMouseController::GetLocation() +{ + return("HID " + location); +} + +std::string PatriotViperMouseController::GetName() +{ + return(name); +} + +std::string PatriotViperMouseController::GetSerial() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + if(ret != 0) + { + serial_string[0] = '\0'; + } + return StringUtils::wstring_to_string(serial_string); +} + +void PatriotViperMouseController::SetRGB(std::vector colors) +{ + /*------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*\ + | led red green blue checksum | + \*------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ + unsigned char buffer[64] = { 0x01, 0x13, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC}; + + for(unsigned char led_index = 0x00; led_index < 0x07; led_index++) + { + buffer[2] = led_index; + buffer[4] = RGBGetRValue(colors[led_index]); + buffer[5] = RGBGetGValue(colors[led_index]); + buffer[6] = RGBGetBValue(colors[led_index]); + + /*--------------------------------------*\ + | calculate the last checksum byte | + \*--------------------------------------*/ + unsigned char xor_value = 0; + + for(int i = 0; i < 63; ++i) + { + xor_value ^= buffer[i]; + } + + if(xor_value % 2 == 0) + { + buffer[63] = (xor_value + 1) % 256; + } + else + { + buffer[63] = (xor_value - 1) % 256; + } + + hid_send_feature_report(dev, buffer, 64); + } +} diff --git a/Controllers/PatriotViperMouseController/PatriotViperMouseController.h b/Controllers/PatriotViperMouseController/PatriotViperMouseController.h new file mode 100644 index 00000000..3478c292 --- /dev/null +++ b/Controllers/PatriotViperMouseController/PatriotViperMouseController.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| PatriotViperMouseController.h | +| | +| Detector for Patriot Viper Mouse | +| | +| mi4code 23 May 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "StringUtils.h" +#include +#include "RGBController.h" + +class PatriotViperMouseController +{ +public: + PatriotViperMouseController(hid_device* dev_handle, const char* path, std::string dev_name); + ~PatriotViperMouseController(); + + std::string GetLocation(); + std::string GetName(); + std::string GetSerial(); + + void SetRGB(std::vector colors); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/PatriotViperMouseController/PatriotViperMouseControllerDetect.cpp b/Controllers/PatriotViperMouseController/PatriotViperMouseControllerDetect.cpp new file mode 100644 index 00000000..35be5700 --- /dev/null +++ b/Controllers/PatriotViperMouseController/PatriotViperMouseControllerDetect.cpp @@ -0,0 +1,38 @@ +/*---------------------------------------------------------*\ +| PatriotViperMouseControllerDetect.cpp | +| | +| Detector for Patriot Viper Mouse | +| | +| mi4code 07 Apr 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "PatriotViperMouseController.h" +#include "RGBController_PatriotViperMouse.h" + + +/*-----------------------------------------------------*\ +| Patriot Viper Mouse IDs | +\*-----------------------------------------------------*/ + +#define PATRIOT_VID 0x0C45 +#define VIPER_V550_PID 0x7E18 + + +void DetectPatriotViperMouseControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + PatriotViperMouseController* controller = new PatriotViperMouseController(dev, info->path, name); + RGBController_PatriotViperMouse* rgb_controller = new RGBController_PatriotViperMouse(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_HID_DETECTOR_IPU("Patriot Viper V550", DetectPatriotViperMouseControllers, PATRIOT_VID, VIPER_V550_PID, 2, 0xFF18, 0x01); diff --git a/Controllers/PatriotViperMouseController/RGBController_PatriotViperMouse.cpp b/Controllers/PatriotViperMouseController/RGBController_PatriotViperMouse.cpp new file mode 100644 index 00000000..aea8d8a3 --- /dev/null +++ b/Controllers/PatriotViperMouseController/RGBController_PatriotViperMouse.cpp @@ -0,0 +1,121 @@ +/*---------------------------------------------------------*\ +| RGBController_PatriotViperMouse.cpp | +| | +| RGBController for Patriot Viper Mouse | +| | +| mi4code 07 Apr 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_PatriotViperMouse.h" + +/**------------------------------------------------------------------*\ + @name Patriot Viper V550 + @category Mouse + @type USB + @save :o: + @direct :white_check_mark: + @effects :o: + @detectors DetectPatriotViperMouseControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_PatriotViperMouse::RGBController_PatriotViperMouse(PatriotViperMouseController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = "Patriot"; + type = DEVICE_TYPE_MOUSE; + description = "Patriot Viper Mouse"; + location = controller->GetLocation(); + serial = controller->GetSerial(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 1; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + SetupZones(); +}; + +RGBController_PatriotViperMouse::~RGBController_PatriotViperMouse() +{ + delete controller; +} + +void RGBController_PatriotViperMouse::SetupZones() +{ + zone left_zone; + left_zone.name = "Left"; + left_zone.type = ZONE_TYPE_LINEAR; + left_zone.leds_min = 3; + left_zone.leds_max = 3; + left_zone.leds_count = 3; + left_zone.matrix_map = NULL; + zones.push_back(left_zone); + + zone right_zone; + right_zone.name = "Right"; + right_zone.type = ZONE_TYPE_LINEAR; + right_zone.leds_min = 3; + right_zone.leds_max = 3; + right_zone.leds_count = 3; + right_zone.matrix_map = NULL; + zones.push_back(right_zone); + + zone wheel_zone; + wheel_zone.name = "Mousewheel"; + wheel_zone.type = ZONE_TYPE_SINGLE; + wheel_zone.leds_min = 1; + wheel_zone.leds_max = 1; + wheel_zone.leds_count = 1; + wheel_zone.matrix_map = NULL; + zones.push_back(wheel_zone); + + for(unsigned char i = 0x00; i < 0x07; i++) + { + led new_led; + new_led.name = "LED " + std::to_string(i+1); + leds.push_back(new_led); + } + + SetupColors(); +} + +void RGBController_PatriotViperMouse::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_PatriotViperMouse::DeviceUpdateLEDs() +{ + DeviceUpdateMode(); +} + +void RGBController_PatriotViperMouse::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_PatriotViperMouse::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_PatriotViperMouse::DeviceUpdateMode() +{ + /*-----------------*\ + | Direct mode | + \*-----------------*/ + if(modes[active_mode].value == 1) + { + controller->SetRGB(colors); + } +} diff --git a/Controllers/PatriotViperMouseController/RGBController_PatriotViperMouse.h b/Controllers/PatriotViperMouseController/RGBController_PatriotViperMouse.h new file mode 100644 index 00000000..5d9ea63b --- /dev/null +++ b/Controllers/PatriotViperMouseController/RGBController_PatriotViperMouse.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_PatriotViperMouse.h | +| | +| RGBController for Patriot Viper Mouse | +| | +| mi4code 07 Apr 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "PatriotViperMouseController.h" + +class RGBController_PatriotViperMouse : public RGBController +{ +public: + RGBController_PatriotViperMouse(PatriotViperMouseController* controller_ptr); + ~RGBController_PatriotViperMouse(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + PatriotViperMouseController* controller; +}; diff --git a/Controllers/PatriotViperSteelController/PatriotViperSteelController.cpp b/Controllers/PatriotViperSteelController/PatriotViperSteelController.cpp index 17a13bdc..d9a716b0 100644 --- a/Controllers/PatriotViperSteelController/PatriotViperSteelController.cpp +++ b/Controllers/PatriotViperSteelController/PatriotViperSteelController.cpp @@ -1,12 +1,14 @@ -/*-----------------------------------------*\ -| PatriotViperSteelController.cpp | -| | -| Definitions and types for Patriot Viper | -| Steel RGB RAM lighting controller | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| PatriotViperSteelController.cpp | +| | +| Driver for Patriot Viper Steel RAM | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "PatriotViperSteelController.h" #include +#include "PatriotViperSteelController.h" PatriotViperSteelController::PatriotViperSteelController(i2c_smbus_interface *bus, viper_dev_id dev) { diff --git a/Controllers/PatriotViperSteelController/PatriotViperSteelController.h b/Controllers/PatriotViperSteelController/PatriotViperSteelController.h index a1a77500..14d5afe2 100644 --- a/Controllers/PatriotViperSteelController/PatriotViperSteelController.h +++ b/Controllers/PatriotViperSteelController/PatriotViperSteelController.h @@ -1,17 +1,19 @@ -/*-----------------------------------------*\ -| PatriotViperController.h | -| | -| Definitions and types for Patriot Viper | -| RGB RAM lighting controller | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| PatriotViperSteelController.h | +| | +| Driver for Patriot Viper Steel RAM | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" -#pragma once - typedef unsigned char viper_dev_id; -typedef unsigned short viper_register; +typedef unsigned char viper_register; enum { @@ -48,5 +50,4 @@ private: i2c_smbus_interface *bus; viper_dev_id dev; unsigned char mode; - unsigned char speed; }; diff --git a/Controllers/PatriotViperSteelController/PatriotViperSteelControllerDetect.cpp b/Controllers/PatriotViperSteelController/PatriotViperSteelControllerDetect.cpp index 110f241a..fba0e9e1 100644 --- a/Controllers/PatriotViperSteelController/PatriotViperSteelControllerDetect.cpp +++ b/Controllers/PatriotViperSteelController/PatriotViperSteelControllerDetect.cpp @@ -1,13 +1,19 @@ +/*---------------------------------------------------------*\ +| PatriotViperSteelControllerDetect.cpp | +| | +| Detector for Patriot Viper Steel RAM | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "PatriotViperSteelController.h" #include "LogManager.h" -#include "RGBController.h" #include "RGBController_PatriotViperSteel.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include -#include -#include using namespace std::chrono_literals; #define PATRIOT_CONTROLLER_NAME "Patriot Viper Steel" @@ -49,67 +55,40 @@ bool TestForPatriotViperSteelController(i2c_smbus_interface* bus, unsigned char * * \******************************************************************************************/ -void DetectPatriotViperSteelControllers(std::vector &busses) +void DetectPatriotViperSteelControllers(i2c_smbus_interface* bus, std::vector &slots, const std::string &/*name*/) { - for(unsigned int bus = 0; bus < busses.size(); bus++) + unsigned char slots_valid = 0x00; + + // Check for Patriot Viper controller at 0x77 + LOG_DEBUG("[%s] Testing bus %d at address 0x77", PATRIOT_CONTROLLER_NAME, bus->port_id); + + if(TestForPatriotViperSteelController(bus, 0x77)) { - unsigned char slots_valid = 0x00; - - IF_DRAM_SMBUS(busses[bus]->pci_vendor, busses[bus]->pci_device) + for(SPDWrapper *slot : slots) { - // Check for Patriot Viper Steel controller at 0x77 - LOG_DEBUG("[%s] Testing bus %d at address 0x77", PATRIOT_CONTROLLER_NAME, bus); - - if(TestForPatriotViperSteelController(busses[bus], 0x77)) + if((slot->manufacturer_data(0x00) == 0x50) + &&(slot->manufacturer_data(0x01) == 0x44) + &&(slot->manufacturer_data(0x02) == 0x41) + &&(slot->manufacturer_data(0x03) == 0x31) + &&(slot->manufacturer_data(0x04) == 0x00) + &&(slot->manufacturer_data(0x05) == 0x00) + &&(slot->manufacturer_data(0x06) == 0x00) + &&(slot->manufacturer_data(0x07) == 0x00)) { - for(int slot_addr = 0x50; slot_addr <= 0x57; slot_addr++) - { - // Test for Patriot Viper Steel RGB SPD at slot_addr - // This test was copied from PatriotViperControllerDetect - // Tests SPD addresses in order: 0x00, 0x40, 0x41, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68 - - busses[bus]->i2c_smbus_write_byte_data(0x36, 0x00, 0xFF); - - std::this_thread::sleep_for(1ms); - - int res = busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x00); - - LOG_DEBUG("[%s] Trying to read 0x%02X RAM module data at 0x00 expect: 0x23 res: %02X", PATRIOT_CONTROLLER_NAME, slot_addr, res); - if(res == 0x23) - { - busses[bus]->i2c_smbus_write_byte_data(0x37, 0x00, 0xFF); - - std::this_thread::sleep_for(1ms); - - if((busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x40) == 0xFF) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x41) == 0xFF) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x61) == 0x50) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x62) == 0x44) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x63) == 0x41) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x64) == 0x31) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x65) == 0x00) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x66) == 0x00) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x67) == 0x00) - &&(busses[bus]->i2c_smbus_read_byte_data(slot_addr, 0x68) == 0x00)) - { - LOG_DEBUG("[%s] The 0x%02X RAM module detected", PATRIOT_CONTROLLER_NAME, slot_addr); - slots_valid |= (1 << (slot_addr - 0x50)); - } - } - - std::this_thread::sleep_for(1ms); - } - - if(slots_valid != 0) - { - PatriotViperSteelController* controller = new PatriotViperSteelController(busses[bus], 0x77); - RGBController_PatriotViperSteel* rgb_controller = new RGBController_PatriotViperSteel(controller); - ResourceManager::get()->RegisterRGBController(rgb_controller); - } + LOG_DEBUG("[%s] The RAM module detected in slot %d", PATRIOT_CONTROLLER_NAME, slot->index()); + slots_valid |= (1 << (slot->index())); } } + + if(slots_valid != 0) + { + PatriotViperSteelController* controller = new PatriotViperSteelController(bus, 0x77); + RGBController_PatriotViperSteel* rgb_controller = new RGBController_PatriotViperSteel(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); + } } } /* DetectPatriotViperSteelControllers() */ -REGISTER_I2C_DETECTOR(PATRIOT_CONTROLLER_NAME, DetectPatriotViperSteelControllers); +REGISTER_I2C_DIMM_DETECTOR(PATRIOT_CONTROLLER_NAME, DetectPatriotViperSteelControllers, 0xFF7E, SPD_DDR4_SDRAM); + diff --git a/Controllers/PatriotViperSteelController/RGBController_PatriotViperSteel.cpp b/Controllers/PatriotViperSteelController/RGBController_PatriotViperSteel.cpp index 2cf2f5e3..dd7a2560 100644 --- a/Controllers/PatriotViperSteelController/RGBController_PatriotViperSteel.cpp +++ b/Controllers/PatriotViperSteelController/RGBController_PatriotViperSteel.cpp @@ -1,9 +1,11 @@ -/*-----------------------------------------*\ -| RGBController_PatriotViperSteel.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Patriot Viper Steel RGB interface | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_PatriotViperSteel.cpp | +| | +| RGBController for Patriot Viper Steel RAM | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_PatriotViperSteel.h" diff --git a/Controllers/PatriotViperSteelController/RGBController_PatriotViperSteel.h b/Controllers/PatriotViperSteelController/RGBController_PatriotViperSteel.h index b29f6628..afdb84c4 100644 --- a/Controllers/PatriotViperSteelController/RGBController_PatriotViperSteel.h +++ b/Controllers/PatriotViperSteelController/RGBController_PatriotViperSteel.h @@ -1,9 +1,11 @@ -/*---------------------------------------------*\ -| RGBController_PatriotViperSteel.h | -| | -| Generic RGB Interface for OpenRGB | -| Patriot Viper Steel RGB interface | -\*---------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_PatriotViperSteel.h | +| | +| RGBController for Patriot Viper Steel RAM | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/PhilipsHueController/PhilipsHueController.cpp b/Controllers/PhilipsHueController/PhilipsHueController.cpp index 4faf78c4..e5ad88e2 100644 --- a/Controllers/PhilipsHueController/PhilipsHueController.cpp +++ b/Controllers/PhilipsHueController/PhilipsHueController.cpp @@ -1,7 +1,12 @@ /*---------------------------------------------------------*\ -| Driver for Philips Hue | +| PhilipsHueController.cpp | | | -| Adam Honse (calcprogrammer1@gmail.com), 9/15/2020 | +| Driver for Philips Hue | +| | +| Adam Honse (calcprogrammer1@gmail.com) 15 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ #include "PhilipsHueController.h" @@ -64,7 +69,7 @@ void PhilipsHueController::SetColor(unsigned char red, unsigned char green, unsi } } - dark = true; + dark = true; } else { diff --git a/Controllers/PhilipsHueController/PhilipsHueController.h b/Controllers/PhilipsHueController/PhilipsHueController.h index 65b42183..f94b15b8 100644 --- a/Controllers/PhilipsHueController/PhilipsHueController.h +++ b/Controllers/PhilipsHueController/PhilipsHueController.h @@ -1,15 +1,19 @@ /*---------------------------------------------------------*\ -| Definitions for Philips Hue | +| PhilipsHueController.h | | | -| Adam Honse (calcprogrammer1@gmail.com), 9/15/2020 | +| Driver for Philips Hue | +| | +| Adam Honse (calcprogrammer1@gmail.com) 15 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "HueDeviceTypes.h" +#pragma once #include #include - -#pragma once +#include "HueDeviceTypes.h" class PhilipsHueController { diff --git a/Controllers/PhilipsHueController/PhilipsHueControllerDetect.cpp b/Controllers/PhilipsHueController/PhilipsHueControllerDetect.cpp index 9d78c52f..e7218aee 100644 --- a/Controllers/PhilipsHueController/PhilipsHueControllerDetect.cpp +++ b/Controllers/PhilipsHueController/PhilipsHueControllerDetect.cpp @@ -1,3 +1,14 @@ +/*---------------------------------------------------------*\ +| PhilipsHueControllerDetect.cpp | +| | +| Detector for Philips Hue | +| | +| Adam Honse (calcprogrammer1@gmail.com) 15 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Bridge.h" #include "HueDeviceTypes.h" @@ -13,7 +24,7 @@ #include "PhilipsHueEntertainmentController.h" #include "RGBController_PhilipsHue.h" #include "RGBController_PhilipsHueEntertainment.h" -#include "SettingsManager.h" +#include "PhilipsHueSettingsHandler.h" /******************************************************************************************\ * * @@ -25,7 +36,7 @@ void DetectPhilipsHueControllers() { - json hue_settings; + PhilipsHueSettingsHandler hue_settings; /*-------------------------------------------------*\ | Create an HTTP handler | @@ -36,11 +47,6 @@ void DetectPhilipsHueControllers() 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 | \*-------------------------------------------------*/ @@ -51,24 +57,14 @@ void DetectPhilipsHueControllers() | If no bridges were detected, manually add bridge | | IP and MAC (need to get these from file) | \*-------------------------------------------------*/ - if(bridges.empty()) + if(hue_settings.GetBridgeCount() > 0) { - if(hue_settings.contains("bridges")) - { - hueplusplus::BridgeFinder::BridgeIdentification ident; + hueplusplus::BridgeFinder::BridgeIdentification ident; - if(hue_settings["bridges"][0].contains("ip")) - { - ident.ip = hue_settings["bridges"][0]["ip"]; - } + ident.ip = hue_settings.GetBridgeIP(0); + ident.mac = hue_settings.GetBridgeMAC(0); - if(hue_settings["bridges"][0].contains("mac")) - { - ident.mac = hue_settings["bridges"][0]["mac"]; - } - - bridges.push_back(ident); - } + bridges.push_back(ident); } /*-------------------------------------------------*\ @@ -84,22 +80,22 @@ void DetectPhilipsHueControllers() /*-------------------------------------------------*\ | Check if a saved username exists | \*-------------------------------------------------*/ - if(hue_settings.contains("bridges")) + if(hue_settings.GetBridgeCount() > 0) { /*-------------------------------------------------*\ | Add the username if it exists | \*-------------------------------------------------*/ - if(hue_settings["bridges"][0].contains("username")) + if(hue_settings.BridgeHasUsername(0)) { - finder.addUsername(bridges[0].mac, hue_settings["bridges"][0]["username"]); + finder.addUsername(bridges[0].mac, hue_settings.GetBridgeUsername(0)); } /*-------------------------------------------------*\ | Add the client key if it exists | \*-------------------------------------------------*/ - if(hue_settings["bridges"][0].contains("clientkey")) + if(hue_settings.BridgeHasClientKey(0)) { - finder.addClientKey(bridges[0].mac, hue_settings["bridges"][0]["clientkey"]); + finder.addClientKey(bridges[0].mac, hue_settings.GetBridgeClientKey(0)); } } @@ -123,11 +119,11 @@ void DetectPhilipsHueControllers() bool use_entertainment = false; bool auto_connect = false; - if(hue_settings.contains("bridges")) + if(hue_settings.GetBridgeCount() > 0) { - if(hue_settings["bridges"][0].contains("username")) + if(hue_settings.BridgeHasUsername(0)) { - if(hue_settings["bridges"][0]["username"] != bridge.getUsername()) + if(hue_settings.GetBridgeUsername(0) != bridge.getUsername()) { save_settings = true; } @@ -137,9 +133,9 @@ void DetectPhilipsHueControllers() save_settings = true; } - if(hue_settings["bridges"][0].contains("clientkey")) + if(hue_settings.BridgeHasClientKey(0)) { - if(hue_settings["bridges"][0]["clientkey"] != bridge.getClientKey()) + if(hue_settings.GetBridgeClientKey(0) != bridge.getClientKey()) { use_entertainment = true; save_settings = true; @@ -156,28 +152,18 @@ void DetectPhilipsHueControllers() \*-------------------------------------------------*/ if(save_settings) { - hue_settings["bridges"][0]["username"] = bridge.getUsername(); - hue_settings["bridges"][0]["clientkey"] = bridge.getClientKey(); - hue_settings["bridges"][0]["entertainment"] = use_entertainment; - hue_settings["bridges"][0]["autoconnect"] = auto_connect; - - ResourceManager::get()->GetSettingsManager()->SetSettings("PhilipsHueDevices", hue_settings); - - ResourceManager::get()->GetSettingsManager()->SaveSettings(); + hue_settings.SetBridgeUsername(0, bridge.getUsername()); + hue_settings.SetBridgeClientKey(0, bridge.getClientKey()); + hue_settings.SetBridgeUseEntertainment(0, use_entertainment); + hue_settings.SetBridgeAutoconnect(0, auto_connect); + hue_settings.SaveSettings(); } /*-------------------------------------------------*\ - | Get entertainment mode settings | + | Get entertainment mode settings | \*-------------------------------------------------*/ - if(hue_settings["bridges"][0].contains("entertainment")) - { - use_entertainment = hue_settings["bridges"][0]["entertainment"]; - } - - if(hue_settings["bridges"][0].contains("autoconnect")) - { - auto_connect = hue_settings["bridges"][0]["autoconnect"]; - } + use_entertainment = hue_settings.GetBridgeUseEntertainment(0); + auto_connect = hue_settings.GetBridgeAutoconnect(0); /*-------------------------------------------------*\ | Get all groups from the bridge | @@ -212,7 +198,7 @@ void DetectPhilipsHueControllers() { for(unsigned int controller_idx = 0; controller_idx < ResourceManager::get()->GetRGBControllers().size(); controller_idx++) { - if(ResourceManager::get()->GetRGBControllers()[controller_idx]->description == "Philips Hue Entertainment Mode Device") + if(ResourceManager::get()->GetRGBControllers()[controller_idx]->GetDescription() == "Philips Hue Entertainment Mode Device") { ResourceManager::get()->GetRGBControllers()[controller_idx]->SetMode(0); break; diff --git a/Controllers/PhilipsHueController/PhilipsHueEntertainmentController.cpp b/Controllers/PhilipsHueController/PhilipsHueEntertainmentController.cpp index 904fe18e..c39e7082 100644 --- a/Controllers/PhilipsHueController/PhilipsHueEntertainmentController.cpp +++ b/Controllers/PhilipsHueController/PhilipsHueEntertainmentController.cpp @@ -1,7 +1,12 @@ /*---------------------------------------------------------*\ -| Driver for Philips Hue Entertainment Mode | +| PhilipsHueEntertainmentController.cpp | | | -| Adam Honse (calcprogrammer1@gmail.com), 11/6/2020 | +| Detector for Philips Hue Entertainment Mode | +| | +| Adam Honse (calcprogrammer1@gmail.com) 06 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ #include "RGBController.h" @@ -13,7 +18,7 @@ PhilipsHueEntertainmentController::PhilipsHueEntertainmentController(hueplusplus | Fill in location string with bridge IP | \*-------------------------------------------------*/ location = "IP: " + bridge.getBridgeIP(); - num_leds = group.getLightIds().size(); + num_leds = (unsigned int)group.getLightIds().size(); connected = false; } @@ -81,7 +86,7 @@ void PhilipsHueEntertainmentController::Connect() | Create Entertainment Mode from bridge and group | \*-------------------------------------------------*/ entertainment = new hueplusplus::EntertainmentMode(bridge, group); - + /*-------------------------------------------------*\ | Connect Hue Entertainment Mode | \*-------------------------------------------------*/ diff --git a/Controllers/PhilipsHueController/PhilipsHueEntertainmentController.h b/Controllers/PhilipsHueController/PhilipsHueEntertainmentController.h index 7339e952..bf459686 100644 --- a/Controllers/PhilipsHueController/PhilipsHueEntertainmentController.h +++ b/Controllers/PhilipsHueController/PhilipsHueEntertainmentController.h @@ -1,17 +1,22 @@ /*---------------------------------------------------------*\ -| Definitions for Philips Hue Entertainment Mode | +| PhilipsHueEntertainmentController.h | | | -| Adam Honse (calcprogrammer1@gmail.com), 11/6/2020 | +| Detector for Philips Hue Entertainment Mode | +| | +| Adam Honse (calcprogrammer1@gmail.com) 06 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "Bridge.h" -#include "EntertainmentMode.h" -#include "Group.h" +#pragma once #include #include - -#pragma once +#include "Bridge.h" +#include "EntertainmentMode.h" +#include "Group.h" +#include "RGBController.h" #define HUE_ENTERTAINMENT_HEADER_SIZE 16 #define HUE_ENTERTAINMENT_LIGHT_SIZE 9 diff --git a/Controllers/PhilipsHueController/PhilipsHueSettingsHandler.cpp b/Controllers/PhilipsHueController/PhilipsHueSettingsHandler.cpp new file mode 100644 index 00000000..8aa33b9a --- /dev/null +++ b/Controllers/PhilipsHueController/PhilipsHueSettingsHandler.cpp @@ -0,0 +1,151 @@ +#include "PhilipsHueSettingsHandler.h" +#include "ResourceManager.h" +#include "SettingsManager.h" + +#define HUE_SETTINGS ((hue_settings_type *)hue_settings)->hue_settings + +typedef struct +{ + json hue_settings; +} hue_settings_type; + +PhilipsHueSettingsHandler::PhilipsHueSettingsHandler() +{ + /*-------------------------------------------------*\ + | Create an object to hold the hue settings json | + | This cannot be a class member as json must not | + | be included in the header file, so it is held as | + | a void pointer instead. | + \*-------------------------------------------------*/ + hue_settings = (void *)(new hue_settings_type); + + /*-------------------------------------------------*\ + | Get Philips Hue settings from settings manager | + \*-------------------------------------------------*/ + HUE_SETTINGS = ResourceManager::get()->GetSettingsManager()->GetSettings("PhilipsHueDevices"); +} + +PhilipsHueSettingsHandler::~PhilipsHueSettingsHandler() +{ + delete (hue_settings_type *)hue_settings; +} + +std::size_t PhilipsHueSettingsHandler::GetBridgeCount() +{ + if(HUE_SETTINGS.contains("bridges")) + { + return(HUE_SETTINGS["bridges"].size()); + } + else + { + return(0); + } +} + +std::string PhilipsHueSettingsHandler::GetBridgeIP(unsigned int bridge_idx) +{ + if(HUE_SETTINGS["bridges"][bridge_idx].contains("ip")) + { + return(HUE_SETTINGS["bridges"][bridge_idx]["ip"]); + } + else + { + return(""); + } +} + +std::string PhilipsHueSettingsHandler::GetBridgeMAC(unsigned int bridge_idx) +{ + if(HUE_SETTINGS["bridges"][bridge_idx].contains("mac")) + { + return(HUE_SETTINGS["bridges"][bridge_idx]["mac"]); + } + else + { + return(""); + } +} + +std::string PhilipsHueSettingsHandler::GetBridgeUsername(unsigned int bridge_idx) +{ + if(HUE_SETTINGS["bridges"][bridge_idx].contains("username")) + { + return(HUE_SETTINGS["bridges"][bridge_idx]["username"]); + } + else + { + return(""); + } +} + +std::string PhilipsHueSettingsHandler::GetBridgeClientKey(unsigned int bridge_idx) +{ + if(HUE_SETTINGS["bridges"][bridge_idx].contains("clientkey")) + { + return(HUE_SETTINGS["bridges"][bridge_idx]["clientkey"]); + } + else + { + return(""); + } +} + +bool PhilipsHueSettingsHandler::GetBridgeAutoconnect(unsigned int bridge_idx) +{ + if(HUE_SETTINGS["bridges"][bridge_idx].contains("autoconnect")) + { + return(HUE_SETTINGS["bridges"][bridge_idx]["autoconnect"]); + } + else + { + return(false); + } +} + +bool PhilipsHueSettingsHandler::GetBridgeUseEntertainment(unsigned int bridge_idx) +{ + if(HUE_SETTINGS["bridges"][bridge_idx].contains("entertainment")) + { + return(HUE_SETTINGS["bridges"][bridge_idx]["entertainment"]); + } + else + { + return(false); + } +} + +bool PhilipsHueSettingsHandler::BridgeHasUsername(unsigned int bridge_idx) +{ + return(HUE_SETTINGS["bridges"][bridge_idx].contains("username")); +} + +bool PhilipsHueSettingsHandler::BridgeHasClientKey(unsigned int bridge_idx) +{ + return(HUE_SETTINGS["bridges"][bridge_idx].contains("clientkey")); +} + +void PhilipsHueSettingsHandler::SetBridgeUsername(unsigned int bridge_idx, std::string username) +{ + HUE_SETTINGS["bridges"][bridge_idx]["username"] = username; +} + +void PhilipsHueSettingsHandler::SetBridgeClientKey(unsigned int bridge_idx, std::string clientkey) +{ + HUE_SETTINGS["bridges"][bridge_idx]["clientkey"] = clientkey; +} + +void PhilipsHueSettingsHandler::SetBridgeAutoconnect(unsigned int bridge_idx, bool auto_connect) +{ + HUE_SETTINGS["bridges"][bridge_idx]["autoconnect"] = auto_connect; +} + +void PhilipsHueSettingsHandler::SetBridgeUseEntertainment(unsigned int bridge_idx, bool use_entertainment) +{ + HUE_SETTINGS["bridges"][bridge_idx]["entertainment"] = use_entertainment; +} + +void PhilipsHueSettingsHandler::SaveSettings() +{ + ResourceManager::get()->GetSettingsManager()->SetSettings("PhilipsHueDevices", HUE_SETTINGS); + ResourceManager::get()->GetSettingsManager()->SaveSettings(); +} diff --git a/Controllers/PhilipsHueController/PhilipsHueSettingsHandler.h b/Controllers/PhilipsHueController/PhilipsHueSettingsHandler.h new file mode 100644 index 00000000..1daf73db --- /dev/null +++ b/Controllers/PhilipsHueController/PhilipsHueSettingsHandler.h @@ -0,0 +1,47 @@ +/*---------------------------------------------------------*\ +| PhilipsHueSettingsHandler.h | +| | +| Settings Handler for Philips Hue | +| Due to conflict in jsoh.hpp library, hueplusplus and | +| SettingsManager should not be included in the same file | +| so handle settings in a separate class. | +| | +| Adam Honse (calcprogrammer1@gmail.com) 17 Jan 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include + +class PhilipsHueSettingsHandler +{ +public: + PhilipsHueSettingsHandler(); + ~PhilipsHueSettingsHandler(); + + std::size_t GetBridgeCount(); + + std::string GetBridgeIP(unsigned int bridge_idx); + std::string GetBridgeMAC(unsigned int bridge_idx); + std::string GetBridgeUsername(unsigned int bridge_idx); + std::string GetBridgeClientKey(unsigned int bridge_idx); + bool GetBridgeAutoconnect(unsigned int bridge_idx); + bool GetBridgeUseEntertainment(unsigned int bridge_idx); + + bool BridgeHasUsername(unsigned int bridge_idx); + bool BridgeHasClientKey(unsigned int bridge_idx); + + void SetBridgeUsername(unsigned int bridge_idx, std::string username); + void SetBridgeClientKey(unsigned int bridge_idx, std::string clientkey); + void SetBridgeAutoconnect(unsigned int bridge_ip, bool auto_connect); + void SetBridgeUseEntertainment(unsigned int bridge_idx, bool use_entertainment); + + void SaveSettings(); + +private: + void * hue_settings; +}; diff --git a/Controllers/PhilipsHueController/RGBController_PhilipsHue.cpp b/Controllers/PhilipsHueController/RGBController_PhilipsHue.cpp index 7bceef6a..f795608c 100644 --- a/Controllers/PhilipsHueController/RGBController_PhilipsHue.cpp +++ b/Controllers/PhilipsHueController/RGBController_PhilipsHue.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_PhilipsHue.cpp | -| | -| Generic RGB Interface for Philips Hue | -| | -| Adam Honse (CalcProgrammer1) 9/15/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_PhilipsHue.cpp | +| | +| RGBController for Philips Hue | +| | +| Adam Honse (calcprogrammer1@gmail.com) 15 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_PhilipsHue.h" diff --git a/Controllers/PhilipsHueController/RGBController_PhilipsHue.h b/Controllers/PhilipsHueController/RGBController_PhilipsHue.h index 2d7cff31..80fb2146 100644 --- a/Controllers/PhilipsHueController/RGBController_PhilipsHue.h +++ b/Controllers/PhilipsHueController/RGBController_PhilipsHue.h @@ -1,12 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_PhilipsHue.h | -| | -| Generic RGB Interface for Philips Hue | -| | -| Adam Honse (CalcProgrammer1) 9/15/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_PhilipsHue.h | +| | +| RGBController for Philips Hue | +| | +| Adam Honse (calcprogrammer1@gmail.com) 15 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "PhilipsHueController.h" diff --git a/Controllers/PhilipsHueController/RGBController_PhilipsHueEntertainment.cpp b/Controllers/PhilipsHueController/RGBController_PhilipsHueEntertainment.cpp index b4d5bd2c..d74120d9 100644 --- a/Controllers/PhilipsHueController/RGBController_PhilipsHueEntertainment.cpp +++ b/Controllers/PhilipsHueController/RGBController_PhilipsHueEntertainment.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_PhilipsHueEntertainment.cpp| -| | -| Generic RGB Interface for Philips Hue | -| Entertainment Mode | -| | -| Adam Honse (CalcProgrammer1) 11/7/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_PhilipsHueEntertainment.cpp | +| | +| RGBController for Philips Hue Entertainment Mode | +| | +| Adam Honse (calcprogrammer1@gmail.com) 07 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_PhilipsHueEntertainment.h" #include "ResourceManager.h" @@ -124,7 +126,7 @@ void RGBController_PhilipsHueEntertainment::DeviceUpdateMode() for(unsigned int controller_idx = 0; controller_idx < rgb_controllers.size(); controller_idx++) { - if(rgb_controllers[controller_idx] != this && rgb_controllers[controller_idx]->description == "Philips Hue Entertainment Mode Device" && rgb_controllers[controller_idx]->active_mode == 0) + if(rgb_controllers[controller_idx] != this && rgb_controllers[controller_idx]->GetDescription() == "Philips Hue Entertainment Mode Device" && rgb_controllers[controller_idx]->active_mode == 0) { rgb_controllers[controller_idx]->SetMode(1); } diff --git a/Controllers/PhilipsHueController/RGBController_PhilipsHueEntertainment.h b/Controllers/PhilipsHueController/RGBController_PhilipsHueEntertainment.h index 67e5cae4..565e850a 100644 --- a/Controllers/PhilipsHueController/RGBController_PhilipsHueEntertainment.h +++ b/Controllers/PhilipsHueController/RGBController_PhilipsHueEntertainment.h @@ -1,18 +1,20 @@ -/*-----------------------------------------*\ -| RGBController_PhilipsHueEntertainment.h | -| | -| Generic RGB Interface for Philips Hue | -| Entertainment Mode | -| | -| Adam Honse (CalcProgrammer1) 11/7/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_PhilipsHueEntertainment.h | +| | +| RGBController for Philips Hue Entertainment Mode | +| | +| Adam Honse (calcprogrammer1@gmail.com) 07 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include "RGBController.h" -#include "PhilipsHueEntertainmentController.h" #include #include +#include "RGBController.h" +#include "PhilipsHueEntertainmentController.h" class RGBController_PhilipsHueEntertainment : public RGBController { diff --git a/Controllers/PhilipsWizController/PhilipsWizController.cpp b/Controllers/PhilipsWizController/PhilipsWizController.cpp index 59871d54..efb92fb6 100644 --- a/Controllers/PhilipsWizController/PhilipsWizController.cpp +++ b/Controllers/PhilipsWizController/PhilipsWizController.cpp @@ -1,16 +1,21 @@ /*---------------------------------------------------------*\ -| Driver for Philips Wiz | +| PhilipsWizController.cpp | | | -| Adam Honse (calcprogrammer1@gmail.com), 9/15/2020 | +| Driver for Philips Wiz | +| | +| Adam Honse (calcprogrammer1@gmail.com) 03 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ #include "PhilipsWizController.h" -#include "json.hpp" +#include using json = nlohmann::json; using namespace std::chrono_literals; -PhilipsWizController::PhilipsWizController(std::string ip, bool use_cool, bool use_warm) +PhilipsWizController::PhilipsWizController(std::string ip, bool use_cool, bool use_warm, std::string selected_white_strategy) { /*-----------------------------------------------------------------*\ | Fill in location string with device's IP address | @@ -22,6 +27,7 @@ PhilipsWizController::PhilipsWizController(std::string ip, bool use_cool, bool u \*-----------------------------------------------------------------*/ use_cool_white = use_cool; use_warm_white = use_warm; + white_strategy = selected_white_strategy; /*-----------------------------------------------------------------*\ | Open a UDP client sending to the device's IP, port 38899 | @@ -80,6 +86,50 @@ std::string PhilipsWizController::GetUniqueID() void PhilipsWizController::SetColor(unsigned char red, unsigned char green, unsigned char blue, unsigned char brightness) { json command; + unsigned char white; + + /*-----------------------------------------------------------------*\ + | The official Wiz app also sends a warm white level with its | + | custom colours. Until we can figure out a way to account for it | + | correctly, set the white level based on selected strategy. | + \*-----------------------------------------------------------------*/ + if(white_strategy == "Average") + { + white = (red + green + blue) / 3; + } + else if(white_strategy == "Minimum") + { + white = std::min(std::min(red, green), blue); + if(use_cool_white || use_warm_white) + { + red = red - white; + green = green - white; + blue = blue - white; + } + } + else + { + white = 0; + } + + if(use_cool_white) + { + command["params"]["c"] = white; + } + else + { + command["params"]["c"] = 0; + } + + if(use_warm_white) + { + command["params"]["w"] = white; + } + else + { + command["params"]["w"] = 0; + } + /*-----------------------------------------------------------------*\ | Fill in the setPilot command with RGB and brightness information. | @@ -92,38 +142,14 @@ void PhilipsWizController::SetColor(unsigned char red, unsigned char green, unsi command["params"]["g"] = green; command["params"]["b"] = blue; command["params"]["dimming"] = brightness; - command["params"]["state"] = !((red == 0) && (green == 0) && (blue == 0)); - - /*-----------------------------------------------------------------*\ - | The official Wiz app also sends a warm white level with its | - | custom colours. Until we can figure out a way to account for it | - | correctly, set the cool white level to the average of RGB to | - | improve its apparent brightness. | - \*-----------------------------------------------------------------*/ - if(use_warm_white) - { - command["params"]["w"] = (red + green + blue) / 3; - } - else - { - command["params"]["w"] = 0; - } - - if(use_cool_white) - { - command["params"]["c"] = (red + green + blue) / 3; - } - else - { - command["params"]["c"] = 0; - } + command["params"]["state"] = !((red == 0) && (green == 0) && (blue == 0) && (white == 0)); /*-----------------------------------------------------------------*\ | Convert the JSON object to a string and write it | \*-----------------------------------------------------------------*/ std::string command_str = command.dump(); - port.udp_write((char *)command_str.c_str(), command_str.length() + 1); + port.udp_write((char *)command_str.c_str(), (int)command_str.length() + 1); } void PhilipsWizController::SetScene(int scene, unsigned char brightness) @@ -142,19 +168,21 @@ void PhilipsWizController::SetScene(int scene, unsigned char brightness) \*------------------------------------------------------------*/ std::string command_str = command.dump(); - port.udp_write((char*)command_str.c_str(), command_str.length() + 1); + port.udp_write((char*)command_str.c_str(), (int)command_str.length() + 1); } void PhilipsWizController::ReceiveThreadFunction() { - char recv_buf[1024]; + char recv_buf[1025]; + + port.set_receive_timeout(1, 0); while(ReceiveThreadRun.load()) { /*-----------------------------------------------------------------*\ | Receive up to 1024 bytes from the device with a 1s timeout | \*-----------------------------------------------------------------*/ - int size = port.udp_listen_timeout(recv_buf, 1024, 1, 0); + int size = port.udp_listen(recv_buf, 1024); if(size > 0) { @@ -219,7 +247,7 @@ void PhilipsWizController::RequestSystemConfig() \*-----------------------------------------------------------------*/ std::string command_str = command.dump(); - port.udp_write((char *)command_str.c_str(), command_str.length() + 1); + port.udp_write((char *)command_str.c_str(), (int)command_str.length() + 1); /*-----------------------------------------------------------------*\ | Wait up to 1s to give it time to receive and process response | diff --git a/Controllers/PhilipsWizController/PhilipsWizController.h b/Controllers/PhilipsWizController/PhilipsWizController.h index 065d192d..147a5416 100644 --- a/Controllers/PhilipsWizController/PhilipsWizController.h +++ b/Controllers/PhilipsWizController/PhilipsWizController.h @@ -1,17 +1,21 @@ /*---------------------------------------------------------*\ -| Definitions for Philips Wiz | +| PhilipsWizController.h | | | -| Adam Honse (calcprogrammer1@gmail.com), 11/3/2020 | +| Driver for Philips Wiz | +| | +| Adam Honse (calcprogrammer1@gmail.com) 03 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "RGBController.h" -#include "net_port.h" +#pragma once #include #include #include - -#pragma once +#include "RGBController.h" +#include "net_port.h" #define PHILIPSWIZ_BRIGHTNESS_MAX 100 #define PHILIPSWIZ_BRIGHTNESS_MIN 10 @@ -56,7 +60,7 @@ enum class PhilipsWizController { public: - PhilipsWizController(std::string ip, bool use_cool, bool use_warm); + PhilipsWizController(std::string ip, bool use_cool, bool use_warm, std::string selected_white_strategy); ~PhilipsWizController(); std::string GetLocation(); @@ -84,6 +88,7 @@ private: bool use_cool_white; bool use_warm_white; + std::string white_strategy; void SendSetPilot(); }; diff --git a/Controllers/PhilipsWizController/PhilipsWizControllerDetect.cpp b/Controllers/PhilipsWizController/PhilipsWizControllerDetect.cpp index c77e1beb..88d87610 100644 --- a/Controllers/PhilipsWizController/PhilipsWizControllerDetect.cpp +++ b/Controllers/PhilipsWizController/PhilipsWizControllerDetect.cpp @@ -1,11 +1,18 @@ +/*---------------------------------------------------------*\ +| PhilipsWizControllerDetect.cpp | +| | +| Detector for Philips Wiz | +| | +| Adam Honse (calcprogrammer1@gmail.com) 03 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "PhilipsWizController.h" -#include "RGBController.h" #include "RGBController_PhilipsWiz.h" #include "SettingsManager.h" -#include -#include -#include /******************************************************************************************\ * * @@ -47,8 +54,13 @@ void DetectPhilipsWizControllers() { wiz_warm = wiz_settings["devices"][device_idx]["use_warm_white"]; } + std::string wiz_white_strategy = "Average"; + if(wiz_settings["devices"][device_idx].contains("selected_white_strategy")) + { + wiz_white_strategy = wiz_settings["devices"][device_idx]["selected_white_strategy"]; + } - PhilipsWizController* controller = new PhilipsWizController(wiz_ip, wiz_cool, wiz_warm); + PhilipsWizController* controller = new PhilipsWizController(wiz_ip, wiz_cool, wiz_warm, wiz_white_strategy); RGBController_PhilipsWiz* rgb_controller = new RGBController_PhilipsWiz(controller); ResourceManager::get()->RegisterRGBController(rgb_controller); diff --git a/Controllers/PhilipsWizController/RGBController_PhilipsWiz.cpp b/Controllers/PhilipsWizController/RGBController_PhilipsWiz.cpp index 9ab9b559..fdb54006 100644 --- a/Controllers/PhilipsWizController/RGBController_PhilipsWiz.cpp +++ b/Controllers/PhilipsWizController/RGBController_PhilipsWiz.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_PhilipsWiz.cpp | -| | -| Generic RGB Interface for Philips Wiz | -| | -| Adam Honse (CalcProgrammer1) 11/3/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_PhilipsWiz.cpp | +| | +| RGBController for Philips Wiz | +| | +| Adam Honse (calcprogrammer1@gmail.com) 03 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_PhilipsWiz.h" diff --git a/Controllers/PhilipsWizController/RGBController_PhilipsWiz.h b/Controllers/PhilipsWizController/RGBController_PhilipsWiz.h index ba2b20ab..236164ad 100644 --- a/Controllers/PhilipsWizController/RGBController_PhilipsWiz.h +++ b/Controllers/PhilipsWizController/RGBController_PhilipsWiz.h @@ -1,12 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_PhilipsWiz.h | -| | -| Generic RGB Interface for Philips Wiz | -| | -| Adam Honse (CalcProgrammer1) 11/3/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_PhilipsWiz.h | +| | +| RGBController for Philips Wiz | +| | +| Adam Honse (calcprogrammer1@gmail.com) 03 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "PhilipsWizController.h" diff --git a/Controllers/PowerColorRedDevilGPUController/PowerColorRedDevilGPUController.cpp b/Controllers/PowerColorRedDevilGPUController/PowerColorRedDevilGPUController.cpp new file mode 100755 index 00000000..e1a027a6 --- /dev/null +++ b/Controllers/PowerColorRedDevilGPUController/PowerColorRedDevilGPUController.cpp @@ -0,0 +1,149 @@ +/*---------------------------------------------------------*\ +| PowerColorRedDevilGPUController.cpp | +| | +| Driver for PowerColor Red Devil GPU | +| | +| Jana Rettig (SapphicKitten) 14 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "pci_ids.h" +#include "PowerColorRedDevilGPUController.h" + +using namespace std::chrono_literals; + +RedDevilGPUController::RedDevilGPUController(i2c_smbus_interface* bus, red_devil_dev_id dev, std::string dev_name) +{ + this->bus = bus; + this->dev = dev; + this->name = dev_name; + + if(bus->pci_device > AMD_NAVI10_DEV) // Only Navi 2 cards have this mode + { + this->has_sync_mode = true; + } +} + +RedDevilGPUController::~RedDevilGPUController() +{ + +} + +std::string RedDevilGPUController::GetDeviceLocation() +{ + std::string return_string(bus->device_name); + char addr[5]; + snprintf(addr, 5, "0x%02X", dev); + return_string.append(", address "); + return_string.append(addr); + return("I2C:" + return_string); +} + +std::string RedDevilGPUController::GetDeviceName() +{ + return(name); +} + +void RedDevilGPUController::SetLEDColor(int led, RGBColor color) +{ + if(led > RED_DEVIL_GPU_LED_MAX_COUNT) + { + return; + } + + unsigned char data[3] = + { + (unsigned char)RGBGetRValue(color), + (unsigned char)RGBGetGValue(color), + (unsigned char)RGBGetBValue(color), + }; + + RegisterWrite(RED_DEVIL_GPU_REG_LED_1 + led, data); +} + +RGBColor RedDevilGPUController::GetLEDColor(int led) +{ + if(led > RED_DEVIL_GPU_LED_MAX_COUNT) + { + return RGBColor(0); + } + + unsigned char data[3] = {0}; + RegisterRead(RED_DEVIL_GPU_REG_LED_1 + RED_DEVIL_GPU_READ_OFFSET, data); + return ToRGBColor(data[0], data[1], data[2]); +} + +void RedDevilGPUController::SetLEDColorAll(RGBColor color) +{ + unsigned char data[3] = + { + (unsigned char)RGBGetRValue(color), + (unsigned char)RGBGetGValue(color), + (unsigned char)RGBGetBValue(color), + }; + + RegisterWrite(RED_DEVIL_GPU_REG_LED_ALL, data); +} + +void RedDevilGPUController::SetModeColor(RGBColor color) +{ + unsigned char data[3] = + { + (unsigned char)RGBGetRValue(color), + (unsigned char)RGBGetGValue(color), + (unsigned char)RGBGetBValue(color), + }; + + RegisterWrite(RED_DEVIL_GPU_REG_MODE_COLOR, data); +} + +RGBColor RedDevilGPUController::GetModeColor() +{ + unsigned char data[3] = {0}; + RegisterRead(RED_DEVIL_GPU_REG_MODE_COLOR + RED_DEVIL_GPU_READ_OFFSET, data); + return ToRGBColor(data[0], data[1], data[2]); +} + +void RedDevilGPUController::SetMode(red_devil_mode_config config) +{ + if(config.mode == RED_DEVIL_GPU_MODE_MB_SYNC) + { + unsigned char data[3] = {1, 0, 1}; + RegisterWrite(RED_DEVIL_GPU_REG_MB_SYNC, data); + } + else + { + unsigned char data[3] = {0}; + RegisterWrite(RED_DEVIL_GPU_REG_MB_SYNC, data); + RegisterWrite(RED_DEVIL_GPU_REG_MODE, (unsigned char *)&config); + } +} + +red_devil_mode_config RedDevilGPUController::GetMode() +{ + unsigned char data[3] = {0}; + RegisterRead(RED_DEVIL_GPU_REG_MB_SYNC + RED_DEVIL_GPU_READ_OFFSET, data); + if(data[0] != 0 && this->has_sync_mode) + { + return red_devil_mode_config{RED_DEVIL_GPU_MODE_MB_SYNC, 0, 0}; + } + + RegisterRead(RED_DEVIL_GPU_REG_MODE + RED_DEVIL_GPU_READ_OFFSET, data); + return red_devil_mode_config{data[0], data[1], data[2]}; +} + +int RedDevilGPUController::RegisterRead(unsigned char reg, unsigned char *data) +{ + int ret = bus->i2c_smbus_read_i2c_block_data(dev, reg, 3, data); + std::this_thread::sleep_for(32ms); + return ret; +} + +int RedDevilGPUController::RegisterWrite(unsigned char reg, unsigned char *data) +{ + int ret = bus->i2c_smbus_write_i2c_block_data(dev, reg, 3, data); + std::this_thread::sleep_for(32ms); + return ret; +} diff --git a/Controllers/PowerColorRedDevilGPUController/PowerColorRedDevilGPUController.h b/Controllers/PowerColorRedDevilGPUController/PowerColorRedDevilGPUController.h new file mode 100755 index 00000000..099273de --- /dev/null +++ b/Controllers/PowerColorRedDevilGPUController/PowerColorRedDevilGPUController.h @@ -0,0 +1,109 @@ +/*---------------------------------------------------------*\ +| PowerColorRedDevilGPUController.h | +| | +| Driver for PowerColor Red Devil GPU | +| | +| Jana Rettig (SapphicKitten) 14 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "i2c_smbus.h" +#include "RGBController.h" + +#pragma once + +#define RED_DEVIL_GPU_READ_OFFSET 0x80 +#define RED_DEVIL_GPU_LED_MAX_COUNT 12 + +typedef unsigned char red_devil_dev_id; + +struct red_devil_mode_config +{ + unsigned char mode; + unsigned char brightness; + unsigned char speed; +}; + +enum +{ + RED_DEVIL_GPU_REG_MODE = 0x01, + RED_DEVIL_GPU_REG_LED_1 = 0x02, + RED_DEVIL_GPU_REG_LED_2 = 0x03, + RED_DEVIL_GPU_REG_LED_3 = 0x04, + RED_DEVIL_GPU_REG_LED_4 = 0x05, + RED_DEVIL_GPU_REG_LED_5 = 0x06, + RED_DEVIL_GPU_REG_LED_6 = 0x07, + RED_DEVIL_GPU_REG_LED_7 = 0x08, + RED_DEVIL_GPU_REG_LED_8 = 0x09, + RED_DEVIL_GPU_REG_LED_9 = 0x0A, + RED_DEVIL_GPU_REG_LED_10 = 0x0B, + RED_DEVIL_GPU_REG_LED_11 = 0x0C, + RED_DEVIL_GPU_REG_LED_12 = 0x0D, // Unused for now, acts like any other led reg + RED_DEVIL_GPU_REG_LED_ALL = 0x0E, + RED_DEVIL_GPU_REG_MODE_COLOR = 0x0F, + RED_DEVIL_GPU_REG_UNKNOWN_1 = 0x10, // Never seen writes to this, reads 0x01 0x05 0x00. Maybe Version? + RED_DEVIL_GPU_REG_UNKNOWN_2 = 0x11, // DevilZone writes to this sometimes. No observable change + RED_DEVIL_GPU_REG_MB_SYNC = 0x12 // Unused on NAVI 1X cards. Disables controller and allows LEDs to be controlled by external source via ARGB header +}; + +enum +{ + RED_DEVIL_GPU_MODE_OFF = 0x00, + RED_DEVIL_GPU_MODE_STATIC = 0x01, + RED_DEVIL_GPU_MODE_BREATHING = 0x02, + RED_DEVIL_GPU_MODE_NEON = 0x03, + RED_DEVIL_GPU_MODE_BLINK = 0x04, + RED_DEVIL_GPU_MODE_DOUBLE_BLINK = 0x05, + RED_DEVIL_GPU_MODE_COLOR_SHIFT = 0x06, + RED_DEVIL_GPU_MODE_METEOR = 0x07, + RED_DEVIL_GPU_MODE_RIPPLE = 0x08, + RED_DEVIL_GPU_MODE_SEVEN_COLORS = 0x09, + RED_DEVIL_GPU_MODE_MB_SYNC = 0xFF +}; + +enum +{ + RED_DEVIL_GPU_BRIGHTNESS_MIN = 0x00, + RED_DEVIL_GPU_BRIGHTNESS_MAX = 0xFF, +}; + +enum +{ + RED_DEVIL_GPU_SPEED_SLOWEST = 0x64, + RED_DEVIL_GPU_SPEED_DEFAULT = 0x32, + RED_DEVIL_GPU_SPEED_FASTEST = 0x00 +}; + +class RedDevilGPUController +{ +public: + RedDevilGPUController(i2c_smbus_interface* bus, red_devil_dev_id dev, std::string dev_name); + ~RedDevilGPUController(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + + void SetLEDColor(int led, RGBColor color); + RGBColor GetLEDColor(int led); + + void SetLEDColorAll(RGBColor color); + + void SetModeColor(RGBColor color); + RGBColor GetModeColor(); + + void SetMode(red_devil_mode_config config); + red_devil_mode_config GetMode(); + + int RegisterRead(unsigned char reg, unsigned char *data); + int RegisterWrite(unsigned char reg, unsigned char *data); + + bool has_sync_mode = false; + +private: + i2c_smbus_interface* bus; + red_devil_dev_id dev; + std::string name; +}; diff --git a/Controllers/PowerColorRedDevilGPUController/PowerColorRedDevilGPUControllerDetect.cpp b/Controllers/PowerColorRedDevilGPUController/PowerColorRedDevilGPUControllerDetect.cpp new file mode 100755 index 00000000..41f935cd --- /dev/null +++ b/Controllers/PowerColorRedDevilGPUController/PowerColorRedDevilGPUControllerDetect.cpp @@ -0,0 +1,37 @@ +/*---------------------------------------------------------*\ +| PowerColorRedDevilGPUControllerDetect.cpp | +| | +| Driver for PowerColor Red Devil GPU | +| | +| Jana Rettig (SapphicKitten) 14 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "pci_ids.h" +#include "RGBController_PowerColorRedDevilGPU.h" +#include "PowerColorRedDevilGPUController.h" + +static const unsigned char indicator[3] = {0x01, 0x05, 0x00}; + +void DetectPowerColorRedDevilGPUControllers(i2c_smbus_interface* bus, uint8_t i2c_addr, const std::string& name) +{ + unsigned char data[3] = {0}; + int ret = bus->i2c_smbus_read_i2c_block_data(i2c_addr, 0x90, 3, data); + + if(ret == 3 && memcmp(data, indicator, 3) == 0) + { + RedDevilGPUController* controller = new RedDevilGPUController(bus, i2c_addr, name); + RGBController_RedDevilGPU* rgb_controller = new RGBController_RedDevilGPU(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_I2C_PCI_DETECTOR("PowerColor Red Devil RX5700", DetectPowerColorRedDevilGPUControllers, AMD_GPU_VEN, AMD_NAVI10_DEV, POWERCOLOR_SUB_VEN, POWERCOLOR_RED_DEVIL_RX5700_SUB_DEV, 0x22); +REGISTER_I2C_PCI_DETECTOR("PowerColor Red Devil RX5700XT", DetectPowerColorRedDevilGPUControllers, AMD_GPU_VEN, AMD_NAVI10_DEV, POWERCOLOR_SUB_VEN, POWERCOLOR_RED_DEVIL_RX5700XT_SUB_DEV, 0x22); +REGISTER_I2C_PCI_DETECTOR("PowerColor Red Devil RX6750XT", DetectPowerColorRedDevilGPUControllers, AMD_GPU_VEN, AMD_NAVI22_DEV, POWERCOLOR_SUB_VEN, POWERCOLOR_RED_DEVIL_RX6750XT_SUB_DEV, 0x22); +REGISTER_I2C_PCI_DETECTOR("PowerColor Red Devil RX6800XT", DetectPowerColorRedDevilGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, POWERCOLOR_SUB_VEN, POWERCOLOR_RED_DEVIL_RX6800XT_SUB_DEV, 0x22); +REGISTER_I2C_PCI_DETECTOR("PowerColor Red Devil RX6900XT Ultimate", DetectPowerColorRedDevilGPUControllers, AMD_GPU_VEN, AMD_NAVI21_DEV2, POWERCOLOR_SUB_VEN, POWERCOLOR_RED_DEVIL_RX6900XT_ULTIMATE_SUB_DEV, 0x22); diff --git a/Controllers/PowerColorRedDevilGPUController/RGBController_PowerColorRedDevilGPU.cpp b/Controllers/PowerColorRedDevilGPUController/RGBController_PowerColorRedDevilGPU.cpp new file mode 100755 index 00000000..475923e0 --- /dev/null +++ b/Controllers/PowerColorRedDevilGPUController/RGBController_PowerColorRedDevilGPU.cpp @@ -0,0 +1,249 @@ +/*---------------------------------------------------------*\ +| RGBController_PowerColorRedDevilGPU.cpp | +| | +| Driver for PowerColor Red Devil GPU | +| | +| Jana Rettig (SapphicKitten) 14 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_PowerColorRedDevilGPU.h" + +RGBController_RedDevilGPU::RGBController_RedDevilGPU(RedDevilGPUController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "PowerColor"; + description = "PowerColor Red Devil GPU Device"; + location = controller->GetDeviceLocation(); + type = DEVICE_TYPE_GPU; + + mode Off; + Off.name = "Off"; + Off.value = RED_DEVIL_GPU_MODE_OFF; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Static; + Static.name = "Static"; + Static.value = RED_DEVIL_GPU_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Static.color_mode = MODE_COLORS_PER_LED; + Static.brightness_min = RED_DEVIL_GPU_BRIGHTNESS_MIN; + Static.brightness_max = RED_DEVIL_GPU_BRIGHTNESS_MAX; + Static.brightness = RED_DEVIL_GPU_BRIGHTNESS_MAX; + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = RED_DEVIL_GPU_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.brightness_min = RED_DEVIL_GPU_BRIGHTNESS_MIN; + Breathing.brightness_max = RED_DEVIL_GPU_BRIGHTNESS_MAX; + Breathing.brightness = RED_DEVIL_GPU_BRIGHTNESS_MAX; + Breathing.speed_min = RED_DEVIL_GPU_SPEED_SLOWEST; + Breathing.speed_max = RED_DEVIL_GPU_SPEED_FASTEST; + Breathing.speed = RED_DEVIL_GPU_SPEED_DEFAULT; + modes.push_back(Breathing); + + mode Neon; + Neon.name = "Neon"; + Neon.value = RED_DEVIL_GPU_MODE_NEON; + Neon.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Neon.color_mode = MODE_COLORS_NONE; + Neon.brightness_min = RED_DEVIL_GPU_BRIGHTNESS_MIN; + Neon.brightness_max = RED_DEVIL_GPU_BRIGHTNESS_MAX; + Neon.brightness = RED_DEVIL_GPU_BRIGHTNESS_MAX; + Neon.speed_min = RED_DEVIL_GPU_SPEED_SLOWEST; + Neon.speed_max = RED_DEVIL_GPU_SPEED_FASTEST; + Neon.speed = RED_DEVIL_GPU_SPEED_DEFAULT; + modes.push_back(Neon); + + mode Blink; + Blink.name = "Blink"; + Blink.value = RED_DEVIL_GPU_MODE_BLINK; + Blink.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Blink.color_mode = MODE_COLORS_PER_LED; + Blink.brightness_min = RED_DEVIL_GPU_BRIGHTNESS_MIN; + Blink.brightness_max = RED_DEVIL_GPU_BRIGHTNESS_MAX; + Blink.brightness = RED_DEVIL_GPU_BRIGHTNESS_MAX; + Blink.speed_min = RED_DEVIL_GPU_SPEED_SLOWEST; + Blink.speed_max = RED_DEVIL_GPU_SPEED_FASTEST; + Blink.speed = RED_DEVIL_GPU_SPEED_DEFAULT; + modes.push_back(Blink); + + mode DoubleBlink; + DoubleBlink.name = "Double Blink"; + DoubleBlink.value = RED_DEVIL_GPU_MODE_DOUBLE_BLINK; + DoubleBlink.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + DoubleBlink.color_mode = MODE_COLORS_PER_LED; + DoubleBlink.brightness_min = RED_DEVIL_GPU_BRIGHTNESS_MIN; + DoubleBlink.brightness_max = RED_DEVIL_GPU_BRIGHTNESS_MAX; + DoubleBlink.brightness = RED_DEVIL_GPU_BRIGHTNESS_MAX; + DoubleBlink.speed_min = RED_DEVIL_GPU_SPEED_SLOWEST; + DoubleBlink.speed_max = RED_DEVIL_GPU_SPEED_FASTEST; + DoubleBlink.speed = RED_DEVIL_GPU_SPEED_DEFAULT; + modes.push_back(DoubleBlink); + + mode ColorShift; + ColorShift.name = "Color Shift"; + ColorShift.value = RED_DEVIL_GPU_MODE_COLOR_SHIFT; + ColorShift.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + ColorShift.color_mode = MODE_COLORS_NONE; + ColorShift.brightness_min = RED_DEVIL_GPU_BRIGHTNESS_MIN; + ColorShift.brightness_max = RED_DEVIL_GPU_BRIGHTNESS_MAX; + ColorShift.brightness = RED_DEVIL_GPU_BRIGHTNESS_MAX; + ColorShift.speed_min = RED_DEVIL_GPU_SPEED_SLOWEST; + ColorShift.speed_max = RED_DEVIL_GPU_SPEED_FASTEST; + ColorShift.speed = RED_DEVIL_GPU_SPEED_DEFAULT; + modes.push_back(ColorShift); + + + mode Meteor; + Meteor.name = "Meteor"; + Meteor.value = RED_DEVIL_GPU_MODE_METEOR; + Meteor.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Meteor.color_mode = MODE_COLORS_MODE_SPECIFIC; + Meteor.colors_min = 1; + Meteor.colors_max = 1; + Meteor.colors.resize(1); + Meteor.brightness_min = RED_DEVIL_GPU_BRIGHTNESS_MIN; + Meteor.brightness_max = RED_DEVIL_GPU_BRIGHTNESS_MAX; + Meteor.brightness = RED_DEVIL_GPU_BRIGHTNESS_MAX; + Meteor.speed_min = RED_DEVIL_GPU_SPEED_SLOWEST; + Meteor.speed_max = RED_DEVIL_GPU_SPEED_FASTEST; + Meteor.speed = RED_DEVIL_GPU_SPEED_DEFAULT; + modes.push_back(Meteor); + + mode Ripple; + Ripple.name = "Ripple"; + Ripple.value = RED_DEVIL_GPU_MODE_RIPPLE; + Ripple.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Ripple.color_mode = MODE_COLORS_MODE_SPECIFIC; + Ripple.colors_min = 1; + Ripple.colors_max = 1; + Ripple.colors.resize(1); + Ripple.brightness_min = RED_DEVIL_GPU_BRIGHTNESS_MIN; + Ripple.brightness_max = RED_DEVIL_GPU_BRIGHTNESS_MAX; + Ripple.brightness = RED_DEVIL_GPU_BRIGHTNESS_MAX; + Ripple.speed_min = RED_DEVIL_GPU_SPEED_SLOWEST; + Ripple.speed_max = RED_DEVIL_GPU_SPEED_FASTEST; + Ripple.speed = RED_DEVIL_GPU_SPEED_DEFAULT; + modes.push_back(Ripple); + + mode SevenColors; + SevenColors.name = "Seven Colors"; + SevenColors.value = RED_DEVIL_GPU_MODE_SEVEN_COLORS; + SevenColors.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + SevenColors.color_mode = MODE_COLORS_NONE; + SevenColors.brightness_min = RED_DEVIL_GPU_BRIGHTNESS_MIN; + SevenColors.brightness_max = RED_DEVIL_GPU_BRIGHTNESS_MAX; + SevenColors.brightness = RED_DEVIL_GPU_BRIGHTNESS_MAX; + SevenColors.speed_min = RED_DEVIL_GPU_SPEED_SLOWEST; + SevenColors.speed_max = RED_DEVIL_GPU_SPEED_FASTEST; + SevenColors.speed = RED_DEVIL_GPU_SPEED_DEFAULT; + modes.push_back(SevenColors); + + if(controller->has_sync_mode) + { + mode Sync; + Sync.name = "Sync with Motherboard"; + Sync.value = RED_DEVIL_GPU_MODE_MB_SYNC; + Sync.flags = MODE_FLAG_AUTOMATIC_SAVE; + Sync.color_mode = MODE_COLORS_NONE; + modes.push_back(Sync); + } + + SetupZones(); + + red_devil_mode_config config = controller->GetMode(); + active_mode = config.mode; + + if(active_mode != RED_DEVIL_GPU_MODE_OFF) + { + modes[active_mode].brightness = config.brightness; + modes[active_mode].speed = config.speed; + + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + modes[active_mode].colors[0] = controller->GetModeColor(); + } + else + { + colors[0] = controller->GetLEDColor(0); + } + } +} + +RGBController_RedDevilGPU::~RGBController_RedDevilGPU() +{ + delete controller; +} + +void RGBController_RedDevilGPU::SetupZones() +{ + /*---------------------------------------------------------*\ + | Set up zone | + \*---------------------------------------------------------*/ + zone* new_zone = new zone(); + + new_zone->name = "GPU"; + new_zone->type = ZONE_TYPE_SINGLE; + new_zone->leds_min = 1; + new_zone->leds_max = 1; + new_zone->leds_count = 1; + new_zone->matrix_map = NULL; + zones.push_back(*new_zone); + + /*---------------------------------------------------------*\ + | This device can control up to 12 LEDs | + | For now all LEDs show the same color | + \*---------------------------------------------------------*/ + led* new_led = new led(); + + new_led->name = "GPU"; + leds.push_back(*new_led); + + SetupColors(); +} + +void RGBController_RedDevilGPU::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_RedDevilGPU::DeviceUpdateLEDs() +{ + controller->SetLEDColorAll(colors[0]); +} + +void RGBController_RedDevilGPU::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RedDevilGPU::UpdateSingleLED(int led) +{ + controller->SetLEDColor(led, colors[led]); +} + +void RGBController_RedDevilGPU::DeviceUpdateMode() +{ + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + if(modes[active_mode].colors[0] != 0) + { + controller->SetModeColor(modes[active_mode].colors[0]); + } + } + + red_devil_mode_config config{(unsigned char)modes[active_mode].value, (unsigned char)modes[active_mode].brightness, (unsigned char)modes[active_mode].speed}; + controller->SetMode(config); +} diff --git a/Controllers/PowerColorRedDevilGPUController/RGBController_PowerColorRedDevilGPU.h b/Controllers/PowerColorRedDevilGPUController/RGBController_PowerColorRedDevilGPU.h new file mode 100755 index 00000000..685faddb --- /dev/null +++ b/Controllers/PowerColorRedDevilGPUController/RGBController_PowerColorRedDevilGPU.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_PowerColorRedDevilGPU.cpp | +| | +| Driver for PowerColor Red Devil GPU | +| | +| Jana Rettig (SapphicKitten) 14 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "PowerColorRedDevilGPUController.h" + +class RGBController_RedDevilGPU : public RGBController +{ +public: + RGBController_RedDevilGPU(RedDevilGPUController* controller_ptr); + ~RGBController_RedDevilGPU(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RedDevilGPUController* controller; +}; diff --git a/Controllers/QMKOpenRGBController/QMKOpenRGBBaseController.cpp b/Controllers/QMKOpenRGBController/QMKOpenRGBBaseController.cpp new file mode 100644 index 00000000..5f3e74b0 --- /dev/null +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBBaseController.cpp @@ -0,0 +1,426 @@ +/*---------------------------------------------------------*\ +| QMKOpenRGBBaseController.cpp | +| | +| Common Driver for OpenRGB QMK Keyboard Protocol | +| | +| ChrisM 20 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "LogManager.h" +#include "RGBControllerKeyNames.h" +#include "SettingsManager.h" +#include "QMKOpenRGBBaseController.h" + +using namespace std::chrono_literals; + +qmk_keycodes qmk_keycode_keyname_map = +{ + { 0, KEY_EN_UNUSED }, + { 1, KEY_EN_RIGHT_FUNCTION }, + { 2, KEY_EN_UNUSED }, + { 3, KEY_EN_UNUSED }, + { 4, KEY_EN_A }, + { 5, KEY_EN_B }, + { 6, KEY_EN_C }, + { 7, KEY_EN_D }, + { 8, KEY_EN_E }, + { 9, KEY_EN_F }, + { 10, KEY_EN_G }, + { 11, KEY_EN_H }, + { 12, KEY_EN_I }, + { 13, KEY_EN_J }, + { 14, KEY_EN_K }, + { 15, KEY_EN_L }, + { 16, KEY_EN_M }, + { 17, KEY_EN_N }, + { 18, KEY_EN_O }, + { 19, KEY_EN_P }, + { 20, KEY_EN_Q }, + { 21, KEY_EN_R }, + { 22, KEY_EN_S }, + { 23, KEY_EN_T }, + { 24, KEY_EN_U }, + { 25, KEY_EN_V }, + { 26, KEY_EN_W }, + { 27, KEY_EN_X }, + { 28, KEY_EN_Y }, + { 29, KEY_EN_Z }, + { 30, KEY_EN_1 }, + { 31, KEY_EN_2 }, + { 32, KEY_EN_3 }, + { 33, KEY_EN_4 }, + { 34, KEY_EN_5 }, + { 35, KEY_EN_6 }, + { 36, KEY_EN_7 }, + { 37, KEY_EN_8 }, + { 38, KEY_EN_9 }, + { 39, KEY_EN_0 }, + { 40, KEY_EN_ANSI_ENTER }, + { 41, KEY_EN_ESCAPE }, + { 42, KEY_EN_BACKSPACE }, + { 43, KEY_EN_TAB }, + { 44, KEY_EN_SPACE }, + { 45, KEY_EN_MINUS }, + { 46, KEY_EN_EQUALS }, + { 47, KEY_EN_LEFT_BRACKET }, + { 48, KEY_EN_RIGHT_BRACKET }, + { 49, KEY_EN_ANSI_BACK_SLASH }, + { 50, KEY_EN_POUND }, + { 51, KEY_EN_SEMICOLON }, + { 52, KEY_EN_QUOTE }, + { 53, KEY_EN_BACK_TICK }, + { 54, KEY_EN_COMMA }, + { 55, KEY_EN_PERIOD }, + { 56, KEY_EN_FORWARD_SLASH }, + { 57, KEY_EN_CAPS_LOCK }, + { 58, KEY_EN_F1 }, + { 59, KEY_EN_F2 }, + { 60, KEY_EN_F3 }, + { 61, KEY_EN_F4 }, + { 62, KEY_EN_F5 }, + { 63, KEY_EN_F6 }, + { 64, KEY_EN_F7 }, + { 65, KEY_EN_F8 }, + { 66, KEY_EN_F9 }, + { 67, KEY_EN_F10 }, + { 68, KEY_EN_F11 }, + { 69, KEY_EN_F12 }, + { 70, KEY_EN_PRINT_SCREEN }, + { 71, KEY_EN_SCROLL_LOCK }, + { 72, KEY_EN_PAUSE_BREAK }, + { 73, KEY_EN_INSERT }, + { 74, KEY_EN_HOME }, + { 75, KEY_EN_PAGE_UP }, + { 76, KEY_EN_DELETE }, + { 77, KEY_EN_END }, + { 78, KEY_EN_PAGE_DOWN }, + { 79, KEY_EN_RIGHT_ARROW }, + { 80, KEY_EN_LEFT_ARROW }, + { 81, KEY_EN_DOWN_ARROW }, + { 82, KEY_EN_UP_ARROW }, + { 83, KEY_EN_NUMPAD_LOCK }, + { 84, KEY_EN_NUMPAD_DIVIDE }, + { 85, KEY_EN_NUMPAD_TIMES }, + { 86, KEY_EN_NUMPAD_MINUS }, + { 87, KEY_EN_NUMPAD_PLUS }, + { 88, KEY_EN_NUMPAD_ENTER }, + { 89, KEY_EN_NUMPAD_1 }, + { 90, KEY_EN_NUMPAD_2 }, + { 91, KEY_EN_NUMPAD_3 }, + { 92, KEY_EN_NUMPAD_4 }, + { 93, KEY_EN_NUMPAD_5 }, + { 94, KEY_EN_NUMPAD_6 }, + { 95, KEY_EN_NUMPAD_7 }, + { 96, KEY_EN_NUMPAD_8 }, + { 97, KEY_EN_NUMPAD_9 }, + { 98, KEY_EN_NUMPAD_0 }, + { 99, KEY_EN_NUMPAD_PERIOD }, + { 100, KEY_EN_ISO_BACK_SLASH }, + { 101, KEY_EN_MENU }, + { 104, "Key: F13" }, + { 105, "Key: F14" }, + { 106, "Key: F15" }, + { 107, "Key: F16" }, + { 168, KEY_EN_MEDIA_MUTE }, + { 169, KEY_EN_MEDIA_VOLUME_UP }, + { 170, KEY_EN_MEDIA_VOLUME_DOWN }, + { 171, KEY_EN_MEDIA_NEXT }, + { 172, KEY_EN_MEDIA_PREVIOUS }, + { 173, KEY_EN_MEDIA_STOP }, + { 174, KEY_EN_MEDIA_PLAY_PAUSE }, + { 175, "Key: Media Select" }, + { 176, "Key: Media Eject" }, + { 189, "Key: Brightness Up" }, + { 190, "Key: Brightness Down" }, + { 196, "Key: Task Manager" }, + { 202, "Key: RGB Brightness Up" }, + { 203, "Key: RGB Brightness Down" }, + { 216, KEY_EN_LEFT_SHIFT }, /* Space Cadet Left Shift */ + { 217, KEY_EN_RIGHT_SHIFT }, /* Space Cadet Right Shift */ + { 224, KEY_EN_LEFT_CONTROL }, + { 225, KEY_EN_LEFT_SHIFT }, + { 226, KEY_EN_LEFT_ALT }, + { 227, KEY_EN_LEFT_WINDOWS }, + { 228, KEY_EN_RIGHT_CONTROL }, + { 229, KEY_EN_RIGHT_SHIFT }, + { 230, KEY_EN_RIGHT_ALT }, + { 231, KEY_EN_RIGHT_WINDOWS }, +}; + +QMKOpenRGBBaseController::QMKOpenRGBBaseController(hid_device *dev_handle, const char *path, unsigned char max_led_count) +{ + /*-------------------------------------------------*\ + | Get QMKOpenRGB settings | + \*-------------------------------------------------*/ + json qmk_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("QMKOpenRGBDevices"); + if(qmk_settings.contains("leds_per_update")) + { + if(qmk_settings["leds_per_update"] > max_led_count) + { + qmk_settings["leds_per_update"] = max_led_count; + } + else if(qmk_settings["leds_per_update"] < 1) + { + qmk_settings["leds_per_update"] = 1; + } + SettingsManager* settings_manager = ResourceManager::get()->GetSettingsManager(); + settings_manager->SetSettings("QMKOpenRGBDevices", qmk_settings); + settings_manager->SaveSettings(); + leds_per_update = qmk_settings["leds_per_update"]; + } + else + { + leds_per_update = max_led_count; + } + + if(qmk_settings.contains("delay")) + { + delay = (unsigned int)qmk_settings["delay"] * 1ms; + } + else + { + delay = 0ms; + } + + dev = dev_handle; + location = path; + + GetDeviceInfo(); + GetModeInfo(); +} + +QMKOpenRGBBaseController::~QMKOpenRGBBaseController() +{ + hid_close(dev); +} + +std::string QMKOpenRGBBaseController::GetLocation() +{ + return("HID: " + location); +} + +std::string QMKOpenRGBBaseController::GetDeviceName() +{ + return device_name; +} + +std::string QMKOpenRGBBaseController::GetDeviceVendor() +{ + return device_vendor; +} + +unsigned int QMKOpenRGBBaseController::GetTotalNumberOfLEDs() +{ + return total_number_of_leds; +} + +unsigned int QMKOpenRGBBaseController::GetTotalNumberOfLEDsWithEmptySpace() +{ + return total_number_of_leds_with_empty_space; +} + +unsigned int QMKOpenRGBBaseController::GetMode() +{ + return mode; +} + +unsigned int QMKOpenRGBBaseController::GetModeSpeed() +{ + return mode_speed; +} + +unsigned int QMKOpenRGBBaseController::GetModeColor() +{ + return mode_color; +} + +std::vector QMKOpenRGBBaseController::GetLEDPoints() +{ + return led_points; +} + +std::vector QMKOpenRGBBaseController::GetLEDFlags() +{ + return led_flags; +} + +std::vector QMKOpenRGBBaseController::GetLEDNames() +{ + return led_names; +} + +std::vector QMKOpenRGBBaseController::GetLEDColors() +{ + return led_colors; +} + +unsigned int QMKOpenRGBBaseController::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_OPENRGB_HID_READ_TIMEOUT); + } while(bytes_read <= 0); + + return usb_buf[1]; +} + +std::string QMKOpenRGBBaseController::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 QMKOpenRGBBaseController::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_OPENRGB_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 QMKOpenRGBBaseController::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_OPENRGB_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 QMKOpenRGBBaseController::SetMode(hsv_t hsv_color, unsigned char mode, unsigned char speed) +{ + SetMode(hsv_color, mode, speed, false); +} + +void QMKOpenRGBBaseController::SetMode(hsv_t hsv_color, unsigned char mode, unsigned char speed, bool save) +{ + 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; + usb_buf[0x07] = save; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); + hid_read_timeout(dev, usb_buf, 65, QMK_OPENRGB_HID_READ_TIMEOUT); +} diff --git a/Controllers/QMKOpenRGBController/QMKOpenRGBBaseController.h b/Controllers/QMKOpenRGBController/QMKOpenRGBBaseController.h new file mode 100644 index 00000000..ca1b3880 --- /dev/null +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBBaseController.h @@ -0,0 +1,81 @@ +/*---------------------------------------------------------*\ +| QMKOpenRGBBaseController.h | +| | +| Common Driver for OpenRGB QMK Keyboard Protocol | +| | +| ChrisM 20 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "LogManager.h" +#include "RGBController.h" +#include "RGBControllerKeyNames.h" +#include "SettingsManager.h" +#include "QMKOpenRGBController.h" + +typedef std::map qmk_keycodes; +extern qmk_keycodes qmk_keycode_keyname_map; + +class QMKOpenRGBBaseController +{ +public: + QMKOpenRGBBaseController(hid_device *dev_handle, const char *path, unsigned char max_led_count); + virtual ~QMKOpenRGBBaseController(); + + 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 GetLEDPoints(); + std::vector GetLEDFlags(); + std::vector GetLEDNames(); + std::vector GetLEDColors(); + + unsigned int GetProtocolVersion(); + std::string GetQMKVersion(); + void GetDeviceInfo(); + void GetModeInfo(); + + void SetMode(hsv_t hsv_color, unsigned char mode, unsigned char speed); + void SetMode(hsv_t hsv_color, unsigned char mode, unsigned char speed, bool save); + + virtual void GetLEDInfo(unsigned int leds_count) = 0; + virtual void DirectModeSetSingleLED(unsigned int led, unsigned char red, unsigned char green, unsigned char blue) = 0; + virtual void DirectModeSetLEDs(std::vector colors, unsigned int leds_count) = 0; + +protected: + hid_device *dev; + + unsigned int leds_per_update; + + std::string location; + + std::string device_name; + std::string device_vendor; + + std::chrono::milliseconds delay; + + 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 led_points; + std::vector led_flags; + std::vector led_names; + std::vector led_colors; + +private: +}; diff --git a/Controllers/QMKOpenRGBController/QMKOpenRGBController.h b/Controllers/QMKOpenRGBController/QMKOpenRGBController.h index d0c4c0fb..3cdcb438 100644 --- a/Controllers/QMKOpenRGBController/QMKOpenRGBController.h +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBController.h @@ -1,20 +1,23 @@ -/*-------------------------------------------------------------------*\ -| QMKOpenRGBController.h | -| | -| Common definitions for QMK OpenRGB Controller | -| | -| Kasper 10th Octobber 2020 | -| Jath03 28th May 2021 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| QMKOpenRGBController.h | +| | +| Driver for OpenRGB QMK Keyboard Protocol | +| | +| Kasper 10 Oct 2020 | +| Jath03 28 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include #include "ResourceManager.h" #include "RGBController.h" #include "hsv.h" -#include -#include -#include #define QMK_OPENRGB_PACKET_SIZE 65 #define QMK_OPENRGB_HID_READ_TIMEOUT 50 @@ -127,4 +130,4 @@ typedef struct { uint8_t x; uint8_t y; -} point_t; \ No newline at end of file +} point_t; diff --git a/Controllers/QMKOpenRGBController/QMKOpenRGBControllerDetect.cpp b/Controllers/QMKOpenRGBController/QMKOpenRGBControllerDetect.cpp index 79a7d2b0..7a745937 100644 --- a/Controllers/QMKOpenRGBController/QMKOpenRGBControllerDetect.cpp +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBControllerDetect.cpp @@ -1,26 +1,27 @@ -/*-------------------------------------------------------------------*\ -| QMKOpenRGBControllerDetect.cpp | -| | -| Driver for QMK keyboards using OpenRGB Protocol | -| | -| Kasper 10th Octobber 2020 | -| Jath03 28th May 2021 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| QMKOpenRGBControllerDetect.cpp | +| | +| Detector for OpenRGB QMK Keyboard Protocol | +| | +| Kasper 10 Oct 2020 | +| Jath03 28 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include #include - +#include #include "Detector.h" #include "QMKOpenRGBRev9Controller.h" #include "QMKOpenRGBRevBController.h" #include "QMKOpenRGBRevDController.h" -#include "RGBController.h" #include "RGBController_QMKOpenRGBRev9.h" #include "RGBController_QMKOpenRGBRevB.h" #include "RGBController_QMKOpenRGBRevD.h" #include "RGBController_QMKOpenRGBRevE.h" #include "LogManager.h" -#include +#include "SettingsManager.h" /*-----------------------------------------------------*\ | Protocol version | diff --git a/Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller.cpp b/Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller.cpp deleted file mode 100644 index b08575f6..00000000 --- a/Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller.cpp +++ /dev/null @@ -1,474 +0,0 @@ -/*-------------------------------------------------------------------*\ -| QMKOpenRGBRev9Controller.cpp | -| | -| Driver for QMK keyboards using OpenRGB Protocol (Revision 9) | -| | -| Revision 9 was the initial protocol supported by OpenRGB 0.6. | -| | -| Kasper 10th Octobber 2020 | -| Jath03 28th May 2021 | -\*-------------------------------------------------------------------*/ - -#include "RGBControllerKeyNames.h" -#include "QMKOpenRGBRev9Controller.h" - -using namespace std::chrono_literals; - -static std::map QMKKeycodeToKeynameMap -{ - { 0, KEY_EN_UNUSED }, { 1, KEY_EN_RIGHT_FUNCTION }, { 2, KEY_EN_UNUSED }, { 3, KEY_EN_UNUSED }, - { 4, KEY_EN_A }, { 5, KEY_EN_B }, { 6, KEY_EN_C }, { 7, KEY_EN_D }, - { 8, KEY_EN_E }, { 9, KEY_EN_F }, { 10, KEY_EN_G }, { 11, KEY_EN_H }, - { 12, KEY_EN_I }, { 13, KEY_EN_J }, { 14, KEY_EN_K }, { 15, KEY_EN_L }, - { 16, KEY_EN_M }, { 17, KEY_EN_N }, { 18, KEY_EN_O }, { 19, KEY_EN_P }, - { 20, KEY_EN_Q }, { 21, KEY_EN_R }, { 22, KEY_EN_S }, { 23, KEY_EN_T }, - { 24, KEY_EN_U }, { 25, KEY_EN_V }, { 26, KEY_EN_W }, { 27, KEY_EN_X }, - { 28, KEY_EN_Y }, { 29, KEY_EN_Z }, { 30, KEY_EN_1 }, { 31, KEY_EN_2 }, - { 32, KEY_EN_3 }, { 33, KEY_EN_4 }, { 34, KEY_EN_5 }, { 35, KEY_EN_6 }, - { 36, KEY_EN_7 }, { 37, KEY_EN_8 }, { 38, KEY_EN_9 }, { 39, KEY_EN_0 }, - { 40, KEY_EN_ANSI_ENTER }, { 41, KEY_EN_ESCAPE }, { 42, KEY_EN_BACKSPACE }, { 43, KEY_EN_TAB }, - { 44, KEY_EN_SPACE }, { 45, KEY_EN_MINUS }, { 46, KEY_EN_EQUALS }, { 47, KEY_EN_LEFT_BRACKET }, - { 48, KEY_EN_RIGHT_BRACKET }, { 49, KEY_EN_ANSI_BACK_SLASH }, { 50, KEY_EN_POUND }, { 51, KEY_EN_SEMICOLON }, - { 52, KEY_EN_QUOTE }, { 53, KEY_EN_BACK_TICK }, { 54, KEY_EN_COMMA }, { 55, KEY_EN_PERIOD }, - { 56, KEY_EN_FORWARD_SLASH }, { 57, KEY_EN_CAPS_LOCK }, { 58, KEY_EN_F1 }, { 59, KEY_EN_F2 }, - { 60, KEY_EN_F3 }, { 61, KEY_EN_F4 }, { 62, KEY_EN_F5 }, { 63, KEY_EN_F6 }, - { 64, KEY_EN_F7 }, { 65, KEY_EN_F8 }, { 66, KEY_EN_F9 }, { 67, KEY_EN_F10 }, - { 68, KEY_EN_F11 }, { 69, KEY_EN_F12 }, { 70, KEY_EN_PRINT_SCREEN }, { 71, KEY_EN_SCROLL_LOCK }, - { 72, KEY_EN_PAUSE_BREAK }, { 73, KEY_EN_INSERT }, { 74, KEY_EN_HOME }, { 75, KEY_EN_PAGE_UP }, - { 76, KEY_EN_DELETE }, { 77, KEY_EN_END }, { 78, KEY_EN_PAGE_DOWN }, { 79, KEY_EN_RIGHT_ARROW }, - { 80, KEY_EN_LEFT_ARROW }, { 81, KEY_EN_DOWN_ARROW }, { 82, KEY_EN_UP_ARROW }, { 83, KEY_EN_NUMPAD_LOCK }, - { 84, KEY_EN_NUMPAD_DIVIDE }, { 85, KEY_EN_NUMPAD_TIMES }, { 86, KEY_EN_NUMPAD_MINUS }, { 87, KEY_EN_NUMPAD_PLUS }, - { 88, KEY_EN_NUMPAD_ENTER }, { 89, KEY_EN_NUMPAD_1 }, { 90, KEY_EN_NUMPAD_2 }, { 91, KEY_EN_NUMPAD_3 }, - { 92, KEY_EN_NUMPAD_4 }, { 93, KEY_EN_NUMPAD_5 }, { 94, KEY_EN_NUMPAD_6 }, { 95, KEY_EN_NUMPAD_7 }, - { 96, KEY_EN_NUMPAD_8 }, { 97, KEY_EN_NUMPAD_9 }, { 98, KEY_EN_NUMPAD_0 }, { 99, KEY_EN_NUMPAD_PERIOD }, - { 100, KEY_EN_ISO_BACK_SLASH}, { 101, KEY_EN_MENU }, { 102, KEY_EN_UNUSED }, { 103, KEY_EN_UNUSED }, - { 104, KEY_EN_UNUSED }, { 105, KEY_EN_UNUSED }, { 106, KEY_EN_UNUSED }, { 107, KEY_EN_UNUSED }, - { 108, KEY_EN_UNUSED }, { 109, KEY_EN_UNUSED }, { 110, KEY_EN_UNUSED }, { 111, KEY_EN_UNUSED }, - { 112, KEY_EN_UNUSED }, { 113, KEY_EN_UNUSED }, { 114, KEY_EN_UNUSED }, { 115, KEY_EN_UNUSED }, - { 116, KEY_EN_UNUSED }, { 117, KEY_EN_UNUSED }, { 118, KEY_EN_UNUSED }, { 119, KEY_EN_UNUSED }, - { 120, KEY_EN_UNUSED }, { 121, KEY_EN_UNUSED }, { 122, KEY_EN_UNUSED }, { 123, KEY_EN_UNUSED }, - { 124, KEY_EN_UNUSED }, { 125, KEY_EN_UNUSED }, { 126, KEY_EN_UNUSED }, { 127, KEY_EN_UNUSED }, - { 128, KEY_EN_UNUSED }, { 129, KEY_EN_UNUSED }, { 130, KEY_EN_UNUSED }, { 131, KEY_EN_UNUSED }, - { 132, KEY_EN_UNUSED }, { 133, KEY_EN_UNUSED }, { 134, KEY_EN_UNUSED }, { 135, KEY_EN_UNUSED }, - { 136, KEY_EN_UNUSED }, { 137, KEY_EN_UNUSED }, { 138, KEY_EN_UNUSED }, { 139, KEY_EN_UNUSED }, - { 140, KEY_EN_UNUSED }, { 141, KEY_EN_UNUSED }, { 142, KEY_EN_UNUSED }, { 143, KEY_EN_UNUSED }, - { 144, KEY_EN_UNUSED }, { 145, KEY_EN_UNUSED }, { 146, KEY_EN_UNUSED }, { 147, KEY_EN_UNUSED }, - { 148, KEY_EN_UNUSED }, { 149, KEY_EN_UNUSED }, { 150, KEY_EN_UNUSED }, { 151, KEY_EN_UNUSED }, - { 152, KEY_EN_UNUSED }, { 153, KEY_EN_UNUSED }, { 154, KEY_EN_UNUSED }, { 155, KEY_EN_UNUSED }, - { 156, KEY_EN_UNUSED }, { 157, KEY_EN_UNUSED }, { 158, KEY_EN_UNUSED }, { 159, KEY_EN_UNUSED }, - { 160, KEY_EN_UNUSED }, { 161, KEY_EN_UNUSED }, { 162, KEY_EN_UNUSED }, { 163, KEY_EN_UNUSED }, - { 164, KEY_EN_UNUSED }, - /*Space Cadet Left Shift*/ { 216, KEY_EN_LEFT_SHIFT }, /*Space Cadet Right Shift*/ { 217, KEY_EN_RIGHT_SHIFT }, - { 224, KEY_EN_LEFT_CONTROL }, { 225, KEY_EN_LEFT_SHIFT }, { 226, KEY_EN_LEFT_ALT }, { 227, KEY_EN_LEFT_WINDOWS }, - { 228, KEY_EN_RIGHT_CONTROL }, { 229, KEY_EN_RIGHT_SHIFT }, { 230, KEY_EN_RIGHT_ALT }, { 231, KEY_EN_RIGHT_WINDOWS }, -}; - -QMKOpenRGBRev9Controller::QMKOpenRGBRev9Controller(hid_device *dev_handle, const char *path) -{ - /*-------------------------------------------------*\ - | Get QMKOpenRGB settings | - \*-------------------------------------------------*/ - json qmk_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("QMKOpenRGBDevices"); - if(qmk_settings.contains("leds_per_update")) - { - if(qmk_settings["leds_per_update"] > 20) - { - qmk_settings["leds_per_update"] = 20; - } - else if(qmk_settings["leds_per_update"] < 1) - { - qmk_settings["leds_per_update"] = 1; - } - SettingsManager* settings_manager = ResourceManager::get()->GetSettingsManager(); - settings_manager->SetSettings("QMKOpenRGBDevices", qmk_settings); - settings_manager->SaveSettings(); - leds_per_update = qmk_settings["leds_per_update"]; - } - else - { - leds_per_update = 20; - } - - if(qmk_settings.contains("delay")) - { - delay = (unsigned int)qmk_settings["delay"] * 1ms; - } - else - { - delay = 0ms; - } - - dev = dev_handle; - location = path; - - GetDeviceInfo(); - GetModeInfo(); -} - -QMKOpenRGBRev9Controller::~QMKOpenRGBRev9Controller() -{ - hid_close(dev); -} - -std::string QMKOpenRGBRev9Controller::GetLocation() -{ - return location; -} - -std::string QMKOpenRGBRev9Controller::GetDeviceName() -{ - return device_name; -} - -std::string QMKOpenRGBRev9Controller::GetDeviceVendor() -{ - return device_vendor; -} - -unsigned int QMKOpenRGBRev9Controller::GetTotalNumberOfLEDs() -{ - return total_number_of_leds; -} - -unsigned int QMKOpenRGBRev9Controller::GetTotalNumberOfLEDsWithEmptySpace() -{ - return total_number_of_leds_with_empty_space; -} - -unsigned int QMKOpenRGBRev9Controller::GetMode() -{ - return mode; -} - -unsigned int QMKOpenRGBRev9Controller::GetModeSpeed() -{ - return mode_speed; -} - -unsigned int QMKOpenRGBRev9Controller::GetModeColor() -{ - return mode_color; -} - -std::vector QMKOpenRGBRev9Controller::GetLEDPoints() -{ - return led_points; -} - -std::vector QMKOpenRGBRev9Controller::GetLEDFlags() -{ - return led_flags; -} - -std::vector QMKOpenRGBRev9Controller::GetLEDNames() -{ - return led_names; -} - -std::vector QMKOpenRGBRev9Controller::GetLEDColors() -{ - return led_colors; -} - -unsigned int QMKOpenRGBRev9Controller::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_OPENRGB_HID_READ_TIMEOUT); - } while(bytes_read <= 0); - - return usb_buf[1]; -} - -std::string QMKOpenRGBRev9Controller::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 QMKOpenRGBRev9Controller::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_OPENRGB_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 QMKOpenRGBRev9Controller::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_OPENRGB_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 QMKOpenRGBRev9Controller::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_OPENRGB_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(QMKKeycodeToKeynameMap[usb_buf[QMK_OPENRGB_KEYCODE_BYTE]]); - } - else - { - led_names.push_back(KEY_EN_UNUSED); - } - } -} - -bool QMKOpenRGBRev9Controller::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_OPENRGB_HID_READ_TIMEOUT); - } while(bytes_read <= 0); - - return usb_buf[1] == QMK_OPENRGB_SUCCESS ? true : false; -} - -void QMKOpenRGBRev9Controller::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_OPENRGB_HID_READ_TIMEOUT); -} - -void QMKOpenRGBRev9Controller::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_OPENRGB_HID_READ_TIMEOUT); -} - -void QMKOpenRGBRev9Controller::DirectModeSetLEDs(std::vector colors, unsigned int leds_count) -{ - unsigned int leds_sent = 0; - unsigned int tmp_leds_per_update = leds_per_update; - - while (leds_sent < leds_count) - { - if ((leds_count - leds_sent) < tmp_leds_per_update) - { - tmp_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] = tmp_leds_per_update; - - for (unsigned int led_idx = 0; led_idx < tmp_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); - - if(delay > 0ms) - { - std::this_thread::sleep_for(delay); - } - - leds_sent += tmp_leds_per_update; - } -} diff --git a/Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller.h b/Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller.h deleted file mode 100644 index ea2ebee8..00000000 --- a/Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller.h +++ /dev/null @@ -1,72 +0,0 @@ -/*-------------------------------------------------------------------*\ -| QMKOpenRGBRev9Controller.h | -| | -| Driver for QMK keyboards using OpenRGB Protocol (Revision 9) | -| | -| Revision 9 was the initial protocol supported by OpenRGB 0.6. | -| | -| Kasper 10th Octobber 2020 | -| Jath03 28th May 2021 | -\*-------------------------------------------------------------------*/ - -#pragma once - -#include "QMKOpenRGBController.h" - -class QMKOpenRGBRev9Controller -{ -public: - QMKOpenRGBRev9Controller(hid_device *dev_handle, const char *path); - ~QMKOpenRGBRev9Controller(); - - 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 GetLEDPoints(); - std::vector GetLEDFlags(); - std::vector GetLEDNames(); - std::vector 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 colors, unsigned int num_colors); - -protected: - hid_device *dev; - -private: - unsigned int leds_per_update; - - std::string location; - - std::string device_name; - std::string device_vendor; - - std::chrono::milliseconds delay; - - 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 led_points; - std::vector led_flags; - std::vector led_names; - std::vector led_colors; -}; diff --git a/Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller/QMKOpenRGBRev9Controller.cpp b/Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller/QMKOpenRGBRev9Controller.cpp new file mode 100644 index 00000000..a6885cc8 --- /dev/null +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller/QMKOpenRGBRev9Controller.cpp @@ -0,0 +1,169 @@ +/*---------------------------------------------------------*\ +| QMKOpenRGBRev9Controller.cpp | +| | +| Driver for OpenRGB QMK Keyboard Protocol Revision 9 | +| Revision 9 was initially supported by OpenRGB 0.6 | +| | +| Kasper 10 Oct 2020 | +| Jath03 28 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "QMKOpenRGBRev9Controller.h" + +using namespace std::chrono_literals; + +QMKOpenRGBRev9Controller::QMKOpenRGBRev9Controller(hid_device *dev_handle, const char *path) : + QMKOpenRGBBaseController(dev_handle, path, 20) +{ +} + +QMKOpenRGBRev9Controller::~QMKOpenRGBRev9Controller() +{ +} + +void QMKOpenRGBRev9Controller::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_OPENRGB_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 (qmk_keycode_keyname_map.count(usb_buf[QMK_OPENRGB_KEYCODE_BYTE]) > 0) + { + led_names.push_back(qmk_keycode_keyname_map[usb_buf[QMK_OPENRGB_KEYCODE_BYTE]]); + } + else + { + LOG_DEBUG("[%s] Key code: %d (%02X) @ offset %d was not found in the QMK keyname map", + device_name.c_str(), usb_buf[QMK_OPENRGB_KEYCODE_BYTE], + usb_buf[QMK_OPENRGB_KEYCODE_BYTE], led); + led_names.push_back(KEY_EN_UNUSED); + } + } +} + +bool QMKOpenRGBRev9Controller::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_OPENRGB_HID_READ_TIMEOUT); + } while(bytes_read <= 0); + + return usb_buf[1] == QMK_OPENRGB_SUCCESS ? true : false; +} + +void QMKOpenRGBRev9Controller::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_OPENRGB_HID_READ_TIMEOUT); +} + +void QMKOpenRGBRev9Controller::DirectModeSetLEDs(std::vector colors, unsigned int leds_count) +{ + unsigned int leds_sent = 0; + unsigned int tmp_leds_per_update = leds_per_update; + + while (leds_sent < leds_count) + { + if ((leds_count - leds_sent) < tmp_leds_per_update) + { + tmp_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] = tmp_leds_per_update; + + for (unsigned int led_idx = 0; led_idx < tmp_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); + + if(delay > 0ms) + { + std::this_thread::sleep_for(delay); + } + + leds_sent += tmp_leds_per_update; + } +} diff --git a/Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller/QMKOpenRGBRev9Controller.h b/Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller/QMKOpenRGBRev9Controller.h new file mode 100644 index 00000000..eeba2404 --- /dev/null +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller/QMKOpenRGBRev9Controller.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------*\ +| QMKOpenRGBRev9Controller.h | +| | +| Driver for OpenRGB QMK Keyboard Protocol Revision 9 | +| Revision 9 was initially supported by OpenRGB 0.6 | +| | +| Kasper 10 Oct 2020 | +| Jath03 28 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "QMKOpenRGBBaseController.h" + +class QMKOpenRGBRev9Controller : public QMKOpenRGBBaseController +{ +public: + QMKOpenRGBRev9Controller(hid_device *dev_handle, const char *path); + ~QMKOpenRGBRev9Controller(); + + //Virtual function implementations + void GetLEDInfo(unsigned int led); + void DirectModeSetSingleLED(unsigned int led, unsigned char red, unsigned char green, unsigned char blue); + void DirectModeSetLEDs(std::vector colors, unsigned int num_colors); + + //Protocol Specific functions + bool GetIsModeEnabled(unsigned int mode); + +private: +}; diff --git a/Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRev9.cpp b/Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller/RGBController_QMKOpenRGBRev9.cpp similarity index 93% rename from Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRev9.cpp rename to Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller/RGBController_QMKOpenRGBRev9.cpp index 320e6197..f394b5a9 100644 --- a/Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRev9.cpp +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller/RGBController_QMKOpenRGBRev9.cpp @@ -1,11 +1,15 @@ -/*-------------------------------------------------------------------*\ -| RGBController_QMKOpenRGBRev9.cpp | -| | -| Driver for QMK keyboards using OpenRGB Protocol (Revision 9) | -| | -| Kasper 10th Octobber 2020 | -| Jath03 28th May 2021 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_QMKOpenRGBRev9.cpp | +| | +| RGBController for OpenRGB QMK Keyboard Protocol | +| Revision 9 | +| | +| Kasper 10 Oct 2020 | +| Jath03 28 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "hsv.h" #include "LogManager.h" @@ -327,7 +331,7 @@ void RGBController_QMKOpenRGBRev9::SetupZones() VectorMatrix underglow_map; PlaceLEDsInMaps(rows, columns, divisor, led_points, led_flags, matrix_map, underglow_map); - CleanMatrixMaps(matrix_map, underglow_map, rows.size(), has_underglow); + CleanMatrixMaps(matrix_map, underglow_map, (unsigned int)rows.size(), has_underglow); /*---------------------------------------------------------*\ | These vectors are class members because if they go out of | @@ -347,8 +351,8 @@ void RGBController_QMKOpenRGBRev9::SetupZones() 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->width = (unsigned int)matrix_map[0].size(); + keys_zone.matrix_map->height = (unsigned int)matrix_map.size(); keys_zone.matrix_map->map = flat_matrix_map.data(); zones.push_back(keys_zone); @@ -364,8 +368,8 @@ void RGBController_QMKOpenRGBRev9::SetupZones() 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->width = (unsigned int)underglow_map[0].size(); + underglow_zone.matrix_map->height = (unsigned int)underglow_map.size(); underglow_zone.matrix_map->map = flat_underglow_map.data(); zones.push_back(underglow_zone); } @@ -567,8 +571,8 @@ void RGBController_QMKOpenRGBRev9::PlaceLEDsInMaps 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); + matrix_map_xl = MakeEmptyMatrixMap(unique_rows.size(), (std::size_t)(std::round(255 / divisor) + 10)); + underglow_map_xl = MakeEmptyMatrixMap(unique_rows.size(), (std::size_t)(std::round(255 / divisor) + 10)); unsigned int x = 0; unsigned int y = 0; @@ -580,8 +584,8 @@ void RGBController_QMKOpenRGBRev9::PlaceLEDsInMaps { 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)); + x = (unsigned int)(std::round(led_points[i].x / divisor)); + y = (unsigned int)(std::distance(unique_rows.begin(), unique_rows.find(led_points[i].y))); if(!underglow) { @@ -608,14 +612,14 @@ void RGBController_QMKOpenRGBRev9::PlaceLEDsInMaps VectorMatrix RGBController_QMKOpenRGBRev9::MakeEmptyMatrixMap ( - unsigned int height, - unsigned int width + std::size_t height, + std::size_t width ) { std::vector > matrix_map(height); - for (unsigned int i = 0; i < height; i++) + for(std::size_t i = 0; i < height; i++) { - for (unsigned int j = 0; j < width; j++) + for(std::size_t j = 0; j < width; j++) { matrix_map[i].push_back(NO_LED); } @@ -648,7 +652,7 @@ void RGBController_QMKOpenRGBRev9::CleanMatrixMaps can_break = false; can_break_udg = false; - for(int j = matrix_map[i].size() - 1; j --> 0; ) + for(int j = (int)matrix_map[i].size() - 1; j --> 0; ) { if(matrix_map[i][j] != NO_LED && width < (j + 1) && !can_break) { @@ -684,15 +688,15 @@ void RGBController_QMKOpenRGBRev9::CleanMatrixMaps } } - unsigned int new_height = height - empty_rows.size(); + unsigned int new_height = height - (unsigned int)empty_rows.size(); width = empty_col ? width - 1 : width; width_udg = empty_col_udg && empty_col ? width_udg - 1 : width_udg; LOG_DEBUG("[%s] Key LED Matrix: %ux%u", name.c_str(), width, new_height); LOG_DEBUG("[%s] Underglow LED Matrix: %ux%u", name.c_str(), width_udg, new_height); - for(unsigned int i = empty_rows.size(); i --> 0; ) + for(unsigned int i = (unsigned int)empty_rows.size(); i --> 0; ) { - matrix_map.erase(matrix_map.begin()+empty_rows[i]); + matrix_map.erase(matrix_map.begin() + empty_rows[i]); } for(unsigned int i = 0; i < new_height; i++) diff --git a/Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRev9.h b/Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller/RGBController_QMKOpenRGBRev9.h similarity index 81% rename from Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRev9.h rename to Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller/RGBController_QMKOpenRGBRev9.h index 9625d643..d3ae0d87 100644 --- a/Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRev9.h +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller/RGBController_QMKOpenRGBRev9.h @@ -1,20 +1,24 @@ -/*-------------------------------------------------------------------*\ -| RGBController_QMKOpenRGBRev9.h | -| | -| Driver for QMK keyboards using OpenRGB Protocol (Revision 9) | -| | -| Kasper 10th Octobber 2020 | -| Jath03 28th May 2021 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_QMKOpenRGBRev9.h | +| | +| RGBController for OpenRGB QMK Keyboard Protocol | +| Revision 9 | +| | +| Kasper 10 Oct 2020 | +| Jath03 28 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include "RGBController.h" -#include "QMKOpenRGBRev9Controller.h" #include #include #include #include +#include "RGBController.h" +#include "QMKOpenRGBRev9Controller.h" #define NO_LED 0xFFFFFFFF @@ -76,8 +80,8 @@ private: VectorMatrix MakeEmptyMatrixMap ( - unsigned int height, - unsigned int width + std::size_t height, + std::size_t width ); void CleanMatrixMaps diff --git a/Controllers/QMKOpenRGBController/QMKOpenRGBRevBController.cpp b/Controllers/QMKOpenRGBController/QMKOpenRGBRevBController.cpp deleted file mode 100644 index 361f523b..00000000 --- a/Controllers/QMKOpenRGBController/QMKOpenRGBRevBController.cpp +++ /dev/null @@ -1,496 +0,0 @@ -/*-------------------------------------------------------------------*\ -| QMKOpenRGBRevBController.cpp | -| | -| Driver for QMK keyboards using OpenRGB Protocol (Revision B) | -| | -| Kasper 10th Octobber 2020 | -| Jath03 28th May 2021 | -\*-------------------------------------------------------------------*/ - -#include "RGBControllerKeyNames.h" -#include "QMKOpenRGBRevBController.h" - -using namespace std::chrono_literals; - -static std::map QMKKeycodeToKeynameMap -{ - { 0, KEY_EN_UNUSED }, { 1, KEY_EN_RIGHT_FUNCTION }, { 2, KEY_EN_UNUSED }, { 3, KEY_EN_UNUSED }, - { 4, KEY_EN_A }, { 5, KEY_EN_B }, { 6, KEY_EN_C }, { 7, KEY_EN_D }, - { 8, KEY_EN_E }, { 9, KEY_EN_F }, { 10, KEY_EN_G }, { 11, KEY_EN_H }, - { 12, KEY_EN_I }, { 13, KEY_EN_J }, { 14, KEY_EN_K }, { 15, KEY_EN_L }, - { 16, KEY_EN_M }, { 17, KEY_EN_N }, { 18, KEY_EN_O }, { 19, KEY_EN_P }, - { 20, KEY_EN_Q }, { 21, KEY_EN_R }, { 22, KEY_EN_S }, { 23, KEY_EN_T }, - { 24, KEY_EN_U }, { 25, KEY_EN_V }, { 26, KEY_EN_W }, { 27, KEY_EN_X }, - { 28, KEY_EN_Y }, { 29, KEY_EN_Z }, { 30, KEY_EN_1 }, { 31, KEY_EN_2 }, - { 32, KEY_EN_3 }, { 33, KEY_EN_4 }, { 34, KEY_EN_5 }, { 35, KEY_EN_6 }, - { 36, KEY_EN_7 }, { 37, KEY_EN_8 }, { 38, KEY_EN_9 }, { 39, KEY_EN_0 }, - { 40, KEY_EN_ANSI_ENTER }, { 41, KEY_EN_ESCAPE }, { 42, KEY_EN_BACKSPACE }, { 43, KEY_EN_TAB }, - { 44, KEY_EN_SPACE }, { 45, KEY_EN_MINUS }, { 46, KEY_EN_EQUALS }, { 47, KEY_EN_LEFT_BRACKET }, - { 48, KEY_EN_RIGHT_BRACKET }, { 49, KEY_EN_ANSI_BACK_SLASH }, { 50, KEY_EN_POUND }, { 51, KEY_EN_SEMICOLON }, - { 52, KEY_EN_QUOTE }, { 53, KEY_EN_BACK_TICK }, { 54, KEY_EN_COMMA }, { 55, KEY_EN_PERIOD }, - { 56, KEY_EN_FORWARD_SLASH }, { 57, KEY_EN_CAPS_LOCK }, { 58, KEY_EN_F1 }, { 59, KEY_EN_F2 }, - { 60, KEY_EN_F3 }, { 61, KEY_EN_F4 }, { 62, KEY_EN_F5 }, { 63, KEY_EN_F6 }, - { 64, KEY_EN_F7 }, { 65, KEY_EN_F8 }, { 66, KEY_EN_F9 }, { 67, KEY_EN_F10 }, - { 68, KEY_EN_F11 }, { 69, KEY_EN_F12 }, { 70, KEY_EN_PRINT_SCREEN }, { 71, KEY_EN_SCROLL_LOCK }, - { 72, KEY_EN_PAUSE_BREAK }, { 73, KEY_EN_INSERT }, { 74, KEY_EN_HOME }, { 75, KEY_EN_PAGE_UP }, - { 76, KEY_EN_DELETE }, { 77, KEY_EN_END }, { 78, KEY_EN_PAGE_DOWN }, { 79, KEY_EN_RIGHT_ARROW }, - { 80, KEY_EN_LEFT_ARROW }, { 81, KEY_EN_DOWN_ARROW }, { 82, KEY_EN_UP_ARROW }, { 83, KEY_EN_NUMPAD_LOCK }, - { 84, KEY_EN_NUMPAD_DIVIDE }, { 85, KEY_EN_NUMPAD_TIMES }, { 86, KEY_EN_NUMPAD_MINUS }, { 87, KEY_EN_NUMPAD_PLUS }, - { 88, KEY_EN_NUMPAD_ENTER }, { 89, KEY_EN_NUMPAD_1 }, { 90, KEY_EN_NUMPAD_2 }, { 91, KEY_EN_NUMPAD_3 }, - { 92, KEY_EN_NUMPAD_4 }, { 93, KEY_EN_NUMPAD_5 }, { 94, KEY_EN_NUMPAD_6 }, { 95, KEY_EN_NUMPAD_7 }, - { 96, KEY_EN_NUMPAD_8 }, { 97, KEY_EN_NUMPAD_9 }, { 98, KEY_EN_NUMPAD_0 }, { 99, KEY_EN_NUMPAD_PERIOD }, - { 100, KEY_EN_ISO_BACK_SLASH}, { 101, KEY_EN_MENU }, { 102, KEY_EN_UNUSED }, { 103, KEY_EN_UNUSED }, - { 104, KEY_EN_UNUSED }, { 105, KEY_EN_UNUSED }, { 106, KEY_EN_UNUSED }, { 107, KEY_EN_UNUSED }, - { 108, KEY_EN_UNUSED }, { 109, KEY_EN_UNUSED }, { 110, KEY_EN_UNUSED }, { 111, KEY_EN_UNUSED }, - { 112, KEY_EN_UNUSED }, { 113, KEY_EN_UNUSED }, { 114, KEY_EN_UNUSED }, { 115, KEY_EN_UNUSED }, - { 116, KEY_EN_UNUSED }, { 117, KEY_EN_UNUSED }, { 118, KEY_EN_UNUSED }, { 119, KEY_EN_UNUSED }, - { 120, KEY_EN_UNUSED }, { 121, KEY_EN_UNUSED }, { 122, KEY_EN_UNUSED }, { 123, KEY_EN_UNUSED }, - { 124, KEY_EN_UNUSED }, { 125, KEY_EN_UNUSED }, { 126, KEY_EN_UNUSED }, { 127, KEY_EN_UNUSED }, - { 128, KEY_EN_UNUSED }, { 129, KEY_EN_UNUSED }, { 130, KEY_EN_UNUSED }, { 131, KEY_EN_UNUSED }, - { 132, KEY_EN_UNUSED }, { 133, KEY_EN_UNUSED }, { 134, KEY_EN_UNUSED }, { 135, KEY_EN_UNUSED }, - { 136, KEY_EN_UNUSED }, { 137, KEY_EN_UNUSED }, { 138, KEY_EN_UNUSED }, { 139, KEY_EN_UNUSED }, - { 140, KEY_EN_UNUSED }, { 141, KEY_EN_UNUSED }, { 142, KEY_EN_UNUSED }, { 143, KEY_EN_UNUSED }, - { 144, KEY_EN_UNUSED }, { 145, KEY_EN_UNUSED }, { 146, KEY_EN_UNUSED }, { 147, KEY_EN_UNUSED }, - { 148, KEY_EN_UNUSED }, { 149, KEY_EN_UNUSED }, { 150, KEY_EN_UNUSED }, { 151, KEY_EN_UNUSED }, - { 152, KEY_EN_UNUSED }, { 153, KEY_EN_UNUSED }, { 154, KEY_EN_UNUSED }, { 155, KEY_EN_UNUSED }, - { 156, KEY_EN_UNUSED }, { 157, KEY_EN_UNUSED }, { 158, KEY_EN_UNUSED }, { 159, KEY_EN_UNUSED }, - { 160, KEY_EN_UNUSED }, { 161, KEY_EN_UNUSED }, { 162, KEY_EN_UNUSED }, { 163, KEY_EN_UNUSED }, - { 164, KEY_EN_UNUSED }, - /*Space Cadet Left Shift*/ { 216, KEY_EN_LEFT_SHIFT }, /*Space Cadet Right Shift*/ { 217, KEY_EN_RIGHT_SHIFT }, - { 224, KEY_EN_LEFT_CONTROL }, { 225, KEY_EN_LEFT_SHIFT }, { 226, KEY_EN_LEFT_ALT }, { 227, KEY_EN_LEFT_WINDOWS }, - { 228, KEY_EN_RIGHT_CONTROL }, { 229, KEY_EN_RIGHT_SHIFT }, { 230, KEY_EN_RIGHT_ALT }, { 231, KEY_EN_RIGHT_WINDOWS }, -}; - -QMKOpenRGBRevBController::QMKOpenRGBRevBController(hid_device *dev_handle, const char *path) -{ - /*-------------------------------------------------*\ - | Get QMKOpenRGB settings | - \*-------------------------------------------------*/ - json qmk_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("QMKOpenRGBDevices"); - if(qmk_settings.contains("leds_per_update")) - { - if(qmk_settings["leds_per_update"] > 20) - { - qmk_settings["leds_per_update"] = 20; - } - else if(qmk_settings["leds_per_update"] < 1) - { - qmk_settings["leds_per_update"] = 1; - } - SettingsManager* settings_manager = ResourceManager::get()->GetSettingsManager(); - settings_manager->SetSettings("QMKOpenRGBDevices", qmk_settings); - settings_manager->SaveSettings(); - leds_per_update = qmk_settings["leds_per_update"]; - } - else - { - leds_per_update = 20; - } - - if(qmk_settings.contains("delay")) - { - delay = (unsigned int)qmk_settings["delay"] * 1ms; - } - else - { - delay = 0ms; - } - - dev = dev_handle; - location = path; - - GetDeviceInfo(); - GetModeInfo(); -} - -QMKOpenRGBRevBController::~QMKOpenRGBRevBController() -{ - hid_close(dev); -} - -std::string QMKOpenRGBRevBController::GetLocation() -{ - return location; -} - -std::string QMKOpenRGBRevBController::GetDeviceName() -{ - return device_name; -} - -std::string QMKOpenRGBRevBController::GetDeviceVendor() -{ - return device_vendor; -} - -unsigned int QMKOpenRGBRevBController::GetTotalNumberOfLEDs() -{ - return total_number_of_leds; -} - -unsigned int QMKOpenRGBRevBController::GetTotalNumberOfLEDsWithEmptySpace() -{ - return total_number_of_leds_with_empty_space; -} - -unsigned int QMKOpenRGBRevBController::GetMode() -{ - return mode; -} - -unsigned int QMKOpenRGBRevBController::GetModeSpeed() -{ - return mode_speed; -} - -unsigned int QMKOpenRGBRevBController::GetModeColor() -{ - return mode_color; -} - -std::vector QMKOpenRGBRevBController::GetLEDPoints() -{ - return led_points; -} - -std::vector QMKOpenRGBRevBController::GetLEDFlags() -{ - return led_flags; -} - -std::vector QMKOpenRGBRevBController::GetLEDNames() -{ - return led_names; -} - -std::vector QMKOpenRGBRevBController::GetLEDColors() -{ - return led_colors; -} - -unsigned int QMKOpenRGBRevBController::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_OPENRGB_HID_READ_TIMEOUT); - } while(bytes_read <= 0); - - return usb_buf[1]; -} - -std::string QMKOpenRGBRevBController::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 QMKOpenRGBRevBController::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_OPENRGB_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 QMKOpenRGBRevBController::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_OPENRGB_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 QMKOpenRGBRevBController::GetLEDInfo(unsigned int leds_count) -{ - unsigned int leds_sent = 0; - unsigned int leds_per_update_info = 8; - - while (leds_sent < leds_count) - { - if ((leds_count - leds_sent) < leds_per_update_info) - { - leds_per_update_info = 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_GET_LED_INFO; - usb_buf[0x02] = leds_sent; - usb_buf[0x03] = leds_per_update_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_OPENRGB_HID_READ_TIMEOUT); - } while(bytes_read <= 0); - - for (unsigned int led_idx = 0; led_idx < leds_per_update_info; led_idx++) - { - if(usb_buf[(led_idx * 7) + QMK_OPENRGB_FLAG_BYTE] != QMK_OPENRGB_FAILURE) - { - led_points.push_back(point_t{usb_buf[(led_idx * 7) + QMK_OPENRGB_POINT_X_BYTE], usb_buf[(led_idx * 7) + QMK_OPENRGB_POINT_Y_BYTE]}); - led_flags.push_back(usb_buf[(led_idx * 7) + QMK_OPENRGB_FLAG_BYTE]); - led_colors.push_back(ToRGBColor(usb_buf[(led_idx * 7) + QMK_OPENRGB_R_COLOR_BYTE], usb_buf[(led_idx * 7) + QMK_OPENRGB_G_COLOR_BYTE], usb_buf[(led_idx * 7) + QMK_OPENRGB_B_COLOR_BYTE])); - } - - if(usb_buf[(led_idx * 7) + QMK_OPENRGB_KEYCODE_BYTE] != 0) - { - if (QMKKeycodeToKeynameMap.count(usb_buf[(led_idx * 7) + QMK_OPENRGB_KEYCODE_BYTE]) > 0) - { - led_names.push_back(QMKKeycodeToKeynameMap[usb_buf[(led_idx * 7) + QMK_OPENRGB_KEYCODE_BYTE]]); - } - else - { - led_names.push_back(KEY_EN_UNUSED); - } - } - } - - leds_sent += leds_per_update_info; - } -} - -std::vector QMKOpenRGBRevBController::GetEnabledModes() -{ - 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_ENABLED_MODES; - - 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_OPENRGB_HID_READ_TIMEOUT); - } while(bytes_read <= 0); - - std::vector enabled_modes; - int i = 1; - while (usb_buf[i] != 0) - { - enabled_modes.push_back(usb_buf[i]); - i++; - } - return enabled_modes; -} - -void QMKOpenRGBRevBController::SetMode(hsv_t hsv_color, unsigned char mode, unsigned char speed, bool save) -{ - 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; - usb_buf[0x07] = save; - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); - hid_read_timeout(dev, usb_buf, 65, QMK_OPENRGB_HID_READ_TIMEOUT); -} - -void QMKOpenRGBRevBController::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_OPENRGB_HID_READ_TIMEOUT); -} - -void QMKOpenRGBRevBController::DirectModeSetLEDs(std::vector colors, unsigned int leds_count) -{ - unsigned int leds_sent = 0; - unsigned int tmp_leds_per_update = leds_per_update; - - while (leds_sent < leds_count) - { - if ((leds_count - leds_sent) < tmp_leds_per_update) - { - tmp_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] = tmp_leds_per_update; - - for (unsigned int led_idx = 0; led_idx < tmp_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); - - if(delay > 0ms) - { - std::this_thread::sleep_for(delay); - } - - leds_sent += tmp_leds_per_update; - } -} diff --git a/Controllers/QMKOpenRGBController/QMKOpenRGBRevBController.h b/Controllers/QMKOpenRGBController/QMKOpenRGBRevBController.h deleted file mode 100644 index 8590373d..00000000 --- a/Controllers/QMKOpenRGBController/QMKOpenRGBRevBController.h +++ /dev/null @@ -1,70 +0,0 @@ -/*-------------------------------------------------------------------*\ -| QMKOpenRGBRevBController.h | -| | -| Driver for QMK keyboards using OpenRGB Protocol (Revision B) | -| | -| Kasper 10th Octobber 2020 | -| Jath03 28th May 2021 | -\*-------------------------------------------------------------------*/ - -#pragma once - -#include "QMKOpenRGBController.h" - -class QMKOpenRGBRevBController -{ -public: - QMKOpenRGBRevBController(hid_device *dev_handle, const char *path); - ~QMKOpenRGBRevBController(); - - 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 GetLEDPoints(); - std::vector GetLEDFlags(); - std::vector GetLEDNames(); - std::vector GetLEDColors(); - - unsigned int GetProtocolVersion(); - std::string GetQMKVersion(); - void GetDeviceInfo(); - void GetModeInfo(); - void GetLEDInfo(unsigned int leds_count); - std::vector GetEnabledModes(); - - void SetMode(hsv_t hsv_color, unsigned char mode, unsigned char speed, bool save); - void DirectModeSetSingleLED(unsigned int led, unsigned char red, unsigned char green, unsigned char blue); - void DirectModeSetLEDs(std::vector colors, unsigned int num_colors); - -protected: - hid_device *dev; - -private: - unsigned int leds_per_update; - - std::string location; - - std::string device_name; - std::string device_vendor; - - std::chrono::milliseconds delay; - - 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 led_points; - std::vector led_flags; - std::vector led_names; - std::vector led_colors; -}; diff --git a/Controllers/QMKOpenRGBController/QMKOpenRGBRevBController/QMKOpenRGBRevBController.cpp b/Controllers/QMKOpenRGBController/QMKOpenRGBRevBController/QMKOpenRGBRevBController.cpp new file mode 100644 index 00000000..909d68fa --- /dev/null +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBRevBController/QMKOpenRGBRevBController.cpp @@ -0,0 +1,193 @@ +/*---------------------------------------------------------*\ +| QMKOpenRGBRevBController.cpp | +| | +| Driver for OpenRGB QMK Keyboard Protocol Revision B | +| | +| Kasper 28 Jun 2021 | +| Jath03 28 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "QMKOpenRGBRevBController.h" + +using namespace std::chrono_literals; + +QMKOpenRGBRevBController::QMKOpenRGBRevBController(hid_device *dev_handle, const char *path) : + QMKOpenRGBBaseController(dev_handle, path, 20) +{ +} + +QMKOpenRGBRevBController::~QMKOpenRGBRevBController() +{ +} + +void QMKOpenRGBRevBController::GetLEDInfo(unsigned int leds_count) +{ + unsigned int leds_sent = 0; + unsigned int leds_per_update_info = 8; + + while (leds_sent < leds_count) + { + if ((leds_count - leds_sent) < leds_per_update_info) + { + leds_per_update_info = 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_GET_LED_INFO; + usb_buf[0x02] = leds_sent; + usb_buf[0x03] = leds_per_update_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_OPENRGB_HID_READ_TIMEOUT); + } while(bytes_read <= 0); + + for (unsigned int led_idx = 0; led_idx < leds_per_update_info; led_idx++) + { + unsigned int offset = led_idx * 7; + + if(usb_buf[(offset) + QMK_OPENRGB_FLAG_BYTE] != QMK_OPENRGB_FAILURE) + { + led_points.push_back(point_t{usb_buf[(offset) + QMK_OPENRGB_POINT_X_BYTE], usb_buf[(offset) + QMK_OPENRGB_POINT_Y_BYTE]}); + led_flags.push_back(usb_buf[(offset) + QMK_OPENRGB_FLAG_BYTE]); + led_colors.push_back(ToRGBColor(usb_buf[(offset) + QMK_OPENRGB_R_COLOR_BYTE], usb_buf[(offset) + QMK_OPENRGB_G_COLOR_BYTE], usb_buf[(offset) + QMK_OPENRGB_B_COLOR_BYTE])); + } + + if(usb_buf[(offset) + QMK_OPENRGB_KEYCODE_BYTE] != 0) + { + if(qmk_keycode_keyname_map.count(usb_buf[(offset) + QMK_OPENRGB_KEYCODE_BYTE]) > 0) + { + led_names.push_back(qmk_keycode_keyname_map[usb_buf[(offset) + QMK_OPENRGB_KEYCODE_BYTE]]); + } + else + { + LOG_DEBUG("[%s] Key code: %d (%02X) @ offset %d was not found in the QMK keyname map", + device_name.c_str(), usb_buf[offset + QMK_OPENRGB_KEYCODE_BYTE], + usb_buf[offset + QMK_OPENRGB_KEYCODE_BYTE], leds_sent + led_idx); + led_names.push_back(KEY_EN_UNUSED); + } + } + } + + leds_sent += leds_per_update_info; + } +} + +std::vector QMKOpenRGBRevBController::GetEnabledModes() +{ + 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_ENABLED_MODES; + + 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_OPENRGB_HID_READ_TIMEOUT); + } while(bytes_read <= 0); + + std::vector enabled_modes; + int i = 1; + while (usb_buf[i] != 0) + { + enabled_modes.push_back(usb_buf[i]); + i++; + } + return enabled_modes; +} + +void QMKOpenRGBRevBController::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_OPENRGB_HID_READ_TIMEOUT); +} + +void QMKOpenRGBRevBController::DirectModeSetLEDs(std::vector colors, unsigned int leds_count) +{ + unsigned int leds_sent = 0; + unsigned int tmp_leds_per_update = leds_per_update; + + while (leds_sent < leds_count) + { + if ((leds_count - leds_sent) < tmp_leds_per_update) + { + tmp_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] = tmp_leds_per_update; + + for (unsigned int led_idx = 0; led_idx < tmp_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); + + if(delay > 0ms) + { + std::this_thread::sleep_for(delay); + } + + leds_sent += tmp_leds_per_update; + } +} diff --git a/Controllers/QMKOpenRGBController/QMKOpenRGBRevBController/QMKOpenRGBRevBController.h b/Controllers/QMKOpenRGBController/QMKOpenRGBRevBController/QMKOpenRGBRevBController.h new file mode 100644 index 00000000..7e37aa68 --- /dev/null +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBRevBController/QMKOpenRGBRevBController.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------*\ +| QMKOpenRGBRevBController.h | +| | +| Driver for OpenRGB QMK Keyboard Protocol Revision B | +| | +| Kasper 28 Jun 2021 | +| Jath03 28 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "QMKOpenRGBBaseController.h" + +class QMKOpenRGBRevBController : public QMKOpenRGBBaseController +{ +public: + QMKOpenRGBRevBController(hid_device *dev_handle, const char *path); + ~QMKOpenRGBRevBController(); + + //Virtual function implementations + void GetLEDInfo(unsigned int leds_count); + void DirectModeSetSingleLED(unsigned int led, unsigned char red, unsigned char green, unsigned char blue); + void DirectModeSetLEDs(std::vector colors, unsigned int num_colors); + + //Protocol Specific functions + std::vector GetEnabledModes(); + +private: +}; diff --git a/Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevB.cpp b/Controllers/QMKOpenRGBController/QMKOpenRGBRevBController/RGBController_QMKOpenRGBRevB.cpp similarity index 94% rename from Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevB.cpp rename to Controllers/QMKOpenRGBController/QMKOpenRGBRevBController/RGBController_QMKOpenRGBRevB.cpp index 36e0d5d6..f8ee4013 100644 --- a/Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevB.cpp +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBRevBController/RGBController_QMKOpenRGBRevB.cpp @@ -1,11 +1,15 @@ -/*-------------------------------------------------------------------*\ -| RGBController_QMKOpenRGBRevB.cpp | -| | -| Driver for QMK keyboards using OpenRGB Protocol (Revision B) | -| | -| Kasper 10th Octobber 2020 | -| Jath03 28th May 2021 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_QMKOpenRGBRevB.cpp | +| | +| RGBController for OpenRGB QMK Keyboard Protocol | +| Revision B | +| | +| Kasper 28 Jun 2021 | +| Jath03 28 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "hsv.h" #include "LogManager.h" @@ -326,7 +330,7 @@ void RGBController_QMKOpenRGBRevB::SetupZones() VectorMatrix underglow_map; PlaceLEDsInMaps(rows, columns, divisor, led_points, led_flags, matrix_map, underglow_map); - CleanMatrixMaps(matrix_map, underglow_map, rows.size(), has_underglow); + CleanMatrixMaps(matrix_map, underglow_map, (unsigned int)rows.size(), has_underglow); /*---------------------------------------------------------*\ | These vectors are class members because if they go out of | @@ -346,8 +350,8 @@ void RGBController_QMKOpenRGBRevB::SetupZones() 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->width = (unsigned int)matrix_map[0].size(); + keys_zone.matrix_map->height = (unsigned int)matrix_map.size(); keys_zone.matrix_map->map = flat_matrix_map.data(); zones.push_back(keys_zone); @@ -363,8 +367,8 @@ void RGBController_QMKOpenRGBRevB::SetupZones() 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->width = (unsigned int)underglow_map[0].size(); + underglow_zone.matrix_map->height = (unsigned int)underglow_map.size(); underglow_zone.matrix_map->map = flat_underglow_map.data(); zones.push_back(underglow_zone); } @@ -608,8 +612,8 @@ void RGBController_QMKOpenRGBRevB::PlaceLEDsInMaps 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); + matrix_map_xl = MakeEmptyMatrixMap(unique_rows.size(), (std::size_t)(std::round(255 / divisor) + 10)); + underglow_map_xl = MakeEmptyMatrixMap(unique_rows.size(), (std::size_t)(std::round(255 / divisor) + 10)); unsigned int x = 0; unsigned int y = 0; @@ -621,8 +625,8 @@ void RGBController_QMKOpenRGBRevB::PlaceLEDsInMaps { 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)); + x = (unsigned int)(std::round(led_points[i].x / divisor)); + y = (unsigned int)(std::distance(unique_rows.begin(), unique_rows.find(led_points[i].y))); if(!underglow) { @@ -649,14 +653,14 @@ void RGBController_QMKOpenRGBRevB::PlaceLEDsInMaps VectorMatrix RGBController_QMKOpenRGBRevB::MakeEmptyMatrixMap ( - unsigned int height, - unsigned int width + std::size_t height, + std::size_t width ) { std::vector > matrix_map(height); - for (unsigned int i = 0; i < height; i++) + for(std::size_t i = 0; i < height; i++) { - for (unsigned int j = 0; j < width; j++) + for(std::size_t j = 0; j < width; j++) { matrix_map[i].push_back(NO_LED); } @@ -689,7 +693,7 @@ void RGBController_QMKOpenRGBRevB::CleanMatrixMaps can_break = false; can_break_udg = false; - for(int j = matrix_map[i].size() - 1; j --> 0; ) + for(int j = (int)matrix_map[i].size() - 1; j --> 0; ) { if(matrix_map[i][j] != NO_LED && width < (j + 1) && !can_break) { @@ -725,13 +729,13 @@ void RGBController_QMKOpenRGBRevB::CleanMatrixMaps } } - unsigned int new_height = height - empty_rows.size(); + unsigned int new_height = height - (unsigned int)empty_rows.size(); width = empty_col ? width - 1 : width; width_udg = empty_col_udg && empty_col ? width_udg - 1 : width_udg; LOG_DEBUG("[%s] Key LED Matrix: %ux%u", name.c_str(), width, new_height); LOG_DEBUG("[%s] Underglow LED Matrix: %ux%u", name.c_str(), width_udg, new_height); - for(unsigned int i = empty_rows.size(); i --> 0; ) + for(unsigned int i = (unsigned int)empty_rows.size(); i --> 0; ) { matrix_map.erase(matrix_map.begin()+empty_rows[i]); } diff --git a/Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevB.h b/Controllers/QMKOpenRGBController/QMKOpenRGBRevBController/RGBController_QMKOpenRGBRevB.h similarity index 82% rename from Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevB.h rename to Controllers/QMKOpenRGBController/QMKOpenRGBRevBController/RGBController_QMKOpenRGBRevB.h index edc6efa4..10424d90 100644 --- a/Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevB.h +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBRevBController/RGBController_QMKOpenRGBRevB.h @@ -1,20 +1,24 @@ -/*-------------------------------------------------------------------*\ -| RGBController_QMKOpenRGBRevB.h | -| | -| Driver for QMK keyboards using OpenRGB Protocol (Revision B) | -| | -| Kasper 10th Octobber 2020 | -| Jath03 28th May 2021 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_QMKOpenRGBRevB.h | +| | +| RGBController for OpenRGB QMK Keyboard Protocol | +| Revision B | +| | +| Kasper 28 Jun 2021 | +| Jath03 28 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include "RGBController.h" -#include "QMKOpenRGBRevBController.h" #include #include #include #include +#include "RGBController.h" +#include "QMKOpenRGBRevBController.h" #define NO_LED 0xFFFFFFFF @@ -78,8 +82,8 @@ private: VectorMatrix MakeEmptyMatrixMap ( - unsigned int height, - unsigned int width + std::size_t height, + std::size_t width ); void CleanMatrixMaps diff --git a/Controllers/QMKOpenRGBController/QMKOpenRGBRevDController.cpp b/Controllers/QMKOpenRGBController/QMKOpenRGBRevDController.cpp deleted file mode 100644 index fa18f54b..00000000 --- a/Controllers/QMKOpenRGBController/QMKOpenRGBRevDController.cpp +++ /dev/null @@ -1,527 +0,0 @@ -/*-------------------------------------------------------------------*\ -| QMKOpenRGBRevDController.cpp | -| | -| Driver for QMK keyboards using OpenRGB Protocol (Revision D) | -| | -| Kasper 10th Octobber 2020 | -| Jath03 28th May 2021 | -\*-------------------------------------------------------------------*/ - -#include "RGBControllerKeyNames.h" -#include "QMKOpenRGBRevDController.h" - -using namespace std::chrono_literals; - -static std::map QMKKeycodeToKeynameMap -{ - { 0, KEY_EN_UNUSED }, { 1, KEY_EN_RIGHT_FUNCTION }, { 2, KEY_EN_UNUSED }, { 3, KEY_EN_UNUSED }, - { 4, KEY_EN_A }, { 5, KEY_EN_B }, { 6, KEY_EN_C }, { 7, KEY_EN_D }, - { 8, KEY_EN_E }, { 9, KEY_EN_F }, { 10, KEY_EN_G }, { 11, KEY_EN_H }, - { 12, KEY_EN_I }, { 13, KEY_EN_J }, { 14, KEY_EN_K }, { 15, KEY_EN_L }, - { 16, KEY_EN_M }, { 17, KEY_EN_N }, { 18, KEY_EN_O }, { 19, KEY_EN_P }, - { 20, KEY_EN_Q }, { 21, KEY_EN_R }, { 22, KEY_EN_S }, { 23, KEY_EN_T }, - { 24, KEY_EN_U }, { 25, KEY_EN_V }, { 26, KEY_EN_W }, { 27, KEY_EN_X }, - { 28, KEY_EN_Y }, { 29, KEY_EN_Z }, { 30, KEY_EN_1 }, { 31, KEY_EN_2 }, - { 32, KEY_EN_3 }, { 33, KEY_EN_4 }, { 34, KEY_EN_5 }, { 35, KEY_EN_6 }, - { 36, KEY_EN_7 }, { 37, KEY_EN_8 }, { 38, KEY_EN_9 }, { 39, KEY_EN_0 }, - { 40, KEY_EN_ANSI_ENTER }, { 41, KEY_EN_ESCAPE }, { 42, KEY_EN_BACKSPACE }, { 43, KEY_EN_TAB }, - { 44, KEY_EN_SPACE }, { 45, KEY_EN_MINUS }, { 46, KEY_EN_EQUALS }, { 47, KEY_EN_LEFT_BRACKET }, - { 48, KEY_EN_RIGHT_BRACKET }, { 49, KEY_EN_ANSI_BACK_SLASH }, { 50, KEY_EN_POUND }, { 51, KEY_EN_SEMICOLON }, - { 52, KEY_EN_QUOTE }, { 53, KEY_EN_BACK_TICK }, { 54, KEY_EN_COMMA }, { 55, KEY_EN_PERIOD }, - { 56, KEY_EN_FORWARD_SLASH }, { 57, KEY_EN_CAPS_LOCK }, { 58, KEY_EN_F1 }, { 59, KEY_EN_F2 }, - { 60, KEY_EN_F3 }, { 61, KEY_EN_F4 }, { 62, KEY_EN_F5 }, { 63, KEY_EN_F6 }, - { 64, KEY_EN_F7 }, { 65, KEY_EN_F8 }, { 66, KEY_EN_F9 }, { 67, KEY_EN_F10 }, - { 68, KEY_EN_F11 }, { 69, KEY_EN_F12 }, { 70, KEY_EN_PRINT_SCREEN }, { 71, KEY_EN_SCROLL_LOCK }, - { 72, KEY_EN_PAUSE_BREAK }, { 73, KEY_EN_INSERT }, { 74, KEY_EN_HOME }, { 75, KEY_EN_PAGE_UP }, - { 76, KEY_EN_DELETE }, { 77, KEY_EN_END }, { 78, KEY_EN_PAGE_DOWN }, { 79, KEY_EN_RIGHT_ARROW }, - { 80, KEY_EN_LEFT_ARROW }, { 81, KEY_EN_DOWN_ARROW }, { 82, KEY_EN_UP_ARROW }, { 83, KEY_EN_NUMPAD_LOCK }, - { 84, KEY_EN_NUMPAD_DIVIDE }, { 85, KEY_EN_NUMPAD_TIMES }, { 86, KEY_EN_NUMPAD_MINUS }, { 87, KEY_EN_NUMPAD_PLUS }, - { 88, KEY_EN_NUMPAD_ENTER }, { 89, KEY_EN_NUMPAD_1 }, { 90, KEY_EN_NUMPAD_2 }, { 91, KEY_EN_NUMPAD_3 }, - { 92, KEY_EN_NUMPAD_4 }, { 93, KEY_EN_NUMPAD_5 }, { 94, KEY_EN_NUMPAD_6 }, { 95, KEY_EN_NUMPAD_7 }, - { 96, KEY_EN_NUMPAD_8 }, { 97, KEY_EN_NUMPAD_9 }, { 98, KEY_EN_NUMPAD_0 }, { 99, KEY_EN_NUMPAD_PERIOD }, - { 100, KEY_EN_ISO_BACK_SLASH}, { 101, KEY_EN_MENU }, { 102, KEY_EN_UNUSED }, { 103, KEY_EN_UNUSED }, - { 104, KEY_EN_UNUSED }, { 105, KEY_EN_UNUSED }, { 106, KEY_EN_UNUSED }, { 107, KEY_EN_UNUSED }, - { 108, KEY_EN_UNUSED }, { 109, KEY_EN_UNUSED }, { 110, KEY_EN_UNUSED }, { 111, KEY_EN_UNUSED }, - { 112, KEY_EN_UNUSED }, { 113, KEY_EN_UNUSED }, { 114, KEY_EN_UNUSED }, { 115, KEY_EN_UNUSED }, - { 116, KEY_EN_UNUSED }, { 117, KEY_EN_UNUSED }, { 118, KEY_EN_UNUSED }, { 119, KEY_EN_UNUSED }, - { 120, KEY_EN_UNUSED }, { 121, KEY_EN_UNUSED }, { 122, KEY_EN_UNUSED }, { 123, KEY_EN_UNUSED }, - { 124, KEY_EN_UNUSED }, { 125, KEY_EN_UNUSED }, { 126, KEY_EN_UNUSED }, { 127, KEY_EN_UNUSED }, - { 128, KEY_EN_UNUSED }, { 129, KEY_EN_UNUSED }, { 130, KEY_EN_UNUSED }, { 131, KEY_EN_UNUSED }, - { 132, KEY_EN_UNUSED }, { 133, KEY_EN_UNUSED }, { 134, KEY_EN_UNUSED }, { 135, KEY_EN_UNUSED }, - { 136, KEY_EN_UNUSED }, { 137, KEY_EN_UNUSED }, { 138, KEY_EN_UNUSED }, { 139, KEY_EN_UNUSED }, - { 140, KEY_EN_UNUSED }, { 141, KEY_EN_UNUSED }, { 142, KEY_EN_UNUSED }, { 143, KEY_EN_UNUSED }, - { 144, KEY_EN_UNUSED }, { 145, KEY_EN_UNUSED }, { 146, KEY_EN_UNUSED }, { 147, KEY_EN_UNUSED }, - { 148, KEY_EN_UNUSED }, { 149, KEY_EN_UNUSED }, { 150, KEY_EN_UNUSED }, { 151, KEY_EN_UNUSED }, - { 152, KEY_EN_UNUSED }, { 153, KEY_EN_UNUSED }, { 154, KEY_EN_UNUSED }, { 155, KEY_EN_UNUSED }, - { 156, KEY_EN_UNUSED }, { 157, KEY_EN_UNUSED }, { 158, KEY_EN_UNUSED }, { 159, KEY_EN_UNUSED }, - { 160, KEY_EN_UNUSED }, { 161, KEY_EN_UNUSED }, { 162, KEY_EN_UNUSED }, { 163, KEY_EN_UNUSED }, - { 164, KEY_EN_UNUSED }, - /*Space Cadet Left Shift*/ { 216, KEY_EN_LEFT_SHIFT }, /*Space Cadet Right Shift*/ { 217, KEY_EN_RIGHT_SHIFT }, - { 224, KEY_EN_LEFT_CONTROL }, { 225, KEY_EN_LEFT_SHIFT }, { 226, KEY_EN_LEFT_ALT }, { 227, KEY_EN_LEFT_WINDOWS }, - { 228, KEY_EN_RIGHT_CONTROL }, { 229, KEY_EN_RIGHT_SHIFT }, { 230, KEY_EN_RIGHT_ALT }, { 231, KEY_EN_RIGHT_WINDOWS }, -}; - -QMKOpenRGBRevDController::QMKOpenRGBRevDController(hid_device *dev_handle, const char *path) -{ - /*-------------------------------------------------*\ - | Get QMKOpenRGB settings | - \*-------------------------------------------------*/ - json qmk_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("QMKOpenRGBDevices"); - if(qmk_settings.contains("leds_per_update")) - { - if(qmk_settings["leds_per_update"] > 15) - { - qmk_settings["leds_per_update"] = 15; - } - else if(qmk_settings["leds_per_update"] < 1) - { - qmk_settings["leds_per_update"] = 1; - } - SettingsManager* settings_manager = ResourceManager::get()->GetSettingsManager(); - settings_manager->SetSettings("QMKOpenRGBDevices", qmk_settings); - settings_manager->SaveSettings(); - leds_per_update = qmk_settings["leds_per_update"]; - } - else - { - leds_per_update = 15; - } - - if(qmk_settings.contains("delay")) - { - delay = (unsigned int)qmk_settings["delay"] * 1ms; - } - else - { - delay = 0ms; - } - - dev = dev_handle; - location = path; - - GetDeviceInfo(); - GetModeInfo(); -} - -QMKOpenRGBRevDController::~QMKOpenRGBRevDController() -{ - hid_close(dev); -} - -std::string QMKOpenRGBRevDController::GetLocation() -{ - return location; -} - -std::string QMKOpenRGBRevDController::GetDeviceName() -{ - return device_name; -} - -std::string QMKOpenRGBRevDController::GetDeviceVendor() -{ - return device_vendor; -} - -unsigned int QMKOpenRGBRevDController::GetTotalNumberOfLEDs() -{ - return total_number_of_leds; -} - -unsigned int QMKOpenRGBRevDController::GetTotalNumberOfLEDsWithEmptySpace() -{ - return total_number_of_leds_with_empty_space; -} - -unsigned int QMKOpenRGBRevDController::GetMode() -{ - return mode; -} - -unsigned int QMKOpenRGBRevDController::GetModeSpeed() -{ - return mode_speed; -} - -unsigned int QMKOpenRGBRevDController::GetModeColor() -{ - return mode_color; -} - -std::vector QMKOpenRGBRevDController::GetLEDPoints() -{ - return led_points; -} - -std::vector QMKOpenRGBRevDController::GetLEDFlags() -{ - return led_flags; -} - -std::vector QMKOpenRGBRevDController::GetLEDNames() -{ - return led_names; -} - -std::vector QMKOpenRGBRevDController::GetLEDColors() -{ - return led_colors; -} - -std::vector QMKOpenRGBRevDController::GetLEDValues() -{ - return led_values; -} - -unsigned int QMKOpenRGBRevDController::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_OPENRGB_HID_READ_TIMEOUT); - } while(bytes_read <= 0); - - return usb_buf[1]; -} - -std::string QMKOpenRGBRevDController::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 QMKOpenRGBRevDController::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_OPENRGB_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 QMKOpenRGBRevDController::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_OPENRGB_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 QMKOpenRGBRevDController::GetLEDInfo(unsigned int leds_count) -{ - unsigned int leds_sent = 0; - unsigned int leds_per_update_info = 8; - - std::vector underglow_points; - std::vector underglow_flags; - std::vector underglow_names; - std::vector underglow_colors; - std::vector underglow_values; - - while (leds_sent < leds_count) - { - if ((leds_count - leds_sent) < leds_per_update_info) - { - leds_per_update_info = 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_GET_LED_INFO; - usb_buf[0x02] = leds_sent; - usb_buf[0x03] = leds_per_update_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_OPENRGB_HID_READ_TIMEOUT); - } while(bytes_read <= 0); - - for (unsigned int led_idx = 0; led_idx < leds_per_update_info; led_idx++) - { - if(usb_buf[(led_idx * 7) + QMK_OPENRGB_FLAG_BYTE] != QMK_OPENRGB_FAILURE) - { - if(usb_buf[(led_idx * 7) + QMK_OPENRGB_FLAG_BYTE] & 2) - { - underglow_points.push_back(point_t{usb_buf[(led_idx * 7) + QMK_OPENRGB_POINT_X_BYTE], usb_buf[(led_idx * 7) + QMK_OPENRGB_POINT_Y_BYTE]}); - underglow_flags.push_back(usb_buf[(led_idx * 7) + QMK_OPENRGB_FLAG_BYTE]); - underglow_colors.push_back(ToRGBColor(usb_buf[(led_idx * 7) + QMK_OPENRGB_R_COLOR_BYTE], usb_buf[(led_idx * 7) + QMK_OPENRGB_G_COLOR_BYTE], usb_buf[(led_idx * 7) + QMK_OPENRGB_B_COLOR_BYTE])); - underglow_values.push_back(underglow_values.size() + led_values.size()); - } - else - { - led_points.push_back(point_t{usb_buf[(led_idx * 7) + QMK_OPENRGB_POINT_X_BYTE], usb_buf[(led_idx * 7) + QMK_OPENRGB_POINT_Y_BYTE]}); - led_flags.push_back(usb_buf[(led_idx * 7) + QMK_OPENRGB_FLAG_BYTE]); - led_colors.push_back(ToRGBColor(usb_buf[(led_idx * 7) + QMK_OPENRGB_R_COLOR_BYTE], usb_buf[(led_idx * 7) + QMK_OPENRGB_G_COLOR_BYTE], usb_buf[(led_idx * 7) + QMK_OPENRGB_B_COLOR_BYTE])); - led_values.push_back(underglow_values.size() + led_values.size()); - } - } - - if(usb_buf[(led_idx * 7) + QMK_OPENRGB_KEYCODE_BYTE] != 0) - { - if (QMKKeycodeToKeynameMap.count(usb_buf[(led_idx * 7) + QMK_OPENRGB_KEYCODE_BYTE]) > 0) - { - led_names.push_back(QMKKeycodeToKeynameMap[usb_buf[(led_idx * 7) + QMK_OPENRGB_KEYCODE_BYTE]]); - } - else - { - led_names.push_back(KEY_EN_UNUSED); - } - } - else if(usb_buf[(led_idx * 7) + QMK_OPENRGB_FLAG_BYTE] & 2){ - underglow_names.push_back("Underglow: " + std::to_string(underglow_names.size() + led_names.size())); - } - } - - leds_sent += leds_per_update_info; - } - - led_points.insert(led_points.end(), underglow_points.begin(), underglow_points.end()); - led_flags.insert(led_flags.end(), underglow_flags.begin(), underglow_flags.end()); - led_colors.insert(led_colors.end(), underglow_colors.begin(), underglow_colors.end()); - led_names.insert(led_names.end(), underglow_names.begin(), underglow_names.end()); - led_values.insert(led_values.end(), underglow_values.begin(), underglow_values.end()); -} - -std::vector QMKOpenRGBRevDController::GetEnabledModes() -{ - 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_ENABLED_MODES; - - 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_OPENRGB_HID_READ_TIMEOUT); - } while(bytes_read <= 0); - - std::vector enabled_modes; - int i = 1; - while (usb_buf[i] != 0) - { - enabled_modes.push_back(usb_buf[i]); - i++; - } - return enabled_modes; -} - -void QMKOpenRGBRevDController::SetMode(hsv_t hsv_color, unsigned char mode, unsigned char speed, bool save) -{ - 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; - usb_buf[0x07] = save; - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); - hid_read_timeout(dev, usb_buf, 65, QMK_OPENRGB_HID_READ_TIMEOUT); -} - -void QMKOpenRGBRevDController::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_values[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_OPENRGB_HID_READ_TIMEOUT); -} - -void QMKOpenRGBRevDController::DirectModeSetLEDs(std::vector colors, unsigned int leds_count) -{ - unsigned int leds_sent = 0; - unsigned int tmp_leds_per_update = leds_per_update; - - while (leds_sent < leds_count) - { - if ((leds_count - leds_sent) < tmp_leds_per_update) - { - tmp_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] = tmp_leds_per_update; - - for (unsigned int led_idx = 0; led_idx < tmp_leds_per_update; led_idx++) - { - usb_buf[(led_idx * 4) + 3] = led_values[led_idx + leds_sent]; - usb_buf[(led_idx * 4) + 4] = RGBGetRValue(colors[led_idx + leds_sent]); - usb_buf[(led_idx * 4) + 5] = RGBGetGValue(colors[led_idx + leds_sent]); - usb_buf[(led_idx * 4) + 6] = RGBGetBValue(colors[led_idx + leds_sent]); - } - - hid_write(dev, usb_buf, 65); - - if(delay > 0ms) - { - std::this_thread::sleep_for(delay); - } - - leds_sent += tmp_leds_per_update; - } -} diff --git a/Controllers/QMKOpenRGBController/QMKOpenRGBRevDController.h b/Controllers/QMKOpenRGBController/QMKOpenRGBRevDController.h deleted file mode 100644 index 378cc600..00000000 --- a/Controllers/QMKOpenRGBController/QMKOpenRGBRevDController.h +++ /dev/null @@ -1,72 +0,0 @@ -/*-------------------------------------------------------------------*\ -| QMKOpenRGBRevDController.h | -| | -| Driver for QMK keyboards using OpenRGB Protocol (Revision D) | -| | -| Kasper 10th Octobber 2020 | -| Jath03 28th May 2021 | -\*-------------------------------------------------------------------*/ - -#pragma once - -#include "QMKOpenRGBController.h" - -class QMKOpenRGBRevDController -{ -public: - QMKOpenRGBRevDController(hid_device *dev_handle, const char *path); - ~QMKOpenRGBRevDController(); - - 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 GetLEDPoints(); - std::vector GetLEDFlags(); - std::vector GetLEDNames(); - std::vector GetLEDColors(); - std::vector GetLEDValues(); - - unsigned int GetProtocolVersion(); - std::string GetQMKVersion(); - void GetDeviceInfo(); - void GetModeInfo(); - void GetLEDInfo(unsigned int leds_count); - std::vector GetEnabledModes(); - - void SetMode(hsv_t hsv_color, unsigned char mode, unsigned char speed, bool save); - void DirectModeSetSingleLED(unsigned int led, unsigned char red, unsigned char green, unsigned char blue); - void DirectModeSetLEDs(std::vector colors, unsigned int num_colors); - -protected: - hid_device *dev; - -private: - unsigned int leds_per_update; - - std::string location; - - std::string device_name; - std::string device_vendor; - - std::chrono::milliseconds delay; - - 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 led_points; - std::vector led_flags; - std::vector led_names; - std::vector led_colors; - std::vector led_values; -}; diff --git a/Controllers/QMKOpenRGBController/QMKOpenRGBRevDController/QMKOpenRGBRevDController.cpp b/Controllers/QMKOpenRGBController/QMKOpenRGBRevDController/QMKOpenRGBRevDController.cpp new file mode 100644 index 00000000..e0822272 --- /dev/null +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBRevDController/QMKOpenRGBRevDController.cpp @@ -0,0 +1,224 @@ +/*---------------------------------------------------------*\ +| QMKOpenRGBRevDController.cpp | +| | +| Driver for OpenRGB QMK Keyboard Protocol Revision D | +| | +| Neneya 26 Dec 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "QMKOpenRGBRevDController.h" + +using namespace std::chrono_literals; + +QMKOpenRGBRevDController::QMKOpenRGBRevDController(hid_device *dev_handle, const char *path) : + QMKOpenRGBBaseController(dev_handle, path, 15) +{ +} + +QMKOpenRGBRevDController::~QMKOpenRGBRevDController() +{ +} + +std::vector QMKOpenRGBRevDController::GetLEDValues() +{ + return led_values; +} + +void QMKOpenRGBRevDController::GetLEDInfo(unsigned int leds_count) +{ + unsigned int leds_sent = 0; + unsigned int leds_per_update_info = 8; + + std::vector underglow_points; + std::vector underglow_flags; + std::vector underglow_names; + std::vector underglow_colors; + std::vector underglow_values; + + while (leds_sent < leds_count) + { + if ((leds_count - leds_sent) < leds_per_update_info) + { + leds_per_update_info = 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_GET_LED_INFO; + usb_buf[0x02] = leds_sent; + usb_buf[0x03] = leds_per_update_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_OPENRGB_HID_READ_TIMEOUT); + } while(bytes_read <= 0); + + for (unsigned int led_idx = 0; led_idx < leds_per_update_info; led_idx++) + { + unsigned int offset = led_idx * 7; + + if(usb_buf[offset + QMK_OPENRGB_FLAG_BYTE] != QMK_OPENRGB_FAILURE) + { + if(usb_buf[offset + QMK_OPENRGB_FLAG_BYTE] & 2) + { + underglow_points.push_back(point_t{usb_buf[offset + QMK_OPENRGB_POINT_X_BYTE], usb_buf[offset + QMK_OPENRGB_POINT_Y_BYTE]}); + underglow_flags.push_back(usb_buf[offset + QMK_OPENRGB_FLAG_BYTE]); + underglow_colors.push_back(ToRGBColor(usb_buf[offset + QMK_OPENRGB_R_COLOR_BYTE], usb_buf[offset + QMK_OPENRGB_G_COLOR_BYTE], usb_buf[offset + QMK_OPENRGB_B_COLOR_BYTE])); + underglow_values.push_back((unsigned int)(underglow_values.size() + led_values.size())); + } + else + { + led_points.push_back(point_t{usb_buf[offset + QMK_OPENRGB_POINT_X_BYTE], usb_buf[offset + QMK_OPENRGB_POINT_Y_BYTE]}); + led_flags.push_back(usb_buf[offset + QMK_OPENRGB_FLAG_BYTE]); + led_colors.push_back(ToRGBColor(usb_buf[offset + QMK_OPENRGB_R_COLOR_BYTE], usb_buf[offset + QMK_OPENRGB_G_COLOR_BYTE], usb_buf[offset + QMK_OPENRGB_B_COLOR_BYTE])); + led_values.push_back((unsigned int)(underglow_values.size() + led_values.size())); + } + } + + if(usb_buf[offset + QMK_OPENRGB_KEYCODE_BYTE] != 0) + { + if (qmk_keycode_keyname_map.count(usb_buf[offset + QMK_OPENRGB_KEYCODE_BYTE]) > 0) + { + led_names.push_back(qmk_keycode_keyname_map[usb_buf[offset + QMK_OPENRGB_KEYCODE_BYTE]]); + } + else + { + LOG_DEBUG("[%s] Key code: %d (%02X) @ offset %d was not found in the QMK keyname map", + device_name.c_str(), usb_buf[offset + QMK_OPENRGB_KEYCODE_BYTE], + usb_buf[offset + QMK_OPENRGB_KEYCODE_BYTE], leds_sent + led_idx); + led_names.push_back(KEY_EN_UNUSED); + } + } + else if(usb_buf[offset + QMK_OPENRGB_FLAG_BYTE] & 2) + { + underglow_names.push_back("Underglow: " + std::to_string(underglow_names.size() + led_names.size())); + } + } + + leds_sent += leds_per_update_info; + } + + led_points.insert(led_points.end(), underglow_points.begin(), underglow_points.end()); + led_flags.insert(led_flags.end(), underglow_flags.begin(), underglow_flags.end()); + led_colors.insert(led_colors.end(), underglow_colors.begin(), underglow_colors.end()); + led_names.insert(led_names.end(), underglow_names.begin(), underglow_names.end()); + led_values.insert(led_values.end(), underglow_values.begin(), underglow_values.end()); +} + +std::vector QMKOpenRGBRevDController::GetEnabledModes() +{ + 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_ENABLED_MODES; + + 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_OPENRGB_HID_READ_TIMEOUT); + } while(bytes_read <= 0); + + std::vector enabled_modes; + int i = 1; + while (usb_buf[i] != 0) + { + enabled_modes.push_back(usb_buf[i]); + i++; + } + return enabled_modes; +} + +void QMKOpenRGBRevDController::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_values[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_OPENRGB_HID_READ_TIMEOUT); +} + +void QMKOpenRGBRevDController::DirectModeSetLEDs(std::vector colors, unsigned int leds_count) +{ + unsigned int leds_sent = 0; + unsigned int tmp_leds_per_update = leds_per_update; + + while (leds_sent < leds_count) + { + if ((leds_count - leds_sent) < tmp_leds_per_update) + { + tmp_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] = tmp_leds_per_update; + + for (unsigned int led_idx = 0; led_idx < tmp_leds_per_update; led_idx++) + { + usb_buf[(led_idx * 4) + 3] = led_values[led_idx + leds_sent]; + usb_buf[(led_idx * 4) + 4] = RGBGetRValue(colors[led_idx + leds_sent]); + usb_buf[(led_idx * 4) + 5] = RGBGetGValue(colors[led_idx + leds_sent]); + usb_buf[(led_idx * 4) + 6] = RGBGetBValue(colors[led_idx + leds_sent]); + } + + hid_write(dev, usb_buf, 65); + + if(delay > 0ms) + { + std::this_thread::sleep_for(delay); + } + + leds_sent += tmp_leds_per_update; + } +} diff --git a/Controllers/QMKOpenRGBController/QMKOpenRGBRevDController/QMKOpenRGBRevDController.h b/Controllers/QMKOpenRGBController/QMKOpenRGBRevDController/QMKOpenRGBRevDController.h new file mode 100644 index 00000000..a059494d --- /dev/null +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBRevDController/QMKOpenRGBRevDController.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------*\ +| QMKOpenRGBRevDController.h | +| | +| Driver for OpenRGB QMK Keyboard Protocol Revision D | +| | +| Neneya 26 Dec 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "QMKOpenRGBBaseController.h" + +class QMKOpenRGBRevDController : public QMKOpenRGBBaseController +{ +public: + QMKOpenRGBRevDController(hid_device *dev_handle, const char *path); + ~QMKOpenRGBRevDController(); + + //Virtual function implementations + void GetLEDInfo(unsigned int leds_count); + void DirectModeSetSingleLED(unsigned int led, unsigned char red, unsigned char green, unsigned char blue); + void DirectModeSetLEDs(std::vector colors, unsigned int num_colors); + + //Protocol Specific functions + std::vector GetLEDValues(); + std::vector GetEnabledModes(); + +private: + std::vector led_values; +}; diff --git a/Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevD.cpp b/Controllers/QMKOpenRGBController/QMKOpenRGBRevDController/RGBController_QMKOpenRGBRevD.cpp similarity index 94% rename from Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevD.cpp rename to Controllers/QMKOpenRGBController/QMKOpenRGBRevDController/RGBController_QMKOpenRGBRevD.cpp index 696646dc..08a1f9b6 100644 --- a/Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevD.cpp +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBRevDController/RGBController_QMKOpenRGBRevD.cpp @@ -1,11 +1,14 @@ -/*-------------------------------------------------------------------*\ -| RGBController_QMKOpenRGBRevD.cpp | -| | -| Driver for QMK keyboards using OpenRGB Protocol (Revision D) | -| | -| Kasper 10th Octobber 2020 | -| Jath03 28th May 2021 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_QMKOpenRGBRevD.cpp | +| | +| RGBController for OpenRGB QMK Keyboard Protocol | +| Revision D | +| | +| Neneya 26 Dec 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "hsv.h" #include "LogManager.h" @@ -322,7 +325,7 @@ void RGBController_QMKOpenRGBRevD::SetupZones() VectorMatrix underglow_map; PlaceLEDsInMaps(rows, columns, divisor, led_points, led_flags, matrix_map, underglow_map); - CleanMatrixMaps(matrix_map, underglow_map, rows.size(), has_underglow); + CleanMatrixMaps(matrix_map, underglow_map, (unsigned int)rows.size(), has_underglow); /*---------------------------------------------------------*\ | These vectors are class members because if they go out of | @@ -342,8 +345,8 @@ void RGBController_QMKOpenRGBRevD::SetupZones() 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->width = (unsigned int)matrix_map[0].size(); + keys_zone.matrix_map->height = (unsigned int)matrix_map.size(); keys_zone.matrix_map->map = flat_matrix_map.data(); zones.push_back(keys_zone); @@ -359,8 +362,8 @@ void RGBController_QMKOpenRGBRevD::SetupZones() 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->width = (unsigned int)underglow_map[0].size(); + underglow_zone.matrix_map->height = (unsigned int)underglow_map.size(); underglow_zone.matrix_map->map = flat_underglow_map.data(); zones.push_back(underglow_zone); } @@ -610,8 +613,8 @@ void RGBController_QMKOpenRGBRevD::PlaceLEDsInMaps 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); + matrix_map_xl = MakeEmptyMatrixMap(unique_rows.size(), (std::size_t)(std::round(255 / divisor) + 10)); + underglow_map_xl = MakeEmptyMatrixMap(unique_rows.size(), (std::size_t)(std::round(255 / divisor) + 10)); unsigned int x = 0; unsigned int y = 0; @@ -623,8 +626,8 @@ void RGBController_QMKOpenRGBRevD::PlaceLEDsInMaps { 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)); + x = (unsigned int)(std::round(led_points[i].x / divisor)); + y = (unsigned int)(std::distance(unique_rows.begin(), unique_rows.find(led_points[i].y))); if(!underglow) { @@ -651,14 +654,14 @@ void RGBController_QMKOpenRGBRevD::PlaceLEDsInMaps VectorMatrix RGBController_QMKOpenRGBRevD::MakeEmptyMatrixMap ( - unsigned int height, - unsigned int width + std::size_t height, + std::size_t width ) { std::vector > matrix_map(height); - for (unsigned int i = 0; i < height; i++) + for(std::size_t i = 0; i < height; i++) { - for (unsigned int j = 0; j < width; j++) + for(std::size_t j = 0; j < width; j++) { matrix_map[i].push_back(NO_LED); } @@ -691,7 +694,7 @@ void RGBController_QMKOpenRGBRevD::CleanMatrixMaps can_break = false; can_break_udg = false; - for(int j = matrix_map[i].size() - 1; j --> 0; ) + for(int j = (int)matrix_map[i].size() - 1; j --> 0; ) { if(matrix_map[i][j] != NO_LED && width < (j + 1) && !can_break) { @@ -727,13 +730,13 @@ void RGBController_QMKOpenRGBRevD::CleanMatrixMaps } } - unsigned int new_height = height - empty_rows.size(); + unsigned int new_height = height - (unsigned int)empty_rows.size(); width = empty_col ? width - 1 : width; width_udg = empty_col_udg && empty_col ? width_udg - 1 : width_udg; LOG_DEBUG("[%s] Key LED Matrix: %ux%u", name.c_str(), width, new_height); LOG_DEBUG("[%s] Underglow LED Matrix: %ux%u", name.c_str(), width_udg, new_height); - for(unsigned int i = empty_rows.size(); i --> 0; ) + for(unsigned int i = (unsigned int)empty_rows.size(); i --> 0; ) { matrix_map.erase(matrix_map.begin()+empty_rows[i]); } diff --git a/Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevD.h b/Controllers/QMKOpenRGBController/QMKOpenRGBRevDController/RGBController_QMKOpenRGBRevD.h similarity index 83% rename from Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevD.h rename to Controllers/QMKOpenRGBController/QMKOpenRGBRevDController/RGBController_QMKOpenRGBRevD.h index 57242e1c..62f323d5 100644 --- a/Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevD.h +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBRevDController/RGBController_QMKOpenRGBRevD.h @@ -1,20 +1,23 @@ -/*-------------------------------------------------------------------*\ -| RGBController_QMKOpenRGBRevD.h | -| | -| Driver for QMK keyboards using OpenRGB Protocol (Revision D) | -| | -| Kasper 10th Octobber 2020 | -| Jath03 28th May 2021 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_QMKOpenRGBRevD.h | +| | +| RGBController for OpenRGB QMK Keyboard Protocol | +| Revision D | +| | +| Neneya 26 Dec 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include "RGBController.h" -#include "QMKOpenRGBRevDController.h" #include #include #include #include +#include "RGBController.h" +#include "QMKOpenRGBRevDController.h" #define NO_LED 0xFFFFFFFF @@ -78,8 +81,8 @@ private: VectorMatrix MakeEmptyMatrixMap ( - unsigned int height, - unsigned int width + std::size_t height, + std::size_t width ); void CleanMatrixMaps diff --git a/Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevE.cpp b/Controllers/QMKOpenRGBController/QMKOpenRGBRevEController/RGBController_QMKOpenRGBRevE.cpp similarity index 94% rename from Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevE.cpp rename to Controllers/QMKOpenRGBController/QMKOpenRGBRevEController/RGBController_QMKOpenRGBRevE.cpp index 639b272d..a5c42ed1 100644 --- a/Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevE.cpp +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBRevEController/RGBController_QMKOpenRGBRevE.cpp @@ -1,12 +1,15 @@ -/*-------------------------------------------------------------------*\ -| RGBController_QMKOpenRGBRevE.cpp | -| | -| Driver for QMK keyboards using OpenRGB Protocol (Revision E) | -| | -| Kasper 10th Octobber 2020 | -| Jath03 28th May 2021 | -| HorrorTroll 11th July 2022 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_QMKOpenRGBRevE.cpp | +| | +| RGBController for OpenRGB QMK Keyboard Protocol | +| Revision E | +| | +| Neneya 26 Dec 2021 | +| HorrorTroll 11 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "hsv.h" #include "LogManager.h" @@ -338,7 +341,7 @@ void RGBController_QMKOpenRGBRevE::SetupZones() VectorMatrix underglow_map; PlaceLEDsInMaps(rows, columns, divisor, led_points, led_flags, matrix_map, underglow_map); - CleanMatrixMaps(matrix_map, underglow_map, rows.size(), has_underglow); + CleanMatrixMaps(matrix_map, underglow_map, (unsigned int)rows.size(), has_underglow); /*---------------------------------------------------------*\ | These vectors are class members because if they go out of | @@ -358,8 +361,8 @@ void RGBController_QMKOpenRGBRevE::SetupZones() 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->width = (unsigned int)matrix_map[0].size(); + keys_zone.matrix_map->height = (unsigned int)matrix_map.size(); keys_zone.matrix_map->map = flat_matrix_map.data(); zones.push_back(keys_zone); @@ -375,8 +378,8 @@ void RGBController_QMKOpenRGBRevE::SetupZones() 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->width = (unsigned int)underglow_map[0].size(); + underglow_zone.matrix_map->height = (unsigned int)underglow_map.size(); underglow_zone.matrix_map->map = flat_underglow_map.data(); zones.push_back(underglow_zone); } @@ -626,8 +629,8 @@ void RGBController_QMKOpenRGBRevE::PlaceLEDsInMaps 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); + matrix_map_xl = MakeEmptyMatrixMap(unique_rows.size(), (std::size_t)(std::round(255 / divisor) + 10)); + underglow_map_xl = MakeEmptyMatrixMap(unique_rows.size(), (std::size_t)(std::round(255 / divisor) + 10)); unsigned int x = 0; unsigned int y = 0; @@ -639,8 +642,8 @@ void RGBController_QMKOpenRGBRevE::PlaceLEDsInMaps { 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)); + x = (unsigned int)(std::round(led_points[i].x / divisor)); + y = (unsigned int)(std::distance(unique_rows.begin(), unique_rows.find(led_points[i].y))); if(!underglow) { @@ -667,14 +670,14 @@ void RGBController_QMKOpenRGBRevE::PlaceLEDsInMaps VectorMatrix RGBController_QMKOpenRGBRevE::MakeEmptyMatrixMap ( - unsigned int height, - unsigned int width + std::size_t height, + std::size_t width ) { std::vector > matrix_map(height); - for (unsigned int i = 0; i < height; i++) + for(std::size_t i = 0; i < height; i++) { - for (unsigned int j = 0; j < width; j++) + for(std::size_t j = 0; j < width; j++) { matrix_map[i].push_back(NO_LED); } @@ -707,7 +710,7 @@ void RGBController_QMKOpenRGBRevE::CleanMatrixMaps can_break = false; can_break_udg = false; - for(int j = matrix_map[i].size() - 1; j --> 0; ) + for(int j = (int)matrix_map[i].size() - 1; j --> 0; ) { if(matrix_map[i][j] != NO_LED && width < (j + 1) && !can_break) { @@ -743,13 +746,13 @@ void RGBController_QMKOpenRGBRevE::CleanMatrixMaps } } - unsigned int new_height = height - empty_rows.size(); + unsigned int new_height = height - (unsigned int)empty_rows.size(); width = empty_col ? width - 1 : width; width_udg = empty_col_udg && empty_col ? width_udg - 1 : width_udg; LOG_DEBUG("[%s] Key LED Matrix: %ux%u", name.c_str(), width, new_height); LOG_DEBUG("[%s] Underglow LED Matrix: %ux%u", name.c_str(), width_udg, new_height); - for(unsigned int i = empty_rows.size(); i --> 0; ) + for(unsigned int i = (unsigned int)empty_rows.size(); i --> 0; ) { matrix_map.erase(matrix_map.begin()+empty_rows[i]); } diff --git a/Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevE.h b/Controllers/QMKOpenRGBController/QMKOpenRGBRevEController/RGBController_QMKOpenRGBRevE.h similarity index 82% rename from Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevE.h rename to Controllers/QMKOpenRGBController/QMKOpenRGBRevEController/RGBController_QMKOpenRGBRevE.h index 3501df3f..1ced8853 100644 --- a/Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevE.h +++ b/Controllers/QMKOpenRGBController/QMKOpenRGBRevEController/RGBController_QMKOpenRGBRevE.h @@ -1,21 +1,24 @@ -/*-------------------------------------------------------------------*\ -| RGBController_QMKOpenRGBRevE.h | -| | -| Driver for QMK keyboards using OpenRGB Protocol (Revision E) | -| | -| Kasper 10th Octobber 2020 | -| Jath03 28th May 2021 | -| HorrorTroll 11th July 2022 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_QMKOpenRGBRevE.h | +| | +| RGBController for OpenRGB QMK Keyboard Protocol | +| Revision E | +| | +| Neneya 26 Dec 2021 | +| HorrorTroll 11 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include "RGBController.h" -#include "QMKOpenRGBRevDController.h" #include #include #include #include +#include "RGBController.h" +#include "QMKOpenRGBRevDController.h" #define NO_LED 0xFFFFFFFF @@ -79,8 +82,8 @@ private: VectorMatrix MakeEmptyMatrixMap ( - unsigned int height, - unsigned int width + std::size_t height, + std::size_t width ); void CleanMatrixMaps diff --git a/Controllers/RazerController/RGBController_Razer.h b/Controllers/RazerController/RGBController_Razer.h deleted file mode 100644 index 1c200267..00000000 --- a/Controllers/RazerController/RGBController_Razer.h +++ /dev/null @@ -1,44 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_Razer.h | -| | -| Generic RGB Interface for Razer devices | -| | -| Adam Honse (CalcProgrammer1) 1/22/2021 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "RazerController.h" - -#define NA 0xFFFFFFFF - -enum -{ - RAZER_MODE_DIRECT, - RAZER_MODE_OFF, - RAZER_MODE_STATIC, - RAZER_MODE_BREATHING, - RAZER_MODE_SPECTRUM_CYCLE, - RAZER_MODE_WAVE, - RAZER_MODE_REACTIVE, -}; - -class RGBController_Razer : public RGBController -{ -public: - RGBController_Razer(RazerController* controller_ptr); - ~RGBController_Razer(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - RazerController* controller; -}; diff --git a/Controllers/RazerController/RGBController_RazerAddressable.h b/Controllers/RazerController/RGBController_RazerAddressable.h deleted file mode 100644 index 698fcee4..00000000 --- a/Controllers/RazerController/RGBController_RazerAddressable.h +++ /dev/null @@ -1,42 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_RazerAddressable.h | -| | -| Generic RGB Interface for Razer devices | -| | -| Adam Honse (CalcProgrammer1) 4/11/2021 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "RazerController.h" - -enum -{ - RAZER_ADDRESSABLE_MODE_DIRECT, - RAZER_ADDRESSABLE_MODE_OFF, - RAZER_ADDRESSABLE_MODE_STATIC, - RAZER_ADDRESSABLE_MODE_BREATHING, - RAZER_ADDRESSABLE_MODE_SPECTRUM_CYCLE, - RAZER_ADDRESSABLE_MODE_WAVE, - RAZER_ADDRESSABLE_MODE_REACTIVE, -}; - -class RGBController_RazerAddressable : public RGBController -{ -public: - RGBController_RazerAddressable(RazerController* controller_ptr); - ~RGBController_RazerAddressable(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - RazerController* controller; -}; diff --git a/Controllers/RazerController/RGBController_RazerKraken.h b/Controllers/RazerController/RGBController_RazerKraken.h deleted file mode 100644 index 237e85b0..00000000 --- a/Controllers/RazerController/RGBController_RazerKraken.h +++ /dev/null @@ -1,41 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_RazerKraken.h | -| | -| Generic RGB Interface for Razer Kraken | -| devices | -| | -| Adam Honse (CalcProgrammer1) 2/28/2021 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "RazerKrakenController.h" - -enum -{ - RAZER_KRAKEN_MODE_DIRECT, - RAZER_KRAKEN_MODE_OFF, - RAZER_KRAKEN_MODE_STATIC, - RAZER_KRAKEN_MODE_BREATHING, - RAZER_KRAKEN_MODE_SPECTRUM_CYCLE, -}; - -class RGBController_RazerKraken : public RGBController -{ -public: - RGBController_RazerKraken(RazerKrakenController* controller_ptr); - ~RGBController_RazerKraken(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - RazerKrakenController* controller; -}; diff --git a/Controllers/RazerController/RGBController_Razer.cpp b/Controllers/RazerController/RazerController/RGBController_Razer.cpp similarity index 79% rename from Controllers/RazerController/RGBController_Razer.cpp rename to Controllers/RazerController/RazerController/RGBController_Razer.cpp index 2bd8936d..871de649 100644 --- a/Controllers/RazerController/RGBController_Razer.cpp +++ b/Controllers/RazerController/RazerController/RGBController_Razer.cpp @@ -1,3 +1,14 @@ +/*---------------------------------------------------------*\ +| RGBController_Razer.cpp | +| | +| RGBController for Razer devices | +| | +| Adam Honse (CalcProgrammer1) 22 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "RGBController_Razer.h" #include "RazerDevices.h" #include "LogManager.h" @@ -29,7 +40,7 @@ RGBController_Razer::RGBController_Razer(RazerController* controller_ptr) if(type == DEVICE_TYPE_KEYBOARD) { LOG_DEBUG("[%s] Checking Keyboard Layout", name.c_str()); - std::string layout = controller->GetKeyboardLayoutName(); + std::string layout = controller->GetKeyboardLayoutString(); LOG_DEBUG("[%s] returned: %s", name.c_str(), layout.c_str()); description.append(", "); @@ -229,7 +240,7 @@ void RGBController_Razer::SetupZones() { led new_led; - new_led.name = new_kb.GetKeyNameAt(row, col); + new_led.name = new_kb.GetKeyNameAt((unsigned int)row, (unsigned int)col); leds.push_back(new_led); } @@ -240,6 +251,10 @@ void RGBController_Razer::SetupZones() } else { + /*---------------------------------------------------------*\ + | Handle all other matrix type zones by filling in all | + | entries | + \*---------------------------------------------------------*/ matrix_map_type * new_map = new matrix_map_type; new_zone.matrix_map = new_map; new_map->height = device_list[device_index]->zones[zone_id]->rows; @@ -250,46 +265,7 @@ void RGBController_Razer::SetupZones() { for(unsigned int x = 0; x < new_map->width; x++) { - bool exists_in_keymap = false; - - if(new_zone.name != ZONE_EN_KEYBOARD) - { - /*---------------------------------------------------------*\ - | For zones other than the actual keyboard, we want all | - | entries in the matrix visible in the LED view (such as | - | underglow) | - \*---------------------------------------------------------*/ - exists_in_keymap = true; - } - else if(device_list[device_index]->keymap != NULL) - { - for(unsigned int i = 0; i < device_list[device_index]->keymap_size; i++) - { - razer_key key = device_list[device_index]->keymap[i]; - if(zone_id == key.zone && y == key.row && x == key.col && (key.layout & layout_type)) - { - exists_in_keymap = true; - break; - } - } - } - else - { - /*---------------------------------------------------------*\ - | If the device has no keymap defined we want all entries in| - | the matrix to be visible in the LED view | - \*---------------------------------------------------------*/ - exists_in_keymap = true; - } - - if (exists_in_keymap) - { - new_map->map[(y * new_map->width) + x] = (y * new_map->width) + x; - } - else - { - new_map->map[(y * new_map->width) + x] = -1; - } + new_map->map[(y * new_map->width) + x] = (y * new_map->width) + x; } } } @@ -315,33 +291,6 @@ void RGBController_Razer::SetupZones() new_led->name.append(std::to_string(col_id + 1)); } - if(device_list[device_index]->keymap != NULL) - { - bool not_found = true; - - for(unsigned int i = 0; i < device_list[device_index]->keymap_size; i++) - { - if(zone_id == device_list[device_index]->keymap[i].zone && - row_id == device_list[device_index]->keymap[i].row && - col_id == device_list[device_index]->keymap[i].col && - layout_type & device_list[device_index]->keymap[i].layout) - { - new_led->name = device_list[device_index]->keymap[i].name; - not_found = false; - break; - } - } - - /*-----------------------------------------------------------------*\ - | If this is the "Keyboard" zone and key was not found in the map | - | then change the value of the key to hide it from view | - \*-----------------------------------------------------------------*/ - if(not_found && zones[zone_id].name == ZONE_EN_KEYBOARD) - { - zones[zone_id].matrix_map->map[row_id * zones[zone_id].matrix_map->width + col_id] = NA; - } - } - leds.push_back(*new_led); } } diff --git a/Controllers/RazerController/RazerController/RGBController_Razer.h b/Controllers/RazerController/RazerController/RGBController_Razer.h new file mode 100644 index 00000000..5909ede2 --- /dev/null +++ b/Controllers/RazerController/RazerController/RGBController_Razer.h @@ -0,0 +1,48 @@ +/*---------------------------------------------------------*\ +| RGBController_Razer.h | +| | +| RGBController for Razer devices | +| | +| Adam Honse (CalcProgrammer1) 22 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RazerController.h" + +#define NA 0xFFFFFFFF + +enum +{ + RAZER_MODE_DIRECT, + RAZER_MODE_OFF, + RAZER_MODE_STATIC, + RAZER_MODE_BREATHING, + RAZER_MODE_SPECTRUM_CYCLE, + RAZER_MODE_WAVE, + RAZER_MODE_REACTIVE, +}; + +class RGBController_Razer : public RGBController +{ +public: + RGBController_Razer(RazerController* controller_ptr); + ~RGBController_Razer(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RazerController* controller; +}; diff --git a/Controllers/RazerController/RGBController_RazerAddressable.cpp b/Controllers/RazerController/RazerController/RGBController_RazerAddressable.cpp similarity index 95% rename from Controllers/RazerController/RGBController_RazerAddressable.cpp rename to Controllers/RazerController/RazerController/RGBController_RazerAddressable.cpp index b7cb6462..d3e0a9ab 100644 --- a/Controllers/RazerController/RGBController_RazerAddressable.cpp +++ b/Controllers/RazerController/RazerController/RGBController_RazerAddressable.cpp @@ -1,7 +1,17 @@ -#include "RGBController_RazerAddressable.h" -#include "RazerDevices.h" +/*---------------------------------------------------------*\ +| RGBController_RazerAddressable.cpp | +| | +| RGBController for Razer ARGB Controller | +| | +| Adam Honse (CalcProgrammer1) 11 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "RGBController_RazerAddressable.h" +#include "RazerDevices.h" /**------------------------------------------------------------------*\ @name Razer ARGB diff --git a/Controllers/RazerController/RazerController/RGBController_RazerAddressable.h b/Controllers/RazerController/RazerController/RGBController_RazerAddressable.h new file mode 100644 index 00000000..9eab31d4 --- /dev/null +++ b/Controllers/RazerController/RazerController/RGBController_RazerAddressable.h @@ -0,0 +1,46 @@ +/*---------------------------------------------------------*\ +| RGBController_RazerAddressable.h | +| | +| RGBController for Razer ARGB Controller | +| | +| Adam Honse (CalcProgrammer1) 11 Apr 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RazerController.h" + +enum +{ + RAZER_ADDRESSABLE_MODE_DIRECT, + RAZER_ADDRESSABLE_MODE_OFF, + RAZER_ADDRESSABLE_MODE_STATIC, + RAZER_ADDRESSABLE_MODE_BREATHING, + RAZER_ADDRESSABLE_MODE_SPECTRUM_CYCLE, + RAZER_ADDRESSABLE_MODE_WAVE, + RAZER_ADDRESSABLE_MODE_REACTIVE, +}; + +class RGBController_RazerAddressable : public RGBController +{ +public: + RGBController_RazerAddressable(RazerController* controller_ptr); + ~RGBController_RazerAddressable(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RazerController* controller; +}; diff --git a/Controllers/RazerController/RazerController.cpp b/Controllers/RazerController/RazerController/RazerController.cpp similarity index 91% rename from Controllers/RazerController/RazerController.cpp rename to Controllers/RazerController/RazerController/RazerController.cpp index 325b5f0d..a39d00a3 100644 --- a/Controllers/RazerController/RazerController.cpp +++ b/Controllers/RazerController/RazerController/RazerController.cpp @@ -1,27 +1,31 @@ -/*-----------------------------------------*\ -| RazerController.cpp | -| | -| Driver for Razer devices | -| | -| Adam Honse (CalcProgrammer1) 1/22/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RazerController.cpp | +| | +| Driver for Razer devices | +| | +| Adam Honse (CalcProgrammer1) 22 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include "RazerController.h" #include "RazerDevices.h" #include "LogManager.h" - -#include +#include "RazerDeviceGuard.h" using namespace std::chrono_literals; RazerController::RazerController(hid_device* dev_handle, hid_device* dev_argb_handle, const char* path, unsigned short pid, std::string dev_name) { - dev = dev_handle; - dev_argb = dev_argb_handle; - dev_pid = pid; - location = path; - name = dev_name; - device_index = 0; + dev = dev_handle; + dev_argb = dev_argb_handle; + dev_pid = pid; + location = path; + name = dev_name; + device_index = 0; + guard_manager_ptr = new DeviceGuardManager(new RazerDeviceGuard()); /*-----------------------------------------------------------------*\ | Loop through all known devices to look for a name match | @@ -42,6 +46,7 @@ RazerController::RazerController(hid_device* dev_handle, hid_device* dev_argb_ha \*-----------------------------------------------------------------*/ switch(dev_pid) { + case RAZER_LEVIATHAN_V2_PID: case RAZER_LEVIATHAN_V2X_PID: report_index = 0x07; response_index = 0x07; @@ -61,6 +66,7 @@ RazerController::RazerController(hid_device* dev_handle, hid_device* dev_argb_ha { case RAZER_CHARGING_PAD_CHROMA_PID: case RAZER_CHROMA_MUG_PID: + case RAZER_FIREFLY_HYPERFLUX_PID: { razer_set_device_mode(RAZER_DEVICE_MODE_SOFTWARE); } @@ -72,33 +78,52 @@ RazerController::RazerController(hid_device* dev_handle, hid_device* dev_argb_ha \*-----------------------------------------------------------------*/ switch(dev_pid) { + case RAZER_BASILISK_ULTIMATE_WIRED_PID: + case RAZER_BASILISK_ULTIMATE_WIRELESS_PID: case RAZER_BASILISK_V3_PID: + case RAZER_BASILISK_V3_35K_PID: + case RAZER_BASILISK_V3_X_HYPERSPEED_PID: case RAZER_BASILISK_V3_PRO_WIRED_PID: case RAZER_BASILISK_V3_PRO_WIRELESS_PID: + case RAZER_BASILISK_V3_PRO_35K_WIRED_PID: + case RAZER_BASILISK_V3_PRO_35K_WIRELESS_PID: case RAZER_BASILISK_V3_PRO_BLUETOOTH_PID: case RAZER_BASE_STATION_CHROMA_PID: case RAZER_BASE_STATION_V2_CHROMA_PID: case RAZER_BLADE_14_2022_PID: + case RAZER_BLADE_14_2023_PID: case RAZER_BLADE_15_2022_PID: case RAZER_CHARGING_PAD_CHROMA_PID: case RAZER_CHROMA_HDK_PID: + case RAZER_COBRA_PRO_WIRED_PID: + case RAZER_COBRA_PRO_WIRELESS_PID: case RAZER_CORE_X_PID: case RAZER_DEATHADDER_ELITE_PID: + case RAZER_DEATHADDER_V2_PID: case RAZER_DEATHADDER_V2_MINI_PID: case RAZER_DEATHADDER_ESSENTIAL_V2_PID: + case RAZER_DEATHSTALKER_V2_PRO_TKL_WIRED_PID: + case RAZER_DEATHSTALKER_V2_PRO_TKL_WIRELESS_PID: case RAZER_DEATHSTALKER_V2_PRO_WIRED_PID: case RAZER_DEATHSTALKER_V2_PRO_WIRELESS_PID: case RAZER_FIREFLY_V2_PID: + case RAZER_FIREFLY_V2_PRO_PID: + case RAZER_FIREFLY_HYPERFLUX_PID: case RAZER_GOLIATHUS_CHROMA_EXTENDED_PID: case RAZER_GOLIATHUS_CHROMA_PID: + case RAZER_GOLIATHUS_CHROMA_3XL_PID: case RAZER_LAPTOP_STAND_CHROMA_PID: case RAZER_LAPTOP_STAND_CHROMA_V2_PID: + case RAZER_LEVIATHAN_V2_PID: case RAZER_LEVIATHAN_V2X_PID: case RAZER_MAMBA_ELITE_PID: + case RAZER_MAMBA_HYPERFLUX_PID: case RAZER_MOUSE_BUNGEE_V3_CHROMA_PID: case RAZER_MOUSE_DOCK_PRO_PID: case RAZER_NAGA_CLASSIC_PID: case RAZER_NAGA_LEFT_HANDED_PID: + case RAZER_NAGA_PRO_V2_WIRED_PID: + case RAZER_NAGA_PRO_V2_WIRELESS_PID: case RAZER_O11_DYNAMIC_PID: case RAZER_STRIDER_CHROMA_PID: case RAZER_TARTARUS_PRO_PID: @@ -124,14 +149,18 @@ RazerController::RazerController(hid_device* dev_handle, hid_device* dev_argb_ha case RAZER_HUNTSMAN_ELITE_PID: case RAZER_HUNTSMAN_PID: case RAZER_HUNTSMAN_MINI_PID: + case RAZER_HUNTSMAN_MINI_ANALOG_PID: case RAZER_HUNTSMAN_TE_PID: case RAZER_HUNTSMAN_V2_ANALOG_PID: case RAZER_HUNTSMAN_V2_TKL_PID: case RAZER_HUNTSMAN_V2_PID: + case RAZER_HUNTSMAN_V3_PRO_PID: + case RAZER_HUNTSMAN_V3_PRO_TKL_WHITE_PID: case RAZER_ORNATA_CHROMA_PID: case RAZER_ORNATA_CHROMA_V2_PID: case RAZER_ORNATA_V3_PID: case RAZER_ORNATA_V3_REV2_PID: + case RAZER_ORNATA_V3_TKL_PID: case RAZER_ORNATA_V3_X_PID: case RAZER_CORE_PID: case RAZER_FIREFLY_PID: @@ -144,11 +173,36 @@ RazerController::RazerController(hid_device* dev_handle, hid_device* dev_argb_ha | Determine matrix type for device | \*-----------------------------------------------------------------*/ matrix_type = device_list[device_index]->matrix_type; + + /*-----------------------------------------------------------------*\ + | Start keepalive thread for devices that need it to prevent RGB | + | from timing out | + \*-----------------------------------------------------------------*/ + switch(dev_pid) + { + case RAZER_BLADE_14_2021_PID: + case RAZER_BLADE_14_2022_PID: + keepalive_thread_run = true; + keepalive_thread = new std::thread(&RazerController::KeepaliveThreadFunction, this); + break; + + default: + keepalive_thread_run = false; + keepalive_thread = NULL; + break; + } } RazerController::~RazerController() { + if(keepalive_thread != NULL) + { + keepalive_thread_run = false; + keepalive_thread->join(); + } + hid_close(dev); + delete guard_manager_ptr; } std::string RazerController::GetName() @@ -181,6 +235,23 @@ std::string RazerController::GetSerialString() return(razer_get_serial()); } +void RazerController::KeepaliveThreadFunction() +{ + /*-----------------------------------------------------------------*\ + | Performing a get device mode request seems to be enough to keep | + | the lighting active on devices with the lighting timeout, so | + | periodically send a device mode request every 2.5s. | + \*-----------------------------------------------------------------*/ + while(keepalive_thread_run.load()) + { + if((std::chrono::steady_clock::now() - last_update_time) > 2500ms) + { + razer_get_device_mode(); + } + std::this_thread::sleep_for(1s); + } +} + void RazerController::SetAddressableZoneSizes(unsigned char zone_1_size, unsigned char zone_2_size, unsigned char zone_3_size, unsigned char zone_4_size, unsigned char zone_5_size, unsigned char zone_6_size) { razer_report report = razer_create_addressable_size_report(zone_1_size, zone_2_size, zone_3_size, zone_4_size, zone_5_size, zone_6_size); @@ -320,8 +391,11 @@ bool RazerController::SupportsBreathing() | Mice | \*-----------------------------------------------------*/ case RAZER_BASILISK_V3_PID: + case RAZER_BASILISK_V3_35K_PID: case RAZER_BASILISK_V3_PRO_WIRED_PID: case RAZER_BASILISK_V3_PRO_WIRELESS_PID: + case RAZER_BASILISK_V3_PRO_35K_WIRED_PID: + case RAZER_BASILISK_V3_PRO_35K_WIRELESS_PID: case RAZER_BASILISK_V3_PRO_BLUETOOTH_PID: supports_breathing = false; @@ -356,6 +430,10 @@ bool RazerController::SupportsWave() case RAZER_BLACKWIDOW_V3_TKL_PID: case RAZER_BLACKWIDOW_V3_MINI_WIRED_PID: case RAZER_BLACKWIDOW_V3_MINI_WIRELESS_PID: + case RAZER_BLACKWIDOW_V4_PID: + case RAZER_BLACKWIDOW_V4_PRO_PID: + case RAZER_BLACKWIDOW_V4_PRO_75_WIRED_PID: + case RAZER_BLACKWIDOW_V4_X_PID: case RAZER_BLACKWIDOW_X_CHROMA_PID: case RAZER_BLACKWIDOW_X_CHROMA_TE_PID: case RAZER_BLADE_2016_PID: @@ -375,6 +453,7 @@ bool RazerController::SupportsWave() case RAZER_BLADE_LATE_2021_ADVANCED_PID: case RAZER_BLADE_14_2021_PID: case RAZER_BLADE_14_2022_PID: + case RAZER_BLADE_14_2023_PID: case RAZER_BLADE_15_2022_PID: case RAZER_BLADE_PRO_2016_PID: case RAZER_BLADE_PRO_2017_PID: @@ -392,20 +471,26 @@ bool RazerController::SupportsWave() case RAZER_CYNOSA_V2_PID: case RAZER_DEATHSTALKER_CHROMA_PID: case RAZER_DEATHSTALKER_V2_PID: + case RAZER_DEATHSTALKER_V2_PRO_TKL_WIRED_PID: + case RAZER_DEATHSTALKER_V2_PRO_TKL_WIRELESS_PID: case RAZER_DEATHSTALKER_V2_PRO_WIRED_PID: case RAZER_DEATHSTALKER_V2_PRO_WIRELESS_PID: case RAZER_ORNATA_CHROMA_PID: case RAZER_ORNATA_CHROMA_V2_PID: case RAZER_ORNATA_V3_PID: case RAZER_ORNATA_V3_REV2_PID: + case RAZER_ORNATA_V3_TKL_PID: case RAZER_ORNATA_V3_X_PID: case RAZER_HUNTSMAN_PID: case RAZER_HUNTSMAN_ELITE_PID: case RAZER_HUNTSMAN_MINI_PID: + case RAZER_HUNTSMAN_MINI_ANALOG_PID: case RAZER_HUNTSMAN_TE_PID: case RAZER_HUNTSMAN_V2_ANALOG_PID: case RAZER_HUNTSMAN_V2_TKL_PID: case RAZER_HUNTSMAN_V2_PID: + case RAZER_HUNTSMAN_V3_PRO_PID: + case RAZER_HUNTSMAN_V3_PRO_TKL_WHITE_PID: case RAZER_ORBWEAVER_CHROMA_PID: case RAZER_TARTARUS_PRO_PID: case RAZER_TARTARUS_V2_PID: @@ -416,9 +501,14 @@ bool RazerController::SupportsWave() case RAZER_BASILISK_ULTIMATE_WIRED_PID: case RAZER_BASILISK_ULTIMATE_WIRELESS_PID: case RAZER_BASILISK_V3_PID: + case RAZER_BASILISK_V3_35K_PID: case RAZER_BASILISK_V3_PRO_WIRED_PID: case RAZER_BASILISK_V3_PRO_WIRELESS_PID: + case RAZER_BASILISK_V3_PRO_35K_WIRED_PID: + case RAZER_BASILISK_V3_PRO_35K_WIRELESS_PID: case RAZER_BASILISK_V3_PRO_BLUETOOTH_PID: + case RAZER_COBRA_PRO_WIRED_PID: + case RAZER_COBRA_PRO_WIRELESS_PID: case RAZER_DIAMONDBACK_CHROMA_PID: case RAZER_MAMBA_2015_WIRED_PID: case RAZER_MAMBA_2015_WIRELESS_PID: @@ -445,8 +535,11 @@ bool RazerController::SupportsWave() case RAZER_CORE_X_PID: case RAZER_FIREFLY_PID: case RAZER_FIREFLY_V2_PID: + case RAZER_FIREFLY_V2_PRO_PID: + case RAZER_FIREFLY_HYPERFLUX_PID: case RAZER_LAPTOP_STAND_CHROMA_PID: case RAZER_LAPTOP_STAND_CHROMA_V2_PID: + case RAZER_LEVIATHAN_V2_PID: case RAZER_LEVIATHAN_V2X_PID: case RAZER_MOUSE_BUNGEE_V3_CHROMA_PID: case RAZER_MOUSE_DOCK_PRO_PID: @@ -663,7 +756,7 @@ razer_report RazerController::razer_create_custom_frame_extended_matrix_report(u const size_t row_length = (size_t)(((stop_col + 1) - start_col) * 3); const size_t packet_length = row_length + 5; - razer_report report = razer_create_report(0x0F, 0x03, packet_length); + razer_report report = razer_create_report(0x0F, 0x03, (unsigned char)packet_length); report.arguments[2] = row_index; report.arguments[3] = start_col; @@ -682,7 +775,7 @@ razer_report RazerController::razer_create_custom_frame_standard_matrix_report(u const size_t row_length = (size_t)(((stop_col + 1) - start_col) * 3); const size_t packet_length = row_length + 4; - razer_report report = razer_create_report(0x03, 0x0B, packet_length); + razer_report report = razer_create_report(0x03, 0x0B, (unsigned char)packet_length); report.arguments[0] = 0xFF; report.arguments[1] = row_index; @@ -945,15 +1038,29 @@ razer_report RazerController::razer_create_set_led_effect_report(unsigned char v | Get functions (request information from device) | \*---------------------------------------------------------------------------------*/ +unsigned char RazerController::razer_get_device_mode() +{ + std::string firmware_string = ""; + struct razer_report report = razer_create_report(0x00, RAZER_COMMAND_ID_GET_DEVICE_MODE, 0x02); + struct razer_report response_report = razer_create_response(); + + std::this_thread::sleep_for(2ms); + razer_usb_send(&report); + std::this_thread::sleep_for(5ms); + razer_usb_receive(&response_report); + + return(response_report.arguments[0]); +} + std::string RazerController::razer_get_firmware() { std::string firmware_string = ""; struct razer_report report = razer_create_report(0x00, RAZER_COMMAND_ID_GET_FIRMWARE_VERSION, 0x02); struct razer_report response_report = razer_create_response(); - std::this_thread::sleep_for(1ms); + std::this_thread::sleep_for(2ms); razer_usb_send(&report); - std::this_thread::sleep_for(1ms); + std::this_thread::sleep_for(5ms); razer_usb_receive(&response_report); firmware_string = "v" + std::to_string(response_report.arguments[0]) + "." + std::to_string(response_report.arguments[1]); @@ -967,12 +1074,12 @@ std::string RazerController::razer_get_serial() struct razer_report report = razer_create_report(0x00, RAZER_COMMAND_ID_GET_SERIAL_STRING, 0x16); struct razer_report response_report = razer_create_response(); - std::this_thread::sleep_for(1ms); + std::this_thread::sleep_for(2ms); razer_usb_send(&report); - std::this_thread::sleep_for(1ms); + std::this_thread::sleep_for(5ms); razer_usb_receive(&response_report); - strncpy(&serial_string[0], (const char*)&response_report.arguments[0], 22); + memcpy(&serial_string[0], &response_report.arguments[0], 22); serial_string[22] = '\0'; for(size_t i = 0; i < 22; i++) @@ -1045,7 +1152,7 @@ unsigned char RazerController::GetKeyboardLayoutType() } } -std::string RazerController::GetKeyboardLayoutName() +std::string RazerController::GetKeyboardLayoutString() { unsigned char layout; unsigned char variant; @@ -1076,7 +1183,7 @@ std::string RazerController::GetKeyboardLayoutName() case RAZER_KEYBOARD_LAYOUT_ARABIC: return "Arabic (ANSI)"; // Unconfirmed default: std::string tmp = "Unknown: "; - tmp += layout; + tmp.append(std::to_string(layout)); return tmp; } } @@ -1208,6 +1315,12 @@ void RazerController::razer_set_custom_frame(unsigned char row_index, unsigned c razer_usb_send(&report); break; + case RAZER_MAMBA_2012_WIRED_PID: + case RAZER_MAMBA_2012_WIRELESS_PID: + report = razer_create_set_led_rgb_report(RAZER_STORAGE_NO_SAVE, RAZER_LED_ID_SCROLL_WHEEL, rgb_data); + razer_usb_send(&report); + break; + /*-------------------------------------------------*\ | The Orbweaver Chroma has an unusual matrix layout | | and the following code allows it to present as a | @@ -1321,6 +1434,14 @@ void RazerController::razer_set_mode_breathing_one_color(unsigned char red, unsi razer_usb_send(&report); break; + case RAZER_MAMBA_2012_WIRED_PID: + case RAZER_MAMBA_2012_WIRELESS_PID: + report = razer_create_set_led_rgb_report(RAZER_STORAGE_NO_SAVE, RAZER_LED_ID_SCROLL_WHEEL, rgb_data); + razer_usb_send(&report); + report = razer_create_set_led_effect_report(RAZER_STORAGE_NO_SAVE, RAZER_LED_ID_SCROLL_WHEEL, 2); + razer_usb_send(&report); + break; + /*-------------------------------------------------*\ | These devices use standard matrix reports | \*-------------------------------------------------*/ @@ -1448,6 +1569,12 @@ void RazerController::razer_set_mode_custom() razer_usb_send(&report); break; + case RAZER_MAMBA_2012_WIRED_PID: + case RAZER_MAMBA_2012_WIRELESS_PID: + report = razer_create_set_led_effect_report(RAZER_STORAGE_NO_SAVE, RAZER_LED_ID_SCROLL_WHEEL, 0); + razer_usb_send(&report); + break; + /*-------------------------------------------------*\ | These devices use standard matrix reports | \*-------------------------------------------------*/ @@ -1753,10 +1880,12 @@ int RazerController::razer_usb_send(razer_report* report) { report->crc = razer_calculate_crc(report); + DeviceGuardLock _ = guard_manager_ptr->AwaitExclusiveAccess(); return hid_send_feature_report(dev, (unsigned char*)report, sizeof(*report)); } int RazerController::razer_usb_send_argb(razer_argb_report* report) { + DeviceGuardLock _ = guard_manager_ptr->AwaitExclusiveAccess(); return hid_send_feature_report(dev_argb, (unsigned char*)report, sizeof(*report)); } diff --git a/Controllers/RazerController/RazerController.h b/Controllers/RazerController/RazerController/RazerController.h similarity index 92% rename from Controllers/RazerController/RazerController.h rename to Controllers/RazerController/RazerController/RazerController.h index 4b0b3bd2..ce6a528f 100644 --- a/Controllers/RazerController/RazerController.h +++ b/Controllers/RazerController/RazerController/RazerController.h @@ -1,18 +1,24 @@ -/*-----------------------------------------*\ -| RazerController.h | -| | -| Definitions and types for Razer devices | -| | -| Adam Honse (CalcProgrammer1) 1/22/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| RazerController.h | +| | +| Driver for Razer devices | +| | +| Adam Honse (CalcProgrammer1) 22 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include +#include +#include +#include "RGBController.h" +#include "DeviceGuardManager.h" + /*---------------------------------------------------------*\ | Struct packing macro for GCC and MSVC | \*---------------------------------------------------------*/ @@ -226,7 +232,7 @@ public: unsigned char GetMaxBrightness(); unsigned char GetKeyboardLayoutType(); - std::string GetKeyboardLayoutName(); + std::string GetKeyboardLayoutString(); std::string GetVariantName(); void SetBrightness(unsigned char brightness); @@ -263,7 +269,6 @@ private: std::string firmware_version; std::string location; std::string name; - device_type type; /*---------------------------------------------------------*\ | Index of device in Razer device list | @@ -281,6 +286,11 @@ private: \*---------------------------------------------------------*/ unsigned char matrix_type; + /*---------------------------------------------------------*\ + | Mutex lock to sync with other softwares | + \*---------------------------------------------------------*/ + DeviceGuardManager* guard_manager_ptr; + /*---------------------------------------------------------*\ | Private functions based on OpenRazer | \*---------------------------------------------------------*/ @@ -316,6 +326,7 @@ private: razer_report razer_create_set_led_effect_report(unsigned char variable_storage, unsigned char led_id, unsigned char effect); razer_report razer_create_set_led_rgb_report(unsigned char variable_storage, unsigned char led_id, unsigned char* rgb_data); + unsigned char razer_get_device_mode(); std::string razer_get_firmware(); std::string razer_get_serial(); void razer_get_keyboard_info(unsigned char* layout, unsigned char* variant); @@ -338,4 +349,9 @@ private: int razer_usb_send(razer_report* report); int razer_usb_send_argb(razer_argb_report* report); + std::chrono::time_point last_update_time; + std::atomic keepalive_thread_run; + std::thread * keepalive_thread; + + void KeepaliveThreadFunction(); }; diff --git a/Controllers/RazerController/RazerControllerDetect.cpp b/Controllers/RazerController/RazerControllerDetect.cpp index 4b48097f..b9367022 100644 --- a/Controllers/RazerController/RazerControllerDetect.cpp +++ b/Controllers/RazerController/RazerControllerDetect.cpp @@ -1,19 +1,26 @@ +/*---------------------------------------------------------*\ +| RazerControllerDetect.cpp | +| | +| Detector for Razer devices | +| | +| Adam Honse (CalcProgrammer1) 22 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include #include "Detector.h" -#include "LogManager.h" #include "RazerController.h" #include "RazerKrakenController.h" +#include "RazerHanboController.h" #include "RazerDevices.h" #include "ResourceManager.h" -#include "RGBController.h" #include "RGBController_Razer.h" #include "RGBController_RazerAddressable.h" #include "RGBController_RazerKraken.h" -#include - -#include - -static bool openrazer_checked = false; -static bool openrazer_enabled = false; +#include "RGBController_RazerHanbo.h" /******************************************************************************************\ * * @@ -27,52 +34,6 @@ void DetectRazerControllers(hid_device_info* info, const std::string& name) { hid_device* dev = hid_open_path(info->path); - /*-------------------------------------------------*\ - | If the OpenRazer/OpenRazer-Win32 controller is | - | enabled, don't use this controller. | - \*-------------------------------------------------*/ - if(!openrazer_checked) - { - /*-------------------------------------------------*\ - | Open device disable list and read in disabled | - | device strings | - \*-------------------------------------------------*/ - json detector_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Detectors"); - - /*-------------------------------------------------*\ - | Check for OpenRazer and OpenRazer-Win32 enable | - \*-------------------------------------------------*/ - if(detector_settings.contains("detectors")) - { - if(detector_settings["detectors"].contains("OpenRazer")) - { - if(detector_settings["detectors"]["OpenRazer"] == true) - { - openrazer_enabled = true; - } - } - if(detector_settings["detectors"].contains("OpenRazer-Win32")) - { - if(detector_settings["detectors"]["OpenRazer-Win32"] == true) - { - openrazer_enabled = true; - } - } - } - - /*-------------------------------------------------*\ - | Set OpenRazer checked flag to prevent having to do| - | the settings lookup multiple times | - \*-------------------------------------------------*/ - openrazer_checked = true; - } - - if(openrazer_enabled) - { - LOG_INFO("[RazerController]: OpenRazer controller currently enabled. Ignoring %s", name.c_str()); - return; - } - if(dev) { RazerController* controller = new RazerController(dev, dev, info->path, info->product_id, name); @@ -183,52 +144,6 @@ void DetectRazerKrakenControllers(hid_device_info* info, const std::string& name { hid_device* dev = hid_open_path(info->path); - /*-------------------------------------------------*\ - | If the OpenRazer/OpenRazer-Win32 controller is | - | enabled, don't use this controller. | - \*-------------------------------------------------*/ - if(!openrazer_checked) - { - /*-------------------------------------------------*\ - | Open device disable list and read in disabled | - | device strings | - \*-------------------------------------------------*/ - json detector_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Detectors"); - - /*-------------------------------------------------*\ - | Check for OpenRazer and OpenRazer-Win32 enable | - \*-------------------------------------------------*/ - if(detector_settings.contains("detectors")) - { - if(detector_settings["detectors"].contains("OpenRazer")) - { - if(detector_settings["detectors"]["OpenRazer"] == true) - { - openrazer_enabled = true; - } - } - if(detector_settings["detectors"].contains("OpenRazer-Win32")) - { - if(detector_settings["detectors"]["OpenRazer-Win32"] == true) - { - openrazer_enabled = true; - } - } - } - - /*-------------------------------------------------*\ - | Set OpenRazer checked flag to prevent having to do| - | the settings lookup multiple times | - \*-------------------------------------------------*/ - openrazer_checked = true; - } - - if(openrazer_enabled) - { - LOG_INFO("[RazerController]: OpenRazer controller currently enabled. Ignoring %s", name.c_str()); - return; - } - if(dev) { RazerKrakenController* controller = new RazerKrakenController(dev, info->path, info->product_id, name); @@ -238,6 +153,27 @@ void DetectRazerKrakenControllers(hid_device_info* info, const std::string& name } } /* DetectRazerKrakenControllers() */ +/******************************************************************************************\ +* * +* DetectRazerHanboController * +* * +* Tests the USB address to see if a Razer Hanbo controller exists there. * +* * +\******************************************************************************************/ + +void DetectRazerHanboControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + RazerHanboController* controller = new RazerHanboController(dev, info->path, info->product_id, name); + + RGBController_RazerHanbo* rgb_controller = new RGBController_RazerHanbo(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} /* DetectRazerHanboControllers() */ + /*-----------------------------------------------------------------------------------------------------*\ | Keyboards | \*-----------------------------------------------------------------------------------------------------*/ @@ -254,6 +190,10 @@ REGISTER_HID_DETECTOR_IPU("Razer Blackwidow V3 Pro (Wireless)", Det REGISTER_HID_DETECTOR_IPU("Razer Blackwidow V3 TKL", DetectRazerControllers, RAZER_VID, RAZER_BLACKWIDOW_V3_TKL_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Blackwidow V3 Mini (Wired)", DetectRazerControllers, RAZER_VID, RAZER_BLACKWIDOW_V3_MINI_WIRED_PID, 0x03, 0x0C, 0x01); REGISTER_HID_DETECTOR_IPU("Razer Blackwidow V3 Mini (Wireless)", DetectRazerControllers, RAZER_VID, RAZER_BLACKWIDOW_V3_MINI_WIRELESS_PID, 0x03, 0x0C, 0x01); +REGISTER_HID_DETECTOR_IPU("Razer Blackwidow V4", DetectRazerControllers, RAZER_VID, RAZER_BLACKWIDOW_V4_PID, 0x03, 0x01, 0x00); +REGISTER_HID_DETECTOR_IPU("Razer Blackwidow V4 Pro", DetectRazerControllers, RAZER_VID, RAZER_BLACKWIDOW_V4_PRO_PID, 0x03, 0x01, 0x00); +REGISTER_HID_DETECTOR_IPU("Razer Blackwidow V4 Pro 75% (Wired)", DetectRazerControllers, RAZER_VID, RAZER_BLACKWIDOW_V4_PRO_75_WIRED_PID, 0x03, 0x0C, 0x01); +REGISTER_HID_DETECTOR_IPU("Razer Blackwidow V4 X", DetectRazerControllers, RAZER_VID, RAZER_BLACKWIDOW_V4_X_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Blackwidow X Chroma", DetectRazerControllers, RAZER_VID, RAZER_BLACKWIDOW_X_CHROMA_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Blackwidow X Chroma Tournament Edition", DetectRazerControllers, RAZER_VID, RAZER_BLACKWIDOW_X_CHROMA_TE_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Cynosa Chroma", DetectRazerControllers, RAZER_VID, RAZER_CYNOSA_CHROMA_PID, 0x02, 0x01, 0x02); @@ -261,20 +201,27 @@ REGISTER_HID_DETECTOR_IPU("Razer Cynosa Chroma V2", Det REGISTER_HID_DETECTOR_IPU("Razer Cynosa Lite", DetectRazerControllers, RAZER_VID, RAZER_CYNOSA_LITE_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Deathstalker Chroma", DetectRazerControllers, RAZER_VID, RAZER_DEATHSTALKER_CHROMA_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Deathstalker V2", DetectRazerControllers, RAZER_VID, RAZER_DEATHSTALKER_V2_PID, 0x03, 0x0C, 0x01); +REGISTER_HID_DETECTOR_IPU("Razer Deathstalker V2 Pro TKL (Wired)", DetectRazerControllers, RAZER_VID, RAZER_DEATHSTALKER_V2_PRO_TKL_WIRED_PID, 0x03, 0x0C, 0x01); +REGISTER_HID_DETECTOR_IPU("Razer Deathstalker V2 Pro TKL (Wireless)", DetectRazerControllers, RAZER_VID, RAZER_DEATHSTALKER_V2_PRO_TKL_WIRELESS_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Deathstalker V2 Pro (Wired)", DetectRazerControllers, RAZER_VID, RAZER_DEATHSTALKER_V2_PRO_WIRED_PID, 0x03, 0x0C, 0x01); REGISTER_HID_DETECTOR_IPU("Razer Deathstalker V2 Pro (Wireless)", DetectRazerControllers, RAZER_VID, RAZER_DEATHSTALKER_V2_PRO_WIRELESS_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Huntsman", DetectRazerControllers, RAZER_VID, RAZER_HUNTSMAN_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Huntsman Elite", DetectRazerControllers, RAZER_VID, RAZER_HUNTSMAN_ELITE_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Huntsman Mini", DetectRazerControllers, RAZER_VID, RAZER_HUNTSMAN_MINI_PID, 0x02, 0x01, 0x02); +REGISTER_HID_DETECTOR_IPU("Razer Huntsman Mini Analog", DetectRazerControllers, RAZER_VID, RAZER_HUNTSMAN_MINI_ANALOG_PID, 0x03, 0x0C, 0x01); REGISTER_HID_DETECTOR_IPU("Razer Huntsman Tournament Edition", DetectRazerControllers, RAZER_VID, RAZER_HUNTSMAN_TE_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Huntsman V2 Analog", DetectRazerControllers, RAZER_VID, RAZER_HUNTSMAN_V2_ANALOG_PID, 0x03, 0x0C, 0x01); REGISTER_HID_DETECTOR_IPU("Razer Huntsman V2 TKL", DetectRazerControllers, RAZER_VID, RAZER_HUNTSMAN_V2_TKL_PID, 0x03, 0x0C, 0x01); REGISTER_HID_DETECTOR_IPU("Razer Huntsman V2", DetectRazerControllers, RAZER_VID, RAZER_HUNTSMAN_V2_PID, 0x03, 0x0C, 0x01); +REGISTER_HID_DETECTOR_IPU("Razer Huntsman V3 Pro", DetectRazerControllers, RAZER_VID, RAZER_HUNTSMAN_V3_PRO_PID, 0x03, 0x0C, 0x01); +REGISTER_HID_DETECTOR_IPU("Razer Huntsman V3 Pro TKL White", DetectRazerControllers, RAZER_VID, RAZER_HUNTSMAN_V3_PRO_TKL_WHITE_PID, 0x03, 0x0C, 0x01); REGISTER_HID_DETECTOR_IPU("Razer Ornata Chroma", DetectRazerControllers, RAZER_VID, RAZER_ORNATA_CHROMA_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Ornata Chroma V2", DetectRazerControllers, RAZER_VID, RAZER_ORNATA_CHROMA_V2_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Ornata V3", DetectRazerControllers, RAZER_VID, RAZER_ORNATA_V3_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Ornata V3 Rev2", DetectRazerControllers, RAZER_VID, RAZER_ORNATA_V3_REV2_PID, 0x02, 0x01, 0x02); +REGISTER_HID_DETECTOR_IPU("Razer Ornata V3 TKL", DetectRazerControllers, RAZER_VID, RAZER_ORNATA_V3_TKL_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Ornata V3 X", DetectRazerControllers, RAZER_VID, RAZER_ORNATA_V3_X_PID, 0x02, 0x01, 0x02); +REGISTER_HID_DETECTOR_IPU("Razer Ornata V3 X Rev2", DetectRazerControllers, RAZER_VID, RAZER_ORNATA_V3_X_REV2_PID, 0x02, 0x01, 0x02); /*-----------------------------------------------------------------------------------------------------*\ | Laptops | \*-----------------------------------------------------------------------------------------------------*/ @@ -282,6 +229,7 @@ REGISTER_HID_DETECTOR_IPU("Razer Blade (2016)", Det REGISTER_HID_DETECTOR_IPU("Razer Blade (Late 2016)", DetectRazerControllers, RAZER_VID, RAZER_BLADE_LATE_2016_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Blade 14 (2021)", DetectRazerControllers, RAZER_VID, RAZER_BLADE_14_2021_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Blade 14 (2022)", DetectRazerControllers, RAZER_VID, RAZER_BLADE_14_2022_PID, 0x02, 0x01, 0x02); +REGISTER_HID_DETECTOR_IPU("Razer Blade 14 (2023)", DetectRazerControllers, RAZER_VID, RAZER_BLADE_14_2023_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Blade 15 (2022)", DetectRazerControllers, RAZER_VID, RAZER_BLADE_15_2022_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Blade 15 (2018 Advanced)", DetectRazerControllers, RAZER_VID, RAZER_BLADE_2018_ADVANCED_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Blade 15 (2018 Base)", DetectRazerControllers, RAZER_VID, RAZER_BLADE_2018_BASE_PID, 0x02, 0x01, 0x02); @@ -325,9 +273,16 @@ REGISTER_HID_DETECTOR_IPU("Razer Basilisk Ultimate (Wired)", Det REGISTER_HID_DETECTOR_IPU("Razer Basilisk Ultimate (Wireless)", DetectRazerControllers, RAZER_VID, RAZER_BASILISK_ULTIMATE_WIRELESS_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Basilisk V2", DetectRazerControllers, RAZER_VID, RAZER_BASILISK_V2_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Basilisk V3", DetectRazerControllers, RAZER_VID, RAZER_BASILISK_V3_PID, 0x03, 0x0C, 0x01); +REGISTER_HID_DETECTOR_IPU("Razer Basilisk V3 35K", DetectRazerControllers, RAZER_VID, RAZER_BASILISK_V3_35K_PID, 0x03, 0x0C, 0x01); REGISTER_HID_DETECTOR_IPU("Razer Basilisk V3 Pro (Wired)", DetectRazerControllers, RAZER_VID, RAZER_BASILISK_V3_PRO_WIRED_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Basilisk V3 Pro (Wireless)", DetectRazerControllers, RAZER_VID, RAZER_BASILISK_V3_PRO_WIRELESS_PID, 0x00, 0x01, 0x02); +REGISTER_HID_DETECTOR_IPU("Razer Basilisk V3 Pro 35K (Wired)", DetectRazerControllers, RAZER_VID, RAZER_BASILISK_V3_PRO_35K_WIRED_PID, 0x00, 0x01, 0x02); +REGISTER_HID_DETECTOR_IPU("Razer Basilisk V3 Pro 35K (Wireless)", DetectRazerControllers, RAZER_VID, RAZER_BASILISK_V3_PRO_35K_WIRELESS_PID, 0x00, 0x01, 0x02); // REGISTER_HID_DETECTOR_PU ("Razer Basilisk V3 Pro (Bluetooth)", DetectRazerControllers, RAZER_VID, RAZER_BASILISK_V3_PRO_BLUETOOTH_PID, 0x01, 0x02); +REGISTER_HID_DETECTOR_IPU("Razer Basilisk V3 X HyperSpeed", DetectRazerControllers, RAZER_VID, RAZER_BASILISK_V3_X_HYPERSPEED_PID, 0x00, 0x01, 0x02); +REGISTER_HID_DETECTOR_IPU("Razer Cobra", DetectRazerControllers, RAZER_VID, RAZER_COBRA_PID, 0x00, 0x01, 0x02); +REGISTER_HID_DETECTOR_IPU("Razer Cobra Pro (Wired)", DetectRazerControllers, RAZER_VID, RAZER_COBRA_PRO_WIRED_PID, 0x00, 0x01, 0x02); +REGISTER_HID_DETECTOR_IPU("Razer Cobra Pro (Wireless)", DetectRazerControllers, RAZER_VID, RAZER_COBRA_PRO_WIRELESS_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Deathadder Chroma", DetectRazerControllers, RAZER_VID, RAZER_DEATHADDER_CHROMA_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Deathadder Elite", DetectRazerControllers, RAZER_VID, RAZER_DEATHADDER_ELITE_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Deathadder Essential", DetectRazerControllers, RAZER_VID, RAZER_DEATHADDER_ESSENTIAL_PID, 0x00, 0x01, 0x02); @@ -350,6 +305,7 @@ REGISTER_HID_DETECTOR_IPU("Razer Mamba 2015 (Wireless)", Det REGISTER_HID_DETECTOR_IPU("Razer Mamba 2018 (Wired)", DetectRazerControllers, RAZER_VID, RAZER_MAMBA_2018_WIRED_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Mamba 2018 (Wireless)", DetectRazerControllers, RAZER_VID, RAZER_MAMBA_2018_WIRELESS_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Mamba Elite", DetectRazerControllers, RAZER_VID, RAZER_MAMBA_ELITE_PID, 0x00, 0x01, 0x02); +REGISTER_HID_DETECTOR_IPU("Razer Mamba Hyperflux (Wired)", DetectRazerControllers, RAZER_VID, RAZER_MAMBA_HYPERFLUX_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Mamba Tournament Edition", DetectRazerControllers, RAZER_VID, RAZER_MAMBA_TE_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Naga Chroma", DetectRazerControllers, RAZER_VID, RAZER_NAGA_CHROMA_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Naga Classic", DetectRazerControllers, RAZER_VID, RAZER_NAGA_CLASSIC_PID, 0x00, 0x01, 0x02); @@ -359,6 +315,8 @@ REGISTER_HID_DETECTOR_IPU("Razer Naga Hex V2", Det REGISTER_HID_DETECTOR_IPU("Razer Naga Trinity", DetectRazerControllers, RAZER_VID, RAZER_NAGA_TRINITY_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Naga Pro (Wired)", DetectRazerControllers, RAZER_VID, RAZER_NAGA_PRO_WIRED_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Naga Pro (Wireless)", DetectRazerControllers, RAZER_VID, RAZER_NAGA_PRO_WIRELESS_PID, 0x00, 0x01, 0x02); +REGISTER_HID_DETECTOR_IPU("Razer Naga Pro V2 (Wired)", DetectRazerControllers, RAZER_VID, RAZER_NAGA_PRO_V2_WIRED_PID, 0x00, 0x01, 0x02); +REGISTER_HID_DETECTOR_IPU("Razer Naga Pro V2 (Wireless)", DetectRazerControllers, RAZER_VID, RAZER_NAGA_PRO_V2_WIRELESS_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Viper", DetectRazerControllers, RAZER_VID, RAZER_VIPER_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Viper 8kHz", DetectRazerControllers, RAZER_VID, RAZER_VIPER_8KHZ_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Viper Mini", DetectRazerControllers, RAZER_VID, RAZER_VIPER_MINI_PID, 0x00, 0x01, 0x02); @@ -382,6 +340,7 @@ REGISTER_HID_DETECTOR_IPU("Razer Kraken 7.1 Chroma", Det REGISTER_HID_DETECTOR_IPU("Razer Kraken 7.1 V2", DetectRazerKrakenControllers, RAZER_VID, RAZER_KRAKEN_V2_PID, 0x03, 0x0C, 0x01); REGISTER_HID_DETECTOR_IPU("Razer Kraken Kitty Edition", DetectRazerControllers, RAZER_VID, RAZER_KRAKEN_KITTY_EDITION_PID, 0x01, 0x01, 0x03); REGISTER_HID_DETECTOR_IPU("Razer Kraken Kitty Black Edition", DetectRazerControllers, RAZER_VID, RAZER_KRAKEN_KITTY_BLACK_EDITION_PID, 0x01, 0x01, 0x03); +REGISTER_HID_DETECTOR_IPU("Razer Kraken Kitty Black Edition V2", DetectRazerKrakenControllers, RAZER_VID, RAZER_KRAKEN_KITTY_BLACK_EDITION_V2_PID, 0x03, 0x0C, 0x01); REGISTER_HID_DETECTOR_IPU("Razer Kraken Ultimate", DetectRazerKrakenControllers, RAZER_VID, RAZER_KRAKEN_ULTIMATE_PID, 0x03, 0x0C, 0x01); REGISTER_HID_DETECTOR_I( "Razer Tiamat 7.1 V2", DetectRazerControllers, RAZER_VID, RAZER_TIAMAT_71_V2_PID, 0x00 ); @@ -390,8 +349,10 @@ REGISTER_HID_DETECTOR_I( "Razer Tiamat 7.1 V2", Det \*-----------------------------------------------------------------------------------------------------*/ REGISTER_HID_DETECTOR_IPU("Razer Firefly", DetectRazerControllers, RAZER_VID, RAZER_FIREFLY_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Firefly V2", DetectRazerControllers, RAZER_VID, RAZER_FIREFLY_V2_PID, 0x00, 0x01, 0x02); +REGISTER_HID_DETECTOR_IPU("Razer Firefly V2 Pro", DetectRazerControllers, RAZER_VID, RAZER_FIREFLY_V2_PRO_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Firefly Hyperflux", DetectRazerControllers, RAZER_VID, RAZER_FIREFLY_HYPERFLUX_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Goliathus", DetectRazerControllers, RAZER_VID, RAZER_GOLIATHUS_CHROMA_PID, 0x00, 0x01, 0x02); +REGISTER_HID_DETECTOR_IPU("Razer Goliathus Chroma 3XL", DetectRazerControllers, RAZER_VID, RAZER_GOLIATHUS_CHROMA_3XL_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Goliathus Extended", DetectRazerControllers, RAZER_VID, RAZER_GOLIATHUS_CHROMA_EXTENDED_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Strider Chroma", DetectRazerControllers, RAZER_VID, RAZER_STRIDER_CHROMA_PID, 0x00, 0x01, 0x02); @@ -401,7 +362,7 @@ REGISTER_HID_DETECTOR_IPU("Razer Strider Chroma", Det REGISTER_HID_DETECTOR_IPU("Razer Base Station Chroma", DetectRazerControllers, RAZER_VID, RAZER_BASE_STATION_CHROMA_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Base Station V2 Chroma", DetectRazerControllers, RAZER_VID, RAZER_BASE_STATION_V2_CHROMA_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Charging Pad Chroma", DetectRazerControllers, RAZER_VID, RAZER_CHARGING_PAD_CHROMA_PID, 0x00, 0x0C, 0x01); -REGISTER_HID_DETECTOR_I ("Razer Chroma Addressable RGB Controller", DetectRazerARGBControllers, RAZER_VID, RAZER_CHROMA_ADDRESSABLE_RGB_CONTROLLER_PID, 0x00 ); +REGISTER_HID_DETECTOR_I("Razer Chroma Addressable RGB Controller", DetectRazerARGBControllers, RAZER_VID, RAZER_CHROMA_ADDRESSABLE_RGB_CONTROLLER_PID, 0x00 ); REGISTER_HID_DETECTOR_IPU("Razer Chroma HDK", DetectRazerControllers, RAZER_VID, RAZER_CHROMA_HDK_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Chroma Mug Holder", DetectRazerControllers, RAZER_VID, RAZER_CHROMA_MUG_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Chroma PC Case Lighting Kit", DetectRazerControllers, RAZER_VID, RAZER_CHROMA_PC_CASE_LIGHTING_KIT_PID, 0x02, 0x01, 0x02); @@ -409,13 +370,15 @@ REGISTER_HID_DETECTOR_IPU("Razer Core", Det REGISTER_HID_DETECTOR_IPU("Razer Core X", DetectRazerControllers, RAZER_VID, RAZER_CORE_X_PID, 0x02, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Laptop Stand Chroma", DetectRazerControllers, RAZER_VID, RAZER_LAPTOP_STAND_CHROMA_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Laptop Stand Chroma V2", DetectRazerControllers, RAZER_VID, RAZER_LAPTOP_STAND_CHROMA_V2_PID, 0x00, 0x01, 0x02); +REGISTER_HID_DETECTOR_IPU("Razer Leviathan V2", DetectRazerControllers, RAZER_VID, RAZER_LEVIATHAN_V2_PID, 0x02, 0x0C, 0x01); REGISTER_HID_DETECTOR_IPU("Razer Leviathan V2 X", DetectRazerControllers, RAZER_VID, RAZER_LEVIATHAN_V2X_PID, 0x00, 0x0C, 0x01); REGISTER_HID_DETECTOR_IPU("Razer Mouse Bungee V3 Chroma", DetectRazerControllers, RAZER_VID, RAZER_MOUSE_BUNGEE_V3_CHROMA_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Mouse Dock Chroma", DetectRazerControllers, RAZER_VID, RAZER_MOUSE_DOCK_CHROMA_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Razer Mouse Dock Pro", DetectRazerControllers, RAZER_VID, RAZER_MOUSE_DOCK_PRO_PID, 0x00, 0x01, 0x02); REGISTER_HID_DETECTOR_IPU("Lian Li O11 Dynamic - Razer Edition", DetectRazerControllers, RAZER_VID, RAZER_O11_DYNAMIC_PID, 0x02, 0x01, 0x02); -REGISTER_HID_DETECTOR_PU ("Razer Seiren Emote", DetectRazerControllers, RAZER_VID, RAZER_SEIREN_EMOTE_PID, 0x0C, 0x01 ); +REGISTER_HID_DETECTOR_PU("Razer Seiren Emote", DetectRazerControllers, RAZER_VID, RAZER_SEIREN_EMOTE_PID, 0x0C, 0x01 ); REGISTER_HID_DETECTOR_PU("Razer Thunderbolt 4 Dock Chroma", DetectRazerControllers, RAZER_VID, RAZER_THUNDERBOLT_4_DOCK_CHROMA_PID, 0x0C, 0x01 ); +REGISTER_HID_DETECTOR_IPU("Razer Hanbo Chroma", DetectRazerHanboControllers, RAZER_VID, RAZER_HANBO_CHROMA_PID, 0x00, 0xFF00, 0x01); /*-----------------------------------------------------------------------------------------------------*\ | Nommo devices seem to have an issue where interface 1 doesn't show on Linux or MacOS. Due to the way | diff --git a/Controllers/RazerController/RazerDeviceGuard.cpp b/Controllers/RazerController/RazerDeviceGuard.cpp new file mode 100644 index 00000000..8d0b28c8 --- /dev/null +++ b/Controllers/RazerController/RazerDeviceGuard.cpp @@ -0,0 +1,64 @@ +/*---------------------------------------------------------*\ +| RazerDeviceGuard.cpp | +| | +| DeviceGuard for Razer devices | +| | +| Aytac Kayadelen 18 May 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RazerDeviceGuard.h" + +RazerDeviceGuard::RazerDeviceGuard() : DeviceGuard() +{ +#ifdef _WIN32 + mutex_handle = CreateWindowsMutex(); +#endif +} + +void RazerDeviceGuard::Acquire() +{ +#ifdef _WIN32 + while(true) + { + DWORD result = WaitForSingleObject(mutex_handle, INFINITE); + + if(result == WAIT_OBJECT_0) + { + break; + } + + if(result == WAIT_ABANDONED) + { + ReleaseMutex(mutex_handle); + } + } +#endif +} + +void RazerDeviceGuard::Release() +{ +#ifdef _WIN32 + ReleaseMutex(mutex_handle); +#endif +} + +#ifdef _WIN32 + +HANDLE RazerDeviceGuard::CreateWindowsMutex() +{ + SECURITY_DESCRIPTOR sd; + InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); + SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE); + + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = &sd; + sa.bInheritHandle = FALSE; + + return CreateMutex(&sa, FALSE, "Global\\RazerLinkReadWriteGuardMutex"); +} + +#endif diff --git a/Controllers/RazerController/RazerDeviceGuard.h b/Controllers/RazerController/RazerDeviceGuard.h new file mode 100644 index 00000000..967037a0 --- /dev/null +++ b/Controllers/RazerController/RazerDeviceGuard.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RazerDeviceGuard.h | +| | +| DeviceGuard for Razer devices | +| | +| Aytac Kayadelen 18 May 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "DeviceGuard.h" + +#ifdef _WIN32 +#include +#endif + +class RazerDeviceGuard : public DeviceGuard +{ +public: + RazerDeviceGuard(); + + void Acquire() override; + void Release() override; + +private: +#ifdef _WIN32 + HANDLE mutex_handle; + + HANDLE CreateWindowsMutex(); +#endif +}; diff --git a/Controllers/RazerController/RazerDevices.cpp b/Controllers/RazerController/RazerDevices.cpp index 1654ec8d..d99c08bc 100644 --- a/Controllers/RazerController/RazerDevices.cpp +++ b/Controllers/RazerController/RazerDevices.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RazerDevices.cpp | -| | -| Razer device table static data | -| | -| Adam Honse (CalcProgrammer1) 9/4/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RazerDevices.cpp | +| | +| Device list for Razer devices | +| | +| Adam Honse (CalcProgrammer1) 04 Sep 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RazerDevices.h" @@ -20,32 +23,32 @@ keyboard_keymap_overlay_values razer_blackwidow_layout { KEYBOARD_LAYOUT_ANSI_QWERTY, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 4, 1, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Move 'Z' 1 right (Account for ISO key) + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 4, 1, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Move 'Z' 1 right (Account for ISO key) } }, /* Add more regional layout fixes here */ } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right - { 0, 0, 2, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'F1' 1 right (Shifts row) - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) - { 0, 1, 14, 0, KEY_EN_EQUALS, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts most of row) - { 0, 3, 13, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Enter 1 right - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts most of row) - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right - { 0, 5, 10, 0, KEY_EN_RIGHT_ALT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert (Another) RGT_ALT (Shifts remainder of row) - { 0, 5, 11, 0, "Logo", KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap RGT_ALT for 'Logo' + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right + { 0, 0, 2, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'F1' 1 right (Shifts row) + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) + { 0, 1, 14, 0, KEY_EN_EQUALS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts most of row) + { 0, 3, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Enter 1 right + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts most of row) + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right + { 0, 5, 10, 0, KEY_EN_RIGHT_ALT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert (Another) RGT_ALT (Shifts remainder of row) + { 0, 5, 11, 0, "Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap RGT_ALT for 'Logo' } }; @@ -59,18 +62,18 @@ keyboard_keymap_overlay_values razer_blackwidow_2019_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right (Shifts row) - { 0, 5, 6, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Move Space 1 left (Shifts row) - { 0, 5, 11, 0, "Logo", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert 'Logo' key + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right (Shifts row) + { 0, 5, 6, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Move Space 1 left (Shifts row) + { 0, 5, 11, 0, "Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert 'Logo' key } }; @@ -84,17 +87,17 @@ keyboard_keymap_overlay_values razer_blackwidow_chroma_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) - { 0, 1, 0, 0, "Key: M1", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 1 (Shifts row) - { 0, 2, 0, 0, "Key: M2", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 2 (Shifts row) - { 0, 3, 0, 0, "Key: M3", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 3 (Shifts row) - { 0, 4, 0, 0, "Key: M4", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 4 (Shifts row) - { 0, 5, 0, 0, "Key: M5", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 5 (Shifts row) - { 0, 0, 20, 0, "Logo", KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert 'Logo' key + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) + { 0, 1, 0, 0, "Key: M1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 1 (Shifts row) + { 0, 2, 0, 0, "Key: M2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 2 (Shifts row) + { 0, 3, 0, 0, "Key: M3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 3 (Shifts row) + { 0, 4, 0, 0, "Key: M4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 4 (Shifts row) + { 0, 5, 0, 0, "Key: M5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 5 (Shifts row) + { 0, 0, 20, 0, "Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert 'Logo' key } }; @@ -108,17 +111,17 @@ keyboard_keymap_overlay_values razer_blackwidow_chroma_v2_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) - { 0, 1, 0, 0, "Key: M1", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 1 (Shifts row) - { 0, 2, 0, 0, "Key: M2", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 2 (Shifts row) - { 0, 3, 0, 0, "Key: M3", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 3 (Shifts row) - { 0, 4, 0, 0, "Key: M4", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 4 (Shifts row) - { 0, 5, 0, 0, "Key: M5", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 5 (Shifts row) - { 0, 0, 20, 0, "Logo", KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert 'Logo' key + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) + { 0, 1, 0, 0, "Key: M1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 1 (Shifts row) + { 0, 2, 0, 0, "Key: M2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 2 (Shifts row) + { 0, 3, 0, 0, "Key: M3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 3 (Shifts row) + { 0, 4, 0, 0, "Key: M4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 4 (Shifts row) + { 0, 5, 0, 0, "Key: M5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Inset Macro key 5 (Shifts row) + { 0, 0, 20, 0, "Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert 'Logo' key } }; @@ -132,17 +135,17 @@ keyboard_keymap_overlay_values razer_blackwidow_chroma_te_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right (Shifts row) - { 0, 0, 20, 0, "Logo", KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert 'Logo' key + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right (Shifts row) + { 0, 0, 20, 0, "Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert 'Logo' key } }; @@ -156,22 +159,22 @@ keyboard_keymap_overlay_values razer_blackwidow_elite_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) - { 0, 0, 18, 0, KEY_EN_MEDIA_PREVIOUS, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 19, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 20, 0, KEY_EN_MEDIA_NEXT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 21, 0, KEY_EN_MEDIA_MUTE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right (Shifts row) - { 0, 5, 6, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Move Space 1 left (Shifts row) - { 0, 5, 11, 0, "Logo", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert 'Logo' key + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) + { 0, 0, 18, 0, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 19, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 20, 0, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 21, 0, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right (Shifts row) + { 0, 5, 6, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Move Space 1 left (Shifts row) + { 0, 5, 11, 0, "Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert 'Logo' key } }; @@ -185,20 +188,20 @@ keyboard_keymap_overlay_values razer_blackwidow_v3_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right (Shifts row) - { 0, 5, 6, 0, KEY_EN_SPACE, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Spacebar @ 5,6 - { 0, 5, 7, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Spacebar @ 5,7 - { 0, 5, 10, 0, KEY_EN_RIGHT_ALT, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert (another) Right Alt - { 0, 5, 11, 0, "Logo", KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap 'Logo' instead of Right ALt + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right (Shifts row) + { 0, 5, 6, 0, KEY_EN_SPACE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Spacebar @ 5,6 + { 0, 5, 7, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Spacebar @ 5,7 + { 0, 5, 10, 0, KEY_EN_RIGHT_ALT, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert (another) Right Alt + { 0, 5, 11, 0, "Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap 'Logo' instead of Right ALt } }; @@ -212,22 +215,22 @@ keyboard_keymap_overlay_values razer_blackwidow_v3_mini_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_ESCAPE, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap Escape in for Backtick - { 0, 0, 13, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backspace 1 right (Shifts row) - { 0, 0, 15, 0, KEY_EN_DELETE, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Delete Key - { 0, 1, 15, 0, KEY_EN_PAGE_UP, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Page Up Key - { 0, 2, 15, 0, KEY_EN_PAGE_DOWN, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Page Down Key - { 0, 3, 14, 0, KEY_EN_INSERT, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Insert Key - { 0, 3, 15, 0, KEY_EN_UP_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Up Arrow Key - { 0, 4, 7, 0, "Logo", KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert 'Logo' key - { 0, 4, 12, 0, KEY_EN_RIGHT_CONTROL, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap Right Control in for Right Menu - { 0, 4, 13, 0, KEY_EN_LEFT_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Left Arrow - { 0, 4, 14, 0, KEY_EN_DOWN_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Down Arrow - { 0, 4, 15, 0, KEY_EN_RIGHT_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Right Arrow + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_ESCAPE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap Escape in for Backtick + { 0, 0, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backspace 1 right (Shifts row) + { 0, 0, 15, 0, KEY_EN_DELETE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Delete Key + { 0, 1, 15, 0, KEY_EN_PAGE_UP, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Page Up Key + { 0, 2, 15, 0, KEY_EN_PAGE_DOWN, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Page Down Key + { 0, 3, 14, 0, KEY_EN_INSERT, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Insert Key + { 0, 3, 15, 0, KEY_EN_UP_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Up Arrow Key + { 0, 4, 7, 0, "Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert 'Logo' key + { 0, 4, 12, 0, KEY_EN_RIGHT_CONTROL, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap Right Control in for Right Menu + { 0, 4, 13, 0, KEY_EN_LEFT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Left Arrow + { 0, 4, 14, 0, KEY_EN_DOWN_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Down Arrow + { 0, 4, 15, 0, KEY_EN_RIGHT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Right Arrow } }; @@ -241,15 +244,15 @@ keyboard_keymap_overlay_values razer_blackwidow_v3_pro_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 18, 0, KEY_EN_MEDIA_PREVIOUS, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 19, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 20, 0, KEY_EN_MEDIA_NEXT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 21, 0, KEY_EN_MEDIA_MUTE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 14, 0, "Logo", KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert 'Logo' + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 18, 0, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 19, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 20, 0, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 21, 0, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 14, 0, "Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert 'Logo' } }; @@ -263,16 +266,145 @@ keyboard_keymap_overlay_values razer_blackwidow_v3_tkl_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right (Shifts row) + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right (Shifts row) + } +}; + +keyboard_keymap_overlay_values razer_blackwidow_v4_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_FULL, + { + { /* ANSI Value set not used */ }, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Esc key 1 right (Shifts row) + { 0, 0, 1, 0, "Key: M6", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M6 macro key (Shifts row) + { 0, 0, 19, 0, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 20, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 21, 0, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 22, 0, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) + { 0, 1, 1, 0, "Key: M5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M5 macro key (Shifts row) + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) + { 0, 2, 1, 0, "Key: M4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M4 macro key (Shifts row) + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) + { 0, 3, 1, 0, "Key: M3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M3 macro key (Shifts row) + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) + { 0, 4, 1, 0, "Key: M2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M2 macro key (Shifts row) + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right (Shifts row) + { 0, 5, 1, 0, "Key: M1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M1 macro key (Shifts row) + } +}; + +keyboard_keymap_overlay_values razer_blackwidow_v4_pro_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_FULL, + { + { /* ANSI Value set not used */ }, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) + { 0, 0, 1, 0, "Key: Dial", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Command Dial (Shifts row) + { 0, 0, 19, 0, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 20, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 21, 0, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 22, 0, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) + { 0, 1, 1, 0, "Key: M5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M5 macro key (Shifts row) + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) + { 0, 2, 1, 0, "Key: M4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M4 macro key (Shifts row) + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) + { 0, 3, 1, 0, "Key: M3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M3 macro key (Shifts row) + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) + { 0, 4, 1, 0, "Key: M2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M2 macro key (Shifts row) + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right (Shifts row) + { 0, 5, 1, 0, "Key: M1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M1 macro key (Shifts row) + } +}; + +keyboard_keymap_overlay_values razer_blackwidow_v4_pro_75_wired_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_SEVENTY_FIVE, + { + { /* ANSI Value set not used */ }, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, "Left Underglow 0", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 2, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Delete gap between ESC and F1 + { 0, 0, 17, 0, "Right Underglow 0", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 0, 0, "Left Underglow 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Add gap between = and Backspace + { 0, 1, 16, 0, KEY_EN_DELETE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 17, 0, "Right Underglow 1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 0, 0, "Left Underglow 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 16, 0, KEY_EN_PAGE_UP, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 17, 0, "Right Underglow 2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 0, 0, "Left Underglow 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 16, 0, KEY_EN_PAGE_DOWN, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 17, 0, "Right Underglow 3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 0, 0, "Left Underglow 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 15, 0, KEY_EN_UP_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 16, 0, KEY_EN_INSERT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 17, 0, "Right Underglow 4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 0, 0, "Left Underglow 5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, // Remove Menu key between Fn and RCtrl + { 0, 5, 14, 0, KEY_EN_LEFT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 15, 0, KEY_EN_DOWN_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 16, 0, KEY_EN_RIGHT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 17, 0, "Right Underglow 5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + } +}; + +keyboard_keymap_overlay_values razer_blackwidow_v4_x_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_FULL, + { + { /* ANSI Value set not used */ }, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, "Key: M6", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M6 macro key (Shifts row) + { 0, 1, 0, 0, "Key: M5", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M5 macro key (Shifts row) + { 0, 2, 0, 0, "Key: M4", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M4 macro key (Shifts row) + { 0, 3, 0, 0, "Key: M3", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M3 macro key (Shifts row) + { 0, 4, 0, 0, "Key: M2", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M2 macro key (Shifts row) + { 0, 5, 0, 0, "Key: M1", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert M1 macro key (Shifts row) } }; @@ -286,17 +418,17 @@ keyboard_keymap_overlay_values razer_blackwidow_x_chroma_te_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right (Shifts row) - { 0, 0, 20, 0, "Logo", KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert 'Logo' key + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right (Shifts row) + { 0, 0, 20, 0, "Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert 'Logo' key } }; @@ -310,66 +442,66 @@ keyboard_keymap_overlay_values razer_blade_pro_2017_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Escape 1 right (Shifts row) - { 0, 0, 1, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Escape @ 0,1 - { 0, 0, 2, 0, KEY_EN_ESCAPE, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Escape @ 0,2 - { 0, 0, 15, 0, KEY_EN_INSERT, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert 'Insert' key - { 0, 0, 17, 0, KEY_EN_DELETE, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Delete key - { 0, 0, 19, 0, KEY_EN_MEDIA_PREVIOUS, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Previous track key - { 0, 0, 20, 0, KEY_EN_MEDIA_NEXT, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Next track key - { 0, 0, 21, 0, "Key: Media Volume", KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Volume key - { 0, 0, 23, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Play / Pause key - { 0, 0, 24, 0, KEY_EN_MEDIA_MUTE, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Volume Mute key - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) - { 0, 1, 19, 0, "Trackpad", KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad - { 0, 1, 20, 0, "Trackpad", KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad - { 0, 1, 21, 0, "Trackpad", KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad - { 0, 1, 22, 0, "Trackpad", KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad - { 0, 1, 23, 0, "Trackpad", KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad - { 0, 1, 24, 0, "Trackpad", KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) - { 0, 2, 3, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Q' 1 right (Shifts row) - { 0, 2, 16, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Back slash 1 right -> 2,17 - { 0, 2, 19, 0, "Trackpad", KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad - { 0, 2, 24, 0, "Trackpad", KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) - { 0, 3, 2, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'A' 1 right (Shifts row) - { 0, 3, 3, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'A' 1 right (Shifts row) - { 0, 3, 16, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move ANSI Enter 1 right -> 3,18 - { 0, 3, 16, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move ANSI Enter 1 right -> 3,18 - { 0, 3, 19, 0, "Trackpad", KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad - { 0, 3, 24, 0, "Trackpad", KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad - { 0, 4, 2, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Z' 1 right (Shifts row) - { 0, 4, 3, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Z' 1 right (Shifts row) - { 0, 4, 14, 0, KEY_EN_UP_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Arrow Up and shift row 1 right - { 0, 4, 16, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Right Shift 1 right -> 4,17 - { 0, 4, 17, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Right Shift 1 right -> 4,18 - { 0, 4, 19, 0, "Trackpad", KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad - { 0, 4, 24, 0, "Trackpad", KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad - { 0, 5, 1, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Left Windows @ 5,1 - { 0, 5, 2, 0, KEY_EN_LEFT_FUNCTION, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Left Function @ 5,2 - { 0, 5, 3, 0, KEY_EN_LEFT_WINDOWS, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Left Windows @ 5,3 - { 0, 5, 5, 0, KEY_EN_LEFT_ALT, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Left Alt @ 5,5 - { 0, 5, 6, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Spacebar @ 5,6 - { 0, 5, 7, 0, KEY_EN_SPACE, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Spacebar @ 5,7 - { 0, 5, 11, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Right Function @ 5,11 - { 0, 5, 12, 0, KEY_EN_RIGHT_CONTROL, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap Right Control for Right Menu @ 5,12 - { 0, 5, 13, 0, KEY_EN_LEFT_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap Arrow Left for Right Control @ 5,13 - { 0, 5, 14, 0, KEY_EN_DOWN_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Arrow Down @ 5,14 - { 0, 5, 15, 0, KEY_EN_RIGHT_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Arrow Right @ 5,15 - { 0, 5, 16, 0, KEY_EN_RIGHT_FUNCTION, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Right Function @ 5,16 - { 0, 5, 19, 0, "Trackpad", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Trackpad - { 0, 5, 20, 0, "Trackpad", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Trackpad - { 0, 5, 21, 0, "Trackpad", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Trackpad - { 0, 5, 22, 0, "Trackpad", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Trackpad - { 0, 5, 23, 0, "Trackpad", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Trackpad - { 0, 5, 24, 0, "Trackpad", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Trackpad + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Escape 1 right (Shifts row) + { 0, 0, 1, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Escape @ 0,1 + { 0, 0, 2, 0, KEY_EN_ESCAPE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Escape @ 0,2 + { 0, 0, 15, 0, KEY_EN_INSERT, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert 'Insert' key + { 0, 0, 17, 0, KEY_EN_DELETE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Delete key + { 0, 0, 19, 0, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Previous track key + { 0, 0, 20, 0, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Next track key + { 0, 0, 21, 0, "Key: Media Volume", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Volume key + { 0, 0, 23, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Play / Pause key + { 0, 0, 24, 0, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Volume Mute key + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) + { 0, 1, 19, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad + { 0, 1, 20, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad + { 0, 1, 21, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad + { 0, 1, 22, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad + { 0, 1, 23, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad + { 0, 1, 24, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) + { 0, 2, 3, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Q' 1 right (Shifts row) + { 0, 2, 16, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Back slash 1 right -> 2,17 + { 0, 2, 19, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad + { 0, 2, 24, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) + { 0, 3, 2, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'A' 1 right (Shifts row) + { 0, 3, 3, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'A' 1 right (Shifts row) + { 0, 3, 16, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move ANSI Enter 1 right -> 3,18 + { 0, 3, 16, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move ANSI Enter 1 right -> 3,18 + { 0, 3, 19, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad + { 0, 3, 24, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad + { 0, 4, 2, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Z' 1 right (Shifts row) + { 0, 4, 3, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Z' 1 right (Shifts row) + { 0, 4, 14, 0, KEY_EN_UP_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Arrow Up and shift row 1 right + { 0, 4, 16, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Right Shift 1 right -> 4,17 + { 0, 4, 17, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Right Shift 1 right -> 4,18 + { 0, 4, 19, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad + { 0, 4, 24, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Trackpad + { 0, 5, 1, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Left Windows @ 5,1 + { 0, 5, 2, 0, KEY_EN_LEFT_FUNCTION, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Left Function @ 5,2 + { 0, 5, 3, 0, KEY_EN_LEFT_WINDOWS, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Left Windows @ 5,3 + { 0, 5, 5, 0, KEY_EN_LEFT_ALT, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Left Alt @ 5,5 + { 0, 5, 6, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Spacebar @ 5,6 + { 0, 5, 7, 0, KEY_EN_SPACE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Spacebar @ 5,7 + { 0, 5, 11, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Right Function @ 5,11 + { 0, 5, 12, 0, KEY_EN_RIGHT_CONTROL, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap Right Control for Right Menu @ 5,12 + { 0, 5, 13, 0, KEY_EN_LEFT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap Arrow Left for Right Control @ 5,13 + { 0, 5, 14, 0, KEY_EN_DOWN_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Arrow Down @ 5,14 + { 0, 5, 15, 0, KEY_EN_RIGHT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Arrow Right @ 5,15 + { 0, 5, 16, 0, KEY_EN_RIGHT_FUNCTION, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Insert Right Function @ 5,16 + { 0, 5, 19, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Trackpad + { 0, 5, 20, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Trackpad + { 0, 5, 21, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Trackpad + { 0, 5, 22, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Trackpad + { 0, 5, 23, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Trackpad + { 0, 5, 24, 0, "Trackpad", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Trackpad } }; @@ -382,53 +514,53 @@ keyboard_keymap_overlay_values razer_blade_15_2021_advanced_layout { KEYBOARD_LAYOUT_ISO_QWERTY, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 2, 13, 0, KEY_EN_ISO_ENTER, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ANSI_BACKSLASH - { 0, 3, 13, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ANSI_ENTER + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 2, 13, 0, KEY_EN_ISO_ENTER, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ANSI_BACKSLASH + { 0, 3, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ANSI_ENTER } }, /* Add more regional layout fixes here */ } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 1, 0, KEY_EN_ESCAPE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 14, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backspace 1 right - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 5, 0, KEY_EN_LEFT_ALT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 9, 0, KEY_EN_RIGHT_ALT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ESC - { 0, 0, 14, 0, KEY_EN_INSERT, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap PRTSCN for INS - { 0, 0, 15, 0, KEY_EN_DELETE, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap SCRLCK for DEL - { 0, 0, 16, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove PSE_BRK - { 0, 1, 16, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove INSERT - { 0, 1, 17, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove HOME - { 0, 1, 18, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove PGUP - { 0, 2, 15, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove DEL - { 0, 2, 16, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove END - { 0, 2, 17, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove PGDN - { 0, 4, 13, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove RGT_SHFT - { 0, 4, 15, 0, KEY_EN_RIGHT_SHIFT, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWUP for RGT_SHFT - { 0, 5, 2, 0, KEY_EN_LEFT_FUNCTION, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap LFT_WIN for LFT_FNC - { 0, 5, 3, 0, KEY_EN_LEFT_WINDOWS, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap LFT_ALT for LFT_WIN - { 0, 5, 6, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove SPACE - { 0, 5, 10, 0, KEY_EN_RIGHT_FUNCTION, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap RGT_ALT for RGT_FNC - { 0, 5, 11, 0, KEY_EN_RIGHT_CONTROL, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap RGT_FNC for RGT_CTL - { 0, 5, 12, 0, KEY_EN_LEFT_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWLFT for RGT_MNU - { 0, 5, 13, 0, KEY_EN_UP_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWUP for RGT_CTL - { 0, 5, 14, 0, KEY_EN_RIGHT_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWRGT for ARWLFT - { 0, 5, 15, 0, KEY_EN_DOWN_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWDWN for ARWDWN - { 0, 5, 16, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ARWRGT + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 1, 0, KEY_EN_ESCAPE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backspace 1 right + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 5, 0, KEY_EN_LEFT_ALT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 9, 0, KEY_EN_RIGHT_ALT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ESC + { 0, 0, 14, 0, KEY_EN_INSERT, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap PRTSCN for INS + { 0, 0, 15, 0, KEY_EN_DELETE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap SCRLCK for DEL + { 0, 0, 16, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove PSE_BRK + { 0, 1, 16, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove INSERT + { 0, 1, 17, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove HOME + { 0, 1, 18, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove PGUP + { 0, 2, 15, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove DEL + { 0, 2, 16, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove END + { 0, 2, 17, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove PGDN + { 0, 4, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove RGT_SHFT + { 0, 4, 15, 0, KEY_EN_RIGHT_SHIFT, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWUP for RGT_SHFT + { 0, 5, 2, 0, KEY_EN_LEFT_FUNCTION, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap LFT_WIN for LFT_FNC + { 0, 5, 3, 0, KEY_EN_LEFT_WINDOWS, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap LFT_ALT for LFT_WIN + { 0, 5, 6, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove SPACE + { 0, 5, 10, 0, KEY_EN_RIGHT_FUNCTION, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap RGT_ALT for RGT_FNC + { 0, 5, 11, 0, KEY_EN_RIGHT_CONTROL, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap RGT_FNC for RGT_CTL + { 0, 5, 12, 0, KEY_EN_LEFT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWLFT for RGT_MNU + { 0, 5, 13, 0, KEY_EN_UP_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWUP for RGT_CTL + { 0, 5, 14, 0, KEY_EN_RIGHT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWRGT for ARWLFT + { 0, 5, 15, 0, KEY_EN_DOWN_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWDWN for ARWDWN + { 0, 5, 16, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ARWRGT } }; @@ -441,65 +573,65 @@ keyboard_keymap_overlay_values razer_blade_15_2022_layout { KEYBOARD_LAYOUT_ANSI_QWERTY, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 4, 1, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Move 'Z' 1 right (Account for ISO key) + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 4, 1, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Move 'Z' 1 right (Account for ISO key) } }, { KEYBOARD_LAYOUT_ISO_QWERTY, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 2, 13, 0, KEY_EN_ISO_ENTER, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ANSI_BACKSLASH - { 0, 3, 13, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ANSI_ENTER + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 2, 13, 0, KEY_EN_ISO_ENTER, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ANSI_BACKSLASH + { 0, 3, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ANSI_ENTER } }, /* Add more regional layout fixes here */ } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Escape 1 right - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 14, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backspace 1 right - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 14, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Back slash 1 right - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 13, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move ANSI Enter 1 right - { 0, 3, 14, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move ANSI Enter 1 right - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 5, 0, KEY_EN_LEFT_ALT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 6, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Space 1 right - { 0, 5, 9, 0, KEY_EN_RIGHT_ALT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 14, 0, KEY_EN_DELETE, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap PRTSCN for DEL - { 0, 0, 15, 0, KEY_EN_POWER, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap SCRLCK for POWER - { 0, 0, 16, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove PSE_BRK - { 0, 1, 16, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove INSERT - { 0, 1, 17, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove HOME - { 0, 1, 18, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove PGUP - { 0, 2, 16, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove DEL - { 0, 2, 17, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove END - { 0, 2, 18, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove PGDN - { 0, 4, 13, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove RGT_SHFT - { 0, 4, 15, 0, KEY_EN_RIGHT_SHIFT, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWUP for RGT_SHFT - { 0, 5, 2, 0, KEY_EN_LEFT_FUNCTION, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap LFT_WIN for LFT_FNC - { 0, 5, 3, 0, KEY_EN_LEFT_WINDOWS, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap LFT_ALT for LFT_WIN - { 0, 5, 10, 0, KEY_EN_RIGHT_FUNCTION, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap RGT_ALT for RGT_FNC - { 0, 5, 11, 0, KEY_EN_RIGHT_CONTROL, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap RGT_FNC for RGT_CTL - { 0, 5, 12, 0, KEY_EN_LEFT_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWLFT for RGT_MNU - { 0, 5, 13, 0, KEY_EN_UP_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWUP for RGT_CTL - { 0, 5, 14, 0, KEY_EN_RIGHT_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWRGT for ARWLFT - { 0, 5, 15, 0, KEY_EN_DOWN_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWDWN for ARWDWN - { 0, 5, 16, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ARWRGT + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Escape 1 right + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backspace 1 right + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Back slash 1 right + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move ANSI Enter 1 right + { 0, 3, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move ANSI Enter 1 right + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 5, 0, KEY_EN_LEFT_ALT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 6, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Space 1 right + { 0, 5, 9, 0, KEY_EN_RIGHT_ALT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 14, 0, KEY_EN_DELETE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap PRTSCN for DEL + { 0, 0, 15, 0, KEY_EN_POWER, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap SCRLCK for POWER + { 0, 0, 16, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove PSE_BRK + { 0, 1, 16, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove INSERT + { 0, 1, 17, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove HOME + { 0, 1, 18, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove PGUP + { 0, 2, 16, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove DEL + { 0, 2, 17, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove END + { 0, 2, 18, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove PGDN + { 0, 4, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove RGT_SHFT + { 0, 4, 15, 0, KEY_EN_RIGHT_SHIFT, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWUP for RGT_SHFT + { 0, 5, 2, 0, KEY_EN_LEFT_FUNCTION, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap LFT_WIN for LFT_FNC + { 0, 5, 3, 0, KEY_EN_LEFT_WINDOWS, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap LFT_ALT for LFT_WIN + { 0, 5, 10, 0, KEY_EN_RIGHT_FUNCTION, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap RGT_ALT for RGT_FNC + { 0, 5, 11, 0, KEY_EN_RIGHT_CONTROL, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap RGT_FNC for RGT_CTL + { 0, 5, 12, 0, KEY_EN_LEFT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWLFT for RGT_MNU + { 0, 5, 13, 0, KEY_EN_UP_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWUP for RGT_CTL + { 0, 5, 14, 0, KEY_EN_RIGHT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWRGT for ARWLFT + { 0, 5, 15, 0, KEY_EN_DOWN_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWDWN for ARWDWN + { 0, 5, 16, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ARWRGT } }; @@ -513,34 +645,34 @@ keyboard_keymap_overlay_values razer_blade_17_pro_2021_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Shift all rows right by one */ - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ - { 0, 1, 14, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Rows 1-4 have an empty spot in */ - { 0, 2, 14, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* 14th column */ - { 0, 3, 14, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ - { 0, 4, 14, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ - { 0, 0, 2, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove empty spot between Esc and F1 */ - { 0, 0, 14, 0, KEY_EN_INSERT, KEYBOARD_OPCODE_SWAP_ONLY }, /* Swap in Delete after F12 */ - { 0, 0, 15, 0, KEY_EN_DELETE, KEYBOARD_OPCODE_SWAP_ONLY }, /* Swap in Power after Delete */ - { 0, 5, 2, 0, KEY_EN_LEFT_FUNCTION, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Insert left Fn between Ctrl and Win */ - { 0, 5, 4, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add empty spot between Win and Alt */ - { 0, 5, 9, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove Space */ - { 0, 5, 9, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove unused */ - { 0, 5, 9, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove unused */ - { 0, 5, 9, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove unused */ - { 0, 5, 11, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove Menu */ - { 0, 5, 12, 0, KEY_EN_LEFT_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Left Arrow at the end of row 5 */ - { 0, 5, 13, 0, KEY_EN_UP_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Up Arrow at the end of row 5 */ - { 0, 5, 14, 0, KEY_EN_RIGHT_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Right Arrow at the end of row 5 */ - { 0, 5, 15, 0, KEY_EN_DOWN_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Down Arrow at the end of row 5 */ + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Shift all rows right by one */ + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ + { 0, 1, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Rows 1-4 have an empty spot in */ + { 0, 2, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* 14th column */ + { 0, 3, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ + { 0, 4, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ + { 0, 0, 2, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove empty spot between Esc and F1 */ + { 0, 0, 14, 0, KEY_EN_INSERT, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY }, /* Swap in Delete after F12 */ + { 0, 0, 15, 0, KEY_EN_DELETE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY }, /* Swap in Power after Delete */ + { 0, 5, 2, 0, KEY_EN_LEFT_FUNCTION, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Insert left Fn between Ctrl and Win */ + { 0, 5, 4, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add empty spot between Win and Alt */ + { 0, 5, 9, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove Space */ + { 0, 5, 9, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove unused */ + { 0, 5, 9, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove unused */ + { 0, 5, 9, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove unused */ + { 0, 5, 11, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove Menu */ + { 0, 5, 12, 0, KEY_EN_LEFT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Left Arrow at the end of row 5 */ + { 0, 5, 13, 0, KEY_EN_UP_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Up Arrow at the end of row 5 */ + { 0, 5, 14, 0, KEY_EN_RIGHT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Right Arrow at the end of row 5 */ + { 0, 5, 15, 0, KEY_EN_DOWN_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Down Arrow at the end of row 5 */ } }; @@ -554,33 +686,33 @@ keyboard_keymap_overlay_values razer_blade_stealth_2016_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Shift rows right by one */ - { 0, 0, 2, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove empty between Esc and F1 */ - { 0, 0, 14, 0, KEY_EN_INSERT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Insert at end of row */ - { 0, 0, 15, 0, KEY_EN_DELETE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Delete at end of row */ - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Shift rows right by one */ - { 0, 1, 15, 0, KEY_EN_BACKSPACE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add second Backspace at end of row */ - { 0, 2, 1, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add empty between tab and Q */ - { 0, 2, 15, 0, KEY_EN_ANSI_BACK_SLASH, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add second Backslash at end of row */ - { 0, 3, 1, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add empty between caps and A */ - { 0, 3, 15, 0, KEY_EN_ANSI_ENTER, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add second Enter at end of row */ - { 0, 4, 12, 0, KEY_EN_RIGHT_SHIFT, KEYBOARD_OPCODE_SWAP_ONLY }, /* Insert 1st Right Shift */ - { 0, 4, 13, 0, KEY_EN_RIGHT_SHIFT, KEYBOARD_OPCODE_SWAP_ONLY }, /* Insert 2nd Right Shift */ - { 0, 4, 14, 0, KEY_EN_RIGHT_SHIFT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Insert 3rd Right Shift */ - { 0, 5, 1, 0, KEY_EN_LEFT_FUNCTION, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Insert left Fn between Ctrl and Win */ - { 0, 5, 5, 0, KEY_EN_SPACE, KEYBOARD_OPCODE_SWAP_ONLY }, /* Insert 1st Space */ - { 0, 5, 6, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove empty between Space 1 and 2 */ - { 0, 5, 8, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove empty between Space 2 and 3 */ - { 0, 5, 8, 0, KEY_EN_SPACE, KEYBOARD_OPCODE_SWAP_ONLY }, /* Insert 3rd Space */ - { 0, 5, 11, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove Menu */ - { 0, 5, 12, 0, KEY_EN_LEFT_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Left Arrow at the end of row 5 */ - { 0, 5, 13, 0, KEY_EN_UP_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Up Arrow at the end of row 5 */ - { 0, 5, 14, 0, KEY_EN_RIGHT_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Right Arrow at the end of row 5 */ - { 0, 5, 15, 0, KEY_EN_DOWN_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Down Arrow at the end of row 5 */ + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Shift rows right by one */ + { 0, 0, 2, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove empty between Esc and F1 */ + { 0, 0, 14, 0, KEY_EN_INSERT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Insert at end of row */ + { 0, 0, 15, 0, KEY_EN_DELETE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Delete at end of row */ + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Shift rows right by one */ + { 0, 1, 15, 0, KEY_EN_BACKSPACE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add second Backspace at end of row */ + { 0, 2, 1, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add empty between tab and Q */ + { 0, 2, 15, 0, KEY_EN_ANSI_BACK_SLASH, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add second Backslash at end of row */ + { 0, 3, 1, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add empty between caps and A */ + { 0, 3, 15, 0, KEY_EN_ANSI_ENTER, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add second Enter at end of row */ + { 0, 4, 12, 0, KEY_EN_RIGHT_SHIFT, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY }, /* Insert 1st Right Shift */ + { 0, 4, 13, 0, KEY_EN_RIGHT_SHIFT, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY }, /* Insert 2nd Right Shift */ + { 0, 4, 14, 0, KEY_EN_RIGHT_SHIFT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Insert 3rd Right Shift */ + { 0, 5, 1, 0, KEY_EN_LEFT_FUNCTION, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Insert left Fn between Ctrl and Win */ + { 0, 5, 5, 0, KEY_EN_SPACE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY }, /* Insert 1st Space */ + { 0, 5, 6, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove empty between Space 1 and 2 */ + { 0, 5, 8, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove empty between Space 2 and 3 */ + { 0, 5, 8, 0, KEY_EN_SPACE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY }, /* Insert 3rd Space */ + { 0, 5, 11, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove Menu */ + { 0, 5, 12, 0, KEY_EN_LEFT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Left Arrow at the end of row 5 */ + { 0, 5, 13, 0, KEY_EN_UP_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Up Arrow at the end of row 5 */ + { 0, 5, 14, 0, KEY_EN_RIGHT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Right Arrow at the end of row 5 */ + { 0, 5, 15, 0, KEY_EN_DOWN_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Down Arrow at the end of row 5 */ } }; @@ -594,17 +726,17 @@ keyboard_keymap_overlay_values razer_cynosa_chroma_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 1 - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 2 - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 3 - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 4 - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 5 - { 0, 0, 20, 0, "Logo", KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert 'Logo' key + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 1 + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 2 + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 3 + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 4 + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 5 + { 0, 0, 20, 0, "Logo", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert 'Logo' key } }; @@ -618,22 +750,22 @@ keyboard_keymap_overlay_values razer_cynosa_chroma_v2_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 1 - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 2 - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 3 - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 4 - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 5 - { 0, 0, 18, 0, KEY_EN_MEDIA_PREVIOUS, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Previous track key - { 0, 0, 19, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Play / Pause key - { 0, 0, 20, 0, KEY_EN_MEDIA_NEXT, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Next track key - { 0, 0, 21, 0, KEY_EN_MEDIA_MUTE, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Volume Mute key - { 0, 4, 15, 0, KEY_EN_MEDIA_VOLUME_UP, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Volume Up - { 0, 4, 17, 0, KEY_EN_MEDIA_VOLUME_DOWN, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Volume Down + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 1 + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 2 + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 3 + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 4 + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 5 + { 0, 0, 18, 0, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Previous track key + { 0, 0, 19, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Play / Pause key + { 0, 0, 20, 0, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Next track key + { 0, 0, 21, 0, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Volume Mute key + { 0, 4, 15, 0, KEY_EN_MEDIA_VOLUME_UP, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Volume Up + { 0, 4, 17, 0, KEY_EN_MEDIA_VOLUME_DOWN, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Volume Down } }; @@ -646,33 +778,33 @@ keyboard_keymap_overlay_values razer_deathstalker_v2_layout { KEYBOARD_LAYOUT_ANSI_QWERTY, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 4, 1, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Move 'Z' 1 right (Account for ISO key) + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 4, 1, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Move 'Z' 1 right (Account for ISO key) } }, { KEYBOARD_LAYOUT_ISO_QWERTY, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 2, 13, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ANSI_BACKSLASH - { 0, 4, 1, 0, KEY_EN_ISO_BACK_SLASH, KEYBOARD_OPCODE_SWAP_ONLY, }, // Add ISO_BACK_SLASH + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 2, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ANSI_BACKSLASH + { 0, 4, 1, 0, KEY_EN_ISO_BACK_SLASH, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Add ISO_BACK_SLASH } }, /* Add more regional layout fixes here */ } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 1, 13, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backspace 1 right + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 1, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backspace 1 right } }; @@ -685,32 +817,73 @@ keyboard_keymap_overlay_values razer_deathstalker_v2_pro_layout { KEYBOARD_LAYOUT_ANSI_QWERTY, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 4, 1, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Move 'Z' 1 right (Account for ISO key) + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 4, 1, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Move 'Z' 1 right (Account for ISO key) } }, { KEYBOARD_LAYOUT_ISO_QWERTY, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 2, 13, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ANSI_BACKSLASH - { 0, 4, 1, 0, KEY_EN_ISO_BACK_SLASH, KEYBOARD_OPCODE_SWAP_ONLY, }, // Add ISO_BACK_SLASH + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 2, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ANSI_BACKSLASH + { 0, 4, 1, 0, KEY_EN_ISO_BACK_SLASH, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Add ISO_BACK_SLASH } }, /* Add more regional layout fixes here */ } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + } +}; + +keyboard_keymap_overlay_values razer_deathstalker_v2_pro_tkl_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_TKL, + { + { /* ANSI Value set not used */ }, + { + { + KEYBOARD_LAYOUT_ANSI_QWERTY, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 4, 1, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Move 'Z' 1 right (Account for ISO key) + } + }, + { + KEYBOARD_LAYOUT_ISO_QWERTY, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 2, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove ANSI_BACKSLASH + { 0, 4, 1, 0, KEY_EN_ISO_BACK_SLASH, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Add ISO_BACK_SLASH + } + }, + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove PRINT_SCREEN + { 0, 0, 15, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove SCROLL_LOCK + { 0, 0, 16, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove PAUSE_BREAK } }; @@ -724,16 +897,16 @@ keyboard_keymap_overlay_values razer_full_size_shifted_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 1 - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 2 - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 3 - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 4 - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 5 + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 1 + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 2 + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 3 + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 4 + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shifts row 5 } }; @@ -747,20 +920,20 @@ keyboard_keymap_overlay_values razer_huntsman_common_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 18, 0, KEY_EN_MEDIA_PREVIOUS, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 19, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 20, 0, KEY_EN_MEDIA_NEXT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 21, 0, KEY_EN_MEDIA_MUTE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 18, 0, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 19, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 20, 0, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 21, 0, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, } }; @@ -774,15 +947,15 @@ keyboard_keymap_overlay_values razer_huntsman_mini_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shift row 0 - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shift row 1 - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shift row 2 - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shift row 3 - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shift row 4 + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shift row 0 + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shift row 1 + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shift row 2 + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shift row 3 + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Shift row 4 } }; @@ -796,16 +969,16 @@ keyboard_keymap_overlay_values razer_huntsman_te_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right (Shifts row) + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move 'Esc' 1 right (Shifts row) + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_CTRL 1 right (Shifts row) } }; @@ -819,14 +992,14 @@ keyboard_keymap_overlay_values razer_huntsman_v2_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 18, 0, KEY_EN_MEDIA_PREVIOUS, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 19, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 20, 0, KEY_EN_MEDIA_NEXT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 21, 0, KEY_EN_MEDIA_MUTE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 17, 0, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 18, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 19, 0, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 20, 0, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, } }; @@ -840,10 +1013,63 @@ keyboard_keymap_overlay_values razer_huntsman_v2_tkl_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + } +}; + +keyboard_keymap_overlay_values razer_huntsman_v3_pro_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_FULL, + { + { /* ANSI Value set not used */ }, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 18, 0, "Media group", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 20, 0, "Media: Volume Dial", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 17, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT, }, + } +}; + +keyboard_keymap_overlay_values razer_huntsman_v3_pro_tkl_layout +{ + KEYBOARD_SIZE::KEYBOARD_SIZE_TKL, + { + { /* ANSI Value set not used */ }, + { + /* Add more regional layout fixes here */ + } + }, + { + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Key, Alternate Name, OpCode, | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 15, 0, "Xbox Game Bar", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 0, 16, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 0, 17, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 18, 0, "Media: Volume Dial", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, } }; @@ -857,35 +1083,35 @@ keyboard_keymap_overlay_values razer_laptop_common_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Shift all rows right by one */ - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ - { 0, 1, 14, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Rows 1-4 have an empty spot in */ - { 0, 2, 14, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* 14th column */ - { 0, 3, 14, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ - { 0, 4, 14, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ - { 0, 0, 2, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove empty spot between Esc and F1 */ - { 0, 0, 14, 0, KEY_EN_DELETE, KEYBOARD_OPCODE_SWAP_ONLY }, /* Swap in Delete after F12 */ - { 0, 0, 15, 0, KEY_EN_POWER, KEYBOARD_OPCODE_SWAP_ONLY }, /* Swap in Power after Delete */ - { 0, 5, 2, 0, KEY_EN_LEFT_FUNCTION, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Insert left Fn between Ctrl and Win */ - { 0, 5, 4, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add empty spot between Win and Alt */ - { 0, 5, 9, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove Space */ - { 0, 5, 9, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove unused */ - { 0, 5, 9, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove unused */ - { 0, 5, 9, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove unused */ - { 0, 5, 10, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove Right Fn */ - { 0, 5, 10, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY }, /* Remove Menu */ - { 0, 5, 12, 0, KEY_EN_LEFT_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Left Arrow at the end of row 5 */ - { 0, 5, 13, 0, KEY_EN_UP_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Up Arrow at the end of row 5 */ - { 0, 5, 14, 0, KEY_EN_RIGHT_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Right Arrow at the end of row 5 */ - { 0, 5, 15, 0, KEY_EN_DOWN_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Down Arrow at the end of row 5 */ + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Shift all rows right by one */ + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ + { 0, 1, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Rows 1-4 have an empty spot in */ + { 0, 2, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* 14th column */ + { 0, 3, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ + { 0, 4, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* */ + { 0, 0, 2, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove empty spot between Esc and F1 */ + { 0, 0, 14, 0, KEY_EN_DELETE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY }, /* Swap in Delete after F12 */ + { 0, 0, 15, 0, KEY_EN_POWER, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY }, /* Swap in Power after Delete */ + { 0, 5, 2, 0, KEY_EN_LEFT_FUNCTION, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Insert left Fn between Ctrl and Win */ + { 0, 5, 4, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add empty spot between Win and Alt */ + { 0, 5, 9, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove Space */ + { 0, 5, 9, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove unused */ + { 0, 5, 9, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove unused */ + { 0, 5, 9, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove unused */ + { 0, 5, 10, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, /* Remove Right Fn */ + { 0, 5, 10, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY }, /* Remove Menu */ + { 0, 5, 12, 0, KEY_EN_LEFT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Left Arrow at the end of row 5 */ + { 0, 5, 13, 0, KEY_EN_UP_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Up Arrow at the end of row 5 */ + { 0, 5, 14, 0, KEY_EN_RIGHT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Right Arrow at the end of row 5 */ + { 0, 5, 15, 0, KEY_EN_DOWN_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, /* Add Down Arrow at the end of row 5 */ } }; @@ -899,35 +1125,35 @@ keyboard_keymap_overlay_values razer_laptop_with_spacebar_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Escape @ 0,0 - { 0, 0, 1, 0, KEY_EN_ESCAPE, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Escape @ 0,1 - { 0, 0, 15, 0, KEY_EN_POWER, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Power key - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) - { 0, 1, 14, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backspace 1 right - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) - { 0, 2, 14, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Back slash 1 right - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) - { 0, 3, 14, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move ANSI Enter 1 right - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) - { 0, 4, 14, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Right Shift 1 right - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Left Control @ 5,0 - { 0, 5, 1, 0, KEY_EN_LEFT_CONTROL, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Left Control @ 5,1 - { 0, 5, 2, 0, KEY_EN_LEFT_FUNCTION, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Left Function @ 5,2 - { 0, 5, 3, 0, KEY_EN_LEFT_WINDOWS, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Left Windows @ 5,3 - { 0, 5, 5, 0, KEY_EN_LEFT_ALT, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Left Alt @ 5,5 - { 0, 5, 6, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Spacebar @ 5,6 - { 0, 5, 7, 0, KEY_EN_SPACE, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Spacebar @ 5,7 - { 0, 5, 9, 0, KEY_EN_RIGHT_ALT, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Right Alt @ 5,9 - { 0, 5, 10, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Right Alt @ 5,10 - { 0, 5, 11, 0, KEY_EN_RIGHT_CONTROL, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap RGT_FNC for RGT_CTL - { 0, 5, 12, 0, KEY_EN_LEFT_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWLFT for RGT_MNU - { 0, 5, 13, 0, KEY_EN_UP_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWUP for RGT_CTL - { 0, 5, 14, 0, KEY_EN_RIGHT_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert ARWRGT - { 0, 5, 15, 0, KEY_EN_DOWN_ARROW, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert ARWDWN + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Escape @ 0,0 + { 0, 0, 1, 0, KEY_EN_ESCAPE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Escape @ 0,1 + { 0, 0, 15, 0, KEY_EN_POWER, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Power key + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backtick 1 right (Shifts row) + { 0, 1, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Backspace 1 right + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Tab 1 right (Shifts row) + { 0, 2, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Back slash 1 right + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Caps 1 right (Shifts row) + { 0, 3, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move ANSI Enter 1 right + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move LFT_SHFT 1 right (Shifts row) + { 0, 4, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, // Move Right Shift 1 right + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Left Control @ 5,0 + { 0, 5, 1, 0, KEY_EN_LEFT_CONTROL, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Left Control @ 5,1 + { 0, 5, 2, 0, KEY_EN_LEFT_FUNCTION, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Left Function @ 5,2 + { 0, 5, 3, 0, KEY_EN_LEFT_WINDOWS, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Left Windows @ 5,3 + { 0, 5, 5, 0, KEY_EN_LEFT_ALT, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Left Alt @ 5,5 + { 0, 5, 6, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Spacebar @ 5,6 + { 0, 5, 7, 0, KEY_EN_SPACE, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Spacebar @ 5,7 + { 0, 5, 9, 0, KEY_EN_RIGHT_ALT, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert Right Alt @ 5,9 + { 0, 5, 10, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Remove Right Alt @ 5,10 + { 0, 5, 11, 0, KEY_EN_RIGHT_CONTROL, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap RGT_FNC for RGT_CTL + { 0, 5, 12, 0, KEY_EN_LEFT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWLFT for RGT_MNU + { 0, 5, 13, 0, KEY_EN_UP_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Swap ARWUP for RGT_CTL + { 0, 5, 14, 0, KEY_EN_RIGHT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert ARWRGT + { 0, 5, 15, 0, KEY_EN_DOWN_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, // Insert ARWDWN } }; @@ -941,20 +1167,20 @@ keyboard_keymap_overlay_values razer_ornata_chroma_v2_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 18, 0, KEY_EN_MEDIA_PREVIOUS, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 19, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 20, 0, KEY_EN_MEDIA_NEXT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 21, 0, KEY_EN_MEDIA_MUTE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 0, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 18, 0, KEY_EN_MEDIA_PREVIOUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 19, 0, KEY_EN_MEDIA_PLAY_PAUSE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 20, 0, KEY_EN_MEDIA_NEXT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 21, 0, KEY_EN_MEDIA_MUTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 0, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, } }; @@ -968,31 +1194,31 @@ keyboard_keymap_overlay_values razer_tartarus_v2_layout } }, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, "Key: 01", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 1, 0, "Key: 02", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 2, 0, "Key: 03", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 3, 0, "Key: 04", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 4, 0, "Key: 05", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 0, 0, "Key: 06", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 1, 0, "Key: 07", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 2, 0, "Key: 08", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 3, 0, "Key: 09", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 4, 0, "Key: 10", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 0, 0, "Key: 11", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 1, 0, "Key: 12", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 2, 0, "Key: 13", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 3, 0, "Key: 14", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 4, 0, "Key: 15", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 0, 0, "Key: 16", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 1, 0, "Key: 17", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 2, 0, "Key: 18", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 3, 0, "Key: 19", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 4, 0, "Key: Scroll Wheel", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 5, 0, "Key: 20", KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, "Key: 01", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 1, 0, "Key: 02", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 2, 0, "Key: 03", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 3, 0, "Key: 04", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 4, 0, "Key: 05", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 0, 0, "Key: 06", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 1, 0, "Key: 07", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 2, 0, "Key: 08", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 3, 0, "Key: 09", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 4, 0, "Key: 10", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 0, 0, "Key: 11", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 1, 0, "Key: 12", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 2, 0, "Key: 13", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 3, 0, "Key: 14", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 4, 0, "Key: 15", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 0, 0, "Key: 16", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 1, 0, "Key: 17", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 2, 0, "Key: 18", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 3, 0, "Key: 19", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 4, 0, "Key: Scroll Wheel", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 5, 0, "Key: 20", KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, } }; @@ -1032,8 +1258,6 @@ static const razer_device blackwidow_2019_device = NULL, NULL }, - NULL, - 0, &razer_blackwidow_2019_layout }; @@ -1069,8 +1293,6 @@ static const razer_device blackwidow_chroma_device = NULL, NULL }, - NULL, - 0, &razer_blackwidow_chroma_layout }; @@ -1106,48 +1328,9 @@ static const razer_device blackwidow_chroma_overwatch_device = NULL, NULL }, - NULL, - 0, NULL }; -/*-------------------------------------------------------------*\ -| Razer Blackwidow V3 1532:024E | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 22 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blackwidow_v3_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 22 -}; - -static const razer_device blackwidow_v3_device = -{ - "Razer Blackwidow V3", - RAZER_BLACKWIDOW_V3_PID, - DEVICE_TYPE_KEYBOARD, - RAZER_MATRIX_TYPE_EXTENDED, - 0x3F, - 6, - 22, - { - &blackwidow_v3_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0, - &razer_blackwidow_v3_layout -}; - /*-------------------------------------------------------------*\ | Razer BlackWidow Chroma Tournament Edition | | | @@ -1180,48 +1363,9 @@ static const razer_device blackwidow_chroma_te_device = NULL, NULL }, - NULL, - 0, &razer_blackwidow_chroma_te_layout }; -/*-------------------------------------------------------------*\ -| Razer Blackwidow Elite 1532:0228 | -| | -| Zone "Keyboard" | -| Matrix | -| 6 Rows, 22 Columns | -\*-------------------------------------------------------------*/ -static const razer_zone blackwidow_elite_zone = -{ - ZONE_EN_KEYBOARD, - ZONE_TYPE_MATRIX, - 6, - 22 -}; - -static const razer_device blackwidow_elite_device = -{ - "Razer BlackWidow Elite", - RAZER_BLACKWIDOW_ELITE_PID, - DEVICE_TYPE_KEYBOARD, - RAZER_MATRIX_TYPE_EXTENDED, - 0x1F, - 6, - 22, - { - &blackwidow_elite_zone, - NULL, - NULL, - NULL, - NULL, - NULL - }, - NULL, - 0, - &razer_blackwidow_elite_layout -}; - /*-------------------------------------------------------------*\ | Razer Blackwidow Chroma V2 1532:0221 | | | @@ -1254,11 +1398,79 @@ static const razer_device blackwidow_chroma_v2_device = NULL, NULL }, - NULL, - 0, &razer_blackwidow_chroma_v2_layout }; +/*-------------------------------------------------------------*\ +| Razer Blackwidow Elite 1532:0228 | +| | +| Zone "Keyboard" | +| Matrix | +| 6 Rows, 22 Columns | +\*-------------------------------------------------------------*/ +static const razer_zone blackwidow_elite_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 6, + 22 +}; + +static const razer_device blackwidow_elite_device = +{ + "Razer BlackWidow Elite", + RAZER_BLACKWIDOW_ELITE_PID, + DEVICE_TYPE_KEYBOARD, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 6, + 22, + { + &blackwidow_elite_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, + &razer_blackwidow_elite_layout +}; + +/*-------------------------------------------------------------*\ +| Razer Blackwidow V3 1532:024E | +| | +| Zone "Keyboard" | +| Matrix | +| 6 Rows, 22 Columns | +\*-------------------------------------------------------------*/ +static const razer_zone blackwidow_v3_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 6, + 22 +}; + +static const razer_device blackwidow_v3_device = +{ + "Razer Blackwidow V3", + RAZER_BLACKWIDOW_V3_PID, + DEVICE_TYPE_KEYBOARD, + RAZER_MATRIX_TYPE_EXTENDED, + 0x3F, + 6, + 22, + { + &blackwidow_v3_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, + &razer_blackwidow_v3_layout +}; + /*-------------------------------------------------------------*\ | Razer Blackwidow V3 Pro (Wired) 1532:025A | | | @@ -1291,8 +1503,6 @@ static const razer_device blackwidow_v3_pro_wired_device = NULL, NULL }, - NULL, - 0, &razer_blackwidow_v3_pro_layout }; @@ -1328,8 +1538,6 @@ static const razer_device blackwidow_v3_pro_bluetooth_device = NULL, NULL }, - NULL, - 0, &razer_blackwidow_v3_pro_layout }; @@ -1365,8 +1573,6 @@ static const razer_device blackwidow_v3_pro_wireless_device = NULL, NULL }, - NULL, - 0, &razer_blackwidow_v3_pro_layout }; @@ -1402,8 +1608,6 @@ static const razer_device blackwidow_v3_tkl_device = NULL, NULL }, - NULL, - 0, &razer_blackwidow_v3_tkl_layout }; @@ -1439,8 +1643,6 @@ static const razer_device blackwidow_v3_mini_wired_device = NULL, NULL }, - NULL, - 0, &razer_blackwidow_v3_mini_layout }; @@ -1468,11 +1670,222 @@ static const razer_device blackwidow_v3_mini_wireless_device = NULL, NULL }, - NULL, - 0, &razer_blackwidow_v3_mini_layout }; +/*-------------------------------------------------------------*\ +| Razer Blackwidow V4 1532:0287 | +| | +| Zone "Keyboard" | +| Matrix | +| 6 Rows, 23 Columns | +| | +| Zone "Underglow Left" | +| Linear | +| 1 Row, 9 Columns | +| | +| Zone "Underglow right" | +| Linear | +| 1 Row, 9 Columns | +| | +\*-------------------------------------------------------------*/ +static const razer_zone blackwidow_v4_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 6, + 23 +}; + +static const razer_zone blackwidow_v4_lbl_zone = +{ + "Underglow Left", + ZONE_TYPE_LINEAR, + 1, + 9 +}; + +static const razer_zone blackwidow_v4_lbr_zone = +{ + "Underglow Right", + ZONE_TYPE_LINEAR, + 1, + 9 +}; + +static const razer_device blackwidow_v4_device = +{ + "Razer Blackwidow V4", + RAZER_BLACKWIDOW_V4_PID, + DEVICE_TYPE_KEYBOARD, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 8, + 23, + { + &blackwidow_v4_zone, + &blackwidow_v4_lbl_zone, + &blackwidow_v4_lbr_zone, + NULL, + NULL, + NULL + }, + &razer_blackwidow_v4_layout +}; + +/*-------------------------------------------------------------*\ +| Razer Blackwidow V4 Pro 1532:028D | +| | +| Zone "Keyboard" | +| Matrix | +| 6 Rows, 23 Columns | +| | +| Zone "Underglow Left" | +| Linear | +| 1 Row, 9 Columns | +| | +| Zone "Underglow right" | +| Linear | +| 1 Row, 9 Columns | +| | +| Zone "Void" - In testing these LEDs were not connected | +| Linear | +| 1 Row, 5 Columns | +| | +| Zone "Underglow Wrist Rest" | +| Linear | +| 1 Rows, 20 Columns | +\*-------------------------------------------------------------*/ +static const razer_zone blackwidow_v4_pro_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 6, + 23 +}; + +static const razer_zone blackwidow_v4_pro_lbl_zone = +{ + "Underglow Left", + ZONE_TYPE_LINEAR, + 1, + 9 +}; + +static const razer_zone blackwidow_v4_pro_lbr_zone = +{ + "Underglow Right", + ZONE_TYPE_LINEAR, + 1, + 9 +}; + +static const razer_zone blackwidow_v4_pro_void_zone = +{ + "Void", + ZONE_TYPE_LINEAR, + 1, + 5 +}; + +static const razer_zone blackwidow_v4_pro_lbwr_zone = +{ + "Underglow Wrist Rest", + ZONE_TYPE_LINEAR, + 1, + 20 +}; + +static const razer_device blackwidow_v4_pro_device = +{ + "Razer Blackwidow V4 Pro", + RAZER_BLACKWIDOW_V4_PRO_PID, + DEVICE_TYPE_KEYBOARD, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 8, + 23, + { + &blackwidow_v4_pro_zone, + &blackwidow_v4_pro_lbl_zone, + &blackwidow_v4_pro_lbr_zone, + &blackwidow_v4_pro_void_zone, + &blackwidow_v4_pro_lbwr_zone, + NULL + }, + &razer_blackwidow_v4_pro_layout +}; + +/*-------------------------------------------------------------*\ +| Razer Blackwidow V4 Pro 75% 1532:02B3 | +| | +| Zone "Keyboard" | +| Matrix | +| 6 Rows, 18 Columns | +\*-------------------------------------------------------------*/ +static const razer_zone blackwidow_v4_pro_75_wired_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 6, + 18 +}; + +static const razer_device blackwidow_v4_pro_75_wired_device = +{ + "Razer Blackwidow V4 Pro 75% (Wired)", + RAZER_BLACKWIDOW_V4_PRO_75_WIRED_PID, + DEVICE_TYPE_KEYBOARD, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 6, + 18, + { + &blackwidow_v4_pro_75_wired_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, + &razer_blackwidow_v4_pro_75_wired_layout +}; + +/*-------------------------------------------------------------*\ +| Razer Blackwidow V4 X 1532:0293 | +| | +| Zone "Keyboard" | +| Matrix | +| 6 Rows, 22 Columns | +\*-------------------------------------------------------------*/ +static const razer_zone blackwidow_v4_x_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 6, + 22 +}; + +static const razer_device blackwidow_v4_x_device = +{ + "Razer Blackwidow V4 X", + RAZER_BLACKWIDOW_V4_X_PID, + DEVICE_TYPE_KEYBOARD, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 6, + 22, + { + &blackwidow_v4_x_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, + &razer_blackwidow_v4_x_layout +}; + /*-------------------------------------------------------------*\ | Razer Blackwidow X Chroma 1532:0216 | | | @@ -1505,8 +1918,6 @@ static const razer_device blackwidow_x_chroma_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -1542,8 +1953,6 @@ static const razer_device blackwidow_x_chroma_te_device = NULL, NULL }, - NULL, - 0, &razer_blackwidow_x_chroma_te_layout }; @@ -1579,8 +1988,6 @@ static const razer_device cynosa_chroma_device = NULL, NULL }, - NULL, - 0, &razer_cynosa_chroma_layout }; @@ -1616,8 +2023,6 @@ static const razer_device cynosa_v2_device = NULL, NULL }, - NULL, - 0, &razer_cynosa_chroma_v2_layout }; @@ -1653,8 +2058,6 @@ static const razer_device cynosa_lite_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -1690,8 +2093,6 @@ static const razer_device ornata_chroma_device = NULL, NULL }, - NULL, - 0, &razer_full_size_shifted_layout }; @@ -1727,8 +2128,6 @@ static const razer_device ornata_chroma_v2_device = NULL, NULL }, - NULL, - 0, &razer_ornata_chroma_v2_layout }; @@ -1764,8 +2163,6 @@ static const razer_device ornata_v3_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -1801,8 +2198,41 @@ static const razer_device ornata_v3_rev2_device = NULL, NULL }, - NULL, - 0, + NULL +}; + +/*-------------------------------------------------------------*\ +| Razer Ornata V3 TKL 1532:02A3 | +| | +| Zone "Keyboard" | +| Single | +| 1 LED | +\*-------------------------------------------------------------*/ +static const razer_zone ornata_v3_tkl_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_SINGLE, + 1, + 8 +}; + +static const razer_device ornata_v3_tkl_device = +{ + "Razer Ornata V3 TKL", + RAZER_ORNATA_V3_TKL_PID, + DEVICE_TYPE_KEYBOARD, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 1, + 8, + { + &ornata_v3_tkl_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, NULL }; @@ -1838,11 +2268,43 @@ static const razer_device ornata_v3_x_device = NULL, NULL }, - NULL, - 0, NULL }; +/*-------------------------------------------------------------*\ +| Razer Ornata V3 X Rev2 1532:02A2 | +| | +| Zone "Keyboard" | +| Single | +| 1 LED | +\*-------------------------------------------------------------*/ +static const razer_zone ornata_v3_x_v2_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_device ornata_v3_x_v2_device = +{ + "Razer Ornata V3 X Rev2", + RAZER_ORNATA_V3_X_REV2_PID, + DEVICE_TYPE_KEYBOARD, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 1, + 1, + { + &ornata_v3_x_v2_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, + NULL +}; /*-------------------------------------------------------------*\ | Razer DeathStalker Chroma | @@ -1876,8 +2338,6 @@ static const razer_device deathstalker_chroma_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -1913,11 +2373,66 @@ static const razer_device deathstalker_v2_device = NULL, NULL }, - NULL, - 0, &razer_deathstalker_v2_layout }; +/*-------------------------------------------------------------*\ +| Razer DeathStalker V2 Pro TKL (Wired) 1532:0298 | +| (Wireless) 1532:0296 | +| (Bluetooth) 1532:0297 | +| | +| Zone "Keyboard" | +| Matrix | +| 84 LEDs | +\*-------------------------------------------------------------*/ +static const razer_zone deathstalker_v2_pro_tkl_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 6, + 17 +}; + +static const razer_device deathstalker_v2_pro_tkl_wired_device = +{ + "Razer DeathStalker V2 Pro TKL (Wired)", + RAZER_DEATHSTALKER_V2_PRO_TKL_WIRED_PID, + DEVICE_TYPE_KEYBOARD, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 6, + 17, + { + &deathstalker_v2_pro_tkl_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, + &razer_deathstalker_v2_pro_tkl_layout +}; + +static const razer_device deathstalker_v2_pro_tkl_wireless_device = +{ + "Razer DeathStalker V2 Pro TKL (Wireless)", + RAZER_DEATHSTALKER_V2_PRO_TKL_WIRELESS_PID, + DEVICE_TYPE_KEYBOARD, + RAZER_MATRIX_TYPE_EXTENDED, + 0x9F, + 6, + 17, + { + &deathstalker_v2_pro_tkl_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, + &razer_deathstalker_v2_pro_tkl_layout +}; + /*-------------------------------------------------------------*\ | Razer DeathStalker V2 Pro (Wireless) 1532:0290 | | | @@ -1950,8 +2465,6 @@ static const razer_device deathstalker_v2_pro_wireless_device = NULL, NULL }, - NULL, - 0, &razer_deathstalker_v2_pro_layout }; @@ -1987,8 +2500,6 @@ static const razer_device deathstalker_v2_pro_wired_device = NULL, NULL }, - NULL, - 0, &razer_deathstalker_v2_pro_layout }; @@ -2024,8 +2535,6 @@ static const razer_device huntsman_device = NULL, NULL }, - NULL, - 0, &razer_full_size_shifted_layout }; @@ -2073,8 +2582,6 @@ static const razer_device huntsman_elite_device = NULL, NULL }, - NULL, - 0, &razer_huntsman_common_layout }; @@ -2122,8 +2629,6 @@ static const razer_device huntsman_v2_analog_device = NULL, NULL }, - NULL, - 0, &razer_huntsman_common_layout }; @@ -2159,8 +2664,41 @@ static const razer_device huntsman_mini_device = NULL, NULL }, - NULL, - 0, + &razer_huntsman_mini_layout +}; + +/*-------------------------------------------------------------*\ +| Razer Huntsman Mini Analog 1532:0282 | +| | +| Zone "Keyboard" | +| Matrix | +| 5 Rows, 15 Columns | +\*-------------------------------------------------------------*/ +static const razer_zone huntsman_mini_analog_keyboard_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 5, + 15 +}; + +static const razer_device huntsman_mini_analog_device = +{ + "Razer Huntsman Mini Analog", + RAZER_HUNTSMAN_MINI_ANALOG_PID, + DEVICE_TYPE_KEYBOARD, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 5, + 15, + { + &huntsman_mini_analog_keyboard_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, &razer_huntsman_mini_layout }; @@ -2196,8 +2734,6 @@ static const razer_device huntsman_te_device = NULL, NULL }, - NULL, - 0, &razer_huntsman_te_layout }; @@ -2233,8 +2769,6 @@ static const razer_device huntsman_v2_tkl_device = NULL, NULL }, - NULL, - 0, &razer_huntsman_v2_tkl_layout }; @@ -2270,11 +2804,79 @@ static const razer_device huntsman_v2_device = NULL, NULL }, - NULL, - 0, &razer_huntsman_v2_layout }; +/*-------------------------------------------------------------*\ +| Razer Huntsman V3 Pro 1532:02A6 | +| | +| Zone "Keyboard" | +| Matrix | +| 6 Rows, 22 Columns | +\*-------------------------------------------------------------*/ +static const razer_zone huntsman_v3_pro_keyboard_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 6, + 22 +}; + +static const razer_device huntsman_v3_pro_device = +{ + "Razer Huntsman V3 Pro", + RAZER_HUNTSMAN_V3_PRO_PID, + DEVICE_TYPE_KEYBOARD, + RAZER_MATRIX_TYPE_EXTENDED, + 0x3F, + 6, + 22, + { + &huntsman_v3_pro_keyboard_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, + &razer_huntsman_v3_pro_layout +}; + +/*-------------------------------------------------------------*\ +| Razer Huntsman V3 Pro TKL White 1532:02A7 | +| | +| Zone "Keyboard" | +| Matrix | +| 6 Rows, 19 Columns | +\*-------------------------------------------------------------*/ +static const razer_zone huntsman_v3_pro_tkl_keyboard_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 6, + 19 +}; + +static const razer_device huntsman_v3_pro_tkl_device = +{ + "Razer Huntsman V3 Pro TKL White", + RAZER_HUNTSMAN_V3_PRO_TKL_WHITE_PID, + DEVICE_TYPE_KEYBOARD, + RAZER_MATRIX_TYPE_EXTENDED, + 0x3F, + 6, + 19, + { + &huntsman_v3_pro_tkl_keyboard_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, + &razer_huntsman_v3_pro_tkl_layout +}; + /*-------------------------------------------------------------------------*\ | LAPTOPS | \*-------------------------------------------------------------------------*/ @@ -2298,7 +2900,7 @@ static const razer_device blade_2016_device = { "Razer Blade (2016)", RAZER_BLADE_2016_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -2311,8 +2913,6 @@ static const razer_device blade_2016_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -2335,7 +2935,7 @@ static const razer_device blade_late_2016_device = { "Razer Blade (Late 2016)", RAZER_BLADE_LATE_2016_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -2348,8 +2948,6 @@ static const razer_device blade_late_2016_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -2372,7 +2970,7 @@ static const razer_device blade_15_2018_advanced_device = { "Razer Blade 15 (2018 Advanced)", RAZER_BLADE_2018_ADVANCED_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -2385,8 +2983,6 @@ static const razer_device blade_15_2018_advanced_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -2409,7 +3005,7 @@ static const razer_device blade_15_2018_base_device = { "Razer Blade 15 (2018 Base)", RAZER_BLADE_2018_BASE_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -2422,8 +3018,6 @@ static const razer_device blade_15_2018_base_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -2446,7 +3040,7 @@ static const razer_device blade_15_2018_mercury_device = { "Razer Blade 15 (2018 Mercury)", RAZER_BLADE_2018_MERCURY_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -2459,8 +3053,6 @@ static const razer_device blade_15_2018_mercury_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -2483,7 +3075,7 @@ static const razer_device blade_15_2019_advanced_device = { "Razer Blade 15 (2019 Advanced)", RAZER_BLADE_2019_ADVANCED_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -2496,8 +3088,6 @@ static const razer_device blade_15_2019_advanced_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -2520,7 +3110,7 @@ static const razer_device blade_15_2019_base_device = { "Razer Blade 15 (2019 Base)", RAZER_BLADE_2019_BASE_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 1, @@ -2533,8 +3123,6 @@ static const razer_device blade_15_2019_base_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -2557,7 +3145,7 @@ static const razer_device blade_15_2019_mercury_device = { "Razer Blade 15 (2019 Mercury)", RAZER_BLADE_2019_MERCURY_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -2570,8 +3158,6 @@ static const razer_device blade_15_2019_mercury_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -2594,7 +3180,7 @@ static const razer_device blade_15_2019_studio_device = { "Razer Blade 15 (2019 Studio)", RAZER_BLADE_2019_STUDIO_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -2607,8 +3193,6 @@ static const razer_device blade_15_2019_studio_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -2631,7 +3215,7 @@ static const razer_device blade_15_2020_advanced_device = { "Razer Blade 15 (2020 Advanced)", RAZER_BLADE_2020_ADVANCED_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -2644,8 +3228,6 @@ static const razer_device blade_15_2020_advanced_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -2668,7 +3250,7 @@ static const razer_device blade_15_2020_base_device = { "Razer Blade 15 (2020 Base)", RAZER_BLADE_2020_BASE_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 1, @@ -2681,8 +3263,6 @@ static const razer_device blade_15_2020_base_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -2705,7 +3285,7 @@ static const razer_device blade_late_2020_device = { "Razer Blade (Late 2020)", RAZER_BLADE_LATE_2020_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -2718,8 +3298,6 @@ static const razer_device blade_late_2020_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -2742,7 +3320,7 @@ static const razer_device blade_15_2021_advanced_device = { "Razer Blade 15 (2021 Advanced)", RAZER_BLADE_2021_ADVANCED_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -2755,8 +3333,6 @@ static const razer_device blade_15_2021_advanced_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -2779,7 +3355,7 @@ static const razer_device blade_15_2021_base_device = { "Razer Blade 15 (2021 Base)", RAZER_BLADE_2021_BASE_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 1, @@ -2792,8 +3368,6 @@ static const razer_device blade_15_2021_base_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -2816,7 +3390,7 @@ static const razer_device blade_15_2021_base_v2_device = { "Razer Blade 15 (2021 Base)", RAZER_BLADE_2021_BASE_V2_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x1F, 1, @@ -2829,8 +3403,6 @@ static const razer_device blade_15_2021_base_v2_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -2853,7 +3425,7 @@ static const razer_device blade_15_late_2021_advanced_device = { "Razer Blade 15 (Late 2021 Advanced)", RAZER_BLADE_LATE_2021_ADVANCED_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -2866,8 +3438,6 @@ static const razer_device blade_15_late_2021_advanced_device = NULL, NULL }, - NULL, - 0, &razer_blade_15_2021_advanced_layout }; @@ -2890,7 +3460,7 @@ static const razer_device blade_14_2021_device = { "Razer Blade 14 (2021)", RAZER_BLADE_14_2021_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -2903,8 +3473,6 @@ static const razer_device blade_14_2021_device = NULL, NULL }, - NULL, - 0, &razer_laptop_common_layout }; @@ -2927,7 +3495,7 @@ static const razer_device blade_14_2022_device = { "Razer Blade 14 (2022)", RAZER_BLADE_14_2022_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x1F, 6, @@ -2940,8 +3508,41 @@ static const razer_device blade_14_2022_device = NULL, NULL }, - NULL, - 0, + &razer_laptop_with_spacebar_layout +}; + +/*-------------------------------------------------------------*\ +| Razer Blade 14 (2023) 1532:029D | +| | +| Zone "Keyboard" | +| Matrix | +| 6 Rows, 16 Columns | +\*-------------------------------------------------------------*/ +static const razer_zone blade_14_2023_zone = +{ + ZONE_EN_KEYBOARD, + ZONE_TYPE_MATRIX, + 6, + 16 +}; + +static const razer_device blade_14_2023_device = +{ + "Razer Blade 14 (2023)", + RAZER_BLADE_14_2023_PID, + DEVICE_TYPE_LAPTOP, + RAZER_MATRIX_TYPE_STANDARD, + 0x1F, + 6, + 16, + { + &blade_14_2023_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, &razer_laptop_with_spacebar_layout }; @@ -2964,7 +3565,7 @@ static const razer_device blade_15_2022_device = { "Razer Blade 15 (2022)", RAZER_BLADE_15_2022_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x1F, 6, @@ -2977,8 +3578,6 @@ static const razer_device blade_15_2022_device = NULL, NULL }, - NULL, - 0, &razer_blade_15_2022_layout }; @@ -3001,7 +3600,7 @@ static const razer_device book_13_2020_device = { "Razer Book 13 (2020)", RAZER_BOOK_13_2020_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -3014,8 +3613,6 @@ static const razer_device book_13_2020_device = NULL, NULL }, - NULL, - 0, &razer_laptop_common_layout }; @@ -3038,7 +3635,7 @@ static const razer_device blade_pro_2016_device = { "Razer Blade Pro (2016)", RAZER_BLADE_PRO_2016_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -3051,8 +3648,6 @@ static const razer_device blade_pro_2016_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3075,7 +3670,7 @@ static const razer_device blade_pro_2017_device = { "Razer Blade Pro (2017)", RAZER_BLADE_PRO_2017_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -3088,8 +3683,6 @@ static const razer_device blade_pro_2017_device = NULL, NULL }, - NULL, - 0, &razer_blade_pro_2017_layout }; @@ -3112,7 +3705,7 @@ static const razer_device blade_pro_2017_fullhd_device = { "Razer Blade Pro (2017 FullHD)", RAZER_BLADE_PRO_2017_FULLHD_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -3125,8 +3718,6 @@ static const razer_device blade_pro_2017_fullhd_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3148,7 +3739,7 @@ static const razer_device blade_pro_2019_device = { "Razer Blade Pro (2019)", RAZER_BLADE_PRO_2019_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -3161,8 +3752,6 @@ static const razer_device blade_pro_2019_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3185,7 +3774,7 @@ static const razer_device blade_pro_late_2019_device = { "Razer Blade Pro (Late 2019)", RAZER_BLADE_PRO_LATE_2019_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -3198,8 +3787,6 @@ static const razer_device blade_pro_late_2019_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3222,7 +3809,7 @@ static const razer_device blade_pro_17_2020_device = { "Razer Blade Pro 17 (2020)", RAZER_BLADE_PRO_17_2020_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -3235,8 +3822,6 @@ static const razer_device blade_pro_17_2020_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3259,7 +3844,7 @@ static const razer_device blade_pro_17_2021_device = { "Razer Blade Pro 17 (2021)", RAZER_BLADE_PRO_17_2021_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -3272,8 +3857,6 @@ static const razer_device blade_pro_17_2021_device = NULL, NULL }, - NULL, - 0, &razer_blade_17_pro_2021_layout }; @@ -3296,7 +3879,7 @@ static const razer_device blade_stealth_2016_device = { "Razer Blade Stealth (2016)", RAZER_BLADE_STEALTH_2016_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -3309,8 +3892,6 @@ static const razer_device blade_stealth_2016_device = NULL, NULL }, - NULL, - 0, &razer_blade_stealth_2016_layout }; @@ -3333,7 +3914,7 @@ static const razer_device blade_stealth_late_2016_device = { "Razer Blade Stealth (Late 2016)", RAZER_BLADE_STEALTH_LATE_2016_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -3346,8 +3927,6 @@ static const razer_device blade_stealth_late_2016_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3370,7 +3949,7 @@ static const razer_device blade_stealth_2017_device = { "Razer Blade Stealth (2017)", RAZER_BLADE_STEALTH_2017_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -3383,8 +3962,6 @@ static const razer_device blade_stealth_2017_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3407,7 +3984,7 @@ static const razer_device blade_stealth_late_2017_device = { "Razer Blade Stealth (Late 2017)", RAZER_BLADE_STEALTH_LATE_2017_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -3420,8 +3997,6 @@ static const razer_device blade_stealth_late_2017_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3444,7 +4019,7 @@ static const razer_device blade_stealth_2019_device = { "Razer Blade Stealth (2019)", RAZER_BLADE_STEALTH_2019_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 6, @@ -3457,8 +4032,6 @@ static const razer_device blade_stealth_2019_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3481,7 +4054,7 @@ static const razer_device blade_stealth_late_2019_device = { "Razer Blade Stealth (Late 2019)", RAZER_BLADE_STEALTH_LATE_2019_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 1, @@ -3494,8 +4067,6 @@ static const razer_device blade_stealth_late_2019_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3518,7 +4089,7 @@ static const razer_device blade_stealth_2020_device = { "Razer Blade Stealth (2020)", RAZER_BLADE_STEALTH_2020_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 1, @@ -3531,8 +4102,6 @@ static const razer_device blade_stealth_2020_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3555,7 +4124,7 @@ static const razer_device blade_stealth_late_2020_device = { "Razer Blade Stealth (Late 2020)", RAZER_BLADE_STEALTH_LATE_2020_PID, - DEVICE_TYPE_KEYBOARD, + DEVICE_TYPE_LAPTOP, RAZER_MATRIX_TYPE_STANDARD, 0x3F, 1, @@ -3568,8 +4137,6 @@ static const razer_device blade_stealth_late_2020_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3609,8 +4176,6 @@ static const razer_device abyssus_elite_dva_edition_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3646,8 +4211,6 @@ static const razer_device abyssus_essential_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3695,8 +4258,6 @@ static const razer_device basilisk_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3732,8 +4293,6 @@ static const razer_device basilisk_essential_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3794,7 +4353,7 @@ static const razer_device basilisk_ultimate_wired_device = RAZER_BASILISK_ULTIMATE_WIRED_PID, DEVICE_TYPE_MOUSE, RAZER_MATRIX_TYPE_EXTENDED, - 0x3F, + 0x1F, 1, 14, { @@ -3805,8 +4364,6 @@ static const razer_device basilisk_ultimate_wired_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3867,7 +4424,7 @@ static const razer_device basilisk_ultimate_wireless_device = RAZER_BASILISK_ULTIMATE_WIRELESS_PID, DEVICE_TYPE_MOUSE, RAZER_MATRIX_TYPE_EXTENDED, - 0x3F, + 0x1F, 1, 14, { @@ -3878,8 +4435,6 @@ static const razer_device basilisk_ultimate_wireless_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3927,8 +4482,6 @@ static const razer_device basilisk_v2_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -3988,8 +4541,65 @@ static const razer_device basilisk_v3_device = NULL, NULL }, - NULL, - 0, + NULL +}; + +/*-------------------------------------------------------------*\ +| Razer Basilisk V3 35K 1532:00CB | +| | +| Zone "Scroll Wheel" | +| Single | +| 1 LED | +| | +| Zone "Logo" | +| Single | +| 1 LED | +| | +| Zone "LED Strip" | +| Linear | +| 9 LED | +\*-------------------------------------------------------------*/ +static const razer_zone basilisk_v3_35k_scroll_wheel_zone = +{ + "Scroll Wheel", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_zone basilisk_v3_35k_logo_zone = +{ + "Logo", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_zone basilisk_v3_35k_ledstrip_zone = +{ + "LED Strip", + ZONE_TYPE_LINEAR, + 1, + 9 +}; + +static const razer_device basilisk_v3_35k_device = +{ + "Razer Basilisk V3 35K", + RAZER_BASILISK_V3_35K_PID, + DEVICE_TYPE_MOUSE, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 1, + 11, + { + &basilisk_v3_35k_logo_zone, + &basilisk_v3_35k_scroll_wheel_zone, + &basilisk_v3_35k_ledstrip_zone, + NULL, + NULL, + NULL + }, NULL }; @@ -4006,9 +4616,9 @@ static const razer_device basilisk_v3_device = | | | Zone "LED Strip" | | Linear | -| 9 LED | +| 11 LED | \*-------------------------------------------------------------*/ -static const razer_zone basilisk_v3_scroll_pro_wired_wheel_zone = +static const razer_zone basilisk_v3_pro_wired_scroll_wheel_zone = { "Scroll Wheel", ZONE_TYPE_SINGLE, @@ -4029,7 +4639,7 @@ static const razer_zone basilisk_v3_pro_wired_ledstrip_zone = "LED Strip", ZONE_TYPE_LINEAR, 1, - 9 + 11 }; static const razer_device basilisk_v3_pro_wired_device = @@ -4040,17 +4650,15 @@ static const razer_device basilisk_v3_pro_wired_device = RAZER_MATRIX_TYPE_EXTENDED, 0x1F, 1, - 11, + 13, { - &basilisk_v3_logo_zone, - &basilisk_v3_scroll_wheel_zone, - &basilisk_v3_ledstrip_zone, + &basilisk_v3_pro_wired_scroll_wheel_zone, + &basilisk_v3_pro_wired_logo_zone, + &basilisk_v3_pro_wired_ledstrip_zone, NULL, NULL, NULL }, - NULL, - 0, NULL }; @@ -4067,9 +4675,9 @@ static const razer_device basilisk_v3_pro_wired_device = | | | Zone "LED Strip" | | Linear | -| 9 LED | +| 11 LED | \*-------------------------------------------------------------*/ -static const razer_zone basilisk_v3_scroll_pro_wireless_wheel_zone = +static const razer_zone basilisk_v3_pro_wireless_scroll_wheel_zone = { "Scroll Wheel", ZONE_TYPE_SINGLE, @@ -4090,7 +4698,7 @@ static const razer_zone basilisk_v3_pro_wireless_ledstrip_zone = "LED Strip", ZONE_TYPE_LINEAR, 1, - 9 + 11 }; static const razer_device basilisk_v3_pro_wireless_device = @@ -4101,17 +4709,132 @@ static const razer_device basilisk_v3_pro_wireless_device = RAZER_MATRIX_TYPE_EXTENDED, 0x1F, 1, - 11, + 13, { - &basilisk_v3_logo_zone, - &basilisk_v3_scroll_wheel_zone, - &basilisk_v3_ledstrip_zone, + &basilisk_v3_pro_wireless_scroll_wheel_zone, + &basilisk_v3_pro_wireless_logo_zone, + &basilisk_v3_pro_wireless_ledstrip_zone, + NULL, + NULL, + NULL + }, + NULL +}; +/*-------------------------------------------------------------*\ +| Razer Basilisk V3 PRO 35K Wired 1532:00CC | +| | +| Zone "Scroll Wheel" | +| Single | +| 1 LED | +| | +| Zone "Logo" | +| Single | +| 1 LED | +| | +| Zone "LED Strip" | +| Linear | +| 11 LED | +\*-------------------------------------------------------------*/ +static const razer_zone basilisk_v3_pro_35k_wired_scroll_wheel_zone = +{ + "Scroll Wheel", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_zone basilisk_v3_pro_35k_wired_logo_zone = +{ + "Logo", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_zone basilisk_v3_pro_35k_wired_ledstrip_zone = +{ + "LED Strip", + ZONE_TYPE_LINEAR, + 1, + 11 +}; + +static const razer_device basilisk_v3_pro_35k_wired_device = +{ + "Razer Basilisk V3 Pro 35K (Wired)", + RAZER_BASILISK_V3_PRO_35K_WIRED_PID, + DEVICE_TYPE_MOUSE, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 1, + 13, + { + &basilisk_v3_pro_35k_wired_scroll_wheel_zone, + &basilisk_v3_pro_35k_wired_logo_zone, + &basilisk_v3_pro_35k_wired_ledstrip_zone, + NULL, + NULL, + NULL + }, + NULL +}; + +/*-------------------------------------------------------------*\ +| Razer Basilisk V3 PRO 35K Wireless 1532:00CD | +| | +| Zone "Scroll Wheel" | +| Single | +| 1 LED | +| | +| Zone "Logo" | +| Single | +| 1 LED | +| | +| Zone "LED Strip" | +| Linear | +| 11 LED | +\*-------------------------------------------------------------*/ +static const razer_zone basilisk_v3_pro_35k_wireless_scroll_wheel_zone = +{ + "Scroll Wheel", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_zone basilisk_v3_pro_35k_wireless_logo_zone = +{ + "Logo", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_zone basilisk_v3_pro_35k_wireless_ledstrip_zone = +{ + "LED Strip", + ZONE_TYPE_LINEAR, + 1, + 11 +}; + +static const razer_device basilisk_v3_pro_35k_wireless_device = +{ + "Razer Basilisk V3 Pro 35K (Wireless)", + RAZER_BASILISK_V3_PRO_35K_WIRELESS_PID, + DEVICE_TYPE_MOUSE, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 1, + 13, + { + &basilisk_v3_pro_35k_wireless_scroll_wheel_zone, + &basilisk_v3_pro_35k_wireless_logo_zone, + &basilisk_v3_pro_35k_wireless_ledstrip_zone, NULL, NULL, NULL }, - NULL, - 0, NULL }; @@ -4128,9 +4851,9 @@ static const razer_device basilisk_v3_pro_wireless_device = | | | Zone "LED Strip" | | Linear | -| 9 LED | +| 11 LED | \*-------------------------------------------------------------*/ -static const razer_zone basilisk_v3_scroll_pro_bluetooth_wheel_zone = +static const razer_zone basilisk_v3_pro_bluetooth_scroll_wheel_zone = { "Scroll Wheel", ZONE_TYPE_SINGLE, @@ -4151,7 +4874,7 @@ static const razer_zone basilisk_v3_pro_bluetooth_ledstrip_zone = "LED Strip", ZONE_TYPE_LINEAR, 1, - 9 + 11 }; static const razer_device basilisk_v3_pro_bluetooth_device = @@ -4162,17 +4885,203 @@ static const razer_device basilisk_v3_pro_bluetooth_device = RAZER_MATRIX_TYPE_EXTENDED, 0x1F, 1, - 11, + 13, { - &basilisk_v3_logo_zone, - &basilisk_v3_scroll_wheel_zone, - &basilisk_v3_ledstrip_zone, + &basilisk_v3_pro_bluetooth_scroll_wheel_zone, + &basilisk_v3_pro_bluetooth_logo_zone, + &basilisk_v3_pro_bluetooth_ledstrip_zone, + NULL, + NULL, + NULL + }, + NULL +}; + +/*-------------------------------------------------------------*\ +| Razer Basilisk V3 X HyperSpeed 1532:00B9 | +| | +| Zone "Scroll Wheel" | +| Single | +| 1 LED | +\*-------------------------------------------------------------*/ +static const razer_zone basilisk_v3_x_hyperspeed_scroll_wheel_zone = +{ + "Scroll Wheel", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_device basilisk_v3_x_hyperspeed_device = +{ + "Razer Basilisk V3 X HyperSpeed", + RAZER_BASILISK_V3_X_HYPERSPEED_PID, + DEVICE_TYPE_MOUSE, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 1, + 1, + { + &basilisk_v3_x_hyperspeed_scroll_wheel_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, + NULL +}; + +/*-------------------------------------------------------------*\ +| Razer Cobra 1532:00A3 | +| | +| Zone "Logo" | +| Single | +| 1 LED | +\*-------------------------------------------------------------*/ +static const razer_zone cobra_logo_zone = +{ + "Logo", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_device cobra_device = +{ + "Razer Cobra", + RAZER_COBRA_PID, + DEVICE_TYPE_MOUSE, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 1, + 1, + { + &cobra_logo_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, + NULL +}; + +/*-------------------------------------------------------------*\ +| Razer Cobra Pro Wired 1532:00AF | +| | +| Zone "Logo" | +| Single | +| 1 LED | +| | +| Zone "Scroll Wheel" | +| Single | +| 1 LED | +| | +| Zone "Underglow" | +| Linear | +| 11 LED | +\*-------------------------------------------------------------*/ +static const razer_zone cobra_pro_wired_logo_zone = +{ + "Logo", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_zone cobra_pro_wired_scroll_wheel_zone = +{ + "Scroll Wheel", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_zone cobra_pro_wired_underglow_zone = +{ + "Underglow", + ZONE_TYPE_LINEAR, + 1, + 9 +}; + +static const razer_device cobra_pro_wired_device = +{ + "Razer Cobra Pro (Wired)", + RAZER_COBRA_PRO_WIRED_PID, + DEVICE_TYPE_MOUSE, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 1, + 11, + { + &cobra_pro_wired_logo_zone, + &cobra_pro_wired_scroll_wheel_zone, + &cobra_pro_wired_underglow_zone, + NULL, + NULL, + NULL + }, + NULL +}; + +/*-------------------------------------------------------------*\ +| Razer Cobra Pro Wireless 1532:00B0 | +| | +| Zone "Logo" | +| Single | +| 1 LED | +| | +| Zone "Scroll Wheel" | +| Single | +| 1 LED | +| | +| Zone "Underglow" | +| Linear | +| 11 LED | +\*-------------------------------------------------------------*/ +static const razer_zone cobra_pro_wireless_logo_zone = +{ + "Logo", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_zone cobra_pro_wireless_scroll_wheel_zone = +{ + "Scroll Wheel", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_zone cobra_pro_wireless_underglow_zone = +{ + "Underglow", + ZONE_TYPE_LINEAR, + 1, + 9 +}; + +static const razer_device cobra_pro_wireless_device = +{ + "Razer Cobra Pro (Wireless)", + RAZER_COBRA_PRO_WIRELESS_PID, + DEVICE_TYPE_MOUSE, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 1, + 11, + { + &cobra_pro_wireless_logo_zone, + &cobra_pro_wireless_scroll_wheel_zone, + &cobra_pro_wireless_underglow_zone, NULL, NULL, NULL }, - NULL, - 0, NULL }; @@ -4220,8 +5129,6 @@ static const razer_device deathadder_chroma_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -4269,8 +5176,6 @@ static const razer_device deathadder_elite_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -4318,8 +5223,6 @@ static const razer_device deathadder_essential_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -4367,8 +5270,6 @@ static const razer_device deathadder_essential_v2_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -4416,8 +5317,6 @@ static const razer_device deathadder_essential_white_edition_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -4454,7 +5353,7 @@ static const razer_device deathadder_v2_device = RAZER_DEATHADDER_V2_PID, DEVICE_TYPE_MOUSE, RAZER_MATRIX_TYPE_EXTENDED, - 0x3F, + 0x1F, 1, 2, { @@ -4465,8 +5364,6 @@ static const razer_device deathadder_v2_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -4502,8 +5399,6 @@ static const razer_device deathadder_v2_mini_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -4539,8 +5434,6 @@ static const razer_device deathadder_v2_pro_wired_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -4576,8 +5469,6 @@ static const razer_device deathadder_v2_pro_wireless_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -4637,8 +5528,6 @@ static const razer_device diamondback_chroma_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -4710,8 +5599,6 @@ static const razer_device lancehead_2017_wired_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -4783,8 +5670,6 @@ static const razer_device lancehead_2017_wireless_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -4856,8 +5741,6 @@ static const razer_device lancehead_2019_wired_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -4929,8 +5812,6 @@ static const razer_device lancehead_2019_wireless_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5002,8 +5883,41 @@ static const razer_device lancehead_te_device = NULL, NULL }, - NULL, - 0, + NULL +}; + +/*-------------------------------------------------------------*\ +| Razer Leviathan V2 1532:0532 | +| | +| Zone "Speaker Underglow" | +| Linear | +| 18 LEDs | +\*-------------------------------------------------------------*/ +static const razer_zone leviathan_v2_speaker_zone = +{ + "Speaker Underglow", + ZONE_TYPE_LINEAR, + 2, + 9 +}; + +static const razer_device leviathan_v2_device = +{ + "Razer Leviathan V2", + RAZER_LEVIATHAN_V2_PID, + DEVICE_TYPE_SPEAKER, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 2, + 9, + { + &leviathan_v2_speaker_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, NULL }; @@ -5039,8 +5953,6 @@ static const razer_device leviathan_v2x_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5076,8 +5988,6 @@ static const razer_device mamba_2012_wired_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5113,8 +6023,6 @@ static const razer_device mamba_2012_wireless_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5150,8 +6058,6 @@ static const razer_device mamba_2015_wired_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5187,8 +6093,6 @@ static const razer_device mamba_2015_wireless_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5236,8 +6140,6 @@ static const razer_device mamba_2018_wired_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5286,8 +6188,6 @@ static const razer_device mamba_2018_wireless_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5360,8 +6260,6 @@ static const razer_device mamba_elite_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5433,22 +6331,68 @@ static const razer_device mamba_te_device = NULL, NULL }, - NULL, - 0, NULL }; /*-------------------------------------------------------------*\ -| Razer Naga Chroma | +| Razer Mamba Hyperflux (Wired) | +| | +| Zone "Scroll Wheel" | +| Single | +| 1 LED | | | | Zone "Logo" | | Single | | 1 LED | +\*-------------------------------------------------------------*/ + +static const razer_zone mamba_hyperflux_scroll_wheel_zone = +{ + "Scroll Wheel", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_zone mamba_hyperflux_logo_zone = +{ + "Logo", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_device mamba_hyperflux_device = +{ + "Razer Mamba Hyperflux (Wired)", + RAZER_MAMBA_HYPERFLUX_PID, + DEVICE_TYPE_MOUSE, + RAZER_MATRIX_TYPE_EXTENDED, + 0x3F, + 1, + 2, + { + &mamba_hyperflux_scroll_wheel_zone, + &mamba_hyperflux_logo_zone, + NULL, + NULL, + NULL, + NULL + }, + NULL +}; + +/*-------------------------------------------------------------*\ +| Razer Naga Chroma 1532:0053 | | | | Zone "Scroll Wheel" | | Single | | 1 LED | | | +| Zone "Logo" | +| Single | +| 1 LED | +| | | Zone "Numpad" | | Single | | 1 LED | @@ -5487,15 +6431,13 @@ static const razer_device naga_chroma_device = 1, 3, { - &naga_chroma_logo_zone, &naga_chroma_scroll_wheel_zone, + &naga_chroma_logo_zone, &naga_chroma_numpad_zone, NULL, NULL, NULL }, - NULL, - 0, NULL }; @@ -5555,8 +6497,6 @@ static const razer_device naga_classic_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5616,8 +6556,6 @@ static const razer_device naga_hex_v2_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5677,8 +6615,6 @@ static const razer_device naga_left_handed_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5738,8 +6674,6 @@ static const razer_device naga_trinity_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5799,8 +6733,6 @@ static const razer_device naga_pro_wired_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5821,8 +6753,73 @@ static const razer_device naga_pro_wireless_device = NULL, NULL }, - NULL, - 0, + NULL +}; + +/*-------------------------------------------------------------*\ +| Razer Naga Pro V2 1532:00A7 (wired) 1532:00A8 (wireless) | +| | +| Zone "Logo" | +| Single | +| 1 LED | +| | +| Zone "Numpad" | +| Single | +| 1 LED | +\*-------------------------------------------------------------*/ +static const razer_zone naga_pro_v2_logo_zone = +{ + "Logo", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_zone naga_pro_v2_numpad_zone = +{ + "Numpad", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_device naga_pro_v2_wired_device = +{ + "Razer Naga Pro V2 (Wired)", + RAZER_NAGA_PRO_V2_WIRED_PID, + DEVICE_TYPE_MOUSE, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 1, + 2, + { + &naga_pro_v2_logo_zone, + &naga_pro_v2_numpad_zone, + NULL, + NULL, + NULL, + NULL + }, + NULL +}; + +static const razer_device naga_pro_v2_wireless_device = +{ + "Razer Naga Pro V2 (Wireless)", + RAZER_NAGA_PRO_V2_WIRELESS_PID, + DEVICE_TYPE_MOUSE, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 1, + 2, + { + &naga_pro_v2_logo_zone, + &naga_pro_v2_numpad_zone, + NULL, + NULL, + NULL, + NULL + }, NULL }; @@ -5858,8 +6855,6 @@ static const razer_device viper_8khz_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5895,8 +6890,6 @@ static const razer_device viper_mini_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5932,8 +6925,6 @@ static const razer_device viper_ultimate_wired_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -5969,8 +6960,6 @@ static const razer_device viper_ultimate_wireless_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -6006,8 +6995,6 @@ static const razer_device viper_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -6055,8 +7042,6 @@ static const razer_device naga_epic_chroma_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -6096,8 +7081,6 @@ static const razer_device orbweaver_chroma_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -6133,8 +7116,6 @@ static const razer_device tartarus_chroma_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -6178,13 +7159,6 @@ static const razer_device tartarus_pro_device = NULL, NULL }, - /*-------------------------------------------------------------*\ - Need to be Implemented to read upper defined keymap(Not working now) - tartarus_pro_keymap, - TARTARUS_PRO_KEYMAP_SIZE - \*-------------------------------------------------------------*/ - NULL, - 0, NULL }; @@ -6220,8 +7194,6 @@ static const razer_device tartarus_v2_device = NULL, NULL }, - NULL, - 0, &razer_tartarus_v2_layout }; @@ -6261,26 +7233,49 @@ static const razer_device firefly_device = NULL, NULL }, - NULL, - 0, NULL }; /*-------------------------------------------------------------*\ | Razer Firefly Hyperflux | | | -| Zone "LED Strip" | +| Zone "Scroll Wheel" | +| Single | +| 1 LED | +| | +| Zone "Logo" | +| Single | +| 1 LED | +| | +| Zone "Mousemat" | | Linear | -| 1 LEDs | +| 12 LEDs | \*-------------------------------------------------------------*/ -static const razer_zone firefly_hyperflux_zone = + +static const razer_zone firefly_hyperflux_scroll_wheel_zone = { - "LED Strip", + "Scroll Wheel", ZONE_TYPE_SINGLE, 1, 1 }; +static const razer_zone firefly_hyperflux_logo_zone = +{ + "Logo", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_zone firefly_hyperflux_mousemat_zone = +{ + "Mousemat", + ZONE_TYPE_LINEAR, + 1, + 12 +}; + static const razer_device firefly_hyperflux_device = { "Razer Firefly Hyperflux", @@ -6289,17 +7284,15 @@ static const razer_device firefly_hyperflux_device = RAZER_MATRIX_TYPE_EXTENDED, 0x3F, 1, - 1, + 14, { - &firefly_hyperflux_zone, - NULL, - NULL, + &firefly_hyperflux_scroll_wheel_zone, + &firefly_hyperflux_logo_zone, + &firefly_hyperflux_mousemat_zone, NULL, NULL, NULL }, - NULL, - 0, NULL }; @@ -6307,7 +7300,7 @@ static const razer_device firefly_hyperflux_device = | Razer Firefly V2 | | | | Zone "LED Strip" | -| Matrix | +| Linear | | 19 LEDs | \*-------------------------------------------------------------*/ static const razer_zone firefly_v2_zone = @@ -6335,8 +7328,41 @@ static const razer_device firefly_v2_device = NULL, NULL }, - NULL, - 0, + NULL +}; + +/*-------------------------------------------------------------*\ +| Razer Firefly Pro V2 | +| | +| Zone "LED Strip" | +| Linear | +| 17 LEDs | +\*-------------------------------------------------------------*/ +static const razer_zone firefly_v2_pro_zone = +{ + "LED Strip", + ZONE_TYPE_LINEAR, + 1, + 17 +}; + +static const razer_device firefly_v2_pro_device = +{ + "Razer Firefly V2 Pro", + RAZER_FIREFLY_V2_PRO_PID, + DEVICE_TYPE_MOUSEMAT, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 1, + 17, + { + &firefly_v2_pro_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, NULL }; @@ -6372,8 +7398,41 @@ static const razer_device goliathus_device = NULL, NULL }, - NULL, - 0, + NULL +}; + +/*-------------------------------------------------------------*\ +| Razer Goliathus Chroma 3XL 1532:0C06 | +| | +| Zone "LED Strip" | +| Single | +| 1 LED | +\*-------------------------------------------------------------*/ +static const razer_zone goliathus_chroma_3xl_zone = +{ + "LED Strip", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_device goliathus_chroma_3xl_device = +{ + "Razer Goliathus Chroma 3XL", + RAZER_GOLIATHUS_CHROMA_3XL_PID, + DEVICE_TYPE_MOUSEMAT, + RAZER_MATRIX_TYPE_EXTENDED, + 0x1F, + 1, + 1, + { + &goliathus_chroma_3xl_zone, + NULL, + NULL, + NULL, + NULL, + NULL + }, NULL }; @@ -6409,8 +7468,6 @@ static const razer_device goliathus_extended_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -6446,8 +7503,6 @@ static const razer_device strider_chroma_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -6487,8 +7542,6 @@ static const razer_device kraken_chroma_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -6524,8 +7577,6 @@ static const razer_device kraken_v2_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -6561,8 +7612,6 @@ static const razer_device kraken_ultimate_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -6598,8 +7647,57 @@ static const razer_device kraken_kitty_device = NULL, NULL }, - NULL, - 0, + NULL +}; + +/*-------------------------------------------------------------*\ +| Razer Kraken Kitty Edition V2 1532:0560 | +| | +| Zone "Headset" | +| Matrix | +| 4 LED | +\*-------------------------------------------------------------*/ +static const razer_zone kraken_kitty_black_v2_zone = +{ + "Cat ears", + ZONE_TYPE_LINEAR, + 1, + 2 +}; + +static const razer_zone kraken_kitty_black_v2_headset_left_zone = +{ + "Headset Left", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_zone kraken_kitty_black_v2_headset_right_zone = +{ + "Headset Right", + ZONE_TYPE_SINGLE, + 1, + 1 +}; + +static const razer_device kraken_kitty_black_v2_device = +{ + "Razer Kraken Kitty Black Edition V2", + RAZER_KRAKEN_KITTY_BLACK_EDITION_V2_PID, + DEVICE_TYPE_HEADSET, + RAZER_MATRIX_TYPE_EXTENDED, + 0x3F, + 1, + 4, + { + &kraken_kitty_black_v2_headset_left_zone, + &kraken_kitty_black_v2_headset_right_zone, + &kraken_kitty_black_v2_zone, + NULL, + NULL, + NULL + }, NULL }; @@ -6659,8 +7757,6 @@ static const razer_device tiamat_71_v2_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -6712,8 +7808,6 @@ static const razer_device core_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -6761,8 +7855,6 @@ static const razer_device core_x_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -6798,8 +7890,6 @@ static const razer_device mug_holder_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -6895,8 +7985,6 @@ static const razer_device chromaargb_device = &chromaargb_zone_5, &chromaargb_zone_6 }, - NULL, - 0, NULL }; @@ -6968,8 +8056,6 @@ static const razer_device chromahdk_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -7017,8 +8103,6 @@ static const razer_device chroma_pc_case_lighting_kit_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -7054,8 +8138,6 @@ static const razer_device base_station_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -7091,8 +8173,6 @@ static const razer_device mouse_bungee_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -7128,8 +8208,6 @@ static const razer_device base_station_v2_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -7165,8 +8243,6 @@ static const razer_device laptop_stand_chroma_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -7202,8 +8278,6 @@ static const razer_device laptop_stand_chroma_v2_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -7239,8 +8313,6 @@ static const razer_device mouse_dock_chroma_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -7276,8 +8348,6 @@ static const razer_device mouse_dock_pro_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -7326,8 +8396,6 @@ static const razer_device nommo_pro_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -7376,8 +8444,6 @@ static const razer_device nommo_chroma_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -7414,8 +8480,6 @@ static const razer_device charging_pad_chroma_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -7452,8 +8516,6 @@ static const razer_device o11_dynamic_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -7490,8 +8552,6 @@ static const razer_device seiren_emote_device = NULL, NULL }, - NULL, - 0, NULL }; @@ -7528,8 +8588,78 @@ static const razer_device thunderbolt_4_dock_chroma_device = NULL, NULL }, - NULL, - 0, + NULL +}; + +/*-------------------------------------------------------------*\ +| Razer Hanbo Chroma | +| | +| Zone "Pump" | +| Linear | +| 16 LEDs | +| | +| Zone "Fan 1" | +| Linear | +| 18 LEDs | +| | +| Zone "Fan 2" | +| Linear | +| 18 LEDs | +| | +| Zone "Fan 3" | +| Linear | +| 18 LEDs | +| | +\*-------------------------------------------------------------*/ +static const razer_zone hanbo_chroma_pump_zone = +{ + "Pump", + ZONE_TYPE_LINEAR, + 1, + 16 +}; + +static const razer_zone hanbo_chroma_fan_one_zone = +{ + "Fan 1", + ZONE_TYPE_LINEAR, + 1, + 18 +}; + +static const razer_zone hanbo_chroma_fan_two_zone = +{ + "Fan 2", + ZONE_TYPE_LINEAR, + 1, + 18 +}; + +static const razer_zone hanbo_chroma_fan_three_zone = +{ + "Fan 3", + ZONE_TYPE_LINEAR, + 1, + 18 +}; + +static const razer_device hanbo_chroma_device = +{ + "Razer Hanbo Chroma", + RAZER_HANBO_CHROMA_PID, + DEVICE_TYPE_COOLER, + RAZER_MATRIX_TYPE_EXTENDED, + 0x3F, + 1, + 70, + { + &hanbo_chroma_pump_zone, + &hanbo_chroma_fan_one_zone, + &hanbo_chroma_fan_two_zone, + &hanbo_chroma_fan_three_zone, + NULL, + NULL + }, NULL }; @@ -7554,6 +8684,10 @@ const razer_device* razer_device_list[] = &blackwidow_v3_tkl_device, &blackwidow_v3_mini_wired_device, &blackwidow_v3_mini_wireless_device, + &blackwidow_v4_device, + &blackwidow_v4_pro_device, + &blackwidow_v4_pro_75_wired_device, + &blackwidow_v4_x_device, &blackwidow_x_chroma_device, &blackwidow_x_chroma_te_device, &cynosa_chroma_device, @@ -7561,20 +8695,27 @@ const razer_device* razer_device_list[] = &cynosa_lite_device, &deathstalker_chroma_device, &deathstalker_v2_device, + &deathstalker_v2_pro_tkl_wired_device, + &deathstalker_v2_pro_tkl_wireless_device, &deathstalker_v2_pro_wired_device, &deathstalker_v2_pro_wireless_device, &huntsman_device, &huntsman_elite_device, &huntsman_mini_device, + &huntsman_mini_analog_device, &huntsman_te_device, &huntsman_v2_device, &huntsman_v2_analog_device, &huntsman_v2_tkl_device, + &huntsman_v3_pro_device, + &huntsman_v3_pro_tkl_device, &ornata_chroma_device, &ornata_chroma_v2_device, &ornata_v3_device, &ornata_v3_rev2_device, + &ornata_v3_tkl_device, &ornata_v3_x_device, + &ornata_v3_x_v2_device, /*-----------------------------------------------------------------*\ | LAPTOPS | \*-----------------------------------------------------------------*/ @@ -7596,6 +8737,7 @@ const razer_device* razer_device_list[] = &blade_15_late_2021_advanced_device, &blade_14_2021_device, &blade_14_2022_device, + &blade_14_2023_device, &blade_15_2022_device, &book_13_2020_device, &blade_pro_2016_device, @@ -7605,7 +8747,6 @@ const razer_device* razer_device_list[] = &blade_pro_late_2019_device, &blade_pro_17_2020_device, &blade_pro_17_2021_device, - &blade_stealth_2019_device, &blade_stealth_2016_device, &blade_stealth_late_2016_device, &blade_stealth_2017_device, @@ -7625,9 +8766,16 @@ const razer_device* razer_device_list[] = &basilisk_ultimate_wireless_device, &basilisk_v2_device, &basilisk_v3_device, + &basilisk_v3_35k_device, &basilisk_v3_pro_wired_device, &basilisk_v3_pro_wireless_device, + &basilisk_v3_pro_35k_wired_device, + &basilisk_v3_pro_35k_wireless_device, &basilisk_v3_pro_bluetooth_device, + &basilisk_v3_x_hyperspeed_device, + &cobra_device, + &cobra_pro_wired_device, + &cobra_pro_wireless_device, &deathadder_chroma_device, &deathadder_elite_device, &deathadder_essential_device, @@ -7651,6 +8799,7 @@ const razer_device* razer_device_list[] = &mamba_2018_wireless_device, &mamba_te_device, &mamba_elite_device, + &mamba_hyperflux_device, &naga_chroma_device, &naga_classic_device, &naga_epic_chroma_device, @@ -7659,6 +8808,8 @@ const razer_device* razer_device_list[] = &naga_trinity_device, &naga_pro_wired_device, &naga_pro_wireless_device, + &naga_pro_v2_wired_device, + &naga_pro_v2_wireless_device, &viper_8khz_device, &viper_mini_device, &viper_ultimate_wired_device, @@ -7677,6 +8828,8 @@ const razer_device* razer_device_list[] = &firefly_device, &firefly_hyperflux_device, &firefly_v2_device, + &firefly_v2_pro_device, + &goliathus_chroma_3xl_device, &goliathus_device, &goliathus_extended_device, &strider_chroma_device, @@ -7687,6 +8840,7 @@ const razer_device* razer_device_list[] = &kraken_v2_device, &kraken_ultimate_device, &kraken_kitty_device, + &kraken_kitty_black_v2_device, &tiamat_71_v2_device, /*-----------------------------------------------------------------*\ | OTHER | @@ -7702,6 +8856,7 @@ const razer_device* razer_device_list[] = &core_x_device, &laptop_stand_chroma_device, &laptop_stand_chroma_v2_device, + &leviathan_v2_device, &leviathan_v2x_device, &mug_holder_device, &mouse_dock_chroma_device, @@ -7711,6 +8866,7 @@ const razer_device* razer_device_list[] = &o11_dynamic_device, &seiren_emote_device, &thunderbolt_4_dock_chroma_device, + &hanbo_chroma_device }; const unsigned int RAZER_NUM_DEVICES = (sizeof(razer_device_list) / sizeof(razer_device_list[ 0 ])); diff --git a/Controllers/RazerController/RazerDevices.h b/Controllers/RazerController/RazerDevices.h index 8ee7bd21..71118488 100644 --- a/Controllers/RazerController/RazerDevices.h +++ b/Controllers/RazerController/RazerDevices.h @@ -1,10 +1,15 @@ -/*-----------------------------------------*\ -| RazerDevices.h | -| | -| Razer device table definitions | -| | -| Adam Honse (CalcProgrammer1) 9/4/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RazerDevices.h | +| | +| Device list for Razer devices | +| | +| Adam Honse (CalcProgrammer1) 04 Sep 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "RGBController.h" @@ -45,6 +50,10 @@ #define RAZER_BLACKWIDOW_V3_PRO_BLUETOOTH_PID 0x025B #define RAZER_BLACKWIDOW_V3_PRO_WIRELESS_PID 0x025C #define RAZER_BLACKWIDOW_V3_TKL_PID 0x0A24 +#define RAZER_BLACKWIDOW_V4_PID 0x0287 +#define RAZER_BLACKWIDOW_V4_PRO_PID 0x028D +#define RAZER_BLACKWIDOW_V4_X_PID 0x0293 +#define RAZER_BLACKWIDOW_V4_PRO_75_WIRED_PID 0x02B3 #define RAZER_BLACKWIDOW_X_CHROMA_PID 0x0216 #define RAZER_BLACKWIDOW_X_CHROMA_TE_PID 0x021A #define RAZER_BLADE_2016_PID 0x020F @@ -66,6 +75,7 @@ #define RAZER_BLADE_14_2021_PID 0x0270 #define RAZER_BLADE_14_2022_PID 0x028C +#define RAZER_BLADE_14_2023_PID 0x029D #define RAZER_BLADE_15_2022_PID 0x028A #define RAZER_BLADE_PRO_2016_PID 0x0210 @@ -92,21 +102,29 @@ #define RAZER_CYNOSA_V2_PID 0x025E #define RAZER_DEATHSTALKER_CHROMA_PID 0x0204 #define RAZER_DEATHSTALKER_V2_PID 0x0295 +#define RAZER_DEATHSTALKER_V2_PRO_TKL_WIRELESS_PID 0x0296 +#define RAZER_DEATHSTALKER_V2_PRO_TKL_WIRED_PID 0x0298 +#define RAZER_DEATHSTALKER_V2_PRO_TKL_BT_PID 0x0297 #define RAZER_DEATHSTALKER_V2_PRO_WIRELESS_PID 0x0290 #define RAZER_DEATHSTALKER_V2_PRO_WIRED_PID 0x0292 #define RAZER_HUNTSMAN_ELITE_PID 0x0226 #define RAZER_HUNTSMAN_PID 0x0227 #define RAZER_HUNTSMAN_MINI_PID 0x0257 +#define RAZER_HUNTSMAN_MINI_ANALOG_PID 0x0282 #define RAZER_HUNTSMAN_TE_PID 0x0243 #define RAZER_HUNTSMAN_V2_ANALOG_PID 0x0266 #define RAZER_HUNTSMAN_V2_TKL_PID 0x026B #define RAZER_HUNTSMAN_V2_PID 0x026C +#define RAZER_HUNTSMAN_V3_PRO_PID 0x02A6 +#define RAZER_HUNTSMAN_V3_PRO_TKL_WHITE_PID 0x02A7 #define RAZER_ORBWEAVER_CHROMA_PID 0x0207 #define RAZER_ORNATA_CHROMA_PID 0x021E #define RAZER_ORNATA_CHROMA_V2_PID 0x025D #define RAZER_ORNATA_V3_PID 0x028F #define RAZER_ORNATA_V3_REV2_PID 0x02A1 +#define RAZER_ORNATA_V3_TKL_PID 0x02A3 #define RAZER_ORNATA_V3_X_PID 0x0294 +#define RAZER_ORNATA_V3_X_REV2_PID 0x02A2 #define RAZER_TARTARUS_CHROMA_PID 0x0208 #define RAZER_TARTARUS_PRO_PID 0x0244 #define RAZER_TARTARUS_V2_PID 0x022B @@ -129,9 +147,16 @@ #define RAZER_BASILISK_X_HYPERSPEED_PID 0x0083 #define RAZER_BASILISK_V2_PID 0x0085 #define RAZER_BASILISK_V3_PID 0x0099 +#define RAZER_BASILISK_V3_35K_PID 0x00CB #define RAZER_BASILISK_V3_PRO_WIRED_PID 0x00AA #define RAZER_BASILISK_V3_PRO_WIRELESS_PID 0x00AB +#define RAZER_BASILISK_V3_PRO_35K_WIRED_PID 0x00CC +#define RAZER_BASILISK_V3_PRO_35K_WIRELESS_PID 0x00CD #define RAZER_BASILISK_V3_PRO_BLUETOOTH_PID 0x00AC +#define RAZER_BASILISK_V3_X_HYPERSPEED_PID 0x00B9 +#define RAZER_COBRA_PID 0x00A3 +#define RAZER_COBRA_PRO_WIRED_PID 0x00AF +#define RAZER_COBRA_PRO_WIRELESS_PID 0x00B0 #define RAZER_DEATHADDER_1800_PID 0x0038 #define RAZER_DEATHADDER_2000_PID 0x004F #define RAZER_DEATHADDER_2013_PID 0x0037 @@ -160,6 +185,7 @@ #define RAZER_MAMBA_2018_WIRED_PID 0x0073 #define RAZER_MAMBA_2018_WIRELESS_PID 0x0072 #define RAZER_MAMBA_ELITE_PID 0x006C +#define RAZER_MAMBA_HYPERFLUX_PID 0x0069 #define RAZER_MAMBA_TE_PID 0x0046 #define RAZER_NAGA_2012_PID 0x002E #define RAZER_NAGA_2014_PID 0x0040 @@ -174,6 +200,8 @@ #define RAZER_NAGA_TRINITY_PID 0x0067 #define RAZER_NAGA_PRO_WIRED_PID 0x008F #define RAZER_NAGA_PRO_WIRELESS_PID 0x0090 +#define RAZER_NAGA_PRO_V2_WIRED_PID 0x00A7 +#define RAZER_NAGA_PRO_V2_WIRELESS_PID 0x00A8 #define RAZER_OROCHI_2011_PID 0x0013 #define RAZER_OROCHI_2013_PID 0x0039 #define RAZER_OROCHI_CHROMA_PID 0x0048 @@ -195,6 +223,7 @@ #define RAZER_KRAKEN_PID 0x0504 #define RAZER_KRAKEN_ULTIMATE_PID 0x0527 #define RAZER_KRAKEN_V2_PID 0x0510 +#define RAZER_KRAKEN_KITTY_BLACK_EDITION_V2_PID 0x0560 #define RAZER_TIAMAT_71_V2_PID 0x0F03 /*-----------------------------------------------------*\ @@ -213,10 +242,13 @@ #define RAZER_FIREFLY_HYPERFLUX_PID 0x0068 #define RAZER_FIREFLY_PID 0x0C00 #define RAZER_FIREFLY_V2_PID 0x0C04 +#define RAZER_FIREFLY_V2_PRO_PID 0x0C08 #define RAZER_GOLIATHUS_CHROMA_EXTENDED_PID 0x0C02 #define RAZER_GOLIATHUS_CHROMA_PID 0x0C01 +#define RAZER_GOLIATHUS_CHROMA_3XL_PID 0x0C06 #define RAZER_LAPTOP_STAND_CHROMA_PID 0x0F0D #define RAZER_LAPTOP_STAND_CHROMA_V2_PID 0x0F2B +#define RAZER_LEVIATHAN_V2_PID 0x0532 #define RAZER_LEVIATHAN_V2X_PID 0x054A #define RAZER_MOUSE_BUNGEE_V3_CHROMA_PID 0x0F1D #define RAZER_MOUSE_DOCK_CHROMA_PID 0x007E @@ -227,6 +259,7 @@ #define RAZER_SEIREN_EMOTE_PID 0x0F1B #define RAZER_STRIDER_CHROMA_PID 0x0C05 #define RAZER_THUNDERBOLT_4_DOCK_CHROMA_PID 0x0F21 +#define RAZER_HANBO_CHROMA_PID 0x0F35 typedef struct { @@ -236,15 +269,6 @@ typedef struct unsigned int cols; } razer_zone; -typedef struct -{ - unsigned int zone; - unsigned int row; - unsigned int col; - const char* name; - unsigned char layout = RAZER_LAYOUT_TYPE_ALL; -} razer_key; - typedef struct { std::string name; @@ -255,8 +279,6 @@ typedef struct unsigned int rows; unsigned int cols; const razer_zone* zones[RAZER_MAX_ZONES]; - const razer_key* keymap; - unsigned int keymap_size; keyboard_keymap_overlay_values* layout; } razer_device; diff --git a/Controllers/RazerController/RazerHanboController/RGBController_RazerHanbo.cpp b/Controllers/RazerController/RazerHanboController/RGBController_RazerHanbo.cpp new file mode 100644 index 00000000..4b11be80 --- /dev/null +++ b/Controllers/RazerController/RazerHanboController/RGBController_RazerHanbo.cpp @@ -0,0 +1,189 @@ +/*---------------------------------------------------------*\ +| RGBController_RazerHanbo.cpp | +| | +| RGBController for Razer Hanbo devices | +| | +| Joseph East (dripsnek) 12 Apr 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_RazerHanbo.h" +#include "RazerDevices.h" + +/**------------------------------------------------------------------*\ + @name Razer Hanbo Chroma + @category Cooler + @type USB + @save :robot: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectRazerHanboControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_RazerHanbo::RGBController_RazerHanbo(RazerHanboController* controller_ptr) +{ + controller = controller_ptr; + name = controller->GetName(); + vendor = "Razer"; + type = controller->GetDeviceType(); + description = "Razer Hanbo Device"; + location = controller->GetDeviceLocation(); + version = controller->GetFirmwareString(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = RAZER_HANBO_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = MIN_BRIGHTNESS; + Direct.brightness_max = MAX_BRIGHTNESS; + Direct.brightness = MAX_BRIGHTNESS/2; + modes.push_back(Direct); + + mode Off; + Off.name = "Off"; + Off.value = RAZER_HANBO_MODE_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = RAZER_HANBO_MODE_SPECTRUM_CYCLE; + SpectrumCycle.flags = 0; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + modes.push_back(SpectrumCycle); + + local_mode = RAZER_HANBO_MODE_DIRECT; + + SetupZones(); +} + +RGBController_RazerHanbo::~RGBController_RazerHanbo() +{ + delete controller; +} + +void RGBController_RazerHanbo::SetupZones() +{ + unsigned int device_index = controller->GetDeviceIndex(); + + /*---------------------------------------------------------*\ + | Fill in zone information based on device table | + \*---------------------------------------------------------*/ + for(unsigned int zone_id = 0; zone_id < RAZER_MAX_ZONES; zone_id++) + { + if(device_list[device_index]->zones[zone_id] != NULL) + { + zone new_zone; + + new_zone.name = device_list[device_index]->zones[zone_id]->name; + new_zone.type = device_list[device_index]->zones[zone_id]->type; + new_zone.leds_count = device_list[device_index]->zones[zone_id]->rows * device_list[device_index]->zones[zone_id]->cols; + new_zone.leds_min = new_zone.leds_count; + new_zone.leds_max = new_zone.leds_count; + + if(new_zone.type == ZONE_TYPE_MATRIX) + { + matrix_map_type * new_map = new matrix_map_type; + + new_zone.matrix_map = new_map; + new_map->height = device_list[device_index]->zones[zone_id]->rows; + new_map->width = device_list[device_index]->zones[zone_id]->cols; + new_map->map = new unsigned int[new_map->height * new_map->width]; + + for(unsigned int y = 0; y < new_map->height; y++) + { + for(unsigned int x = 0; x < new_map->width; x++) + { + new_map->map[(y * new_map->width) + x] = (y * new_map->width) + x; + } + } + } + else + { + new_zone.matrix_map = NULL; + } + + zones.push_back(new_zone); + } + } + + for(unsigned int zone_id = 0; zone_id < zones.size(); zone_id++) + { + for(unsigned int row_id = 0; row_id < device_list[device_index]->zones[zone_id]->rows; row_id++) + { + for(unsigned int col_id = 0; col_id < device_list[device_index]->zones[zone_id]->cols; col_id++) + { + led* new_led = new led(); + + new_led->name = device_list[device_index]->zones[zone_id]->name; + + if(zones[zone_id].leds_count > 1) + { + new_led->name.append(" LED "); + new_led->name.append(std::to_string(col_id + 1)); + } + + leds.push_back(*new_led); + } + } + } + + SetupColors(); +} + +void RGBController_RazerHanbo::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_RazerHanbo::DeviceUpdateLEDs() +{ + UpdateZoneLEDs(PUMP); + UpdateZoneLEDs(FAN1); + UpdateZoneLEDs(FAN2); + UpdateZoneLEDs(FAN3); +} + +/*---------------------------------------------------------*\ +| The Hanbo command set is arranged in terms of zones. | +| Transactions are straight forward when grouped this way. | +\*---------------------------------------------------------*/ + +void RGBController_RazerHanbo::UpdateZoneLEDs(int zoneid) +{ + controller->SetZoneLeds(zoneid, this->zones[zoneid]); +} + +void RGBController_RazerHanbo::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RazerHanbo::DeviceUpdateMode() +{ + switch(modes[active_mode].value) + { + case RAZER_HANBO_MODE_DIRECT: + if(local_mode != RAZER_HANBO_MODE_DIRECT) + controller->SetDirectMode(); + break; + + case RAZER_HANBO_MODE_OFF: + controller->SetModeOff(); + break; + + case RAZER_HANBO_MODE_SPECTRUM_CYCLE: + controller->SetModeSpectrumCycle(); + break; + } + + local_mode = modes[active_mode].value; +} diff --git a/Controllers/RazerController/RazerHanboController/RGBController_RazerHanbo.h b/Controllers/RazerController/RazerHanboController/RGBController_RazerHanbo.h new file mode 100644 index 00000000..4ca14d54 --- /dev/null +++ b/Controllers/RazerController/RazerHanboController/RGBController_RazerHanbo.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------*\ +| RGBController_Razer.h | +| | +| RGBController for Razer Hanbo devices | +| | +| Joseph East (dripsnek) 12 Apr 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RazerHanboController.h" + +enum +{ + RAZER_HANBO_MODE_DIRECT, + RAZER_HANBO_MODE_OFF, + RAZER_HANBO_MODE_SPECTRUM_CYCLE, +}; + +class RGBController_RazerHanbo : public RGBController +{ +public: + RGBController_RazerHanbo(RazerHanboController* controller_ptr); + ~RGBController_RazerHanbo(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RazerHanboController* controller; + int local_mode; +}; diff --git a/Controllers/RazerController/RazerHanboController/RazerHanboController.cpp b/Controllers/RazerController/RazerHanboController/RazerHanboController.cpp new file mode 100644 index 00000000..1c51bcf6 --- /dev/null +++ b/Controllers/RazerController/RazerHanboController/RazerHanboController.cpp @@ -0,0 +1,262 @@ +/*---------------------------------------------------------*\ +| RazerHanboController.cpp | +| | +| Driver for Razer Hanbo devices | +| | +| Joseph East (dripsnek) 12 Apr 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RazerHanboController.h" +#include "RazerDevices.h" + +using namespace std::chrono_literals; + +RazerHanboController::RazerHanboController(hid_device* dev_handle, const char* path, unsigned short pid, std::string dev_name) +{ + dev = dev_handle; + dev_pid = pid; + location = path; + name = dev_name; + device_index = 0; + + for(unsigned int i = 0; i < RAZER_NUM_DEVICES; i++) + { + if(device_list[i]->pid == dev_pid) + { + device_index = i; + } + } + + GetFirmware(); + SetDirectMode(); +} + +RazerHanboController::~RazerHanboController() +{ + hid_close(dev); +} + +unsigned int RazerHanboController::GetDeviceIndex() +{ + return(device_index); +} + +device_type RazerHanboController::GetDeviceType() +{ + return(device_list[device_index]->type); +} + +std::string RazerHanboController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string RazerHanboController::GetFirmwareString() +{ + return firmware_version; +} + +std::string RazerHanboController::GetSerialString() +{ + return serial_string; +} + +std::string RazerHanboController::GetName() +{ + return(name); +} + +void RazerHanboController::SetDirectMode() +{ + razer_hanbo_report request_report = razer_hanbo_create_report(0x82); + razer_hanbo_report response_report = razer_hanbo_create_report(0x00); + + /*---------------------------------------*\ + | Take the one request and transform as | + | appropriate for the sequence. | + \*---------------------------------------*/ + request_report.arguments[0] = 0x01; + UsbSend(&request_report); + UsbReceive(&response_report); + + request_report.header[1] = 0x80; + request_report.arguments[0] = 0x01; + request_report.arguments[1] = 0x00; + request_report.arguments[2] = 0x01; + UsbSend(&request_report); + UsbReceive(&response_report); + + request_report.header[1] = 0x80; + request_report.arguments[0] = 0x01; + request_report.arguments[1] = 0x01; + request_report.arguments[2] = 0x01; + UsbSend(&request_report); + UsbReceive(&response_report); + + memset(&request_report, 0, sizeof(razer_hanbo_report)); + request_report.header[1] = 0x82; + request_report.arguments[0] = 0x01; + UsbSend(&request_report); + UsbReceive(&response_report); +} + +void RazerHanboController::SetModeOff() +{ + SetDirectMode(); +} + +void RazerHanboController::SetModeSpectrumCycle() +{ + razer_hanbo_report request_report = razer_hanbo_create_report(0x82); + razer_hanbo_report response_report = razer_hanbo_create_report(0x00); + + request_report.arguments[0] = 0x01; + UsbSend(&request_report); + UsbReceive(&response_report); + + request_report.header[1] = 0x80; + request_report.arguments[0] = 0x01; + UsbSend(&request_report); + UsbReceive(&response_report); + + request_report.header[1] = 0x80; + request_report.arguments[0] = 0x01; + request_report.arguments[1] = 0x01; + UsbSend(&request_report); + UsbReceive(&response_report); +} + +void RazerHanboController::SetZoneLeds(int zone_idx, const zone& input_zone) +{ + razer_hanbo_report request_report = razer_hanbo_create_report(0x32); + std::string payload; + + unsigned int j = 0; + + if(zone_idx > PUMP) + request_report.header[1] = 0x40; + + payload = "0107000000000" + std::to_string(zone_idx); + + for(unsigned int i = 0; i < payload.length(); i += 2) + { + std::string byteString = payload.substr(i, 2); + char byte = (char)strtol(byteString.c_str(), NULL, 16); + request_report.arguments[j] = byte; + j++; + } + + /*--------------------------------------------*\ + | The color command format is G/R/B | + \*--------------------------------------------*/ + + for(unsigned int i = 0; i < input_zone.leds_count; i++) + { + request_report.arguments[j] = RGBGetGValue(input_zone.colors[i]); + j++; + request_report.arguments[j] = RGBGetRValue(input_zone.colors[i]); + j++; + request_report.arguments[j] = RGBGetBValue(input_zone.colors[i]); + j++; + } + + /*--------------------------------------------*\ + | Writing RGB values does not generate ack | + | reports from the cooler. Add a gap between | + | transactions to not overwhelm it. | + \*--------------------------------------------*/ + UsbSend(&request_report); + std::this_thread::sleep_for(2ms); +} + +/*--------------------------------------------*\ +| The Hanbo allows for individual brightness | +| of the pump cap and fans. OpenRGB only has | +| a single brightness slider. Whilst this | +| function can support individual settings, | +| most of the time they will be invoked with | +| identical values | +\*--------------------------------------------*/ +void RazerHanboController::SetBrightness(int zone, unsigned int brightness) +{ + razer_hanbo_report request_report = razer_hanbo_create_report(0x70); + razer_hanbo_report response_report = razer_hanbo_create_report(0x00); + + request_report.arguments[0] = 0x01; + request_report.arguments[1] = 0x00; + + if(zone > PUMP) + request_report.arguments[1] = 0x01; + + request_report.arguments[2] = brightness & 0xFF; + UsbSend(&request_report); + UsbReceive(&response_report); +} + +/*---------------------------------------------------------------------------------*\ +| Basic report and response creation function | +\*---------------------------------------------------------------------------------*/ + +razer_hanbo_report RazerHanboController::razer_hanbo_create_report(unsigned char header) +{ + /*---------------------------------------------------------*\ + | One type supports both requests and responses. | + | Requests start at header[1] to provide a dummy byte. | + | Responses provide 0 to this function for consistency | + \*---------------------------------------------------------*/ + razer_hanbo_report new_report; + + memset(&new_report, 0, sizeof(razer_hanbo_report)); + new_report.header[1] = header; + return new_report; +} + +/*---------------------------------------------------------------------------------*\ +| Get functions (request information from device) | +\*---------------------------------------------------------------------------------*/ + +void RazerHanboController::GetFirmware() +{ + razer_hanbo_report request_report = razer_hanbo_create_report(0x01); + razer_hanbo_report response_report = razer_hanbo_create_report(0x00); + + request_report.arguments[0] = 0x01; + UsbSend(&request_report); + /*---------------------------------------*\ + | The Hanbo sends firmware reports twice | + \*---------------------------------------*/ + UsbReceive(&response_report); + UsbReceive(&response_report); + + if(response_report.header[0] == 0x02) + { + std::string ret_serial(response_report.arguments, response_report.arguments+15); + std::vector firmware_ret(response_report.arguments+27, response_report.arguments+29); + char major = firmware_ret[0]; + char minor = firmware_ret[1] >> 4 & 0x0F; + char patch = firmware_ret[1] & 0x0F; + char ver[12]; + + snprintf(ver, sizeof(ver), "%hhu.%hhu.%hhu", major, minor, patch); + serial_string = ret_serial; + firmware_version = std::string(ver); + } +} + +/*---------------------------------------------------------------------------------*\ +| USB transfer functions | +\*---------------------------------------------------------------------------------*/ + +int RazerHanboController::UsbReceive(razer_hanbo_report* report) +{ + return hid_read_timeout(dev, (unsigned char*)report, sizeof(*report),2); +} + +int RazerHanboController::UsbSend(razer_hanbo_report* report) +{ + return hid_write(dev, (unsigned char*)report, sizeof(*report)); +} diff --git a/Controllers/RazerController/RazerHanboController/RazerHanboController.h b/Controllers/RazerController/RazerHanboController/RazerHanboController.h new file mode 100644 index 00000000..6f257db8 --- /dev/null +++ b/Controllers/RazerController/RazerHanboController/RazerHanboController.h @@ -0,0 +1,103 @@ +/*---------------------------------------------------------*\ +| RazerHanboController.h | +| | +| Driver for Razer Hanbo devices | +| | +| Joseph East (dripsnek) 12 Apr 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +/*---------------------------------------------------------*\ +| Struct packing macro for GCC and MSVC | +\*---------------------------------------------------------*/ +#ifdef __GNUC__ +#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__)) +#endif + +#ifdef _MSC_VER +#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop)) +#endif + +/*---------------------------------------------------------*\ +| The Hanbo does not advertise HID report IDs. | +| In this case under Windows, payloads sent to hidapi must | +| be prefixed with a byte of value 0 even if this exceeds | +| the device report length. This dummy byte never ends up | +| on the wire. Hidapi via libusb under Linux is compatible | +| with this behavior. This is generally not compatible with | +| hidraw when using it directly. | +| | +| Request payloads start at header[1] to make this byte. | +| Responses are unaffected and start at header[0]. | +\*---------------------------------------------------------*/ +PACK(struct razer_hanbo_report +{ + unsigned char header[2]; + unsigned char arguments[63]; +}); + +enum +{ + MIN_BRIGHTNESS = 0x00, + MAX_BRIGHTNESS = 0x64, +}; + +enum +{ + PUMP, + FAN1, + FAN2, + FAN3 +}; + +class RazerHanboController +{ +public: + RazerHanboController(hid_device* dev_handle, const char* path, unsigned short pid, std::string dev_name); + ~RazerHanboController(); + + unsigned int GetDeviceIndex(); + device_type GetDeviceType(); + std::string GetDeviceLocation(); + std::string GetFirmwareString(); + std::string GetSerialString(); + std::string GetName(); + void SetDirectMode(); + void SetModeOff(); + void SetModeSpectrumCycle(); + void SetZoneLeds(int zone_idc, const zone& input_zone); + void SetBrightness(int zone, unsigned int brightness); + +private: + hid_device* dev; + unsigned short dev_pid; + + /*---------------------------------------------------------*\ + | Device information strings | + \*---------------------------------------------------------*/ + std::string firmware_version; + std::string serial_string; + std::string location; + std::string name; + + /*---------------------------------------------------------*\ + | Index of device in Razer device list | + \*---------------------------------------------------------*/ + unsigned int device_index; + + /*---------------------------------------------------------*\ + | Private functions | + \*---------------------------------------------------------*/ + razer_hanbo_report razer_hanbo_create_report(unsigned char header); + void GetFirmware(); + int UsbReceive(razer_hanbo_report* report); + int UsbSend(razer_hanbo_report* report); +}; diff --git a/Controllers/RazerController/RGBController_RazerKraken.cpp b/Controllers/RazerController/RazerKrakenController/RGBController_RazerKraken.cpp similarity index 93% rename from Controllers/RazerController/RGBController_RazerKraken.cpp rename to Controllers/RazerController/RazerKrakenController/RGBController_RazerKraken.cpp index 845ba496..4774a203 100644 --- a/Controllers/RazerController/RGBController_RazerKraken.cpp +++ b/Controllers/RazerController/RazerKrakenController/RGBController_RazerKraken.cpp @@ -1,3 +1,14 @@ +/*---------------------------------------------------------*\ +| RGBController_RazerKraken.cpp | +| | +| RGBController for Razer Kraken | +| | +| Adam Honse (CalcProgrammer1) 28 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "RGBController_RazerKraken.h" #include "RazerDevices.h" @@ -146,19 +157,6 @@ void RGBController_RazerKraken::SetupZones() new_led->name.append(std::to_string(col_id + 1)); } - if(device_list[device_index]->keymap != NULL) - { - for(unsigned int i = 0; i < device_list[device_index]->keymap_size; i++) - { - if(zone_id == device_list[device_index]->keymap[i].zone && - row_id == device_list[device_index]->keymap[i].row && - col_id == device_list[device_index]->keymap[i].col) - { - new_led->name = device_list[device_index]->keymap[i].name; - } - } - } - leds.push_back(*new_led); } } diff --git a/Controllers/RazerController/RazerKrakenController/RGBController_RazerKraken.h b/Controllers/RazerController/RazerKrakenController/RGBController_RazerKraken.h new file mode 100644 index 00000000..b879742f --- /dev/null +++ b/Controllers/RazerController/RazerKrakenController/RGBController_RazerKraken.h @@ -0,0 +1,44 @@ +/*---------------------------------------------------------*\ +| RGBController_RazerKraken.h | +| | +| RGBController for Razer Kraken | +| | +| Adam Honse (CalcProgrammer1) 28 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RazerKrakenController.h" + +enum +{ + RAZER_KRAKEN_MODE_DIRECT, + RAZER_KRAKEN_MODE_OFF, + RAZER_KRAKEN_MODE_STATIC, + RAZER_KRAKEN_MODE_BREATHING, + RAZER_KRAKEN_MODE_SPECTRUM_CYCLE, +}; + +class RGBController_RazerKraken : public RGBController +{ +public: + RGBController_RazerKraken(RazerKrakenController* controller_ptr); + ~RGBController_RazerKraken(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RazerKrakenController* controller; +}; diff --git a/Controllers/RazerController/RazerKrakenController.cpp b/Controllers/RazerController/RazerKrakenController/RazerKrakenController.cpp similarity index 93% rename from Controllers/RazerController/RazerKrakenController.cpp rename to Controllers/RazerController/RazerKrakenController/RazerKrakenController.cpp index 3245f0bd..7ff0a948 100644 --- a/Controllers/RazerController/RazerKrakenController.cpp +++ b/Controllers/RazerController/RazerKrakenController/RazerKrakenController.cpp @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| RazerKrakenController.cpp | -| | -| Driver for Razer Kraken devices | -| | -| Adam Honse (CalcProgrammer1) 2/28/2021 | -\*-----------------------------------------*/ - -#include "RazerKrakenController.h" -#include "RazerDevices.h" +/*---------------------------------------------------------*\ +| RazerKrakenController.cpp | +| | +| Driver for Razer Kraken | +| | +| Adam Honse (CalcProgrammer1) 28 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "RazerKrakenController.h" +#include "RazerDevices.h" using namespace std::chrono_literals; @@ -41,6 +43,7 @@ RazerKrakenController::RazerKrakenController(hid_device* dev_handle, const char* switch(dev_pid) { case RAZER_KRAKEN_V2_PID: + case RAZER_KRAKEN_KITTY_BLACK_EDITION_V2_PID: case RAZER_KRAKEN_ULTIMATE_PID: led_mode_address = 0x172D; custom_address = 0x1189; @@ -204,6 +207,14 @@ std::string RazerKrakenController::razer_get_serial() serial_string[22] = '\0'; } + for(size_t i = 0; i < 22; i++) + { + if(serial_string[i] < 30 || serial_string[i] > 126) + { + serial_string[i] = ' '; + } + } + std::string ret_string = serial_string; return ret_string; } @@ -307,6 +318,7 @@ void RazerKrakenController::razer_set_mode_custom(unsigned char red, unsigned ch { case RAZER_KRAKEN_PID: case RAZER_KRAKEN_V2_PID: + case RAZER_KRAKEN_KITTY_BLACK_EDITION_V2_PID: case RAZER_KRAKEN_ULTIMATE_PID: razer_usb_send(&rgb_report); break; @@ -365,6 +377,7 @@ void RazerKrakenController::razer_set_mode_static(unsigned char red, unsigned ch { case RAZER_KRAKEN_PID: case RAZER_KRAKEN_V2_PID: + case RAZER_KRAKEN_KITTY_BLACK_EDITION_V2_PID: case RAZER_KRAKEN_ULTIMATE_PID: razer_usb_send(&rgb_report); break; diff --git a/Controllers/RazerController/RazerKrakenController.h b/Controllers/RazerController/RazerKrakenController/RazerKrakenController.h similarity index 87% rename from Controllers/RazerController/RazerKrakenController.h rename to Controllers/RazerController/RazerKrakenController/RazerKrakenController.h index 8c723296..dbb9e1f5 100644 --- a/Controllers/RazerController/RazerKrakenController.h +++ b/Controllers/RazerController/RazerKrakenController/RazerKrakenController.h @@ -1,19 +1,20 @@ -/*-----------------------------------------*\ -| RazerKrakenController.h | -| | -| Definitions and types for Razer Kraken | -| devices | -| | -| Adam Honse (CalcProgrammer1) 2/28/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| RazerKrakenController.h | +| | +| Driver for Razer Kraken | +| | +| Adam Honse (CalcProgrammer1) 28 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + /*---------------------------------------------------------*\ | Struct packing macro for GCC and MSVC | \*---------------------------------------------------------*/ @@ -90,7 +91,6 @@ private: std::string firmware_version; std::string location; std::string name; - device_type type; /*---------------------------------------------------------*\ | Kraken LED/Mode Addresses | @@ -104,21 +104,15 @@ private: \*---------------------------------------------------------*/ unsigned int device_index; - /*---------------------------------------------------------*\ - | HID report index for request and response | - \*---------------------------------------------------------*/ - unsigned char report_index; - unsigned char response_index; - /*---------------------------------------------------------*\ | Private functions based on OpenRazer | \*---------------------------------------------------------*/ razer_kraken_request_report razer_kraken_create_report(unsigned char report_id, unsigned char destination, unsigned char length, unsigned short address); razer_kraken_effect_byte razer_kraken_create_effect_byte(); - + std::string razer_get_firmware(); std::string razer_get_serial(); - + void razer_set_mode_breathing_one_color(unsigned char red, unsigned char grn, unsigned char blu); void razer_set_mode_breathing_two_colors(unsigned char r1, unsigned char g1, unsigned char b1, unsigned char r2, unsigned char g2, unsigned char b2); void razer_set_mode_breathing_three_colors(unsigned char r1, unsigned char g1, unsigned char b1, unsigned char r2, unsigned char g2, unsigned char b2, unsigned char r3, unsigned char g3, unsigned char b3); diff --git a/Controllers/RedSquareKeyroxController/RGBController_RedSquareKeyrox.h b/Controllers/RedSquareKeyroxController/RGBController_RedSquareKeyrox.h deleted file mode 100644 index 428ecc3a..00000000 --- a/Controllers/RedSquareKeyroxController/RGBController_RedSquareKeyrox.h +++ /dev/null @@ -1,30 +0,0 @@ -/*---------------------------------------------*\ -| RGBController_RedSquareKeyrox.h | -| | -| Driver for Red Square Keyrox USB Controller | -| | -| cafeed28 3 Nov 2022 | -\*---------------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "RedSquareKeyroxController.h" - -class RGBController_RedSquareKeyrox : public RGBController -{ -public: - RGBController_RedSquareKeyrox(RedSquareKeyroxController* controller_ptr); - ~RGBController_RedSquareKeyrox(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - RedSquareKeyroxController* controller; -}; diff --git a/Controllers/RedSquareKeyroxController/RGBController_RedSquareKeyroxTKLClassic.h b/Controllers/RedSquareKeyroxController/RGBController_RedSquareKeyroxTKLClassic.h deleted file mode 100644 index 3dadabbf..00000000 --- a/Controllers/RedSquareKeyroxController/RGBController_RedSquareKeyroxTKLClassic.h +++ /dev/null @@ -1,35 +0,0 @@ -/*---------------------------------------------*\ -| RGBController_RedSquareKeyroxTKLClassic.h | -| | -| Driver for Red Square Keyrox USB Controller | -| | -| vlack 3 May 2023 | -\*---------------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "RGBControllerKeyNames.h" -#include "KeyboardLayoutManager.h" -#include "RedSquareKeyroxTKLClassicController.h" - -#define KEYROX_TKL_CLASSIC_WIDTH 17 -#define KEYROX_TKL_CLASSIC_HEIGHT 6 - -class RGBController_RedSquareKeyroxTKLClassic : public RGBController -{ -public: - RGBController_RedSquareKeyroxTKLClassic(RedSquareKeyroxTKLClassicController* controller_ptr); - ~RGBController_RedSquareKeyroxTKLClassic(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - RedSquareKeyroxTKLClassicController* controller; -}; diff --git a/Controllers/RedSquareKeyroxController/RedSquareKeyroxController.h b/Controllers/RedSquareKeyroxController/RedSquareKeyroxController.h deleted file mode 100644 index b88ca22e..00000000 --- a/Controllers/RedSquareKeyroxController/RedSquareKeyroxController.h +++ /dev/null @@ -1,85 +0,0 @@ -/*---------------------------------------------*\ -| RedSquareKeyroxController.h | -| | -| Driver for Red Square Keyrox USB Controller | -| | -| cafeed28 3 Nov 2022 | -\*---------------------------------------------*/ - -#pragma once -#include -#include - -#include "RGBController.h" - -#define PACKET_DATA_LENGTH 520 - -/*-----------------------------*\ -| Red Square Keyrox variants | -\*-----------------------------*/ -enum -{ - KEYROX_VARIANT_TKL, -}; - -/*---------------------------------------*\ -| Modes | -\*---------------------------------------*/ -enum -{ - WAVE_MODE_VALUE = 0x00, - CONST_MODE_VALUE = 0x01, - BREATHE_MODE_VALUE = 0x02, - HEARTRATE_MODE_VALUE = 0x03, - POINT_MODE_VALUE = 0x04, - WINNOWER_MODE_VALUE = 0x05, - STARS_MODE_VALUE = 0x06, - SPECTRUM_MODE_VALUE = 0x07, - PLUMFLOWER_MODE_VALUE = 0x08, - SHOOT_MODE_VALUE = 0x09, - AMBILIGHT_ROTATE_MODE_VALUE = 0x0A, - RIPPLE_MODE_VALUE = 0x0B, - CUSTOM_MODE_VALUE = 0x0C, -}; - -/*-----------------------------*\ -| Other settings | -\*-----------------------------*/ -enum -{ - KEYROX_BRIGHTNESS_MIN = 0x00, - KEYROX_BRIGHTNESS_MAX = 0x7F, - KEYROX_SPEED_MIN = 0x00, - KEYROX_SPEED_MAX = 0x04, -}; - - -class RedSquareKeyroxController -{ -public: - RedSquareKeyroxController(hid_device *dev_handle, const hid_device_info &info, int variant); - ~RedSquareKeyroxController(); - - int GetVariant(); - std::string GetDeviceLocation(); - std::string GetSerialString(); - - int GetDirectionLRUD(int direction); // Direction for Left-Right-Up-Down modes - int GetDirectionUD(int direction); // Direction for Up-Down modes - - void SetLedSequencePositions(std::vector positions); - void SetMode(std::vector modes, int active_mode); - void SetModeData(std::vector modes, int active_mode); - void SetLEDsData(std::vector modes, int active_mode, std::vector colors); - - void Send(unsigned char data[PACKET_DATA_LENGTH]); - -protected: - hid_device* dev; - -private: - int variant; - std::string location; - std::string serial_number; - std::vector led_sequence_positions; -}; diff --git a/Controllers/RedSquareKeyroxController/RGBController_RedSquareKeyrox.cpp b/Controllers/RedSquareKeyroxController/RedSquareKeyroxController/RGBController_RedSquareKeyrox.cpp similarity index 93% rename from Controllers/RedSquareKeyroxController/RGBController_RedSquareKeyrox.cpp rename to Controllers/RedSquareKeyroxController/RedSquareKeyroxController/RGBController_RedSquareKeyrox.cpp index 4d22947e..93c986ef 100644 --- a/Controllers/RedSquareKeyroxController/RGBController_RedSquareKeyrox.cpp +++ b/Controllers/RedSquareKeyroxController/RedSquareKeyroxController/RGBController_RedSquareKeyrox.cpp @@ -1,11 +1,14 @@ -/*-------------------------------------------------------*\ -| RGBController_RedSquareKeyrox.cpp | -| | -| Driver for Red Square Keyrox USB Controller | -| Based on Keychron Controller by Guimard Morgan (morg) | -| | -| cafeed28 3 Nov 2022 | -\*-------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_RedSquareKeyrox.cpp | +| | +| RGBController for Red Square Keyrox | +| | +| cafeed28 03 Nov 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "RGBControllerKeyNames.h" #include "RGBController_RedSquareKeyrox.h" @@ -158,10 +161,10 @@ RGBController_RedSquareKeyrox::RGBController_RedSquareKeyrox(RedSquareKeyroxCont { controller = controller_ptr; - name = "Red Square Keyrox"; + name = controller->GetNameString(); vendor = "Red Square"; type = DEVICE_TYPE_KEYBOARD; - description = name; + description = "Red Square Keyrox Device"; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); diff --git a/Controllers/RedSquareKeyroxController/RedSquareKeyroxController/RGBController_RedSquareKeyrox.h b/Controllers/RedSquareKeyroxController/RedSquareKeyroxController/RGBController_RedSquareKeyrox.h new file mode 100644 index 00000000..8b4a1744 --- /dev/null +++ b/Controllers/RedSquareKeyroxController/RedSquareKeyroxController/RGBController_RedSquareKeyrox.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_RedSquareKeyrox.h | +| | +| RGBController for Red Square Keyrox | +| | +| cafeed28 03 Nov 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RedSquareKeyroxController.h" + +class RGBController_RedSquareKeyrox : public RGBController +{ +public: + RGBController_RedSquareKeyrox(RedSquareKeyroxController* controller_ptr); + ~RGBController_RedSquareKeyrox(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RedSquareKeyroxController* controller; +}; diff --git a/Controllers/RedSquareKeyroxController/RedSquareKeyroxController.cpp b/Controllers/RedSquareKeyroxController/RedSquareKeyroxController/RedSquareKeyroxController.cpp similarity index 86% rename from Controllers/RedSquareKeyroxController/RedSquareKeyroxController.cpp rename to Controllers/RedSquareKeyroxController/RedSquareKeyroxController/RedSquareKeyroxController.cpp index 165e5e71..96c07e9a 100644 --- a/Controllers/RedSquareKeyroxController/RedSquareKeyroxController.cpp +++ b/Controllers/RedSquareKeyroxController/RedSquareKeyroxController/RedSquareKeyroxController.cpp @@ -1,22 +1,25 @@ -/*---------------------------------------------*\ -| RedSquareKeyroxController.cpp | -| | -| Driver for Red Square Keyrox USB Controller | -| | -| cafeed28 3 Nov 2022 | -\*---------------------------------------------*/ +/*---------------------------------------------------------*\ +| RedSquareKeyroxController.cpp | +| | +| Driver for Red Square Keyrox | +| | +| cafeed28 03 Nov 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include "LogManager.h" #include "RedSquareKeyroxController.h" -#include - using namespace std::chrono_literals; -RedSquareKeyroxController::RedSquareKeyroxController(hid_device *dev_handle, const hid_device_info &info, int variant) +RedSquareKeyroxController::RedSquareKeyroxController(hid_device *dev_handle, const hid_device_info &info, int variant, std::string dev_name) { dev = dev_handle; location = info.path; + name = dev_name; this->variant = variant; } @@ -35,6 +38,11 @@ std::string RedSquareKeyroxController::GetDeviceLocation() return("HID: " + location); } +std::string RedSquareKeyroxController::GetNameString() +{ + return(name); +} + std::string RedSquareKeyroxController::GetSerialString() { wchar_t serial_wchar[128]; diff --git a/Controllers/RedSquareKeyroxController/RedSquareKeyroxController/RedSquareKeyroxController.h b/Controllers/RedSquareKeyroxController/RedSquareKeyroxController/RedSquareKeyroxController.h new file mode 100644 index 00000000..4bd659be --- /dev/null +++ b/Controllers/RedSquareKeyroxController/RedSquareKeyroxController/RedSquareKeyroxController.h @@ -0,0 +1,90 @@ +/*---------------------------------------------------------*\ +| RedSquareKeyroxController.h | +| | +| Driver for Red Square Keyrox | +| | +| cafeed28 03 Nov 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define PACKET_DATA_LENGTH 520 + +/*-----------------------------*\ +| Red Square Keyrox variants | +\*-----------------------------*/ +enum +{ + KEYROX_VARIANT_TKL, +}; + +/*---------------------------------------*\ +| Modes | +\*---------------------------------------*/ +enum +{ + WAVE_MODE_VALUE = 0x00, + CONST_MODE_VALUE = 0x01, + BREATHE_MODE_VALUE = 0x02, + HEARTRATE_MODE_VALUE = 0x03, + POINT_MODE_VALUE = 0x04, + WINNOWER_MODE_VALUE = 0x05, + STARS_MODE_VALUE = 0x06, + SPECTRUM_MODE_VALUE = 0x07, + PLUMFLOWER_MODE_VALUE = 0x08, + SHOOT_MODE_VALUE = 0x09, + AMBILIGHT_ROTATE_MODE_VALUE = 0x0A, + RIPPLE_MODE_VALUE = 0x0B, + CUSTOM_MODE_VALUE = 0x0C, +}; + +/*-----------------------------*\ +| Other settings | +\*-----------------------------*/ +enum +{ + KEYROX_BRIGHTNESS_MIN = 0x00, + KEYROX_BRIGHTNESS_MAX = 0x7F, + KEYROX_SPEED_MIN = 0x00, + KEYROX_SPEED_MAX = 0x04, +}; + + +class RedSquareKeyroxController +{ +public: + RedSquareKeyroxController(hid_device *dev_handle, const hid_device_info &info, int variant, std::string dev_name); + ~RedSquareKeyroxController(); + + int GetVariant(); + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + int GetDirectionLRUD(int direction); // Direction for Left-Right-Up-Down modes + int GetDirectionUD(int direction); // Direction for Up-Down modes + + void SetLedSequencePositions(std::vector positions); + void SetMode(std::vector modes, int active_mode); + void SetModeData(std::vector modes, int active_mode); + void SetLEDsData(std::vector modes, int active_mode, std::vector colors); + + void Send(unsigned char data[PACKET_DATA_LENGTH]); + +protected: + hid_device* dev; + +private: + int variant; + std::string location; + std::string name; + std::string serial_number; + std::vector led_sequence_positions; +}; diff --git a/Controllers/RedSquareKeyroxController/RedSquareKeyroxControllerDetect.cpp b/Controllers/RedSquareKeyroxController/RedSquareKeyroxControllerDetect.cpp index 613e0a65..b9169e8c 100644 --- a/Controllers/RedSquareKeyroxController/RedSquareKeyroxControllerDetect.cpp +++ b/Controllers/RedSquareKeyroxController/RedSquareKeyroxControllerDetect.cpp @@ -1,10 +1,20 @@ +/*---------------------------------------------------------*\ +| RedSquareKeyroxControllerDetect.cpp | +| | +| Detector for Red Square Keyrox | +| | +| cafeed28 03 Nov 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "RedSquareKeyroxController.h" #include "RedSquareKeyroxTKLClassicController.h" -#include "RGBController.h" #include "RGBController_RedSquareKeyrox.h" #include "RGBController_RedSquareKeyroxTKLClassic.h" -#include /*-----------------------------------------------------*\ | Red Square vendor ID | @@ -16,6 +26,7 @@ | Red Square product ID | \*-----------------------------------------------------*/ #define RED_SQUARE_KEYROX_TKL_PID 0x1511 +#define RED_SQUARE_KEYROX_TKL_V2_PID 0x2511 #define RED_SQUARE_KEYROX_TKL_CLASSIC_PID 0xC345 void DetectRedSquareKeyroxTKL(hid_device_info* info, const std::string& name) @@ -24,9 +35,8 @@ void DetectRedSquareKeyroxTKL(hid_device_info* info, const std::string& name) if(dev) { - RedSquareKeyroxController* controller = new RedSquareKeyroxController(dev, *info, KEYROX_VARIANT_TKL); + RedSquareKeyroxController* controller = new RedSquareKeyroxController(dev, *info, KEYROX_VARIANT_TKL, name); RGBController_RedSquareKeyrox* rgb_controller = new RGBController_RedSquareKeyrox(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } @@ -37,13 +47,13 @@ void DetectRedSquareKeyroxTKLClassic(hid_device_info* info, const std::string& n if(dev) { - RedSquareKeyroxTKLClassicController* controller = new RedSquareKeyroxTKLClassicController(dev, *info); + RedSquareKeyroxTKLClassicController* controller = new RedSquareKeyroxTKLClassicController(dev, *info, name); RGBController_RedSquareKeyroxTKLClassic* rgb_controller = new RGBController_RedSquareKeyroxTKLClassic(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } -REGISTER_HID_DETECTOR_IPU("Red Square Keyrox TKL", DetectRedSquareKeyroxTKL, RED_SQUARE_VID, RED_SQUARE_KEYROX_TKL_PID, 3, 0xFF00, 2); -REGISTER_HID_DETECTOR_I("Red Square Keyrox TKL Classic", DetectRedSquareKeyroxTKLClassic, RED_SQUARE_KEYROX_TKL_CLASSIC_VID, RED_SQUARE_KEYROX_TKL_CLASSIC_PID, 2); +REGISTER_HID_DETECTOR_IPU("Red Square Keyrox TKL", DetectRedSquareKeyroxTKL, RED_SQUARE_VID, RED_SQUARE_KEYROX_TKL_PID, 3, 0xFF00, 2); +REGISTER_HID_DETECTOR_IPU("Red Square Keyrox TKL V2", DetectRedSquareKeyroxTKL, RED_SQUARE_VID, RED_SQUARE_KEYROX_TKL_V2_PID, 3, 0xFF00, 2); +REGISTER_HID_DETECTOR_I( "Red Square Keyrox TKL Classic", DetectRedSquareKeyroxTKLClassic, RED_SQUARE_KEYROX_TKL_CLASSIC_VID, RED_SQUARE_KEYROX_TKL_CLASSIC_PID, 2); diff --git a/Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController.h b/Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController.h deleted file mode 100644 index ef28df68..00000000 --- a/Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController.h +++ /dev/null @@ -1,73 +0,0 @@ -/*---------------------------------------------*\ -| RedSquareKeyroxTKLClassicController.h | -| | -| Driver for Red Square Keyrox USB Controller | -| | -| vlack 3 May 2023 | -\*---------------------------------------------*/ - -#pragma once -#include -#include - -#include "RGBController.h" - -#define CLASSIC_PACKET_DATA_LENGTH 64 - -/*---------------------------------------*\ -| Modes | -\*---------------------------------------*/ -enum -{ - CLASSIC_CONST_MODE_VALUE = 0x00, // static - CLASSIC_BREATHE_MODE_VALUE = 0x01, // breath - CLASSIC_WAVE_MODE_VALUE = 0x02, // wave - CLASSIC_FADE_MODE_VALUE = 0x03, // neon - CLASSIC_RADAR_MODE_VALUE = 0x04, // radar - CLASSIC_STAR_MODE_VALUE = 0x06, // интерактив - CLASSIC_LINE_MODE_VALUE = 0x07, // ÑиÑние - CLASSIC_RIPPLE_MODE_VALUE = 0x08, // Ñ€Ñбь интерактив - CLASSIC_STARS_MODE_VALUE = 0x09, // мерцание - CLASSIC_CUSTOM_MODE_VALUE = 0x0A, - CLASSIC_CROSS_MODE_VALUE = 0x0B, // Ñкрещивание - CLASSIC_WTF_MODE_VALUE = 0x0C, // быÑтрый отклик - CLASSIC_RIPPLE_RANDOM_MODE_VALUE = 0x0E, // Ñ€Ñбь - CLASSIC_RUNNING_LINE_MODE_VALUE = 0x0F, // Ð±ÐµÐ³ÑƒÑ‰Ð°Ñ Ñтрока - CLASSIC_FIREWORK_MODE_VALUE = 0x10, // firework -}; - -/*-----------------------------*\ -| Other settings | -\*-----------------------------*/ -enum -{ - CLASSIC_KEYROX_BRIGHTNESS_MIN = 0x00, - CLASSIC_KEYROX_BRIGHTNESS_MAX = 0x04, - CLASSIC_KEYROX_SPEED_MIN = 0x00, - CLASSIC_KEYROX_SPEED_MAX = 0x04, -}; - - -class RedSquareKeyroxTKLClassicController -{ -public: - RedSquareKeyroxTKLClassicController(hid_device *dev_handle, const hid_device_info &info); - ~RedSquareKeyroxTKLClassicController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - - int GetDirection(int direction); - int GetDirectionRound(int direction); - - void SetMode(mode m); - void SetLEDsData(std::vector colors, std::vector leds); - -protected: - hid_device* dev; - -private: - std::string location; - std::string serial_number; - std::vector led_sequence_positions; -}; diff --git a/Controllers/RedSquareKeyroxController/RGBController_RedSquareKeyroxTKLClassic.cpp b/Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController/RGBController_RedSquareKeyroxTKLClassic.cpp similarity index 84% rename from Controllers/RedSquareKeyroxController/RGBController_RedSquareKeyroxTKLClassic.cpp rename to Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController/RGBController_RedSquareKeyroxTKLClassic.cpp index 8f0b6c91..c19710ee 100644 --- a/Controllers/RedSquareKeyroxController/RGBController_RedSquareKeyroxTKLClassic.cpp +++ b/Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController/RGBController_RedSquareKeyroxTKLClassic.cpp @@ -1,11 +1,13 @@ -/*-------------------------------------------------------*\ -| RGBController_RedSquareKeyroxTKLClassic.cpp | -| | -| Driver for Red Square Keyrox USB Controller | -| Based on Keyrox TKL Controller by cafeed28 | -| | -| vlack 3 May 2023 | -\*-------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_RedSquareKeyroxTKLClassic.cpp | +| | +| RGBController for Red Square Keyrox TKL Classic | +| | +| vlack 03 May 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_RedSquareKeyroxTKLClassic.h" @@ -39,10 +41,10 @@ layout_values keyrox_tkl_offset_values = 83, 86, 89, 92, 95, 98, 101, 104, 107, 110, 113, 116, 119, 135, 138, 141, 144, /* TAB Q W E R T Y U I O P [ ] \ DEL END PGDN */ 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 199, 202, 205, 211, 214, 217, 220, - /* CPLK A S D F G H J K L ; " ENTR */ - 235, 241, 244, 247, 250, 263, 266, 269, 272, 275, 278, 281, 287, - /* LSFT Z X C V B N M , . / RSFT ARWU */ - 311, 327, 330, 333, 336, 339, 342, 345, 348, 351, 354, 363, 369, + /* CPLK A S D F G H J K L ; " # ENTR */ + 235, 241, 244, 247, 250, 263, 266, 269, 272, 275, 278, 281, 284, 287, + /* LSFT ISO\ Z X C V B N M , . / RSFT ARWU */ + 311, 314, 327, 330, 333, 336, 339, 342, 345, 348, 351, 354, 363, 369, /* LCTL LWIN LALT SPC RALT RFNC RMNU RCTL ARWR ARWD ARWR */ 397, 400, 403, 415, 427, 430, 433, 436, 442, 455, 458 }, @@ -53,16 +55,16 @@ layout_values keyrox_tkl_offset_values = RGBController_RedSquareKeyroxTKLClassic::RGBController_RedSquareKeyroxTKLClassic(RedSquareKeyroxTKLClassicController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Red Square Keyrox TKL Classic"; - vendor = "Red Square"; - type = DEVICE_TYPE_KEYBOARD; - description = name; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "Red Square"; + type = DEVICE_TYPE_KEYBOARD; + description = "Red Square Keyrox TKL Classic Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); - int BASE_EFFECT_FLAGS = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + int BASE_EFFECT_FLAGS = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; const int EFFECTS_COUNT = 14; keyrox_effect keyrox_effects[EFFECTS_COUNT] = @@ -232,8 +234,8 @@ void RGBController_RedSquareKeyroxTKLClassic::SetupZones() { led new_led; - new_led.name = new_kb.GetKeyNameAt(led_idx); - new_led.value = new_kb.GetKeyValueAt(led_idx); + new_led.name = new_kb.GetKeyNameAt((unsigned int)led_idx); + new_led.value = new_kb.GetKeyValueAt((unsigned int)led_idx); leds.push_back(new_led); } diff --git a/Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController/RGBController_RedSquareKeyroxTKLClassic.h b/Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController/RGBController_RedSquareKeyroxTKLClassic.h new file mode 100644 index 00000000..6b39f7cf --- /dev/null +++ b/Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController/RGBController_RedSquareKeyroxTKLClassic.h @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| RGBController_RedSquareKeyroxTKLClassic.h | +| | +| RGBController for Red Square Keyrox TKL Classic | +| | +| vlack 03 May 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RGBControllerKeyNames.h" +#include "KeyboardLayoutManager.h" +#include "RedSquareKeyroxTKLClassicController.h" + +#define KEYROX_TKL_CLASSIC_WIDTH 17 +#define KEYROX_TKL_CLASSIC_HEIGHT 6 + +class RGBController_RedSquareKeyroxTKLClassic : public RGBController +{ +public: + RGBController_RedSquareKeyroxTKLClassic(RedSquareKeyroxTKLClassicController* controller_ptr); + ~RGBController_RedSquareKeyroxTKLClassic(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RedSquareKeyroxTKLClassicController* controller; +}; diff --git a/Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController.cpp b/Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController/RedSquareKeyroxTKLClassicController.cpp similarity index 84% rename from Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController.cpp rename to Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController/RedSquareKeyroxTKLClassicController.cpp index c143b24b..40080cf6 100644 --- a/Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController.cpp +++ b/Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController/RedSquareKeyroxTKLClassicController.cpp @@ -1,21 +1,24 @@ -/*-------------------------------------------------------*\ -| RedSquareKeyroxTKLClassicController.cpp | -| | -| Driver for Red Square Keyrox USB Controller | -| Based on Keyrox TKL Controller by cafeed28 | -| | -| vlack 3 May 2023 | -\*-------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RedSquareKeyroxTKLClassicController.cpp | +| | +| Driver for Red Square Keyrox TKL Classic | +| | +| vlack 03 May 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "LogManager.h" #include "RedSquareKeyroxTKLClassicController.h" using namespace std::chrono_literals; -RedSquareKeyroxTKLClassicController::RedSquareKeyroxTKLClassicController(hid_device *dev_handle, const hid_device_info &info) +RedSquareKeyroxTKLClassicController::RedSquareKeyroxTKLClassicController(hid_device *dev_handle, const hid_device_info &info, std::string dev_name) { dev = dev_handle; location = info.path; + name = dev_name; } RedSquareKeyroxTKLClassicController::~RedSquareKeyroxTKLClassicController() @@ -28,6 +31,11 @@ std::string RedSquareKeyroxTKLClassicController::GetDeviceLocation() return("HID: " + location); } +std::string RedSquareKeyroxTKLClassicController::GetNameString() +{ + return(name); +} + std::string RedSquareKeyroxTKLClassicController::GetSerialString() { wchar_t serial_wchar[128]; diff --git a/Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController/RedSquareKeyroxTKLClassicController.h b/Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController/RedSquareKeyroxTKLClassicController.h new file mode 100644 index 00000000..a0e1d32d --- /dev/null +++ b/Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController/RedSquareKeyroxTKLClassicController.h @@ -0,0 +1,78 @@ +/*---------------------------------------------------------*\ +| RedSquareKeyroxTKLClassicController.h | +| | +| Driver for Red Square Keyrox TKL Classic | +| | +| vlack 03 May 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define CLASSIC_PACKET_DATA_LENGTH 64 + +/*---------------------------------------*\ +| Modes | +\*---------------------------------------*/ +enum +{ + CLASSIC_CONST_MODE_VALUE = 0x00, // static + CLASSIC_BREATHE_MODE_VALUE = 0x01, // breath + CLASSIC_WAVE_MODE_VALUE = 0x02, // wave + CLASSIC_FADE_MODE_VALUE = 0x03, // neon + CLASSIC_RADAR_MODE_VALUE = 0x04, // radar + CLASSIC_STAR_MODE_VALUE = 0x06, // интерактив + CLASSIC_LINE_MODE_VALUE = 0x07, // ÑиÑние + CLASSIC_RIPPLE_MODE_VALUE = 0x08, // Ñ€Ñбь интерактив + CLASSIC_STARS_MODE_VALUE = 0x09, // мерцание + CLASSIC_CUSTOM_MODE_VALUE = 0x0A, + CLASSIC_CROSS_MODE_VALUE = 0x0B, // Ñкрещивание + CLASSIC_WTF_MODE_VALUE = 0x0C, // быÑтрый отклик + CLASSIC_RIPPLE_RANDOM_MODE_VALUE = 0x0E, // Ñ€Ñбь + CLASSIC_RUNNING_LINE_MODE_VALUE = 0x0F, // Ð±ÐµÐ³ÑƒÑ‰Ð°Ñ Ñтрока + CLASSIC_FIREWORK_MODE_VALUE = 0x10, // firework +}; + +/*-----------------------------*\ +| Other settings | +\*-----------------------------*/ +enum +{ + CLASSIC_KEYROX_BRIGHTNESS_MIN = 0x00, + CLASSIC_KEYROX_BRIGHTNESS_MAX = 0x04, + CLASSIC_KEYROX_SPEED_MIN = 0x00, + CLASSIC_KEYROX_SPEED_MAX = 0x04, +}; + + +class RedSquareKeyroxTKLClassicController +{ +public: + RedSquareKeyroxTKLClassicController(hid_device *dev_handle, const hid_device_info &info, std::string dev_name); + ~RedSquareKeyroxTKLClassicController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + int GetDirection(int direction); + int GetDirectionRound(int direction); + + void SetMode(mode m); + void SetLEDsData(std::vector colors, std::vector leds); + +protected: + hid_device* dev; + +private: + std::string location; + std::string name; + std::string serial_number; + std::vector led_sequence_positions; +}; diff --git a/Controllers/RedragonController/RGBController_RedragonMouse.cpp b/Controllers/RedragonController/RGBController_RedragonMouse.cpp index af903034..428b2644 100644 --- a/Controllers/RedragonController/RGBController_RedragonMouse.cpp +++ b/Controllers/RedragonController/RGBController_RedragonMouse.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_RedragonMouse.cpp | -| | -| Generic RGB Interface for Redragon Mouse | -| | -| Adam Honse (CalcProgrammer1) 3/25/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_RedragonMouse.cpp | +| | +| RGBController for Redragon mouse | +| | +| Adam Honse (CalcProgrammer1) 25 Mar 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_RedragonMouse.h" @@ -21,48 +24,48 @@ RGBController_RedragonMouse::RGBController_RedragonMouse(RedragonMouseController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Redragon Mouse Device"; - vendor = "Redragon"; - type = DEVICE_TYPE_MOUSE; - description = "Redragon Mouse Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "Redragon"; + type = DEVICE_TYPE_MOUSE; + description = "Redragon Mouse Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Static; - Static.name = "Static"; - Static.value = REDRAGON_MOUSE_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Static.color_mode = MODE_COLORS_PER_LED; + Static.name = "Static"; + Static.value = REDRAGON_MOUSE_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Static.color_mode = MODE_COLORS_PER_LED; modes.push_back(Static); mode Wave; - Wave.name = "Wave"; - Wave.value = REDRAGON_MOUSE_MODE_WAVE; - Wave.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Wave.color_mode = MODE_COLORS_PER_LED; + Wave.name = "Wave"; + Wave.value = REDRAGON_MOUSE_MODE_WAVE; + Wave.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Wave.color_mode = MODE_COLORS_PER_LED; modes.push_back(Wave); mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = REDRAGON_MOUSE_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.name = "Breathing"; + Breathing.value = REDRAGON_MOUSE_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.color_mode = MODE_COLORS_PER_LED; modes.push_back(Breathing); mode Rainbow; - Rainbow.name = "Rainbow"; - Rainbow.value = REDRAGON_MOUSE_MODE_RAINBOW; - Rainbow.flags = MODE_FLAG_AUTOMATIC_SAVE; - Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.name = "Rainbow"; + Rainbow.value = REDRAGON_MOUSE_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_AUTOMATIC_SAVE; + Rainbow.color_mode = MODE_COLORS_NONE; modes.push_back(Rainbow); mode Flashing; - Flashing.name = "Flashing"; - Flashing.value = REDRAGON_MOUSE_MODE_FLASHING; - Flashing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Flashing.color_mode = MODE_COLORS_PER_LED; + Flashing.name = "Flashing"; + Flashing.value = REDRAGON_MOUSE_MODE_FLASHING; + Flashing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Flashing.color_mode = MODE_COLORS_PER_LED; modes.push_back(Flashing); SetupZones(); @@ -76,16 +79,16 @@ RGBController_RedragonMouse::~RGBController_RedragonMouse() void RGBController_RedragonMouse::SetupZones() { zone mouse_zone; - mouse_zone.name = "Mouse"; - mouse_zone.type = ZONE_TYPE_SINGLE; - mouse_zone.leds_min = REDRAGON_MOUSE_LED_COUNT; - mouse_zone.leds_max = REDRAGON_MOUSE_LED_COUNT; - mouse_zone.leds_count = REDRAGON_MOUSE_LED_COUNT; - mouse_zone.matrix_map = NULL; + mouse_zone.name = "Mouse"; + mouse_zone.type = ZONE_TYPE_SINGLE; + mouse_zone.leds_min = REDRAGON_MOUSE_LED_COUNT; + mouse_zone.leds_max = REDRAGON_MOUSE_LED_COUNT; + mouse_zone.leds_count = REDRAGON_MOUSE_LED_COUNT; + mouse_zone.matrix_map = NULL; zones.push_back(mouse_zone); led mouse_led; - mouse_led.name = "Mouse"; + mouse_led.name = "Mouse"; leds.push_back(mouse_led); SetupColors(); diff --git a/Controllers/RedragonController/RGBController_RedragonMouse.h b/Controllers/RedragonController/RGBController_RedragonMouse.h index 9f37888e..a389ec57 100644 --- a/Controllers/RedragonController/RGBController_RedragonMouse.h +++ b/Controllers/RedragonController/RGBController_RedragonMouse.h @@ -1,10 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_RedragonMouse.h | -| | -| Generic RGB Interface for Redragon Mouse | -| | -| Adam Honse (CalcProgrammer1) 3/25/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_RedragonMouse.h | +| | +| RGBController for Redragon mouse | +| | +| Adam Honse (CalcProgrammer1) 25 Mar 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include "RGBController.h" @@ -18,7 +22,7 @@ public: void SetupZones(); void ResizeZone(int zone, int new_size); - + void DeviceUpdateLEDs(); void UpdateZoneLEDs(int zone); void UpdateSingleLED(int led); diff --git a/Controllers/RedragonController/RedragonControllerDetect.cpp b/Controllers/RedragonController/RedragonControllerDetect.cpp index 9d1f0a48..1249cfee 100644 --- a/Controllers/RedragonController/RedragonControllerDetect.cpp +++ b/Controllers/RedragonController/RedragonControllerDetect.cpp @@ -1,9 +1,18 @@ +/*---------------------------------------------------------*\ +| RedragonControllerDetect.cpp | +| | +| Detector for Redragon devices | +| | +| Adam Honse (CalcProgrammer1) 15 Mar 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "RedragonMouseController.h" -#include "RGBController.h" #include "RGBController_RedragonMouse.h" -#include -#include /*-----------------------------------------------------*\ | Mouse product IDs | @@ -16,6 +25,8 @@ #define REDRAGON_M908_PID 0xFC4D #define REDRAGON_M602_PID 0xFC38 #define REDRAGON_M808_PID 0xFC5F +#define REDRAGON_M801_PID 0xFC58 +#define REDRAGON_M810_PID 0xFA7E /******************************************************************************************\ * * @@ -28,11 +39,12 @@ void DetectRedragonMice(hid_device_info* info, const std::string& name) { hid_device* dev = hid_open_path(info->path); - if( dev ) + + if(dev) { - RedragonMouseController* controller = new RedragonMouseController(dev, info->path); + RedragonMouseController* controller = new RedragonMouseController(dev, info->path, name); RGBController_RedragonMouse* rgb_controller = new RGBController_RedragonMouse(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -46,3 +58,5 @@ REGISTER_HID_DETECTOR_IP("Redragon M716 Inquisitor", DetectRedragonMice, RE REGISTER_HID_DETECTOR_IP("Redragon M908 Impact", DetectRedragonMice, REDRAGON_MOUSE_VID, REDRAGON_M908_PID, 2, REDRAGON_MOUSE_USAGE_PAGE); REGISTER_HID_DETECTOR_IP("Redragon M602 Griffin", DetectRedragonMice, REDRAGON_MOUSE_VID, REDRAGON_M602_PID, 2, REDRAGON_MOUSE_USAGE_PAGE); REGISTER_HID_DETECTOR_IP("Redragon M808 Storm", DetectRedragonMice, REDRAGON_MOUSE_VID, REDRAGON_M808_PID, 2, REDRAGON_MOUSE_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("Redragon M801 Sniper", DetectRedragonMice, REDRAGON_MOUSE_VID, REDRAGON_M801_PID, 2, REDRAGON_MOUSE_USAGE_PAGE); +REGISTER_HID_DETECTOR_IP("Redragon M810 Taipan", DetectRedragonMice, REDRAGON_MOUSE_VID, REDRAGON_M810_PID, 2, REDRAGON_MOUSE_USAGE_PAGE); diff --git a/Controllers/RedragonController/RedragonMouseController.cpp b/Controllers/RedragonController/RedragonMouseController.cpp index 53af0a0f..a04f2a5f 100644 --- a/Controllers/RedragonController/RedragonMouseController.cpp +++ b/Controllers/RedragonController/RedragonMouseController.cpp @@ -1,11 +1,23 @@ -#include "RedragonMouseController.h" +/*---------------------------------------------------------*\ +| RedragonMouseController.cpp | +| | +| Driver for Redragon mouse | +| | +| Adam Honse (CalcProgrammer1) 15 Mar 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "RedragonMouseController.h" +#include "StringUtils.h" -RedragonMouseController::RedragonMouseController(hid_device* dev_handle, const char* path) +RedragonMouseController::RedragonMouseController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; unsigned char active_profile = 0x00; @@ -23,6 +35,11 @@ std::string RedragonMouseController::GetDeviceLocation() return("HID: " + location); } +std::string RedragonMouseController::GetNameString() +{ + return(name); +} + std::string RedragonMouseController::GetSerialString() { wchar_t serial_string[128]; @@ -33,10 +50,7 @@ std::string RedragonMouseController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void RedragonMouseController::SendMouseColor @@ -97,7 +111,7 @@ void RedragonMouseController::SendMouseMode void RedragonMouseController::SendMouseApply() { - char usb_buf[REDRAGON_MOUSE_REPORT_SIZE]; + unsigned char usb_buf[REDRAGON_MOUSE_REPORT_SIZE]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -111,11 +125,11 @@ void RedragonMouseController::SendMouseApply() usb_buf[0x01] = 0xF1; usb_buf[0x02] = 0x02; usb_buf[0x03] = 0x04; - + /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_send_feature_report(dev, (unsigned char *)usb_buf, REDRAGON_MOUSE_REPORT_SIZE); + hid_send_feature_report(dev, usb_buf, REDRAGON_MOUSE_REPORT_SIZE); } void RedragonMouseController::SendWritePacket @@ -125,7 +139,7 @@ void RedragonMouseController::SendWritePacket unsigned char * data ) { - char usb_buf[REDRAGON_MOUSE_REPORT_SIZE]; + unsigned char usb_buf[REDRAGON_MOUSE_REPORT_SIZE]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -145,9 +159,9 @@ void RedragonMouseController::SendWritePacket | Copy in data bytes | \*-----------------------------------------------------*/ memcpy(&usb_buf[0x08], data, data_size); - + /*-----------------------------------------------------*\ | Send packet | \*-----------------------------------------------------*/ - hid_send_feature_report(dev, (unsigned char *)usb_buf, REDRAGON_MOUSE_REPORT_SIZE); + hid_send_feature_report(dev, usb_buf, REDRAGON_MOUSE_REPORT_SIZE); } diff --git a/Controllers/RedragonController/RedragonMouseController.h b/Controllers/RedragonController/RedragonMouseController.h index c9fbfcac..0958bdea 100644 --- a/Controllers/RedragonController/RedragonMouseController.h +++ b/Controllers/RedragonController/RedragonMouseController.h @@ -1,15 +1,18 @@ -/*-----------------------------------------*\ -| RedragonMouseController.h | -| | -| Definitions and types for Redragon Mouse | -| lighting controller | -| | -| Adam Honse (CalcProgrammer1) 3/15/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RedragonMouseController.h | +| | +| Driver for Redragon mouse | +| | +| Adam Honse (CalcProgrammer1) 15 Mar 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include -#include +#include #define REDRAGON_MOUSE_REPORT_ID 0x02 #define REDRAGON_MOUSE_REPORT_SIZE 16 @@ -28,10 +31,11 @@ enum class RedragonMouseController { public: - RedragonMouseController(hid_device* dev_handle, const char* path); + RedragonMouseController(hid_device* dev_handle, const char* path, std::string dev_name); ~RedragonMouseController(); std::string GetDeviceLocation(); + std::string GetNameString(); std::string GetSerialString(); void SendMouseApply(); @@ -59,8 +63,9 @@ public: ); private: - hid_device* dev; - std::string location; + hid_device* dev; + std::string location; + std::string name; void SendWritePacket ( diff --git a/Controllers/RoccatController/RGBController_RoccatBurst.h b/Controllers/RoccatController/RGBController_RoccatBurst.h deleted file mode 100644 index b5d223bf..00000000 --- a/Controllers/RoccatController/RGBController_RoccatBurst.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_RoccatBurst.h | -| | -| Generic RGB Interface for Roccat Burst | -| Core and Pro Mouse controller | -| | -| Morgan Guimard (morg) 6/01/2022 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "RoccatBurstController.h" - -class RGBController_RoccatBurst : public RGBController -{ -public: - RGBController_RoccatBurst(RoccatBurstController* controller_ptr, unsigned int leds_count); - ~RGBController_RoccatBurst(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - RoccatBurstController* controller; - unsigned int leds_count; -}; diff --git a/Controllers/RoccatController/RGBController_RoccatElo.cpp b/Controllers/RoccatController/RGBController_RoccatElo.cpp deleted file mode 100644 index ff4bceff..00000000 --- a/Controllers/RoccatController/RGBController_RoccatElo.cpp +++ /dev/null @@ -1,85 +0,0 @@ -#include "RGBController_RoccatElo.h" - -#include -#include - -/**------------------------------------------------------------------*\ - @name Roccat Elo 7.1 - @category Headset - @type USB - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectRoccatEloControllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_RoccatElo::RGBController_RoccatElo(RoccatEloController* controller_ptr) -{ - controller = controller_ptr; - name = "Roccat Elo 7.1"; - vendor = "Roccat"; - type = DEVICE_TYPE_HEADSET; - description = name; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - version = ""; - - mode Direct; - Direct.name = "Direct"; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - - SetupZones(); -} - -RGBController_RoccatElo::~RGBController_RoccatElo() -{ - delete controller; -} - -void RGBController_RoccatElo::SetupZones() -{ - zone new_zone; - - new_zone.name = "Headset"; - new_zone.type = ZONE_TYPE_LINEAR; - new_zone.leds_min = ROCCAT_ELO_LEDS_COUNT; - new_zone.leds_max = ROCCAT_ELO_LEDS_COUNT; - new_zone.leds_count = ROCCAT_ELO_LEDS_COUNT; - new_zone.matrix_map = nullptr; - - zones.emplace_back(new_zone); - - leds.resize(new_zone.leds_count); - - SetupColors(); -} - -void RGBController_RoccatElo::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_RoccatElo::DeviceUpdateLEDs() -{ - controller->SendDirect(colors[0]); -} - -void RGBController_RoccatElo::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_RoccatElo::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_RoccatElo::DeviceUpdateMode() -{ - -} diff --git a/Controllers/RoccatController/RGBController_RoccatElo.h b/Controllers/RoccatController/RGBController_RoccatElo.h deleted file mode 100644 index 77871b3e..00000000 --- a/Controllers/RoccatController/RGBController_RoccatElo.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once - -#include "RGBController.h" -#include "RoccatEloController.h" - -class RGBController_RoccatElo : public RGBController -{ -public: - RGBController_RoccatElo(RoccatEloController* controller_ptr); - ~RGBController_RoccatElo(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - RoccatEloController* controller; -}; diff --git a/Controllers/RoccatController/RGBController_RoccatHordeAimo.cpp b/Controllers/RoccatController/RGBController_RoccatHordeAimo.cpp deleted file mode 100644 index 3b161ca3..00000000 --- a/Controllers/RoccatController/RGBController_RoccatHordeAimo.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_RoccatHordeAimo.cpp | -| | -| Generic RGB Interface for OpenRGB | -| | -| | -| Morgan Guimard (morg) 2/24/2022 | -\*-----------------------------------------*/ - -#include "RGBController_RoccatHordeAimo.h" - -/**------------------------------------------------------------------*\ - @name Roccat Horde Aimo - @category Keyboard - @type USB - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectRoccatHordeAimoKeyboardControllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_RoccatHordeAimo::RGBController_RoccatHordeAimo(RoccatHordeAimoController* controller_ptr) -{ - controller = controller_ptr; - - name = "Roccat Horde Aimo"; - vendor = "Roccat"; - type = DEVICE_TYPE_KEYBOARD; - description = "Roccat Horde Aimo Keyboard"; - - 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(); -} - -RGBController_RoccatHordeAimo::~RGBController_RoccatHordeAimo() -{ - delete controller; -} - -void RGBController_RoccatHordeAimo::SetupZones() -{ - zone new_zone; - new_zone.name = "Keyboard"; - new_zone.type = ZONE_TYPE_LINEAR; - new_zone.leds_min = NUMBER_OF_LEDS; - new_zone.leds_max = NUMBER_OF_LEDS; - new_zone.leds_count = NUMBER_OF_LEDS; - new_zone.matrix_map = NULL; - zones.push_back(new_zone); - - for(unsigned int i = 0; i < NUMBER_OF_LEDS; i++) - { - led new_led; - new_led.name = "LED " + std::to_string(i + 1); - leds.push_back(new_led); - } - - SetupColors(); -} - -void RGBController_RoccatHordeAimo::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_RoccatHordeAimo::DeviceUpdateLEDs() -{ - UpdateZoneLEDs(0); -} - -void RGBController_RoccatHordeAimo::UpdateZoneLEDs(int /*zone_idx*/) -{ - controller->SetColors(colors); -} - -void RGBController_RoccatHordeAimo::UpdateSingleLED(int /*led_idx*/) -{ - UpdateZoneLEDs(0); -} - -void RGBController_RoccatHordeAimo::DeviceUpdateMode() -{ - -} diff --git a/Controllers/RoccatController/RGBController_RoccatHordeAimo.h b/Controllers/RoccatController/RGBController_RoccatHordeAimo.h deleted file mode 100644 index 6ea336c4..00000000 --- a/Controllers/RoccatController/RGBController_RoccatHordeAimo.h +++ /dev/null @@ -1,31 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_RoccatHordeAimo.h | -| | -| Generic RGB Interface for Roccat Horde | -| Aimo Keyboard controller | -| | -| Morgan Guimard (morg) 2/24/2022 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "RoccatHordeAimoController.h" - -class RGBController_RoccatHordeAimo : public RGBController -{ -public: - RGBController_RoccatHordeAimo(RoccatHordeAimoController* controller_ptr); - ~RGBController_RoccatHordeAimo(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - RoccatHordeAimoController* controller; -}; diff --git a/Controllers/RoccatController/RGBController_RoccatKoneAimo.cpp b/Controllers/RoccatController/RGBController_RoccatKoneAimo.cpp deleted file mode 100644 index d713e418..00000000 --- a/Controllers/RoccatController/RGBController_RoccatKoneAimo.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_RoccatKoneAimo.cpp | -| | -| Generic RGB Interface for OpenRGB | -| | -| | -| Thibaud M (enlight3d) 17/11/2020 | -\*-----------------------------------------*/ - -#include "RGBController_RoccatKoneAimo.h" - -/**------------------------------------------------------------------*\ - @name Roccat Kone Aimo - @category Mouse - @type USB - @save :x: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectRoccatMouseControllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_RoccatKoneAimo::RGBController_RoccatKoneAimo(RoccatKoneAimoController* controller_ptr) -{ - controller = controller_ptr; - - name = "Roccat Kone Aimo"; - vendor = "Roccat"; - type = DEVICE_TYPE_MOUSE; - description = "Roccat Kone Aimo Mouse"; - location = controller->GetLocation(); - serial = controller->GetSerial(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = 0; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.speed_min = 0; - Direct.speed_max = 0; - Direct.speed = 0; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - - active_mode = 0; - - SetupZones(); -} - -RGBController_RoccatKoneAimo::~RGBController_RoccatKoneAimo() -{ - delete controller; -} - -void RGBController_RoccatKoneAimo::SetupZones() -{ - /*---------------------------------------------------------*\ - | Set up zones and leds per zone | - \*---------------------------------------------------------*/ - zone WHEEL_zone; - WHEEL_zone.name = "Scroll Wheel"; - WHEEL_zone.type = ZONE_TYPE_SINGLE; - WHEEL_zone.leds_min = 1; - WHEEL_zone.leds_max = 1; - WHEEL_zone.leds_count = 1; - WHEEL_zone.matrix_map = NULL; - zones.push_back(WHEEL_zone); - zones_channel.push_back(SCROLL_WHEEL); - - led WHEEL_led; - WHEEL_led.name = "Wheel LED"; - WHEEL_led.value = zones.size(); - leds.push_back(WHEEL_led); - leds_channel.push_back(SCROLL_WHEEL); - - zone STRIP_LEFT_zone; - STRIP_LEFT_zone.name = "Strip left"; - STRIP_LEFT_zone.type = ZONE_TYPE_LINEAR; - STRIP_LEFT_zone.leds_min = 4; - STRIP_LEFT_zone.leds_max = 4; - STRIP_LEFT_zone.leds_count = 4; - STRIP_LEFT_zone.matrix_map = NULL; - zones.push_back(STRIP_LEFT_zone); - zones_channel.push_back(STRIP_LEFT); - - for(std::size_t led_idx = 0; led_idx < STRIP_LEFT_zone.leds_max; led_idx++) - { - led STRIP_LEFT_led; - STRIP_LEFT_led.name = "Strip left LED " + std::to_string(led_idx + 1); - STRIP_LEFT_led.value = zones.size(); - leds.push_back(STRIP_LEFT_led); - leds_channel.push_back(STRIP_LEFT); - } - - zone STRIP_RIGHT_zone; - STRIP_RIGHT_zone.name = "Strip right"; - STRIP_RIGHT_zone.type = ZONE_TYPE_LINEAR; - STRIP_RIGHT_zone.leds_min = 4; - STRIP_RIGHT_zone.leds_max = 4; - STRIP_RIGHT_zone.leds_count = 4; - STRIP_RIGHT_zone.matrix_map = NULL; - zones.push_back(STRIP_RIGHT_zone); - zones_channel.push_back(STRIP_RIGHT); - - for(std::size_t led_idx = 0; led_idx < STRIP_RIGHT_zone.leds_max; led_idx++) - { - led STRIP_RIGHT_led; - STRIP_RIGHT_led.name = "Strip right LED " + std::to_string(led_idx + 1); - STRIP_RIGHT_led.value = zones.size(); - leds.push_back(STRIP_RIGHT_led); - leds_channel.push_back(STRIP_RIGHT); - } - - zone LOWER_LEFT_zone; - LOWER_LEFT_zone.name = "Lower left"; - LOWER_LEFT_zone.type = ZONE_TYPE_SINGLE; - LOWER_LEFT_zone.leds_min = 1; - LOWER_LEFT_zone.leds_max = 1; - LOWER_LEFT_zone.leds_count = 1; - LOWER_LEFT_zone.matrix_map = NULL; - zones.push_back(LOWER_LEFT_zone); - zones_channel.push_back(LOWER_LEFT); - - led LOWER_LEFT_led; - LOWER_LEFT_led.name = "Lower left LED"; - LOWER_LEFT_led.value = zones.size(); - leds.push_back(LOWER_LEFT_led); - leds_channel.push_back(LOWER_LEFT); - - zone LOWER_RIGHT_zone; - LOWER_RIGHT_zone.name = "Lower right"; - LOWER_RIGHT_zone.type = ZONE_TYPE_SINGLE; - LOWER_RIGHT_zone.leds_min = 1; - LOWER_RIGHT_zone.leds_max = 1; - LOWER_RIGHT_zone.leds_count = 1; - LOWER_RIGHT_zone.matrix_map = NULL; - zones.push_back(LOWER_RIGHT_zone); - zones_channel.push_back(LOWER_RIGHT); - - led LOWER_RIGHT_led; - LOWER_RIGHT_led.name = "Lower right LED"; - LOWER_RIGHT_led.value = zones.size(); - leds.push_back(LOWER_RIGHT_led); - leds_channel.push_back(LOWER_RIGHT); - - SetupColors(); - - /*---------------------------------------------------------*\ - | Initialize colors for each LED | - \*---------------------------------------------------------*/ - for(std::size_t led_idx = 0; led_idx < leds.size(); led_idx++) - { - unsigned char red = 0x00; - unsigned char grn = 0x00; - unsigned char blu = 0x00; - - colors[led_idx] = ToRGBColor(red, grn, blu); - } -} - -void RGBController_RoccatKoneAimo::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_RoccatKoneAimo::DeviceUpdateLEDs() -{ - /*---------------------------------------------------------*\ - | Set colors for all channel/leds | - \*---------------------------------------------------------*/ - for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) - { - controller->SetChannelColors(zones_channel[zone_idx], zones[zone_idx].colors, zones[zone_idx].leds_count); - } - /*---------------------------------------------------------*\ - | Apply new colors to the mouse | - \*---------------------------------------------------------*/ - controller->SendUpdate(); -} - -void RGBController_RoccatKoneAimo::UpdateZoneLEDs(int zone_idx) -{ - /*---------------------------------------------------------*\ - | Set colors for one channel of leds | - \*---------------------------------------------------------*/ - controller->SetChannelColors(zones_channel[zone_idx], zones[zone_idx].colors, zones[zone_idx].leds_count); - /*---------------------------------------------------------*\ - | Apply new colors to the mouse | - \*---------------------------------------------------------*/ - controller->SendUpdate(); -} - -void RGBController_RoccatKoneAimo::UpdateSingleLED(int led_idx) -{ - /*---------------------------------------------------------*\ - | Get channel corresponding to led | - \*---------------------------------------------------------*/ - ROCCAT_KONE_AIMO_CHANNEL channel = leds_channel[led_idx]; - /*---------------------------------------------------------*\ - | Update channel corresponding to led | - \*---------------------------------------------------------*/ - controller->SetChannelColors(channel, zones[leds[led_idx].value].colors, zones[leds[led_idx].value].leds_count); - /*---------------------------------------------------------*\ - | Apply new colors to the mouse | - \*---------------------------------------------------------*/ - controller->SendUpdate(); -} - -void RGBController_RoccatKoneAimo::DeviceUpdateMode() -{ - /*---------------------------------------------------------*\ - | This device does not support changing mode | - \*---------------------------------------------------------*/ -} diff --git a/Controllers/RoccatController/RGBController_RoccatKoneAimo.h b/Controllers/RoccatController/RGBController_RoccatKoneAimo.h deleted file mode 100644 index 17cc3c2b..00000000 --- a/Controllers/RoccatController/RGBController_RoccatKoneAimo.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_RoccatKoneAimo.h | -| | -| Generic RGB Interface for Roccat Kone | -| Aimo controller | -| | -| Thibaud M (enlight3d) 17/11/2020 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "RoccatKoneAimoController.h" - -class RGBController_RoccatKoneAimo : public RGBController -{ -public: - RGBController_RoccatKoneAimo(RoccatKoneAimoController* controller_ptr); - ~RGBController_RoccatKoneAimo(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - RoccatKoneAimoController* controller; - std::vector zones_channel; - std::vector leds_channel; -}; diff --git a/Controllers/RoccatController/RGBController_RoccatKova.h b/Controllers/RoccatController/RGBController_RoccatKova.h deleted file mode 100644 index d3a551ee..00000000 --- a/Controllers/RoccatController/RGBController_RoccatKova.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_RoccatKova.h | -| | -| RGB Controller for Roccat Kova | -| | -| Gustash 01/12/2022 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "RoccatKovaController.h" - -class RGBController_RoccatKova : public RGBController -{ -public: - RGBController_RoccatKova(RoccatKovaController *controller_ptr); - ~RGBController_RoccatKova(); - - void SetupZones(); - - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - RoccatKovaController *controller; -}; diff --git a/Controllers/RoccatController/RGBController_RoccatVulcanAimo.cpp b/Controllers/RoccatController/RGBController_RoccatVulcanAimo.cpp deleted file mode 100644 index ff2c8af6..00000000 --- a/Controllers/RoccatController/RGBController_RoccatVulcanAimo.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_RoccatVulcanAimo.cpp | -| | -| Generic RGB Interface for OpenRGB | -| | -| | -| Mola19 17/12/2021 | -\*-----------------------------------------*/ - -#include "RGBControllerKeyNames.h" -#include "RGBController_RoccatVulcanAimo.h" -#include - -#define NA 0xFFFFFFFF - -/**------------------------------------------------------------------*\ - @name Roccat Vulcan Aimo - @category Keyboard - @type USB - @save :robot: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectRoccatVulcanAimoControllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_RoccatVulcanAimo::RGBController_RoccatVulcanAimo(RoccatVulcanAimoController* controller_ptr) -{ - controller = controller_ptr; - - controller->InitDeviceInfo(); - - name = "Roccat Vulcan 120-Series Aimo"; - vendor = "Roccat"; - type = DEVICE_TYPE_KEYBOARD; - description = "Roccat Vulcan Aimo Keyboard"; - version = controller->GetDeviceInfo().version; - location = controller->GetLocation(); - serial = controller->GetSerial(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = ROCCAT_VULCAN_MODE_DIRECT; - 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 = ROCCAT_VULCAN_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Static.brightness_min = ROCCAT_VULCAN_BRIGHTNESS_MIN; - Static.brightness_max = ROCCAT_VULCAN_BRIGHTNESS_MAX; - Static.brightness = ROCCAT_VULCAN_BRIGHTNESS_DEFAULT; - Static.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Static); - - mode Wave; - Wave.name = "Rainbow Wave"; - Wave.value = ROCCAT_VULCAN_MODE_WAVE; - Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Wave.speed_min = ROCCAT_VULCAN_SPEED_MIN; - Wave.speed_max = ROCCAT_VULCAN_SPEED_MAX; - Wave.speed = ROCCAT_VULCAN_SPEED_DEFAULT; - Wave.brightness_min = ROCCAT_VULCAN_BRIGHTNESS_MIN; - Wave.brightness_max = ROCCAT_VULCAN_BRIGHTNESS_MAX; - Wave.brightness = ROCCAT_VULCAN_BRIGHTNESS_DEFAULT; - Wave.color_mode = MODE_COLORS_NONE; - modes.push_back(Wave); - - SetupZones(); -} - -RGBController_RoccatVulcanAimo::~RGBController_RoccatVulcanAimo() -{ - delete controller; -} - -void RGBController_RoccatVulcanAimo::SetupZones() -{ - unsigned char layout = controller->GetDeviceInfo().layout_variant; - - if(RoccatVulcanLayouts.find(layout) == RoccatVulcanLayouts.end()) - { - /*---------------------------------------------------------*\ - | If Layout not found, take uk or us | - \*---------------------------------------------------------*/ - layout = controller->GetDeviceInfo().layout_type == 1 ? ROCCAT_VULCAN_LAYOUT_UK : ROCCAT_VULCAN_LAYOUT_US; - } - - zone keyboard_zone; - keyboard_zone.name = "Keyboard"; - keyboard_zone.type = ZONE_TYPE_MATRIX; - keyboard_zone.leds_min = RoccatVulcanLayouts[layout].size; - keyboard_zone.leds_max = RoccatVulcanLayouts[layout].size; - keyboard_zone.leds_count = RoccatVulcanLayouts[layout].size; - keyboard_zone.matrix_map = new matrix_map_type; - keyboard_zone.matrix_map->height = RoccatVulcanLayouts[layout].rows; - keyboard_zone.matrix_map->width = RoccatVulcanLayouts[layout].cols; - keyboard_zone.matrix_map->map = RoccatVulcanLayouts[layout].matrix_map; - zones.push_back(keyboard_zone); - - for(int led_id = 0; led_id < RoccatVulcanLayouts[layout].size; led_id++) - { - led new_led; - new_led.name = RoccatVulcanLayouts[layout].led_names[led_id].name; - new_led.value = RoccatVulcanLayouts[layout].led_names[led_id].id; - leds.push_back(new_led); - } - - SetupColors(); - - /*---------------------------------------------------------*\ - | sends the init packet for the default mode (direct) | - \*---------------------------------------------------------*/ - DeviceUpdateMode(); -} - -void RGBController_RoccatVulcanAimo::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_RoccatVulcanAimo::DeviceUpdateLEDs() -{ - if (modes[active_mode].value == ROCCAT_VULCAN_MODE_DIRECT) - { - std::vector led_color_list = {}; - - for(unsigned int i = 0; i < colors.size(); i++) - { - led_color_list.push_back({ leds[i].value, colors[i] }); - } - - controller->SendColors(led_color_list); - } - else - { - DeviceUpdateMode(); - } -} - -void RGBController_RoccatVulcanAimo::UpdateZoneLEDs(int /*zone_idx*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_RoccatVulcanAimo::UpdateSingleLED(int /*led_idx*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_RoccatVulcanAimo::DeviceUpdateMode() -{ - std::vector led_color_list = {}; - - if(modes[active_mode].value == ROCCAT_VULCAN_MODE_STATIC) - { - for(unsigned int i = 0; i < colors.size(); i++) - { - led_color_list.push_back({ leds[i].value, colors[i] }); - } - } - - controller->SendMode(modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, led_color_list); -} diff --git a/Controllers/RoccatController/RGBController_RoccatVulcanAimo.h b/Controllers/RoccatController/RGBController_RoccatVulcanAimo.h deleted file mode 100644 index cff4bf2a..00000000 --- a/Controllers/RoccatController/RGBController_RoccatVulcanAimo.h +++ /dev/null @@ -1,41 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_RoccatVulcanAimo.h | -| | -| Generic RGB Interface for Roccat Vulcan | -| Aimo controller | -| | -| Mola19 17/12/2021 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "RoccatVulcanAimoController.h" - -enum -{ - ROCCAT_VULCAN_SPEED_MIN = 0x01, - ROCCAT_VULCAN_SPEED_MAX = 0x0B, - ROCCAT_VULCAN_SPEED_DEFAULT = 0x06, - ROCCAT_VULCAN_BRIGHTNESS_MIN = 0x01, - ROCCAT_VULCAN_BRIGHTNESS_MAX = 0x45, - ROCCAT_VULCAN_BRIGHTNESS_DEFAULT = 0x45, -}; - -class RGBController_RoccatVulcanAimo : public RGBController -{ -public: - RGBController_RoccatVulcanAimo(RoccatVulcanAimoController* controller_ptr); - ~RGBController_RoccatVulcanAimo(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - RoccatVulcanAimoController* controller; -}; diff --git a/Controllers/RoccatController/RoccatBurstController.h b/Controllers/RoccatController/RoccatBurstController.h deleted file mode 100644 index 704167f4..00000000 --- a/Controllers/RoccatController/RoccatBurstController.h +++ /dev/null @@ -1,67 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RoccatBurstController.h | -| | -| Driver for Roccat Burst Core and Pro Mouse | -| | -| Morgan Guimard (morg) 6/01/2022 | -\*-------------------------------------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include - -#define ROCCAT_BURST_CONTROL_MODE_PACKET_LENGTH 6 -#define ROCCAT_BURST_DIRECT_MODE_PACKET_LENGTH 11 -#define ROCCAT_BURST_FLASH_PACKET_LENGTH 63 -#define ROCCAT_BURST_FLASH_REPORT_ID 0x06 -#define ROCCAT_BURST_DIRECT_MODE_REPORT_ID 0x0D -#define ROCCAT_BURST_DIRECT_MODE_BYTE 0x0B -#define ROCCAT_BURST_CORE_NUMBER_OF_LEDS 1 -#define ROCCAT_BURST_PRO_NUMBER_OF_LEDS 2 -enum -{ - ROCCAT_BURST_DIRECT_MODE_VALUE = 0x00, - ROCCAT_BURST_STATIC_MODE_VALUE = 0x01, - ROCCAT_BURST_WAVE_MODE_VALUE = 0x0A, - ROCCAT_BURST_HEARTBEAT_MODE_VALUE = 0x04, - ROCCAT_BURST_BREATHING_MODE_VALUE = 0x03, - ROCCAT_BURST_BLINKING_MODE_VALUE = 0x02 -}; - -enum -{ - ROCCAT_BURST_SPEED_MIN = 0x01, - ROCCAT_BURST_SPEED_MAX = 0x0B, - ROCCAT_BURST_BRIGHTNESS_MIN = 0x00, - ROCCAT_BURST_BRIGHTNESS_MAX = 0xFF -}; - -class RoccatBurstController -{ -public: - RoccatBurstController(hid_device* dev_handle, const hid_device_info& info); - ~RoccatBurstController(); - - std::string GetSerialString(); - std::string GetDeviceLocation(); - std::string GetFirmwareVersion(); - - void SetupDirectMode(); - void SendDirect(std::vector colors); - void SetMode(std::vector colors, - unsigned char mode_value, - unsigned char speed, - unsigned char brightness, - unsigned int color_mode, - unsigned int mode_flags - ); -private: - hid_device* dev; - std::string location; - std::string serial_number; - std::string version; - - unsigned int CalculateCRC(unsigned char* bytes); - void SwitchControl(bool direct); -}; diff --git a/Controllers/RoccatController/RGBController_RoccatBurst.cpp b/Controllers/RoccatController/RoccatBurstController/RGBController_RoccatBurst.cpp similarity index 85% rename from Controllers/RoccatController/RGBController_RoccatBurst.cpp rename to Controllers/RoccatController/RoccatBurstController/RGBController_RoccatBurst.cpp index ca21940c..5d58dac9 100644 --- a/Controllers/RoccatController/RGBController_RoccatBurst.cpp +++ b/Controllers/RoccatController/RoccatBurstController/RGBController_RoccatBurst.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_RoccatBurst.cpp | -| | -| Generic RGB Interface for OpenRGB | -| | -| | -| Morgan Guimard (morg) 6/01/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_RoccatBurst.cpp | +| | +| RGBController for Roccat Burst | +| | +| Morgan Guimard (morg) 01 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_RoccatBurst.h" @@ -25,10 +27,12 @@ RGBController_RoccatBurst::RGBController_RoccatBurst(RoccatBurstController* cont { controller = controller_ptr; - name = "Roccat Burst Core"; + name = controller->GetNameString(); vendor = "Roccat"; type = DEVICE_TYPE_MOUSE; - description = "Roccat Burst Core Mouse"; + description = "Roccat Burst Mouse Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Direct; Direct.name = "Direct"; diff --git a/Controllers/RoccatController/RoccatBurstController/RGBController_RoccatBurst.h b/Controllers/RoccatController/RoccatBurstController/RGBController_RoccatBurst.h new file mode 100644 index 00000000..76133556 --- /dev/null +++ b/Controllers/RoccatController/RoccatBurstController/RGBController_RoccatBurst.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatBurst.h | +| | +| RGBController for Roccat Burst | +| | +| Morgan Guimard (morg) 01 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RoccatBurstController.h" + +class RGBController_RoccatBurst : public RGBController +{ +public: + RGBController_RoccatBurst(RoccatBurstController* controller_ptr, unsigned int leds_count); + ~RGBController_RoccatBurst(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RoccatBurstController* controller; + unsigned int leds_count; +}; diff --git a/Controllers/RoccatController/RoccatBurstController.cpp b/Controllers/RoccatController/RoccatBurstController/RoccatBurstController.cpp similarity index 82% rename from Controllers/RoccatController/RoccatBurstController.cpp rename to Controllers/RoccatController/RoccatBurstController/RoccatBurstController.cpp index 27b40f90..67748b15 100644 --- a/Controllers/RoccatController/RoccatBurstController.cpp +++ b/Controllers/RoccatController/RoccatBurstController/RoccatBurstController.cpp @@ -1,34 +1,23 @@ -/*-------------------------------------------------------------------*\ -| RoccatBurstController.cpp | -| | -| Driver for Roccat Burst Core and Pro Mouse | -| | -| Morgan Guimard (morg) 2/24/2022 | -| | -\*-------------------------------------------------------------------*/ - -#include "RoccatBurstController.h" +/*---------------------------------------------------------*\ +| RoccatBurstController.cpp | +| | +| Driver for Roccat Burst | +| | +| Morgan Guimard (morg) 24 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "RoccatBurstController.h" +#include "StringUtils.h" -RoccatBurstController::RoccatBurstController(hid_device* dev_handle, const hid_device_info& info) +RoccatBurstController::RoccatBurstController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) { dev = dev_handle; - version = ""; location = info.path; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } + name = dev_name; SetupDirectMode(); } @@ -38,19 +27,27 @@ RoccatBurstController::~RoccatBurstController() hid_close(dev); } -std::string RoccatBurstController::GetFirmwareVersion() +std::string RoccatBurstController::GetDeviceLocation() { - return version; + return("HID: " + location); +} + +std::string RoccatBurstController::GetNameString() +{ + return(name); } std::string RoccatBurstController::GetSerialString() { - return serial_number; -} + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); -std::string RoccatBurstController::GetDeviceLocation() -{ - return("HID: " + location); + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } void RoccatBurstController::SetupDirectMode() diff --git a/Controllers/RoccatController/RoccatBurstController/RoccatBurstController.h b/Controllers/RoccatController/RoccatBurstController/RoccatBurstController.h new file mode 100644 index 00000000..177d0b4a --- /dev/null +++ b/Controllers/RoccatController/RoccatBurstController/RoccatBurstController.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------*\ +| RoccatBurstController.h | +| | +| Driver for Roccat Burst | +| | +| Morgan Guimard (morg) 01 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include + +#define ROCCAT_BURST_CONTROL_MODE_PACKET_LENGTH 6 +#define ROCCAT_BURST_DIRECT_MODE_PACKET_LENGTH 11 +#define ROCCAT_BURST_FLASH_PACKET_LENGTH 63 +#define ROCCAT_BURST_FLASH_REPORT_ID 0x06 +#define ROCCAT_BURST_DIRECT_MODE_REPORT_ID 0x0D +#define ROCCAT_BURST_DIRECT_MODE_BYTE 0x0B +#define ROCCAT_BURST_CORE_NUMBER_OF_LEDS 1 +#define ROCCAT_BURST_PRO_NUMBER_OF_LEDS 2 + +enum +{ + ROCCAT_BURST_DIRECT_MODE_VALUE = 0x00, + ROCCAT_BURST_STATIC_MODE_VALUE = 0x01, + ROCCAT_BURST_WAVE_MODE_VALUE = 0x0A, + ROCCAT_BURST_HEARTBEAT_MODE_VALUE = 0x04, + ROCCAT_BURST_BREATHING_MODE_VALUE = 0x03, + ROCCAT_BURST_BLINKING_MODE_VALUE = 0x02 +}; + +enum +{ + ROCCAT_BURST_SPEED_MIN = 0x01, + ROCCAT_BURST_SPEED_MAX = 0x0B, + ROCCAT_BURST_BRIGHTNESS_MIN = 0x00, + ROCCAT_BURST_BRIGHTNESS_MAX = 0xFF +}; + +class RoccatBurstController +{ +public: + RoccatBurstController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~RoccatBurstController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SetupDirectMode(); + void SendDirect(std::vector colors); + void SetMode(std::vector colors, + unsigned char mode_value, + unsigned char speed, + unsigned char brightness, + unsigned int color_mode, + unsigned int mode_flags + ); +private: + hid_device* dev; + std::string location; + std::string name; + + unsigned int CalculateCRC(unsigned char* bytes); + void SwitchControl(bool direct); +}; diff --git a/Controllers/RoccatController/RoccatBurstProAirController/RGBController_RoccatBurstProAir.cpp b/Controllers/RoccatController/RoccatBurstProAirController/RGBController_RoccatBurstProAir.cpp new file mode 100644 index 00000000..50a80910 --- /dev/null +++ b/Controllers/RoccatController/RoccatBurstProAirController/RGBController_RoccatBurstProAir.cpp @@ -0,0 +1,148 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatBurstProAir.cpp | +| | +| RGBController for Roccat Burst Pro Air | +| | +| Morgan Guimard (morg) 16 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_RoccatBurstProAir.h" + +/**------------------------------------------------------------------*\ + @name Roccat Burst Pro Air + @category Mouse + @type USB + @save :warning: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectRoccatBurstProAirCoreControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_RoccatBurstProAir::RGBController_RoccatBurstProAir(RoccatBurstProAirController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "Roccat"; + type = DEVICE_TYPE_MOUSE; + description = "Roccat Burst Pro Air Mouse Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = ROCCAT_BURST_PRO_AIR_DIRECT_MODE_VALUE; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX; + Direct.brightness_min = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MIN; + Direct.brightness_max = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX; + modes.push_back(Direct); + + mode Blink; + Blink.name = "Blink"; + Blink.value = ROCCAT_BURST_PRO_AIR_BLINK_MODE_VALUE; + Blink.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Blink.color_mode = MODE_COLORS_PER_LED; + Blink.brightness = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX; + Blink.brightness_min = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MIN; + Blink.brightness_max = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX; + Blink.speed = ROCCAT_BURST_PRO_AIR_SPEED_MIN; + Blink.speed_min = ROCCAT_BURST_PRO_AIR_SPEED_MIN; + Blink.speed_max = ROCCAT_BURST_PRO_AIR_SPEED_MAX; + modes.push_back(Blink); + + mode Breath; + Breath.name = "Breathing"; + Breath.value = ROCCAT_BURST_PRO_AIR_BREATH_MODE_VALUE; + Breath.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Breath.color_mode = MODE_COLORS_PER_LED; + Breath.brightness = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX; + Breath.brightness_min = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MIN; + Breath.brightness_max = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX; + Breath.speed = ROCCAT_BURST_PRO_AIR_SPEED_MIN; + Breath.speed_min = ROCCAT_BURST_PRO_AIR_SPEED_MIN; + Breath.speed_max = ROCCAT_BURST_PRO_AIR_SPEED_MAX; + modes.push_back(Breath); + + mode Wave; + Wave.name = "Wave"; + Wave.value = ROCCAT_BURST_PRO_AIR_WAVE_MODE_VALUE; + Wave.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Wave.color_mode = MODE_COLORS_PER_LED; + Wave.brightness = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX; + Wave.brightness_min = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MIN; + Wave.brightness_max = ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX; + Wave.speed = ROCCAT_BURST_PRO_AIR_SPEED_MIN; + Wave.speed_min = ROCCAT_BURST_PRO_AIR_SPEED_MIN; + Wave.speed_max = ROCCAT_BURST_PRO_AIR_SPEED_MAX; + modes.push_back(Wave); + + SetupZones(); +} + +RGBController_RoccatBurstProAir::~RGBController_RoccatBurstProAir() +{ + delete controller; +} + +void RGBController_RoccatBurstProAir::SetupZones() +{ + zone new_zone; + new_zone.name = "Mouse"; + new_zone.type = ZONE_TYPE_LINEAR; + new_zone.leds_min = ROCCAT_BURST_PRO_AIR_PRO_NUMBER_OF_LEDS; + new_zone.leds_max = ROCCAT_BURST_PRO_AIR_PRO_NUMBER_OF_LEDS; + new_zone.leds_count = ROCCAT_BURST_PRO_AIR_PRO_NUMBER_OF_LEDS; + new_zone.matrix_map = NULL; + zones.push_back(new_zone); + + std::string led_names[ROCCAT_BURST_PRO_AIR_PRO_NUMBER_OF_LEDS] = + { + "Scroll Wheel", + "Logo", + "Left button", + "Right button" + }; + + for(unsigned int i = 0; i < ROCCAT_BURST_PRO_AIR_PRO_NUMBER_OF_LEDS; i++) + { + led new_led; + new_led.name = led_names[i]; + leds.push_back(new_led); + } + + SetupColors(); +} + +void RGBController_RoccatBurstProAir::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_RoccatBurstProAir::DeviceUpdateLEDs() +{ + UpdateZoneLEDs(0); +} + +void RGBController_RoccatBurstProAir::UpdateZoneLEDs(int /*zone_idx*/) +{ + controller->SetColors(colors); +} + +void RGBController_RoccatBurstProAir::UpdateSingleLED(int /*led_idx*/) +{ + UpdateZoneLEDs(0); +} + +void RGBController_RoccatBurstProAir::DeviceUpdateMode() +{ + const mode& active = modes[active_mode]; + controller->SetModeValues(active.value, active.speed, active.brightness); +} diff --git a/Controllers/RoccatController/RoccatBurstProAirController/RGBController_RoccatBurstProAir.h b/Controllers/RoccatController/RoccatBurstProAirController/RGBController_RoccatBurstProAir.h new file mode 100644 index 00000000..fb96c0db --- /dev/null +++ b/Controllers/RoccatController/RoccatBurstProAirController/RGBController_RoccatBurstProAir.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatBurstProAir.h | +| | +| RGBController for Roccat Burst Pro Air | +| | +| Morgan Guimard (morg) 16 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RoccatBurstProAirController.h" + +class RGBController_RoccatBurstProAir : public RGBController +{ +public: + RGBController_RoccatBurstProAir(RoccatBurstProAirController* controller_ptr); + ~RGBController_RoccatBurstProAir(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + void DeviceUpdateMode(); + +private: + RoccatBurstProAirController* controller; +}; diff --git a/Controllers/RoccatController/RoccatBurstProAirController/RoccatBurstProAirController.cpp b/Controllers/RoccatController/RoccatBurstProAirController/RoccatBurstProAirController.cpp new file mode 100644 index 00000000..2b134b69 --- /dev/null +++ b/Controllers/RoccatController/RoccatBurstProAirController/RoccatBurstProAirController.cpp @@ -0,0 +1,94 @@ +/*---------------------------------------------------------*\ +| RoccatBurstProAirController.cpp | +| | +| Driver for Roccat Burst Pro Air | +| | +| Morgan Guimard (morg) 16 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RoccatBurstProAirController.h" +#include "StringUtils.h" + +RoccatBurstProAirController::RoccatBurstProAirController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) +{ + dev = dev_handle; + location = info.path; + name = dev_name; +} + +RoccatBurstProAirController::~RoccatBurstProAirController() +{ + hid_close(dev); +} + +std::string RoccatBurstProAirController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string RoccatBurstProAirController::GetNameString() +{ + return(name); +} + +std::string RoccatBurstProAirController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void RoccatBurstProAirController::SetColors(std::vector colors) +{ + unsigned char usb_buf[ROCCAT_BURST_PRO_AIR_REPORT_SIZE]; + memset(usb_buf, 0x00, ROCCAT_BURST_PRO_AIR_REPORT_SIZE); + + usb_buf[0] = ROCCAT_BURST_PRO_AIR_REPORT_ID; + + usb_buf[1] = 0x01; + usb_buf[2] = 0x4C; + usb_buf[3] = 0x06; + usb_buf[4] = 0x14; + + for(unsigned char i = 0; i < colors.size(); i++) + { + usb_buf[5 + 5 * i] = i + 1; + usb_buf[6 + 5 * i] = 0xFF; + usb_buf[7 + 5 * i] = RGBGetRValue(colors[i]); + usb_buf[8 + 5 * i] = RGBGetGValue(colors[i]); + usb_buf[9 + 5 * i] = RGBGetBValue(colors[i]); + } + + hid_send_feature_report(dev, usb_buf, ROCCAT_BURST_PRO_AIR_REPORT_SIZE); +} + +void RoccatBurstProAirController::SetModeValues(unsigned char mode_value, unsigned char speed, unsigned char brightness) +{ + unsigned char usb_buf[ROCCAT_BURST_PRO_AIR_REPORT_SIZE]; + memset(usb_buf, 0x00, ROCCAT_BURST_PRO_AIR_REPORT_SIZE); + + usb_buf[0] = ROCCAT_BURST_PRO_AIR_REPORT_ID; + + usb_buf[1] = 0x01; + usb_buf[2] = 0x4C; + usb_buf[3] = 0x06; + usb_buf[4] = 0x06; + + usb_buf[5] = mode_value; + usb_buf[6] = speed; + usb_buf[7] = brightness; + + usb_buf[8] = 0x0F; + + hid_send_feature_report(dev, usb_buf, ROCCAT_BURST_PRO_AIR_REPORT_SIZE); +} diff --git a/Controllers/RoccatController/RoccatBurstProAirController/RoccatBurstProAirController.h b/Controllers/RoccatController/RoccatBurstProAirController/RoccatBurstProAirController.h new file mode 100644 index 00000000..c70a2365 --- /dev/null +++ b/Controllers/RoccatController/RoccatBurstProAirController/RoccatBurstProAirController.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------*\ +| RoccatBurstProAirController.h | +| | +| Driver for Roccat Burst Pro Air | +| | +| Morgan Guimard (morg) 16 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" + +#define ROCCAT_BURST_PRO_AIR_REPORT_ID 0x06 +#define ROCCAT_BURST_PRO_AIR_REPORT_SIZE 30 +#define ROCCAT_BURST_PRO_AIR_PRO_NUMBER_OF_LEDS 4 + +enum +{ + ROCCAT_BURST_PRO_AIR_DIRECT_MODE_VALUE = 0x01, + ROCCAT_BURST_PRO_AIR_BLINK_MODE_VALUE = 0x02, + ROCCAT_BURST_PRO_AIR_BREATH_MODE_VALUE = 0x03, + ROCCAT_BURST_PRO_AIR_WAVE_MODE_VALUE = 0x04 +}; + +enum +{ + ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MIN = 0x00, + ROCCAT_BURST_PRO_AIR_BRIGHTNESS_MAX = 0xFF, + ROCCAT_BURST_PRO_AIR_SPEED_MIN = 0x00, + ROCCAT_BURST_PRO_AIR_SPEED_MAX = 0x0B +}; + +class RoccatBurstProAirController +{ +public: + RoccatBurstProAirController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~RoccatBurstProAirController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SetColors(std::vector colors); + void SetModeValues(unsigned char mode_value, unsigned char speed, unsigned char brightness); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/RoccatController/RoccatControllerDetect.cpp b/Controllers/RoccatController/RoccatControllerDetect.cpp index 1667388b..b9b8106a 100644 --- a/Controllers/RoccatController/RoccatControllerDetect.cpp +++ b/Controllers/RoccatController/RoccatControllerDetect.cpp @@ -1,36 +1,69 @@ -/******************************************************************************************\ -* * -* DetectRoccatControllers * -* * -* Tests the USB address to see if a Roccat Kone Aimo controller exists there. * -* * -\******************************************************************************************/ +/*---------------------------------------------------------*\ +| RoccatControllerDetect.cpp | +| | +| Detector for Roccat devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "Detector.h" #include "RoccatBurstController.h" +#include "RoccatBurstProAirController.h" #include "RoccatKoneAimoController.h" -#include "RoccatVulcanAimoController.h" +#include "RoccatKoneProController.h" +#include "RoccatKoneProAirController.h" +#include "RoccatKoneXPController.h" +#include "RoccatSenseAimoController.h" +#include "RoccatVulcanKeyboardController.h" #include "RoccatKovaController.h" #include "RoccatEloController.h" -#include "RGBController.h" #include "RGBController_RoccatBurst.h" +#include "RGBController_RoccatBurstProAir.h" #include "RGBController_RoccatHordeAimo.h" #include "RGBController_RoccatKoneAimo.h" -#include "RGBController_RoccatVulcanAimo.h" +#include "RGBController_RoccatKonePro.h" +#include "RGBController_RoccatKoneProAir.h" +#include "RGBController_RoccatKoneXP.h" +#include "RGBController_RoccatSenseAimo.h" +#include "RGBController_RoccatVulcanKeyboard.h" #include "RGBController_RoccatKova.h" #include "RGBController_RoccatElo.h" -#include +#include #include #define ROCCAT_VID 0x1E7D +#define TURTLE_BEACH_VID 0x10F5 -#define ROCCAT_KONE_AIMO_PID 0x2E27 -#define ROCCAT_KONE_AIMO_16K_PID 0x2E2C -#define ROCCAT_VULCAN_120_AIMO_PID 0x3098 +/*--------------------------------------------------------------------------------*\ +| KEYBOARDS | +| RoccatVulcanKeyboardController PIDs defined in RoccatVulcanKeyboardController.h | +\*--------------------------------------------------------------------------------*/ #define ROCCAT_HORDE_AIMO_PID 0x303E -#define ROCCAT_BURST_CORE_PID 0x2DE6 -#define ROCCAT_BURST_PRO_PID 0x2DE1 -#define ROCCAT_KOVA_PID 0x2CEE + +/*-----------------------------------------------------------------*\ +| MICE | +\*-----------------------------------------------------------------*/ +#define ROCCAT_BURST_CORE_PID 0x2DE6 +#define ROCCAT_BURST_PRO_PID 0x2DE1 +#define ROCCAT_BURST_PRO_AIR_PID 0x2CA6 +#define ROCCAT_KONE_AIMO_PID 0x2E27 +#define ROCCAT_KONE_AIMO_16K_PID 0x2E2C +#define ROCCAT_KONE_PRO_PID 0x2C88 +#define ROCCAT_KONE_PRO_AIR_PID 0x2C8E +#define ROCCAT_KONE_PRO_AIR_WIRED_PID 0x2C92 +#define ROCCAT_KONE_XP_PID 0x2C8B +#define ROCCAT_KOVA_PID 0x2CEE + +/*-----------------------------------------------------------------*\ +| MOUSEMATS | +\*-----------------------------------------------------------------*/ +#define ROCCAT_SENSE_AIMO_MID_PID 0x343A +#define ROCCAT_SENSE_AIMO_XXL_PID 0x343B + +/*-----------------------------------------------------------------*\ +| HEADSETS | +\*-----------------------------------------------------------------*/ #define ROCCAT_ELO_PID 0x3A34 void DetectRoccatMouseControllers(hid_device_info* info, const std::string& name) @@ -39,60 +72,80 @@ void DetectRoccatMouseControllers(hid_device_info* info, const std::string& name if(dev) { - RoccatKoneAimoController * controller = new RoccatKoneAimoController(dev, info->path); + RoccatKoneAimoController * controller = new RoccatKoneAimoController(dev, info->path, name); RGBController_RoccatKoneAimo * rgb_controller = new RGBController_RoccatKoneAimo(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } -/*-----------------------------------------------------------------------------*\ -| Tracks the paths used in DetectRoccatVulcanAimoControllers so multiple Roccat | -| devices can be detected without all controlling the same device. | -\*-----------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------------*\ +| Tracks the paths used in DetectRoccatVulcanKeyboardControllers so multiple Roccat | +| devices can be detected without all controlling the same device. | +\*---------------------------------------------------------------------------------*/ static std::unordered_set used_paths; /*--------------------------------------------------------------------------------*\ | Removes all entries in used_paths so device discovery does not skip any of them. | \*--------------------------------------------------------------------------------*/ -void ResetRoccatVulcanAimoControllersPaths() +void ResetRoccatVulcanKeyboardControllersPaths() { used_paths.clear(); } -void DetectRoccatVulcanAimoControllers(hid_device_info* info, const std::string& name) +void DetectRoccatVulcanKeyboardControllers(hid_device_info* info, const std::string& name) { /*-------------------------------------------------------------------------------------------------*\ - | Create a local copy of the HID enumerations for the Roccat Vulcan Aimo VID/PID and iterate | + | Create a local copy of the HID enumerations for the Roccat Vulcan Keyboard VID/PID and iterate | | through it. This prevents detection from failing if interface 1 comes before interface 0 in the | | main info list. | \*-------------------------------------------------------------------------------------------------*/ - hid_device* dev_ctrl = nullptr; - hid_device* dev_led = nullptr; - hid_device_info* info_full = hid_enumerate(info->vendor_id, info->product_id); - hid_device_info* info_temp = info_full; + hid_device* dev_ctrl = nullptr; + hid_device* dev_led = nullptr; + hid_device_info* info_full = hid_enumerate(info->vendor_id, info->product_id); + hid_device_info* info_temp = info_full; + /*--------------------------------------------------------------------------------------------*\ | Keep track of paths so they can be added to used_paths only if both interfaces can be found. | \*--------------------------------------------------------------------------------------------*/ - std::string dev_ctrl_path; - std::string dev_led_path; + std::string dev_ctrl_path; + std::string dev_led_path; + int dev_led_page; + int dev_ctrl_page; + + switch(info->product_id) + { + case ROCCAT_VULCAN_PRO_PID: + case ROCCAT_PYRO_PID: + case ROCCAT_MAGMA_PID: + case ROCCAT_MAGMA_MINI_PID: + case ROCCAT_VULCAN_II_PID: + case TURTLE_BEACH_VULCAN_II_PID: + dev_led_page = 0xFF00; + dev_ctrl_page = 0xFF01; + break; + default: + dev_led_page = 0x0001; + dev_ctrl_page = 0x000B; + break; + } while(info_temp) { - /*------------------------------------------------------------------------------------*\ - | Check for paths used on an already registered Roccat Vulcan Aimo controller to avoid | - | registering multiple controllers that refer to the same physical hardware. | - \*------------------------------------------------------------------------------------*/ + /*----------------------------------------------------------------------------------------*\ + | Check for paths used on an already registered Roccat Vulcan Keyboard controller to avoid | + | registering multiple controllers that refer to the same physical hardware. | + \*----------------------------------------------------------------------------------------*/ if(info_temp->vendor_id == info->vendor_id && info_temp->product_id == info->product_id && used_paths.find(info_temp->path) == used_paths.end() ) { - if(info_temp->interface_number == 1 && info_temp->usage_page == 11) + if(info_temp->interface_number == 1 && info_temp->usage_page == dev_ctrl_page) { dev_ctrl = hid_open_path(info_temp->path); dev_ctrl_path = info_temp->path; } - else if(info_temp->interface_number == 3 && info_temp->usage_page == 1) + else if(info_temp->interface_number == 3 && info_temp->usage_page == dev_led_page) { dev_led = hid_open_path(info_temp->path); dev_led_path = info_temp->path; @@ -109,10 +162,11 @@ void DetectRoccatVulcanAimoControllers(hid_device_info* info, const std::string& if(dev_ctrl && dev_led) { - RoccatVulcanAimoController * controller = new RoccatVulcanAimoController(dev_ctrl, dev_led, info->path); - RGBController_RoccatVulcanAimo * rgb_controller = new RGBController_RoccatVulcanAimo(controller); - rgb_controller->name = name; + RoccatVulcanKeyboardController * controller = new RoccatVulcanKeyboardController(dev_ctrl, dev_led, info->path, info->product_id, name); + RGBController_RoccatVulcanKeyboard * rgb_controller = new RGBController_RoccatVulcanKeyboard(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); + used_paths.insert(dev_ctrl_path); used_paths.insert(dev_led_path); } @@ -130,9 +184,9 @@ void DetectRoccatHordeAimoKeyboardControllers(hid_device_info* info, const std:: if(dev) { - RoccatHordeAimoController * controller = new RoccatHordeAimoController(dev, *info); + RoccatHordeAimoController * controller = new RoccatHordeAimoController(dev, *info, name); RGBController_RoccatHordeAimo * rgb_controller = new RGBController_RoccatHordeAimo(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -143,9 +197,9 @@ void DetectRoccatBurstCoreControllers(hid_device_info* info, const std::string& if(dev) { - RoccatBurstController * controller = new RoccatBurstController(dev, *info); - RGBController_RoccatBurst * rgb_controller = new RGBController_RoccatBurst(controller, ROCCAT_BURST_CORE_NUMBER_OF_LEDS); - rgb_controller->name = name; + RoccatBurstController * controller = new RoccatBurstController(dev, *info, name); + RGBController_RoccatBurst * rgb_controller = new RGBController_RoccatBurst(controller, ROCCAT_BURST_CORE_NUMBER_OF_LEDS); + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -156,9 +210,61 @@ void DetectRoccatBurstProControllers(hid_device_info* info, const std::string& n if(dev) { - RoccatBurstController * controller = new RoccatBurstController(dev, *info); - RGBController_RoccatBurst * rgb_controller = new RGBController_RoccatBurst(controller, ROCCAT_BURST_PRO_NUMBER_OF_LEDS); - rgb_controller->name = name; + RoccatBurstController * controller = new RoccatBurstController(dev, *info, name); + RGBController_RoccatBurst * rgb_controller = new RGBController_RoccatBurst(controller, ROCCAT_BURST_PRO_NUMBER_OF_LEDS); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectRoccatBurstProAirControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + RoccatBurstProAirController * controller = new RoccatBurstProAirController(dev, *info, name); + RGBController_RoccatBurstProAir * rgb_controller = new RGBController_RoccatBurstProAir(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectRoccatKoneProControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + RoccatKoneProController * controller = new RoccatKoneProController(dev, *info, name); + RGBController_RoccatKonePro * rgb_controller = new RGBController_RoccatKonePro(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectRoccatKoneProAirControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + RoccatKoneProAirController * controller = new RoccatKoneProAirController(dev, *info, name); + RGBController_RoccatKoneProAir * rgb_controller = new RGBController_RoccatKoneProAir(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectRoccatKoneXPControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + RoccatKoneXPController * controller = new RoccatKoneXPController(dev, info->path, name); + RGBController_RoccatKoneXP * rgb_controller = new RGBController_RoccatKoneXP(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -169,9 +275,9 @@ void DetectRoccatKovaControllers(hid_device_info* info, const std::string& name) if(dev) { - RoccatKovaController * controller = new RoccatKovaController(dev, info->path); - RGBController_RoccatKova * rgb_controller = new RGBController_RoccatKova(controller); - rgb_controller->name = name; + RoccatKovaController * controller = new RoccatKovaController(dev, info->path, name); + RGBController_RoccatKova * rgb_controller = new RGBController_RoccatKova(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -182,20 +288,69 @@ void DetectRoccatEloControllers(hid_device_info* info, const std::string& name) if(dev) { - RoccatEloController * controller = new RoccatEloController(dev, *info); - RGBController_RoccatElo * rgb_controller = new RGBController_RoccatElo(controller); - rgb_controller->name = name; + RoccatEloController * controller = new RoccatEloController(dev, *info, name); + RGBController_RoccatElo * rgb_controller = new RGBController_RoccatElo(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); } } -REGISTER_PRE_DETECTION_HOOK(ResetRoccatVulcanAimoControllersPaths); +void DetectRoccatSenseAimoControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + RoccatSenseAimoController * controller = new RoccatSenseAimoController(dev, info->path, name); + RGBController_RoccatSenseAimo * rgb_controller = new RGBController_RoccatSenseAimo(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +REGISTER_PRE_DETECTION_HOOK(ResetRoccatVulcanKeyboardControllersPaths); + +/*-----------------------------------------------------------------*\ +| KEYBOARDS | +\*-----------------------------------------------------------------*/ +REGISTER_HID_DETECTOR_IPU("Roccat Horde Aimo", DetectRoccatHordeAimoKeyboardControllers, ROCCAT_VID, ROCCAT_HORDE_AIMO_PID, 1, 0x0B, 0 ); + +REGISTER_HID_DETECTOR_IP ("Roccat Magma", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_MAGMA_PID, 1, 0xFF01); +REGISTER_HID_DETECTOR_IP ("Roccat Magma Mini", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_MAGMA_MINI_PID, 1, 0xFF01); +REGISTER_HID_DETECTOR_IP ("Roccat Pyro", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_PYRO_PID, 1, 0xFF01); +REGISTER_HID_DETECTOR_IP ("Roccat Vulcan 100 Aimo", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_VULCAN_100_AIMO_PID, 1, 11); +REGISTER_HID_DETECTOR_IP ("Roccat Vulcan 120-Series Aimo", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_VULCAN_120_AIMO_PID, 1, 11); +REGISTER_HID_DETECTOR_IP ("Roccat Vulcan TKL", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_VULCAN_TKL_PID, 1, 11); +REGISTER_HID_DETECTOR_IP ("Roccat Vulcan Pro", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_VULCAN_PRO_PID, 1, 0xFF01); +REGISTER_HID_DETECTOR_IP ("Roccat Vulcan II", DetectRoccatVulcanKeyboardControllers, ROCCAT_VID, ROCCAT_VULCAN_II_PID, 1, 0xFF01); +REGISTER_HID_DETECTOR_IP ("Turtle Beach Vulcan II", DetectRoccatVulcanKeyboardControllers, TURTLE_BEACH_VID, TURTLE_BEACH_VULCAN_II_PID, 1, 0xFF01); +REGISTER_HID_DETECTOR_IP ("Turtle Beach Vulcan II TKL", DetectRoccatVulcanKeyboardControllers, TURTLE_BEACH_VID, TURTLE_BEACH_VULCAN_II_TKL_PID, 1, 11); + +/*-----------------------------------------------------------------*\ +| MICE | +\*-----------------------------------------------------------------*/ +REGISTER_HID_DETECTOR_IPU("Roccat Burst Core", DetectRoccatBurstCoreControllers, ROCCAT_VID, ROCCAT_BURST_CORE_PID, 3, 0xFF01, 1 ); +REGISTER_HID_DETECTOR_IPU("Roccat Burst Pro", DetectRoccatBurstProControllers, ROCCAT_VID, ROCCAT_BURST_PRO_PID, 3, 0xFF01, 1 ); +REGISTER_HID_DETECTOR_IPU("Roccat Burst Pro Air", DetectRoccatBurstProAirControllers, ROCCAT_VID, ROCCAT_BURST_PRO_AIR_PID, 0, 0x01, 2 ); REGISTER_HID_DETECTOR_IPU("Roccat Kone Aimo", DetectRoccatMouseControllers, ROCCAT_VID, ROCCAT_KONE_AIMO_PID, 0, 0x0B, 0 ); REGISTER_HID_DETECTOR_IPU("Roccat Kone Aimo 16K", DetectRoccatMouseControllers, ROCCAT_VID, ROCCAT_KONE_AIMO_16K_PID, 0, 0x0B, 0 ); -REGISTER_HID_DETECTOR_IP ("Roccat Vulcan 120-Series Aimo", DetectRoccatVulcanAimoControllers, ROCCAT_VID, ROCCAT_VULCAN_120_AIMO_PID, 1, 11); -REGISTER_HID_DETECTOR_IPU("Roccat Horde Aimo", DetectRoccatHordeAimoKeyboardControllers, ROCCAT_VID, ROCCAT_HORDE_AIMO_PID, 1, 0x0B, 0 ); -REGISTER_HID_DETECTOR_IPU("Roccat Burst Core", DetectRoccatBurstCoreControllers, ROCCAT_VID, ROCCAT_BURST_CORE_PID, 3, 0xFF01, 1 ); -REGISTER_HID_DETECTOR_IPU("Roccat Burst Pro", DetectRoccatBurstProControllers, ROCCAT_VID, ROCCAT_BURST_PRO_PID, 3, 0xFF01, 1 ); + +REGISTER_HID_DETECTOR_IPU("Roccat Kone Pro", DetectRoccatKoneProControllers, ROCCAT_VID, ROCCAT_KONE_PRO_PID, 3, 0xFF01, 1 ); +REGISTER_HID_DETECTOR_IPU("Roccat Kone Pro Air", DetectRoccatKoneProAirControllers, ROCCAT_VID, ROCCAT_KONE_PRO_AIR_PID, 2, 0xFF00, 1 ); +REGISTER_HID_DETECTOR_IPU("Roccat Kone Pro Air (Wired)", DetectRoccatKoneProAirControllers, ROCCAT_VID, ROCCAT_KONE_PRO_AIR_WIRED_PID, 1, 0xFF13, 1 ); + +REGISTER_HID_DETECTOR_IPU("Roccat Kone XP", DetectRoccatKoneXPControllers, ROCCAT_VID, ROCCAT_KONE_XP_PID, 3, 0xFF01, 1 ); + REGISTER_HID_DETECTOR_IPU("Roccat Kova", DetectRoccatKovaControllers, ROCCAT_VID, ROCCAT_KOVA_PID, 0, 0x0B, 0 ); + +/*-----------------------------------------------------------------*\ +| MOUSEMATS | +\*-----------------------------------------------------------------*/ +REGISTER_HID_DETECTOR_IPU("Roccat Sense Aimo Mid", DetectRoccatSenseAimoControllers, ROCCAT_VID, ROCCAT_SENSE_AIMO_MID_PID, 0, 0xFF01, 1 ); +REGISTER_HID_DETECTOR_IPU("Roccat Sense Aimo XXL", DetectRoccatSenseAimoControllers, ROCCAT_VID, ROCCAT_SENSE_AIMO_XXL_PID, 0, 0xFF01, 1 ); + +/*-----------------------------------------------------------------*\ +| HEADSETS | +\*-----------------------------------------------------------------*/ REGISTER_HID_DETECTOR_IPU("Roccat Elo 7.1", DetectRoccatEloControllers, ROCCAT_VID, ROCCAT_ELO_PID, 3, 0x0C, 1 ); diff --git a/Controllers/RoccatController/RoccatEloController.cpp b/Controllers/RoccatController/RoccatEloController.cpp deleted file mode 100644 index f674da38..00000000 --- a/Controllers/RoccatController/RoccatEloController.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "RoccatEloController.h" -#include -#include - -RoccatEloController::RoccatEloController(hid_device* dev_handle, const hid_device_info& info) -{ - dev = dev_handle; - location = info.path; - version = ""; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } - - SendInit(); -} - -RoccatEloController::~RoccatEloController() -{ - hid_close(dev); -} - -std::string RoccatEloController::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string RoccatEloController::GetSerialString() -{ - return(serial_number); -} - -void RoccatEloController::SendInit() -{ - unsigned char usb_buf[ROCCAT_ELO_REPORT_SIZE]; - - memset(usb_buf, 0x00, ROCCAT_ELO_REPORT_SIZE); - - usb_buf[0x00] = ROCCAT_ELO_REPORT_ID; - usb_buf[0x01] = 0x01; - - hid_write(dev, usb_buf, ROCCAT_ELO_REPORT_SIZE); - - usb_buf[0x01] = 0x02; - - hid_write(dev, usb_buf, ROCCAT_ELO_REPORT_SIZE); - - usb_buf[0x01] = 0x03; - usb_buf[0x03] = 0x01; - - hid_write(dev, usb_buf, ROCCAT_ELO_REPORT_SIZE); - - SendDirect(0); - - memset(usb_buf, 0x00, ROCCAT_ELO_REPORT_SIZE); - - usb_buf[0x00] = ROCCAT_ELO_REPORT_ID; - usb_buf[0x01] = 0x01; - - hid_write(dev, usb_buf, ROCCAT_ELO_REPORT_SIZE); -} - -void RoccatEloController::SendDirect(RGBColor color) -{ - unsigned char usb_buf[ROCCAT_ELO_REPORT_SIZE]; - - memset(usb_buf, 0x00, ROCCAT_ELO_REPORT_SIZE); - - usb_buf[0x00] = ROCCAT_ELO_REPORT_ID; - usb_buf[0x01] = 0x04; - usb_buf[0x04] = RGBGetRValue(color); - usb_buf[0x05] = RGBGetGValue(color); - usb_buf[0x06] = RGBGetBValue(color); - - hid_write(dev, usb_buf, ROCCAT_ELO_REPORT_SIZE); -} - diff --git a/Controllers/RoccatController/RoccatEloController.h b/Controllers/RoccatController/RoccatEloController.h deleted file mode 100644 index 576e8a10..00000000 --- a/Controllers/RoccatController/RoccatEloController.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once - -#include "RGBController.h" -#include -#include - -#define ROCCAT_ELO_REPORT_SIZE 16 -#define ROCCAT_ELO_LEDS_COUNT 1 -#define ROCCAT_ELO_REPORT_ID 0xFF - -class RoccatEloController -{ -public: - RoccatEloController(hid_device* dev_handle, const hid_device_info& info); - ~RoccatEloController(); - - std::string GetSerialString(); - std::string GetDeviceLocation(); - - void SendDirect(RGBColor color); - -private: - hid_device* dev; - std::string location; - std::string serial_number; - std::string version; - - void SendInit(); -}; diff --git a/Controllers/RoccatController/RoccatEloController/RGBController_RoccatElo.cpp b/Controllers/RoccatController/RoccatEloController/RGBController_RoccatElo.cpp new file mode 100644 index 00000000..a53ac25b --- /dev/null +++ b/Controllers/RoccatController/RoccatEloController/RGBController_RoccatElo.cpp @@ -0,0 +1,95 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatElo.cpp | +| | +| RGBController for Roccat Elo | +| | +| Flora Aubry 02 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "RGBController_RoccatElo.h" + +/**------------------------------------------------------------------*\ + @name Roccat Elo 7.1 + @category Headset + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectRoccatEloControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_RoccatElo::RGBController_RoccatElo(RoccatEloController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "Roccat"; + type = DEVICE_TYPE_HEADSET; + description = "Roccat Elo 7.1 Headset Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + SetupZones(); +} + +RGBController_RoccatElo::~RGBController_RoccatElo() +{ + delete controller; +} + +void RGBController_RoccatElo::SetupZones() +{ + zone new_zone; + + new_zone.name = "Headset"; + new_zone.type = ZONE_TYPE_LINEAR; + new_zone.leds_min = ROCCAT_ELO_LEDS_COUNT; + new_zone.leds_max = ROCCAT_ELO_LEDS_COUNT; + new_zone.leds_count = ROCCAT_ELO_LEDS_COUNT; + new_zone.matrix_map = nullptr; + + zones.emplace_back(new_zone); + + leds.resize(new_zone.leds_count); + + SetupColors(); +} + +void RGBController_RoccatElo::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_RoccatElo::DeviceUpdateLEDs() +{ + controller->SendDirect(colors[0]); +} + +void RGBController_RoccatElo::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RoccatElo::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RoccatElo::DeviceUpdateMode() +{ + +} diff --git a/Controllers/RoccatController/RoccatEloController/RGBController_RoccatElo.h b/Controllers/RoccatController/RoccatEloController/RGBController_RoccatElo.h new file mode 100644 index 00000000..a725056f --- /dev/null +++ b/Controllers/RoccatController/RoccatEloController/RGBController_RoccatElo.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatElo.h | +| | +| RGBController for Roccat Elo | +| | +| Flora Aubry 02 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RoccatEloController.h" + +class RGBController_RoccatElo : public RGBController +{ +public: + RGBController_RoccatElo(RoccatEloController* controller_ptr); + ~RGBController_RoccatElo(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RoccatEloController* controller; +}; diff --git a/Controllers/RoccatController/RoccatEloController/RoccatEloController.cpp b/Controllers/RoccatController/RoccatEloController/RoccatEloController.cpp new file mode 100644 index 00000000..09af64ce --- /dev/null +++ b/Controllers/RoccatController/RoccatEloController/RoccatEloController.cpp @@ -0,0 +1,98 @@ +/*---------------------------------------------------------*\ +| RoccatEloController.cpp | +| | +| Driver for Roccat Elo | +| | +| Flora Aubry 02 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "RoccatEloController.h" +#include "StringUtils.h" + +RoccatEloController::RoccatEloController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) +{ + dev = dev_handle; + location = info.path; + name = dev_name; + + SendInit(); +} + +RoccatEloController::~RoccatEloController() +{ + hid_close(dev); +} + +std::string RoccatEloController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string RoccatEloController::GetNameString() +{ + return(name); +} + +std::string RoccatEloController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void RoccatEloController::SendInit() +{ + unsigned char usb_buf[ROCCAT_ELO_REPORT_SIZE]; + + memset(usb_buf, 0x00, ROCCAT_ELO_REPORT_SIZE); + + usb_buf[0x00] = ROCCAT_ELO_REPORT_ID; + usb_buf[0x01] = 0x01; + + hid_write(dev, usb_buf, ROCCAT_ELO_REPORT_SIZE); + + usb_buf[0x01] = 0x02; + + hid_write(dev, usb_buf, ROCCAT_ELO_REPORT_SIZE); + + usb_buf[0x01] = 0x03; + usb_buf[0x03] = 0x01; + + hid_write(dev, usb_buf, ROCCAT_ELO_REPORT_SIZE); + + SendDirect(0); + + memset(usb_buf, 0x00, ROCCAT_ELO_REPORT_SIZE); + + usb_buf[0x00] = ROCCAT_ELO_REPORT_ID; + usb_buf[0x01] = 0x01; + + hid_write(dev, usb_buf, ROCCAT_ELO_REPORT_SIZE); +} + +void RoccatEloController::SendDirect(RGBColor color) +{ + unsigned char usb_buf[ROCCAT_ELO_REPORT_SIZE]; + + memset(usb_buf, 0x00, ROCCAT_ELO_REPORT_SIZE); + + usb_buf[0x00] = ROCCAT_ELO_REPORT_ID; + usb_buf[0x01] = 0x04; + usb_buf[0x04] = RGBGetRValue(color); + usb_buf[0x05] = RGBGetGValue(color); + usb_buf[0x06] = RGBGetBValue(color); + + hid_write(dev, usb_buf, ROCCAT_ELO_REPORT_SIZE); +} + diff --git a/Controllers/RoccatController/RoccatEloController/RoccatEloController.h b/Controllers/RoccatController/RoccatEloController/RoccatEloController.h new file mode 100644 index 00000000..945e272a --- /dev/null +++ b/Controllers/RoccatController/RoccatEloController/RoccatEloController.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------*\ +| RoccatEloController.h | +| | +| Driver for Roccat Elo | +| | +| Flora Aubry 02 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define ROCCAT_ELO_REPORT_SIZE 16 +#define ROCCAT_ELO_LEDS_COUNT 1 +#define ROCCAT_ELO_REPORT_ID 0xFF + +class RoccatEloController +{ +public: + RoccatEloController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~RoccatEloController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SendDirect(RGBColor color); + +private: + hid_device* dev; + std::string location; + std::string name; + + void SendInit(); +}; diff --git a/Controllers/RoccatController/RoccatHordeAimoController.cpp b/Controllers/RoccatController/RoccatHordeAimoController.cpp deleted file mode 100644 index 1d91b9f7..00000000 --- a/Controllers/RoccatController/RoccatHordeAimoController.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RoccatHordeAimoController.cpp | -| | -| Driver for Roccat Horde Aimo Keyboard | -| | -| Morgan Guimard (morg) 2/24/2022 | -| | -\*-------------------------------------------------------------------*/ - -#include "RoccatHordeAimoController.h" - -#include - -RoccatHordeAimoController::RoccatHordeAimoController(hid_device* dev_handle, const hid_device_info& info) -{ - dev = dev_handle; - version = ""; - location = info.path; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } - - InitialPacket(); -} - -RoccatHordeAimoController::~RoccatHordeAimoController() -{ - hid_close(dev); -} - -void RoccatHordeAimoController::InitialPacket() -{ - unsigned char usb_buf[8]; - - memset(usb_buf, 0x00,8); - - usb_buf[0x00] = 0x13; - usb_buf[0x01] = 0x08; - usb_buf[0x02] = 0x01; - - hid_send_feature_report(dev, usb_buf, 8); -} - -std::string RoccatHordeAimoController::GetFirmwareVersion() -{ - return version; -} - -std::string RoccatHordeAimoController::GetSerialString() -{ - return serial_number; -} - -std::string RoccatHordeAimoController::GetDeviceLocation() -{ - return("HID: " + location); -} - -void RoccatHordeAimoController::SetColors(std::vector colors) -{ - unsigned char usb_buf[WRITE_PACKET_LENGTH]; - - usb_buf[0x00] = REPORT_ID; - usb_buf[0x01] = WRITE_PACKET_LENGTH; - usb_buf[0x02] = 0xFF; - usb_buf[0x03] = 0xFF; - - for(unsigned int i = 0; i < 6; i++) - { - usb_buf[0x04 + (i * 3)] = RGBGetRValue(colors[i]); - usb_buf[0x05 + (i * 3)] = RGBGetGValue(colors[i]); - usb_buf[0x06 + (i * 3)] = RGBGetBValue(colors[i]); - } - - int crc = 0; - - for(unsigned int i = 0; i < WRITE_PACKET_LENGTH - 2; i++) - { - crc += usb_buf[i]; - } - - usb_buf[22] = crc; - usb_buf[23] = crc >> 8; - - hid_send_feature_report(dev, usb_buf, WRITE_PACKET_LENGTH); - - unsigned char usb_read_buf[READ_PACKET_LENGTH]; - hid_get_feature_report(dev, usb_read_buf, READ_PACKET_LENGTH); -} diff --git a/Controllers/RoccatController/RoccatHordeAimoController.h b/Controllers/RoccatController/RoccatHordeAimoController.h deleted file mode 100644 index 0cb37750..00000000 --- a/Controllers/RoccatController/RoccatHordeAimoController.h +++ /dev/null @@ -1,39 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RoccatHordeAimoController.h | -| | -| Driver for Roccat Horde Aimo Keyboard | -| | -| Morgan Guimard (morg) 2/24/2022 | -| | -\*-------------------------------------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include - -#define WRITE_PACKET_LENGTH 24 -#define READ_PACKET_LENGTH 3 -#define REPORT_ID 0x18 -#define NUMBER_OF_LEDS 6 - -class RoccatHordeAimoController -{ -public: - RoccatHordeAimoController(hid_device* dev_handle, const hid_device_info& info); - ~RoccatHordeAimoController(); - - std::string GetSerialString(); - std::string GetDeviceLocation(); - std::string GetFirmwareVersion(); - - void SetColors(std::vector colors); - -private: - hid_device* dev; - std::string location; - std::string serial_number; - std::string version; - - void InitialPacket(); -}; diff --git a/Controllers/RoccatController/RoccatHordeAimoController/RGBController_RoccatHordeAimo.cpp b/Controllers/RoccatController/RoccatHordeAimoController/RGBController_RoccatHordeAimo.cpp new file mode 100644 index 00000000..ad6fbe64 --- /dev/null +++ b/Controllers/RoccatController/RoccatHordeAimoController/RGBController_RoccatHordeAimo.cpp @@ -0,0 +1,97 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatHordeAimo.cpp | +| | +| RGBController for Roccat Horde Aimo | +| | +| Morgan Guimard (morg) 24 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_RoccatHordeAimo.h" + +/**------------------------------------------------------------------*\ + @name Roccat Horde Aimo + @category Keyboard + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectRoccatHordeAimoKeyboardControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_RoccatHordeAimo::RGBController_RoccatHordeAimo(RoccatHordeAimoController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "Roccat"; + type = DEVICE_TYPE_KEYBOARD; + description = "Roccat Horde Aimo Keyboard Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + 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(); +} + +RGBController_RoccatHordeAimo::~RGBController_RoccatHordeAimo() +{ + delete controller; +} + +void RGBController_RoccatHordeAimo::SetupZones() +{ + zone new_zone; + new_zone.name = "Keyboard"; + new_zone.type = ZONE_TYPE_LINEAR; + new_zone.leds_min = NUMBER_OF_LEDS; + new_zone.leds_max = NUMBER_OF_LEDS; + new_zone.leds_count = NUMBER_OF_LEDS; + new_zone.matrix_map = NULL; + zones.push_back(new_zone); + + for(unsigned int i = 0; i < NUMBER_OF_LEDS; i++) + { + led new_led; + new_led.name = "LED " + std::to_string(i + 1); + leds.push_back(new_led); + } + + SetupColors(); +} + +void RGBController_RoccatHordeAimo::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_RoccatHordeAimo::DeviceUpdateLEDs() +{ + UpdateZoneLEDs(0); +} + +void RGBController_RoccatHordeAimo::UpdateZoneLEDs(int /*zone_idx*/) +{ + controller->SetColors(colors); +} + +void RGBController_RoccatHordeAimo::UpdateSingleLED(int /*led_idx*/) +{ + UpdateZoneLEDs(0); +} + +void RGBController_RoccatHordeAimo::DeviceUpdateMode() +{ + +} diff --git a/Controllers/RoccatController/RoccatHordeAimoController/RGBController_RoccatHordeAimo.h b/Controllers/RoccatController/RoccatHordeAimoController/RGBController_RoccatHordeAimo.h new file mode 100644 index 00000000..15bfc36c --- /dev/null +++ b/Controllers/RoccatController/RoccatHordeAimoController/RGBController_RoccatHordeAimo.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatHordeAimo.h | +| | +| RGBController for Roccat Horde Aimo | +| | +| Morgan Guimard (morg) 24 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RoccatHordeAimoController.h" + +class RGBController_RoccatHordeAimo : public RGBController +{ +public: + RGBController_RoccatHordeAimo(RoccatHordeAimoController* controller_ptr); + ~RGBController_RoccatHordeAimo(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RoccatHordeAimoController* controller; +}; diff --git a/Controllers/RoccatController/RoccatHordeAimoController/RoccatHordeAimoController.cpp b/Controllers/RoccatController/RoccatHordeAimoController/RoccatHordeAimoController.cpp new file mode 100644 index 00000000..abe49cd8 --- /dev/null +++ b/Controllers/RoccatController/RoccatHordeAimoController/RoccatHordeAimoController.cpp @@ -0,0 +1,96 @@ +/*---------------------------------------------------------*\ +| RoccatHordeAimoController.cpp | +| | +| Driver for Roccat Horde Aimo | +| | +| Morgan Guimard (morg) 24 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RoccatHordeAimoController.h" +#include "StringUtils.h" + +RoccatHordeAimoController::RoccatHordeAimoController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) +{ + dev = dev_handle; + location = info.path; + name = dev_name; + + InitialPacket(); +} + +RoccatHordeAimoController::~RoccatHordeAimoController() +{ + hid_close(dev); +} + +void RoccatHordeAimoController::InitialPacket() +{ + unsigned char usb_buf[8]; + + memset(usb_buf, 0x00,8); + + usb_buf[0x00] = 0x13; + usb_buf[0x01] = 0x08; + usb_buf[0x02] = 0x01; + + hid_send_feature_report(dev, usb_buf, 8); +} + +std::string RoccatHordeAimoController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string RoccatHordeAimoController::GetNameString() +{ + return(name); +} + +std::string RoccatHordeAimoController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void RoccatHordeAimoController::SetColors(std::vector colors) +{ + unsigned char usb_buf[WRITE_PACKET_LENGTH]; + + usb_buf[0x00] = REPORT_ID; + usb_buf[0x01] = WRITE_PACKET_LENGTH; + usb_buf[0x02] = 0xFF; + usb_buf[0x03] = 0xFF; + + for(unsigned int i = 0; i < 6; i++) + { + usb_buf[0x04 + (i * 3)] = RGBGetRValue(colors[i]); + usb_buf[0x05 + (i * 3)] = RGBGetGValue(colors[i]); + usb_buf[0x06 + (i * 3)] = RGBGetBValue(colors[i]); + } + + int crc = 0; + + for(unsigned int i = 0; i < WRITE_PACKET_LENGTH - 2; i++) + { + crc += usb_buf[i]; + } + + usb_buf[22] = crc; + usb_buf[23] = crc >> 8; + + hid_send_feature_report(dev, usb_buf, WRITE_PACKET_LENGTH); + + unsigned char usb_read_buf[READ_PACKET_LENGTH]; + hid_get_feature_report(dev, usb_read_buf, READ_PACKET_LENGTH); +} diff --git a/Controllers/RoccatController/RoccatHordeAimoController/RoccatHordeAimoController.h b/Controllers/RoccatController/RoccatHordeAimoController/RoccatHordeAimoController.h new file mode 100644 index 00000000..680feada --- /dev/null +++ b/Controllers/RoccatController/RoccatHordeAimoController/RoccatHordeAimoController.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------*\ +| RoccatHordeAimoController.h | +| | +| Driver for Roccat Horde Aimo | +| | +| Morgan Guimard (morg) 24 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" + +#define WRITE_PACKET_LENGTH 24 +#define READ_PACKET_LENGTH 3 +#define REPORT_ID 0x18 +#define NUMBER_OF_LEDS 6 + +class RoccatHordeAimoController +{ +public: + RoccatHordeAimoController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~RoccatHordeAimoController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SetColors(std::vector colors); + +private: + hid_device* dev; + std::string location; + std::string name; + + void InitialPacket(); +}; diff --git a/Controllers/RoccatController/RoccatKoneAimoController.cpp b/Controllers/RoccatController/RoccatKoneAimoController.cpp deleted file mode 100644 index 3ae2dfd9..00000000 --- a/Controllers/RoccatController/RoccatKoneAimoController.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RoccatKoneAimoController.cpp | -| | -| Driver for Roccat Kone Aimo Mouse | -| | -| Thibaud M (enlight3d) 17th Nov 2020 | -| | -\*-------------------------------------------------------------------*/ - -#include "RoccatKoneAimoController.h" - -#include - -RoccatKoneAimoController::RoccatKoneAimoController(hid_device* dev_handle, char *_path) -{ - dev = dev_handle; - location = _path; - - const int szTemp = 256; - wchar_t tmpName[szTemp]; - - hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - device_name = std::string(wName.begin(), wName.end()); - - hid_get_product_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); - - hid_get_serial_number_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - serial = std::string(wName.begin(), wName.end()); - - /*-----------------------------------------------------*\ - | Init usb buffer to 0 and add first two bytes | - \*-----------------------------------------------------*/ - memset(usb_colors_buf, 0x00, USB_COLOR_BUFF_LEN); - usb_colors_buf[0x00] = 0x0D; - usb_colors_buf[0x01] = 0x2E; - - SendInit(); -} - -RoccatKoneAimoController::~RoccatKoneAimoController() -{ - hid_close(dev); -} - -std::string RoccatKoneAimoController::GetDeviceName() -{ - return device_name; -} - -std::string RoccatKoneAimoController::GetSerial() -{ - return serial; -} - -std::string RoccatKoneAimoController::GetLocation() -{ - return("HID: " + location); -} - -void RoccatKoneAimoController::SendInit() -{ - unsigned char usb_buf[6] = {00}; - - /*-----------------------------------------------------*\ - | Read first a packet from mouse (swarm does it) | - \*-----------------------------------------------------*/ - hid_get_feature_report(dev, usb_buf, 3); - - /*-----------------------------------------------------*\ - | Set up Init packet | - \*-----------------------------------------------------*/ - usb_buf[0x00] = 0x0E; - usb_buf[0x01] = 0x06; - usb_buf[0x02] = 0x01; - usb_buf[0x03] = 0x01; - usb_buf[0x04] = 0x00; - usb_buf[0x05] = 0xFF; - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_send_feature_report(dev, usb_buf, 6); -} - -void RoccatKoneAimoController::SetChannelColors(ROCCAT_KONE_AIMO_CHANNEL channel, RGBColor * colors, unsigned int num_colors) -{ - /*---------------------------------------------------------*\ - | Receiving update request for only one channel | - | and updating usb buffer to match colors | - \*---------------------------------------------------------*/ - for(unsigned char i = 0; i < num_colors; i++) - { - std::size_t color = channel + i; - int usb_idx = 0x02 + (color * 4); - - usb_colors_buf[usb_idx + R_OFFSET] = RGBGetRValue(colors[i]); - usb_colors_buf[usb_idx + G_OFFSET] = RGBGetGValue(colors[i]); - usb_colors_buf[usb_idx + B_OFFSET] = RGBGetBValue(colors[i]); - } -} - -void RoccatKoneAimoController::SendUpdate() -{ - /*-----------------------------------------------------*\ - | Send packet (whole buffer needs to be sent everytime) | - \*-----------------------------------------------------*/ - hid_send_feature_report(dev, usb_colors_buf, 46); - /*-----------------------------------------------------*\ - | Read a packet from mouse (swarm does it) | - \*-----------------------------------------------------*/ - hid_get_feature_report(dev, usb_colors_buf, 3); -} diff --git a/Controllers/RoccatController/RoccatKoneAimoController.h b/Controllers/RoccatController/RoccatKoneAimoController.h deleted file mode 100644 index 2b3d0b51..00000000 --- a/Controllers/RoccatController/RoccatKoneAimoController.h +++ /dev/null @@ -1,57 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RoccatKoneAimoController.h | -| | -| Driver for Roccat Kone Aimo Mouse | -| | -| Thibaud M (enlight3d) 17th Nov 2020 | -| | -\*-------------------------------------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include -#include -#include -#include -#include - -#define NUM_LEDS 11 - -#define R_OFFSET 0 -#define G_OFFSET 1 -#define B_OFFSET 2 - -#define USB_COLOR_BUFF_LEN 46 - -enum ROCCAT_KONE_AIMO_CHANNEL -{ - SCROLL_WHEEL = 0, - STRIP_LEFT = 1, - STRIP_RIGHT = 5, - LOWER_LEFT = 9, - LOWER_RIGHT = 10 -}; - -class RoccatKoneAimoController -{ -public: - RoccatKoneAimoController(hid_device* dev_handle, char *_path); - ~RoccatKoneAimoController(); - - std::string GetDeviceName(); - std::string GetSerial(); - std::string GetLocation(); - - void SetChannelColors(ROCCAT_KONE_AIMO_CHANNEL channel, RGBColor * colors, unsigned int num_colors); - void SendUpdate(); - -private: - std::string device_name; - std::string serial; - std::string location; - hid_device* dev; - unsigned char usb_colors_buf[USB_COLOR_BUFF_LEN]; // USB buffer to be sent everytime we update mouse's LEDs - - void SendInit(); -}; \ No newline at end of file diff --git a/Controllers/RoccatController/RoccatKoneAimoController/RGBController_RoccatKoneAimo.cpp b/Controllers/RoccatController/RoccatKoneAimoController/RGBController_RoccatKoneAimo.cpp new file mode 100644 index 00000000..113f6f0d --- /dev/null +++ b/Controllers/RoccatController/RoccatKoneAimoController/RGBController_RoccatKoneAimo.cpp @@ -0,0 +1,217 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatKoneAimo.cpp | +| | +| RGBController for Roccat Kone Aimo | +| | +| Thibaud M (enlight3d) 17 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_RoccatKoneAimo.h" + +/**------------------------------------------------------------------*\ + @name Roccat Kone Aimo + @category Mouse + @type USB + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectRoccatMouseControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_RoccatKoneAimo::RGBController_RoccatKoneAimo(RoccatKoneAimoController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = "Roccat"; + type = DEVICE_TYPE_MOUSE; + description = "Roccat Kone Aimo Mouse Device"; + location = controller->GetLocation(); + serial = controller->GetSerial(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.speed_min = 0; + Direct.speed_max = 0; + Direct.speed = 0; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + active_mode = 0; + + SetupZones(); +} + +RGBController_RoccatKoneAimo::~RGBController_RoccatKoneAimo() +{ + delete controller; +} + +void RGBController_RoccatKoneAimo::SetupZones() +{ + /*---------------------------------------------------------*\ + | Set up zones and leds per zone | + \*---------------------------------------------------------*/ + zone WHEEL_zone; + WHEEL_zone.name = "Scroll Wheel"; + WHEEL_zone.type = ZONE_TYPE_SINGLE; + WHEEL_zone.leds_min = 1; + WHEEL_zone.leds_max = 1; + WHEEL_zone.leds_count = 1; + WHEEL_zone.matrix_map = NULL; + zones.push_back(WHEEL_zone); + zones_channel.push_back(SCROLL_WHEEL); + + led WHEEL_led; + WHEEL_led.name = "Wheel LED"; + WHEEL_led.value = (unsigned int)zones.size(); + leds.push_back(WHEEL_led); + leds_channel.push_back(SCROLL_WHEEL); + + zone STRIP_LEFT_zone; + STRIP_LEFT_zone.name = "Strip left"; + STRIP_LEFT_zone.type = ZONE_TYPE_LINEAR; + STRIP_LEFT_zone.leds_min = 4; + STRIP_LEFT_zone.leds_max = 4; + STRIP_LEFT_zone.leds_count = 4; + STRIP_LEFT_zone.matrix_map = NULL; + zones.push_back(STRIP_LEFT_zone); + zones_channel.push_back(STRIP_LEFT); + + for(std::size_t led_idx = 0; led_idx < STRIP_LEFT_zone.leds_max; led_idx++) + { + led STRIP_LEFT_led; + STRIP_LEFT_led.name = "Strip left LED " + std::to_string(led_idx + 1); + STRIP_LEFT_led.value = (unsigned int)zones.size(); + leds.push_back(STRIP_LEFT_led); + leds_channel.push_back(STRIP_LEFT); + } + + zone STRIP_RIGHT_zone; + STRIP_RIGHT_zone.name = "Strip right"; + STRIP_RIGHT_zone.type = ZONE_TYPE_LINEAR; + STRIP_RIGHT_zone.leds_min = 4; + STRIP_RIGHT_zone.leds_max = 4; + STRIP_RIGHT_zone.leds_count = 4; + STRIP_RIGHT_zone.matrix_map = NULL; + zones.push_back(STRIP_RIGHT_zone); + zones_channel.push_back(STRIP_RIGHT); + + for(std::size_t led_idx = 0; led_idx < STRIP_RIGHT_zone.leds_max; led_idx++) + { + led STRIP_RIGHT_led; + STRIP_RIGHT_led.name = "Strip right LED " + std::to_string(led_idx + 1); + STRIP_RIGHT_led.value = (unsigned int)zones.size(); + leds.push_back(STRIP_RIGHT_led); + leds_channel.push_back(STRIP_RIGHT); + } + + zone LOWER_LEFT_zone; + LOWER_LEFT_zone.name = "Lower left"; + LOWER_LEFT_zone.type = ZONE_TYPE_SINGLE; + LOWER_LEFT_zone.leds_min = 1; + LOWER_LEFT_zone.leds_max = 1; + LOWER_LEFT_zone.leds_count = 1; + LOWER_LEFT_zone.matrix_map = NULL; + zones.push_back(LOWER_LEFT_zone); + zones_channel.push_back(LOWER_LEFT); + + led LOWER_LEFT_led; + LOWER_LEFT_led.name = "Lower left LED"; + LOWER_LEFT_led.value = (unsigned int)zones.size(); + leds.push_back(LOWER_LEFT_led); + leds_channel.push_back(LOWER_LEFT); + + zone LOWER_RIGHT_zone; + LOWER_RIGHT_zone.name = "Lower right"; + LOWER_RIGHT_zone.type = ZONE_TYPE_SINGLE; + LOWER_RIGHT_zone.leds_min = 1; + LOWER_RIGHT_zone.leds_max = 1; + LOWER_RIGHT_zone.leds_count = 1; + LOWER_RIGHT_zone.matrix_map = NULL; + zones.push_back(LOWER_RIGHT_zone); + zones_channel.push_back(LOWER_RIGHT); + + led LOWER_RIGHT_led; + LOWER_RIGHT_led.name = "Lower right LED"; + LOWER_RIGHT_led.value = (unsigned int)zones.size(); + leds.push_back(LOWER_RIGHT_led); + leds_channel.push_back(LOWER_RIGHT); + + SetupColors(); + + /*---------------------------------------------------------*\ + | Initialize colors for each LED | + \*---------------------------------------------------------*/ + for(std::size_t led_idx = 0; led_idx < leds.size(); led_idx++) + { + unsigned char red = 0x00; + unsigned char grn = 0x00; + unsigned char blu = 0x00; + + colors[led_idx] = ToRGBColor(red, grn, blu); + } +} + +void RGBController_RoccatKoneAimo::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_RoccatKoneAimo::DeviceUpdateLEDs() +{ + /*---------------------------------------------------------*\ + | Set colors for all channel/leds | + \*---------------------------------------------------------*/ + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + controller->SetChannelColors(zones_channel[zone_idx], zones[zone_idx].colors, zones[zone_idx].leds_count); + } + /*---------------------------------------------------------*\ + | Apply new colors to the mouse | + \*---------------------------------------------------------*/ + controller->SendUpdate(); +} + +void RGBController_RoccatKoneAimo::UpdateZoneLEDs(int zone_idx) +{ + /*---------------------------------------------------------*\ + | Set colors for one channel of leds | + \*---------------------------------------------------------*/ + controller->SetChannelColors(zones_channel[zone_idx], zones[zone_idx].colors, zones[zone_idx].leds_count); + /*---------------------------------------------------------*\ + | Apply new colors to the mouse | + \*---------------------------------------------------------*/ + controller->SendUpdate(); +} + +void RGBController_RoccatKoneAimo::UpdateSingleLED(int led_idx) +{ + /*---------------------------------------------------------*\ + | Get channel corresponding to led | + \*---------------------------------------------------------*/ + ROCCAT_KONE_AIMO_CHANNEL channel = leds_channel[led_idx]; + /*---------------------------------------------------------*\ + | Update channel corresponding to led | + \*---------------------------------------------------------*/ + controller->SetChannelColors(channel, zones[leds[led_idx].value].colors, zones[leds[led_idx].value].leds_count); + /*---------------------------------------------------------*\ + | Apply new colors to the mouse | + \*---------------------------------------------------------*/ + controller->SendUpdate(); +} + +void RGBController_RoccatKoneAimo::DeviceUpdateMode() +{ + /*---------------------------------------------------------*\ + | This device does not support changing mode | + \*---------------------------------------------------------*/ +} diff --git a/Controllers/RoccatController/RoccatKoneAimoController/RGBController_RoccatKoneAimo.h b/Controllers/RoccatController/RoccatKoneAimoController/RGBController_RoccatKoneAimo.h new file mode 100644 index 00000000..b273db2b --- /dev/null +++ b/Controllers/RoccatController/RoccatKoneAimoController/RGBController_RoccatKoneAimo.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatKoneAimo.h | +| | +| RGBController for Roccat Kone Aimo | +| | +| Thibaud M (enlight3d) 17 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RoccatKoneAimoController.h" + +class RGBController_RoccatKoneAimo : public RGBController +{ +public: + RGBController_RoccatKoneAimo(RoccatKoneAimoController* controller_ptr); + ~RGBController_RoccatKoneAimo(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RoccatKoneAimoController* controller; + std::vector zones_channel; + std::vector leds_channel; +}; diff --git a/Controllers/RoccatController/RoccatKoneAimoController/RoccatKoneAimoController.cpp b/Controllers/RoccatController/RoccatKoneAimoController/RoccatKoneAimoController.cpp new file mode 100644 index 00000000..6c6db943 --- /dev/null +++ b/Controllers/RoccatController/RoccatKoneAimoController/RoccatKoneAimoController.cpp @@ -0,0 +1,112 @@ +/*---------------------------------------------------------*\ +| RoccatKoneAimoController.cpp | +| | +| Driver for Roccat Kone Aimo | +| | +| Thibaud M (enlight3d) 17 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RoccatKoneAimoController.h" +#include "StringUtils.h" + +RoccatKoneAimoController::RoccatKoneAimoController(hid_device* dev_handle, char *_path, std::string dev_name) +{ + dev = dev_handle; + location = _path; + name = dev_name; + + /*-----------------------------------------------------*\ + | Init usb buffer to 0 and add first two bytes | + \*-----------------------------------------------------*/ + memset(usb_colors_buf, 0x00, USB_COLOR_BUFF_LEN); + usb_colors_buf[0x00] = 0x0D; + usb_colors_buf[0x01] = 0x2E; + + SendInit(); +} + +RoccatKoneAimoController::~RoccatKoneAimoController() +{ + hid_close(dev); +} + +std::string RoccatKoneAimoController::GetName() +{ + return(name); +} + +std::string RoccatKoneAimoController::GetSerial() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string RoccatKoneAimoController::GetLocation() +{ + return("HID: " + location); +} + +void RoccatKoneAimoController::SendInit() +{ + unsigned char usb_buf[6] = {00}; + + /*-----------------------------------------------------*\ + | Read first a packet from mouse (swarm does it) | + \*-----------------------------------------------------*/ + hid_get_feature_report(dev, usb_buf, 3); + + /*-----------------------------------------------------*\ + | Set up Init packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x0E; + usb_buf[0x01] = 0x06; + usb_buf[0x02] = 0x01; + usb_buf[0x03] = 0x01; + usb_buf[0x04] = 0x00; + usb_buf[0x05] = 0xFF; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_send_feature_report(dev, usb_buf, 6); +} + +void RoccatKoneAimoController::SetChannelColors(ROCCAT_KONE_AIMO_CHANNEL channel, RGBColor * colors, unsigned int num_colors) +{ + /*---------------------------------------------------------*\ + | Receiving update request for only one channel | + | and updating usb buffer to match colors | + \*---------------------------------------------------------*/ + for(unsigned char i = 0; i < num_colors; i++) + { + std::size_t color = channel + i; + int usb_idx = (int)(0x02 + (color * 4)); + + usb_colors_buf[usb_idx + R_OFFSET] = RGBGetRValue(colors[i]); + usb_colors_buf[usb_idx + G_OFFSET] = RGBGetGValue(colors[i]); + usb_colors_buf[usb_idx + B_OFFSET] = RGBGetBValue(colors[i]); + } +} + +void RoccatKoneAimoController::SendUpdate() +{ + /*-----------------------------------------------------*\ + | Send packet (whole buffer needs to be sent everytime) | + \*-----------------------------------------------------*/ + hid_send_feature_report(dev, usb_colors_buf, 46); + /*-----------------------------------------------------*\ + | Read a packet from mouse (swarm does it) | + \*-----------------------------------------------------*/ + hid_get_feature_report(dev, usb_colors_buf, 3); +} diff --git a/Controllers/RoccatController/RoccatKoneAimoController/RoccatKoneAimoController.h b/Controllers/RoccatController/RoccatKoneAimoController/RoccatKoneAimoController.h new file mode 100644 index 00000000..9dd005ba --- /dev/null +++ b/Controllers/RoccatController/RoccatKoneAimoController/RoccatKoneAimoController.h @@ -0,0 +1,59 @@ +/*---------------------------------------------------------*\ +| RoccatKoneAimoController.h | +| | +| Driver for Roccat Kone Aimo | +| | +| Thibaud M (enlight3d) 17 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include +#include +#include "RGBController.h" + +#define HID_MAX_STR 255 +#define NUM_LEDS 11 + +#define R_OFFSET 0 +#define G_OFFSET 1 +#define B_OFFSET 2 + +#define USB_COLOR_BUFF_LEN 46 + +enum ROCCAT_KONE_AIMO_CHANNEL +{ + SCROLL_WHEEL = 0, + STRIP_LEFT = 1, + STRIP_RIGHT = 5, + LOWER_LEFT = 9, + LOWER_RIGHT = 10 +}; + +class RoccatKoneAimoController +{ +public: + RoccatKoneAimoController(hid_device* dev_handle, char *_path, std::string dev_name); + ~RoccatKoneAimoController(); + + std::string GetLocation(); + std::string GetName(); + std::string GetSerial(); + + void SetChannelColors(ROCCAT_KONE_AIMO_CHANNEL channel, RGBColor * colors, unsigned int num_colors); + void SendUpdate(); + +private: + std::string location; + std::string name; + hid_device* dev; + unsigned char usb_colors_buf[USB_COLOR_BUFF_LEN]; // USB buffer to be sent everytime we update mouse's LEDs + + void SendInit(); +}; diff --git a/Controllers/RoccatController/RoccatKoneProAirController/RGBController_RoccatKoneProAir.cpp b/Controllers/RoccatController/RoccatKoneProAirController/RGBController_RoccatKoneProAir.cpp new file mode 100644 index 00000000..b13b5006 --- /dev/null +++ b/Controllers/RoccatController/RoccatKoneProAirController/RGBController_RoccatKoneProAir.cpp @@ -0,0 +1,193 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatKoneProAir.cpp | +| | +| RGBController for Roccat Kone Pro Air | +| | +| Plunti 10 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_RoccatKoneProAir.h" + +/**------------------------------------------------------------------*\ + @name Roccat Kone Pro Air Mouse + @category Mouse + @type USB + @save :robot: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectRoccatKoneProAirControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_RoccatKoneProAir::RGBController_RoccatKoneProAir(RoccatKoneProAirController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "Roccat"; + type = DEVICE_TYPE_MOUSE; + description = "Roccat Kone Pro Air Mouse Device"; + serial = controller->GetSerialString(); + location = controller->GetDeviceLocation(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = ROCCAT_KONE_PRO_AIR_DIRECT_MODE_VALUE; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Off; + Off.name = "Off"; + Off.value = ROCCAT_KONE_PRO_AIR_OFF_MODE_VALUE; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Static; + Static.name = "Static"; + Static.value = ROCCAT_KONE_PRO_AIR_STATIC_MODE_VALUE; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Static.color_mode = MODE_COLORS_PER_LED; + Static.brightness = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX; + Static.brightness_min = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MIN; + Static.brightness_max = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX; + modes.push_back(Static); + + mode RainbowWave; + RainbowWave.name = "Rainbow Wave"; + RainbowWave.value = ROCCAT_KONE_PRO_AIR_RAINBOW_WAVE_MODE_VALUE; + RainbowWave.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + RainbowWave.color_mode = MODE_COLORS_NONE; + RainbowWave.brightness = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX; + RainbowWave.brightness_min = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MIN; + RainbowWave.brightness_max = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX; + RainbowWave.speed = ROCCAT_KONE_PRO_AIR_SPEED_MID; + RainbowWave.speed_min = ROCCAT_KONE_PRO_AIR_SPEED_MIN; + RainbowWave.speed_max = ROCCAT_KONE_PRO_AIR_SPEED_MAX; + modes.push_back(RainbowWave); + + mode Heartbeat; + Heartbeat.name = "Heartbeat"; + Heartbeat.value = ROCCAT_KONE_PRO_AIR_HEARTBEAT_MODE_VALUE; + Heartbeat.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Heartbeat.color_mode = MODE_COLORS_PER_LED; + Heartbeat.brightness = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX; + Heartbeat.brightness_min = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MIN; + Heartbeat.brightness_max = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX; + Heartbeat.speed = ROCCAT_KONE_PRO_AIR_SPEED_MID; + Heartbeat.speed_min = ROCCAT_KONE_PRO_AIR_SPEED_MIN; + Heartbeat.speed_max = ROCCAT_KONE_PRO_AIR_SPEED_MAX; + modes.push_back(Heartbeat); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = ROCCAT_KONE_PRO_AIR_BREATHING_MODE_VALUE; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.brightness = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX; + Breathing.brightness_min = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MIN; + Breathing.brightness_max = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX; + Breathing.speed = ROCCAT_KONE_PRO_AIR_SPEED_MID; + Breathing.speed_min = ROCCAT_KONE_PRO_AIR_SPEED_MIN; + Breathing.speed_max = ROCCAT_KONE_PRO_AIR_SPEED_MAX; + modes.push_back(Breathing); + + mode Flashing; + Flashing.name = "Flashing"; + Flashing.value = ROCCAT_KONE_PRO_AIR_FLASHING_MODE_VALUE; + Flashing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Flashing.color_mode = MODE_COLORS_PER_LED; + Flashing.brightness = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX; + Flashing.brightness_min = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MIN; + Flashing.brightness_max = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX; + Flashing.speed = ROCCAT_KONE_PRO_AIR_SPEED_MID; + Flashing.speed_min = ROCCAT_KONE_PRO_AIR_SPEED_MIN; + Flashing.speed_max = ROCCAT_KONE_PRO_AIR_SPEED_MAX; + modes.push_back(Flashing); + + mode Battery; + Battery.name = "Battery"; + Battery.value = ROCCAT_KONE_PRO_AIR_BATTERY_MODE_VALUE; + Battery.flags = MODE_FLAG_AUTOMATIC_SAVE; + Battery.color_mode = MODE_COLORS_NONE; + modes.push_back(Battery); + + SetupZones(); +} + +RGBController_RoccatKoneProAir::~RGBController_RoccatKoneProAir() +{ + delete controller; +} + +void RGBController_RoccatKoneProAir::SetupZones() +{ + zone new_zone; + new_zone.name = "Mouse"; + new_zone.type = ZONE_TYPE_LINEAR; + new_zone.leds_min = ROCCAT_KONE_PRO_AIR_LED_COUNT; + new_zone.leds_max = ROCCAT_KONE_PRO_AIR_LED_COUNT; + new_zone.leds_count = ROCCAT_KONE_PRO_AIR_LED_COUNT; + new_zone.matrix_map = NULL; + zones.push_back(new_zone); + + std::string led_names[2] = + { + "Left Button", + "Right Button" + }; + + for(unsigned int i = 0; i < ROCCAT_KONE_PRO_AIR_LED_COUNT; i++) + { + led new_led; + new_led.name = led_names[i]; + leds.push_back(new_led); + } + + SetupColors(); +} + +void RGBController_RoccatKoneProAir::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_RoccatKoneProAir::DeviceUpdateLEDs() +{ + const mode& active = modes[active_mode]; + + if(active.value == ROCCAT_KONE_PRO_AIR_DIRECT_MODE_VALUE) + { + controller->SendDirect(colors); + } + else + { + controller->SetMode(colors, active.value, active.speed, active.brightness, active.flags); + } +} + +void RGBController_RoccatKoneProAir::UpdateZoneLEDs(int /*zone_idx*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RoccatKoneProAir::UpdateSingleLED(int /*led_idx*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RoccatKoneProAir::DeviceUpdateMode() +{ + const mode& active = modes[active_mode]; + + if(!(active.flags & MODE_FLAG_HAS_PER_LED_COLOR)) + { + DeviceUpdateLEDs(); + } +} diff --git a/Controllers/RoccatController/RoccatKoneProAirController/RGBController_RoccatKoneProAir.h b/Controllers/RoccatController/RoccatKoneProAirController/RGBController_RoccatKoneProAir.h new file mode 100644 index 00000000..f007a454 --- /dev/null +++ b/Controllers/RoccatController/RoccatKoneProAirController/RGBController_RoccatKoneProAir.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatKoneProAir.h | +| | +| RGBController for Roccat Kone Pro Air | +| | +| Plunti 10 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RoccatKoneProAirController.h" + +class RGBController_RoccatKoneProAir : public RGBController +{ +public: + RGBController_RoccatKoneProAir(RoccatKoneProAirController* controller_ptr); + ~RGBController_RoccatKoneProAir(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RoccatKoneProAirController* controller; +}; diff --git a/Controllers/RoccatController/RoccatKoneProAirController/RoccatKoneProAirController.cpp b/Controllers/RoccatController/RoccatKoneProAirController/RoccatKoneProAirController.cpp new file mode 100644 index 00000000..6a0b4ca8 --- /dev/null +++ b/Controllers/RoccatController/RoccatKoneProAirController/RoccatKoneProAirController.cpp @@ -0,0 +1,119 @@ +/*---------------------------------------------------------*\ +| RoccatKoneProAirController.cpp | +| | +| Driver for Roccat Kone Pro Air | +| | +| Plunti 10 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RoccatKoneProAirController.h" +#include "StringUtils.h" + +RoccatKoneProAirController::RoccatKoneProAirController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) +{ + dev = dev_handle; + location = info.path; + name = dev_name; +} + +RoccatKoneProAirController::~RoccatKoneProAirController() +{ + hid_close(dev); +} + +std::string RoccatKoneProAirController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string RoccatKoneProAirController::GetNameString() +{ + return(name); +} + +std::string RoccatKoneProAirController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void RoccatKoneProAirController::SendDirect(std::vector colors) +{ + SendRGB(true, colors, ROCCAT_KONE_PRO_AIR_DIRECT_MODE_VALUE, ROCCAT_KONE_PRO_AIR_SPEED_MAX, ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX); +} + +void RoccatKoneProAirController::SetMode(std::vector colors, unsigned char mode_value, unsigned char speed, unsigned char brightness, unsigned int mode_flags) +{ + /*---------------------------------------------------------*\ + | 1. Read settings | + \*---------------------------------------------------------*/ + unsigned char active_settings[ROCCAT_KONE_PRO_AIR_SETTINGS_READ_PACKET_LENGTH]; + + unsigned char settings_request[] = {0x00, 0x90, 0x00, 0x04, 0x00, 0x18, 0x25, 0x51, 0x32}; + hid_write(dev, settings_request, sizeof(settings_request)); + + do + { + hid_read(dev, active_settings, ROCCAT_KONE_PRO_AIR_SETTINGS_READ_PACKET_LENGTH); + } while( (active_settings[0] != 0x90) || (active_settings[2] != 0x26) ); + + /*---------------------------------------------------------*\ + | 2. Send settings and select profile | + \*---------------------------------------------------------*/ + unsigned char usb_buf[ROCCAT_KONE_PRO_AIR_SETTINGS_WRITE_PACKET_LENGTH]; + memset(usb_buf, 0x00, ROCCAT_KONE_PRO_AIR_SETTINGS_WRITE_PACKET_LENGTH); + + usb_buf[1] = 0x10; + usb_buf[2] = 0x50; + usb_buf[3] = 0x14; + memcpy(usb_buf + 5, active_settings + 10, 19); + usb_buf[24] = active_settings[41]; + + hid_write(dev, usb_buf, ROCCAT_KONE_PRO_AIR_SETTINGS_WRITE_PACKET_LENGTH); + + /*---------------------------------------------------------*\ + | 3. Send RGB | + \*---------------------------------------------------------*/ + SendRGB(false, + colors, + mode_value, + (mode_flags & MODE_FLAG_HAS_SPEED ) ? speed : (unsigned char)ROCCAT_KONE_PRO_AIR_SPEED_MAX, + (mode_flags & MODE_FLAG_HAS_BRIGHTNESS) ? brightness : (unsigned char)ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX + ); +} + +void RoccatKoneProAirController::SendRGB(bool direct, std::vector colors, unsigned char mode_value, unsigned char speed, unsigned char brightness) +{ + unsigned char usb_buf[ROCCAT_KONE_PRO_AIR_RGB_PACKET_LENGTH]; + memset(usb_buf, 0x00, ROCCAT_KONE_PRO_AIR_RGB_PACKET_LENGTH); + + usb_buf[1] = 0x10; + usb_buf[2] = direct ? 0x10 : 0x50; + usb_buf[3] = 0x0B; + usb_buf[4] = direct ? 0x00 : 0x01; + usb_buf[5] = mode_value; + usb_buf[6] = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX; // Explicit brightness for first LED, not used by OpenRGB + usb_buf[7] = ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX; // Explicit brightness for second LED, not used by OpenRGB + usb_buf[8] = brightness; + usb_buf[9] = speed; + + for(unsigned int i = 0; i < colors.size(); i++) + { + usb_buf[10 + 3 * i] = RGBGetRValue(colors[i]); + usb_buf[11 + 3 * i] = RGBGetGValue(colors[i]); + usb_buf[12 + 3 * i] = RGBGetBValue(colors[i]); + } + + hid_write(dev, usb_buf, ROCCAT_KONE_PRO_AIR_RGB_PACKET_LENGTH); +} diff --git a/Controllers/RoccatController/RoccatKoneProAirController/RoccatKoneProAirController.h b/Controllers/RoccatController/RoccatKoneProAirController/RoccatKoneProAirController.h new file mode 100644 index 00000000..4181062e --- /dev/null +++ b/Controllers/RoccatController/RoccatKoneProAirController/RoccatKoneProAirController.h @@ -0,0 +1,62 @@ +/*---------------------------------------------------------*\ +| RoccatKoneProAirController.h | +| | +| Driver for Roccat Kone Pro Air | +| | +| Plunti 10 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" + +#define ROCCAT_KONE_PRO_AIR_RGB_PACKET_LENGTH 16 +#define ROCCAT_KONE_PRO_AIR_SETTINGS_WRITE_PACKET_LENGTH 25 +#define ROCCAT_KONE_PRO_AIR_SETTINGS_READ_PACKET_LENGTH 42 +#define ROCCAT_KONE_PRO_AIR_LED_COUNT 2 + +enum +{ + ROCCAT_KONE_PRO_AIR_DIRECT_MODE_VALUE = 0x09, + ROCCAT_KONE_PRO_AIR_OFF_MODE_VALUE = 0x00, + ROCCAT_KONE_PRO_AIR_STATIC_MODE_VALUE = 0x01, + ROCCAT_KONE_PRO_AIR_RAINBOW_WAVE_MODE_VALUE = 0x06, + ROCCAT_KONE_PRO_AIR_HEARTBEAT_MODE_VALUE = 0x05, + ROCCAT_KONE_PRO_AIR_BREATHING_MODE_VALUE = 0x02, + ROCCAT_KONE_PRO_AIR_FLASHING_MODE_VALUE = 0x08, + ROCCAT_KONE_PRO_AIR_BATTERY_MODE_VALUE = 0x0A +}; + +enum +{ + ROCCAT_KONE_PRO_AIR_SPEED_MIN = 0x01, + ROCCAT_KONE_PRO_AIR_SPEED_MAX = 0x0B, + ROCCAT_KONE_PRO_AIR_SPEED_MID = (ROCCAT_KONE_PRO_AIR_SPEED_MAX - ROCCAT_KONE_PRO_AIR_SPEED_MIN) / 2, + ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MIN = 0x00, + ROCCAT_KONE_PRO_AIR_BRIGHTNESS_MAX = 0x64 +}; + +class RoccatKoneProAirController +{ +public: + RoccatKoneProAirController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~RoccatKoneProAirController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SendDirect(std::vector colors); + void SetMode(std::vector colors, unsigned char mode_value, unsigned char speed, unsigned char brightness, unsigned int mode_flags); + +private: + hid_device* dev; + std::string location; + std::string name; + + void SendRGB(bool direct, std::vector colors, unsigned char mode_value, unsigned char speed, unsigned char brightness); +}; diff --git a/Controllers/RoccatController/RoccatKoneProController/RGBController_RoccatKonePro.cpp b/Controllers/RoccatController/RoccatKoneProController/RGBController_RoccatKonePro.cpp new file mode 100644 index 00000000..75a3a118 --- /dev/null +++ b/Controllers/RoccatController/RoccatKoneProController/RGBController_RoccatKonePro.cpp @@ -0,0 +1,188 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatKonePro.cpp | +| | +| RGBController for Roccat Kone Pro | +| | +| Garrett Denham (GardenOfWyers) 12 Jan 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_RoccatKonePro.h" + +/**------------------------------------------------------------------*\ + @name Roccat Kone Pro Mouse + @category Mouse + @type USB + @save :robot: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectRoccatKoneProControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_RoccatKonePro::RGBController_RoccatKonePro(RoccatKoneProController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "Roccat"; + type = DEVICE_TYPE_MOUSE; + description = "Roccat Kone Pro Mouse Device"; + serial = controller->GetSerialString(); + location = controller->GetDeviceLocation(); + + // Also known as "Intelligent Lighting System" mode in Roccat Swarm + mode Direct; + Direct.name = "Direct"; + Direct.value = ROCCAT_KONE_PRO_DIRECT_MODE_VALUE; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + // Also known as "Fully Lit" mode in Roccat Swarm + mode Static; + Static.name = "Static"; + Static.value = ROCCAT_KONE_PRO_STATIC_MODE_VALUE; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.brightness = ROCCAT_KONE_PRO_BRIGHTNESS_MAX; + Static.brightness_min = ROCCAT_KONE_PRO_BRIGHTNESS_MIN; + Static.brightness_max = ROCCAT_KONE_PRO_BRIGHTNESS_MAX; + Static.colors.resize(ROCCAT_KONE_PRO_LED_COUNT); + modes.push_back(Static); + + // Also known as "Wave" mode in Roccat Swarm + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = ROCCAT_KONE_PRO_WAVE_MODE_VALUE; + Rainbow.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.brightness = ROCCAT_KONE_PRO_BRIGHTNESS_MAX; + Rainbow.brightness_min = ROCCAT_KONE_PRO_BRIGHTNESS_MIN; + Rainbow.brightness_max = ROCCAT_KONE_PRO_BRIGHTNESS_MAX; + Rainbow.speed = ROCCAT_KONE_PRO_SPEED_MID; + Rainbow.speed_min = ROCCAT_KONE_PRO_SPEED_MIN; + Rainbow.speed_max = ROCCAT_KONE_PRO_SPEED_MAX; + modes.push_back(Rainbow); + + mode Heartbeat; + Heartbeat.name = "Heartbeat"; + Heartbeat.value = ROCCAT_KONE_PRO_HEARTBEAT_MODE_VALUE; + Heartbeat.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Heartbeat.color_mode = MODE_COLORS_MODE_SPECIFIC; + Heartbeat.brightness = ROCCAT_KONE_PRO_BRIGHTNESS_MAX; + Heartbeat.brightness_min = ROCCAT_KONE_PRO_BRIGHTNESS_MIN; + Heartbeat.brightness_max = ROCCAT_KONE_PRO_BRIGHTNESS_MAX; + Heartbeat.speed = ROCCAT_KONE_PRO_SPEED_MID; + Heartbeat.speed_min = ROCCAT_KONE_PRO_SPEED_MIN; + Heartbeat.speed_max = ROCCAT_KONE_PRO_SPEED_MAX; + Heartbeat.colors.resize(ROCCAT_KONE_PRO_LED_COUNT); + modes.push_back(Heartbeat); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = ROCCAT_KONE_PRO_BREATHING_MODE_VALUE; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.brightness = ROCCAT_KONE_PRO_BRIGHTNESS_MAX; + Breathing.brightness_min = ROCCAT_KONE_PRO_BRIGHTNESS_MIN; + Breathing.brightness_max = ROCCAT_KONE_PRO_BRIGHTNESS_MAX; + Breathing.speed = ROCCAT_KONE_PRO_SPEED_MID; + Breathing.speed_min = ROCCAT_KONE_PRO_SPEED_MIN; + Breathing.speed_max = ROCCAT_KONE_PRO_SPEED_MAX; + Breathing.colors.resize(ROCCAT_KONE_PRO_LED_COUNT); + modes.push_back(Breathing); + + mode Blinking; + Blinking.name = "Blinking"; + Blinking.value = ROCCAT_KONE_PRO_BLINKING_MODE_VALUE; + Blinking.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Blinking.color_mode = MODE_COLORS_MODE_SPECIFIC; + Blinking.brightness = ROCCAT_KONE_PRO_BRIGHTNESS_MAX; + Blinking.brightness_min = ROCCAT_KONE_PRO_BRIGHTNESS_MIN; + Blinking.brightness_max = ROCCAT_KONE_PRO_BRIGHTNESS_MAX; + Blinking.speed = ROCCAT_KONE_PRO_SPEED_MID; + Blinking.speed_min = ROCCAT_KONE_PRO_SPEED_MIN; + Blinking.speed_max = ROCCAT_KONE_PRO_SPEED_MAX; + Blinking.colors.resize(ROCCAT_KONE_PRO_LED_COUNT); + modes.push_back(Blinking); + + SetupZones(); +} + +RGBController_RoccatKonePro::~RGBController_RoccatKonePro() +{ + delete controller; +} + +void RGBController_RoccatKonePro::SetupZones() +{ + zone new_zone; + new_zone.name = "Mouse"; + new_zone.type = ZONE_TYPE_LINEAR; + new_zone.leds_min = ROCCAT_KONE_PRO_LED_COUNT; + new_zone.leds_max = ROCCAT_KONE_PRO_LED_COUNT; + new_zone.leds_count = ROCCAT_KONE_PRO_LED_COUNT; + new_zone.matrix_map = NULL; + zones.push_back(new_zone); + + std::string led_names[2] = + { + "Left Button", + "Right Button" + }; + + for(unsigned int i = 0; i < ROCCAT_KONE_PRO_LED_COUNT; i++) + { + led new_led; + new_led.name = led_names[i]; + leds.push_back(new_led); + } + + SetupColors(); +} + +void RGBController_RoccatKonePro::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_RoccatKonePro::DeviceUpdateLEDs() +{ + const mode& active = modes[active_mode]; + + if(active.value == ROCCAT_KONE_PRO_DIRECT_MODE_VALUE) + { + controller->SendDirect(colors); + } + else + { + controller->SetMode(active.colors, active.value, active.speed, active.brightness, active.color_mode, active.flags); + } +} + +void RGBController_RoccatKonePro::UpdateZoneLEDs(int /*zone_idx*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RoccatKonePro::UpdateSingleLED(int /*led_idx*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RoccatKonePro::DeviceUpdateMode() +{ + if(modes[active_mode].value == ROCCAT_KONE_PRO_DIRECT_MODE_VALUE) + { + controller->SetupDirectMode(); + } + else + { + DeviceUpdateLEDs(); + } +} diff --git a/Controllers/RoccatController/RoccatKoneProController/RGBController_RoccatKonePro.h b/Controllers/RoccatController/RoccatKoneProController/RGBController_RoccatKonePro.h new file mode 100644 index 00000000..86ef9efb --- /dev/null +++ b/Controllers/RoccatController/RoccatKoneProController/RGBController_RoccatKonePro.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatKonePro.h | +| | +| RGBController for Roccat Kone Pro | +| | +| Garrett Denham (GardenOfWyers) 12 Jan 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RoccatKoneProController.h" + +class RGBController_RoccatKonePro : public RGBController +{ +public: + RGBController_RoccatKonePro(RoccatKoneProController* controller_ptr); + ~RGBController_RoccatKonePro(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RoccatKoneProController* controller; +}; diff --git a/Controllers/RoccatController/RoccatKoneProController/RoccatKoneProController.cpp b/Controllers/RoccatController/RoccatKoneProController/RoccatKoneProController.cpp new file mode 100644 index 00000000..0af3d3cd --- /dev/null +++ b/Controllers/RoccatController/RoccatKoneProController/RoccatKoneProController.cpp @@ -0,0 +1,169 @@ +/*---------------------------------------------------------*\ +| RoccatKoneProController.cpp | +| | +| Driver for Roccat Kone Pro | +| | +| Garrett Denham (GardenOfWyers) 12 Jan 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RoccatKoneProController.h" +#include "StringUtils.h" + +RoccatKoneProController::RoccatKoneProController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) +{ + dev = dev_handle; + location = info.path; + name = dev_name; + + SetupDirectMode(); +} + +RoccatKoneProController::~RoccatKoneProController() +{ + hid_close(dev); +} + +std::string RoccatKoneProController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string RoccatKoneProController::GetNameString() +{ + return(name); +} + +std::string RoccatKoneProController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void RoccatKoneProController::SetupDirectMode() +{ + SwitchControl(true); +} + +void RoccatKoneProController::SwitchControl(bool direct) +{ + unsigned char usb_buf[ROCCAT_KONE_PRO_CONTROL_MODE_PACKET_LENGTH]; + + usb_buf[0x00] = 0x0E; + usb_buf[0x01] = 0x06; + usb_buf[0x02] = 0x01; + usb_buf[0x03] = direct ? 0x01 : 0x00; + usb_buf[0x04] = 0x00; + usb_buf[0x05] = 0xFF; + + hid_send_feature_report(dev, usb_buf, ROCCAT_KONE_PRO_CONTROL_MODE_PACKET_LENGTH); +} + +void RoccatKoneProController::SendDirect(std::vector colors) +{ + unsigned char usb_buf[ROCCAT_KONE_PRO_DIRECT_MODE_PACKET_LENGTH]; + + memset(usb_buf, 0x00, ROCCAT_KONE_PRO_DIRECT_MODE_PACKET_LENGTH); + + usb_buf[0x00] = ROCCAT_KONE_PRO_DIRECT_MODE_REPORT_ID; + usb_buf[0x01] = ROCCAT_KONE_PRO_DIRECT_MODE_BYTE; + + for(unsigned int i = 0; i < colors.size(); i++) + { + usb_buf[0x02 + 3 * i] = RGBGetRValue(colors[i]); + usb_buf[0x03 + 3 * i] = RGBGetGValue(colors[i]); + usb_buf[0x04 + 3 * i] = RGBGetBValue(colors[i]); + } + + hid_send_feature_report(dev, usb_buf, ROCCAT_KONE_PRO_DIRECT_MODE_PACKET_LENGTH); +} + +void RoccatKoneProController::SetMode(std::vector colors, unsigned char mode_value, unsigned char speed, unsigned char brightness, unsigned int color_mode, unsigned int mode_flags) +{ + /*---------------------------------------------------------*\ + | 1. Read from flash | + \*---------------------------------------------------------*/ + unsigned char usb_buf[ROCCAT_KONE_PRO_FLASH_PACKET_LENGTH]; + memset(usb_buf, 0x00, ROCCAT_KONE_PRO_FLASH_PACKET_LENGTH); + + hid_get_feature_report(dev, usb_buf, ROCCAT_KONE_PRO_FLASH_PACKET_LENGTH); + + /*---------------------------------------------------------*\ + | 2. Update needed bytes | + \*---------------------------------------------------------*/ + usb_buf[0x00] = 0x06; + usb_buf[0x01] = 0x45; + + usb_buf[0x03] = 0x06; + usb_buf[0x04] = 0x06; + usb_buf[0x05] = 0x1F; + + usb_buf[0x1E] = mode_value; + usb_buf[0x1F] = mode_flags & MODE_FLAG_HAS_SPEED ? speed : 0xFF; + usb_buf[0x20] = brightness; + + if(color_mode & MODE_COLORS_MODE_SPECIFIC) + { + for(unsigned int i = 0; i < colors.size(); i++) + { + usb_buf[0x24 + 5 * i] = 0x14; + usb_buf[0x25 + 5 * i] = 0xFF; + usb_buf[0x26 + 5 * i] = RGBGetRValue(colors[i]); + usb_buf[0x27 + 5 * i] = RGBGetGValue(colors[i]); + usb_buf[0x28 + 5 * i] = RGBGetBValue(colors[i]); + } + } + else if(color_mode & MODE_COLORS_NONE) + { + for(unsigned int i = 0; i < colors.size(); i++) + { + usb_buf[0x24 + 5 * i] = 0x14; + usb_buf[0x25 + 5 * i] = 0x00; + usb_buf[0x26 + 5 * i] = 0x00; + usb_buf[0x27 + 5 * i] = 0x00; + usb_buf[0x28 + 5 * i] = 0x00; + } + } + + usb_buf[0x2E] = 0x14; + usb_buf[0x2F] = 0xFF; + + unsigned int crc = CalculateCRC(&usb_buf[0x00]); + + usb_buf[0x43] = (unsigned char) crc; + usb_buf[0x44] = crc >> 8; + + /*---------------------------------------------------------*\ + | 3. Send to flash | + \*---------------------------------------------------------*/ + hid_send_feature_report(dev, usb_buf, ROCCAT_KONE_PRO_FLASH_PACKET_LENGTH); + + std::this_thread::sleep_for(std::chrono::milliseconds(10)); + + /*---------------------------------------------------------*\ + | 4. Switch to built-in mode | + \*---------------------------------------------------------*/ + SwitchControl(false); +} + +unsigned int RoccatKoneProController::CalculateCRC(unsigned char* bytes) +{ + unsigned int crc = 0; + + for(unsigned int i = 0; i < ROCCAT_KONE_PRO_FLASH_PACKET_LENGTH - 2; i++) + { + crc += bytes[i]; + } + + return crc; +} diff --git a/Controllers/RoccatController/RoccatKoneProController/RoccatKoneProController.h b/Controllers/RoccatController/RoccatKoneProController/RoccatKoneProController.h new file mode 100644 index 00000000..cd9bacc8 --- /dev/null +++ b/Controllers/RoccatController/RoccatKoneProController/RoccatKoneProController.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------*\ +| RoccatKoneProController.h | +| | +| Driver for Roccat Kone Pro | +| | +| Garrett Denham (GardenOfWyers) 12 Jan 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" + +#define ROCCAT_KONE_PRO_CONTROL_MODE_PACKET_LENGTH 6 +#define ROCCAT_KONE_PRO_DIRECT_MODE_PACKET_LENGTH 11 +#define ROCCAT_KONE_PRO_FLASH_PACKET_LENGTH 69 +#define ROCCAT_KONE_PRO_FLASH_REPORT_ID 0x06 +#define ROCCAT_KONE_PRO_DIRECT_MODE_REPORT_ID 0x0D +#define ROCCAT_KONE_PRO_DIRECT_MODE_BYTE 0x0B +#define ROCCAT_KONE_PRO_LED_COUNT 2 + +enum +{ + ROCCAT_KONE_PRO_DIRECT_MODE_VALUE = 0x00, + ROCCAT_KONE_PRO_STATIC_MODE_VALUE = 0x01, + ROCCAT_KONE_PRO_WAVE_MODE_VALUE = 0x0A, + ROCCAT_KONE_PRO_HEARTBEAT_MODE_VALUE = 0x04, + ROCCAT_KONE_PRO_BREATHING_MODE_VALUE = 0x03, + ROCCAT_KONE_PRO_BLINKING_MODE_VALUE = 0x02 +}; + +enum +{ + ROCCAT_KONE_PRO_SPEED_MIN = 0x01, + ROCCAT_KONE_PRO_SPEED_MAX = 0x0B, + ROCCAT_KONE_PRO_SPEED_MID = (ROCCAT_KONE_PRO_SPEED_MAX - ROCCAT_KONE_PRO_SPEED_MIN) / 2, + ROCCAT_KONE_PRO_BRIGHTNESS_MIN = 0x00, + ROCCAT_KONE_PRO_BRIGHTNESS_MAX = 0xFF +}; + +class RoccatKoneProController +{ +public: + RoccatKoneProController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~RoccatKoneProController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SetupDirectMode(); + void SendDirect(std::vector colors); + void SetMode(std::vector colors, + unsigned char mode_value, + unsigned char speed, + unsigned char brightness, + unsigned int color_mode, + unsigned int mode_flags + ); +private: + hid_device* dev; + std::string location; + std::string name; + + unsigned int CalculateCRC(unsigned char* bytes); + void SwitchControl(bool direct); +}; diff --git a/Controllers/RoccatController/RoccatKoneXPController/RGBController_RoccatKoneXP.cpp b/Controllers/RoccatController/RoccatKoneXPController/RGBController_RoccatKoneXP.cpp new file mode 100644 index 00000000..8f9b34f9 --- /dev/null +++ b/Controllers/RoccatController/RoccatKoneXPController/RGBController_RoccatKoneXP.cpp @@ -0,0 +1,285 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatKoneXP.cpp | +| | +| RGBController for Roccat Kone XP | +| | +| Mola19 12 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_RoccatKoneXP.h" + +/**------------------------------------------------------------------*\ + @name Roccat Kone XP Mouse + @category Mouse + @type USB + @save :robot: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectRoccatKoneXPControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_RoccatKoneXP::RGBController_RoccatKoneXP(RoccatKoneXPController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = "Roccat"; + type = DEVICE_TYPE_MOUSE; + description = "Roccat Kone XP Mouse Device"; + version = controller->GetVersion(); + location = controller->GetLocation(); + serial = controller->GetSerial(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = ROCCAT_KONE_XP_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Off; + Off.name = "Off"; + Off.value = ROCCAT_KONE_XP_MODE_OFF; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Static; + Static.name = "Static"; + Static.value = ROCCAT_KONE_XP_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Static.color_mode = MODE_COLORS_PER_LED; + Static.brightness = ROCCAT_KONE_XP_BRIGHTNESS_DEFAULT; + Static.brightness_min = ROCCAT_KONE_XP_BRIGHTNESS_MIN; + Static.brightness_max = ROCCAT_KONE_XP_BRIGHTNESS_MAX; + modes.push_back(Static); + + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = ROCCAT_KONE_XP_MODE_WAVE; + Rainbow.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.brightness = ROCCAT_KONE_XP_BRIGHTNESS_DEFAULT; + Rainbow.brightness_min = ROCCAT_KONE_XP_BRIGHTNESS_MIN; + Rainbow.brightness_max = ROCCAT_KONE_XP_BRIGHTNESS_MAX; + Rainbow.speed = ROCCAT_KONE_XP_SPEED_DEFAULT; + Rainbow.speed_min = ROCCAT_KONE_XP_SPEED_MIN; + Rainbow.speed_max = ROCCAT_KONE_XP_SPEED_MAX; + modes.push_back(Rainbow); + + mode Blinking; + Blinking.name = "Blinking"; + Blinking.value = ROCCAT_KONE_XP_MODE_BLINKING; + Blinking.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Blinking.color_mode = MODE_COLORS_PER_LED; + Blinking.brightness = ROCCAT_KONE_XP_BRIGHTNESS_DEFAULT; + Blinking.brightness_min = ROCCAT_KONE_XP_BRIGHTNESS_MIN; + Blinking.brightness_max = ROCCAT_KONE_XP_BRIGHTNESS_MAX; + Blinking.speed = ROCCAT_KONE_XP_SPEED_DEFAULT; + Blinking.speed_min = ROCCAT_KONE_XP_SPEED_MIN; + Blinking.speed_max = ROCCAT_KONE_XP_SPEED_MAX; + modes.push_back(Blinking); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = ROCCAT_KONE_XP_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.brightness = ROCCAT_KONE_XP_BRIGHTNESS_DEFAULT; + Breathing.brightness_min = ROCCAT_KONE_XP_BRIGHTNESS_MIN; + Breathing.brightness_max = ROCCAT_KONE_XP_BRIGHTNESS_MAX; + Breathing.speed = ROCCAT_KONE_XP_SPEED_DEFAULT; + Breathing.speed_min = ROCCAT_KONE_XP_SPEED_MIN; + Breathing.speed_max = ROCCAT_KONE_XP_SPEED_MAX; + modes.push_back(Breathing); + + mode Heartbeat; + Heartbeat.name = "Heartbeat"; + Heartbeat.value = ROCCAT_KONE_XP_MODE_HEARTBEAT; + Heartbeat.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Heartbeat.color_mode = MODE_COLORS_PER_LED; + Heartbeat.brightness = ROCCAT_KONE_XP_BRIGHTNESS_DEFAULT; + Heartbeat.brightness_min = ROCCAT_KONE_XP_BRIGHTNESS_MIN; + Heartbeat.brightness_max = ROCCAT_KONE_XP_BRIGHTNESS_MAX; + Heartbeat.speed = ROCCAT_KONE_XP_SPEED_DEFAULT; + Heartbeat.speed_min = ROCCAT_KONE_XP_SPEED_MIN; + Heartbeat.speed_max = ROCCAT_KONE_XP_SPEED_MAX; + modes.push_back(Heartbeat); + + mode Photon; + Photon.name = "Photon FX"; + Photon.value = ROCCAT_KONE_XP_MODE_PHOTON_FX; + Photon.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Photon.color_mode = MODE_COLORS_NONE; + Photon.brightness = ROCCAT_KONE_XP_BRIGHTNESS_DEFAULT; + Photon.brightness_min = ROCCAT_KONE_XP_BRIGHTNESS_MIN; + Photon.brightness_max = ROCCAT_KONE_XP_BRIGHTNESS_MAX; + modes.push_back(Photon); + + /*---------------------------------------------------------------------*\ + | This is the default mode for software modes, while swarm isn't active | + \*---------------------------------------------------------------------*/ + mode Default; + Default.name = "Default"; + Default.value = ROCCAT_KONE_XP_MODE_DEFAULT; + Default.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Default.color_mode = MODE_COLORS_NONE; + Default.brightness = ROCCAT_KONE_XP_BRIGHTNESS_DEFAULT; + Default.brightness_min = ROCCAT_KONE_XP_BRIGHTNESS_MIN; + Default.brightness_max = ROCCAT_KONE_XP_BRIGHTNESS_MAX; + modes.push_back(Default); + + SetupZones(); + + uint8_t active_profile = controller->GetActiveProfile(); + controller->SetReadProfile(active_profile); + controller->WaitUntilReady(); + + roccat_kone_xp_mode_struct active = controller->GetMode(); + + for(uint32_t i = 0; i < modes.size(); i++) + { + if(modes[i].value == active.mode) + { + active_mode = i; + break; + } + + /*----------------------------------------------*\ + | If no mode was found, select 0th mode (direct) | + \*----------------------------------------------*/ + if(i == modes.size() - 1) + { + active_mode = 0; + } + } + + modes[active_mode].speed = active.speed; + modes[active_mode].brightness = active.brightness; + + for(uint8_t i = 0; i < 20; i++) + { + colors[i] = active.colors[i].color; + } +} + +RGBController_RoccatKoneXP::~RGBController_RoccatKoneXP() +{ + delete controller; +} + +void RGBController_RoccatKoneXP::SetupZones() +{ + zone left; + left.name = "Left"; + left.type = ZONE_TYPE_LINEAR; + left.leds_min = 9; + left.leds_max = 9; + left.leds_count = 9; + left.matrix_map = NULL; + zones.push_back(left); + + for (uint8_t i = 1; i <= 9; i++) { + led left_led; + left_led.name = "Left LED " + std::to_string(i); + leds.push_back(left_led); + } + + zone right; + right.name = "Right"; + right.type = ZONE_TYPE_LINEAR; + right.leds_min = 9; + right.leds_max = 9; + right.leds_count = 9; + right.matrix_map = NULL; + zones.push_back(right); + + for (uint8_t i = 1; i <= 9; i++) { + led left_led; + left_led.name = "Right LED " + std::to_string(i); + leds.push_back(left_led); + } + + zone wheel; + wheel.name = "Scrollwheel"; + wheel.type = ZONE_TYPE_SINGLE; + wheel.leds_min = 1; + wheel.leds_max = 1; + wheel.leds_count = 1; + wheel.matrix_map = NULL; + zones.push_back(wheel); + + led wheel_led; + wheel_led.name = "Scrollwheel LED"; + leds.push_back(wheel_led); + + zone dpi; + dpi.name = "DPI button"; + dpi.type = ZONE_TYPE_SINGLE; + dpi.leds_min = 1; + dpi.leds_max = 1; + dpi.leds_count = 1; + dpi.matrix_map = NULL; + zones.push_back(dpi); + + led dpi_led; + dpi_led.name = "DPI button LED"; + leds.push_back(dpi_led); + + SetupColors(); +} + +void RGBController_RoccatKoneXP::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_RoccatKoneXP::DeviceUpdateLEDs() +{ + if(modes[active_mode].value == ROCCAT_KONE_XP_MODE_DIRECT) + { + controller->SendDirect(colors); + } + else + { + DeviceUpdateMode(); + } +} + +void RGBController_RoccatKoneXP::UpdateZoneLEDs(int /*zone_idx*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RoccatKoneXP::UpdateSingleLED(int /*led_idx*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RoccatKoneXP::DeviceUpdateMode() +{ + mode selected = modes[active_mode]; + + roccat_kone_xp_mode_struct active = controller->GetMode(); + + active.mode = selected.value; + active.speed = selected.speed; + active.brightness = (modes[active_mode].value == ROCCAT_KONE_XP_MODE_DIRECT) ? 0xFF : selected.brightness; + + for(uint8_t i = 0; i < 20; i++) + { + active.colors[i].color = colors[i]; + } + + controller->SetMode(active); + controller->WaitUntilReady(); + + controller->EnableDirect(selected.value == ROCCAT_KONE_XP_MODE_DIRECT); + controller->WaitUntilReady(); +} diff --git a/Controllers/RoccatController/RoccatKoneXPController/RGBController_RoccatKoneXP.h b/Controllers/RoccatController/RoccatKoneXPController/RGBController_RoccatKoneXP.h new file mode 100644 index 00000000..dad65cf2 --- /dev/null +++ b/Controllers/RoccatController/RoccatKoneXPController/RGBController_RoccatKoneXP.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatKoneXP.h | +| | +| RGBController for Roccat Kone XP | +| | +| Mola19 12 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RoccatKoneXPController.h" + +class RGBController_RoccatKoneXP : public RGBController +{ +public: + RGBController_RoccatKoneXP(RoccatKoneXPController* controller_ptr); + ~RGBController_RoccatKoneXP(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RoccatKoneXPController* controller; +}; diff --git a/Controllers/RoccatController/RoccatKoneXPController/RoccatKoneXPController.cpp b/Controllers/RoccatController/RoccatKoneXPController/RoccatKoneXPController.cpp new file mode 100644 index 00000000..c9094f60 --- /dev/null +++ b/Controllers/RoccatController/RoccatKoneXPController/RoccatKoneXPController.cpp @@ -0,0 +1,308 @@ +/*---------------------------------------------------------*\ +| RoccatKoneXPController.cpp | +| | +| Driver for Roccat Kone XP | +| | +| Mola19 12 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include "LogManager.h" +#include "RoccatKoneXPController.h" +#include "StringUtils.h" + +RoccatKoneXPController::RoccatKoneXPController(hid_device* dev_handle, char *path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; +} + +RoccatKoneXPController::~RoccatKoneXPController() +{ + hid_close(dev); +} + +std::string RoccatKoneXPController::GetLocation() +{ + return("HID: " + location); +} + +std::string RoccatKoneXPController::GetName() +{ + return(name); +} + +std::string RoccatKoneXPController::GetSerial() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); + +} + +std::string RoccatKoneXPController::GetVersion() +{ + uint8_t buf[9] = { 0x09 }; + int return_length = hid_get_feature_report(dev, buf, 9); + + if(return_length == -1) + { + LOG_DEBUG("[Roccat Kone XP]: Could not fetch version. HIDAPI Error: %ls", hid_error(dev)); + return std::string("Unknown"); + } + + char version[5]; + snprintf(version, 5, "%d.%02d", buf[2] / 100, buf[2] % 100); + + return std::string(version); +} + +uint8_t RoccatKoneXPController::GetActiveProfile() +{ + uint8_t buf[4] = { 0x05 }; + int return_length = hid_get_feature_report(dev, buf, 4); + + if(return_length == -1) + { + LOG_DEBUG("[Roccat Kone XP]: Could not fetch active profile. HIDAPI Error: %ls", hid_error(dev)); + return 0; + } + + return buf[2]; +} + +#include +roccat_kone_xp_mode_struct RoccatKoneXPController::GetMode() +{ + uint8_t buf[0xAE] = { 0x06 }; + int return_length = hid_get_feature_report(dev, buf, 0xAE); + + if(return_length == -1) + { + LOG_DEBUG("[Roccat Kone XP]: Could not fetch mode. HIDAPI Error: %ls", hid_error(dev)); + roccat_kone_xp_mode_struct default_mode; + return default_mode; + } + + roccat_kone_xp_mode_struct active_mode; + + active_mode.profile = buf[2]; + active_mode.byte_3 = buf[3]; + active_mode.byte_4 = buf[4]; + active_mode.dpi_flag = buf[5]; + active_mode.byte_6 = buf[6]; + + for(uint8_t i = 0; i < 10; i++) + { + active_mode.dpi[i] = (buf[8 + i * 2] << 8) + buf[7 + i * 2]; + } + + active_mode.angle_snapping = (bool) buf[27]; + active_mode.byte_28 = buf[28]; + active_mode.polling_rate = buf[29]; + active_mode.mode = buf[30]; + active_mode.speed = buf[31]; + active_mode.brightness = buf[32]; + active_mode.time_until_idle = buf[33]; + active_mode.idle_mode = buf[34]; + active_mode.byte_35 = buf[35]; + + for(uint8_t i = 0; i < 20; i++) + { + active_mode.colors[i].brightness = buf[37 + i * 6]; + active_mode.colors[i].color = ToRGBColor( + buf[38 + i * 6], + buf[39 + i * 6], + buf[40 + i * 6] + ); + } + + active_mode.byte_156 = buf[156]; + active_mode.byte_157 = buf[157]; + active_mode.profile_color_brightness = buf[158]; + active_mode.profile_color_red = buf[159]; + active_mode.profile_color_green = buf[160]; + active_mode.profile_color_blue = buf[161]; + active_mode.byte_162 = buf[162]; + active_mode.theme = buf[163]; + active_mode.auto_dpi_flag = buf[164]; + + active_mode.end_bytes[0] = buf[165]; + active_mode.end_bytes[1] = buf[166]; + active_mode.end_bytes[2] = buf[167]; + active_mode.end_bytes[3] = buf[168]; + active_mode.end_bytes[4] = buf[169]; + active_mode.end_bytes[5] = buf[170]; + active_mode.end_bytes[6] = buf[171]; + + return active_mode; +} + +void RoccatKoneXPController::EnableDirect(bool on_off_switch) +{ + unsigned char usb_buf[6]; + + usb_buf[0x00] = 0x0E; + usb_buf[0x01] = 0x06; + usb_buf[0x02] = 0x01; + usb_buf[0x03] = on_off_switch; + usb_buf[0x04] = 0x00; + usb_buf[0x05] = 0xFF; + + int return_length = hid_send_feature_report(dev, usb_buf, 6); + + if(return_length == -1) + { + LOG_DEBUG("[Roccat Kone XP]: Could not send mode. HIDAPI Error: %ls", hid_error(dev)); + } +} + +void RoccatKoneXPController::SetReadProfile(uint8_t profile) +{ + unsigned char usb_buf[4]; + + usb_buf[0x00] = 0x04; + usb_buf[0x01] = profile; + usb_buf[0x02] = 0x80; + usb_buf[0x03] = 0xFF; + + int return_length = hid_send_feature_report(dev, usb_buf, 4); + + if(return_length == -1) + { + LOG_DEBUG("[Roccat Kone XP]: Could not set profile to read. HIDAPI Error: %ls", hid_error(dev)); + } +} + +void RoccatKoneXPController::SetMode(roccat_kone_xp_mode_struct mode) +{ + uint8_t buf[0xAE]; + memset(buf, 0x00, 0xAE); + + buf[0x00] = 0x06; + buf[0x01] = 0xAE; + + buf[0x02] = mode.profile; + buf[0x03] = mode.byte_3; + buf[0x04] = mode.byte_4; + buf[0x05] = mode.dpi_flag; + buf[0x06] = mode.byte_6; + + for(uint8_t i = 0; i < 10; i++) + { + buf[0x07 + i * 2] = mode.dpi[i] & 0xFF; + buf[0x08 + i * 2] = mode.dpi[i] >> 8; + } + + buf[0x1B] = mode.angle_snapping; + buf[0x1C] = mode.byte_28; + buf[0x1D] = mode.polling_rate; + buf[0x1E] = mode.mode; + buf[0x1F] = mode.speed; + buf[0x20] = mode.brightness; + buf[0x21] = mode.time_until_idle; + buf[0x22] = mode.idle_mode; + buf[0x23] = mode.byte_35; + + for(uint8_t i = 0; i < 20; i++) + { + buf[0x24 + i * 6] = mode.colors[i].byte_0; + buf[0x25 + i * 6] = 0xFF; + buf[0x26 + i * 6] = RGBGetRValue(mode.colors[i].color); + buf[0x27 + i * 6] = RGBGetGValue(mode.colors[i].color); + buf[0x28 + i * 6] = RGBGetBValue(mode.colors[i].color); + buf[0x29 + i * 6] = mode.colors[i].byte_5; + } + + buf[0x9C] = mode.byte_156; + buf[0x9D] = mode.byte_157; + buf[0x9E] = mode.profile_color_brightness; + buf[0x9F] = mode.profile_color_red; + buf[0xA0] = mode.profile_color_green; + buf[0xA1] = mode.profile_color_blue; + buf[0xA2] = mode.byte_162; + buf[0xA3] = mode.theme & ~0x80; // this stores the swarm intern selected theme (biggest bit is a flag for custom theme) + buf[0xA4] = mode.auto_dpi_flag; + + for(uint8_t i = 0; i < 7; i++) + { + buf[0xA5 + i] = mode.end_bytes[i]; + } + + unsigned short total = 0; + for(int i = 0; i < 0xAE - 2; i++) total += buf[i]; + + buf[0xAE - 2] = total & 0xFF; + buf[0xAE - 1] = total >> 8; + + + int return_length = hid_send_feature_report(dev, buf, 0xAE); + + if(return_length == -1) + { + LOG_DEBUG("[Roccat Kone XP]: Could not send mode. HIDAPI Error: %ls", hid_error(dev)); + } +} + +void RoccatKoneXPController::SendDirect(std::vector colors) +{ + uint8_t buf[0x7A]; + memset(buf, 0x00, 0x7A); + + buf[0x00] = 0x0D; + buf[0x01] = 0x7A; + + for(uint8_t i = 0; i < colors.size() && i < 20; i++) + { + /*-----------------------------------------------------------*\ + | This device uses rgbrgb which means that e.g. the red value | + | is calculated by multiplying both given red values. | + | Maybe it is some sort of brightness? | + | For OpenRGBs purpose these aren't usefull, | + | so the second part is always 0xff. | + \*-----------------------------------------------------------*/ + buf[0x02 + i * 6] = RGBGetRValue(colors[i]); + buf[0x03 + i * 6] = RGBGetGValue(colors[i]); + buf[0x04 + i * 6] = RGBGetBValue(colors[i]); + buf[0x05 + i * 6] = 0xFF; + buf[0x06 + i * 6] = 0xFF; + buf[0x07 + i * 6] = 0xFF; + } + + int return_length = hid_send_feature_report(dev, buf, 0x7A); + + if(return_length == -1) + { + LOG_DEBUG("[Roccat Kone XP]: Could not send direct. HIDAPI Error: %ls", hid_error(dev)); + } +} + +void RoccatKoneXPController::WaitUntilReady() +{ + uint8_t buf[4]; + memset(buf, 0x00, 4); + + buf[0] = 0x04; + + for(unsigned char i = 0; buf[1] != 1 && i < 100; i++) + { + if(i != 0) + { + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + + hid_get_feature_report(dev, buf, 4); + } +} diff --git a/Controllers/RoccatController/RoccatKoneXPController/RoccatKoneXPController.h b/Controllers/RoccatController/RoccatKoneXPController/RoccatKoneXPController.h new file mode 100644 index 00000000..150f25f1 --- /dev/null +++ b/Controllers/RoccatController/RoccatKoneXPController/RoccatKoneXPController.h @@ -0,0 +1,103 @@ +/*---------------------------------------------------------*\ +| RoccatKoneXPController.h | +| | +| Driver for Roccat Kone XP | +| | +| Mola19 12 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" + +enum +{ + ROCCAT_KONE_XP_MODE_DIRECT = 0x0B, + ROCCAT_KONE_XP_MODE_OFF = 0x00, + ROCCAT_KONE_XP_MODE_STATIC = 0x01, + ROCCAT_KONE_XP_MODE_BLINKING = 0x02, + ROCCAT_KONE_XP_MODE_BREATHING = 0x03, + ROCCAT_KONE_XP_MODE_HEARTBEAT = 0x04, + ROCCAT_KONE_XP_MODE_PHOTON_FX = 0x05, + ROCCAT_KONE_XP_MODE_DEFAULT = 0x09, + ROCCAT_KONE_XP_MODE_WAVE = 0x0A +}; + +enum +{ + ROCCAT_KONE_XP_SPEED_MIN = 0x0B, + ROCCAT_KONE_XP_SPEED_MAX = 0x01, + ROCCAT_KONE_XP_SPEED_DEFAULT = 0x06, + ROCCAT_KONE_XP_BRIGHTNESS_MIN = 0x00, + ROCCAT_KONE_XP_BRIGHTNESS_MAX = 0xFF, + ROCCAT_KONE_XP_BRIGHTNESS_DEFAULT = 0xFF +}; + +struct roccat_kone_xp_color_struct +{ + uint8_t byte_0 = 0x14; + uint8_t brightness = 0xFF; + RGBColor color = 0; + uint8_t byte_5 = 0x64; +}; + +struct roccat_kone_xp_mode_struct +{ + uint8_t profile = 0; + uint8_t byte_3 = 0x06; + uint8_t byte_4 = 0x06; + uint8_t dpi_flag = 0x1F; + uint8_t byte_6 = 0x01; + uint16_t dpi[10] = { 0x08, 0x10, 0x18, 0x20, 0x40, 0x08, 0x10, 0x18, 0x20, 0x40 }; + bool angle_snapping = false; + uint8_t byte_28 = 0x00; + uint8_t polling_rate = 0x03; + uint8_t mode = ROCCAT_KONE_XP_MODE_STATIC; + uint8_t speed = 0x00; + uint8_t brightness = 0xFF; + uint8_t time_until_idle = 0x0F; + uint8_t idle_mode = 0x00; + uint8_t byte_35 = 0x00; + roccat_kone_xp_color_struct colors[20]; + uint8_t byte_156 = 0x01; + uint8_t byte_157 = 0x64; + uint8_t profile_color_brightness = 0xFF; + uint8_t profile_color_red = 0xFF; + uint8_t profile_color_green = 0x00; + uint8_t profile_color_blue = 0x00; + uint8_t byte_162 = 0x00; + uint8_t theme = 0x80; + uint8_t auto_dpi_flag = 0x00; + uint8_t end_bytes[7] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +}; + +class RoccatKoneXPController +{ +public: + RoccatKoneXPController(hid_device* dev_handle, char *path, std::string dev_name); + ~RoccatKoneXPController(); + + std::string GetLocation(); + std::string GetName(); + std::string GetSerial(); + std::string GetVersion(); + + uint8_t GetActiveProfile(); + roccat_kone_xp_mode_struct GetMode(); + + void EnableDirect(bool on_off_switch); + void SetReadProfile(uint8_t profile); + void SendDirect(std::vector colors); + void SetMode(roccat_kone_xp_mode_struct mode); + + void WaitUntilReady(); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/RoccatController/RGBController_RoccatKova.cpp b/Controllers/RoccatController/RoccatKovaController/RGBController_RoccatKova.cpp similarity index 85% rename from Controllers/RoccatController/RGBController_RoccatKova.cpp rename to Controllers/RoccatController/RoccatKovaController/RGBController_RoccatKova.cpp index f0e69b97..48f2aae1 100644 --- a/Controllers/RoccatController/RGBController_RoccatKova.cpp +++ b/Controllers/RoccatController/RoccatKovaController/RGBController_RoccatKova.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_RoccatKova.cpp | -| | -| RGB Controller for Roccat Kova | -| | -| Gustash 01/12/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_RoccatKova.cpp | +| | +| RGBController for Roccat Kova | +| | +| Gustash 01 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_RoccatKova.h" @@ -26,13 +29,13 @@ RGBController_RoccatKova::RGBController_RoccatKova(RoccatKovaController* control { controller = controller_ptr; - type = DEVICE_TYPE_MOUSE; - name = "Roccat Kova"; + name = controller->GetName(); vendor = "Roccat"; - description = "Controller compatible with the Roccat Kova gaming mouse"; + type = DEVICE_TYPE_MOUSE; + description = "Roccat Kova Mouse Device"; serial = controller->GetSerial(); location = controller->GetLocation(); - version = controller->GetFirmwareVersion(); + version = controller->GetVersion(); mode Static; Static.name = "Static"; diff --git a/Controllers/RoccatController/RoccatKovaController/RGBController_RoccatKova.h b/Controllers/RoccatController/RoccatKovaController/RGBController_RoccatKova.h new file mode 100644 index 00000000..921b70c4 --- /dev/null +++ b/Controllers/RoccatController/RoccatKovaController/RGBController_RoccatKova.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatKova.h | +| | +| RGBController for Roccat Kova | +| | +| Gustash 01 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RoccatKovaController.h" + +class RGBController_RoccatKova : public RGBController +{ +public: + RGBController_RoccatKova(RoccatKovaController *controller_ptr); + ~RGBController_RoccatKova(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RoccatKovaController *controller; +}; diff --git a/Controllers/RoccatController/RoccatKovaController.cpp b/Controllers/RoccatController/RoccatKovaController/RoccatKovaController.cpp similarity index 75% rename from Controllers/RoccatController/RoccatKovaController.cpp rename to Controllers/RoccatController/RoccatKovaController/RoccatKovaController.cpp index f9ff7051..30fa3d39 100644 --- a/Controllers/RoccatController/RoccatKovaController.cpp +++ b/Controllers/RoccatController/RoccatKovaController/RoccatKovaController.cpp @@ -1,19 +1,24 @@ -/*-----------------------------------------*\ -| RoccatKovaController.cpp | -| | -| Controller for Roccat Kova | -| | -| Gustash 01/12/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RoccatKovaController.cpp | +| | +| Driver for Roccat Kova | +| | +| Gustash 01 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RoccatKovaController.h" +#include #include "LogManager.h" -#include +#include "RoccatKovaController.h" +#include "StringUtils.h" -RoccatKovaController::RoccatKovaController(hid_device* dev_handle, char *path) +RoccatKovaController::RoccatKovaController(hid_device* dev_handle, char *path, std::string dev_name) { - dev = dev_handle; - location = path; + dev = dev_handle; + location = path; + name = dev_name; SendInitialPacket(); FetchFirmwareVersion(); @@ -26,31 +31,30 @@ RoccatKovaController::~RoccatKovaController() std::string RoccatKovaController::GetLocation() { - return ("HID: " + location); + return("HID: " + location); +} + +std::string RoccatKovaController::GetName() +{ + return(name); } std::string RoccatKovaController::GetSerial() { - const uint8_t sz = ROCCAT_KOVA_HID_MAX_STR; - wchar_t tmp[sz]; - - uint8_t ret = hid_get_serial_number_string(dev, tmp, sz); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); if(ret != 0) { - LOG_DEBUG("[Roccat Kova] Get HID Serial string failed"); - return ""; + return(""); } - std::wstring w_tmp = std::wstring(tmp); - std::string serial = std::string(w_tmp.begin(), w_tmp.end()); - - return serial; + return(StringUtils::wstring_to_string(serial_string)); } -std::string RoccatKovaController::GetFirmwareVersion() +std::string RoccatKovaController::GetVersion() { - return firmware_version; + return(version); } void RoccatKovaController::SetColor(RGBColor color_wheel, @@ -120,10 +124,10 @@ void RoccatKovaController::FetchFirmwareVersion() hid_get_feature_report(dev, buf, ROCCAT_KOVA_VERSION_READ_PACKET_SIZE); - uint8_t version = buf[ROCCAT_KOVA_FIRMWARE_VERSION_IDX]; + uint8_t fw_version = buf[ROCCAT_KOVA_FIRMWARE_VERSION_IDX]; char version_str[5] {00}; - snprintf(version_str, 5, "%.2f", version / 100.); - firmware_version = version_str; + snprintf(version_str, 5, "%.2f", fw_version / 100.); + version = version_str; } void RoccatKovaController::FetchProfileData(uint8_t *buf) diff --git a/Controllers/RoccatController/RoccatKovaController.h b/Controllers/RoccatController/RoccatKovaController/RoccatKovaController.h similarity index 75% rename from Controllers/RoccatController/RoccatKovaController.h rename to Controllers/RoccatController/RoccatKovaController/RoccatKovaController.h index f7516169..19ddc894 100644 --- a/Controllers/RoccatController/RoccatKovaController.h +++ b/Controllers/RoccatController/RoccatKovaController/RoccatKovaController.h @@ -1,15 +1,18 @@ -/*-----------------------------------------*\ -| RoccatKovaController.h | -| | -| Controller for Roccat Kova | -| | -| Gustash 01/12/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RoccatKovaController.h | +| | +| Driver for Roccat Kova | +| | +| Gustash 01 Dec 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include #include "RGBController.h" -#include #define ROCCAT_KOVA_HID_MAX_STR 255 #define ROCCAT_KOVA_LED_COUNT 2 @@ -62,12 +65,13 @@ enum class RoccatKovaController { public: - RoccatKovaController(hid_device* dev_handle, char *path); + RoccatKovaController(hid_device* dev_handle, char *path, std::string dev_name); ~RoccatKovaController(); std::string GetLocation(); + std::string GetName(); std::string GetSerial(); - std::string GetFirmwareVersion(); + std::string GetVersion(); void SetColor(RGBColor color_wheel, RGBColor color_stripe, @@ -78,7 +82,8 @@ public: private: hid_device* dev; std::string location; - std::string firmware_version; + std::string name; + std::string version; void SendInitialPacket(); void FetchProfileData(uint8_t *buf); diff --git a/Controllers/RoccatController/RoccatSenseAimoController/RGBController_RoccatSenseAimo.cpp b/Controllers/RoccatController/RoccatSenseAimoController/RGBController_RoccatSenseAimo.cpp new file mode 100644 index 00000000..a3b99fb4 --- /dev/null +++ b/Controllers/RoccatController/RoccatSenseAimoController/RGBController_RoccatSenseAimo.cpp @@ -0,0 +1,196 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatSenseAimo.cpp | +| | +| RGBController for Roccat Sense Aimo | +| | +| Mola19 09 Aug 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_RoccatSenseAimo.h" + +/**------------------------------------------------------------------*\ + @name Roccat Sense Aimo Mousepad + @category Mousemat + @type USB + @save :robot: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectRoccatSenseAimoControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_RoccatSenseAimo::RGBController_RoccatSenseAimo(RoccatSenseAimoController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + vendor = "Roccat"; + type = DEVICE_TYPE_MOUSEMAT; + description = "Roccat Sense Aimo Mousepad Device"; + version = controller->GetVersion(); + location = controller->GetLocation(); + serial = controller->GetSerial(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = ROCCAT_SENSE_AIMO_MODE_DIRECT; + 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 = ROCCAT_SENSE_AIMO_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Static.color_mode = MODE_COLORS_PER_LED; + Static.brightness = ROCCAT_SENSE_AIMO_BRIGHTNESS_DEFAULT; + Static.brightness_min = ROCCAT_SENSE_AIMO_BRIGHTNESS_MIN; + Static.brightness_max = ROCCAT_SENSE_AIMO_BRIGHTNESS_MAX; + modes.push_back(Static); + + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = ROCCAT_SENSE_AIMO_MODE_WAVE; + Rainbow.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.brightness = ROCCAT_SENSE_AIMO_BRIGHTNESS_DEFAULT; + Rainbow.brightness_min = ROCCAT_SENSE_AIMO_BRIGHTNESS_MIN; + Rainbow.brightness_max = ROCCAT_SENSE_AIMO_BRIGHTNESS_MAX; + Rainbow.speed = ROCCAT_SENSE_AIMO_SPEED_DEFAULT; + Rainbow.speed_min = ROCCAT_SENSE_AIMO_SPEED_MIN; + Rainbow.speed_max = ROCCAT_SENSE_AIMO_SPEED_MAX; + modes.push_back(Rainbow); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = ROCCAT_SENSE_AIMO_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.brightness = ROCCAT_SENSE_AIMO_BRIGHTNESS_DEFAULT; + Breathing.brightness_min = ROCCAT_SENSE_AIMO_BRIGHTNESS_MIN; + Breathing.brightness_max = ROCCAT_SENSE_AIMO_BRIGHTNESS_MAX; + Breathing.speed = ROCCAT_SENSE_AIMO_SPEED_DEFAULT; + Breathing.speed_min = ROCCAT_SENSE_AIMO_SPEED_MIN; + Breathing.speed_max = ROCCAT_SENSE_AIMO_SPEED_MAX; + modes.push_back(Breathing); + + mode Heartbeat; + Heartbeat.name = "Heartbeat"; + Heartbeat.value = ROCCAT_SENSE_AIMO_MODE_HEARTBEAT; + Heartbeat.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED; + Heartbeat.color_mode = MODE_COLORS_PER_LED; + Heartbeat.brightness = ROCCAT_SENSE_AIMO_BRIGHTNESS_DEFAULT; + Heartbeat.brightness_min = ROCCAT_SENSE_AIMO_BRIGHTNESS_MIN; + Heartbeat.brightness_max = ROCCAT_SENSE_AIMO_BRIGHTNESS_MAX; + Heartbeat.speed = ROCCAT_SENSE_AIMO_SPEED_DEFAULT; + Heartbeat.speed_min = ROCCAT_SENSE_AIMO_SPEED_MIN; + Heartbeat.speed_max = ROCCAT_SENSE_AIMO_SPEED_MAX; + modes.push_back(Heartbeat); + + /*---------------------------------------------------------------------*\ + | This is the default mode for software modes, while swarm isn't active | + \*---------------------------------------------------------------------*/ + mode Default; + Default.name = "Default"; + Default.value = ROCCAT_SENSE_AIMO_MODE_DEFAULT; + Default.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS; + Default.color_mode = MODE_COLORS_NONE; + Default.brightness = ROCCAT_SENSE_AIMO_BRIGHTNESS_DEFAULT; + Default.brightness_min = ROCCAT_SENSE_AIMO_BRIGHTNESS_MIN; + Default.brightness_max = ROCCAT_SENSE_AIMO_BRIGHTNESS_MAX; + modes.push_back(Default); + + SetupZones(); + + mode_struct active = controller->GetMode(); + + for(uint32_t i = 0; i < modes.size(); i++) + { + if(modes[i].value == active.mode) + { + active_mode = i; + break; + } + + /*----------------------------------------------*\ + | If no mode was found, select 0th mode (direct) | + \*----------------------------------------------*/ + if(i == modes.size() - 1) + { + active_mode = 0; + } + } + + modes[active_mode].speed = active.speed; + modes[active_mode].brightness = active.brightness; + + colors[0] = active.left; + colors[1] = active.right; +} + +RGBController_RoccatSenseAimo::~RGBController_RoccatSenseAimo() +{ + delete controller; +} + +void RGBController_RoccatSenseAimo::SetupZones() +{ + zone pad; + pad.name = "Mousepad"; + pad.type = ZONE_TYPE_LINEAR; + pad.leds_min = 2; + pad.leds_max = 2; + pad.leds_count = 2; + pad.matrix_map = NULL; + zones.push_back(pad); + + led left_led; + left_led.name = "Mousepad left led"; + leds.push_back(left_led); + + led right_led; + right_led.name = "Mousepad right led"; + leds.push_back(right_led); + + SetupColors(); +} + +void RGBController_RoccatSenseAimo::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_RoccatSenseAimo::DeviceUpdateLEDs() +{ + if(modes[active_mode].value == ROCCAT_SENSE_AIMO_MODE_DIRECT) + { + controller->SendDirect(colors); + } + else + { + DeviceUpdateMode(); + } +} + +void RGBController_RoccatSenseAimo::UpdateZoneLEDs(int /*zone_idx*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RoccatSenseAimo::UpdateSingleLED(int /*led_idx*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RoccatSenseAimo::DeviceUpdateMode() +{ + mode selected = modes[active_mode]; + + mode_struct active = controller->GetMode(); + controller->SetMode(active.profile, selected.value, selected.speed, selected.brightness, colors); +} diff --git a/Controllers/RoccatController/RoccatSenseAimoController/RGBController_RoccatSenseAimo.h b/Controllers/RoccatController/RoccatSenseAimoController/RGBController_RoccatSenseAimo.h new file mode 100644 index 00000000..bad13dcb --- /dev/null +++ b/Controllers/RoccatController/RoccatSenseAimoController/RGBController_RoccatSenseAimo.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatSenseAimo.h | +| | +| RGBController for Roccat Sense Aimo | +| | +| Mola19 09 Aug 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RoccatSenseAimoController.h" + +class RGBController_RoccatSenseAimo : public RGBController +{ +public: + RGBController_RoccatSenseAimo(RoccatSenseAimoController* controller_ptr); + ~RGBController_RoccatSenseAimo(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RoccatSenseAimoController* controller; +}; diff --git a/Controllers/RoccatController/RoccatSenseAimoController/RoccatSenseAimoController.cpp b/Controllers/RoccatController/RoccatSenseAimoController/RoccatSenseAimoController.cpp new file mode 100644 index 00000000..e807b089 --- /dev/null +++ b/Controllers/RoccatController/RoccatSenseAimoController/RoccatSenseAimoController.cpp @@ -0,0 +1,152 @@ +/*---------------------------------------------------------*\ +| RoccatSenseAimoController.cpp | +| | +| Driver for Roccat Sense Aimo | +| | +| Mola19 09 Aug 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "LogManager.h" +#include "RoccatSenseAimoController.h" +#include "StringUtils.h" + +RoccatSenseAimoController::RoccatSenseAimoController(hid_device* dev_handle, char *path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; +} + +RoccatSenseAimoController::~RoccatSenseAimoController() +{ + hid_close(dev); +} + +std::string RoccatSenseAimoController::GetLocation() +{ + return("HID: " + location); +} + +std::string RoccatSenseAimoController::GetName() +{ + return(name); +} + +std::string RoccatSenseAimoController::GetSerial() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string RoccatSenseAimoController::GetVersion() +{ + uint8_t buf[8] = { 0x01 }; + int return_length = hid_get_feature_report(dev, buf, 5); + + if(return_length == -1) + { + LOG_DEBUG("[Roccat Sense Aimo]: Could not fetch mode. HIDAPI Error: %ls", hid_error(dev)); + return std::string("Unknown"); + } + + char version[6]; + snprintf(version, 6, "%2X.%02X", buf[1], buf[2]); + + return std::string(version); +} + +mode_struct RoccatSenseAimoController::GetMode() +{ + uint8_t buf[19] = { 0x02 }; + int return_length = hid_get_feature_report(dev, buf, 19); + + if(return_length == -1) + { + LOG_DEBUG("[Roccat Sense Aimo]: Could not fetch mode. HIDAPI Error: %ls", hid_error(dev)); + mode_struct default_mode; + + default_mode.profile = 0; + default_mode.mode = ROCCAT_SENSE_AIMO_MODE_STATIC; + default_mode.speed = 0; + default_mode.brightness = ROCCAT_SENSE_AIMO_BRIGHTNESS_DEFAULT; + default_mode.left = ToRGBColor(0, 0, 0); + default_mode.right = ToRGBColor(0, 0, 0); + + return default_mode; + } + + mode_struct active_mode; + + active_mode.profile = buf[1]; + active_mode.mode = buf[2]; + active_mode.speed = buf[3]; + active_mode.brightness = buf[4]; + active_mode.left = ToRGBColor(buf[6], buf[7], buf[8]); + active_mode.right = ToRGBColor(buf[14], buf[15], buf[16]); + + return active_mode; +} + +void RoccatSenseAimoController::SetMode(uint8_t profile, uint8_t mode, uint8_t speed, uint8_t brightness, std::vector colors) +{ + uint8_t buf[19]; + memset(buf, 0x00, 19); + + buf[0x00] = 0x02; + buf[0x01] = profile; + + for(uint8_t i = 0; i < 2; i++) + { + buf[0x02 + i * 8] = mode; // this device has per led modes + buf[0x03 + i * 8] = speed; + buf[0x04 + i * 8] = brightness; + buf[0x05 + i * 8] = 0x00; + buf[0x06 + i * 8] = RGBGetRValue(colors[i]); + buf[0x07 + i * 8] = RGBGetGValue(colors[i]); + buf[0x08 + i * 8] = RGBGetBValue(colors[i]); + buf[0x09 + i * 8] = 0xFF; // this device uses RGBA, but OpenRGB doesn't allow it, so it is always max + } + + buf[0x12] = 0x00; // this stores the swarm theme and first bit is a flag if custom is active in swarm. No usage outside Swarm + + int return_length = hid_send_feature_report(dev, buf, 19); + + if(return_length == -1) + { + LOG_DEBUG("[Roccat Sense Aimo]: Could not send mode. HIDAPI Error: %ls", hid_error(dev)); + } +} + +void RoccatSenseAimoController::SendDirect(std::vector colors) +{ + uint8_t buf[9]; + memset(buf, 0x00, 9); + + buf[0x00] = 0x03; + + for(uint8_t i = 0; i < 2; i++) + { + buf[0x01 + i * 4] = RGBGetRValue(colors[i]); + buf[0x02 + i * 4] = RGBGetGValue(colors[i]); + buf[0x03 + i * 4] = RGBGetBValue(colors[i]); + buf[0x04 + i * 4] = 0xFF; // this device uses RGBA, but OpenRGB doesn't allow it, so it is always max + } + + int return_length = hid_send_feature_report(dev, buf, 9); + + if(return_length == -1) + { + LOG_DEBUG("[Roccat Sense Aimo]: Could not send direct. HIDAPI Error: %ls", hid_error(dev)); + } +} diff --git a/Controllers/RoccatController/RoccatSenseAimoController/RoccatSenseAimoController.h b/Controllers/RoccatController/RoccatSenseAimoController/RoccatSenseAimoController.h new file mode 100644 index 00000000..c7f44d05 --- /dev/null +++ b/Controllers/RoccatController/RoccatSenseAimoController/RoccatSenseAimoController.h @@ -0,0 +1,67 @@ +/*---------------------------------------------------------*\ +| RoccatSenseAimoController.h | +| | +| Driver for Roccat Sense Aimo | +| | +| Mola19 09 Aug 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" + +enum +{ + ROCCAT_SENSE_AIMO_MODE_DIRECT = 0x0B, + ROCCAT_SENSE_AIMO_MODE_STATIC = 0x01, + ROCCAT_SENSE_AIMO_MODE_BREATHING = 0x03, + ROCCAT_SENSE_AIMO_MODE_HEARTBEAT = 0x04, + ROCCAT_SENSE_AIMO_MODE_DEFAULT = 0x09, + ROCCAT_SENSE_AIMO_MODE_WAVE = 0x0A +}; + +enum +{ + ROCCAT_SENSE_AIMO_SPEED_MIN = 0xFF, + ROCCAT_SENSE_AIMO_SPEED_MAX = 0x00, + ROCCAT_SENSE_AIMO_SPEED_DEFAULT = 0x07, + ROCCAT_SENSE_AIMO_BRIGHTNESS_MIN = 0x00, + ROCCAT_SENSE_AIMO_BRIGHTNESS_MAX = 0xFF, + ROCCAT_SENSE_AIMO_BRIGHTNESS_DEFAULT = 0xFF +}; + +struct mode_struct +{ + uint8_t profile; + uint8_t mode; + uint8_t speed; + uint8_t brightness; + RGBColor left; + RGBColor right; +}; + +class RoccatSenseAimoController +{ +public: + RoccatSenseAimoController(hid_device* dev_handle, char *path, std::string dev_name); + ~RoccatSenseAimoController(); + + std::string GetLocation(); + std::string GetName(); + std::string GetSerial(); + std::string GetVersion(); + + mode_struct GetMode(); + + void SendDirect(std::vector colors); + void SetMode(uint8_t profile, uint8_t mode, uint8_t speed, uint8_t brightness, std::vector colors); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/RoccatController/RoccatVulcanAimoController.cpp b/Controllers/RoccatController/RoccatVulcanAimoController.cpp deleted file mode 100644 index 2daa7bc3..00000000 --- a/Controllers/RoccatController/RoccatVulcanAimoController.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RoccatVulcanAimoController.cpp | -| | -| Driver for Roccat Vulcan Aimo Mouse | -| | -| Mola19 17/12/2021 | -| | -\*-------------------------------------------------------------------*/ - -#include "RoccatVulcanAimoController.h" - -#include -#include - -RoccatVulcanAimoController::RoccatVulcanAimoController(hid_device* dev_ctrl_handle, hid_device* dev_led_handle, char *path) -{ - dev_ctrl = dev_ctrl_handle; - dev_led = dev_led_handle; - location = path; -} - -RoccatVulcanAimoController::~RoccatVulcanAimoController() -{ - hid_close(dev_ctrl); - hid_close(dev_led); -} - -std::string RoccatVulcanAimoController::GetSerial() -{ - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev_ctrl, 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); - -} - -std::string RoccatVulcanAimoController::GetLocation() -{ - return("HID: " + location); -} - - -device_info RoccatVulcanAimoController::InitDeviceInfo() -{ - unsigned char usb_buf[8] = { 0x0F }; - hid_get_feature_report(dev_ctrl, usb_buf, 8); - - dev_info.version = std::to_string((int) floor(usb_buf[2] / 100)) + "." + std::to_string(usb_buf[2] % 100); - - dev_info.layout_type = usb_buf[6]; - dev_info.layout_variant = usb_buf[7]; - - return dev_info; -} - -device_info RoccatVulcanAimoController::GetDeviceInfo() -{ - return dev_info; -} - - -void RoccatVulcanAimoController::SendColors(std::vector colors) -{ - unsigned char bufs[7][65]; - - for(int p = 0; p < 7; p++) - { - memset(bufs[p], 0x00, 65); - } - - bufs[0][1] = 0xA1; - bufs[0][2] = 0x01; - bufs[0][3] = 0x01; - bufs[0][4] = 0xB4; - - for(unsigned int i = 0; i < colors.size(); i++) - { - int coloumn = floor(colors[i].value / 12); - int row = colors[i].value % 12; - - int offset = coloumn * 36 + row + 4; - - bufs[offset / 64][offset % 64 + 1] = RGBGetRValue(colors[i].color); - - offset += 12; - - bufs[offset / 64][offset % 64 + 1] = RGBGetGValue(colors[i].color); - - offset += 12; - - bufs[offset / 64][offset % 64 + 1] = RGBGetBValue(colors[i].color); - } - - for(int p = 0; p < 7; p++) - { - hid_write(dev_led, bufs[p], 65); - } -} - -void RoccatVulcanAimoController::SendMode(unsigned int mode, unsigned int speed, unsigned int brightness, std::vector colors) -{ - if(speed == 0) speed = 1; - if(brightness == 0) brightness = 1; - - unsigned char buf[443]; - - memset(buf, 0x00, 443); - - buf[0] = 0x0D; - buf[1] = 0xBB; - buf[2] = 0x01; - buf[3] = 0x00; - buf[4] = mode; - buf[5] = speed; - buf[6] = 0x05; - buf[7] = brightness; - buf[8] = 0x00; - - if(mode == ROCCAT_VULCAN_MODE_STATIC) - { - - for(unsigned int i = 0; i < colors.size(); i++) - { - int coloumn = floor(colors[i].value / 12); - int row = colors[i].value % 12; - - int offset = coloumn * 36 + row + 9; - - buf[offset] = RGBGetRValue(colors[i].color); - - offset += 12; - - buf[offset] = RGBGetGValue(colors[i].color); - - offset += 12; - - buf[offset] = RGBGetBValue(colors[i].color); - } - } - - unsigned short total = 0; - for(int i = 0; i < 441; i++) total += buf[i]; - - buf[441] = total & 0xFF; - buf[442] = total >> 8; - - hid_send_feature_report(dev_ctrl, buf, 443); -} diff --git a/Controllers/RoccatController/RoccatVulcanAimoController.h b/Controllers/RoccatController/RoccatVulcanAimoController.h deleted file mode 100644 index 964b63c8..00000000 --- a/Controllers/RoccatController/RoccatVulcanAimoController.h +++ /dev/null @@ -1,57 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RoccatVulcanAimoController.h | -| | -| Driver for Roccat Vulcan Aimo Keyboard | -| | -| Mola19 17/12/2021 | -| | -\*-------------------------------------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "RoccatVulcanAimoLayouts.h" - -#include -#include - -enum -{ - ROCCAT_VULCAN_MODE_DIRECT = 0x0B, - ROCCAT_VULCAN_MODE_STATIC = 0x01, - ROCCAT_VULCAN_MODE_WAVE = 0x0A, -}; - -struct device_info -{ - std::string version; - int layout_type; - int layout_variant; -}; - -struct led_color -{ - unsigned int value; - RGBColor color; -}; - -class RoccatVulcanAimoController -{ -public: - RoccatVulcanAimoController(hid_device* dev_ctrl_handle, hid_device* dev_led_handle, char *path); - ~RoccatVulcanAimoController(); - - std::string GetSerial(); - std::string GetLocation(); - device_info InitDeviceInfo(); - device_info GetDeviceInfo(); - - void SendColors(std::vector colors); - void SendMode(unsigned int mode, unsigned int speed, unsigned int brightness, std::vector colors); - -private: - std::string location; - hid_device* dev_ctrl; - hid_device* dev_led; - device_info dev_info; -}; diff --git a/Controllers/RoccatController/RoccatVulcanAimoLayouts.h b/Controllers/RoccatController/RoccatVulcanAimoLayouts.h deleted file mode 100644 index 6d14b18a..00000000 --- a/Controllers/RoccatController/RoccatVulcanAimoLayouts.h +++ /dev/null @@ -1,335 +0,0 @@ -/*-----------------------------------------*\ -| RoccatVulcanAimoLayouts.h | -| | -| Keyboard Layouts for Roccat Vulcan Aimo | -| USB RGB lighting controller | -| | -| Mola19 09/29/2022 | -\*-----------------------------------------*/ - -#include "RGBControllerKeyNames.h" -#include -#include -#include "RGBController.h" - -#pragma once - -enum -{ - ROCCAT_VULCAN_LAYOUT_US = 6, - ROCCAT_VULCAN_LAYOUT_DE = 7, - ROCCAT_VULCAN_LAYOUT_UK = 0xFF, // this is a placeholder, since the id isn't known -}; - -#define NA 0xFFFFFFFF - -struct led_value -{ - const char* name; - unsigned char id; -}; - -struct layout_info -{ - unsigned int* matrix_map; - int size; - int rows; - int cols; - std::vector led_names; -}; - -static unsigned int ROCCAT_VULCAN_LAYOUT_KEYS_104[6][24] = { - { 0, NA, 8, 14, 19, 24, NA, 34, 39, 44, 49, 55, 61, 66, 70, NA, 74, 78, 83, NA, NA, NA, NA, NA }, - { 1, 6, 9, 15, 20, 25, 29, 35, 40, 45, 50, 56, 62, 67, NA, NA, 75, 79, 84, NA, 87, 92, 96, 101 }, - { 2, NA, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, 71, NA, 76, 80, 85, NA, 88, 93, 97, 102 }, - { 3, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, NA, 72, NA, NA, NA, NA, NA, 89, 94, 98, NA }, - { 4, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, NA, 69, NA, NA, NA, 81, NA, NA, 90, 95, 99, 103 }, - { 5, 7, 13, NA, NA, NA, 33, NA, NA, NA, 54, 60, 65, NA, 73, NA, 77, 82, 86, NA, 91, NA, 100, NA } -}; - - -static unsigned int ROCCAT_VULCAN_LAYOUT_KEYS_105[6][24] = { - { 0, NA, 9, 15, 20, 25, NA, 35, 40, 45, 50, 56, 62, 67, 72, NA, 75, 79, 84, NA, NA, NA, NA, NA }, - { 1, 6, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, NA, NA, 76, 80, 85, NA, 88, 93, 97, 102 }, - { 2, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, 69, NA, NA, 77, 81, 86, NA, 89, 94, 98, 103 }, - { 3, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, 65, 70, 73, NA, NA, NA, NA, NA, 90, 95, 99, NA }, - { 4, 7, 13, 19, 24, 29, 33, 39, 44, 49, 54, 60, NA, 71, NA, NA, NA, 82, NA, NA, 91, 96, 100, 104 }, - { 5, 8, 14, NA, NA, NA, 34, NA, NA, NA, 55, 61, 66, NA, 74, NA, 78, 83, 87, NA, 92, NA, 101, NA } -}; - -static std::map RoccatVulcanLayouts = -{ - { - ROCCAT_VULCAN_LAYOUT_UK, - { - *ROCCAT_VULCAN_LAYOUT_KEYS_105, - 105, - 6, - 24, - { - { KEY_EN_ESCAPE, 0x00 }, - { KEY_EN_BACK_TICK, 0x01 }, - { KEY_EN_TAB, 0x02 }, - { KEY_EN_CAPS_LOCK, 0x03 }, - { KEY_EN_LEFT_SHIFT, 0x04 }, - { KEY_EN_LEFT_CONTROL, 0x05 }, - - { KEY_EN_1, 0x06 }, - { KEY_EN_ISO_BACK_SLASH, 0x09 }, - { KEY_EN_LEFT_WINDOWS, 0x0A }, - - { KEY_EN_F1, 0x0B }, - { KEY_EN_2, 0x0C }, - { KEY_EN_Q, 0x07 }, - { KEY_EN_A, 0x08 }, - { KEY_EN_Z, 0x0F }, - { KEY_EN_LEFT_ALT, 0x10 }, - - { KEY_EN_F2, 0x11 }, - { KEY_EN_3, 0x12 }, - { KEY_EN_W, 0x0D }, - { KEY_EN_S, 0x0E }, - { KEY_EN_X, 0x15 }, - - { KEY_EN_F3, 0x17 }, - { KEY_EN_4, 0x18 }, - { KEY_EN_E, 0x13 }, - { KEY_EN_D, 0x14 }, - { KEY_EN_C, 0x1B }, - - { KEY_EN_F4, 0x1C }, - { KEY_EN_5, 0x1D }, - { KEY_EN_R, 0x19 }, - { KEY_EN_F, 0x1A }, - { KEY_EN_V, 0x20 }, - - { KEY_EN_6, 0x21 }, - { KEY_EN_T, 0x1E }, - { KEY_EN_G, 0x1F }, - { KEY_EN_B, 0x24 }, - { KEY_EN_SPACE, 0x25 }, - - { KEY_EN_F5, 0x30 }, - { KEY_EN_7, 0x31 }, - { KEY_EN_Y, 0x22 }, - { KEY_EN_H, 0x23 }, - { KEY_EN_N, 0x34 }, - - { KEY_EN_F6, 0x35 }, - { KEY_EN_8, 0x36 }, - { KEY_EN_U, 0x32 }, - { KEY_EN_J, 0x33 }, - { KEY_EN_M, 0x39 }, - - { KEY_EN_F7, 0x3B }, - { KEY_EN_9, 0x3C }, - { KEY_EN_I, 0x37 }, - { KEY_EN_K, 0x38 }, - { KEY_EN_COMMA, 0x3F }, - - { KEY_EN_F8, 0x41 }, - { KEY_EN_0, 0x42 }, - { KEY_EN_O, 0x3D }, - { KEY_EN_L, 0x3E }, - { KEY_EN_PERIOD, 0x45 }, - { KEY_EN_RIGHT_ALT, 0x46 }, - - { KEY_EN_F9, 0x4E }, - { KEY_EN_MINUS, 0x48 }, - { KEY_EN_P, 0x43 }, - { KEY_EN_SEMICOLON, 0x44 }, - { KEY_EN_FORWARD_SLASH, 0x4B }, - { KEY_EN_RIGHT_FUNCTION, 0x4C }, - - { KEY_EN_F10, 0x54 }, - { KEY_EN_EQUALS, 0x4F }, - { KEY_EN_LEFT_BRACKET, 0x49 }, - { KEY_EN_QUOTE, 0x4A }, - { KEY_EN_MENU, 0x53 }, - - { KEY_EN_F11, 0x55 }, - { KEY_EN_BACKSPACE, 0x57 }, - { KEY_EN_RIGHT_BRACKET, 0x50 }, - { KEY_EN_POUND, 0x60 }, - { KEY_EN_RIGHT_SHIFT, 0x52 }, - - { KEY_EN_F12, 0x56 }, - { KEY_EN_ISO_ENTER, 0x58 }, - { KEY_EN_RIGHT_CONTROL, 0x59 }, - - { KEY_EN_PRINT_SCREEN, 0x63 }, - { KEY_EN_INSERT, 0x64 }, - { KEY_EN_DELETE, 0x65 }, - { KEY_EN_LEFT_ARROW, 0x66 }, - - { KEY_EN_SCROLL_LOCK, 0x67 }, - { KEY_EN_HOME, 0x68 }, - { KEY_EN_END, 0x69 }, - { KEY_EN_UP_ARROW, 0x6A }, - { KEY_EN_DOWN_ARROW, 0x6B }, - - { KEY_EN_PAUSE_BREAK, 0x6C }, - { KEY_EN_PAGE_UP, 0x6D }, - { KEY_EN_PAGE_DOWN, 0x6E }, - { KEY_EN_RIGHT_ARROW, 0x6F }, - - { KEY_EN_NUMPAD_LOCK, 0x71 }, - { KEY_EN_NUMPAD_7, 0x72 }, - { KEY_EN_NUMPAD_4, 0x73 }, - { KEY_EN_NUMPAD_1, 0x74 }, - { KEY_EN_NUMPAD_0, 0x75 }, - - { KEY_EN_NUMPAD_DIVIDE, 0x77 }, - { KEY_EN_NUMPAD_8, 0x78 }, - { KEY_EN_NUMPAD_5, 0x79 }, - { KEY_EN_NUMPAD_2, 0x7A }, - - { KEY_EN_NUMPAD_TIMES, 0x7C }, - { KEY_EN_NUMPAD_9, 0x7D }, - { KEY_EN_NUMPAD_6, 0x7E }, - { KEY_EN_NUMPAD_3, 0x7F }, - - { KEY_EN_NUMPAD_PERIOD, 0x80 }, - { KEY_EN_NUMPAD_MINUS, 0x81 }, - { KEY_EN_NUMPAD_PLUS, 0x82 }, - { KEY_EN_NUMPAD_ENTER, 0x83 } - } - } - }, - { - ROCCAT_VULCAN_LAYOUT_US, - { - *ROCCAT_VULCAN_LAYOUT_KEYS_104, - 104, - 6, - 24, - { - { KEY_EN_ESCAPE, 0x00 }, - { KEY_EN_BACK_TICK, 0x01 }, - { KEY_EN_TAB, 0x02 }, - { KEY_EN_CAPS_LOCK, 0x03 }, - { KEY_EN_LEFT_SHIFT, 0x04 }, - { KEY_EN_LEFT_CONTROL, 0x05 }, - - { KEY_EN_1, 0x06 }, - { KEY_EN_LEFT_WINDOWS, 0x0A }, - - { KEY_EN_F1, 0x0B }, - { KEY_EN_2, 0x0C }, - { KEY_EN_Q, 0x07 }, - { KEY_EN_A, 0x08 }, - { KEY_EN_Z, 0x0F }, - { KEY_EN_LEFT_ALT, 0x10 }, - - { KEY_EN_F2, 0x11 }, - { KEY_EN_3, 0x12 }, - { KEY_EN_W, 0x0D }, - { KEY_EN_S, 0x0E }, - { KEY_EN_X, 0x15 }, - - { KEY_EN_F3, 0x17 }, - { KEY_EN_4, 0x18 }, - { KEY_EN_E, 0x13 }, - { KEY_EN_D, 0x14 }, - { KEY_EN_C, 0x1B }, - - { KEY_EN_F4, 0x1C }, - { KEY_EN_5, 0x1D }, - { KEY_EN_R, 0x19 }, - { KEY_EN_F, 0x1A }, - { KEY_EN_V, 0x20 }, - - { KEY_EN_6, 0x21 }, - { KEY_EN_T, 0x1E }, - { KEY_EN_G, 0x1F }, - { KEY_EN_B, 0x24 }, - { KEY_EN_SPACE, 0x25 }, - - { KEY_EN_F5, 0x30 }, - { KEY_EN_7, 0x31 }, - { KEY_EN_Y, 0x22 }, - { KEY_EN_H, 0x23 }, - { KEY_EN_N, 0x34 }, - - { KEY_EN_F6, 0x35 }, - { KEY_EN_8, 0x36 }, - { KEY_EN_U, 0x32 }, - { KEY_EN_J, 0x33 }, - { KEY_EN_M, 0x39 }, - - { KEY_EN_F7, 0x3B }, - { KEY_EN_9, 0x3C }, - { KEY_EN_I, 0x37 }, - { KEY_EN_K, 0x38 }, - { KEY_EN_COMMA, 0x3F }, - - { KEY_EN_F8, 0x41 }, - { KEY_EN_0, 0x42 }, - { KEY_EN_O, 0x3D }, - { KEY_EN_L, 0x3E }, - { KEY_EN_PERIOD, 0x45 }, - { KEY_EN_RIGHT_ALT, 0x46 }, - - { KEY_EN_F9, 0x4E }, - { KEY_EN_MINUS, 0x48 }, - { KEY_EN_P, 0x43 }, - { KEY_EN_SEMICOLON, 0x44 }, - { KEY_EN_FORWARD_SLASH, 0x4B }, - { KEY_EN_RIGHT_FUNCTION, 0x4C }, - - { KEY_EN_F10, 0x54 }, - { KEY_EN_EQUALS, 0x4F }, - { KEY_EN_LEFT_BRACKET, 0x49 }, - { KEY_EN_QUOTE, 0x4A }, - { KEY_EN_MENU, 0x53 }, - - { KEY_EN_F11, 0x55 }, - { KEY_EN_BACKSPACE, 0x57 }, - { KEY_EN_RIGHT_BRACKET, 0x50 }, - { KEY_EN_RIGHT_SHIFT, 0x52 }, - - { KEY_EN_F12, 0x56 }, - { KEY_EN_ANSI_BACK_SLASH, 0x51 }, - { KEY_EN_ANSI_ENTER, 0x58 }, - { KEY_EN_RIGHT_CONTROL, 0x59 }, - - { KEY_EN_PRINT_SCREEN, 0x63 }, - { KEY_EN_INSERT, 0x64 }, - { KEY_EN_DELETE, 0x65 }, - { KEY_EN_LEFT_ARROW, 0x66 }, - - { KEY_EN_SCROLL_LOCK, 0x67 }, - { KEY_EN_HOME, 0x68 }, - { KEY_EN_END, 0x69 }, - { KEY_EN_UP_ARROW, 0x6A }, - { KEY_EN_DOWN_ARROW, 0x6B }, - - { KEY_EN_PAUSE_BREAK, 0x6C }, - { KEY_EN_PAGE_UP, 0x6D }, - { KEY_EN_PAGE_DOWN, 0x6E }, - { KEY_EN_RIGHT_ARROW, 0x6F }, - - { KEY_EN_NUMPAD_LOCK, 0x71 }, - { KEY_EN_NUMPAD_7, 0x72 }, - { KEY_EN_NUMPAD_4, 0x73 }, - { KEY_EN_NUMPAD_1, 0x74 }, - { KEY_EN_NUMPAD_0, 0x75 }, - - { KEY_EN_NUMPAD_DIVIDE, 0x77 }, - { KEY_EN_NUMPAD_8, 0x78 }, - { KEY_EN_NUMPAD_5, 0x79 }, - { KEY_EN_NUMPAD_2, 0x7A }, - - { KEY_EN_NUMPAD_TIMES, 0x7C }, - { KEY_EN_NUMPAD_9, 0x7D }, - { KEY_EN_NUMPAD_6, 0x7E }, - { KEY_EN_NUMPAD_3, 0x7F }, - - { KEY_EN_NUMPAD_PERIOD, 0x80 }, - { KEY_EN_NUMPAD_MINUS, 0x81 }, - { KEY_EN_NUMPAD_PLUS, 0x82 }, - { KEY_EN_NUMPAD_ENTER, 0x83 } - } - } - }, -}; diff --git a/Controllers/RoccatController/RoccatVulcanKeyboardController/RGBController_RoccatVulcanKeyboard.cpp b/Controllers/RoccatController/RoccatVulcanKeyboardController/RGBController_RoccatVulcanKeyboard.cpp new file mode 100644 index 00000000..7c24916a --- /dev/null +++ b/Controllers/RoccatController/RoccatVulcanKeyboardController/RGBController_RoccatVulcanKeyboard.cpp @@ -0,0 +1,233 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatVulcanKeyboard.cpp | +| | +| RGBController for Roccat Vulcan keyboard | +| | +| Mola19 17 Dec 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RGBControllerKeyNames.h" +#include "RGBController_RoccatVulcanKeyboard.h" + +#define NA 0xFFFFFFFF + +/**------------------------------------------------------------------*\ + @name Roccat Vulcan Keyboard + @category Keyboard + @type USB + @save :robot: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectRoccatVulcanKeyboardControllers + @comment The mode "Default" differs from device to device and + and sometimes also based on which profile you are on. + Often it is very close to the rainbow mode. +\*-------------------------------------------------------------------*/ + +RGBController_RoccatVulcanKeyboard::RGBController_RoccatVulcanKeyboard(RoccatVulcanKeyboardController* controller_ptr) +{ + controller = controller_ptr; + + pid = controller->device_pid; + + controller->InitDeviceInfo(); + + name = controller->GetName(); + vendor = "Roccat"; + type = DEVICE_TYPE_KEYBOARD; + description = "Roccat Vulcan Keyboard Device"; + version = controller->GetDeviceInfo().version; + location = controller->GetLocation(); + serial = controller->GetSerial(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = ROCCAT_VULCAN_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + + if(pid != ROCCAT_VULCAN_120_AIMO_PID && pid != ROCCAT_VULCAN_100_AIMO_PID) + { + Direct.flags |= MODE_FLAG_HAS_BRIGHTNESS; + Direct.brightness_min = ROCCAT_VULCAN_BRIGHTNESS_MIN; + Direct.brightness_max = ROCCAT_VULCAN_BRIGHTNESS_MAX; + Direct.brightness = ROCCAT_VULCAN_BRIGHTNESS_DEFAULT; + } + + modes.push_back(Direct); + + mode Static; + Static.name = "Static"; + Static.value = ROCCAT_VULCAN_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Static.brightness_min = ROCCAT_VULCAN_BRIGHTNESS_MIN; + Static.brightness_max = ROCCAT_VULCAN_BRIGHTNESS_MAX; + Static.brightness = ROCCAT_VULCAN_BRIGHTNESS_DEFAULT; + Static.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Static); + + mode Wave; + Wave.name = "Rainbow Wave"; + Wave.value = ROCCAT_VULCAN_MODE_WAVE; + Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Wave.speed_min = ROCCAT_VULCAN_SPEED_MIN; + Wave.speed_max = ROCCAT_VULCAN_SPEED_MAX; + Wave.speed = ROCCAT_VULCAN_SPEED_DEFAULT; + Wave.brightness_min = ROCCAT_VULCAN_BRIGHTNESS_MIN; + Wave.brightness_max = ROCCAT_VULCAN_BRIGHTNESS_MAX; + Wave.brightness = ROCCAT_VULCAN_BRIGHTNESS_DEFAULT; + Wave.color_mode = MODE_COLORS_NONE; + modes.push_back(Wave); + + mode Default; + Default.name = "Default"; + Default.value = ROCCAT_VULCAN_MODE_DEFAULT; + Default.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Default.brightness_min = ROCCAT_VULCAN_BRIGHTNESS_MIN; + Default.brightness_max = ROCCAT_VULCAN_BRIGHTNESS_MAX; + Default.brightness = ROCCAT_VULCAN_BRIGHTNESS_DEFAULT; + Default.color_mode = MODE_COLORS_NONE; + modes.push_back(Default); + + SetupZones(); +} + +RGBController_RoccatVulcanKeyboard::~RGBController_RoccatVulcanKeyboard() +{ + delete controller; +} + +void RGBController_RoccatVulcanKeyboard::SetupZones() +{ + std::map * keyboard_ptr; + + switch(pid) + { + case ROCCAT_VULCAN_100_AIMO_PID: + case ROCCAT_VULCAN_120_AIMO_PID: + keyboard_ptr = &RoccatVulcan120AimoLayouts; + break; + case ROCCAT_VULCAN_TKL_PID: + case TURTLE_BEACH_VULCAN_II_TKL_PID: + keyboard_ptr = &RoccatVulcanTKLLayouts; + break; + case ROCCAT_VULCAN_PRO_PID: + case ROCCAT_PYRO_PID: + keyboard_ptr = &RoccatPyroLayouts; + break; + case ROCCAT_VULCAN_II_PID: + case TURTLE_BEACH_VULCAN_II_PID: + keyboard_ptr = &RoccatVulcanIILayouts; + break; + case ROCCAT_MAGMA_PID: + case ROCCAT_MAGMA_MINI_PID: + keyboard_ptr = &RoccatMagmaLayouts; + break; + default: + keyboard_ptr = &RoccatVulcan120AimoLayouts; + } + + std::map & keyboard = *keyboard_ptr; + + unsigned char layout; + + switch(controller->GetDeviceInfo().layout_type) + { + case ROCCAT_VULCAN_LAYOUT_DE: + case ROCCAT_VULCAN_LAYOUT_UK: + case ROCCAT_VULCAN_LAYOUT_FR: + layout = ROCCAT_VULCAN_LAYOUT_UK; + break; + case ROCCAT_VULCAN_LAYOUT_US: + default: + layout = ROCCAT_VULCAN_LAYOUT_US; + } + + + zone keyboard_zone; + keyboard_zone.name = "Keyboard"; + keyboard_zone.type = ZONE_TYPE_MATRIX; + keyboard_zone.leds_min = keyboard[layout].size; + keyboard_zone.leds_max = keyboard[layout].size; + keyboard_zone.leds_count = keyboard[layout].size; + keyboard_zone.matrix_map = new matrix_map_type; + keyboard_zone.matrix_map->height = keyboard[layout].rows; + keyboard_zone.matrix_map->width = keyboard[layout].cols; + keyboard_zone.matrix_map->map = keyboard[layout].matrix_map; + zones.push_back(keyboard_zone); + + for(int led_id = 0; led_id < keyboard[layout].size; led_id++) + { + led new_led; + new_led.name = keyboard[layout].led_names[led_id].name; + new_led.value = keyboard[layout].led_names[led_id].id; + leds.push_back(new_led); + } + + SetupColors(); + + /*---------------------------------------------------------*\ + | sends the init packet for the default mode (direct) | + \*---------------------------------------------------------*/ + DeviceUpdateMode(); + DeviceUpdateLEDs(); +} + +void RGBController_RoccatVulcanKeyboard::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_RoccatVulcanKeyboard::DeviceUpdateLEDs() +{ + if (modes[active_mode].value == ROCCAT_VULCAN_MODE_DIRECT) + { + std::vector led_color_list = {}; + + for(unsigned int i = 0; i < colors.size(); i++) + { + led_color_list.push_back({ leds[i].value, colors[i] }); + } + + controller->SendColors(led_color_list); + } + else + { + DeviceUpdateMode(); + } +} + +void RGBController_RoccatVulcanKeyboard::UpdateZoneLEDs(int /*zone_idx*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RoccatVulcanKeyboard::UpdateSingleLED(int /*led_idx*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_RoccatVulcanKeyboard::DeviceUpdateMode() +{ + std::vector led_color_list = {}; + + if(modes[active_mode].value == ROCCAT_VULCAN_MODE_STATIC) + { + for(unsigned int i = 0; i < colors.size(); i++) + { + led_color_list.push_back({ leds[i].value, colors[i] }); + } + } + + controller->SendMode(modes[active_mode].value, modes[active_mode].speed, modes[active_mode].brightness, led_color_list); + controller->WaitUntilReady(); + + controller->EnableDirect(modes[active_mode].value != ROCCAT_VULCAN_MODE_DEFAULT); + controller->WaitUntilReady(); +} diff --git a/Controllers/RoccatController/RoccatVulcanKeyboardController/RGBController_RoccatVulcanKeyboard.h b/Controllers/RoccatController/RoccatVulcanKeyboardController/RGBController_RoccatVulcanKeyboard.h new file mode 100644 index 00000000..83312ffe --- /dev/null +++ b/Controllers/RoccatController/RoccatVulcanKeyboardController/RGBController_RoccatVulcanKeyboard.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_RoccatVulcanKeyboard.h | +| | +| RGBController for Roccat Vulcan keyboard | +| | +| Mola19 17 Dec 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "RoccatVulcanKeyboardController.h" + +class RGBController_RoccatVulcanKeyboard : public RGBController +{ +public: + RGBController_RoccatVulcanKeyboard(RoccatVulcanKeyboardController* controller_ptr); + ~RGBController_RoccatVulcanKeyboard(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + RoccatVulcanKeyboardController* controller; + uint16_t pid; +}; diff --git a/Controllers/RoccatController/RoccatVulcanKeyboardController/RoccatVulcanKeyboardController.cpp b/Controllers/RoccatController/RoccatVulcanKeyboardController/RoccatVulcanKeyboardController.cpp new file mode 100644 index 00000000..672b74c0 --- /dev/null +++ b/Controllers/RoccatController/RoccatVulcanKeyboardController/RoccatVulcanKeyboardController.cpp @@ -0,0 +1,421 @@ +/*---------------------------------------------------------*\ +| RoccatVulcanKeyboardController.cpp | +| | +| Driver for Roccat Vulcan keyboard | +| | +| Mola19 17 Dec 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include "LogManager.h" +#include "RoccatVulcanKeyboardController.h" +#include "StringUtils.h" + +RoccatVulcanKeyboardController::RoccatVulcanKeyboardController(hid_device* dev_ctrl_handle, hid_device* dev_led_handle, char *path, uint16_t pid, std::string dev_name) +{ + dev_ctrl = dev_ctrl_handle; + dev_led = dev_led_handle; + location = path; + name = dev_name; + device_pid = pid; +} + +RoccatVulcanKeyboardController::~RoccatVulcanKeyboardController() +{ + hid_close(dev_ctrl); + hid_close(dev_led); +} + +std::string RoccatVulcanKeyboardController::GetLocation() +{ + return("HID: " + location); +} + +std::string RoccatVulcanKeyboardController::GetName() +{ + return(name); +} + +std::string RoccatVulcanKeyboardController::GetSerial() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev_ctrl, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +device_info RoccatVulcanKeyboardController::InitDeviceInfo() +{ + uint8_t packet_length; + uint8_t report_id; + + switch(device_pid) + { + case ROCCAT_PYRO_PID: + case ROCCAT_MAGMA_PID: + case ROCCAT_MAGMA_MINI_PID: + case ROCCAT_VULCAN_PRO_PID: + case ROCCAT_VULCAN_II_PID: + case TURTLE_BEACH_VULCAN_II_PID: + packet_length = 9; + report_id = 0x09; + break; + default: + packet_length = 8; + report_id = 0x0F; + } + + uint8_t* buf = new uint8_t[packet_length]; + memset(buf, 0x00, packet_length); + + buf[0] = report_id; + hid_get_feature_report(dev_ctrl, buf, packet_length); + + char version[5]; + snprintf(version, 5, "%d.%02d", buf[2] / 100, buf[2] % 100); + + dev_info.version = version; + + if(device_pid == ROCCAT_MAGMA_PID || device_pid == ROCCAT_MAGMA_MINI_PID) + { + /*---------------------------------------------------------*\ + | This device doesn't need a layout, | + | because it doesn't have per-led lighting. | + | Taking us layout as placeholder instead | + \*---------------------------------------------------------*/ + dev_info.layout_type = ROCCAT_VULCAN_LAYOUT_US; + } + else + { + dev_info.layout_type = buf[6]; + } + + LOG_DEBUG("[Roccat Vulcan Keyboard]: Detected layout '0x%02X'", buf[6]); + + delete[] buf; + return dev_info; +} + +device_info RoccatVulcanKeyboardController::GetDeviceInfo() +{ + return dev_info; +} + +void RoccatVulcanKeyboardController::EnableDirect(bool on_off_switch) +{ + uint8_t* buf; + switch(device_pid) + { + case ROCCAT_PYRO_PID: + case ROCCAT_MAGMA_PID: + case ROCCAT_MAGMA_MINI_PID: + case ROCCAT_VULCAN_PRO_PID: + case ROCCAT_VULCAN_II_PID: + case TURTLE_BEACH_VULCAN_II_PID: + buf = new uint8_t[5] { 0x0E, 0x05, on_off_switch, 0x00, 0x00 }; + hid_send_feature_report(dev_ctrl, buf, 5); + break; + default: + buf = new uint8_t[3] { 0x15, 0x00, on_off_switch }; + hid_send_feature_report(dev_ctrl, buf, 3); + } + delete[] buf; +} + +void RoccatVulcanKeyboardController::SendColors(std::vector colors) +{ + unsigned short packet_length; + unsigned char column_length; + unsigned char protocol_version; + + switch(device_pid) + { + case ROCCAT_MAGMA_PID: + case ROCCAT_MAGMA_MINI_PID: + packet_length = 64; + column_length = 5; + protocol_version = 2; + break; + case ROCCAT_PYRO_PID: + packet_length = 378; + column_length = 1; + protocol_version = 2; + break; + case ROCCAT_VULCAN_PRO_PID: + packet_length = 384; + column_length = 12; + protocol_version = 2; + break; + case ROCCAT_VULCAN_II_PID: + case TURTLE_BEACH_VULCAN_II_PID: + packet_length = 396; + column_length = 1; + protocol_version = 2; + break; + default: + packet_length = 436; + column_length = 12; + protocol_version = 1; + } + + unsigned char packet_num = (unsigned char)(ceil((float)packet_length / 64)); + + std::vector> bufs(packet_num); + + for(int p = 0; p < packet_num; p++) + { + bufs[p].resize(65); + memset(&bufs[p][0], 0x00, sizeof(bufs[p][0]) * bufs[p].size()); + } + + if(protocol_version > 1) + { + for(unsigned int i = 0; i < packet_num; i++) + { + bufs[i][1] = 0xA1; + bufs[i][2] = i + 1; + } + } + else + { + bufs[0][1] = 0xA1; + bufs[0][2] = 0x01; + } + + unsigned char header_length_first = (packet_length > 255) ? 4 : 3; + + if(header_length_first == 3) + { + bufs[0][3] = (uint8_t)packet_length; + } + else + { + if(protocol_version > 1) + { + bufs[0][3] = packet_length % 256; + bufs[0][4] = packet_length / 256; + } + else + { + bufs[0][3] = packet_length / 256; + bufs[0][4] = packet_length % 256; + } + } + + for(unsigned int i = 0; i < colors.size(); i++) + { + int column = (int)(floor(colors[i].value / column_length)); + int row = colors[i].value % column_length; + + /*-----------------------------------------------------------------------*\ + | This has to be split up for readability. | + | This assumes that the header for each packet besides the first | + | is either 0 bytes long (protocol v1) or as long as the first one (v2). | + | This currently covers all keyboards. | + | A solution unified solution that can handle general header length | + | independent of the first header would be desirable, but seems | + | too complicated for now. | + \*-----------------------------------------------------------------------*/ + if(protocol_version == 1) + { + int offset = column * 3 * column_length + row + header_length_first; + + bufs[offset / 64][offset % 64 + 1] = RGBGetRValue(colors[i].color); + + offset += column_length; + bufs[offset / 64][offset % 64 + 1] = RGBGetGValue(colors[i].color); + + offset += column_length; + bufs[offset / 64][offset % 64 + 1] = RGBGetBValue(colors[i].color); + } + else + { + unsigned int data_length_packet = 64 - header_length_first; + + int offset = column * 3 * column_length + row; + + bufs[offset / data_length_packet][offset % data_length_packet + header_length_first + 1] = RGBGetRValue(colors[i].color); + + offset += column_length; + bufs[offset / data_length_packet][offset % data_length_packet + header_length_first + 1] = RGBGetGValue(colors[i].color); + + offset += column_length; + bufs[offset / data_length_packet][offset % data_length_packet + header_length_first + 1] = RGBGetBValue(colors[i].color); + } + } + + for(int p = 0; p < packet_num; p++) + { + hid_write(dev_led, &bufs[p][0], 65); + } + + ClearResponses(); + AwaitResponse(20); +} + +void RoccatVulcanKeyboardController::SendMode(unsigned int mode, unsigned int speed, unsigned int brightness, std::vector colors) +{ + if(speed == 0) speed = ROCCAT_VULCAN_SPEED_DEFAULT; + if(brightness == 0) brightness = ROCCAT_VULCAN_BRIGHTNESS_DEFAULT; + + unsigned short packet_length; + unsigned char protocol_version; + unsigned char column_length; + + switch(device_pid) + { + case ROCCAT_PYRO_PID: + protocol_version = 2; + packet_length = 365; + column_length = 1; + break; + case ROCCAT_MAGMA_PID: + case ROCCAT_MAGMA_MINI_PID: + protocol_version = 2; + packet_length = 26; + column_length = 5; + break; + case ROCCAT_VULCAN_PRO_PID: + protocol_version = 2; + packet_length = 371; + column_length = 12; + break; + case ROCCAT_VULCAN_II_PID: + case TURTLE_BEACH_VULCAN_II_PID: + protocol_version = 2; + packet_length = 377; + column_length = 1; + break; + default: + protocol_version = 1; + packet_length = 443; + column_length = 12; + } + + + uint8_t* buf = new uint8_t[packet_length]; + memset(buf, 0x00, packet_length); + + unsigned char header_length = (packet_length > 255) ? 2 : 1; + + buf[0] = (protocol_version == 1) ? 0x0D : 0x11; + + if(header_length == 1) + { + buf[1] = (uint8_t)packet_length; + } + else + { + buf[1] = packet_length % 256; + buf[2] = packet_length / 256; + } + + unsigned char offset = header_length + 1; + + buf[0 + offset] = 0x00; + buf[1 + offset] = mode; + buf[2 + offset] = speed; + + if(protocol_version == 1) + { + buf[3 + offset] = 0x00; + buf[4 + offset] = brightness; + buf[5 + offset] = 0x00; + } + else + { + buf[3 + offset] = brightness; + buf[4 + offset] = 0x00; + buf[5 + offset] = 0x00; + } + + + for(unsigned int i = 0; i < colors.size(); i++) + { + int column = (int)(floor(colors[i].value / column_length)); + int row = colors[i].value % column_length; + + int offset = column * 3 * column_length + row + 9; + + buf[offset] = RGBGetRValue(colors[i].color); + + offset += column_length; + + buf[offset] = RGBGetGValue(colors[i].color); + + offset += column_length; + + buf[offset] = RGBGetBValue(colors[i].color); + } + + unsigned short total = 0; + for(int i = 0; i < packet_length - 2; i++) total += buf[i]; + + buf[packet_length - 2] = total & 0xFF; + buf[packet_length - 1] = total >> 8; + + hid_send_feature_report(dev_ctrl, buf, packet_length); + + delete[] buf; +} + +void RoccatVulcanKeyboardController::WaitUntilReady() +{ + unsigned short packet_length; + + switch(device_pid) + { + case ROCCAT_PYRO_PID: + case ROCCAT_MAGMA_PID: + case ROCCAT_MAGMA_MINI_PID: + case ROCCAT_VULCAN_PRO_PID: + packet_length = 4; + break; + default: + packet_length = 3; + } + + uint8_t* buf = new uint8_t[packet_length]; + + buf[0] = 0x04; + + for(unsigned char i = 0; buf[1] != 1 && i < 100; i++) + { + if(i != 0) + { + std::this_thread::sleep_for(std::chrono::milliseconds(25)); + } + + hid_get_feature_report(dev_ctrl, buf, packet_length); + } + + delete[] buf; +} + +void RoccatVulcanKeyboardController::AwaitResponse(int ms) +{ + unsigned char usb_buf_out[65]; + hid_read_timeout(dev_led, usb_buf_out, 65, ms); +} + +void RoccatVulcanKeyboardController::ClearResponses() +{ + int result = 1; + unsigned char usb_buf_flush[65]; + while(result > 0) + { + result = hid_read_timeout(dev_led, usb_buf_flush, 65, 0); + } +} diff --git a/Controllers/RoccatController/RoccatVulcanKeyboardController/RoccatVulcanKeyboardController.h b/Controllers/RoccatController/RoccatVulcanKeyboardController/RoccatVulcanKeyboardController.h new file mode 100644 index 00000000..3ed548dc --- /dev/null +++ b/Controllers/RoccatController/RoccatVulcanKeyboardController/RoccatVulcanKeyboardController.h @@ -0,0 +1,97 @@ +/*---------------------------------------------------------*\ +| RoccatVulcanKeyboardController.h | +| | +| Driver for Roccat Vulcan keyboard | +| | +| Mola19 17 Dec 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" +#include "RoccatVulcanKeyboardLayouts.h" + +/*--------------------------------------------------------------------------------*\ +| KEYBOARDS | +| This section was used to be enum. | +\*--------------------------------------------------------------------------------*/ +#define ROCCAT_VULCAN_100_AIMO_PID 0x307A +#define ROCCAT_VULCAN_120_AIMO_PID 0x3098 +#define ROCCAT_VULCAN_TKL_PID 0x2FEE +#define ROCCAT_VULCAN_PRO_PID 0x30F7 +#define ROCCAT_VULCAN_II_PID 0x2F4E +#define ROCCAT_PYRO_PID 0x314C +#define ROCCAT_MAGMA_PID 0x3124 +#define ROCCAT_MAGMA_MINI_PID 0x69A0 +#define TURTLE_BEACH_VULCAN_II_PID 0x501B +#define TURTLE_BEACH_VULCAN_II_TKL_PID 0x5023 + +enum +{ + ROCCAT_VULCAN_MODE_DIRECT = 0x0B, + ROCCAT_VULCAN_MODE_STATIC = 0x01, + ROCCAT_VULCAN_MODE_WAVE = 0x0A, + /*-------------------------------------------------------------------*\ + | This mode is not a real mode, it's just the default mode when | + | a mode is software generated, but Swarm is inactive, hence it has | + | no id. Unfortunately 0 is refused by some keyboards, so 2 seems | + | like a good choice as it is not used anywhere else | + \*-------------------------------------------------------------------*/ + ROCCAT_VULCAN_MODE_DEFAULT = 0x02, +}; + +enum +{ + ROCCAT_VULCAN_SPEED_MIN = 0x01, + ROCCAT_VULCAN_SPEED_MAX = 0x0B, + ROCCAT_VULCAN_SPEED_DEFAULT = 0x06, + ROCCAT_VULCAN_BRIGHTNESS_MIN = 0x01, + ROCCAT_VULCAN_BRIGHTNESS_MAX = 0x45, + ROCCAT_VULCAN_BRIGHTNESS_DEFAULT = 0x45, +}; + +struct device_info +{ + std::string version; + int layout_type; +}; + +struct led_color +{ + unsigned int value; + RGBColor color; +}; + +class RoccatVulcanKeyboardController +{ +public: + RoccatVulcanKeyboardController(hid_device* dev_ctrl_handle, hid_device* dev_led_handle, char *path, uint16_t pid, std::string dev_name); + ~RoccatVulcanKeyboardController(); + + std::string GetSerial(); + std::string GetLocation(); + std::string GetName(); + device_info InitDeviceInfo(); + device_info GetDeviceInfo(); + + void EnableDirect(bool on_off_switch); + void SendColors(std::vector colors); + void SendMode(unsigned int mode, unsigned int speed, unsigned int brightness, std::vector colors); + void WaitUntilReady(); + void AwaitResponse(int ms); + void ClearResponses(); + + uint16_t device_pid; + +private: + hid_device* dev_ctrl; + hid_device* dev_led; + device_info dev_info; + std::string location; + std::string name; +}; diff --git a/Controllers/RoccatController/RoccatVulcanKeyboardController/RoccatVulcanKeyboardLayouts.h b/Controllers/RoccatController/RoccatVulcanKeyboardController/RoccatVulcanKeyboardLayouts.h new file mode 100644 index 00000000..916640d7 --- /dev/null +++ b/Controllers/RoccatController/RoccatVulcanKeyboardController/RoccatVulcanKeyboardLayouts.h @@ -0,0 +1,1047 @@ +/*---------------------------------------------------------*\ +| RoccatVulcanKeyboardLayouts.h | +| | +| Layouts for Roccat Vulcan keyboard | +| | +| Mola19 29 Sep 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBControllerKeyNames.h" +#include "RGBController.h" + +enum +{ + ROCCAT_VULCAN_LAYOUT_US = 0, + ROCCAT_VULCAN_LAYOUT_DE = 1, + ROCCAT_VULCAN_LAYOUT_UK = 2, + ROCCAT_VULCAN_LAYOUT_FR = 3, +}; + +#define NA 0xFFFFFFFF + +struct led_value +{ + const char* name; + unsigned char id; +}; + +struct layout_info +{ + unsigned int* matrix_map; + int size; + int rows; + int cols; + std::vector led_names; +}; + +static unsigned int ROCCAT_VULCAN_120_AIMO_LAYOUT_KEYS_104[6][24] = +{ + { 0, NA, 8, 14, 19, 24, NA, 34, 39, 44, 49, 55, 61, 66, 70, NA, 74, 78, 83, NA, NA, NA, NA, NA }, + { 1, 6, 9, 15, 20, 25, 29, 35, 40, 45, 50, 56, 62, 67, NA, NA, 75, 79, 84, NA, 87, 92, 96, 101 }, + { 2, NA, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, 71, NA, 76, 80, 85, NA, 88, 93, 97, 102 }, + { 3, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, NA, 72, NA, NA, NA, NA, NA, 89, 94, 98, NA }, + { 4, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, NA, 69, NA, NA, NA, 81, NA, NA, 90, 95, 99, 103 }, + { 5, 7, 13, NA, NA, NA, 33, NA, NA, NA, 54, 60, 65, NA, 73, NA, 77, 82, 86, NA, 91, NA, 100, NA } +}; + +static unsigned int ROCCAT_VULCAN_120_AIMO_LAYOUT_KEYS_105[6][24] = +{ + { 0, NA, 9, 15, 20, 25, NA, 35, 40, 45, 50, 56, 62, 67, 72, NA, 75, 79, 84, NA, NA, NA, NA, NA }, + { 1, 6, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, NA, NA, 76, 80, 85, NA, 88, 93, 97, 102 }, + { 2, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, 69, NA, NA, 77, 81, 86, NA, 89, 94, 98, 103 }, + { 3, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, 65, 70, 73, NA, NA, NA, NA, NA, 90, 95, 99, NA }, + { 4, 7, 13, 19, 24, 29, 33, 39, 44, 49, 54, 60, NA, 71, NA, NA, NA, 82, NA, NA, 91, 96, 100, 104 }, + { 5, 8, 14, NA, NA, NA, 34, NA, NA, NA, 55, 61, 66, NA, 74, NA, 78, 83, 87, NA, 92, NA, 101, NA } +}; + +static unsigned int ROCCAT_VULCAN_II_LAYOUT_KEYS_105[6][24] = +{ + { 0, NA, 9, 15, 20, 25, NA, 35, 40, 45, 50, 56, 62, 67, 72, NA, 75, 79, 84, NA, 105, 106, 107, NA }, + { 1, 6, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, NA, NA, 76, 80, 85, NA, 88, 93, 97, 102 }, + { 2, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, 69, NA, NA, 77, 81, 86, NA, 89, 94, 98, 103 }, + { 3, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, 65, 70, 73, NA, NA, NA, NA, NA, 90, 95, 99, NA }, + { 4, 7, 13, 19, 24, 29, 33, 39, 44, 49, 54, 60, NA, 71, NA, NA, NA, 82, NA, NA, 91, 96, 100, 104 }, + { 5, 8, 14, NA, NA, NA, 34, NA, NA, NA, 55, 61, 66, NA, 74, NA, 78, 83, 87, NA, 92, NA, 101, NA } +}; + +static unsigned int ROCCAT_VULCAN_TKL_LAYOUT_KEYS_104[6][19] = +{ + { 0, NA, 8, 14, 19, 24, NA, 34, 39, 44, 49, 55, 61, 66, 70, NA, 74, NA, NA }, + { 1, 6, 9, 15, 20, 25, 29, 35, 40, 45, 50, 56, 62, 67, NA, NA, 75, 78, 82 }, + { 2, NA, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, 71, NA, 76, 79, 83 }, + { 3, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, NA, 72, NA, NA, NA, NA }, + { 4, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, NA, 69, NA, NA, NA, 80, NA }, + { 5, 7, 13, NA, NA, NA, 33, NA, NA, NA, 54, 60, 65, NA, 73, NA, 77, 81, 84 } +}; + +static unsigned int ROCCAT_VULCAN_TKL_LAYOUT_KEYS_105[6][19] = +{ + { 0, NA, 9, 15, 20, 25, NA, 35, 40, 45, 50, 56, 62, 67, 72, NA, 75, NA, NA }, + { 1, 6, 10, 16, 21, 26, 30, 36, 41, 46, 51, 57, 63, 68, NA, NA, 76, 79, 83 }, + { 2, NA, 11, 17, 22, 27, 31, 37, 42, 47, 52, 58, 64, 69, NA, NA, 77, 80, 84 }, + { 3, NA, 12, 18, 23, 28, 32, 38, 43, 48, 53, 59, 65, 70, 73, NA, NA, NA, NA }, + { 4, 7, 13, 19, 24, 29, 33, 39, 44, 49, 54, 60, NA, 71, NA, NA, NA, 81, NA }, + { 5, 8, 14, NA, NA, NA, 34, NA, NA, NA, 55, 61, 66, NA, 74, NA, 78, 82, 85 } +}; + +static unsigned int ROCCAT_MAGMA_LAYOUT_KEYS[1][5] = +{ + { 0, 1, 2, 3, 4 }, +}; + +static std::map RoccatVulcan120AimoLayouts = +{ + { + ROCCAT_VULCAN_LAYOUT_UK, + { + *ROCCAT_VULCAN_120_AIMO_LAYOUT_KEYS_105, + 105, + 6, + 24, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_1, 0x06 }, + { KEY_EN_ISO_BACK_SLASH, 0x09 }, + { KEY_EN_LEFT_WINDOWS, 0x0A }, + + { KEY_EN_F1, 0x0B }, + { KEY_EN_2, 0x0C }, + { KEY_EN_Q, 0x07 }, + { KEY_EN_A, 0x08 }, + { KEY_EN_Z, 0x0F }, + { KEY_EN_LEFT_ALT, 0x10 }, + + { KEY_EN_F2, 0x11 }, + { KEY_EN_3, 0x12 }, + { KEY_EN_W, 0x0D }, + { KEY_EN_S, 0x0E }, + { KEY_EN_X, 0x15 }, + + { KEY_EN_F3, 0x17 }, + { KEY_EN_4, 0x18 }, + { KEY_EN_E, 0x13 }, + { KEY_EN_D, 0x14 }, + { KEY_EN_C, 0x1B }, + + { KEY_EN_F4, 0x1C }, + { KEY_EN_5, 0x1D }, + { KEY_EN_R, 0x19 }, + { KEY_EN_F, 0x1A }, + { KEY_EN_V, 0x20 }, + + { KEY_EN_6, 0x21 }, + { KEY_EN_T, 0x1E }, + { KEY_EN_G, 0x1F }, + { KEY_EN_B, 0x24 }, + { KEY_EN_SPACE, 0x25 }, + + { KEY_EN_F5, 0x30 }, + { KEY_EN_7, 0x31 }, + { KEY_EN_Y, 0x22 }, + { KEY_EN_H, 0x23 }, + { KEY_EN_N, 0x34 }, + + { KEY_EN_F6, 0x35 }, + { KEY_EN_8, 0x36 }, + { KEY_EN_U, 0x32 }, + { KEY_EN_J, 0x33 }, + { KEY_EN_M, 0x39 }, + + { KEY_EN_F7, 0x3B }, + { KEY_EN_9, 0x3C }, + { KEY_EN_I, 0x37 }, + { KEY_EN_K, 0x38 }, + { KEY_EN_COMMA, 0x3F }, + + { KEY_EN_F8, 0x41 }, + { KEY_EN_0, 0x42 }, + { KEY_EN_O, 0x3D }, + { KEY_EN_L, 0x3E }, + { KEY_EN_PERIOD, 0x45 }, + { KEY_EN_RIGHT_ALT, 0x46 }, + + { KEY_EN_F9, 0x4E }, + { KEY_EN_MINUS, 0x48 }, + { KEY_EN_P, 0x43 }, + { KEY_EN_SEMICOLON, 0x44 }, + { KEY_EN_FORWARD_SLASH, 0x4B }, + { KEY_EN_RIGHT_FUNCTION, 0x4C }, + + { KEY_EN_F10, 0x54 }, + { KEY_EN_EQUALS, 0x4F }, + { KEY_EN_LEFT_BRACKET, 0x49 }, + { KEY_EN_QUOTE, 0x4A }, + { KEY_EN_MENU, 0x53 }, + + { KEY_EN_F11, 0x55 }, + { KEY_EN_BACKSPACE, 0x57 }, + { KEY_EN_RIGHT_BRACKET, 0x50 }, + { KEY_EN_POUND, 0x60 }, + { KEY_EN_RIGHT_SHIFT, 0x52 }, + + { KEY_EN_F12, 0x56 }, + { KEY_EN_ISO_ENTER, 0x58 }, + { KEY_EN_RIGHT_CONTROL, 0x59 }, + + { KEY_EN_PRINT_SCREEN, 0x63 }, + { KEY_EN_INSERT, 0x64 }, + { KEY_EN_DELETE, 0x65 }, + { KEY_EN_LEFT_ARROW, 0x66 }, + + { KEY_EN_SCROLL_LOCK, 0x67 }, + { KEY_EN_HOME, 0x68 }, + { KEY_EN_END, 0x69 }, + { KEY_EN_UP_ARROW, 0x6A }, + { KEY_EN_DOWN_ARROW, 0x6B }, + + { KEY_EN_PAUSE_BREAK, 0x6C }, + { KEY_EN_PAGE_UP, 0x6D }, + { KEY_EN_PAGE_DOWN, 0x6E }, + { KEY_EN_RIGHT_ARROW, 0x6F }, + + { KEY_EN_NUMPAD_LOCK, 0x71 }, + { KEY_EN_NUMPAD_7, 0x72 }, + { KEY_EN_NUMPAD_4, 0x73 }, + { KEY_EN_NUMPAD_1, 0x74 }, + { KEY_EN_NUMPAD_0, 0x75 }, + + { KEY_EN_NUMPAD_DIVIDE, 0x77 }, + { KEY_EN_NUMPAD_8, 0x78 }, + { KEY_EN_NUMPAD_5, 0x79 }, + { KEY_EN_NUMPAD_2, 0x7A }, + + { KEY_EN_NUMPAD_TIMES, 0x7C }, + { KEY_EN_NUMPAD_9, 0x7D }, + { KEY_EN_NUMPAD_6, 0x7E }, + { KEY_EN_NUMPAD_3, 0x7F }, + + { KEY_EN_NUMPAD_PERIOD, 0x80 }, + { KEY_EN_NUMPAD_MINUS, 0x81 }, + { KEY_EN_NUMPAD_PLUS, 0x82 }, + { KEY_EN_NUMPAD_ENTER, 0x83 } + } + } + }, + { + ROCCAT_VULCAN_LAYOUT_US, + { + *ROCCAT_VULCAN_120_AIMO_LAYOUT_KEYS_104, + 104, + 6, + 24, + { + { KEY_EN_ESCAPE, 0x00 }, + { KEY_EN_BACK_TICK, 0x01 }, + { KEY_EN_TAB, 0x02 }, + { KEY_EN_CAPS_LOCK, 0x03 }, + { KEY_EN_LEFT_SHIFT, 0x04 }, + { KEY_EN_LEFT_CONTROL, 0x05 }, + + { KEY_EN_1, 0x06 }, + { KEY_EN_LEFT_WINDOWS, 0x0A }, + + { KEY_EN_F1, 0x0B }, + { KEY_EN_2, 0x0C }, + { KEY_EN_Q, 0x07 }, + { KEY_EN_A, 0x08 }, + { KEY_EN_Z, 0x0F }, + { KEY_EN_LEFT_ALT, 0x10 }, + + { KEY_EN_F2, 0x11 }, + { KEY_EN_3, 0x12 }, + { KEY_EN_W, 0x0D }, + { KEY_EN_S, 0x0E }, + { KEY_EN_X, 0x15 }, + + { KEY_EN_F3, 0x17 }, + { KEY_EN_4, 0x18 }, + { KEY_EN_E, 0x13 }, + { KEY_EN_D, 0x14 }, + { KEY_EN_C, 0x1B }, + + { KEY_EN_F4, 0x1C }, + { KEY_EN_5, 0x1D }, + { KEY_EN_R, 0x19 }, + { KEY_EN_F, 0x1A }, + { KEY_EN_V, 0x20 }, + + { KEY_EN_6, 0x21 }, + { KEY_EN_T, 0x1E }, + { KEY_EN_G, 0x1F }, + { KEY_EN_B, 0x24 }, + { KEY_EN_SPACE, 0x25 }, + + { KEY_EN_F5, 0x30 }, + { KEY_EN_7, 0x31 }, + { KEY_EN_Y, 0x22 }, + { KEY_EN_H, 0x23 }, + { KEY_EN_N, 0x34 }, + + { KEY_EN_F6, 0x35 }, + { KEY_EN_8, 0x36 }, + { KEY_EN_U, 0x32 }, + { KEY_EN_J, 0x33 }, + { KEY_EN_M, 0x39 }, + + { KEY_EN_F7, 0x3B }, + { KEY_EN_9, 0x3C }, + { KEY_EN_I, 0x37 }, + { KEY_EN_K, 0x38 }, + { KEY_EN_COMMA, 0x3F }, + + { KEY_EN_F8, 0x41 }, + { KEY_EN_0, 0x42 }, + { KEY_EN_O, 0x3D }, + { KEY_EN_L, 0x3E }, + { KEY_EN_PERIOD, 0x45 }, + { KEY_EN_RIGHT_ALT, 0x46 }, + + { KEY_EN_F9, 0x4E }, + { KEY_EN_MINUS, 0x48 }, + { KEY_EN_P, 0x43 }, + { KEY_EN_SEMICOLON, 0x44 }, + { KEY_EN_FORWARD_SLASH, 0x4B }, + { KEY_EN_RIGHT_FUNCTION, 0x4C }, + + { KEY_EN_F10, 0x54 }, + { KEY_EN_EQUALS, 0x4F }, + { KEY_EN_LEFT_BRACKET, 0x49 }, + { KEY_EN_QUOTE, 0x4A }, + { KEY_EN_MENU, 0x53 }, + + { KEY_EN_F11, 0x55 }, + { KEY_EN_BACKSPACE, 0x57 }, + { KEY_EN_RIGHT_BRACKET, 0x50 }, + { KEY_EN_RIGHT_SHIFT, 0x52 }, + + { KEY_EN_F12, 0x56 }, + { KEY_EN_ANSI_BACK_SLASH, 0x51 }, + { KEY_EN_ANSI_ENTER, 0x58 }, + { KEY_EN_RIGHT_CONTROL, 0x59 }, + + { KEY_EN_PRINT_SCREEN, 0x63 }, + { KEY_EN_INSERT, 0x64 }, + { KEY_EN_DELETE, 0x65 }, + { KEY_EN_LEFT_ARROW, 0x66 }, + + { KEY_EN_SCROLL_LOCK, 0x67 }, + { KEY_EN_HOME, 0x68 }, + { KEY_EN_END, 0x69 }, + { KEY_EN_UP_ARROW, 0x6A }, + { KEY_EN_DOWN_ARROW, 0x6B }, + + { KEY_EN_PAUSE_BREAK, 0x6C }, + { KEY_EN_PAGE_UP, 0x6D }, + { KEY_EN_PAGE_DOWN, 0x6E }, + { KEY_EN_RIGHT_ARROW, 0x6F }, + + { KEY_EN_NUMPAD_LOCK, 0x71 }, + { KEY_EN_NUMPAD_7, 0x72 }, + { KEY_EN_NUMPAD_4, 0x73 }, + { KEY_EN_NUMPAD_1, 0x74 }, + { KEY_EN_NUMPAD_0, 0x75 }, + + { KEY_EN_NUMPAD_DIVIDE, 0x77 }, + { KEY_EN_NUMPAD_8, 0x78 }, + { KEY_EN_NUMPAD_5, 0x79 }, + { KEY_EN_NUMPAD_2, 0x7A }, + + { KEY_EN_NUMPAD_TIMES, 0x7C }, + { KEY_EN_NUMPAD_9, 0x7D }, + { KEY_EN_NUMPAD_6, 0x7E }, + { KEY_EN_NUMPAD_3, 0x7F }, + + { KEY_EN_NUMPAD_PERIOD, 0x80 }, + { KEY_EN_NUMPAD_MINUS, 0x81 }, + { KEY_EN_NUMPAD_PLUS, 0x82 }, + { KEY_EN_NUMPAD_ENTER, 0x83 } + } + } + }, +}; + +static std::map RoccatPyroLayouts = +{ + { + ROCCAT_VULCAN_LAYOUT_UK, + { + *ROCCAT_VULCAN_120_AIMO_LAYOUT_KEYS_105, + 105, + 6, + 24, + { + { KEY_EN_ESCAPE, 0x02 }, + { KEY_EN_BACK_TICK, 0x03 }, + { KEY_EN_TAB, 0x04 }, + { KEY_EN_CAPS_LOCK, 0x05 }, + { KEY_EN_LEFT_SHIFT, 0x00 }, + { KEY_EN_LEFT_CONTROL, 0x01 }, + + { KEY_EN_1, 0x08 }, + { KEY_EN_ISO_BACK_SLASH, 0x06 }, + { KEY_EN_LEFT_WINDOWS, 0x07 }, + + { KEY_EN_F1, 0x0D }, + { KEY_EN_2, 0x0E }, + { KEY_EN_Q, 0x09 }, + { KEY_EN_A, 0x0A }, + { KEY_EN_Z, 0x0B }, + { KEY_EN_LEFT_ALT, 0x0C }, + + { KEY_EN_F2, 0x14 }, + { KEY_EN_3, 0x15 }, + { KEY_EN_W, 0x0F }, + { KEY_EN_S, 0x10 }, + { KEY_EN_X, 0x11 }, + + { KEY_EN_F3, 0x19 }, + { KEY_EN_4, 0x1A }, + { KEY_EN_E, 0x16 }, + { KEY_EN_D, 0x17 }, + { KEY_EN_C, 0x18 }, + + { KEY_EN_F4, 0x1E }, + { KEY_EN_5, 0x1F }, + { KEY_EN_R, 0x1B }, + { KEY_EN_F, 0x1C }, + { KEY_EN_V, 0x1D }, + + { KEY_EN_6, 0x24 }, + { KEY_EN_T, 0x20 }, + { KEY_EN_G, 0x21 }, + { KEY_EN_B, 0x22 }, + { KEY_EN_SPACE, 0x23 }, + + { KEY_EN_F5, 0x28 }, + { KEY_EN_7, 0x29 }, + { KEY_EN_Y, 0x25 }, + { KEY_EN_H, 0x26 }, + { KEY_EN_N, 0x27 }, + + { KEY_EN_F6, 0x2F }, + { KEY_EN_8, 0x30 }, + { KEY_EN_U, 0x2A }, + { KEY_EN_J, 0x2B }, + { KEY_EN_M, 0x2C }, + + { KEY_EN_F7, 0x35 }, + { KEY_EN_9, 0x36 }, + { KEY_EN_I, 0x31 }, + { KEY_EN_K, 0x32 }, + { KEY_EN_COMMA, 0x33 }, + + { KEY_EN_F8, 0x3B }, + { KEY_EN_0, 0x3C }, + { KEY_EN_O, 0x37 }, + { KEY_EN_L, 0x38 }, + { KEY_EN_PERIOD, 0x39 }, + { KEY_EN_RIGHT_ALT, 0x3A }, + + { KEY_EN_F9, 0x41 }, + { KEY_EN_MINUS, 0x42 }, + { KEY_EN_P, 0x3D }, + { KEY_EN_SEMICOLON, 0x3E }, + { KEY_EN_FORWARD_SLASH, 0x3F }, + { KEY_EN_RIGHT_FUNCTION, 0x40 }, + + { KEY_EN_F10, 0x47 }, + { KEY_EN_EQUALS, 0x48 }, + { KEY_EN_LEFT_BRACKET, 0x43 }, + { KEY_EN_QUOTE, 0x44 }, + { KEY_EN_MENU, 0x46 }, + + { KEY_EN_F11, 0x4D }, + { KEY_EN_BACKSPACE, 0x50 }, + { KEY_EN_RIGHT_BRACKET, 0x49 }, + { KEY_EN_POUND, 0x4A }, + { KEY_EN_RIGHT_SHIFT, 0x4B }, + + { KEY_EN_F12, 0x4F }, + { KEY_EN_ISO_ENTER, 0x52 }, + { KEY_EN_RIGHT_CONTROL, 0x4C }, + + { KEY_EN_PRINT_SCREEN, 0x53 }, + { KEY_EN_INSERT, 0x54 }, + { KEY_EN_DELETE, 0x55 }, + { KEY_EN_LEFT_ARROW, 0x56 }, + + { KEY_EN_SCROLL_LOCK, 0x57 }, + { KEY_EN_HOME, 0x58 }, + { KEY_EN_END, 0x59 }, + { KEY_EN_UP_ARROW, 0x5A }, + { KEY_EN_DOWN_ARROW, 0x5B }, + + { KEY_EN_PAUSE_BREAK, 0x5C }, + { KEY_EN_PAGE_UP, 0x5D }, + { KEY_EN_PAGE_DOWN, 0x5E }, + { KEY_EN_RIGHT_ARROW, 0x5F }, + + { KEY_EN_NUMPAD_LOCK, 0x61 }, + { KEY_EN_NUMPAD_7, 0x62 }, + { KEY_EN_NUMPAD_4, 0x63 }, + { KEY_EN_NUMPAD_1, 0x64 }, + { KEY_EN_NUMPAD_0, 0x65 }, + + { KEY_EN_NUMPAD_DIVIDE, 0x67 }, + { KEY_EN_NUMPAD_8, 0x68 }, + { KEY_EN_NUMPAD_5, 0x69 }, + { KEY_EN_NUMPAD_2, 0x6A }, + + { KEY_EN_NUMPAD_TIMES, 0x6C }, + { KEY_EN_NUMPAD_9, 0x6D }, + { KEY_EN_NUMPAD_6, 0x6E }, + { KEY_EN_NUMPAD_3, 0x6F }, + { KEY_EN_NUMPAD_PERIOD, 0x70 }, + + { KEY_EN_NUMPAD_MINUS, 0x72 }, + { KEY_EN_NUMPAD_PLUS, 0x73 }, + { KEY_EN_NUMPAD_ENTER, 0x75 } + } + } + }, + { + ROCCAT_VULCAN_LAYOUT_US, + { + *ROCCAT_VULCAN_120_AIMO_LAYOUT_KEYS_104, + 104, + 6, + 24, + { + { KEY_EN_ESCAPE, 0x02 }, + { KEY_EN_BACK_TICK, 0x03 }, + { KEY_EN_TAB, 0x04 }, + { KEY_EN_CAPS_LOCK, 0x05 }, + { KEY_EN_LEFT_SHIFT, 0x00 }, + { KEY_EN_LEFT_CONTROL, 0x01 }, + + { KEY_EN_1, 0x08 }, + { KEY_EN_LEFT_WINDOWS, 0x07 }, + + { KEY_EN_F1, 0x0D }, + { KEY_EN_2, 0x0E }, + { KEY_EN_Q, 0x09 }, + { KEY_EN_A, 0x0A }, + { KEY_EN_Z, 0x0B }, + { KEY_EN_LEFT_ALT, 0x0C }, + + { KEY_EN_F2, 0x14 }, + { KEY_EN_3, 0x15 }, + { KEY_EN_W, 0x0F }, + { KEY_EN_S, 0x10 }, + { KEY_EN_X, 0x11 }, + + { KEY_EN_F3, 0x19 }, + { KEY_EN_4, 0x1A }, + { KEY_EN_E, 0x16 }, + { KEY_EN_D, 0x17 }, + { KEY_EN_C, 0x18 }, + + { KEY_EN_F4, 0x1E }, + { KEY_EN_5, 0x1F }, + { KEY_EN_R, 0x1B }, + { KEY_EN_F, 0x1C }, + { KEY_EN_V, 0x1D }, + + { KEY_EN_6, 0x24 }, + { KEY_EN_T, 0x20 }, + { KEY_EN_G, 0x21 }, + { KEY_EN_B, 0x22 }, + { KEY_EN_SPACE, 0x23 }, + + { KEY_EN_F5, 0x28 }, + { KEY_EN_7, 0x29 }, + { KEY_EN_Y, 0x25 }, + { KEY_EN_H, 0x26 }, + { KEY_EN_N, 0x27 }, + + { KEY_EN_F6, 0x2F }, + { KEY_EN_8, 0x30 }, + { KEY_EN_U, 0x2A }, + { KEY_EN_J, 0x2B }, + { KEY_EN_M, 0x2C }, + + { KEY_EN_F7, 0x35 }, + { KEY_EN_9, 0x36 }, + { KEY_EN_I, 0x31 }, + { KEY_EN_K, 0x32 }, + { KEY_EN_COMMA, 0x33 }, + + { KEY_EN_F8, 0x3B }, + { KEY_EN_0, 0x3C }, + { KEY_EN_O, 0x37 }, + { KEY_EN_L, 0x38 }, + { KEY_EN_PERIOD, 0x39 }, + { KEY_EN_RIGHT_ALT, 0x3A }, + + { KEY_EN_F9, 0x41 }, + { KEY_EN_MINUS, 0x42 }, + { KEY_EN_P, 0x3D }, + { KEY_EN_SEMICOLON, 0x3E }, + { KEY_EN_FORWARD_SLASH, 0x3F }, + { KEY_EN_RIGHT_FUNCTION, 0x40 }, + + { KEY_EN_F10, 0x47 }, + { KEY_EN_EQUALS, 0x48 }, + { KEY_EN_LEFT_BRACKET, 0x43 }, + { KEY_EN_QUOTE, 0x44 }, + { KEY_EN_MENU, 0x46 }, + + { KEY_EN_F11, 0x4D }, + { KEY_EN_BACKSPACE, 0x50 }, + { KEY_EN_RIGHT_BRACKET, 0x49 }, + { KEY_EN_RIGHT_SHIFT, 0x4B }, + + { KEY_EN_F12, 0x4F }, + { KEY_EN_ANSI_BACK_SLASH, 0x51 }, + { KEY_EN_ANSI_ENTER, 0x52 }, + { KEY_EN_RIGHT_CONTROL, 0x4C }, + + { KEY_EN_PRINT_SCREEN, 0x53 }, + { KEY_EN_INSERT, 0x54 }, + { KEY_EN_DELETE, 0x55 }, + { KEY_EN_LEFT_ARROW, 0x56 }, + + { KEY_EN_SCROLL_LOCK, 0x57 }, + { KEY_EN_HOME, 0x58 }, + { KEY_EN_END, 0x59 }, + { KEY_EN_UP_ARROW, 0x5A }, + { KEY_EN_DOWN_ARROW, 0x5B }, + + { KEY_EN_PAUSE_BREAK, 0x5C }, + { KEY_EN_PAGE_UP, 0x5D }, + { KEY_EN_PAGE_DOWN, 0x5E }, + { KEY_EN_RIGHT_ARROW, 0x5F }, + + { KEY_EN_NUMPAD_LOCK, 0x61 }, + { KEY_EN_NUMPAD_7, 0x62 }, + { KEY_EN_NUMPAD_4, 0x63 }, + { KEY_EN_NUMPAD_1, 0x64 }, + { KEY_EN_NUMPAD_0, 0x65 }, + + { KEY_EN_NUMPAD_DIVIDE, 0x67 }, + { KEY_EN_NUMPAD_8, 0x68 }, + { KEY_EN_NUMPAD_5, 0x69 }, + { KEY_EN_NUMPAD_2, 0x6A }, + + { KEY_EN_NUMPAD_TIMES, 0x6C }, + { KEY_EN_NUMPAD_9, 0x6D }, + { KEY_EN_NUMPAD_6, 0x6E }, + { KEY_EN_NUMPAD_3, 0x6F }, + { KEY_EN_NUMPAD_PERIOD, 0x70 }, + + { KEY_EN_NUMPAD_MINUS, 0x72 }, + { KEY_EN_NUMPAD_PLUS, 0x73 }, + { KEY_EN_NUMPAD_ENTER, 0x75 } + } + } + }, +}; + +static std::map RoccatVulcanIILayouts = +{ + { + ROCCAT_VULCAN_LAYOUT_UK, + { + *ROCCAT_VULCAN_II_LAYOUT_KEYS_105, + 108, + 6, + 24, + { + { KEY_EN_ESCAPE, 0x02 }, + { KEY_EN_BACK_TICK, 0x03 }, + { KEY_EN_TAB, 0x04 }, + { KEY_EN_CAPS_LOCK, 0x05 }, + { KEY_EN_LEFT_SHIFT, 0x00 }, + { KEY_EN_LEFT_CONTROL, 0x01 }, + + { KEY_EN_1, 0x08 }, + { KEY_EN_ISO_BACK_SLASH, 0x06 }, + { KEY_EN_LEFT_WINDOWS, 0x07 }, + + { KEY_EN_F1, 0x0D }, + { KEY_EN_2, 0x0E }, + { KEY_EN_Q, 0x09 }, + { KEY_EN_A, 0x0A }, + { KEY_EN_Z, 0x0B }, + { KEY_EN_LEFT_ALT, 0x0C }, + + { KEY_EN_F2, 0x14 }, + { KEY_EN_3, 0x15 }, + { KEY_EN_W, 0x0F }, + { KEY_EN_S, 0x10 }, + { KEY_EN_X, 0x11 }, + + { KEY_EN_F3, 0x19 }, + { KEY_EN_4, 0x1A }, + { KEY_EN_E, 0x16 }, + { KEY_EN_D, 0x17 }, + { KEY_EN_C, 0x18 }, + + { KEY_EN_F4, 0x1E }, + { KEY_EN_5, 0x1F }, + { KEY_EN_R, 0x1B }, + { KEY_EN_F, 0x1C }, + { KEY_EN_V, 0x1D }, + + { KEY_EN_6, 0x24 }, + { KEY_EN_T, 0x20 }, + { KEY_EN_G, 0x21 }, + { KEY_EN_B, 0x22 }, + { KEY_EN_SPACE, 0x23 }, + + { KEY_EN_F5, 0x28 }, + { KEY_EN_7, 0x29 }, + { KEY_EN_Y, 0x25 }, + { KEY_EN_H, 0x26 }, + { KEY_EN_N, 0x27 }, + + { KEY_EN_F6, 0x2F }, + { KEY_EN_8, 0x30 }, + { KEY_EN_U, 0x2A }, + { KEY_EN_J, 0x2B }, + { KEY_EN_M, 0x2C }, + + { KEY_EN_F7, 0x35 }, + { KEY_EN_9, 0x36 }, + { KEY_EN_I, 0x31 }, + { KEY_EN_K, 0x32 }, + { KEY_EN_COMMA, 0x33 }, + + { KEY_EN_F8, 0x3B }, + { KEY_EN_0, 0x3C }, + { KEY_EN_O, 0x37 }, + { KEY_EN_L, 0x38 }, + { KEY_EN_PERIOD, 0x39 }, + { KEY_EN_RIGHT_ALT, 0x3A }, + + { KEY_EN_F9, 0x41 }, + { KEY_EN_MINUS, 0x42 }, + { KEY_EN_P, 0x3D }, + { KEY_EN_SEMICOLON, 0x3E }, + { KEY_EN_FORWARD_SLASH, 0x3F }, + { KEY_EN_RIGHT_FUNCTION, 0x40 }, + + { KEY_EN_F10, 0x47 }, + { KEY_EN_EQUALS, 0x48 }, + { KEY_EN_LEFT_BRACKET, 0x43 }, + { KEY_EN_QUOTE, 0x44 }, + { KEY_EN_MENU, 0x46 }, + + { KEY_EN_F11, 0x4D }, + { KEY_EN_BACKSPACE, 0x50 }, + { KEY_EN_RIGHT_BRACKET, 0x49 }, + { KEY_EN_POUND, 0x4A }, + { KEY_EN_RIGHT_SHIFT, 0x4B }, + + { KEY_EN_F12, 0x4F }, + { KEY_EN_ISO_ENTER, 0x52 }, + { KEY_EN_RIGHT_CONTROL, 0x4C }, + + { KEY_EN_PRINT_SCREEN, 0x53 }, + { KEY_EN_INSERT, 0x54 }, + { KEY_EN_DELETE, 0x55 }, + { KEY_EN_LEFT_ARROW, 0x56 }, + + { KEY_EN_SCROLL_LOCK, 0x57 }, + { KEY_EN_HOME, 0x58 }, + { KEY_EN_END, 0x59 }, + { KEY_EN_UP_ARROW, 0x5A }, + { KEY_EN_DOWN_ARROW, 0x5B }, + + { KEY_EN_PAUSE_BREAK, 0x5C }, + { KEY_EN_PAGE_UP, 0x5D }, + { KEY_EN_PAGE_DOWN, 0x5E }, + { KEY_EN_RIGHT_ARROW, 0x5F }, + + { KEY_EN_NUMPAD_LOCK, 0x61 }, + { KEY_EN_NUMPAD_7, 0x62 }, + { KEY_EN_NUMPAD_4, 0x63 }, + { KEY_EN_NUMPAD_1, 0x64 }, + { KEY_EN_NUMPAD_0, 0x65 }, + + { KEY_EN_NUMPAD_DIVIDE, 0x67 }, + { KEY_EN_NUMPAD_8, 0x68 }, + { KEY_EN_NUMPAD_5, 0x69 }, + { KEY_EN_NUMPAD_2, 0x6A }, + + { KEY_EN_NUMPAD_TIMES, 0x6C }, + { KEY_EN_NUMPAD_9, 0x6D }, + { KEY_EN_NUMPAD_6, 0x6E }, + { KEY_EN_NUMPAD_3, 0x6F }, + { KEY_EN_NUMPAD_PERIOD, 0x70 }, + + { KEY_EN_NUMPAD_MINUS, 0x72 }, + { KEY_EN_NUMPAD_PLUS, 0x73 }, + { KEY_EN_NUMPAD_ENTER, 0x75 }, + { KEY_EN_MEDIA_PREVIOUS, 0x76 }, + { KEY_EN_MEDIA_PLAY_PAUSE, 0x78 }, + + { KEY_EN_MEDIA_NEXT, 0x79 } + } + } + }, +}; + +static std::map RoccatVulcanTKLLayouts = +{ + { + ROCCAT_VULCAN_LAYOUT_UK, + { + *ROCCAT_VULCAN_TKL_LAYOUT_KEYS_105, + 86, + 6, + 19, + { + { KEY_EN_ESCAPE, 0x02 }, + { KEY_EN_BACK_TICK, 0x03 }, + { KEY_EN_TAB, 0x04 }, + { KEY_EN_CAPS_LOCK, 0x05 }, + { KEY_EN_LEFT_SHIFT, 0x00 }, + { KEY_EN_LEFT_CONTROL, 0x01 }, + + { KEY_EN_1, 0x08 }, + { KEY_EN_ISO_BACK_SLASH, 0x06 }, + { KEY_EN_LEFT_WINDOWS, 0x07 }, + + { KEY_EN_F1, 0x0D }, + { KEY_EN_2, 0x0E }, + { KEY_EN_Q, 0x09 }, + { KEY_EN_A, 0x0A }, + { KEY_EN_Z, 0x0B }, + { KEY_EN_LEFT_ALT, 0x0C }, + + { KEY_EN_F2, 0x14 }, + { KEY_EN_3, 0x15 }, + { KEY_EN_W, 0x0F }, + { KEY_EN_S, 0x10 }, + { KEY_EN_X, 0x11 }, + + { KEY_EN_F3, 0x19 }, + { KEY_EN_4, 0x1A }, + { KEY_EN_E, 0x16 }, + { KEY_EN_D, 0x17 }, + { KEY_EN_C, 0x18 }, + + { KEY_EN_F4, 0x1E }, + { KEY_EN_5, 0x1F }, + { KEY_EN_R, 0x1B }, + { KEY_EN_F, 0x1C }, + { KEY_EN_V, 0x1D }, + + { KEY_EN_6, 0x24 }, + { KEY_EN_T, 0x20 }, + { KEY_EN_G, 0x21 }, + { KEY_EN_B, 0x22 }, + { KEY_EN_SPACE, 0x23 }, + + { KEY_EN_F5, 0x28 }, + { KEY_EN_7, 0x29 }, + { KEY_EN_Y, 0x25 }, + { KEY_EN_H, 0x26 }, + { KEY_EN_N, 0x27 }, + + { KEY_EN_F6, 0x2F }, + { KEY_EN_8, 0x30 }, + { KEY_EN_U, 0x2A }, + { KEY_EN_J, 0x2B }, + { KEY_EN_M, 0x2C }, + + { KEY_EN_F7, 0x35 }, + { KEY_EN_9, 0x36 }, + { KEY_EN_I, 0x31 }, + { KEY_EN_K, 0x32 }, + { KEY_EN_COMMA, 0x33 }, + + { KEY_EN_F8, 0x3B }, + { KEY_EN_0, 0x3C }, + { KEY_EN_O, 0x37 }, + { KEY_EN_L, 0x38 }, + { KEY_EN_PERIOD, 0x39 }, + { KEY_EN_RIGHT_ALT, 0x3A }, + + { KEY_EN_F9, 0x41 }, + { KEY_EN_MINUS, 0x42 }, + { KEY_EN_P, 0x3D }, + { KEY_EN_SEMICOLON, 0x3E }, + { KEY_EN_FORWARD_SLASH, 0x3F }, + { KEY_EN_RIGHT_FUNCTION, 0x40 }, + + { KEY_EN_F10, 0x47 }, + { KEY_EN_EQUALS, 0x48 }, + { KEY_EN_LEFT_BRACKET, 0x43 }, + { KEY_EN_QUOTE, 0x44 }, + { KEY_EN_MENU, 0x46 }, + + { KEY_EN_F11, 0x4D }, + { KEY_EN_BACKSPACE, 0x50 }, + { KEY_EN_RIGHT_BRACKET, 0x49 }, + { KEY_EN_POUND, 0x4A }, + { KEY_EN_RIGHT_SHIFT, 0x4B }, + + { KEY_EN_F12, 0x4F }, + { KEY_EN_ISO_ENTER, 0x52 }, + { KEY_EN_RIGHT_CONTROL, 0x4C }, + + { KEY_EN_MEDIA_MUTE, 0x5C }, + { KEY_EN_INSERT, 0x54 }, + { KEY_EN_DELETE, 0x55 }, + { KEY_EN_LEFT_ARROW, 0x56 }, + + { KEY_EN_HOME, 0x58 }, + { KEY_EN_END, 0x59 }, + { KEY_EN_UP_ARROW, 0x5A }, + { KEY_EN_DOWN_ARROW, 0x5B }, + + { KEY_EN_PAGE_UP, 0x5D }, + { KEY_EN_PAGE_DOWN, 0x5E }, + { KEY_EN_RIGHT_ARROW, 0x5F }, + } + } + }, + { + ROCCAT_VULCAN_LAYOUT_US, + { + *ROCCAT_VULCAN_TKL_LAYOUT_KEYS_104, + 85, + 6, + 19, + { + { KEY_EN_ESCAPE, 0x02 }, + { KEY_EN_BACK_TICK, 0x03 }, + { KEY_EN_TAB, 0x04 }, + { KEY_EN_CAPS_LOCK, 0x05 }, + { KEY_EN_LEFT_SHIFT, 0x00 }, + { KEY_EN_LEFT_CONTROL, 0x01 }, + + { KEY_EN_1, 0x08 }, + { KEY_EN_LEFT_WINDOWS, 0x07 }, + + { KEY_EN_F1, 0x0D }, + { KEY_EN_2, 0x0E }, + { KEY_EN_Q, 0x09 }, + { KEY_EN_A, 0x0A }, + { KEY_EN_Z, 0x0B }, + { KEY_EN_LEFT_ALT, 0x0C }, + + { KEY_EN_F2, 0x14 }, + { KEY_EN_3, 0x15 }, + { KEY_EN_W, 0x0F }, + { KEY_EN_S, 0x10 }, + { KEY_EN_X, 0x11 }, + + { KEY_EN_F3, 0x19 }, + { KEY_EN_4, 0x1A }, + { KEY_EN_E, 0x16 }, + { KEY_EN_D, 0x17 }, + { KEY_EN_C, 0x18 }, + + { KEY_EN_F4, 0x1E }, + { KEY_EN_5, 0x1F }, + { KEY_EN_R, 0x1B }, + { KEY_EN_F, 0x1C }, + { KEY_EN_V, 0x1D }, + + { KEY_EN_6, 0x24 }, + { KEY_EN_T, 0x20 }, + { KEY_EN_G, 0x21 }, + { KEY_EN_B, 0x22 }, + { KEY_EN_SPACE, 0x23 }, + + { KEY_EN_F5, 0x28 }, + { KEY_EN_7, 0x29 }, + { KEY_EN_Y, 0x25 }, + { KEY_EN_H, 0x26 }, + { KEY_EN_N, 0x27 }, + + { KEY_EN_F6, 0x2F }, + { KEY_EN_8, 0x30 }, + { KEY_EN_U, 0x2A }, + { KEY_EN_J, 0x2B }, + { KEY_EN_M, 0x2C }, + + { KEY_EN_F7, 0x35 }, + { KEY_EN_9, 0x36 }, + { KEY_EN_I, 0x31 }, + { KEY_EN_K, 0x32 }, + { KEY_EN_COMMA, 0x33 }, + + { KEY_EN_F8, 0x3B }, + { KEY_EN_0, 0x3C }, + { KEY_EN_O, 0x37 }, + { KEY_EN_L, 0x38 }, + { KEY_EN_PERIOD, 0x39 }, + { KEY_EN_RIGHT_ALT, 0x3A }, + + { KEY_EN_F9, 0x41 }, + { KEY_EN_MINUS, 0x42 }, + { KEY_EN_P, 0x3D }, + { KEY_EN_SEMICOLON, 0x3E }, + { KEY_EN_FORWARD_SLASH, 0x3F }, + { KEY_EN_RIGHT_FUNCTION, 0x40 }, + + { KEY_EN_F10, 0x47 }, + { KEY_EN_EQUALS, 0x48 }, + { KEY_EN_LEFT_BRACKET, 0x43 }, + { KEY_EN_QUOTE, 0x44 }, + { KEY_EN_MENU, 0x46 }, + + { KEY_EN_F11, 0x4D }, + { KEY_EN_BACKSPACE, 0x50 }, + { KEY_EN_RIGHT_BRACKET, 0x49 }, + { KEY_EN_RIGHT_SHIFT, 0x4B }, + + { KEY_EN_F12, 0x4F }, + { KEY_EN_ANSI_BACK_SLASH, 0x51 }, // this one is guessed, not tested with ansi layout + { KEY_EN_ANSI_ENTER, 0x52 }, + { KEY_EN_RIGHT_CONTROL, 0x4C }, + + { KEY_EN_MEDIA_MUTE, 0x5C }, + { KEY_EN_INSERT, 0x54 }, + { KEY_EN_DELETE, 0x55 }, + { KEY_EN_LEFT_ARROW, 0x56 }, + + { KEY_EN_HOME, 0x58 }, + { KEY_EN_END, 0x59 }, + { KEY_EN_UP_ARROW, 0x5A }, + { KEY_EN_DOWN_ARROW, 0x5B }, + + { KEY_EN_PAGE_UP, 0x5D }, + { KEY_EN_PAGE_DOWN, 0x5E }, + { KEY_EN_RIGHT_ARROW, 0x5F }, + } + } + }, +}; + +static std::map RoccatMagmaLayouts = +{ + { + ROCCAT_VULCAN_LAYOUT_US, + { + *ROCCAT_MAGMA_LAYOUT_KEYS, + 5, + 1, + 5, + { + { "Keyboard LED 1", 0x00 }, + { "Keyboard LED 2", 0x01 }, + { "Keyboard LED 3", 0x02 }, + { "Keyboard LED 4", 0x03 }, + { "Keyboard LED 5", 0x04 }, + } + } + }, +}; diff --git a/Controllers/SRGBmodsController/RGBController_SRGBmodsLEDControllerV1.h b/Controllers/SRGBmodsController/RGBController_SRGBmodsLEDControllerV1.h deleted file mode 100644 index 91c3f343..00000000 --- a/Controllers/SRGBmodsController/RGBController_SRGBmodsLEDControllerV1.h +++ /dev/null @@ -1,36 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SRGBmodsLEDControllerV1.h | -| | -| Generic RGB Interface for SRGBmods | -| LED Controller V1 | -| | -| Adam Honse (CalcProgrammer1) 6/30/2023 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "SRGBmodsLEDControllerV1.h" - -#define SRGBMODS_LED_CONTROLLER_V1_NUM_CHANNELS 1 - -class RGBController_SRGBmodsLEDControllerV1 : public RGBController -{ -public: - RGBController_SRGBmodsLEDControllerV1(SRGBmodsLEDControllerV1* controller_ptr); - ~RGBController_SRGBmodsLEDControllerV1(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - SRGBmodsLEDControllerV1* controller; - std::vector leds_channel; - std::vector zones_channel; -}; diff --git a/Controllers/SRGBmodsController/RGBController_SRGBmodsPico.cpp b/Controllers/SRGBmodsController/RGBController_SRGBmodsPico.cpp deleted file mode 100644 index b619a638..00000000 --- a/Controllers/SRGBmodsController/RGBController_SRGBmodsPico.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SRGBmodsPico.cpp | -| | -| Generic RGB Interface for SRGBmods | -| Raspberry Pi Pico LED Controller | -| | -| Adam Honse (CalcProgrammer1) 7/21/2022 | -\*-----------------------------------------*/ - -#include "RGBController_SRGBmodsPico.h" - -/**------------------------------------------------------------------*\ - @name SRGBmods Raspberry Pi Pico LED Controller - @category LEDStrip - @type USB - @save :x: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectSRGBmodsControllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_SRGBmodsPico::RGBController_SRGBmodsPico(SRGBmodsPicoController* controller_ptr) -{ - controller = controller_ptr; - - name = "SRGBmods Device"; - vendor = "SRGBmods.net"; - description = "SRGBmods Pico LED Controller Device"; - type = DEVICE_TYPE_LEDSTRIP; - location = controller->GetLocationString(); - serial = controller->GetSerialString(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = 0xFFFF; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - - SetupZones(); -} - -RGBController_SRGBmodsPico::~RGBController_SRGBmodsPico() -{ - delete controller; -} - -void RGBController_SRGBmodsPico::SetupZones() -{ - /*-------------------------------------------------*\ - | Only set LED count on the first run | - \*-------------------------------------------------*/ - bool first_run = false; - - if(zones.size() == 0) - { - first_run = true; - } - - /*-------------------------------------------------*\ - | Clear any existing color/LED configuration | - \*-------------------------------------------------*/ - leds.clear(); - colors.clear(); - zones.resize(SRGBMODS_PICO_NUM_CHANNELS); - - /*-------------------------------------------------*\ - | Set zones and leds | - \*-------------------------------------------------*/ - for(unsigned int channel_idx = 0; channel_idx < SRGBMODS_PICO_NUM_CHANNELS; channel_idx++) - { - char ch_idx_string[2]; - snprintf(ch_idx_string, 2, "%d", channel_idx + 1); - - zones[channel_idx].name = "Channel "; - zones[channel_idx].name.append(ch_idx_string); - zones[channel_idx].type = ZONE_TYPE_LINEAR; - - /*-------------------------------------------------*\ - | The maximum number of LEDs per channel is 512 | - | according to https://srgbmods.net/picoled/ | - \*-------------------------------------------------*/ - zones[channel_idx].leds_min = 0; - zones[channel_idx].leds_max = 512; - - if(first_run) - { - zones[channel_idx].leds_count = 0; - } - - zones[channel_idx].matrix_map = NULL; - - for(unsigned int led_ch_idx = 0; led_ch_idx < zones[channel_idx].leds_count; led_ch_idx++) - { - char led_idx_string[4]; - snprintf(led_idx_string, 4, "%d", led_ch_idx + 1); - - led new_led; - new_led.name = "LED "; - new_led.name.append(led_idx_string); - - leds.push_back(new_led); - leds_channel.push_back(channel_idx); - } - } - - SetupColors(); -} - -void RGBController_SRGBmodsPico::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_SRGBmodsPico::DeviceUpdateLEDs() -{ - for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) - { - if(zones[zone_idx].leds_count > 0) - { - controller->SetChannelLEDs(zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); - } - } -} - -void RGBController_SRGBmodsPico::UpdateZoneLEDs(int zone) -{ - controller->SetChannelLEDs(zone, zones[zone].colors, zones[zone].leds_count); -} - -void RGBController_SRGBmodsPico::UpdateSingleLED(int led) -{ - unsigned int channel = leds_channel[led]; - - controller->SetChannelLEDs(channel, zones[channel].colors, zones[channel].leds_count); -} - -void RGBController_SRGBmodsPico::DeviceUpdateMode() -{ - DeviceUpdateLEDs(); -} diff --git a/Controllers/SRGBmodsController/RGBController_SRGBmodsPico.h b/Controllers/SRGBmodsController/RGBController_SRGBmodsPico.h deleted file mode 100644 index 696a21e7..00000000 --- a/Controllers/SRGBmodsController/RGBController_SRGBmodsPico.h +++ /dev/null @@ -1,36 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SRGBmodsPico.h | -| | -| Generic RGB Interface for SRGBmods | -| Raspberry Pi Pico LED Controller | -| | -| Adam Honse (CalcProgrammer1) 7/21/2022 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "SRGBmodsPicoController.h" - -#define SRGBMODS_PICO_NUM_CHANNELS 2 - -class RGBController_SRGBmodsPico : public RGBController -{ -public: - RGBController_SRGBmodsPico(SRGBmodsPicoController* controller_ptr); - ~RGBController_SRGBmodsPico(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - SRGBmodsPicoController* controller; - std::vector leds_channel; - std::vector zones_channel; -}; diff --git a/Controllers/SRGBmodsController/SRGBmodsControllerDetect.cpp b/Controllers/SRGBmodsController/SRGBmodsControllerDetect.cpp index 8b79ed21..d4310e03 100644 --- a/Controllers/SRGBmodsController/SRGBmodsControllerDetect.cpp +++ b/Controllers/SRGBmodsController/SRGBmodsControllerDetect.cpp @@ -1,11 +1,20 @@ +/*---------------------------------------------------------*\ +| SRGBModsControllerDetect.cpp | +| | +| Detector for SRGBmods devices | +| | +| Adam Honse (CalcProgrammer1) 21 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "SRGBmodsLEDControllerV1.h" #include "SRGBmodsPicoController.h" -#include "RGBController.h" #include "RGBController_SRGBmodsLEDControllerV1.h" #include "RGBController_SRGBmodsPico.h" -#include -#include #define SRGBMODS_VID 0x16D0 @@ -37,17 +46,15 @@ void DetectSRGBmodsControllers(hid_device_info* info, const std::string& name) \*-------------------------------------------------------------------------*/ if(product_str == L"SRGBmods Pico LED Controller" || product_str == L"Pico LED Controller") { - SRGBmodsPicoController* controller = new SRGBmodsPicoController(dev, info->path); + SRGBmodsPicoController* controller = new SRGBmodsPicoController(dev, info->path, name); RGBController_SRGBmodsPico* rgb_controller = new RGBController_SRGBmodsPico(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } else if(product_str == L"LED Controller v1") { - SRGBmodsLEDControllerV1* controller = new SRGBmodsLEDControllerV1(dev, info->path); + SRGBmodsLEDControllerV1* controller = new SRGBmodsLEDControllerV1(dev, info->path, name); RGBController_SRGBmodsLEDControllerV1* rgb_controller = new RGBController_SRGBmodsLEDControllerV1(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } diff --git a/Controllers/SRGBmodsController/SRGBmodsLEDControllerV1.h b/Controllers/SRGBmodsController/SRGBmodsLEDControllerV1.h deleted file mode 100644 index 73276a63..00000000 --- a/Controllers/SRGBmodsController/SRGBmodsLEDControllerV1.h +++ /dev/null @@ -1,63 +0,0 @@ -/*-----------------------------------------*\ -| SRGBmodsLEDControllerV1.h | -| | -| Definitions and types for SRGBmods | -| LED Controller V1 | -| | -| Adam Honse (CalcProgrammer1) 6/30/2023 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include -#include - -#pragma once - -enum -{ - SRGBMODS_LED_CONTROLLER_V1_MODE_RAINBOW = 0x01, /* Rainbow wave mode */ - SRGBMODS_LED_CONTROLLER_V1_MODE_BREATHING_RANDOM = 0x02, /* Breathing random mode */ - SRGBMODS_LED_CONTROLLER_V1_MODE_STATIC = 0x03, /* Static mode */ - SRGBMODS_LED_CONTROLLER_V1_MODE_BREATHING_MODE_SPECIFIC = 0x04, /* Breathing mode specific mode */ - SRGBMODS_LED_CONTROLLER_V1_MODE_DIRECT = 0xFF, /* Direct (SW) mode */ -}; - -class SRGBmodsLEDControllerV1 -{ -public: - SRGBmodsLEDControllerV1(hid_device* dev_handle, const char* path); - ~SRGBmodsLEDControllerV1(); - - std::string GetLocationString(); - std::string GetSerialString(); - - void SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors); - void SetConfiguration(unsigned char mode, unsigned char speed, unsigned char brightness, RGBColor color); - void SetDirect(); - -private: - hid_device* dev; - std::string location; - - void SendPacket - ( - unsigned char this_packet_id, - unsigned char last_packet_id, - bool reset, - RGBColor* colors, - unsigned int num_colors - ); - - void SendConfiguration - ( - bool reset, - unsigned char hw_effect_enable, - unsigned char hw_effect_mode, - unsigned char hw_effect_speed, - unsigned char hw_effect_brightness, - RGBColor hw_effect_color, - unsigned char status_led_enable, - unsigned char color_compression_enable - ); -}; diff --git a/Controllers/SRGBmodsController/RGBController_SRGBmodsLEDControllerV1.cpp b/Controllers/SRGBmodsController/SRGBmodsLEDControllerV1/RGBController_SRGBmodsLEDControllerV1.cpp similarity index 89% rename from Controllers/SRGBmodsController/RGBController_SRGBmodsLEDControllerV1.cpp rename to Controllers/SRGBmodsController/SRGBmodsLEDControllerV1/RGBController_SRGBmodsLEDControllerV1.cpp index 3b0daedf..cf637406 100644 --- a/Controllers/SRGBmodsController/RGBController_SRGBmodsLEDControllerV1.cpp +++ b/Controllers/SRGBmodsController/SRGBmodsLEDControllerV1/RGBController_SRGBmodsLEDControllerV1.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_SRGBmodsLEDControllerV1.cpp| -| | -| Generic RGB Interface for SRGBmods | -| LED Controller V1 | -| | -| Adam Honse (CalcProgrammer1) 6/30/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_SRGBmodsLEDControllerV1.cpp | +| | +| RGBController for SRGBmods LED Controller V1 | +| | +| Adam Honse (CalcProgrammer1) 30 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_SRGBmodsLEDControllerV1.h" @@ -24,7 +26,7 @@ RGBController_SRGBmodsLEDControllerV1::RGBController_SRGBmodsLEDControllerV1(SRG { controller = controller_ptr; - name = "SRGBmods Device"; + name = controller->GetNameString(); vendor = "SRGBmods.net"; description = "SRGBmods LED Controller V1 Device"; type = DEVICE_TYPE_LEDSTRIP; @@ -152,7 +154,7 @@ void RGBController_SRGBmodsLEDControllerV1::SetupZones() void RGBController_SRGBmodsLEDControllerV1::ResizeZone(int zone, int new_size) { - if((size_t) zone >= zones.size()) + if((size_t)zone >= zones.size()) { return; } @@ -173,7 +175,7 @@ void RGBController_SRGBmodsLEDControllerV1::DeviceUpdateLEDs() { if(zones[zone_idx].leds_count > 0) { - controller->SetChannelLEDs(zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); + controller->SetChannelLEDs((unsigned char)zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); } } } diff --git a/Controllers/SRGBmodsController/SRGBmodsLEDControllerV1/RGBController_SRGBmodsLEDControllerV1.h b/Controllers/SRGBmodsController/SRGBmodsLEDControllerV1/RGBController_SRGBmodsLEDControllerV1.h new file mode 100644 index 00000000..5c08e287 --- /dev/null +++ b/Controllers/SRGBmodsController/SRGBmodsLEDControllerV1/RGBController_SRGBmodsLEDControllerV1.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------*\ +| RGBController_SRGBmodsLEDControllerV1.h | +| | +| RGBController for SRGBmods LED Controller V1 | +| | +| Adam Honse (CalcProgrammer1) 30 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SRGBmodsLEDControllerV1.h" + +#define SRGBMODS_LED_CONTROLLER_V1_NUM_CHANNELS 1 + +class RGBController_SRGBmodsLEDControllerV1 : public RGBController +{ +public: + RGBController_SRGBmodsLEDControllerV1(SRGBmodsLEDControllerV1* controller_ptr); + ~RGBController_SRGBmodsLEDControllerV1(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + SRGBmodsLEDControllerV1* controller; + std::vector leds_channel; + std::vector zones_channel; +}; diff --git a/Controllers/SRGBmodsController/SRGBmodsLEDControllerV1.cpp b/Controllers/SRGBmodsController/SRGBmodsLEDControllerV1/SRGBmodsLEDControllerV1.cpp similarity index 86% rename from Controllers/SRGBmodsController/SRGBmodsLEDControllerV1.cpp rename to Controllers/SRGBmodsController/SRGBmodsLEDControllerV1/SRGBmodsLEDControllerV1.cpp index 478713ec..1da4c684 100644 --- a/Controllers/SRGBmodsController/SRGBmodsLEDControllerV1.cpp +++ b/Controllers/SRGBmodsController/SRGBmodsLEDControllerV1/SRGBmodsLEDControllerV1.cpp @@ -1,20 +1,25 @@ -/*-----------------------------------------*\ -| SRGBmodsLEDControllerV1.cpp | -| | -| Driver for SRGBmods LED Controller V1 | -| | -| Adam Honse (CalcProgrammer1) 6/30/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| SRGBmodsLEDControllerV1.cpp | +| | +| Driver for SRGBmods LED Controller V1 | +| | +| Adam Honse (CalcProgrammer1) 30 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "SRGBmodsLEDControllerV1.h" #include +#include "SRGBmodsLEDControllerV1.h" +#include "StringUtils.h" using namespace std::chrono_literals; -SRGBmodsLEDControllerV1::SRGBmodsLEDControllerV1(hid_device* dev_handle, const char* path) +SRGBmodsLEDControllerV1::SRGBmodsLEDControllerV1(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; } SRGBmodsLEDControllerV1::~SRGBmodsLEDControllerV1() @@ -27,6 +32,11 @@ std::string SRGBmodsLEDControllerV1::GetLocationString() return("HID: " + location); } +std::string SRGBmodsLEDControllerV1::GetNameString() +{ + return(name); +} + std::string SRGBmodsLEDControllerV1::GetSerialString() { wchar_t serial_string[128]; @@ -37,10 +47,7 @@ std::string SRGBmodsLEDControllerV1::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void SRGBmodsLEDControllerV1::SetChannelLEDs(unsigned char /*channel*/, RGBColor* colors, unsigned int num_colors) diff --git a/Controllers/SRGBmodsController/SRGBmodsLEDControllerV1/SRGBmodsLEDControllerV1.h b/Controllers/SRGBmodsController/SRGBmodsLEDControllerV1/SRGBmodsLEDControllerV1.h new file mode 100644 index 00000000..64e3c887 --- /dev/null +++ b/Controllers/SRGBmodsController/SRGBmodsLEDControllerV1/SRGBmodsLEDControllerV1.h @@ -0,0 +1,67 @@ +/*---------------------------------------------------------*\ +| SRGBmodsLEDControllerV1.h | +| | +| Driver for SRGBmods LED Controller V1 | +| | +| Adam Honse (CalcProgrammer1) 30 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" + +enum +{ + SRGBMODS_LED_CONTROLLER_V1_MODE_RAINBOW = 0x01, /* Rainbow wave mode */ + SRGBMODS_LED_CONTROLLER_V1_MODE_BREATHING_RANDOM = 0x02, /* Breathing random mode */ + SRGBMODS_LED_CONTROLLER_V1_MODE_STATIC = 0x03, /* Static mode */ + SRGBMODS_LED_CONTROLLER_V1_MODE_BREATHING_MODE_SPECIFIC = 0x04, /* Breathing mode specific mode */ + SRGBMODS_LED_CONTROLLER_V1_MODE_DIRECT = 0xFF, /* Direct (SW) mode */ +}; + +class SRGBmodsLEDControllerV1 +{ +public: + SRGBmodsLEDControllerV1(hid_device* dev_handle, const char* path, std::string dev_name); + ~SRGBmodsLEDControllerV1(); + + std::string GetLocationString(); + std::string GetNameString(); + std::string GetSerialString(); + + void SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors); + void SetConfiguration(unsigned char mode, unsigned char speed, unsigned char brightness, RGBColor color); + void SetDirect(); + +private: + hid_device* dev; + std::string location; + std::string name; + + void SendPacket + ( + unsigned char this_packet_id, + unsigned char last_packet_id, + bool reset, + RGBColor* colors, + unsigned int num_colors + ); + + void SendConfiguration + ( + bool reset, + unsigned char hw_effect_enable, + unsigned char hw_effect_mode, + unsigned char hw_effect_speed, + unsigned char hw_effect_brightness, + RGBColor hw_effect_color, + unsigned char status_led_enable, + unsigned char color_compression_enable + ); +}; diff --git a/Controllers/SRGBmodsController/SRGBmodsPicoController.h b/Controllers/SRGBmodsController/SRGBmodsPicoController.h deleted file mode 100644 index 381031aa..00000000 --- a/Controllers/SRGBmodsController/SRGBmodsPicoController.h +++ /dev/null @@ -1,45 +0,0 @@ -/*-----------------------------------------*\ -| SRGBmodsPicoController.h | -| | -| Definitions and types for SRGBmods | -| Raspberry Pi Pico LED Controller | -| | -| Adam Honse (CalcProgrammer1) 7/21/2022 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include -#include - -#pragma once - -class SRGBmodsPicoController -{ -public: - SRGBmodsPicoController(hid_device* dev_handle, const char* path); - ~SRGBmodsPicoController(); - - std::string GetLocationString(); - std::string GetSerialString(); - - void SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors); - - void KeepaliveThread(); -private: - hid_device* dev; - std::string location; - std::thread* keepalive_thread; - std::atomic keepalive_thread_run; - std::chrono::time_point last_commit_time; - - void SendPacket - ( - unsigned char channel, - unsigned char this_packet_id, - unsigned char last_packet_id, - bool reset, - RGBColor* colors, - unsigned int num_colors - ); -}; diff --git a/Controllers/SRGBmodsController/SRGBmodsPicoController/RGBController_SRGBmodsPico.cpp b/Controllers/SRGBmodsController/SRGBmodsPicoController/RGBController_SRGBmodsPico.cpp new file mode 100644 index 00000000..62f02931 --- /dev/null +++ b/Controllers/SRGBmodsController/SRGBmodsPicoController/RGBController_SRGBmodsPico.cpp @@ -0,0 +1,155 @@ +/*---------------------------------------------------------*\ +| RGBController_SRGBmodsPico.cpp | +| | +| RGBController for SRGBmods Raspberry Pi Pico LED | +| Controller | +| | +| Adam Honse (CalcProgrammer1) 21 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_SRGBmodsPico.h" + +/**------------------------------------------------------------------*\ + @name SRGBmods Raspberry Pi Pico LED Controller + @category LEDStrip + @type USB + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectSRGBmodsControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_SRGBmodsPico::RGBController_SRGBmodsPico(SRGBmodsPicoController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "SRGBmods.net"; + description = "SRGBmods Pico LED Controller Device"; + type = DEVICE_TYPE_LEDSTRIP; + location = controller->GetLocationString(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + SetupZones(); +} + +RGBController_SRGBmodsPico::~RGBController_SRGBmodsPico() +{ + delete controller; +} + +void RGBController_SRGBmodsPico::SetupZones() +{ + /*-------------------------------------------------*\ + | Only set LED count on the first run | + \*-------------------------------------------------*/ + bool first_run = false; + + if(zones.size() == 0) + { + first_run = true; + } + + /*-------------------------------------------------*\ + | Clear any existing color/LED configuration | + \*-------------------------------------------------*/ + leds.clear(); + colors.clear(); + zones.resize(SRGBMODS_PICO_NUM_CHANNELS); + + /*-------------------------------------------------*\ + | Set zones and leds | + \*-------------------------------------------------*/ + for(unsigned int channel_idx = 0; channel_idx < SRGBMODS_PICO_NUM_CHANNELS; channel_idx++) + { + char ch_idx_string[2]; + snprintf(ch_idx_string, 2, "%d", channel_idx + 1); + + zones[channel_idx].name = "Channel "; + zones[channel_idx].name.append(ch_idx_string); + zones[channel_idx].type = ZONE_TYPE_LINEAR; + + /*-------------------------------------------------*\ + | The maximum number of LEDs per channel is 512 | + | according to https://srgbmods.net/picoled/ | + \*-------------------------------------------------*/ + zones[channel_idx].leds_min = 0; + zones[channel_idx].leds_max = 512; + + if(first_run) + { + zones[channel_idx].leds_count = 0; + } + + zones[channel_idx].matrix_map = NULL; + + for(unsigned int led_ch_idx = 0; led_ch_idx < zones[channel_idx].leds_count; led_ch_idx++) + { + char led_idx_string[4]; + snprintf(led_idx_string, 4, "%d", led_ch_idx + 1); + + led new_led; + new_led.name = "LED "; + new_led.name.append(led_idx_string); + + leds.push_back(new_led); + leds_channel.push_back(channel_idx); + } + } + + SetupColors(); +} + +void RGBController_SRGBmodsPico::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_SRGBmodsPico::DeviceUpdateLEDs() +{ + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + if(zones[zone_idx].leds_count > 0) + { + controller->SetChannelLEDs((unsigned char)zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); + } + } +} + +void RGBController_SRGBmodsPico::UpdateZoneLEDs(int zone) +{ + controller->SetChannelLEDs(zone, zones[zone].colors, zones[zone].leds_count); +} + +void RGBController_SRGBmodsPico::UpdateSingleLED(int led) +{ + unsigned int channel = leds_channel[led]; + + controller->SetChannelLEDs(channel, zones[channel].colors, zones[channel].leds_count); +} + +void RGBController_SRGBmodsPico::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} diff --git a/Controllers/SRGBmodsController/SRGBmodsPicoController/RGBController_SRGBmodsPico.h b/Controllers/SRGBmodsController/SRGBmodsPicoController/RGBController_SRGBmodsPico.h new file mode 100644 index 00000000..0e1a3ee9 --- /dev/null +++ b/Controllers/SRGBmodsController/SRGBmodsPicoController/RGBController_SRGBmodsPico.h @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| RGBController_SRGBmodsPico.h | +| | +| RGBController for SRGBmods Raspberry Pi Pico LED | +| Controller | +| | +| Adam Honse (CalcProgrammer1) 21 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SRGBmodsPicoController.h" + +#define SRGBMODS_PICO_NUM_CHANNELS 2 + +class RGBController_SRGBmodsPico : public RGBController +{ +public: + RGBController_SRGBmodsPico(SRGBmodsPicoController* controller_ptr); + ~RGBController_SRGBmodsPico(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + SRGBmodsPicoController* controller; + std::vector leds_channel; + std::vector zones_channel; +}; diff --git a/Controllers/SRGBmodsController/SRGBmodsPicoController.cpp b/Controllers/SRGBmodsController/SRGBmodsPicoController/SRGBmodsPicoController.cpp similarity index 79% rename from Controllers/SRGBmodsController/SRGBmodsPicoController.cpp rename to Controllers/SRGBmodsController/SRGBmodsPicoController/SRGBmodsPicoController.cpp index d95f1715..c6a4c147 100644 --- a/Controllers/SRGBmodsController/SRGBmodsPicoController.cpp +++ b/Controllers/SRGBmodsController/SRGBmodsPicoController/SRGBmodsPicoController.cpp @@ -1,21 +1,25 @@ -/*-----------------------------------------*\ -| SRGBmodsPicoController.cpp | -| | -| Driver for SRGBmods Raspberry Pi Pico | -| LED Controller | -| | -| Adam Honse (CalcProgrammer1) 7/21/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| SRGBmodsPicoController.cpp | +| | +| Driver for SRGBmods Raspberry Pi Pico LED Controller | +| | +| Adam Honse (CalcProgrammer1) 21 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "SRGBmodsPicoController.h" #include +#include "SRGBmodsPicoController.h" +#include "StringUtils.h" using namespace std::chrono_literals; -SRGBmodsPicoController::SRGBmodsPicoController(hid_device* dev_handle, const char* path) +SRGBmodsPicoController::SRGBmodsPicoController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; /*-----------------------------------------------------*\ | The SRGBmods Pico controller requires a packet within | @@ -53,6 +57,11 @@ std::string SRGBmodsPicoController::GetLocationString() return("HID: " + location); } +std::string SRGBmodsPicoController::GetNameString() +{ + return(name); +} + std::string SRGBmodsPicoController::GetSerialString() { wchar_t serial_string[128]; @@ -63,10 +72,7 @@ std::string SRGBmodsPicoController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void SRGBmodsPicoController::SetChannelLEDs(unsigned char channel, RGBColor* colors, unsigned int num_colors) diff --git a/Controllers/SRGBmodsController/SRGBmodsPicoController/SRGBmodsPicoController.h b/Controllers/SRGBmodsController/SRGBmodsPicoController/SRGBmodsPicoController.h new file mode 100644 index 00000000..bd418abb --- /dev/null +++ b/Controllers/SRGBmodsController/SRGBmodsPicoController/SRGBmodsPicoController.h @@ -0,0 +1,49 @@ +/*---------------------------------------------------------*\ +| SRGBmodsPicoController.h | +| | +| Driver for SRGBmods Raspberry Pi Pico LED Controller | +| | +| Adam Honse (CalcProgrammer1) 21 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" + +class SRGBmodsPicoController +{ +public: + SRGBmodsPicoController(hid_device* dev_handle, const char* path, std::string dev_name); + ~SRGBmodsPicoController(); + + std::string GetLocationString(); + std::string GetNameString(); + std::string GetSerialString(); + + void SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors); + + void KeepaliveThread(); +private: + hid_device* dev; + std::string location; + std::string name; + std::thread* keepalive_thread; + std::atomic keepalive_thread_run; + std::chrono::time_point last_commit_time; + + void SendPacket + ( + unsigned char channel, + unsigned char this_packet_id, + unsigned char last_packet_id, + bool reset, + RGBColor* colors, + unsigned int num_colors + ); +}; diff --git a/Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV1.h b/Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV1.h deleted file mode 100644 index 540ea7b5..00000000 --- a/Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV1.h +++ /dev/null @@ -1,34 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SapphireNitroGlowV1.h | -| | -| Generic RGB Interface for OpenRGB | -| Sapphire Nitro Glow V1 GPU RGB Driver | -| | -| Adam Honse (CalcProgrammer1) 7/15/2020 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "SapphireNitroGlowV1Controller.h" - -class RGBController_SapphireNitroGlowV1 : public RGBController -{ -public: - RGBController_SapphireNitroGlowV1(SapphireNitroGlowV1Controller* controller_ptr); - ~RGBController_SapphireNitroGlowV1(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - SapphireNitroGlowV1Controller* controller; - - void ReadConfiguration(); -}; diff --git a/Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV3.h b/Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV3.h deleted file mode 100644 index e6b18be5..00000000 --- a/Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV3.h +++ /dev/null @@ -1,34 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SapphireNitroGlowV3.h | -| | -| Generic RGB Interface for OpenRGB | -| Sapphire Nitro Glow V3 GPU RGB Driver | -| | -| K900 2/3/2021 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "SapphireNitroGlowV3Controller.h" - -class RGBController_SapphireNitroGlowV3 : public RGBController -{ -public: - RGBController_SapphireNitroGlowV3(SapphireNitroGlowV3Controller* controller_ptr); - ~RGBController_SapphireNitroGlowV3(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - SapphireNitroGlowV3Controller* controller; - - void ReadConfiguration(); -}; diff --git a/Controllers/SapphireGPUController/SapphireGPUControllerDetect.cpp b/Controllers/SapphireGPUController/SapphireGPUControllerDetect.cpp index 20d5f39a..e833c225 100644 --- a/Controllers/SapphireGPUController/SapphireGPUControllerDetect.cpp +++ b/Controllers/SapphireGPUController/SapphireGPUControllerDetect.cpp @@ -1,12 +1,19 @@ +/*---------------------------------------------------------*\ +| SapphireGPUControllerDetect.cpp | +| | +| Detector for Sapphire Nitro Glow | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" -#include "RGBController.h" #include "SapphireNitroGlowV1Controller.h" #include "SapphireNitroGlowV3Controller.h" #include "RGBController_SapphireNitroGlowV1.h" #include "RGBController_SapphireNitroGlowV3.h" #include "i2c_smbus.h" #include "pci_ids.h" -#include /*-----------------------------------------------------*\ | I2C Addresses for Sapphire Nitro Glow RGB | @@ -55,9 +62,8 @@ void DetectSapphireV1Controllers(i2c_smbus_interface* bus, uint8_t i2c_addr, con { if(TestForSapphireGPUController(bus, i2c_addr)) { - SapphireNitroGlowV1Controller* new_sapphire_gpu = new SapphireNitroGlowV1Controller(bus, i2c_addr); + SapphireNitroGlowV1Controller* new_sapphire_gpu = new SapphireNitroGlowV1Controller(bus, i2c_addr, name); RGBController_SapphireNitroGlowV1* new_controller = new RGBController_SapphireNitroGlowV1(new_sapphire_gpu); - new_controller->name = name; ResourceManager::get()->RegisterRGBController(new_controller); } @@ -67,32 +73,40 @@ void DetectSapphireV3Controllers(i2c_smbus_interface* bus, uint8_t i2c_addr, con { if(TestForSapphireGPUController(bus, i2c_addr)) { - SapphireNitroGlowV3Controller* new_sapphire_gpu = new SapphireNitroGlowV3Controller(bus, i2c_addr); + SapphireNitroGlowV3Controller* new_sapphire_gpu = new SapphireNitroGlowV3Controller(bus, i2c_addr, name); RGBController_SapphireNitroGlowV3* new_controller = new RGBController_SapphireNitroGlowV3(new_sapphire_gpu); - new_controller->name = name; ResourceManager::get()->RegisterRGBController(new_controller); } } /* DetectSapphireV3Controllers() */ -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 470/480 Nitro+", DetectSapphireV1Controllers, AMD_GPU_VEN, AMD_POLARIS_DEV, SAPPHIRE_LEGACY_SUB_VEN, SAPPHIRE_LEGACY_POLARIS_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V1_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 570/580/590 Nitro+", DetectSapphireV1Controllers, AMD_GPU_VEN, AMD_POLARIS_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_POLARIS_NITRO_PLUS_SUB_DEV1, SAPPHIRE_NITRO_GLOW_V1_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 570/580/590 Nitro+", DetectSapphireV1Controllers, AMD_GPU_VEN, AMD_POLARIS_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_POLARIS_NITRO_PLUS_SUB_DEV2, SAPPHIRE_NITRO_GLOW_V1_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 580 Nitro+ (2048SP)", DetectSapphireV1Controllers, AMD_GPU_VEN, AMD_POLARIS20XL_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_POLARIS_NITRO_PLUS_SUB_DEV1, SAPPHIRE_NITRO_GLOW_V1_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX Vega 56/64 Nitro+", DetectSapphireV1Controllers, AMD_GPU_VEN, AMD_VEGA10_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_VEGA10_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V1_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 5700 (XT) Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI10_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI10_NITRO_PLUS_SUB_DEV1, SAPPHIRE_NITRO_GLOW_V3_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 5700 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI10_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI10_NITRO_PLUS_SUB_DEV2, SAPPHIRE_NITRO_GLOW_V3_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 5700 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI10_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI10_NITRO_PLUS_SUB_DEV3, SAPPHIRE_NITRO_GLOW_V3_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 5500 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI14_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI14_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 6800 XT Nitro+ SE", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_NITRO_PLUS_SUB_DEV1, SAPPHIRE_NITRO_GLOW_V3_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 6800 XT/6900 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_NITRO_PLUS_SUB_DEV2, SAPPHIRE_NITRO_GLOW_V3_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 6800 Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_NITRO_PLUS_SUB_DEV3, SAPPHIRE_NITRO_GLOW_V3_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 6700 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI22_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI22_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 6750 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI22_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI22_NITRO_PLUS_SUB_DEV1, SAPPHIRE_NITRO_GLOW_V3_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 6600 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI23_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI23_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 6900 XT Nitro+ SE", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_6900XT_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 6950 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV3, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_6950XT_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 6900 XT Toxic", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV2, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_TOXIC_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 6900 XT Toxic Limited Edition", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_TOXIC_SUB_DEV1, SAPPHIRE_NITRO_GLOW_V3_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 6900 XT Toxic", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_6900XT_TOXIC_AC_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); -REGISTER_I2C_PCI_DETECTOR("Sapphire RX 7900 XTX Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI31_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI31_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 470/480 Nitro+", DetectSapphireV1Controllers, AMD_GPU_VEN, AMD_POLARIS_DEV, SAPPHIRE_LEGACY_SUB_VEN, SAPPHIRE_LEGACY_POLARIS_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V1_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 570/580/590 Nitro+", DetectSapphireV1Controllers, AMD_GPU_VEN, AMD_POLARIS_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_POLARIS_NITRO_PLUS_SUB_DEV1, SAPPHIRE_NITRO_GLOW_V1_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 570/580/590 Nitro+", DetectSapphireV1Controllers, AMD_GPU_VEN, AMD_POLARIS_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_POLARIS_NITRO_PLUS_SUB_DEV2, SAPPHIRE_NITRO_GLOW_V1_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 580 Nitro+ (2048SP)", DetectSapphireV1Controllers, AMD_GPU_VEN, AMD_POLARIS20XL_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_POLARIS_NITRO_PLUS_SUB_DEV1, SAPPHIRE_NITRO_GLOW_V1_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX Vega 56/64 Nitro+", DetectSapphireV1Controllers, AMD_GPU_VEN, AMD_VEGA10_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_VEGA10_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V1_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 5500 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI14_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI14_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 5700 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI10_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI10_NITRO_PLUS_SUB_DEV1, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 5700 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI10_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI10_NITRO_PLUS_SUB_DEV2, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 5700 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI10_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI10_NITRO_PLUS_SUB_DEV3, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 6600 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI23_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI23_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 6650 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI23_DEV1, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI23_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 6700 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI22_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI22_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 6750 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI22_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI22_NITRO_PLUS_SUB_DEV1, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 6800 Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_NITRO_PLUS_SUB_DEV3, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 6800 XT Nitro+ SE", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_NITRO_PLUS_SUB_DEV1, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 6800 XT/6900 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_NITRO_PLUS_SUB_DEV2, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 6900 XT Nitro+ SE", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_6900XT_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 6900 XT Toxic", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV2, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_TOXIC_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 6900 XT Toxic", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_6900XT_TOXIC_AC_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 6900 XT Toxic Limited Edition", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV1, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_TOXIC_SUB_DEV1, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 6950 XT Toxic", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV3, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_6950XT_TOXIC_AC_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 6950 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV3, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_6950XT_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 6950 XT Nitro+ Pure", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI21_DEV3, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI21_6950XT_NITRO_PLUS_PURE_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 7700 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI32_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI32_7700XT_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 7800 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI32_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI32_7800XT_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 7900 GRE Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI31_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI31_GRE_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 7900 XTX Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI31_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI31_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 9070 Pure", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI48_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI48_PURE_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 9070 XT Nitro+", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI48_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI48_NITRO_PLUS_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); +REGISTER_I2C_PCI_DETECTOR("Sapphire Radeon RX 9070 XT Pure", DetectSapphireV3Controllers, AMD_GPU_VEN, AMD_NAVI48_DEV, SAPPHIRE_SUB_VEN, SAPPHIRE_NAVI48_PURE_XT_SUB_DEV, SAPPHIRE_NITRO_GLOW_V3_ADDR); diff --git a/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller.cpp b/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller.cpp deleted file mode 100644 index dd16cd28..00000000 --- a/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/*-----------------------------------------*\ -| SapphireNitroGlowV1Controller.cpp | -| | -| Driver for Sapphire Nitro Glow V1 GPU | -| RGB lighting controller | -| | -| Adam Honse (CalcProgrammer1) 7/15/2020 | -\*-----------------------------------------*/ - -#include "SapphireNitroGlowV1Controller.h" - -SapphireNitroGlowV1Controller::SapphireNitroGlowV1Controller(i2c_smbus_interface* bus, sapphire_dev_id dev) -{ - this->bus = bus; - this->dev = dev; -} - -SapphireNitroGlowV1Controller::~SapphireNitroGlowV1Controller() -{ - -} - -std::string SapphireNitroGlowV1Controller::GetDeviceLocation() -{ - std::string return_string(bus->device_name); - char addr[5]; - snprintf(addr, 5, "0x%02X", dev); - return_string.append(", address "); - return_string.append(addr); - return("I2C: " + return_string); -} - -unsigned char SapphireNitroGlowV1Controller::GetRed() -{ - return(bus->i2c_smbus_read_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_RED)); -} - -unsigned char SapphireNitroGlowV1Controller::GetGreen() -{ - return(bus->i2c_smbus_read_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_GREEN)); -} - -unsigned char SapphireNitroGlowV1Controller::GetBlue() -{ - return(bus->i2c_smbus_read_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_BLUE)); -} - -void SapphireNitroGlowV1Controller::SetColor(unsigned char red, unsigned char green, unsigned char blue) -{ - bus->i2c_smbus_write_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_RED, red); - bus->i2c_smbus_write_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_GREEN, green); - bus->i2c_smbus_write_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_BLUE, blue); -} - -unsigned char SapphireNitroGlowV1Controller::GetMode() -{ - return(bus->i2c_smbus_read_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_MODE)); -} - -void SapphireNitroGlowV1Controller::SetMode(unsigned char mode) -{ - bus->i2c_smbus_write_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_MODE, mode); -} - -unsigned char SapphireNitroGlowV1Controller::GetBrightness() -{ - return(bus->i2c_smbus_read_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_BRIGHTNESS)); -} - -void SapphireNitroGlowV1Controller::SetBrightness(unsigned char brightness) -{ - bus->i2c_smbus_write_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_BRIGHTNESS, brightness); -} diff --git a/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller.h b/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller.h deleted file mode 100644 index 5db15ebc..00000000 --- a/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller.h +++ /dev/null @@ -1,63 +0,0 @@ -/*-----------------------------------------*\ -| SapphireNitroGlowV1Controller.h | -| | -| Definitions and types for Sapphire Nitro | -| Glow V1 GPU RGB lighting controller | -| | -| Adam Honse (CalcProgrammer1) 7/15/2020 | -\*-----------------------------------------*/ - -#include -#include "i2c_smbus.h" - -#pragma once - -#define SAPPHITE_NITRO_GLOW_V1_BRIGHTNESS_MIN 2; -#define SAPPHITE_NITRO_GLOW_V1_BRIGHTNESS_MAX 0; - -typedef unsigned char sapphire_dev_id; - -enum -{ - SAPPHIRE_NITRO_GLOW_V1_REG_MODE = 0x00, - SAPPHIRE_NITRO_GLOW_V1_REG_BRIGHTNESS = 0x01, - SAPPHIRE_NITRO_GLOW_V1_REG_RED = 0x03, - SAPPHIRE_NITRO_GLOW_V1_REG_GREEN = 0x04, - SAPPHIRE_NITRO_GLOW_V1_REG_BLUE = 0x05, -}; - -enum -{ - SAPPHIRE_NITRO_GLOW_V1_MODE_SAPPHIRE_BLUE = 0x00, - SAPPHIRE_NITRO_GLOW_V1_MODE_RAINBOW = 0x01, - SAPPHIRE_NITRO_GLOW_V1_MODE_BOARD_TEMPERATURE = 0x02, - SAPPHIRE_NITRO_GLOW_V1_MODE_FAN_SPEED = 0x03, - SAPPHIRE_NITRO_GLOW_V1_MODE_CUSTOM = 0x04, - SAPPHIRE_NITRO_GLOW_V1_MODE_OFF = 0x05, -}; - -class SapphireNitroGlowV1Controller -{ -public: - SapphireNitroGlowV1Controller(i2c_smbus_interface* bus, sapphire_dev_id dev); - ~SapphireNitroGlowV1Controller(); - - std::string GetDeviceLocation(); - - unsigned char GetRed(); - unsigned char GetGreen(); - unsigned char GetBlue(); - - void SetColor(unsigned char red, unsigned char green, unsigned char blue); - - unsigned char GetMode(); - void SetMode(unsigned char mode); - - unsigned char GetBrightness(); - void SetBrightness(unsigned char brightness); - -private: - i2c_smbus_interface* bus; - sapphire_dev_id dev; - -}; diff --git a/Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV1.cpp b/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller/RGBController_SapphireNitroGlowV1.cpp similarity index 90% rename from Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV1.cpp rename to Controllers/SapphireGPUController/SapphireNitroGlowV1Controller/RGBController_SapphireNitroGlowV1.cpp index 57724c8c..b8446c6c 100644 --- a/Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV1.cpp +++ b/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller/RGBController_SapphireNitroGlowV1.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_SapphireNitroGlowV1.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Sapphire Nitro Glow V1 GPU Driver | -| | -| Adam Honse (CalcProgrammer1) 7/15/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_SapphireNitroGlowV1.cpp | +| | +| RGBController for Sapphire Nitro Glow V1 | +| | +| Adam Honse (CalcProgrammer1) 15 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_SapphireNitroGlowV1.h" @@ -24,7 +26,7 @@ RGBController_SapphireNitroGlowV1::RGBController_SapphireNitroGlowV1(SapphireNit { controller = controller_ptr; - name = "Sapphire Nitro Glow V1 Device"; + name = controller->GetDeviceName(); vendor = "Sapphire"; description = "Sapphire Nitro Glow V1 Device"; location = controller->GetDeviceLocation(); diff --git a/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller/RGBController_SapphireNitroGlowV1.h b/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller/RGBController_SapphireNitroGlowV1.h new file mode 100644 index 00000000..cc5dc64d --- /dev/null +++ b/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller/RGBController_SapphireNitroGlowV1.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_SapphireNitroGlowV1.h | +| | +| RGBController for Sapphire Nitro Glow V1 | +| | +| Adam Honse (CalcProgrammer1) 15 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SapphireNitroGlowV1Controller.h" + +class RGBController_SapphireNitroGlowV1 : public RGBController +{ +public: + RGBController_SapphireNitroGlowV1(SapphireNitroGlowV1Controller* controller_ptr); + ~RGBController_SapphireNitroGlowV1(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + SapphireNitroGlowV1Controller* controller; + + void ReadConfiguration(); +}; diff --git a/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller/SapphireNitroGlowV1Controller.cpp b/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller/SapphireNitroGlowV1Controller.cpp new file mode 100644 index 00000000..960fb53c --- /dev/null +++ b/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller/SapphireNitroGlowV1Controller.cpp @@ -0,0 +1,81 @@ +/*---------------------------------------------------------*\ +| SapphireNitroGlowV1Controller.cpp | +| | +| Driver for Sapphire Nitro Glow V1 | +| | +| Adam Honse (CalcProgrammer1) 15 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "SapphireNitroGlowV1Controller.h" + +SapphireNitroGlowV1Controller::SapphireNitroGlowV1Controller(i2c_smbus_interface* bus, sapphire_dev_id dev, std::string dev_name) +{ + this->bus = bus; + this->dev = dev; + this->name = dev_name; +} + +SapphireNitroGlowV1Controller::~SapphireNitroGlowV1Controller() +{ + +} + +std::string SapphireNitroGlowV1Controller::GetDeviceLocation() +{ + std::string return_string(bus->device_name); + char addr[5]; + snprintf(addr, 5, "0x%02X", dev); + return_string.append(", address "); + return_string.append(addr); + return("I2C: " + return_string); +} + +std::string SapphireNitroGlowV1Controller::GetDeviceName() +{ + return(name); +} + +unsigned char SapphireNitroGlowV1Controller::GetRed() +{ + return(bus->i2c_smbus_read_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_RED)); +} + +unsigned char SapphireNitroGlowV1Controller::GetGreen() +{ + return(bus->i2c_smbus_read_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_GREEN)); +} + +unsigned char SapphireNitroGlowV1Controller::GetBlue() +{ + return(bus->i2c_smbus_read_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_BLUE)); +} + +void SapphireNitroGlowV1Controller::SetColor(unsigned char red, unsigned char green, unsigned char blue) +{ + bus->i2c_smbus_write_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_RED, red); + bus->i2c_smbus_write_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_GREEN, green); + bus->i2c_smbus_write_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_BLUE, blue); +} + +unsigned char SapphireNitroGlowV1Controller::GetMode() +{ + return(bus->i2c_smbus_read_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_MODE)); +} + +void SapphireNitroGlowV1Controller::SetMode(unsigned char mode) +{ + bus->i2c_smbus_write_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_MODE, mode); +} + +unsigned char SapphireNitroGlowV1Controller::GetBrightness() +{ + return(bus->i2c_smbus_read_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_BRIGHTNESS)); +} + +void SapphireNitroGlowV1Controller::SetBrightness(unsigned char brightness) +{ + bus->i2c_smbus_write_byte_data(dev, SAPPHIRE_NITRO_GLOW_V1_REG_BRIGHTNESS, brightness); +} diff --git a/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller/SapphireNitroGlowV1Controller.h b/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller/SapphireNitroGlowV1Controller.h new file mode 100644 index 00000000..cfe6ee33 --- /dev/null +++ b/Controllers/SapphireGPUController/SapphireNitroGlowV1Controller/SapphireNitroGlowV1Controller.h @@ -0,0 +1,66 @@ +/*---------------------------------------------------------*\ +| SapphireNitroGlowV1Controller.h | +| | +| Driver for Sapphire Nitro Glow V1 | +| | +| Adam Honse (CalcProgrammer1) 15 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "i2c_smbus.h" + +#define SAPPHITE_NITRO_GLOW_V1_BRIGHTNESS_MIN 2; +#define SAPPHITE_NITRO_GLOW_V1_BRIGHTNESS_MAX 0; + +typedef unsigned char sapphire_dev_id; + +enum +{ + SAPPHIRE_NITRO_GLOW_V1_REG_MODE = 0x00, + SAPPHIRE_NITRO_GLOW_V1_REG_BRIGHTNESS = 0x01, + SAPPHIRE_NITRO_GLOW_V1_REG_RED = 0x03, + SAPPHIRE_NITRO_GLOW_V1_REG_GREEN = 0x04, + SAPPHIRE_NITRO_GLOW_V1_REG_BLUE = 0x05, +}; + +enum +{ + SAPPHIRE_NITRO_GLOW_V1_MODE_SAPPHIRE_BLUE = 0x00, + SAPPHIRE_NITRO_GLOW_V1_MODE_RAINBOW = 0x01, + SAPPHIRE_NITRO_GLOW_V1_MODE_BOARD_TEMPERATURE = 0x02, + SAPPHIRE_NITRO_GLOW_V1_MODE_FAN_SPEED = 0x03, + SAPPHIRE_NITRO_GLOW_V1_MODE_CUSTOM = 0x04, + SAPPHIRE_NITRO_GLOW_V1_MODE_OFF = 0x05, +}; + +class SapphireNitroGlowV1Controller +{ +public: + SapphireNitroGlowV1Controller(i2c_smbus_interface* bus, sapphire_dev_id dev, std::string dev_name); + ~SapphireNitroGlowV1Controller(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + + unsigned char GetRed(); + unsigned char GetGreen(); + unsigned char GetBlue(); + + void SetColor(unsigned char red, unsigned char green, unsigned char blue); + + unsigned char GetMode(); + void SetMode(unsigned char mode); + + unsigned char GetBrightness(); + void SetBrightness(unsigned char brightness); + +private: + i2c_smbus_interface* bus; + sapphire_dev_id dev; + std::string name; +}; diff --git a/Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV3.cpp b/Controllers/SapphireGPUController/SapphireNitroGlowV3Controller/RGBController_SapphireNitroGlowV3.cpp similarity index 86% rename from Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV3.cpp rename to Controllers/SapphireGPUController/SapphireNitroGlowV3Controller/RGBController_SapphireNitroGlowV3.cpp index b4826e71..90eb1b05 100644 --- a/Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV3.cpp +++ b/Controllers/SapphireGPUController/SapphireNitroGlowV3Controller/RGBController_SapphireNitroGlowV3.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_SapphireNitroGlowV3.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Sapphire Nitro Glow V3 GPU Driver | -| | -| K900 2/3/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_SapphireNitroGlowV3.cpp | +| | +| RGBController for Sapphire Nitro Glow V3 | +| | +| K900 03 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_SapphireNitroGlowV3.h" @@ -24,7 +26,7 @@ RGBController_SapphireNitroGlowV3::RGBController_SapphireNitroGlowV3(SapphireNit { controller = controller_ptr; - name = "Sapphire Nitro Glow V3 Device"; + name = controller->GetDeviceName(); vendor = "Sapphire"; description = "Sapphire Nitro Glow V3 Device"; location = controller->GetDeviceLocation(); @@ -80,6 +82,13 @@ RGBController_SapphireNitroGlowV3::RGBController_SapphireNitroGlowV3(SapphireNit External.color_mode = MODE_COLORS_NONE; modes.push_back(External); + mode Off; + Off.name = "Off"; + Off.value = SAPPHIRE_NITRO_GLOW_V3_MODE_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + SetupZones(); ReadConfiguration(); @@ -159,7 +168,7 @@ void RGBController_SapphireNitroGlowV3::ReadConfiguration() break; case SAPPHIRE_NITRO_GLOW_V3_MODE_OFF: - active_mode = 0; + active_mode = 6; colors[0] = ToRGBColor(0, 0, 0); break; @@ -234,5 +243,11 @@ void RGBController_SapphireNitroGlowV3::DeviceUpdateMode() case SAPPHIRE_NITRO_GLOW_V3_MODE_EXTERNAL_CONTROL: controller->SetExternalControl(true); break; + + case SAPPHIRE_NITRO_GLOW_V3_MODE_OFF: + controller->SetExternalControl(false); + controller->SetColor(0, 0, 0); + controller->SetMode(mode.value); + break; } } diff --git a/Controllers/SapphireGPUController/SapphireNitroGlowV3Controller/RGBController_SapphireNitroGlowV3.h b/Controllers/SapphireGPUController/SapphireNitroGlowV3Controller/RGBController_SapphireNitroGlowV3.h new file mode 100644 index 00000000..edd683e7 --- /dev/null +++ b/Controllers/SapphireGPUController/SapphireNitroGlowV3Controller/RGBController_SapphireNitroGlowV3.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_SapphireNitroGlowV3.h | +| | +| RGBController for Sapphire Nitro Glow V3 | +| | +| K900 03 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SapphireNitroGlowV3Controller.h" + +class RGBController_SapphireNitroGlowV3 : public RGBController +{ +public: + RGBController_SapphireNitroGlowV3(SapphireNitroGlowV3Controller* controller_ptr); + ~RGBController_SapphireNitroGlowV3(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + SapphireNitroGlowV3Controller* controller; + + void ReadConfiguration(); +}; diff --git a/Controllers/SapphireGPUController/SapphireNitroGlowV3Controller.cpp b/Controllers/SapphireGPUController/SapphireNitroGlowV3Controller/SapphireNitroGlowV3Controller.cpp similarity index 82% rename from Controllers/SapphireGPUController/SapphireNitroGlowV3Controller.cpp rename to Controllers/SapphireGPUController/SapphireNitroGlowV3Controller/SapphireNitroGlowV3Controller.cpp index 2a2ce7d5..995fae9c 100644 --- a/Controllers/SapphireGPUController/SapphireNitroGlowV3Controller.cpp +++ b/Controllers/SapphireGPUController/SapphireNitroGlowV3Controller/SapphireNitroGlowV3Controller.cpp @@ -1,18 +1,21 @@ -/*-----------------------------------------*\ -| SapphireNitroGlowV3Controller.cpp | -| | -| Driver for Sapphire Nitro Glow V3 GPU | -| RGB lighting controller | -| | -| K900 2/3/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| SapphireNitroGlowV3Controller.cpp | +| | +| Driver for Sapphire Nitro Glow V3 | +| | +| K900 03 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "SapphireNitroGlowV3Controller.h" -SapphireNitroGlowV3Controller::SapphireNitroGlowV3Controller(i2c_smbus_interface* bus, sapphire_dev_id dev) +SapphireNitroGlowV3Controller::SapphireNitroGlowV3Controller(i2c_smbus_interface* bus, sapphire_dev_id dev, std::string dev_name) { - this->bus = bus; - this->dev = dev; + this->bus = bus; + this->dev = dev; + this->name = dev_name; } SapphireNitroGlowV3Controller::~SapphireNitroGlowV3Controller() @@ -30,6 +33,11 @@ std::string SapphireNitroGlowV3Controller::GetDeviceLocation() return("I2C: " + return_string); } +std::string SapphireNitroGlowV3Controller::GetDeviceName() +{ + return(name); +} + unsigned char SapphireNitroGlowV3Controller::GetRed() { return(bus->i2c_smbus_read_byte_data(dev, SAPPHIRE_NITRO_GLOW_V3_REG_RED)); @@ -74,7 +82,7 @@ void SapphireNitroGlowV3Controller::SetExternalControl(bool enabled) unsigned char SapphireNitroGlowV3Controller::GetBrightness() { - return(bus->i2c_smbus_read_byte_data(dev, SAPPHIRE_NITRO_GLOW_V3_REG_MODE)); + return(bus->i2c_smbus_read_byte_data(dev, SAPPHIRE_NITRO_GLOW_V3_REG_BRIGHTNESS)); } void SapphireNitroGlowV3Controller::SetBrightness(unsigned char brightness) diff --git a/Controllers/SapphireGPUController/SapphireNitroGlowV3Controller.h b/Controllers/SapphireGPUController/SapphireNitroGlowV3Controller/SapphireNitroGlowV3Controller.h similarity index 79% rename from Controllers/SapphireGPUController/SapphireNitroGlowV3Controller.h rename to Controllers/SapphireGPUController/SapphireNitroGlowV3Controller/SapphireNitroGlowV3Controller.h index 2ee36f2f..793ce93e 100644 --- a/Controllers/SapphireGPUController/SapphireNitroGlowV3Controller.h +++ b/Controllers/SapphireGPUController/SapphireNitroGlowV3Controller/SapphireNitroGlowV3Controller.h @@ -1,17 +1,19 @@ -/*-----------------------------------------*\ -| SapphireNitroGlowV3Controller.h | -| | -| Definitions and types for Sapphire Nitro | -| Glow V3 GPU RGB lighting controller | -| | -| K900 2/3/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| SapphireNitroGlowV3Controller.h | +| | +| Driver for Sapphire Nitro Glow V3 | +| | +| K900 03 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" -#pragma once - typedef unsigned char sapphire_dev_id; enum @@ -46,10 +48,11 @@ enum class SapphireNitroGlowV3Controller { public: - SapphireNitroGlowV3Controller(i2c_smbus_interface* bus, sapphire_dev_id dev); + SapphireNitroGlowV3Controller(i2c_smbus_interface* bus, sapphire_dev_id dev, std::string dev_name); ~SapphireNitroGlowV3Controller(); std::string GetDeviceLocation(); + std::string GetDeviceName(); unsigned char GetRed(); unsigned char GetGreen(); @@ -84,5 +87,5 @@ public: private: i2c_smbus_interface* bus; sapphire_dev_id dev; - + std::string name; }; diff --git a/Controllers/SeagateController/RGBController_Seagate.cpp b/Controllers/SeagateController/RGBController_Seagate.cpp new file mode 100644 index 00000000..e2391dd6 --- /dev/null +++ b/Controllers/SeagateController/RGBController_Seagate.cpp @@ -0,0 +1,171 @@ +/*---------------------------------------------------------*\ +| RGBController_Seagate.cpp | +| | +| RGBController for Seagate | +| | +| Adam Honse (CalcProgrammer1) 08 Nov 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_Seagate.h" + +/**------------------------------------------------------------------*\ + @name Seagate + @category Storage + @type SCSI + @save :white_check_mark: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectSeagateControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_Seagate::RGBController_Seagate(SeagateController* controller_ptr) +{ + controller = controller_ptr; + + name = "Seagate Device"; + vendor = "Seagate"; + type = DEVICE_TYPE_STORAGE; + description = "Seagate Device"; + location = controller->GetLocation(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = SEAGATE_MODE_STATIC; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Blink; + Blink.name = "Flashing"; + Blink.value = SEAGATE_MODE_BLINK; + Blink.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + Blink.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Blink); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = SEAGATE_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + Breathing.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Breathing); + + mode Spectrum; + Spectrum.name = "Spectrum Cycle"; + Spectrum.value = SEAGATE_MODE_SPECTRUM; + Spectrum.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_MANUAL_SAVE; + Spectrum.color_mode = MODE_COLORS_RANDOM; + modes.push_back(Spectrum); + + SetupZones(); +} + +RGBController_Seagate::~RGBController_Seagate() +{ + delete controller; +} + +void RGBController_Seagate::SetupZones() +{ + zone led_zone; + led_zone.name = "LED Strip"; + led_zone.type = ZONE_TYPE_LINEAR; + led_zone.leds_min = 6; + led_zone.leds_max = 6; + led_zone.leds_count = 6; + led_zone.matrix_map = NULL; + zones.push_back(led_zone); + + for(unsigned int led_idx = 0; led_idx < zones[0].leds_count; led_idx++) + { + led new_led; + new_led.name = "LED Strip LED"; + + leds.push_back(new_led); + } + + SetupColors(); +} + +void RGBController_Seagate::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_Seagate::DeviceUpdateLEDs() +{ + for(unsigned int led_idx = 0; led_idx < leds.size(); led_idx++) + { + UpdateSingleLED(led_idx); + } +} + +void RGBController_Seagate::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_Seagate::UpdateSingleLED(int led) +{ + unsigned char red = RGBGetRValue(colors[led]); + unsigned char grn = RGBGetGValue(colors[led]); + unsigned char blu = RGBGetBValue(colors[led]); + + switch(modes[active_mode].value) + { + case SEAGATE_MODE_STATIC: + controller->SetLEDStatic(led, red, grn, blu, false); + break; + + case SEAGATE_MODE_BLINK: + controller->SetLEDBlink(led, red, grn, blu, false); + break; + + case SEAGATE_MODE_BREATHING: + controller->SetLEDBreathing(led, red, grn, blu, false); + break; + + case SEAGATE_MODE_SPECTRUM: + controller->SetLEDsSpectrum(led, false); + break; + } +} + +void RGBController_Seagate::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} + +void RGBController_Seagate::DeviceSaveMode() +{ + for(unsigned int led_idx = 0; led_idx < leds.size(); led_idx++) + { + unsigned char red = RGBGetRValue(colors[led_idx]); + unsigned char grn = RGBGetGValue(colors[led_idx]); + unsigned char blu = RGBGetBValue(colors[led_idx]); + + switch(modes[active_mode].value) + { + case SEAGATE_MODE_STATIC: + controller->SetLEDStatic(led_idx, red, grn, blu, true); + break; + + case SEAGATE_MODE_BLINK: + controller->SetLEDBlink(led_idx, red, grn, blu, true); + break; + + case SEAGATE_MODE_BREATHING: + controller->SetLEDBreathing(led_idx, red, grn, blu, true); + break; + + case SEAGATE_MODE_SPECTRUM: + controller->SetLEDsSpectrum(led_idx, true); + break; + } + } +} diff --git a/Controllers/SeagateController/RGBController_Seagate.h b/Controllers/SeagateController/RGBController_Seagate.h new file mode 100644 index 00000000..ed5cc65d --- /dev/null +++ b/Controllers/SeagateController/RGBController_Seagate.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------*\ +| RGBController_Seagate.h | +| | +| RGBController for Seagate | +| | +| Adam Honse (CalcProgrammer1) 08 Nov 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SeagateController.h" + +class RGBController_Seagate : public RGBController +{ +public: + RGBController_Seagate(SeagateController* controller_ptr); + ~RGBController_Seagate(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + + void DeviceSaveMode(); + +private: + SeagateController* controller; +}; diff --git a/Controllers/SeagateController/SeagateController.cpp b/Controllers/SeagateController/SeagateController.cpp new file mode 100644 index 00000000..38feea1b --- /dev/null +++ b/Controllers/SeagateController/SeagateController.cpp @@ -0,0 +1,224 @@ +/*---------------------------------------------------------*\ +| SeagateController.cpp | +| | +| Driver for Seagate | +| | +| Adam Honse (CalcProgrammer1) 15 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "SeagateController.h" + +SeagateController::SeagateController(scsi_device* dev_handle, char* path) +{ + this->dev = dev_handle; + this->path = path; +} + +SeagateController::~SeagateController() +{ + scsi_close(dev); +} + +std::string SeagateController::GetLocation() +{ + std::string str(path.begin(), path.end()); + return("SCSI: " + str); +} + +void SeagateController::SetLEDBlink + ( + unsigned char led_id, + unsigned char r, + unsigned char g, + unsigned char b, + bool save + ) +{ + /*-----------------------------------------------------------------------------*\ + | Create buffer to hold RGB control data | + \*-----------------------------------------------------------------------------*/ + unsigned char data[0x10] = {0}; + data[0] = 0x10; /* size of data packet */ + data[1] = 0x00; + data[2] = 0x01; + data[3] = 0x09; + data[4] = 0x01; + data[5] = 0x06; + data[6] = led_id; + data[7] = SEAGATE_MODE_BLINK; + if(save) + { + data[8] = 0x03; /* 0x00 for no save, 0x03 for */ + /* save */ + } + else + { + data[8] = 0x00; + } + data[9] = 0x10; + data[10] = 0x10; + data[11] = r; + data[12] = g; + data[13] = b; + data[14] = 0xFF; + data[15] = 0xFF; + + /*-----------------------------------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------------------------------*/ + SendPacket(data, 0x10); +} + +void SeagateController::SetLEDBreathing + ( + unsigned char led_id, + unsigned char r, + unsigned char g, + unsigned char b, + bool save + ) +{ + /*-----------------------------------------------------------------------------*\ + | Create buffer to hold RGB control data | + \*-----------------------------------------------------------------------------*/ + unsigned char data[0x14] = {0}; + data[0] = 0x14; /* size of data packet */ + data[1] = 0x00; + data[2] = 0x01; + data[3] = 0x09; + data[4] = 0x01; + data[5] = 0x06; + data[6] = led_id; + data[7] = SEAGATE_MODE_BREATHING; + if(save) + { + data[8] = 0x03; /* 0x00 for no save, 0x03 for */ + /* save */ + } + else + { + data[8] = 0x00; + } + data[9] = 0x0F; + data[10] = 0x0F; + data[11] = 0x0F; + data[12] = 0x0F; + data[13] = r; + data[14] = g; + data[15] = b; + data[16] = 0xFF; + data[17] = 0xFF; + data[18] = 0xFF; + data[19] = 0x00; + + /*-----------------------------------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------------------------------*/ + SendPacket(data, 0x14); +} + +void SeagateController::SetLEDsSpectrum + ( + unsigned char led_id, + bool /*save*/ + ) +{ + /*-----------------------------------------------------------------------------*\ + | Create buffer to hold RGB control data | + \*-----------------------------------------------------------------------------*/ + unsigned char data[0x0A] = {0}; + data[0] = 0x0A; /* size of data packet */ + data[1] = 0x00; + data[2] = 0x01; + data[3] = 0x09; + data[4] = 0x01; + data[5] = 0x06; + data[6] = led_id; + data[7] = SEAGATE_MODE_SPECTRUM; + data[8] = 0x02; + data[9] = 0xB4; + + /*-----------------------------------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------------------------------*/ + SendPacket(data, 0x0A); +} + +void SeagateController::SetLEDStatic + ( + unsigned char led_id, + unsigned char r, + unsigned char g, + unsigned char b, + bool save + ) +{ + /*-----------------------------------------------------------------------------*\ + | Create buffer to hold RGB control data | + \*-----------------------------------------------------------------------------*/ + unsigned char data[0x0E] = {0}; + data[0] = 0x0E; /* size of data packet */ + data[1] = 0x00; + data[2] = 0x01; + data[3] = 0x09; + data[4] = 0x01; + data[5] = 0x06; + data[6] = led_id; + data[7] = SEAGATE_MODE_STATIC; + if(save) + { + data[8] = 0x03; /* 0x00 for no save, 0x03 for */ + /* save */ + } + else + { + data[8] = 0x00; + } + data[9] = r; + data[10] = g; + data[11] = b; + data[12] = 0xFF; + data[13] = 0xFF; + + /*-----------------------------------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------------------------------*/ + SendPacket(data, 0x0E); +} + +void SeagateController::SendPacket + ( + unsigned char * packet, + unsigned char packet_sz + ) +{ + /*-----------------------------------------------------------------------------*\ + | Create buffer to hold CDB | + \*-----------------------------------------------------------------------------*/ + unsigned char cdb[12] = {0}; + cdb[0] = 0xD2; + cdb[1] = 0x53; /* S */ + cdb[2] = 0x65; /* e */ + cdb[3] = 0x74; /* t */ + cdb[4] = 0x4C; /* L */ + cdb[5] = 0x65; /* e */ + cdb[6] = 0x64; /* d */ + cdb[7] = 0x00; + cdb[8] = 0x00; + cdb[9] = 0x30; + cdb[10] = packet_sz; + cdb[11] = 0x00; + + /*-----------------------------------------------------------------------------*\ + | Create buffer to hold sense data | + \*-----------------------------------------------------------------------------*/ + unsigned char sense[32] = {0}; + + /*-----------------------------------------------------------------------------*\ + | Write SCSI packet | + \*-----------------------------------------------------------------------------*/ + scsi_write(dev, packet, packet_sz, cdb, 12, sense, 32); +} diff --git a/Controllers/SeagateController/SeagateController.h b/Controllers/SeagateController/SeagateController.h new file mode 100644 index 00000000..6f2fda72 --- /dev/null +++ b/Controllers/SeagateController/SeagateController.h @@ -0,0 +1,75 @@ +/*---------------------------------------------------------*\ +| SeagateController.h | +| | +| Driver for Seagate | +| | +| Adam Honse (CalcProgrammer1) 15 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "scsiapi.h" + +enum +{ + SEAGATE_MODE_STATIC = 0x01, /* Static mode */ + SEAGATE_MODE_BLINK = 0x02, /* Blink mode */ + SEAGATE_MODE_BREATHING = 0x03, /* Breathing mode */ + SEAGATE_MODE_SPECTRUM = 0x05, /* Spectrum mode */ +}; + +class SeagateController +{ +public: + SeagateController(scsi_device* dev_handle, char* path); + ~SeagateController(); + + std::string GetLocation(); + + void SetLEDBlink + ( + unsigned char led_id, + unsigned char r, + unsigned char g, + unsigned char b, + bool save + ); + + void SetLEDBreathing + ( + unsigned char led_id, + unsigned char r, + unsigned char g, + unsigned char b, + bool save + ); + + void SetLEDsSpectrum + ( + unsigned char led_id, + bool save + ); + + void SetLEDStatic + ( + unsigned char led_id, + unsigned char r, + unsigned char g, + unsigned char b, + bool save + ); + +private: + scsi_device* dev; + std::string path; + + void SendPacket + ( + unsigned char * packet, + unsigned char packet_sz + ); +}; diff --git a/Controllers/SeagateController/SeagateControllerDetect.cpp b/Controllers/SeagateController/SeagateControllerDetect.cpp new file mode 100644 index 00000000..fbbfcad4 --- /dev/null +++ b/Controllers/SeagateController/SeagateControllerDetect.cpp @@ -0,0 +1,50 @@ +/*---------------------------------------------------------*\ +| SeagateControllerDetect.cpp | +| | +| Detector for Seagate | +| | +| Adam Honse (CalcProgrammer1) 15 Jun 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "SeagateController.h" +#include "RGBController_Seagate.h" +#include "scsiapi.h" + +/******************************************************************************************\ +* * +* DetectSeagateControllers * +* * +* Detects Seagate FireCuda HDD devices * +* * +\******************************************************************************************/ + +void DetectSeagateControllers() +{ + scsi_device_info * info = scsi_enumerate(NULL, NULL); + + while(info) + { + if(strncmp(info->vendor, "Seagate", 7) == 0 && strncmp(info->product, "FireCuda HDD", 12) == 0) + { + scsi_device * dev = scsi_open_path(info->path); + + if(dev) + { + SeagateController* controller = new SeagateController(dev, info->path); + RGBController_Seagate* rgb_controller = new RGBController_Seagate(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + } + info = info->next; + } + + scsi_free_enumeration(info); + +} /* DetectSeagateControllers() */ + +REGISTER_DETECTOR("Seagate Firecuda HDD", DetectSeagateControllers); diff --git a/Controllers/SinowealthController/GenesisXenon200Controller/GenesisXenon200Controller.cpp b/Controllers/SinowealthController/GenesisXenon200Controller/GenesisXenon200Controller.cpp new file mode 100644 index 00000000..8f699f2c --- /dev/null +++ b/Controllers/SinowealthController/GenesisXenon200Controller/GenesisXenon200Controller.cpp @@ -0,0 +1,56 @@ +/*---------------------------------------------------------*\ +| GenesisXenon200Controller.cpp | +| | +| Driver for Genesis Xenon 200 mouse | +| | +| chrabonszcz Jul 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "GenesisXenon200Controller.h" + +GenesisXenon200Controller::GenesisXenon200Controller(hid_device* dev_handle, hid_device* cmd_dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + cmd_dev = cmd_dev_handle; + location = path; + name = dev_name; +} + +GenesisXenon200Controller::~GenesisXenon200Controller() +{ + +} + +std::string GenesisXenon200Controller::GetLocationString() +{ + return("HID: " + location); +} + +std::string GenesisXenon200Controller::GetNameString() +{ + return(name); +} + +void GenesisXenon200Controller::SaveMode(unsigned char mode, unsigned char value, RGBColor color) +{ + unsigned char usb_buf[154]; + + usb_buf[0] = 0x04; + + hid_get_feature_report(dev, usb_buf, 154); + + usb_buf[0x5D] = mode; + usb_buf[0x60] = value; + usb_buf[0x61] = RGBGetRValue(color); + usb_buf[0x62] = RGBGetGValue(color); + usb_buf[0x63] = RGBGetBValue(color); + + hid_send_feature_report(dev, usb_buf, 154); + + usb_buf[0] = 0x08; + hid_get_feature_report(cmd_dev, usb_buf, 9); + hid_send_feature_report(cmd_dev, usb_buf, 9); +} diff --git a/Controllers/SinowealthController/GenesisXenon200Controller/GenesisXenon200Controller.h b/Controllers/SinowealthController/GenesisXenon200Controller/GenesisXenon200Controller.h new file mode 100644 index 00000000..d733fe89 --- /dev/null +++ b/Controllers/SinowealthController/GenesisXenon200Controller/GenesisXenon200Controller.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------*\ +| GenesisXenon200Controller.h | +| | +| Driver for Genesis Xenon 200 mouse | +| | +| chrabonszcz Jul 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" + +class GenesisXenon200Controller +{ +public: + GenesisXenon200Controller(hid_device* dev_handle, hid_device* cmd_dev_handle, const char* path, std::string dev_name); + ~GenesisXenon200Controller(); + + std::string GetLocationString(); + std::string GetNameString(); + + void SaveMode(unsigned char mode, unsigned char value, RGBColor color); + +private: + hid_device* dev; + hid_device* cmd_dev; + std::string location; + std::string name; +}; diff --git a/Controllers/SinowealthController/GenesisXenon200Controller/RGBController_GenesisXenon200.cpp b/Controllers/SinowealthController/GenesisXenon200Controller/RGBController_GenesisXenon200.cpp new file mode 100644 index 00000000..ffaed0c9 --- /dev/null +++ b/Controllers/SinowealthController/GenesisXenon200Controller/RGBController_GenesisXenon200.cpp @@ -0,0 +1,145 @@ +/*---------------------------------------------------------*\ +| RGBController_GenesisXenon200.cpp | +| | +| RGBController for Genesis Xenon 200 mouse | +| | +| chrabonszcz Jul 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +/**------------------------------------------------------------------*\ + @name Genesis Xenon 200 + @type USB + @save :white_check_mark: + @direct :x: + @effects :white_check_mark: + @detectors DetectSinowealthMouse + @comment +\*-------------------------------------------------------------------*/ + +#include "RGBController_GenesisXenon200.h" + +RGBController_GenesisXenon200::RGBController_GenesisXenon200(GenesisXenon200Controller* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "Genesis"; + description = "Genesis Xenon 200 Mouse Device"; + type = DEVICE_TYPE_MOUSE; + location = controller->GetLocationString(); + + mode Static; + Static.name = "Static"; + Static.value = GENESIS_XENON_200_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.brightness = 1; + Static.brightness_min = 0; + Static.brightness_max = 2; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.resize(1); + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = GENESIS_XENON_200_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.speed = 1; + Breathing.speed_min = 0; + Breathing.speed_max = 2; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.colors.resize(1); + modes.push_back(Breathing); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = GENESIS_XENON_200_MODE_SPECTRUM_CYCLE; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.speed = 1; + SpectrumCycle.speed_min = 0; + SpectrumCycle.speed_max = 2; + modes.push_back(SpectrumCycle); + + mode Off; + Off.name = "Off"; + Off.value = GENESIS_XENON_200_MODE_OFF; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + SetupColors(); +} + +RGBController_GenesisXenon200::~RGBController_GenesisXenon200() +{ + delete controller; +} + +void RGBController_GenesisXenon200::DeviceUpdateMode() +{ + RGBColor color = 0; + unsigned char value = 0; + + if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC) + { + color = modes[active_mode].colors[0]; + } + + switch(modes[active_mode].value) + { + case GENESIS_XENON_200_MODE_STATIC: + + value = GENESIS_XENON_200_STATIC_BRIGHTESS_VALUES[modes[active_mode].brightness]; + break; + + case GENESIS_XENON_200_MODE_BREATHING: + + value = GENESIS_XENON_200_BREATHING_SPEED_VALUES[modes[active_mode].speed]; + break; + + case GENESIS_XENON_200_MODE_SPECTRUM_CYCLE: + + value = GENESIS_XENON_200_SPECTRUM_CYCLE_SPEED_VALUES[modes[active_mode].speed]; + break; + + } + + controller->SaveMode(modes[active_mode].value, value, color); +} + +void RGBController_GenesisXenon200::DeviceUpdateLEDs() +{ + DeviceUpdateMode(); +} + +void RGBController_GenesisXenon200::DeviceSaveMode() +{ + +} + +void RGBController_GenesisXenon200::SetupZones() +{ + +} + +void RGBController_GenesisXenon200::ResizeZone(int /*zone*/, int /*new_size*/) +{ + +} + +void RGBController_GenesisXenon200::UpdateZoneLEDs(int /*zone*/) +{ + +} + +void RGBController_GenesisXenon200::UpdateSingleLED(int /*led*/) +{ + +} diff --git a/Controllers/SinowealthController/GenesisXenon200Controller/RGBController_GenesisXenon200.h b/Controllers/SinowealthController/GenesisXenon200Controller/RGBController_GenesisXenon200.h new file mode 100644 index 00000000..58c31e17 --- /dev/null +++ b/Controllers/SinowealthController/GenesisXenon200Controller/RGBController_GenesisXenon200.h @@ -0,0 +1,45 @@ +/*---------------------------------------------------------*\ +| RGBController_GenesisXenon200.h | +| | +| RGBController for Genesis Xenon 200 mouse | +| | +| chrabonszcz Jul 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "GenesisXenon200Controller.h" +#include "RGBController.h" + +#define GENESIS_XENON_200_MODE_STATIC 0x18 +#define GENESIS_XENON_200_MODE_BREATHING 0x12 +#define GENESIS_XENON_200_MODE_SPECTRUM_CYCLE 0x14 +#define GENESIS_XENON_200_MODE_OFF 0x11 + +const unsigned char GENESIS_XENON_200_STATIC_BRIGHTESS_VALUES[] {0x11, 0x51, 0xA1}; +const unsigned char GENESIS_XENON_200_BREATHING_SPEED_VALUES[] {0x51, 0x31, 0x11}; +const unsigned char GENESIS_XENON_200_SPECTRUM_CYCLE_SPEED_VALUES[] {0xC1, 0x81, 0x41}; + +class RGBController_GenesisXenon200 : public RGBController +{ +public: + RGBController_GenesisXenon200(GenesisXenon200Controller* controller_ptr); + ~RGBController_GenesisXenon200(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + GenesisXenon200Controller* controller; +}; diff --git a/Controllers/SinowealthController/RGBController_Sinowealth.cpp b/Controllers/SinowealthController/RGBController_Sinowealth.cpp deleted file mode 100644 index b6a958b7..00000000 --- a/Controllers/SinowealthController/RGBController_Sinowealth.cpp +++ /dev/null @@ -1,242 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_Sinowealth.cpp | -| | -| Definitions and types for Sinowealth | -| mice, including Glorious | -| | -| Niels Westphal (crashniels) 20/5/2020 | -\*-----------------------------------------*/ - -#include "RGBController_Sinowealth.h" - -/**------------------------------------------------------------------*\ - @name Sinowealth Mice - @category Mouse - @type USB - @save :robot: - @direct :x: - @effects :white_check_mark: - @detectors DetectSinowealthMouse - @comment -\*-------------------------------------------------------------------*/ - -RGBController_Sinowealth::RGBController_Sinowealth(SinowealthController* controller_ptr) -{ - controller = controller_ptr; - - name = "Sinowealth Device"; - type = DEVICE_TYPE_MOUSE; - description = "Sinowealth Device"; - location = controller->GetLocation(); - serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); - - mode Static; - Static.name = "Static"; - Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Static.color_mode = MODE_COLORS_PER_LED; - Static.value = GLORIOUS_MODE_STATIC; - modes.push_back(Static); - - mode Off; - Off.name = "Off"; - Off.flags = MODE_FLAG_AUTOMATIC_SAVE; - Off.color_mode = MODE_COLORS_NONE; - Off.value = GLORIOUS_MODE_OFF; - modes.push_back(Off); - - mode Rainbow; - Rainbow.name = "Glorious Mode"; - Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_AUTOMATIC_SAVE; - Rainbow.speed_min = GLORIOUS_SPEED_SLOW; - Rainbow.speed = GLORIOUS_SPEED_NORMAL; - Rainbow.speed_max = GLORIOUS_SPEED_FAST; - Rainbow.direction = MODE_DIRECTION_UP; - Rainbow.color_mode = MODE_COLORS_NONE; - Rainbow.value = GLORIOUS_MODE_RAINBOW; - modes.push_back(Rainbow); - - mode SpectrumBreathing; - SpectrumBreathing.name = "Seemless Breathing"; - SpectrumBreathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - SpectrumBreathing.speed_min = GLORIOUS_SPEED_SLOW; - SpectrumBreathing.speed = GLORIOUS_SPEED_NORMAL; - SpectrumBreathing.speed_max = GLORIOUS_SPEED_FAST; - SpectrumBreathing.colors_min = 7; - SpectrumBreathing.colors_max = 7; - SpectrumBreathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - SpectrumBreathing.value = GLORIOUS_MODE_SPECTRUM_BREATING; - SpectrumBreathing.colors.resize(7); - modes.push_back(SpectrumBreathing); - - mode Chase; - Chase.name = "Tail"; - Chase.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; - Chase.speed_min = GLORIOUS_SPEED_SLOW; - Chase.speed = GLORIOUS_SPEED_NORMAL; - Chase.speed_max = GLORIOUS_SPEED_FAST; - Chase.color_mode = MODE_COLORS_NONE; - Chase.value = GLORIOUS_MODE_TAIL; - modes.push_back(Chase); - - mode SpectrumCycle; - SpectrumCycle.name = "Spectrum Cycle"; - SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; - SpectrumCycle.speed_min = GLORIOUS_SPEED_SLOW; - SpectrumCycle.speed = GLORIOUS_SPEED_NORMAL; - SpectrumCycle.speed_max = GLORIOUS_SPEED_FAST; - SpectrumCycle.color_mode = MODE_COLORS_NONE; - SpectrumCycle.value = GLORIOUS_MODE_SPECTRUM_CYCLE; - modes.push_back(SpectrumCycle); - - mode Flashing; - Flashing.name = "Rave"; - Flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Flashing.speed_min = GLORIOUS_SPEED_SLOW; - Flashing.speed = GLORIOUS_SPEED_NORMAL; - Flashing.speed_max = GLORIOUS_SPEED_FAST; - Flashing.colors_min = 2; - Flashing.colors_max = 2; - Flashing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Flashing.value = GLORIOUS_MODE_RAVE; - Flashing.colors.resize(2); - modes.push_back(Flashing); - - mode Epilepsy; - Epilepsy.name = "Epilepsy"; - Epilepsy.flags = MODE_FLAG_AUTOMATIC_SAVE; - Epilepsy.color_mode = MODE_COLORS_NONE; - Epilepsy.value = GLORIOUS_MODE_EPILEPSY; - modes.push_back(Epilepsy); - - mode RainbowSlow; - RainbowSlow.name = "Wave"; - RainbowSlow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; - RainbowSlow.speed_min = GLORIOUS_SPEED_SLOW; - RainbowSlow.speed = GLORIOUS_SPEED_NORMAL; - RainbowSlow.speed_max = GLORIOUS_SPEED_FAST; - RainbowSlow.color_mode = MODE_COLORS_NONE; - RainbowSlow.value = GLORIOUS_MODE_WAVE; - modes.push_back(RainbowSlow); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - Breathing.speed_min = GLORIOUS_MODE_BREATING_SLOW; - Breathing.speed = GLORIOUS_MODE_BREATING_NORMAL; - Breathing.speed_max = GLORIOUS_MODE_BREATING_FAST; - Breathing.colors_min = 1; - Breathing.colors_max = 1; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.value = GLORIOUS_MODE_BREATHING; - Breathing.colors.resize(1); - modes.push_back(Breathing); - - SetupZones(); -} - -RGBController_Sinowealth::~RGBController_Sinowealth() -{ - delete controller; -} - -void RGBController_Sinowealth::SetupZones() -{ - /*---------------------------------------------------------*\ - | Create a single zone | - \*---------------------------------------------------------*/ - zone new_zone; - new_zone.name = "Mouse"; - new_zone.type = ZONE_TYPE_SINGLE; - new_zone.leds_min = controller->GetLEDCount(); - new_zone.leds_max = controller->GetLEDCount(); - new_zone.leds_count = controller->GetLEDCount(); - new_zone.matrix_map = NULL; - zones.push_back(new_zone); - - /*---------------------------------------------------------*\ - | Set up LEDs | - \*---------------------------------------------------------*/ - for(std::size_t led_idx = 0; led_idx < zones[0].leds_count; led_idx++) - { - led* new_led = new led(); - new_led->name = "Mouse LED"; - leds.push_back(*new_led); - } - - SetupColors(); -} - -void RGBController_Sinowealth::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_Sinowealth::DeviceUpdateLEDs() -{ - controller->SetLEDColor(&colors[0]); -} - -void RGBController_Sinowealth::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_Sinowealth::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_Sinowealth::DeviceUpdateMode() -{ - unsigned int direction = 0; - unsigned int speed = GLORIOUS_SPEED_NORMAL; - - if (modes[active_mode].value == GLORIOUS_MODE_STATIC) - { - - } - else - { - if (modes[active_mode].direction == MODE_DIRECTION_UP) - { - direction = GLORIOUS_DIRECTION_DOWN; - } - else - { - direction = GLORIOUS_DIRECTION_UP; - } - - if ((modes[active_mode].speed == GLORIOUS_SPEED_FAST) || - (modes[active_mode].speed == GLORIOUS_SPEED_SLOW) || - (modes[active_mode].speed == GLORIOUS_SPEED_NORMAL)) - { - speed = modes[active_mode].speed; - } - else - { - if ((modes[active_mode].speed == GLORIOUS_MODE_BREATING_FAST) || - (modes[active_mode].speed == GLORIOUS_MODE_BREATING_SLOW) || - (modes[active_mode].speed == GLORIOUS_MODE_BREATING_NORMAL)) - { - speed = modes[active_mode].speed; - } - else - { - speed = GLORIOUS_SPEED_NORMAL; - } - } - - if (modes[active_mode].color_mode == MODE_COLORS_NONE) - { - controller->SetMode(modes[active_mode].value, speed, direction, 0); - } - else - { - controller->SetMode(modes[active_mode].value, speed, direction, &modes[active_mode].colors[0]); - } - } -} - diff --git a/Controllers/SinowealthController/RGBController_Sinowealth.h b/Controllers/SinowealthController/RGBController_Sinowealth.h deleted file mode 100644 index 644ec5c5..00000000 --- a/Controllers/SinowealthController/RGBController_Sinowealth.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_Sinowealth.h | -| | -| Definitions and types for Sinowealth | -| mice, including Glorious | -| | -| Niels Westphal (crashniels) 20/5/2020 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "SinowealthController.h" - -class RGBController_Sinowealth : public RGBController -{ -public: - RGBController_Sinowealth(SinowealthController* controller_ptr); - ~RGBController_Sinowealth(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - -private: - SinowealthController* controller; -}; diff --git a/Controllers/SinowealthController/RGBController_Sinowealth1007.h b/Controllers/SinowealthController/RGBController_Sinowealth1007.h deleted file mode 100644 index 59697430..00000000 --- a/Controllers/SinowealthController/RGBController_Sinowealth1007.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-------------------------------------------*\ -| RGBController_Sinowealth1007.h | -| | -| Generic RGB Interface for Sinowealth | -| mice with PID 1007 and similar controllers | -| | -| Moon_darker (Vaker) 25.01.2022 | -\*-------------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "SinowealthController1007.h" - -class RGBController_Sinowealth1007 : public RGBController -{ -public: - RGBController_Sinowealth1007(SinowealthController1007* controller_ptr); - ~RGBController_Sinowealth1007(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - - -private: - SinowealthController1007* controller; -}; diff --git a/Controllers/SinowealthController/RGBController_SinowealthGMOW.cpp b/Controllers/SinowealthController/RGBController_SinowealthGMOW.cpp deleted file mode 100644 index 879813c7..00000000 --- a/Controllers/SinowealthController/RGBController_SinowealthGMOW.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/*-------------------------------------------*\ -| RGBController_GMOW.cpp | -| | -| Support for the Glorious Model O Wireless | -| | -| Matt Silva (thesilvanator) 05/2022 | -\*-------------------------------------------*/ - -/**------------------------------------------------------------------*\ - @name Sinowealth Glorious Model O Wireless - @type USB - @save :white_check_mark: - @direct :x: - @effects :white_check_mark: - @detectors DetectSinowealthMouse - @comment -\*-------------------------------------------------------------------*/ - -#include "RGBController_SinowealthGMOW.h" - -RGBController_GMOW::RGBController_GMOW(SinowealthGMOWController* controller_ptr) -{ - controller = controller_ptr; - - name = "Sinowealth Device"; - type = DEVICE_TYPE_MOUSE; - description = "Sinowealth Device"; - location = controller->GetLocation(); - serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); - - mode Off; - Off.name = "Off"; - Off.flags = MODE_FLAG_AUTOMATIC_SAVE; - Off.color_mode = MODE_COLORS_NONE; - Off.value = GMOW_MODE_OFF; - modes.push_back(Off); - - mode RainbowWave; - RainbowWave.name = "Rainbow Wave"; - RainbowWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - RainbowWave.speed_min = GMOW_SPEED1_MIN; - RainbowWave.speed = GMOW_SPEED1_MID; - RainbowWave.speed_max = GMOW_SPEED1_MAX; - RainbowWave.direction = MODE_DIRECTION_UP; - RainbowWave.color_mode = MODE_COLORS_NONE; - RainbowWave.brightness_min = GMOW_BRIGHTNESS_MIN; - RainbowWave.brightness = GMOW_BRIGHTNESS_MID; - RainbowWave.brightness_max = GMOW_BRIGHTNESS_MAX; - RainbowWave.value = GMOW_MODE_RAINBOW_WAVE; - modes.push_back(RainbowWave); - - mode SpectrumCycle; - SpectrumCycle.name = "Spectrum Cycle"; - SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - SpectrumCycle.speed_min = GMOW_SPEED1_MIN; - SpectrumCycle.speed = GMOW_SPEED1_MID; - SpectrumCycle.speed_max = GMOW_SPEED1_MAX; - SpectrumCycle.color_mode = MODE_COLORS_NONE; - SpectrumCycle.brightness_min = GMOW_BRIGHTNESS_MIN; - SpectrumCycle.brightness = GMOW_BRIGHTNESS_MID; - SpectrumCycle.brightness_max = GMOW_BRIGHTNESS_MAX; - SpectrumCycle.value = GMOW_MODE_SPECTRUM_CYCLE; - modes.push_back(SpectrumCycle); - - mode CustomBreathing; - CustomBreathing.name = "Custom Breathing"; - CustomBreathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; - CustomBreathing.speed_min = GMOW_SPEED1_MIN; - CustomBreathing.speed = GMOW_SPEED1_MID; - CustomBreathing.speed_max = GMOW_SPEED1_MAX; - CustomBreathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - CustomBreathing.colors_min = 2; - CustomBreathing.colors_max = 7; - CustomBreathing.brightness_min = GMOW_BRIGHTNESS_MIN; - CustomBreathing.brightness = GMOW_BRIGHTNESS_MID; - CustomBreathing.brightness_max = GMOW_BRIGHTNESS_MAX; - CustomBreathing.value = GMOW_MODE_CUSTOM_BREATHING; - CustomBreathing.colors.resize(7); - modes.push_back(CustomBreathing); - - mode Static; - Static.name = "Static"; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; - Static.colors_min = 1; - Static.colors_max = 1; - Static.brightness_min = GMOW_BRIGHTNESS_MIN; - Static.brightness = GMOW_BRIGHTNESS_MID; - Static.brightness_max = GMOW_BRIGHTNESS_MAX; - Static.value = GMOW_MODE_STATIC; - Static.colors.resize(1); - modes.push_back(Static); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Breathing.speed_min = GMOW_SPEED1_MIN; - Breathing.speed = GMOW_SPEED1_MID; - Breathing.speed_max = GMOW_SPEED1_MAX; - Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; - Breathing.colors_min = 1; - Breathing.colors_max = 1; - Breathing.brightness_min = GMOW_BRIGHTNESS_MIN; - Breathing.brightness = GMOW_BRIGHTNESS_MID; - Breathing.brightness_max = GMOW_BRIGHTNESS_MAX; - Breathing.value = GMOW_MODE_BREATHING; - Breathing.colors.resize(1); - modes.push_back(Breathing); - - mode Tail; - Tail.name = "Tail"; - Tail.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Tail.speed_min = GMOW_SPEED1_MIN; - Tail.speed = GMOW_SPEED1_MID; - Tail.speed_max = GMOW_SPEED1_MAX; - Tail.color_mode = MODE_COLORS_NONE; - Tail.brightness_min = GMOW_BRIGHTNESS_MIN; - Tail.brightness = GMOW_BRIGHTNESS_MID; - Tail.brightness_max = GMOW_BRIGHTNESS_MAX; - Tail.value = GMOW_MODE_TAIL; - modes.push_back(Tail); - - mode Rave; - Rave.name = "Rave"; - Rave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Rave.speed_min = GMOW_SPEED2_MIN; - Rave.speed = GMOW_SPEED2_MID; - Rave.speed_max = GMOW_SPEED2_MAX; - Rave.color_mode = MODE_COLORS_MODE_SPECIFIC; - Rave.colors_min = 1; - Rave.colors_max = 2; - Rave.brightness_min = GMOW_BRIGHTNESS_MIN; - Rave.brightness = GMOW_BRIGHTNESS_MID; - Rave.brightness_max = GMOW_BRIGHTNESS_MAX; - Rave.value = GMOW_MODE_RAVE; - Rave.colors.resize(2); - modes.push_back(Rave); - - mode Wave; - Wave.name = "Wave"; - Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Wave.speed_min = GMOW_SPEED2_MIN; - Wave.speed = GMOW_SPEED2_MID; - Wave.speed_max = GMOW_SPEED2_MAX; - Wave.color_mode = MODE_COLORS_NONE; - Wave.brightness_min = GMOW_BRIGHTNESS_MIN; - Wave.brightness = GMOW_BRIGHTNESS_MID; - Wave.brightness_max = GMOW_BRIGHTNESS_MAX; - Wave.value = GMOW_MODE_WAVE; - modes.push_back(Wave); - - SetupZones(); -} - -RGBController_GMOW::~RGBController_GMOW() -{ - delete controller; -} - -void RGBController_GMOW::SetupZones() -{ - -} - -void RGBController_GMOW::ResizeZone(int /*zone*/, int /*new_size*/) -{ - -} - -void RGBController_GMOW::DeviceUpdateLEDs() -{ - -} - -void RGBController_GMOW::UpdateZoneLEDs(int /*zone*/) -{ - -} - -void RGBController_GMOW::UpdateSingleLED(int /*led*/) -{ - -} - -void RGBController_GMOW::DeviceUpdateMode() -{ - mode curr = modes[active_mode]; - controller->SetMode(active_mode, curr.speed,curr.brightness, curr.brightness, curr.colors.data(), curr.colors.size()); -} \ No newline at end of file diff --git a/Controllers/SinowealthController/RGBController_SinowealthGMOW.h b/Controllers/SinowealthController/RGBController_SinowealthGMOW.h deleted file mode 100644 index f299057a..00000000 --- a/Controllers/SinowealthController/RGBController_SinowealthGMOW.h +++ /dev/null @@ -1,31 +0,0 @@ -/*-------------------------------------------*\ -| RGBController_GMOW.h | -| | -| Support for the Glorious Model O Wireless | -| | -| Matt Silva (thesilvanator) 05/2022 | -\*-------------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "SinowealthGMOWController.h" - -class RGBController_GMOW : public RGBController -{ -public: - RGBController_GMOW(SinowealthGMOWController* sinowealth_ptr); - ~RGBController_GMOW(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - SinowealthGMOWController* controller; -}; diff --git a/Controllers/SinowealthController/RGBController_SinowealthKeyboard.cpp b/Controllers/SinowealthController/RGBController_SinowealthKeyboard.cpp deleted file mode 100644 index 4c0a7030..00000000 --- a/Controllers/SinowealthController/RGBController_SinowealthKeyboard.cpp +++ /dev/null @@ -1,479 +0,0 @@ -/*------------------------------------------*\ -| RGBController_SinowealthKeyboard.cpp | -| | -| Definitions and types for Sinowealth | -| Keyboard, Hopefully generic, this was | -| made spefically for FL eSports F11 KB | -| | -| Dmitri Kalinichenko (Dima-Kal) 23/06/2021 | -\*-----------------------------------------=*/ - -#include "RGBControllerKeyNames.h" -#include "RGBController_SinowealthKeyboard.h" - -#define NA 0xFFFFFFFF - -static unsigned int tkl_matrix_map[6][17] = - { { 8, NA, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, - { 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45}, - { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66}, - { 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 84, NA, NA, NA, NA}, - { 93, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 106, NA, NA, NA, 107, NA}, - { 113, 114, 115, NA, NA, NA, 118, NA, NA, NA, NA, 121, 122, 123, 127, 128, 129}}; - - -static const char *led_names_tkl[] = -{ - KEY_EN_ESCAPE, - KEY_EN_F1, - KEY_EN_F2, - KEY_EN_F3, - KEY_EN_F4, - KEY_EN_F5, - KEY_EN_F6, - KEY_EN_F7, - KEY_EN_F8, - KEY_EN_F9, - KEY_EN_F10, - KEY_EN_F11, - KEY_EN_F12, - KEY_EN_PRINT_SCREEN, - KEY_EN_SCROLL_LOCK, - "Key: Pause", - - KEY_EN_BACK_TICK, - KEY_EN_1, - KEY_EN_2, - KEY_EN_3, - KEY_EN_4, - KEY_EN_5, - KEY_EN_6, - KEY_EN_7, - KEY_EN_8, - KEY_EN_9, - KEY_EN_0, - KEY_EN_MINUS, - KEY_EN_EQUALS, - KEY_EN_BACKSPACE, - KEY_EN_INSERT, - KEY_EN_HOME, - KEY_EN_PAGE_UP, - - KEY_EN_TAB, - KEY_EN_Q, - KEY_EN_W, - KEY_EN_E, - KEY_EN_R, - KEY_EN_T, - KEY_EN_Y, - KEY_EN_U, - KEY_EN_I, - KEY_EN_O, - KEY_EN_P, - KEY_EN_LEFT_BRACKET, - KEY_EN_RIGHT_BRACKET, - KEY_EN_ANSI_BACK_SLASH, - KEY_EN_DELETE, - KEY_EN_END, - KEY_EN_PAGE_DOWN, - - KEY_EN_CAPS_LOCK, - KEY_EN_A, - KEY_EN_S, - KEY_EN_D, - KEY_EN_F, - KEY_EN_G, - KEY_EN_H, - KEY_EN_J, - KEY_EN_K, - KEY_EN_L, - KEY_EN_SEMICOLON, - KEY_EN_QUOTE, - KEY_EN_ANSI_ENTER, - - KEY_EN_LEFT_SHIFT, - KEY_EN_Z, - KEY_EN_X, - KEY_EN_C, - KEY_EN_V, - KEY_EN_B, - KEY_EN_N, - KEY_EN_M, - KEY_EN_COMMA, - KEY_EN_PERIOD, - KEY_EN_FORWARD_SLASH, - KEY_EN_RIGHT_SHIFT, - KEY_EN_UP_ARROW, - - KEY_EN_LEFT_CONTROL, - KEY_EN_LEFT_WINDOWS, - KEY_EN_LEFT_ALT, - KEY_EN_SPACE, - KEY_EN_RIGHT_CONTROL, - KEY_EN_RIGHT_ALT, - KEY_EN_RIGHT_WINDOWS, - KEY_EN_RIGHT_FUNCTION, - KEY_EN_LEFT_ARROW, - KEY_EN_DOWN_ARROW, - KEY_EN_RIGHT_ARROW, -}; - -/**------------------------------------------------------------------*\ - @name Sinowealth Keyboard - @category Keyboard - @type USB - @save :x: - @direct :x: - @effects :white_check_mark: - @detectors DetectSinowealthKeyboard - @comment -\*-------------------------------------------------------------------*/ - -RGBController_SinowealthKeyboard::RGBController_SinowealthKeyboard(SinowealthKeyboardController* controller_ptr) -{ - controller = controller_ptr; - - name = "Sinowealth Keyboard"; - type = DEVICE_TYPE_KEYBOARD; - description = "Sinowealth Keyboard"; - location = controller->GetLocation(); - serial = controller->GetSerialString(); - - mode Static; - Static.name = "Static"; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; - Static.value = MODE_STATIC; - Static.colors_min = 1; - Static.colors_max = 1; - Static.colors.resize(1); - modes.push_back(Static); - - mode Custom; - Custom.name = "Custom"; - Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Custom.color_mode = MODE_COLORS_PER_LED; - Custom.value = MODE_PER_KEY; - modes.push_back(Custom); - - mode Off; - Off.name = "Off"; - Off.flags = 0; - Off.color_mode = MODE_COLORS_NONE; - Off.value = MODE_OFF; - modes.push_back(Off); - - mode Respire; - Respire.name = "Respire"; - Respire.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Respire.speed_min = SPEED_SLOW; - Respire.speed = SPEED_NORMAL; - Respire.speed_max = SPEED_FASTEST; - Respire.color_mode = MODE_COLORS_RANDOM; - Respire.value = MODE_RESPIRE; - Respire.colors_min = 1; - Respire.colors_max = 1; - Respire.colors.resize(1); - modes.push_back(Respire); - - mode Rainbow; - Rainbow.name = "Rainbow"; - Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; - Rainbow.speed_min = SPEED_SLOW; - Rainbow.speed = SPEED_NORMAL; - Rainbow.speed_max = SPEED_FASTEST; - Rainbow.color_mode = MODE_COLORS_NONE; - Rainbow.value = MODE_RAINBOW; - modes.push_back(Rainbow); - - mode FlashAway; - FlashAway.name = "Flash Away"; - FlashAway.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - FlashAway.speed_min = SPEED_SLOW; - FlashAway.speed = SPEED_NORMAL; - FlashAway.speed_max = SPEED_FASTEST; - FlashAway.color_mode = MODE_COLORS_RANDOM; - FlashAway.value = MODE_FLASH_AWAY; - FlashAway.colors_min = 1; - FlashAway.colors_max = 1; - FlashAway.colors.resize(1); - modes.push_back(FlashAway); - - mode Raindrops; - Raindrops.name = "Raindrops"; - Raindrops.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Raindrops.speed_min = SPEED_SLOW; - Raindrops.speed = SPEED_NORMAL; - Raindrops.speed_max = SPEED_FASTEST; - Raindrops.color_mode = MODE_COLORS_RANDOM; - Raindrops.value = MODE_RAINDROPS; - Raindrops.colors_min = 1; - Raindrops.colors_max = 1; - Raindrops.colors.resize(1); - modes.push_back(Raindrops); - - mode RainbowWheel; - RainbowWheel.name = "Rainbow Wheel"; - RainbowWheel.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - RainbowWheel.speed_min = SPEED_SLOW; - RainbowWheel.speed = SPEED_NORMAL; - RainbowWheel.speed_max = SPEED_FASTEST; - RainbowWheel.color_mode = MODE_COLORS_RANDOM; - RainbowWheel.value = MODE_RAINBOW_WHEEL; - RainbowWheel.colors_min = 1; - RainbowWheel.colors_max = 1; - RainbowWheel.colors.resize(1); - modes.push_back(RainbowWheel); - - mode RipplesShining; - RipplesShining.name = "Ripples Shining"; - RipplesShining.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - RipplesShining.speed_min = SPEED_SLOW; - RipplesShining.speed = SPEED_NORMAL; - RipplesShining.speed_max = SPEED_FASTEST; - RipplesShining.color_mode = MODE_COLORS_RANDOM; - RipplesShining.value = MODE_RIPPLES_SHINING; - RipplesShining.colors_min = 1; - RipplesShining.colors_max = 1; - RipplesShining.colors.resize(1); - modes.push_back(RipplesShining); - - mode StarsTwinkle; - StarsTwinkle.name = "Stars Twinkle"; - StarsTwinkle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - StarsTwinkle.speed_min = SPEED_SLOW; - StarsTwinkle.speed = SPEED_NORMAL; - StarsTwinkle.speed_max = SPEED_FASTEST; - StarsTwinkle.color_mode = MODE_COLORS_RANDOM; - StarsTwinkle.value = MODE_STARS_TWINKLE; - StarsTwinkle.colors_min = 1; - StarsTwinkle.colors_max = 1; - StarsTwinkle.colors.resize(1); - modes.push_back(StarsTwinkle); - - mode ShadowDisappear; - ShadowDisappear.name = "Shadow Disappear"; - ShadowDisappear.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - ShadowDisappear.speed_min = SPEED_SLOW; - ShadowDisappear.speed = SPEED_NORMAL; - ShadowDisappear.speed_max = SPEED_FASTEST; - ShadowDisappear.color_mode = MODE_COLORS_RANDOM; - ShadowDisappear.value = MODE_SHADOW_DISAPPEAR; - ShadowDisappear.colors_min = 1; - ShadowDisappear.colors_max = 1; - ShadowDisappear.colors.resize(1); - modes.push_back(ShadowDisappear); - - mode RetroSnake; - RetroSnake.name = "Retro Snake"; - RetroSnake.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - RetroSnake.speed_min = SPEED_SLOW; - RetroSnake.speed = SPEED_NORMAL; - RetroSnake.speed_max = SPEED_FASTEST; - RetroSnake.color_mode = MODE_COLORS_RANDOM; - RetroSnake.value = MODE_RETRO_SNAKE; - RetroSnake.colors_min = 1; - RetroSnake.colors_max = 1; - RetroSnake.colors.resize(1); - modes.push_back(RetroSnake); - - mode NeonStream; - NeonStream.name = "Neon Stream"; - NeonStream.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - NeonStream.speed_min = SPEED_SLOW; - NeonStream.speed = SPEED_NORMAL; - NeonStream.speed_max = SPEED_FASTEST; - NeonStream.color_mode = MODE_COLORS_RANDOM; - NeonStream.value = MODE_NEON_STREAM; - NeonStream.colors_min = 1; - NeonStream.colors_max = 1; - NeonStream.colors.resize(1); - modes.push_back(NeonStream); - - mode Reaction; - Reaction.name = "Reaction"; - Reaction.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Reaction.speed_min = SPEED_SLOW; - Reaction.speed = SPEED_NORMAL; - Reaction.speed_max = SPEED_FASTEST; - Reaction.color_mode = MODE_COLORS_RANDOM; - Reaction.value = MODE_REACTION; - Reaction.colors_min = 1; - Reaction.colors_max = 1; - Reaction.colors.resize(1); - modes.push_back(Reaction); - - mode SineWave; - SineWave.name = "Sine Wave"; - SineWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - SineWave.speed_min = SPEED_SLOW; - SineWave.speed = SPEED_NORMAL; - SineWave.speed_max = SPEED_FASTEST; - SineWave.color_mode = MODE_COLORS_RANDOM; - SineWave.value = MODE_SINE_WAVE; - SineWave.colors_min = 1; - SineWave.colors_max = 1; - SineWave.colors.resize(1); - modes.push_back(SineWave); - - mode RetinueScanning; - RetinueScanning.name = "Retinue Scanning"; - RetinueScanning.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - RetinueScanning.speed_min = SPEED_SLOW; - RetinueScanning.speed = SPEED_NORMAL; - RetinueScanning.speed_max = SPEED_FASTEST; - RetinueScanning.color_mode = MODE_COLORS_RANDOM; - RetinueScanning.value = MODE_RETINUE_SCANNING; - RetinueScanning.colors_min = 1; - RetinueScanning.colors_max = 1; - RetinueScanning.colors.resize(1); - modes.push_back(RetinueScanning); - - mode RotatingWindmill; - RotatingWindmill.name = "Rotating Windmill"; - RotatingWindmill.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - RotatingWindmill.speed_min = SPEED_SLOW; - RotatingWindmill.speed = SPEED_NORMAL; - RotatingWindmill.speed_max = SPEED_FASTEST; - RotatingWindmill.color_mode = MODE_COLORS_RANDOM; - RotatingWindmill.value = MODE_ROTATING_WINDMILL; - RotatingWindmill.colors_min = 1; - RotatingWindmill.colors_max = 1; - RotatingWindmill.colors.resize(1); - modes.push_back(RotatingWindmill); - - mode ColorfulWaterfall; - ColorfulWaterfall.name = "Colorful Waterfall"; - ColorfulWaterfall.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; - ColorfulWaterfall.speed_min = SPEED_SLOW; - ColorfulWaterfall.speed = SPEED_NORMAL; - ColorfulWaterfall.speed_max = SPEED_FASTEST; - ColorfulWaterfall.color_mode = MODE_COLORS_NONE; - ColorfulWaterfall.value = MODE_COLORFUL_WATERFALL; - modes.push_back(ColorfulWaterfall); - - mode Blossoming; - Blossoming.name = "Blossoming"; - Blossoming.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; - Blossoming.speed_min = SPEED_SLOW; - Blossoming.speed = SPEED_NORMAL; - Blossoming.speed_max = SPEED_FASTEST; - Blossoming.color_mode = MODE_COLORS_NONE; - Blossoming.value = MODE_BLOSSOMING; - modes.push_back(Blossoming); - - mode RotatingStorm; - RotatingStorm.name = "Rotating Storm"; - RotatingStorm.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - RotatingStorm.speed_min = SPEED_SLOW; - RotatingStorm.speed = SPEED_NORMAL; - RotatingStorm.speed_max = SPEED_FASTEST; - RotatingStorm.color_mode = MODE_COLORS_RANDOM; - RotatingStorm.value = MODE_ROTATING_STORM; - RotatingStorm.colors_min = 1; - RotatingStorm.colors_max = 1; - RotatingStorm.colors.resize(1); - modes.push_back(RotatingStorm); - - mode Collision; - Collision.name = "Collision"; - Collision.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Collision.speed_min = SPEED_SLOW; - Collision.speed = SPEED_NORMAL; - Collision.speed_max = SPEED_FASTEST; - Collision.color_mode = MODE_COLORS_RANDOM; - Collision.value = MODE_COLLISION; - Collision.colors_min = 1; - Collision.colors_max = 1; - Collision.colors.resize(1); - modes.push_back(Collision); - - mode Perfect; - Perfect.name = "Perfect"; - Perfect.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Perfect.speed_min = SPEED_SLOW; - Perfect.speed = SPEED_NORMAL; - Perfect.speed_max = SPEED_FASTEST; - Perfect.color_mode = MODE_COLORS_RANDOM; - Perfect.value = MODE_PERFECT; - Perfect.colors_min = 1; - Perfect.colors_max = 1; - Perfect.colors.resize(1); - modes.push_back(Perfect); - - SetupZones(); -} - -RGBController_SinowealthKeyboard::~RGBController_SinowealthKeyboard() -{ - delete controller; -} - -void RGBController_SinowealthKeyboard::SetupZones() -{ - /*---------------------------------------------------------*\ - | Set up zones | - \*---------------------------------------------------------*/ - zone new_zone; - - new_zone.name = ZONE_EN_KEYBOARD; - new_zone.type = ZONE_TYPE_MATRIX; - new_zone.leds_min = 86; - new_zone.leds_max = 86; - new_zone.leds_count = 86; - new_zone.matrix_map = new matrix_map_type; - new_zone.matrix_map->height = 6; - new_zone.matrix_map->width = 17; - new_zone.matrix_map->map = (unsigned int *)&tkl_matrix_map; - - zones.push_back(new_zone); - - /*---------------------------------------------------------*\ - | Set up LEDs | - \*---------------------------------------------------------*/ - for(unsigned int led_idx = 0; led_idx < 86; led_idx++) - { - led new_led; - new_led.name = led_names_tkl[led_idx]; - leds.push_back(new_led); - } - - SetupColors(); -} - -void RGBController_SinowealthKeyboard::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_SinowealthKeyboard::DeviceUpdateLEDs() -{ - controller->SetLEDsDirect(colors); -} - -void RGBController_SinowealthKeyboard::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_SinowealthKeyboard::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_SinowealthKeyboard::DeviceUpdateMode() -{ - unsigned int brightness = BRIGHTNESS_FULL; - RGBColor* selected_color = (modes[active_mode].color_mode == MODE_COLORS_NONE) ? 0 : &modes[active_mode].colors[0]; - - if(modes[active_mode].value == MODE_STATIC) - { - controller->SetStaticColor(selected_color); - } - else - { - controller->SetMode(modes[active_mode].value, brightness, modes[active_mode].speed, modes[active_mode].color_mode); - } -} diff --git a/Controllers/SinowealthController/RGBController_Sinowealth1007.cpp b/Controllers/SinowealthController/Sinowealth1007Controller/RGBController_Sinowealth1007.cpp similarity index 90% rename from Controllers/SinowealthController/RGBController_Sinowealth1007.cpp rename to Controllers/SinowealthController/Sinowealth1007Controller/RGBController_Sinowealth1007.cpp index 4dbfcec0..23d5cdb1 100644 --- a/Controllers/SinowealthController/RGBController_Sinowealth1007.cpp +++ b/Controllers/SinowealthController/Sinowealth1007Controller/RGBController_Sinowealth1007.cpp @@ -1,11 +1,13 @@ -/*-------------------------------------------*\ -| RGBController_Sinowealth1007.cpp | -| | -| Generic RGB Interface for Sinowealth | -| mice with PID 1007 and similar controllers | -| | -| Moon_darker (Vaker) 02.02.2022 | -\*-------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Sinowealth1007.cpp | +| | +| RGBController for Sinowealth mice with PID 1007 | +| | +| Moon_darker (Vaker) 02 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_Sinowealth1007.h" @@ -33,14 +35,14 @@ static const char *led_names[] = RGBController_Sinowealth1007::RGBController_Sinowealth1007(SinowealthController1007* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "ZET Fury Pro Mouse Device"; - vendor = "ZET"; - type = DEVICE_TYPE_MOUSE; - description = "ZET Fury Pro Mouse Device"; - location = controller->GetLocation(); - serial = controller->GetSerialString(); + name = controller->GetName(); + vendor = "ZET"; + type = DEVICE_TYPE_MOUSE; + description = "ZET Fury Pro Mouse Device"; + location = controller->GetLocation(); + serial = controller->GetSerialString(); mode Custom; Custom.name = "Custom"; diff --git a/Controllers/SinowealthController/Sinowealth1007Controller/RGBController_Sinowealth1007.h b/Controllers/SinowealthController/Sinowealth1007Controller/RGBController_Sinowealth1007.h new file mode 100644 index 00000000..56d1713a --- /dev/null +++ b/Controllers/SinowealthController/Sinowealth1007Controller/RGBController_Sinowealth1007.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_Sinowealth1007.h | +| | +| RGBController for Sinowealth mice with PID 1007 | +| | +| Moon_darker (Vaker) 25 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SinowealthController1007.h" + +class RGBController_Sinowealth1007 : public RGBController +{ +public: + RGBController_Sinowealth1007(SinowealthController1007* controller_ptr); + ~RGBController_Sinowealth1007(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + SinowealthController1007* controller; +}; diff --git a/Controllers/SinowealthController/Sinowealth1007Controller/SinowealthController1007.cpp b/Controllers/SinowealthController/Sinowealth1007Controller/SinowealthController1007.cpp new file mode 100644 index 00000000..3e0cac55 --- /dev/null +++ b/Controllers/SinowealthController/Sinowealth1007Controller/SinowealthController1007.cpp @@ -0,0 +1,128 @@ +/*---------------------------------------------------------*\ +| SinowealthController1007.cpp | +| | +| Driver for Sinowealth mice with PID 1007 | +| | +| Moon_darker (Vaker) 02 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "LogManager.h" +#include "SinowealthController1007.h" +#include "StringUtils.h" + +SinowealthController1007::SinowealthController1007(hid_device* dev, char *_path, std::string dev_name) +{ + this->dev = dev; + this->location = _path; + this->name = dev_name; + + this->led_count = 7; + this->current_mode = ZET_FURY_PRO_MODE_CUSTOM + ZET_FURY_PRO_SPEED_DEF; + this->current_direction = ZET_FURY_PRO_DIR_RIGHT; + + memset(device_colors, 0x00, sizeof(device_colors)); +} + +SinowealthController1007::~SinowealthController1007() +{ + hid_close(dev); +} + +std::string SinowealthController1007::GetLocation() +{ + return("HID: " + location); +} + +std::string SinowealthController1007::GetName() +{ + return(name); +} + +unsigned int SinowealthController1007::GetLEDCount() +{ + return(led_count); +} + +std::string SinowealthController1007::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void SinowealthController1007::SetLEDColors(const std::vector& colors) +{ + memset(device_colors, 0x00, sizeof(device_colors)); + + unsigned int color_counter = 0; + for (RGBColor color: colors) + { + unsigned int pkt_pointer = (color_counter * 3); // 3 bytes per color + + device_colors[pkt_pointer] = RGBGetRValue(color); + device_colors[pkt_pointer + 1] = RGBGetGValue(color); + device_colors[pkt_pointer + 2] = RGBGetBValue(color); + + if (++color_counter == 7) break; + } + + SendPacket(); +} + +void SinowealthController1007::SetMode( + unsigned char mode, + unsigned char spd_or_lum, + unsigned char direction, + const std::vector& colors, + unsigned char random, + bool has_per_led_colors) +{ + current_mode = mode + (spd_or_lum ? spd_or_lum : ZET_FURY_PRO_SPEED_DEF); + current_direction = random ? random : direction; + + if (!has_per_led_colors) + { + memset(device_colors, 0x00, sizeof(device_colors)); + SetLEDColors(colors); + } +} + +void SinowealthController1007::SendPacket() +{ + if (GetProfile() < 0) return; + + unsigned char usb_buf[ZET_FURY_PRO_STATE_BUFFER_LENGTH]; + memcpy(usb_buf, device_configuration, sizeof(usb_buf)); + memcpy(usb_buf + 23, device_colors, sizeof(device_colors)); // colors are bytes 23-43 in RGB format counting from 0 + + usb_buf[21] = current_mode; + usb_buf[22] = current_direction; + + hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); +} + +int SinowealthController1007::GetProfile() +{ + int bytesReceived; + + memset(device_configuration, 0x00, ZET_FURY_PRO_STATE_BUFFER_LENGTH); + device_configuration[0] = 0x04; + + bytesReceived = hid_get_feature_report(dev, device_configuration, ZET_FURY_PRO_STATE_BUFFER_LENGTH); + if (bytesReceived < 0) + { + LOG_ERROR("[ZET Fury Pro] Error reading device configuration!"); + } + + return bytesReceived; +} diff --git a/Controllers/SinowealthController/Sinowealth1007Controller/SinowealthController1007.h b/Controllers/SinowealthController/Sinowealth1007Controller/SinowealthController1007.h new file mode 100644 index 00000000..ce15ec91 --- /dev/null +++ b/Controllers/SinowealthController/Sinowealth1007Controller/SinowealthController1007.h @@ -0,0 +1,84 @@ +/*---------------------------------------------------------*\ +| SinowealthController1007.h | +| | +| Driver for Sinowealth mice with PID 1007 | +| | +| Moon_darker (Vaker) 25 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define ZET_FURY_PRO_STATE_BUFFER_LENGTH 59 +#define ZET_FURY_PRO_COLOR_BUFFER_LENGTH 21 + +#define ZET_FURY_PRO_BRIGHTNESS_MIN 1 +#define ZET_FURY_PRO_BRIGHTNESS_MAX 9 +#define ZET_FURY_PRO_BRIGHTNESS_DEF 9 + +#define ZET_FURY_PRO_SPEED_MIN 1 +#define ZET_FURY_PRO_SPEED_MAX 3 +#define ZET_FURY_PRO_SPEED_DEF 2 + +enum +{ + ZET_FURY_PRO_MODE_OFF = 0x00, + ZET_FURY_PRO_MODE_RAINBOW = 0x10, + ZET_FURY_PRO_MODE_STATIC = 0x20, + ZET_FURY_PRO_MODE_BREATHING = 0x30, + ZET_FURY_PRO_MODE_PENDULUM = 0x40, + ZET_FURY_PRO_MODE_SPECTRUM = 0x50, + ZET_FURY_PRO_MODE_CUSTOM = 0x60, + ZET_FURY_PRO_MODE_TWO_COLORS = 0x70, + ZET_FURY_PRO_MODE_REACTIVE = 0x80, + ZET_FURY_PRO_MODE_FLICKER = 0x90, + ZET_FURY_PRO_MODE_RAIN = 0xA0, + ZET_FURY_PRO_MODE_SNAKE = 0xB0, +}; + +enum +{ + ZET_FURY_PRO_SUBMODE_SET_COLOR = 0x07, + ZET_FURY_PRO_SUBMODE_RANDOM = 0x80, +}; + +enum +{ + ZET_FURY_PRO_DIR_LEFT = 0x80, + ZET_FURY_PRO_DIR_RIGHT = 0x00, +}; + +class SinowealthController1007 +{ +public: + SinowealthController1007(hid_device* dev, char *_path, std::string dev_name); + ~SinowealthController1007(); + + unsigned int GetLEDCount(); + std::string GetLocation(); + std::string GetName(); + std::string GetSerialString(); + + void SetLEDColors(const std::vector& colors); + void SetMode(unsigned char mode, unsigned char spd_or_lum, unsigned char direction, const std::vector& colors, unsigned char random, bool has_per_led_colors); + int GetProfile(); + void SendPacket(); +private: + hid_device* dev; + + unsigned int led_count; + + unsigned char current_mode; + unsigned char current_direction; + unsigned char device_configuration[ZET_FURY_PRO_STATE_BUFFER_LENGTH]; + unsigned char device_colors[ZET_FURY_PRO_COLOR_BUFFER_LENGTH]; + + std::string location; + std::string name; +}; diff --git a/Controllers/SinowealthController/SinowealthController.h b/Controllers/SinowealthController/SinowealthController.h deleted file mode 100644 index 3ed338e7..00000000 --- a/Controllers/SinowealthController/SinowealthController.h +++ /dev/null @@ -1,81 +0,0 @@ -/*-----------------------------------------*\ -| SinowealthController.h | -| | -| Definitions and types for Sinowealth | -| mice, including Glorious | -| | -| Niels Westphal (crashniels) 20/5/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include - -#pragma once - -#define SINOWEALTH_CONFIG_SIZE 167 -#define SINOWEALTH_CONFIG_SIZE_MIN 131 -#define SINOWEALTH_CONFIG_REPORT_SIZE 520 -#define SINOWEALTH_COMMAND_REPORT_SIZE 6 - -enum -{ - GLORIOUS_MODE_OFF = 0x00, //does nothing - GLORIOUS_MODE_RAINBOW = 0x01, - GLORIOUS_MODE_STATIC = 0x02, - GLORIOUS_MODE_SPECTRUM_BREATING = 0x03, - GLORIOUS_MODE_TAIL = 0x04, - GLORIOUS_MODE_SPECTRUM_CYCLE = 0x05, - GLORIOUS_MODE_RAVE = 0x07, - GLORIOUS_MODE_EPILEPSY = 0x08, //not in the official software - GLORIOUS_MODE_WAVE = 0x09, - GLORIOUS_MODE_BREATHING = 0x0a, -}; - -enum -{ - GLORIOUS_SPEED_SLOW = 0x41, - GLORIOUS_SPEED_NORMAL = 0x42, - GLORIOUS_SPEED_FAST = 0x43, -}; - -enum -{ - GLORIOUS_DIRECTION_UP = 0x00, - GLORIOUS_DIRECTION_DOWN = 0x01, -}; - -enum -{ - GLORIOUS_MODE_BREATING_SLOW = 0x01, - GLORIOUS_MODE_BREATING_NORMAL = 0x02, - GLORIOUS_MODE_BREATING_FAST = 0x03, -}; - -class SinowealthController -{ -public: - SinowealthController(hid_device* dev_data_handle, hid_device* dev_cmd_handle, char *_path); //RGB, Command, path - ~SinowealthController(); - - unsigned int GetLEDCount(); - std::string GetLocation(); - std::string GetSerialString(); - std::string GetFirmwareVersion(); - - void SetLEDColor(RGBColor* color_buf); - void SetMode(unsigned char mode, unsigned char speed, unsigned char direction, RGBColor* color_buf); - int GetProfile(); -private: - hid_device* dev_cmd; - hid_device* dev_data; - - unsigned int led_count; - - unsigned char current_mode; - unsigned char current_speed; - unsigned char current_direction; - unsigned char device_configuration[SINOWEALTH_CONFIG_REPORT_SIZE]; - - std::string location; -}; diff --git a/Controllers/SinowealthController/SinowealthController/RGBController_Sinowealth.cpp b/Controllers/SinowealthController/SinowealthController/RGBController_Sinowealth.cpp new file mode 100644 index 00000000..52e11295 --- /dev/null +++ b/Controllers/SinowealthController/SinowealthController/RGBController_Sinowealth.cpp @@ -0,0 +1,244 @@ +/*---------------------------------------------------------*\ +| RGBController_Sinowealth.cpp | +| | +| RGBController for Sinowealth mice, including Glorious | +| | +| Niels Westphal (crashniels) 20 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_Sinowealth.h" + +/**------------------------------------------------------------------*\ + @name Sinowealth Mice + @category Mouse + @type USB + @save :robot: + @direct :x: + @effects :white_check_mark: + @detectors DetectSinowealthMouse + @comment +\*-------------------------------------------------------------------*/ + +RGBController_Sinowealth::RGBController_Sinowealth(SinowealthController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + type = DEVICE_TYPE_MOUSE; + description = "Sinowealth Device"; + location = controller->GetLocation(); + serial = controller->GetSerialString(); + version = controller->GetFirmwareVersion(); + + mode Static; + Static.name = "Static"; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Static.color_mode = MODE_COLORS_PER_LED; + Static.value = GLORIOUS_MODE_STATIC; + modes.push_back(Static); + + mode Off; + Off.name = "Off"; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + Off.value = GLORIOUS_MODE_OFF; + modes.push_back(Off); + + mode Rainbow; + Rainbow.name = "Glorious Mode"; + Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_UD | MODE_FLAG_AUTOMATIC_SAVE; + Rainbow.speed_min = GLORIOUS_SPEED_SLOW; + Rainbow.speed = GLORIOUS_SPEED_NORMAL; + Rainbow.speed_max = GLORIOUS_SPEED_FAST; + Rainbow.direction = MODE_DIRECTION_UP; + Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.value = GLORIOUS_MODE_RAINBOW; + modes.push_back(Rainbow); + + mode SpectrumBreathing; + SpectrumBreathing.name = "Seemless Breathing"; + SpectrumBreathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + SpectrumBreathing.speed_min = GLORIOUS_SPEED_SLOW; + SpectrumBreathing.speed = GLORIOUS_SPEED_NORMAL; + SpectrumBreathing.speed_max = GLORIOUS_SPEED_FAST; + SpectrumBreathing.colors_min = 7; + SpectrumBreathing.colors_max = 7; + SpectrumBreathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + SpectrumBreathing.value = GLORIOUS_MODE_SPECTRUM_BREATING; + SpectrumBreathing.colors.resize(7); + modes.push_back(SpectrumBreathing); + + mode Chase; + Chase.name = "Tail"; + Chase.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + Chase.speed_min = GLORIOUS_SPEED_SLOW; + Chase.speed = GLORIOUS_SPEED_NORMAL; + Chase.speed_max = GLORIOUS_SPEED_FAST; + Chase.color_mode = MODE_COLORS_NONE; + Chase.value = GLORIOUS_MODE_TAIL; + modes.push_back(Chase); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + SpectrumCycle.speed_min = GLORIOUS_SPEED_SLOW; + SpectrumCycle.speed = GLORIOUS_SPEED_NORMAL; + SpectrumCycle.speed_max = GLORIOUS_SPEED_FAST; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.value = GLORIOUS_MODE_SPECTRUM_CYCLE; + modes.push_back(SpectrumCycle); + + mode Flashing; + Flashing.name = "Rave"; + Flashing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Flashing.speed_min = GLORIOUS_SPEED_SLOW; + Flashing.speed = GLORIOUS_SPEED_NORMAL; + Flashing.speed_max = GLORIOUS_SPEED_FAST; + Flashing.colors_min = 2; + Flashing.colors_max = 2; + Flashing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Flashing.value = GLORIOUS_MODE_RAVE; + Flashing.colors.resize(2); + modes.push_back(Flashing); + + mode Epilepsy; + Epilepsy.name = "Epilepsy"; + Epilepsy.flags = MODE_FLAG_AUTOMATIC_SAVE; + Epilepsy.color_mode = MODE_COLORS_NONE; + Epilepsy.value = GLORIOUS_MODE_EPILEPSY; + modes.push_back(Epilepsy); + + mode RainbowSlow; + RainbowSlow.name = "Wave"; + RainbowSlow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + RainbowSlow.speed_min = GLORIOUS_SPEED_SLOW; + RainbowSlow.speed = GLORIOUS_SPEED_NORMAL; + RainbowSlow.speed_max = GLORIOUS_SPEED_FAST; + RainbowSlow.color_mode = MODE_COLORS_NONE; + RainbowSlow.value = GLORIOUS_MODE_WAVE; + modes.push_back(RainbowSlow); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.speed_min = GLORIOUS_MODE_BREATING_SLOW; + Breathing.speed = GLORIOUS_MODE_BREATING_NORMAL; + Breathing.speed_max = GLORIOUS_MODE_BREATING_FAST; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.value = GLORIOUS_MODE_BREATHING; + Breathing.colors.resize(1); + modes.push_back(Breathing); + + SetupZones(); +} + +RGBController_Sinowealth::~RGBController_Sinowealth() +{ + delete controller; +} + +void RGBController_Sinowealth::SetupZones() +{ + /*---------------------------------------------------------*\ + | Create a single zone | + \*---------------------------------------------------------*/ + zone new_zone; + new_zone.name = "Mouse"; + new_zone.type = ZONE_TYPE_SINGLE; + new_zone.leds_min = controller->GetLEDCount(); + new_zone.leds_max = controller->GetLEDCount(); + new_zone.leds_count = controller->GetLEDCount(); + new_zone.matrix_map = NULL; + zones.push_back(new_zone); + + /*---------------------------------------------------------*\ + | Set up LEDs | + \*---------------------------------------------------------*/ + for(std::size_t led_idx = 0; led_idx < zones[0].leds_count; led_idx++) + { + led* new_led = new led(); + new_led->name = "Mouse LED"; + leds.push_back(*new_led); + } + + SetupColors(); +} + +void RGBController_Sinowealth::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_Sinowealth::DeviceUpdateLEDs() +{ + controller->SetLEDColor(&colors[0]); +} + +void RGBController_Sinowealth::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_Sinowealth::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_Sinowealth::DeviceUpdateMode() +{ + unsigned int direction = 0; + unsigned int speed = GLORIOUS_SPEED_NORMAL; + + if (modes[active_mode].value == GLORIOUS_MODE_STATIC) + { + + } + else + { + if (modes[active_mode].direction == MODE_DIRECTION_UP) + { + direction = GLORIOUS_DIRECTION_DOWN; + } + else + { + direction = GLORIOUS_DIRECTION_UP; + } + + if ((modes[active_mode].speed == GLORIOUS_SPEED_FAST) || + (modes[active_mode].speed == GLORIOUS_SPEED_SLOW) || + (modes[active_mode].speed == GLORIOUS_SPEED_NORMAL)) + { + speed = modes[active_mode].speed; + } + else + { + if ((modes[active_mode].speed == GLORIOUS_MODE_BREATING_FAST) || + (modes[active_mode].speed == GLORIOUS_MODE_BREATING_SLOW) || + (modes[active_mode].speed == GLORIOUS_MODE_BREATING_NORMAL)) + { + speed = modes[active_mode].speed; + } + else + { + speed = GLORIOUS_SPEED_NORMAL; + } + } + + if (modes[active_mode].color_mode == MODE_COLORS_NONE) + { + controller->SetMode(modes[active_mode].value, speed, direction, 0); + } + else + { + controller->SetMode(modes[active_mode].value, speed, direction, &modes[active_mode].colors[0]); + } + } +} + diff --git a/Controllers/SinowealthController/SinowealthController/RGBController_Sinowealth.h b/Controllers/SinowealthController/SinowealthController/RGBController_Sinowealth.h new file mode 100644 index 00000000..091d2737 --- /dev/null +++ b/Controllers/SinowealthController/SinowealthController/RGBController_Sinowealth.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_Sinowealth.h | +| | +| RGBController for Sinowealth mice, including Glorious | +| | +| Niels Westphal (crashniels) 20 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SinowealthController.h" + +class RGBController_Sinowealth : public RGBController +{ +public: + RGBController_Sinowealth(SinowealthController* controller_ptr); + ~RGBController_Sinowealth(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + SinowealthController* controller; +}; diff --git a/Controllers/SinowealthController/SinowealthController.cpp b/Controllers/SinowealthController/SinowealthController/SinowealthController.cpp similarity index 79% rename from Controllers/SinowealthController/SinowealthController.cpp rename to Controllers/SinowealthController/SinowealthController/SinowealthController.cpp index 69ef565d..f4ede7ff 100644 --- a/Controllers/SinowealthController/SinowealthController.cpp +++ b/Controllers/SinowealthController/SinowealthController/SinowealthController.cpp @@ -1,34 +1,45 @@ -/*-----------------------------------------*\ -| SinowealthController.cpp | -| | -| Definitions and types for Sinowealth | -| mice, including Glorious | -| | -| Niels Westphal (crashniels) 20/5/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| SinowealthController.cpp | +| | +| Driver for Sinowealth mice, including Glorious | +| | +| Niels Westphal (crashniels) 20 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "SinowealthController.h" #include -#include +#include "LogManager.h" +#include "SinowealthController.h" +#include "StringUtils.h" -SinowealthController::SinowealthController(hid_device* dev_data_handle, hid_device* dev_cmd_handle, char *_path) +SinowealthController::SinowealthController(hid_device* dev_data_handle, hid_device* dev_cmd_handle, char *_path, std::string dev_name) { - dev_data = dev_data_handle; - dev_cmd = dev_cmd_handle; + dev_data = dev_data_handle; + dev_cmd = dev_cmd_handle; + location = _path; + name = dev_name; - led_count = 1; + led_count = 1; - current_mode = GLORIOUS_MODE_STATIC; - current_speed = GLORIOUS_SPEED_NORMAL; - current_direction = GLORIOUS_DIRECTION_UP; - - location = _path; + current_mode = GLORIOUS_MODE_STATIC; + current_speed = GLORIOUS_SPEED_NORMAL; + current_direction = GLORIOUS_DIRECTION_UP; } SinowealthController::~SinowealthController() { hid_close(dev_data); - hid_close(dev_cmd); + + /*---------------------------------------------------------------------*\ + | If the dev_cmd handle was passed in as the same device as dev_data | + | then attempting to close it a second time will segfault | + \*---------------------------------------------------------------------*/ + if(dev_cmd) + { + hid_close(dev_cmd); + } } std::string SinowealthController::GetLocation() @@ -36,6 +47,11 @@ std::string SinowealthController::GetLocation() return("HID: " + location); } +std::string SinowealthController::GetName() +{ + return(name); +} + unsigned int SinowealthController::GetLEDCount() { return(led_count); @@ -44,17 +60,14 @@ unsigned int SinowealthController::GetLEDCount() std::string SinowealthController::GetSerialString() { wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev_data, serial_string, 128); + int ret = hid_get_serial_number_string(dev_cmd, 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); + return(StringUtils::wstring_to_string(serial_string)); } std::string SinowealthController::GetFirmwareVersion() diff --git a/Controllers/SinowealthController/SinowealthController/SinowealthController.h b/Controllers/SinowealthController/SinowealthController/SinowealthController.h new file mode 100644 index 00000000..8630da7e --- /dev/null +++ b/Controllers/SinowealthController/SinowealthController/SinowealthController.h @@ -0,0 +1,82 @@ +/*---------------------------------------------------------*\ +| SinowealthController.h | +| | +| Driver for Sinowealth mice, including Glorious | +| | +| Niels Westphal (crashniels) 20 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define SINOWEALTH_CONFIG_SIZE 167 +#define SINOWEALTH_CONFIG_SIZE_MIN 131 +#define SINOWEALTH_CONFIG_REPORT_SIZE 520 +#define SINOWEALTH_COMMAND_REPORT_SIZE 6 + +enum +{ + GLORIOUS_MODE_OFF = 0x00, //does nothing + GLORIOUS_MODE_RAINBOW = 0x01, + GLORIOUS_MODE_STATIC = 0x02, + GLORIOUS_MODE_SPECTRUM_BREATING = 0x03, + GLORIOUS_MODE_TAIL = 0x04, + GLORIOUS_MODE_SPECTRUM_CYCLE = 0x05, + GLORIOUS_MODE_RAVE = 0x07, + GLORIOUS_MODE_EPILEPSY = 0x08, //not in the official software + GLORIOUS_MODE_WAVE = 0x09, + GLORIOUS_MODE_BREATHING = 0x0a, +}; + +enum +{ + GLORIOUS_SPEED_SLOW = 0x41, + GLORIOUS_SPEED_NORMAL = 0x42, + GLORIOUS_SPEED_FAST = 0x43, +}; + +enum +{ + GLORIOUS_DIRECTION_UP = 0x00, + GLORIOUS_DIRECTION_DOWN = 0x01, +}; + +enum +{ + GLORIOUS_MODE_BREATING_SLOW = 0x01, + GLORIOUS_MODE_BREATING_NORMAL = 0x02, + GLORIOUS_MODE_BREATING_FAST = 0x03, +}; + +class SinowealthController +{ +public: + SinowealthController(hid_device* dev_data_handle, hid_device* dev_cmd_handle, char *_path, std::string dev_name); //RGB, Command, path + ~SinowealthController(); + + unsigned int GetLEDCount(); + std::string GetLocation(); + std::string GetName(); + std::string GetSerialString(); + std::string GetFirmwareVersion(); + + void SetLEDColor(RGBColor* color_buf); + void SetMode(unsigned char mode, unsigned char speed, unsigned char direction, RGBColor* color_buf); + int GetProfile(); +private: + hid_device* dev_cmd; + hid_device* dev_data; + unsigned int led_count; + unsigned char current_mode; + unsigned char current_speed; + unsigned char current_direction; + unsigned char device_configuration[SINOWEALTH_CONFIG_REPORT_SIZE]; + std::string location; + std::string name; +}; diff --git a/Controllers/SinowealthController/SinowealthController1007.cpp b/Controllers/SinowealthController/SinowealthController1007.cpp deleted file mode 100644 index 810a2b76..00000000 --- a/Controllers/SinowealthController/SinowealthController1007.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/*-----------------------------------------*\ -| SinowealthController1007.cpp | -| | -| Driver for Sinowealth mice with PID 1007 | -| and ones with similar protocol | -| | -| Moon_darker (Vaker) 02.02.2022 | -\*-----------------------------------------*/ - -#include "SinowealthController1007.h" -#include -#include - -SinowealthController1007::SinowealthController1007(hid_device* dev, char *_path) -{ - this->dev = dev; - - this->led_count = 7; - - this->current_mode = ZET_FURY_PRO_MODE_CUSTOM + ZET_FURY_PRO_SPEED_DEF; - this->current_direction = ZET_FURY_PRO_DIR_RIGHT; - - this->location = _path; - memset(device_colors, 0x00, sizeof(device_colors)); -} - -SinowealthController1007::~SinowealthController1007() -{ - hid_close(dev); -} - -std::string SinowealthController1007::GetLocation() -{ - return("HID: " + location); -} - -unsigned int SinowealthController1007::GetLEDCount() -{ - return(led_count); -} - -std::string SinowealthController1007::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 SinowealthController1007::SetLEDColors(const std::vector& colors) -{ - memset(device_colors, 0x00, sizeof(device_colors)); - - unsigned int color_counter = 0; - for (RGBColor color: colors) - { - unsigned int pkt_pointer = (color_counter * 3); // 3 bytes per color - - device_colors[pkt_pointer] = RGBGetRValue(color); - device_colors[pkt_pointer + 1] = RGBGetGValue(color); - device_colors[pkt_pointer + 2] = RGBGetBValue(color); - - if (++color_counter == 7) break; - } - - SendPacket(); -} - -void SinowealthController1007::SetMode( - unsigned char mode, - unsigned char spd_or_lum, - unsigned char direction, - const std::vector& colors, - unsigned char random, - bool has_per_led_colors) -{ - current_mode = mode + (spd_or_lum ? spd_or_lum : ZET_FURY_PRO_SPEED_DEF); - current_direction = random ? random : direction; - - if (!has_per_led_colors) - { - memset(device_colors, 0x00, sizeof(device_colors)); - SetLEDColors(colors); - } -} - -void SinowealthController1007::SendPacket() -{ - if (GetProfile() < 0) return; - - unsigned char usb_buf[ZET_FURY_PRO_STATE_BUFFER_LENGTH]; - memcpy(usb_buf, device_configuration, sizeof(usb_buf)); - memcpy(usb_buf + 23, device_colors, sizeof(device_colors)); // colors are bytes 23-43 in RGB format counting from 0 - - usb_buf[21] = current_mode; - usb_buf[22] = current_direction; - - hid_send_feature_report(dev, usb_buf, sizeof(usb_buf)); -} - -int SinowealthController1007::GetProfile() -{ - int bytesReceived; - - memset(device_configuration, 0x00, ZET_FURY_PRO_STATE_BUFFER_LENGTH); - device_configuration[0] = 0x04; - - bytesReceived = hid_get_feature_report(dev, device_configuration, ZET_FURY_PRO_STATE_BUFFER_LENGTH); - if (bytesReceived < 0) - { - LOG_ERROR("[ZET Fury Pro] Error reading device configuration!"); - } - - return bytesReceived; -} diff --git a/Controllers/SinowealthController/SinowealthController1007.h b/Controllers/SinowealthController/SinowealthController1007.h deleted file mode 100644 index 4b15d824..00000000 --- a/Controllers/SinowealthController/SinowealthController1007.h +++ /dev/null @@ -1,81 +0,0 @@ -/*-----------------------------------------*\ -| SinowealthController1007.h | -| | -| Definitions and types for Sinowealth | -| mice with PID 1007 and ones with similar | -| protocol | -| | -| Moon_darker (Vaker) 25.01.2022 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include - -#pragma once - -#define ZET_FURY_PRO_STATE_BUFFER_LENGTH 59 -#define ZET_FURY_PRO_COLOR_BUFFER_LENGTH 21 - -#define ZET_FURY_PRO_BRIGHTNESS_MIN 1 -#define ZET_FURY_PRO_BRIGHTNESS_MAX 9 -#define ZET_FURY_PRO_BRIGHTNESS_DEF 9 - -#define ZET_FURY_PRO_SPEED_MIN 1 -#define ZET_FURY_PRO_SPEED_MAX 3 -#define ZET_FURY_PRO_SPEED_DEF 2 - -enum -{ - ZET_FURY_PRO_MODE_OFF = 0x00, - ZET_FURY_PRO_MODE_RAINBOW = 0x10, - ZET_FURY_PRO_MODE_STATIC = 0x20, - ZET_FURY_PRO_MODE_BREATHING = 0x30, - ZET_FURY_PRO_MODE_PENDULUM = 0x40, - ZET_FURY_PRO_MODE_SPECTRUM = 0x50, - ZET_FURY_PRO_MODE_CUSTOM = 0x60, - ZET_FURY_PRO_MODE_TWO_COLORS = 0x70, - ZET_FURY_PRO_MODE_REACTIVE = 0x80, - ZET_FURY_PRO_MODE_FLICKER = 0x90, - ZET_FURY_PRO_MODE_RAIN = 0xA0, - ZET_FURY_PRO_MODE_SNAKE = 0xB0, -}; - -enum -{ - ZET_FURY_PRO_SUBMODE_SET_COLOR = 0x07, - ZET_FURY_PRO_SUBMODE_RANDOM = 0x80, -}; - -enum -{ - ZET_FURY_PRO_DIR_LEFT = 0x80, - ZET_FURY_PRO_DIR_RIGHT = 0x00, -}; - -class SinowealthController1007 -{ -public: - SinowealthController1007(hid_device* dev, char *_path); - ~SinowealthController1007(); - - unsigned int GetLEDCount(); - std::string GetLocation(); - std::string GetSerialString(); - - void SetLEDColors(const std::vector& colors); - void SetMode(unsigned char mode, unsigned char spd_or_lum, unsigned char direction, const std::vector& colors, unsigned char random, bool has_per_led_colors); - int GetProfile(); - void SendPacket(); -private: - hid_device* dev; - - unsigned int led_count; - - unsigned char current_mode; - unsigned char current_direction; - unsigned char device_configuration[ZET_FURY_PRO_STATE_BUFFER_LENGTH]; - unsigned char device_colors[ZET_FURY_PRO_COLOR_BUFFER_LENGTH]; - - std::string location; -}; diff --git a/Controllers/SinowealthController/SinowealthControllerDetect.cpp b/Controllers/SinowealthController/SinowealthControllerDetect.cpp index de955c82..ff555b24 100644 --- a/Controllers/SinowealthController/SinowealthControllerDetect.cpp +++ b/Controllers/SinowealthController/SinowealthControllerDetect.cpp @@ -1,33 +1,45 @@ +/*---------------------------------------------------------*\ +| SinowealthControllerDetect.cpp | +| | +| Detector for Sinowealth, Genesis and Everest brand Mice | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "SinowealthController.h" #include "SinowealthController1007.h" -#include "SinowealthKeyboardController.h" -#include "SinowealthKeyboard16Controller.h" +#include "SinowealthKeyboardController.h" // Disabled +#include "SinowealthKeyboard16Controller.h" // Disabled #include "SinowealthKeyboard90Controller.h" #include "SinowealthGMOWController.h" +#include "GenesisXenon200Controller.cpp" #include "RGBController.h" #include "RGBController_Sinowealth.h" #include "RGBController_Sinowealth1007.h" -#include "RGBController_SinowealthKeyboard.h" -#include "RGBController_SinowealthKeyboard16.h" +#include "RGBController_SinowealthKeyboard.h" // Disabled +#include "RGBController_SinowealthKeyboard16.h" // Disabled #include "RGBController_SinowealthKeyboard90.h" #include "RGBController_SinowealthGMOW.h" -#include +#include "RGBController_GenesisXenon200.h" +#include #include "LogManager.h" -#define SINOWEALTH_VID 0x258A +#define SINOWEALTH_VID 0x258A -#define Glorious_Model_O_PID 0x0036 -#define Glorious_Model_OW_PID1 0x2022 // wireless -#define Glorious_Model_OW_PID2 0x2011 // when connected via cable -#define Glorious_Model_D_PID 0x0033 -#define Glorious_Model_DW_PID1 0x2023 // Wireless -#define Glorious_Model_DW_PID2 0x2012 // When connected via cable -#define Everest_GT100_PID 0x0029 -#define ZET_FURY_PRO_PID 0x1007 -#define Fl_Esports_F11_PID 0x0049 -#define RGB_KEYBOARD_0016PID 0x0016 -#define GENESIS_THOR_300_PID 0x0090 +#define Glorious_Model_O_PID 0x0036 +#define Glorious_Model_OW_PID1 0x2022 // wireless +#define Glorious_Model_OW_PID2 0x2011 // when connected via cable +#define Glorious_Model_D_PID 0x0033 +#define Glorious_Model_DW_PID1 0x2023 // Wireless +#define Glorious_Model_DW_PID2 0x2012 // When connected via cable +#define Everest_GT100_PID 0x0029 +#define ZET_FURY_PRO_PID 0x1007 +#define Fl_Esports_F11_PID 0x0049 +#define RGB_KEYBOARD_0016PID 0x0016 +#define GENESIS_THOR_300_PID 0x0090 +#define GENESIS_XENON_200_PID 0x1007 /******************************************************************************************\ * * @@ -52,17 +64,17 @@ struct expected_report expected_report(unsigned int id, unsigned size, unsigned char* cmd_buf, unsigned int cmd_size) : id(id), size(size), cmd_buf(cmd_buf), cmd_size(cmd_size) {} }; -typedef std::vector expected_reports; +typedef std::vector expected_reports; -int GetDeviceCount(hid_device_info* info, unsigned int &device_count_total, unsigned int device_count_expected) +static int GetDeviceCount(hid_device_info* info, unsigned int &device_count_total, unsigned int device_count_expected) { hid_device_info* info_temp = info; while(info_temp) { - if (info_temp->vendor_id == info->vendor_id // constant SINOWEALTH_VID - && info_temp->product_id == info->product_id // NON-constant - && info_temp->usage_page == info->usage_page) // constant 0xFF00 + if(info_temp->vendor_id == info->vendor_id // constant SINOWEALTH_VID + && info_temp->product_id == info->product_id // NON-constant + && info_temp->usage_page == info->usage_page) // constant 0xFF00 { device_count_total++; } @@ -80,7 +92,7 @@ int GetDeviceCount(hid_device_info* info, unsigned int &device_count_total, unsi return false; } -bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_count_expected, expected_reports& reports) +static bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_count_expected, expected_reports& reports) { hid_device_info* info_temp = info; hid_device* device = nullptr; @@ -116,9 +128,9 @@ bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_c /*----------------------------------------------------------------*\ | If it's still our device | \*----------------------------------------------------------------*/ - if(info_temp->vendor_id == info->vendor_id // constant SINOWEALTH_VID - && info_temp->product_id == info->product_id // NON-constant - && info_temp->usage_page == info->usage_page) // constant 0xFF00 + if(info_temp->vendor_id == info->vendor_id // constant SINOWEALTH_VID + && info_temp->product_id == info->product_id // NON-constant + && info_temp->usage_page == info->usage_page) // constant 0xFF00 { /*----------------------------------------------------------*\ | Open current device to check if it has expected report IDs | @@ -133,44 +145,47 @@ bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_c return false; } - for (expected_report* report: reports) + for(expected_report& report: reports) { /*-----------------------------------------------------------*\ | We shouldn't do any checks if device is already found | \*-----------------------------------------------------------*/ - if(report->device != nullptr) continue; + if(report.device != nullptr) + { + continue; + } memset(tmp_buf, 0x00, sizeof(tmp_buf)); - tmp_buf[0] = report->id; + tmp_buf[0] = report.id; /*--------------------------------------------------------------------------------------*\ | If we need to send a command before requesting data, send it and flag the report | | (DON'T TRY TO CREATE MORE THAN 1 EXPECTED REPORT SENDING COMMANDS) | \*--------------------------------------------------------------------------------------*/ - if(report->cmd_buf != nullptr && report->cmd_device == nullptr) + if(report.cmd_buf != nullptr && report.cmd_device == nullptr) { - if (hid_send_feature_report(device, report->cmd_buf, report->cmd_size) > -1) + if(hid_send_feature_report(device, report.cmd_buf, report.cmd_size) > -1) { restart_flag = true; // Because Windows - report->cmd_device = device; - LOG_TRACE("[%s] Successfully sent command for ReportId 0x%02X to device at location \"HID: %s\", handle: %08X", name.c_str(), report->id, info_temp->path, device); + report.cmd_device = device; + LOG_TRACE("[%s] Successfully sent command for ReportId 0x%02X to device at location \"HID: %s\", handle: %08X", name.c_str(), report.id, info_temp->path, device); } } /*------------------------------------------------------*\ | Now we try to request data for expected feature report | \*------------------------------------------------------*/ - if(report->cmd_buf == nullptr || report->cmd_device != nullptr) + if(report.cmd_buf == nullptr || report.cmd_device != nullptr) { /*---------------------------------------------------------------------------*\ | If device actually responds to expected report ID, set a flag | \*---------------------------------------------------------------------------*/ - if(hid_get_feature_report(device, tmp_buf, report->size) > -1) + if(hid_get_feature_report(device, tmp_buf, report.size) > -1) { device_count++; report_found = true; - report->device = device; - LOG_TRACE("[%s] Successfully requested feature ReportId 0x%02X from device at location \"HID: %s\", handle: %08X", name.c_str(), report->id, info_temp->path, device); + report.device = device; + LOG_TRACE("[%s] Successfully requested feature ReportId 0x%02X from device at location \"HID: %s\", handle: %08X", name.c_str(), report.id, info_temp->path, device); } } } @@ -199,11 +214,11 @@ bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_c \*-----------------------------------------------------------*/ if(device_count < reports.size()) { - for (expected_report* report: reports) + for(expected_report& report: reports) { - if(report->device != nullptr) + if(report.device != nullptr) { - hid_close(report->device); + hid_close(report.device); } } @@ -214,28 +229,89 @@ bool DetectUsages(hid_device_info* info, std::string name, unsigned int device_c return true; } -void DetectSinowealthMouse(hid_device_info* info, const std::string& name) +static void DetectGenesisXenon200(hid_device_info* info, const std::string name) { - unsigned int pid = info->product_id; -#ifdef USE_HID_USAGE - - /*-------------------------------------------------------------------------------------------------*\ - | Sinowealth devices use 3 (or more) different Report IDs on the same Usage Page. | - | The 4 on 0xFF00 is for RGB, 7 is Unknown and 5 (or 8, or whatever...) is for Commands. | - \*-------------------------------------------------------------------------------------------------*/ - expected_reports* reports = new expected_reports(); - RGBController *rgb_controller; - - if(pid == ZET_FURY_PRO_PID) + expected_reports reports{expected_report(0x04, 154), expected_report(0x08, 9)}; + if(!DetectUsages(info, name, 5, reports)) { - reports->emplace_back(new expected_report(0x04, 59)); - - if(!DetectUsages(info, name, 5, *reports)) return; - - SinowealthController1007* controller = new SinowealthController1007(reports->at(0)->device, info->path); - rgb_controller = new RGBController_Sinowealth1007(controller); - + return; } + + hid_device* dev = reports.at(0).device; + hid_device* cmd_dev = reports.at(1).device; + + GenesisXenon200Controller* controller = new GenesisXenon200Controller(dev, cmd_dev, info->path, name); + RGBController* rgb_controller = new RGBController_GenesisXenon200(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + +} + +static void DetectZetFuryPro(hid_device_info* info, const std::string& name) +{ +#ifdef USE_HID_USAGE + expected_reports reports{expected_report(0x04, 59)}; + if(!DetectUsages(info, name, 5, reports)) + { + return; + } + hid_device* dev = reports.at(0).device; +#else + hid_device* dev = hid_open_path(info->path); +#endif + + if(dev) + { + SinowealthController1007* controller = new SinowealthController1007(dev, info->path, name); + RGBController_Sinowealth1007* rgb_controller = new RGBController_Sinowealth1007(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +static void DetectSinowealthMouse(hid_device_info* info, const std::string& name) +{ +#ifdef USE_HID_USAGE + unsigned char command[6] = {0x05, 0x11, 0x00, 0x00, 0x00, 0x00}; + expected_reports reports{expected_report(0x04, 520, command, sizeof(command))}; + + if(!DetectUsages(info, name, 3, reports)) + { + return; + } + + hid_device *dev = reports.at(0).device; + hid_device *dev_cmd = reports.at(0).cmd_device; +#else + hid_device* dev = hid_open_path(info->path); + hid_device* dev_cmd = dev; +#endif + + if(dev && dev_cmd) + { + SinowealthController* controller = new SinowealthController(dev, dev_cmd, info->path, name); + RGBController_Sinowealth* rgb_controller = new RGBController_Sinowealth(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +static void DetectGMOW_Cable(hid_device_info* info, const std::string& name) +{ + LOG_DEBUG("[%s] Detected connection via USB cable", name.c_str()); + hid_device *dev = hid_open_path(info->path); + + if(dev) + { + SinowealthGMOWController* controller = new SinowealthGMOWController(dev, info->path, GMOW_CABLE_CONNECTED, name); + RGBController_GMOW* rgb_controller = new RGBController_GMOW(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +static void DetectGMOW_Dongle(hid_device_info* info, const std::string& name) +{ /*-------------------------------------------------------------------------*\ | When the GMOW is connected only via the wireless dongle, only one | | device shows up (PID=2022), and RGB packets go to that device. | @@ -243,194 +319,130 @@ void DetectSinowealthMouse(hid_device_info* info, const std::string& name) | the device is PID=2011). However, when both are plugged in, packets | | should only go to the cable connected device | \*-------------------------------------------------------------------------*/ - else if(pid == Glorious_Model_OW_PID1 || pid == Glorious_Model_DW_PID1) // if dongle - { - LOG_DEBUG("[%s] Detected connection via wireless dongle", name.c_str()); - hid_device_info* start = hid_enumerate(SINOWEALTH_VID,0); - hid_device_info* curr = start; + LOG_DEBUG("[%s] Detected connection via wireless dongle", name.c_str()); + hid_device_info* start = hid_enumerate(SINOWEALTH_VID,0); + hid_device_info* curr = start; - while(curr) + while(curr) + { + if(curr->product_id == Glorious_Model_OW_PID2 || curr->product_id == Glorious_Model_DW_PID2) { - if(curr->product_id == Glorious_Model_OW_PID2 || curr->product_id == Glorious_Model_DW_PID2) - { - delete reports; - return; - } - curr = curr->next; + return; } - - hid_device *dev = hid_open_path(info->path); - SinowealthGMOWController* controller = new SinowealthGMOWController(dev, info->path, GMOW_DONGLE_CONNECTED); - rgb_controller = new RGBController_GMOW(controller); + curr = curr->next; } - else if(pid == Glorious_Model_OW_PID2 || pid == Glorious_Model_DW_PID2) - { - LOG_DEBUG("[%s] Detected connection via USB cable", name.c_str()); - hid_device *dev = hid_open_path(info->path); - SinowealthGMOWController* controller = new SinowealthGMOWController(dev, info->path, GMOW_CABLE_CONNECTED); - rgb_controller = new RGBController_GMOW(controller); - } - else - { - unsigned char command[6] = {0x05, 0x11, 0x00, 0x00, 0x00, 0x00}; - reports->emplace_back(new expected_report(0x04, 520, command, sizeof(command))); + hid_free_enumeration(start); - if(!DetectUsages(info, name, 3, *reports)) return; + hid_device *dev = hid_open_path(info->path); - SinowealthController* controller = new SinowealthController(reports->at(0)->device, reports->at(0)->cmd_device, info->path); - rgb_controller = new RGBController_Sinowealth(controller); - } - - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - - reports->clear(); -#else - hid_device* dev = hid_open_path(info->path); if(dev) { - RGBController *rgb_controller; + SinowealthGMOWController* controller = new SinowealthGMOWController(dev, info->path, GMOW_DONGLE_CONNECTED, name); + RGBController_GMOW* rgb_controller = new RGBController_GMOW(controller); - if(pid == ZET_FURY_PRO_PID) - { - SinowealthController1007* controller = new SinowealthController1007(dev, info->path); - rgb_controller = new RGBController_Sinowealth1007(controller); - } - /*-------------------------------------------------------------------------*\ - | See above where USE_HID_USAGE is true for explanation of the detection | - | process for the GMOW | - \*-------------------------------------------------------------------------*/ - else if(pid == Glorious_Model_OW_PID1 || pid == Glorious_Model_DW_PID1) // if dongle - { - LOG_DEBUG("[%s] Detected connection via wireless dongle", name.c_str()); - hid_device_info* start = hid_enumerate(SINOWEALTH_VID,0); - hid_device_info* curr = start; - - while(curr) - { - if(curr->product_id == Glorious_Model_OW_PID2 || curr->product_id == Glorious_Model_DW_PID2) - { - return; - } - curr = curr->next; - } - - hid_device *dev = hid_open_path(info->path); - SinowealthGMOWController* controller = new SinowealthGMOWController(dev, info->path, GMOW_DONGLE_CONNECTED); - rgb_controller = new RGBController_GMOW(controller); - } - else if(pid == Glorious_Model_OW_PID2 || pid == Glorious_Model_DW_PID2) - { - LOG_DEBUG("[%s] Detected connection via USB cable", name.c_str()); - hid_device *dev = hid_open_path(info->path); - SinowealthGMOWController* controller = new SinowealthGMOWController(dev, info->path, GMOW_CABLE_CONNECTED); - rgb_controller = new RGBController_GMOW(controller); - } - else - { - SinowealthController* controller = new SinowealthController(dev, dev, info->path); - rgb_controller = new RGBController_Sinowealth(controller); - } - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } -#endif } -void DetectSinowealthKeyboard(hid_device_info* info, const std::string& name) -{ - unsigned int pid = info->product_id; -#ifdef USE_HID_USAGE - expected_reports* reports = new expected_reports(); +// static void DetectSinowealthKeyboard16(hid_device_info* info, const std::string& name) +// { +// #ifdef USE_HID_USAGE +// unsigned char command[6] = {0x05, 0x83, 0x00, 0x00, 0x00, 0x00}; +// expected_reports reports{expected_report(0x06, 1032, command, sizeof(command))}; +// if(!DetectUsages(info, name, 3, reports)) +// { +// return; +// } +// hid_device *dev = reports.at(0).device; +// hid_device *dev_cmd = reports.at(0).cmd_device; +// #else +// hid_device* dev = hid_open_path(info->path); +// hid_device* dev_cmd = dev; +// #endif +// if(dev && dev_cmd) +// { +// SinowealthKeyboard16Controller* controller = new SinowealthKeyboard16Controller(dev_cmd, dev, info->path, name); +// RGBController_SinowealthKeyboard16* rgb_controller = new RGBController_SinowealthKeyboard16(controller); +// +// ResourceManager::get()->RegisterRGBController(rgb_controller); +// } +// } - RGBController *rgb_controller; - if(pid == RGB_KEYBOARD_0016PID) - { - unsigned char command[6] = {0x05, 0x83, 0x00, 0x00, 0x00, 0x00}; - reports->emplace_back(new expected_report(0x06, 1032, command, sizeof(command))); +// static void DetectSinowealthKeyboard(hid_device_info* info, const std::string& name) +// { +// #ifdef USE_HID_USAGE +// unsigned char command[6] = {0x05, 0x83, 0xB6, 0x00, 0x00, 0x00}; +// expected_reports reports{expected_report(0x06, 1032, command, sizeof(command))}; +// if(!DetectUsages(info, name, 3, reports)) +// { +// return; +// } +// +// hid_device *dev = reports.at(0).device; +// hid_device *dev_cmd = reports.at(0).cmd_device; +// +// if(dev && dev_cmd) +// { +// SinowealthKeyboardController* controller = new SinowealthKeyboardController(dev_cmd, dev, info->path, name); +// RGBController_SinowealthKeyboard* rgb_controller = new RGBController_SinowealthKeyboard(controller); +// +// ResourceManager::get()->RegisterRGBController(rgb_controller); +// } +// #else +// // It is unknown why this code used the MOUSE controller here; could it be the reason why it was disabled? +// hid_device* dev = hid_open_path(info->path); +// +// if(dev) +// { +// SinowealthController* controller = new SinowealthController(dev, dev, info->path, name); +// RGBController_Sinowealth* rgb_controller = new RGBController_Sinowealth(controller); +// +// ResourceManager::get()->RegisterRGBController(rgb_controller); +// } +// #endif +// } - if(!DetectUsages(info, name, 3, *reports)) return; - - SinowealthKeyboard16Controller* controller = new SinowealthKeyboard16Controller(reports->at(0)->cmd_device, reports->at(0)->device, info->path, name); - rgb_controller = new RGBController_SinowealthKeyboard16(controller); - } - else - { - unsigned char command[6] = {0x05, 0x83, 0xB6, 0x00, 0x00, 0x00}; - reports->emplace_back(new expected_report(0x06, 1032, command, sizeof(command))); - - if(!DetectUsages(info, name, 3, *reports)) return; - - SinowealthKeyboardController* controller = new SinowealthKeyboardController(reports->at(0)->cmd_device, reports->at(0)->device, info->path); - rgb_controller = new RGBController_SinowealthKeyboard(controller); - } - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - - reports->clear(); -#else - hid_device* dev = hid_open_path(info->path); - if(dev) - { - RGBController *rgb_controller; - - if(pid == RGB_KEYBOARD_0016PID) - { - SinowealthKeyboard16Controller* controller = new SinowealthKeyboard16Controller(dev, dev, info->path, name); - rgb_controller = new RGBController_SinowealthKeyboard16(controller); - } - else - { - SinowealthController* controller = new SinowealthController(dev, dev, info->path); - rgb_controller = new RGBController_Sinowealth(controller); - } - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -#endif -} - -void DetectSinowealthGenesisKeyboard(hid_device_info* info, const std::string& name) +static void DetectSinowealthGenesisKeyboard(hid_device_info* info, const std::string& name) { unsigned int pid = info->product_id; hid_device* dev = hid_open_path(info->path); + if(dev) { - if(pid == GENESIS_THOR_300_PID) - { - SinowealthKeyboard90Controller* controller = new SinowealthKeyboard90Controller(dev, info->path, pid); - RGBController_SinowealthKeyboard90* rgb_controller = new RGBController_SinowealthKeyboard90(controller); - rgb_controller->name = name; + SinowealthKeyboard90Controller* controller = new SinowealthKeyboard90Controller(dev, info->path, pid, name); + RGBController_SinowealthKeyboard90* rgb_controller = new RGBController_SinowealthKeyboard90(controller); - ResourceManager::get()->RegisterRGBController(rgb_controller); - } + ResourceManager::get()->RegisterRGBController(rgb_controller); } } #ifdef USE_HID_USAGE -REGISTER_HID_DETECTOR_P("Glorious Model O / O-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_O_PID, 0xFF00); -REGISTER_HID_DETECTOR_P("Glorious Model D / D-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_D_PID, 0xFF00); -REGISTER_HID_DETECTOR_P("Everest GT-100 RGB", DetectSinowealthMouse, SINOWEALTH_VID, Everest_GT100_PID, 0xFF00); -REGISTER_HID_DETECTOR_IPU("ZET Fury Pro", DetectSinowealthMouse, SINOWEALTH_VID, ZET_FURY_PRO_PID, 1, 0xFF00, 1); -REGISTER_HID_DETECTOR_PU("Glorious Model O / O- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_OW_PID1, 0xFFFF, 1); -REGISTER_HID_DETECTOR_PU("Glorious Model O / O- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_OW_PID2, 0xFFFF, 0x0000); -REGISTER_HID_DETECTOR_PU("Glorious Model D / D- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_DW_PID1, 0xFFFF, 0x0000); -REGISTER_HID_DETECTOR_PU("Glorious Model D / D- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_DW_PID2, 0xFFFF, 0x0000); +REGISTER_HID_DETECTOR_P("Glorious Model O / O-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_O_PID, 0xFF00 ); +REGISTER_HID_DETECTOR_P("Glorious Model D / D-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_D_PID, 0xFF00 ); +REGISTER_HID_DETECTOR_P("Everest GT-100 RGB", DetectSinowealthMouse, SINOWEALTH_VID, Everest_GT100_PID, 0xFF00 ); +REGISTER_HID_DETECTOR_IPU("ZET Fury Pro", DetectZetFuryPro, SINOWEALTH_VID, ZET_FURY_PRO_PID, 1, 0xFF00, 1 ); +REGISTER_HID_DETECTOR_PU("Glorious Model O / O- Wireless", DetectGMOW_Dongle, SINOWEALTH_VID, Glorious_Model_OW_PID1, 0xFFFF, 1 ); +REGISTER_HID_DETECTOR_PU("Glorious Model O / O- Wireless", DetectGMOW_Cable, SINOWEALTH_VID, Glorious_Model_OW_PID2, 0xFFFF, 0x0000 ); +REGISTER_HID_DETECTOR_PU("Glorious Model D / D- Wireless", DetectGMOW_Dongle, SINOWEALTH_VID, Glorious_Model_DW_PID1, 0xFFFF, 0x0000 ); +REGISTER_HID_DETECTOR_PU("Glorious Model D / D- Wireless", DetectGMOW_Cable, SINOWEALTH_VID, Glorious_Model_DW_PID2, 0xFFFF, 0x0000 ); +REGISTER_HID_DETECTOR_PU("Genesis Xenon 200", DetectGenesisXenon200, SINOWEALTH_VID, GENESIS_XENON_200_PID, 0xFF00, 1 ); +REGISTER_HID_DETECTOR_IPU("Genesis Thor 300", DetectSinowealthGenesisKeyboard, SINOWEALTH_VID, GENESIS_THOR_300_PID, 1, 0xFF00, 1 ); -REGISTER_HID_DETECTOR_IPU("Genesis Thor 300", DetectSinowealthGenesisKeyboard, SINOWEALTH_VID, GENESIS_THOR_300_PID, 1, 0xFF00, 1); -//REGISTER_HID_DETECTOR_P("FL ESPORTS F11", DetectSinowealthKeyboard, SINOWEALTH_VID, Fl_Esports_F11_PID, 0xFF00); -//REGISTER_HID_DETECTOR_P("Sinowealth Keyboard", DetectSinowealthKeyboard, SINOWEALTH_VID, RGB_KEYBOARD_0016PID, 0xFF00); +// Sinowealth keyboards are disabled due to VID/PID pairs being reused from Redragon keyboards, which ended up in bricking the latter +//REGISTER_HID_DETECTOR_P("FL ESPORTS F11", DetectSinowealthKeyboard, SINOWEALTH_VID, Fl_Esports_F11_PID, 0xFF00 ); +//REGISTER_HID_DETECTOR_P("Sinowealth Keyboard", DetectSinowealthKeyboard16, SINOWEALTH_VID, RGB_KEYBOARD_0016PID, 0xFF00 ); #else -REGISTER_HID_DETECTOR_I("Glorious Model O / O-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_O_PID, 1); -REGISTER_HID_DETECTOR_I("Glorious Model D / D-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_D_PID, 1); -REGISTER_HID_DETECTOR_I("Everest GT-100 RGB", DetectSinowealthMouse, SINOWEALTH_VID, Everest_GT100_PID, 1); -REGISTER_HID_DETECTOR_I("ZET Fury Pro", DetectSinowealthMouse, SINOWEALTH_VID, ZET_FURY_PRO_PID, 1); -REGISTER_HID_DETECTOR_I("Glorious Model O / O- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_OW_PID1, 1); -REGISTER_HID_DETECTOR_I("Glorious Model O / O- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_OW_PID2, 2); -REGISTER_HID_DETECTOR_I("Glorious Model D / D- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_DW_PID1, 2); -REGISTER_HID_DETECTOR_I("Glorious Model D / D- Wireless", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_DW_PID2, 2); +REGISTER_HID_DETECTOR_I("Glorious Model O / O-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_O_PID, 1); +REGISTER_HID_DETECTOR_I("Glorious Model D / D-", DetectSinowealthMouse, SINOWEALTH_VID, Glorious_Model_D_PID, 1); +REGISTER_HID_DETECTOR_I("Everest GT-100 RGB", DetectSinowealthMouse, SINOWEALTH_VID, Everest_GT100_PID, 1); +REGISTER_HID_DETECTOR_I("ZET Fury Pro", DetectZetFuryPro, SINOWEALTH_VID, ZET_FURY_PRO_PID, 1); +REGISTER_HID_DETECTOR_I("Glorious Model O / O- Wireless", DetectGMOW_Dongle, SINOWEALTH_VID, Glorious_Model_OW_PID1, 1); +REGISTER_HID_DETECTOR_I("Glorious Model O / O- Wireless", DetectGMOW_Cable, SINOWEALTH_VID, Glorious_Model_OW_PID2, 2); +REGISTER_HID_DETECTOR_I("Glorious Model D / D- Wireless", DetectGMOW_Dongle, SINOWEALTH_VID, Glorious_Model_DW_PID1, 2); +REGISTER_HID_DETECTOR_I("Glorious Model D / D- Wireless", DetectGMOW_Cable, SINOWEALTH_VID, Glorious_Model_DW_PID2, 2); +REGISTER_HID_DETECTOR_I("Genesis Xenon 200", DetectGenesisXenon200, SINOWEALTH_VID, GENESIS_XENON_200_PID, 1); +REGISTER_HID_DETECTOR_I("Genesis Thor 300", DetectSinowealthGenesisKeyboard, SINOWEALTH_VID, GENESIS_THOR_300_PID, 1); -REGISTER_HID_DETECTOR_I("Genesis Thor 300", DetectSinowealthGenesisKeyboard, SINOWEALTH_VID, GENESIS_THOR_300_PID, 1); -//REGISTER_HID_DETECTOR_I("FL ESPORTS F11", DetectSinowealthKeyboard, SINOWEALTH_VID, Fl_Esports_F11_PID, 1); -//REGISTER_HID_DETECTOR_I("Sinowealth Keyboard", DetectSinowealthKeyboard, SINOWEALTH_VID, RGB_KEYBOARD_0016PID, 1); +//REGISTER_HID_DETECTOR_I("FL ESPORTS F11", DetectSinowealthKeyboard, SINOWEALTH_VID, Fl_Esports_F11_PID, 1); +//REGISTER_HID_DETECTOR_I("Sinowealth Keyboard", DetectSinowealthKeyboard16, SINOWEALTH_VID, RGB_KEYBOARD_0016PID, 1); #endif diff --git a/Controllers/SinowealthController/SinowealthGMOWController.h b/Controllers/SinowealthController/SinowealthGMOWController.h deleted file mode 100644 index 9a2294e3..00000000 --- a/Controllers/SinowealthController/SinowealthGMOWController.h +++ /dev/null @@ -1,82 +0,0 @@ -/*-------------------------------------------*\ -| SinowealthGMOWController.h | -| | -| Support for the Glorious Model O Wireless | -| | -| Matt Silva (thesilvanator) 05/2022 | -\*-------------------------------------------*/ - -#include "RGBController.h" -#include -#include - -#pragma once - -#define GMOW_PACKET_SIZE 64 + 1 - -enum -{ - GMOW_MODE_OFF = 0x00, - GMOW_MODE_RAINBOW_WAVE = 0x01, - GMOW_MODE_SPECTRUM_CYCLE = 0x02, - GMOW_MODE_CUSTOM_BREATHING = 0x03, - GMOW_MODE_STATIC = 0x04, - GMOW_MODE_BREATHING = 0x05, - GMOW_MODE_TAIL = 0x06, - GMOW_MODE_RAVE = 0x07, - GMOW_MODE_WAVE = 0x08, -}; - -enum -{ - GMOW_SPEED1_MIN = 0x14, - GMOW_SPEED1_MID = 0x0B, - GMOW_SPEED1_MAX = 0x01, - - GMOW_SPEED2_MIN = 0xC8, - GMOW_SPEED2_MID = 0x6E, - GMOW_SPEED2_MAX = 0x0A, -}; - - -enum -{ - GMOW_BRIGHTNESS_MIN = 0x00, - GMOW_BRIGHTNESS_MID = 0x7F, - GMOW_BRIGHTNESS_MAX = 0xFF, -}; - -enum -{ - GMOW_CABLE_CONNECTED, - GMOW_DONGLE_CONNECTED -}; - - -class SinowealthGMOWController -{ -public: - SinowealthGMOWController(hid_device* dev_handle, char *_path, int type); - ~SinowealthGMOWController(); - - std::string GetLocation(); - std::string GetSerialString(); - - void SetMode(unsigned char mode, - unsigned char speed, - unsigned char wired_brightness, - unsigned char less_brightness, - RGBColor* color_buf, - unsigned char color_count); - - std::string GetFirmwareVersion(); - -private: - hid_device* dev; - unsigned char mode_packet[GMOW_PACKET_SIZE]; - unsigned char wired_packet[GMOW_PACKET_SIZE]; - unsigned char less_packet[GMOW_PACKET_SIZE]; - - std::string location; - int type; -}; diff --git a/Controllers/SinowealthController/SinowealthGMOWController/RGBController_SinowealthGMOW.cpp b/Controllers/SinowealthController/SinowealthGMOWController/RGBController_SinowealthGMOW.cpp new file mode 100644 index 00000000..6eabffc3 --- /dev/null +++ b/Controllers/SinowealthController/SinowealthGMOWController/RGBController_SinowealthGMOW.cpp @@ -0,0 +1,193 @@ +/*---------------------------------------------------------*\ +| RGBController_SinowealthGMOW.cpp | +| | +| RGBController for Glorious Model O Wireless | +| | +| Matt Silva (thesilvanator) May 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +/**------------------------------------------------------------------*\ + @name Sinowealth Glorious Model O Wireless + @type USB + @save :white_check_mark: + @direct :x: + @effects :white_check_mark: + @detectors DetectSinowealthMouse + @comment +\*-------------------------------------------------------------------*/ + +#include "RGBController_SinowealthGMOW.h" + +RGBController_GMOW::RGBController_GMOW(SinowealthGMOWController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + type = DEVICE_TYPE_MOUSE; + description = "Sinowealth Device"; + location = controller->GetLocation(); + serial = controller->GetSerialString(); + version = controller->GetFirmwareVersion(); + + mode Off; + Off.name = "Off"; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + Off.value = GMOW_MODE_OFF; + modes.push_back(Off); + + mode RainbowWave; + RainbowWave.name = "Rainbow Wave"; + RainbowWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + RainbowWave.speed_min = GMOW_SPEED1_MIN; + RainbowWave.speed = GMOW_SPEED1_MID; + RainbowWave.speed_max = GMOW_SPEED1_MAX; + RainbowWave.direction = MODE_DIRECTION_UP; + RainbowWave.color_mode = MODE_COLORS_NONE; + RainbowWave.brightness_min = GMOW_BRIGHTNESS_MIN; + RainbowWave.brightness = GMOW_BRIGHTNESS_MID; + RainbowWave.brightness_max = GMOW_BRIGHTNESS_MAX; + RainbowWave.value = GMOW_MODE_RAINBOW_WAVE; + modes.push_back(RainbowWave); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + SpectrumCycle.speed_min = GMOW_SPEED1_MIN; + SpectrumCycle.speed = GMOW_SPEED1_MID; + SpectrumCycle.speed_max = GMOW_SPEED1_MAX; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.brightness_min = GMOW_BRIGHTNESS_MIN; + SpectrumCycle.brightness = GMOW_BRIGHTNESS_MID; + SpectrumCycle.brightness_max = GMOW_BRIGHTNESS_MAX; + SpectrumCycle.value = GMOW_MODE_SPECTRUM_CYCLE; + modes.push_back(SpectrumCycle); + + mode CustomBreathing; + CustomBreathing.name = "Custom Breathing"; + CustomBreathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_AUTOMATIC_SAVE; + CustomBreathing.speed_min = GMOW_SPEED1_MIN; + CustomBreathing.speed = GMOW_SPEED1_MID; + CustomBreathing.speed_max = GMOW_SPEED1_MAX; + CustomBreathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + CustomBreathing.colors_min = 2; + CustomBreathing.colors_max = 7; + CustomBreathing.brightness_min = GMOW_BRIGHTNESS_MIN; + CustomBreathing.brightness = GMOW_BRIGHTNESS_MID; + CustomBreathing.brightness_max = GMOW_BRIGHTNESS_MAX; + CustomBreathing.value = GMOW_MODE_CUSTOM_BREATHING; + CustomBreathing.colors.resize(7); + modes.push_back(CustomBreathing); + + mode Static; + Static.name = "Static"; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors_min = 1; + Static.colors_max = 1; + Static.brightness_min = GMOW_BRIGHTNESS_MIN; + Static.brightness = GMOW_BRIGHTNESS_MID; + Static.brightness_max = GMOW_BRIGHTNESS_MAX; + Static.value = GMOW_MODE_STATIC; + Static.colors.resize(1); + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.speed_min = GMOW_SPEED1_MIN; + Breathing.speed = GMOW_SPEED1_MID; + Breathing.speed_max = GMOW_SPEED1_MAX; + Breathing.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breathing.colors_min = 1; + Breathing.colors_max = 1; + Breathing.brightness_min = GMOW_BRIGHTNESS_MIN; + Breathing.brightness = GMOW_BRIGHTNESS_MID; + Breathing.brightness_max = GMOW_BRIGHTNESS_MAX; + Breathing.value = GMOW_MODE_BREATHING; + Breathing.colors.resize(1); + modes.push_back(Breathing); + + mode Tail; + Tail.name = "Tail"; + Tail.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Tail.speed_min = GMOW_SPEED1_MIN; + Tail.speed = GMOW_SPEED1_MID; + Tail.speed_max = GMOW_SPEED1_MAX; + Tail.color_mode = MODE_COLORS_NONE; + Tail.brightness_min = GMOW_BRIGHTNESS_MIN; + Tail.brightness = GMOW_BRIGHTNESS_MID; + Tail.brightness_max = GMOW_BRIGHTNESS_MAX; + Tail.value = GMOW_MODE_TAIL; + modes.push_back(Tail); + + mode Rave; + Rave.name = "Rave"; + Rave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Rave.speed_min = GMOW_SPEED2_MIN; + Rave.speed = GMOW_SPEED2_MID; + Rave.speed_max = GMOW_SPEED2_MAX; + Rave.color_mode = MODE_COLORS_MODE_SPECIFIC; + Rave.colors_min = 1; + Rave.colors_max = 2; + Rave.brightness_min = GMOW_BRIGHTNESS_MIN; + Rave.brightness = GMOW_BRIGHTNESS_MID; + Rave.brightness_max = GMOW_BRIGHTNESS_MAX; + Rave.value = GMOW_MODE_RAVE; + Rave.colors.resize(2); + modes.push_back(Rave); + + mode Wave; + Wave.name = "Wave"; + Wave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Wave.speed_min = GMOW_SPEED2_MIN; + Wave.speed = GMOW_SPEED2_MID; + Wave.speed_max = GMOW_SPEED2_MAX; + Wave.color_mode = MODE_COLORS_NONE; + Wave.brightness_min = GMOW_BRIGHTNESS_MIN; + Wave.brightness = GMOW_BRIGHTNESS_MID; + Wave.brightness_max = GMOW_BRIGHTNESS_MAX; + Wave.value = GMOW_MODE_WAVE; + modes.push_back(Wave); + + SetupZones(); +} + +RGBController_GMOW::~RGBController_GMOW() +{ + delete controller; +} + +void RGBController_GMOW::SetupZones() +{ + +} + +void RGBController_GMOW::ResizeZone(int /*zone*/, int /*new_size*/) +{ + +} + +void RGBController_GMOW::DeviceUpdateLEDs() +{ + +} + +void RGBController_GMOW::UpdateZoneLEDs(int /*zone*/) +{ + +} + +void RGBController_GMOW::UpdateSingleLED(int /*led*/) +{ + +} + +void RGBController_GMOW::DeviceUpdateMode() +{ + mode curr = modes[active_mode]; + controller->SetMode(active_mode, curr.speed,curr.brightness, curr.brightness, curr.colors.data(), (unsigned char)curr.colors.size()); +} diff --git a/Controllers/SinowealthController/SinowealthGMOWController/RGBController_SinowealthGMOW.h b/Controllers/SinowealthController/SinowealthGMOWController/RGBController_SinowealthGMOW.h new file mode 100644 index 00000000..eec3a645 --- /dev/null +++ b/Controllers/SinowealthController/SinowealthGMOWController/RGBController_SinowealthGMOW.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_SinowealthGMOW.h | +| | +| RGBController for Glorious Model O Wireless | +| | +| Matt Silva (thesilvanator) May 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SinowealthGMOWController.h" + +class RGBController_GMOW : public RGBController +{ +public: + RGBController_GMOW(SinowealthGMOWController* sinowealth_ptr); + ~RGBController_GMOW(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + SinowealthGMOWController* controller; +}; diff --git a/Controllers/SinowealthController/SinowealthGMOWController.cpp b/Controllers/SinowealthController/SinowealthGMOWController/SinowealthGMOWController.cpp similarity index 86% rename from Controllers/SinowealthController/SinowealthGMOWController.cpp rename to Controllers/SinowealthController/SinowealthGMOWController/SinowealthGMOWController.cpp index c8b454cc..53e057a4 100644 --- a/Controllers/SinowealthController/SinowealthGMOWController.cpp +++ b/Controllers/SinowealthController/SinowealthGMOWController/SinowealthGMOWController.cpp @@ -1,21 +1,26 @@ -/*-------------------------------------------*\ -| SinowealthGMOWController.cpp | -| | -| Support for the Glorious Model O Wireless | -| | -| Matt Silva (thesilvanator) 05/2022 | -\*-------------------------------------------*/ +/*---------------------------------------------------------*\ +| SinowealthGMOWController.cpp | +| | +| Driver for Glorious Model O Wireless | +| | +| Matt Silva (thesilvanator) May 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "SinowealthGMOWController.h" #include -#include - #include +#include "LogManager.h" +#include "SinowealthGMOWController.h" +#include "StringUtils.h" -SinowealthGMOWController::SinowealthGMOWController(hid_device* dev_handle, char *_path, int _type) +SinowealthGMOWController::SinowealthGMOWController(hid_device* dev_handle, char *_path, int _type, std::string dev_name) { - dev = dev_handle; - location = _path; + dev = dev_handle; + location = _path; + name = dev_name; + type = _type; memset(mode_packet,0x00, GMOW_PACKET_SIZE); mode_packet[0x03] = 0x02; @@ -32,8 +37,6 @@ SinowealthGMOWController::SinowealthGMOWController(hid_device* dev_handle, char memcpy(less_packet, wired_packet, GMOW_PACKET_SIZE); less_packet[0x07] = 0x00; - - type = _type; } SinowealthGMOWController::~SinowealthGMOWController() @@ -46,6 +49,11 @@ std::string SinowealthGMOWController::GetLocation() return("HID: " + location); } +std::string SinowealthGMOWController::GetName() +{ + return(name); +} + std::string SinowealthGMOWController::GetSerialString() { wchar_t serial_string[128]; @@ -56,10 +64,7 @@ std::string SinowealthGMOWController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } std::string SinowealthGMOWController::GetFirmwareVersion() @@ -233,4 +238,4 @@ void SinowealthGMOWController::SetMode(unsigned char mode, hid_send_feature_report(dev, less_buff, GMOW_PACKET_SIZE); -} \ No newline at end of file +} diff --git a/Controllers/SinowealthController/SinowealthGMOWController/SinowealthGMOWController.h b/Controllers/SinowealthController/SinowealthGMOWController/SinowealthGMOWController.h new file mode 100644 index 00000000..49b2da03 --- /dev/null +++ b/Controllers/SinowealthController/SinowealthGMOWController/SinowealthGMOWController.h @@ -0,0 +1,87 @@ +/*---------------------------------------------------------*\ +| SinowealthGMOWController.h | +| | +| Driver for Glorious Model O Wireless | +| | +| Matt Silva (thesilvanator) May 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define GMOW_PACKET_SIZE 64 + 1 + +enum +{ + GMOW_MODE_OFF = 0x00, + GMOW_MODE_RAINBOW_WAVE = 0x01, + GMOW_MODE_SPECTRUM_CYCLE = 0x02, + GMOW_MODE_CUSTOM_BREATHING = 0x03, + GMOW_MODE_STATIC = 0x04, + GMOW_MODE_BREATHING = 0x05, + GMOW_MODE_TAIL = 0x06, + GMOW_MODE_RAVE = 0x07, + GMOW_MODE_WAVE = 0x08, +}; + +enum +{ + GMOW_SPEED1_MIN = 0x14, + GMOW_SPEED1_MID = 0x0B, + GMOW_SPEED1_MAX = 0x01, + + GMOW_SPEED2_MIN = 0xC8, + GMOW_SPEED2_MID = 0x6E, + GMOW_SPEED2_MAX = 0x0A, +}; + + +enum +{ + GMOW_BRIGHTNESS_MIN = 0x00, + GMOW_BRIGHTNESS_MID = 0x7F, + GMOW_BRIGHTNESS_MAX = 0xFF, +}; + +enum +{ + GMOW_CABLE_CONNECTED, + GMOW_DONGLE_CONNECTED +}; + + +class SinowealthGMOWController +{ +public: + SinowealthGMOWController(hid_device* dev_handle, char *_path, int type, std::string dev_name); + ~SinowealthGMOWController(); + + std::string GetLocation(); + std::string GetName(); + std::string GetSerialString(); + + void SetMode(unsigned char mode, + unsigned char speed, + unsigned char wired_brightness, + unsigned char less_brightness, + RGBColor* color_buf, + unsigned char color_count); + + std::string GetFirmwareVersion(); + +private: + hid_device* dev; + unsigned char mode_packet[GMOW_PACKET_SIZE]; + unsigned char wired_packet[GMOW_PACKET_SIZE]; + unsigned char less_packet[GMOW_PACKET_SIZE]; + + std::string location; + std::string name; + int type; +}; diff --git a/Controllers/SinowealthController/RGBController_SinowealthKeyboard16.cpp b/Controllers/SinowealthController/SinowealthKeyboard16Controller/RGBController_SinowealthKeyboard16.cpp similarity index 97% rename from Controllers/SinowealthController/RGBController_SinowealthKeyboard16.cpp rename to Controllers/SinowealthController/SinowealthKeyboard16Controller/RGBController_SinowealthKeyboard16.cpp index 15f2b8b4..8d012b7d 100644 --- a/Controllers/SinowealthController/RGBController_SinowealthKeyboard16.cpp +++ b/Controllers/SinowealthController/SinowealthKeyboard16Controller/RGBController_SinowealthKeyboard16.cpp @@ -182,13 +182,13 @@ static const char *led_names_tkl[] = RGBController_SinowealthKeyboard16::RGBController_SinowealthKeyboard16(SinowealthKeyboard16Controller* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Sinowealth Keyboard"; - type = DEVICE_TYPE_KEYBOARD; - description = "Generic Sinowealth Keyboard"; - location = controller->GetLocation(); - serial = controller->GetSerialString(); + name = controller->GetName(); + type = DEVICE_TYPE_KEYBOARD; + description = "Sinowealth Keyboard Device"; + location = controller->GetLocation(); + serial = controller->GetSerialString(); std::vector modes_cfg = controller->GetDeviceModes(); std::vector color_presets = controller->GetDeviceColors(); diff --git a/Controllers/SinowealthController/RGBController_SinowealthKeyboard16.h b/Controllers/SinowealthController/SinowealthKeyboard16Controller/RGBController_SinowealthKeyboard16.h similarity index 100% rename from Controllers/SinowealthController/RGBController_SinowealthKeyboard16.h rename to Controllers/SinowealthController/SinowealthKeyboard16Controller/RGBController_SinowealthKeyboard16.h diff --git a/Controllers/SinowealthController/SinowealthKeyboard16Controller.cpp b/Controllers/SinowealthController/SinowealthKeyboard16Controller/SinowealthKeyboard16Controller.cpp similarity index 98% rename from Controllers/SinowealthController/SinowealthKeyboard16Controller.cpp rename to Controllers/SinowealthController/SinowealthKeyboard16Controller/SinowealthKeyboard16Controller.cpp index 4faee271..01e5be0c 100644 --- a/Controllers/SinowealthController/SinowealthKeyboard16Controller.cpp +++ b/Controllers/SinowealthController/SinowealthKeyboard16Controller/SinowealthKeyboard16Controller.cpp @@ -11,10 +11,11 @@ | Dmitri Kalinichenko (Dima-Kal) 23/06/2021 | \*-----------------------------------------=*/ -#include "SinowealthKeyboard16Controller.h" -#include "LogManager.h" -#include #include +#include +#include "LogManager.h" +#include "SinowealthKeyboard16Controller.h" +#include "StringUtils.h" using namespace std::chrono_literals; using namespace kbd16; @@ -28,7 +29,7 @@ static unsigned char request_per_led_cm5[] = {0x05, 0x89, 0xB4, 0x00, 0x40, 0x0 SinowealthKeyboard16Controller::SinowealthKeyboard16Controller(hid_device* cmd_handle, hid_device* data_handle, char* path, std::string dev_name) -{ +{ dev_cmd = cmd_handle; dev_data = data_handle; name = dev_name; @@ -55,6 +56,11 @@ std::string SinowealthKeyboard16Controller::GetLocation() return("HID: " + location); } +std::string SinowealthKeyboard16Controller::GetName() +{ + return(name); +} + unsigned char SinowealthKeyboard16Controller::GetCurrentMode() { return current_mode; @@ -75,10 +81,7 @@ std::string SinowealthKeyboard16Controller::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void SinowealthKeyboard16Controller::SetLEDsDirect(std::vector colors) @@ -213,7 +216,7 @@ std::vector SinowealthKeyboard16Controller::GetPerLedColors() res[i] = color; } - + return res; } diff --git a/Controllers/SinowealthController/SinowealthKeyboard16Controller.h b/Controllers/SinowealthController/SinowealthKeyboard16Controller/SinowealthKeyboard16Controller.h similarity index 98% rename from Controllers/SinowealthController/SinowealthKeyboard16Controller.h rename to Controllers/SinowealthController/SinowealthKeyboard16Controller/SinowealthKeyboard16Controller.h index 874ee27a..e7827407 100644 --- a/Controllers/SinowealthController/SinowealthKeyboard16Controller.h +++ b/Controllers/SinowealthController/SinowealthKeyboard16Controller/SinowealthKeyboard16Controller.h @@ -13,7 +13,7 @@ #include "RGBController.h" #include -#include +#include #pragma once @@ -109,6 +109,7 @@ public: unsigned int GetLEDCount(); std::string GetLocation(); + std::string GetName(); std::string GetSerialString(); unsigned char GetCurrentMode(); std::vector GetDeviceModes(); diff --git a/Controllers/SinowealthController/RGBController_SinowealthKeyboard90.cpp b/Controllers/SinowealthController/SinowealthKeyboard90Controller/RGBController_SinowealthKeyboard90.cpp similarity index 95% rename from Controllers/SinowealthController/RGBController_SinowealthKeyboard90.cpp rename to Controllers/SinowealthController/SinowealthKeyboard90Controller/RGBController_SinowealthKeyboard90.cpp index 5e8fef0b..c3360816 100644 --- a/Controllers/SinowealthController/RGBController_SinowealthKeyboard90.cpp +++ b/Controllers/SinowealthController/SinowealthKeyboard90Controller/RGBController_SinowealthKeyboard90.cpp @@ -28,7 +28,7 @@ RGBController_SinowealthKeyboard90::RGBController_SinowealthKeyboard90(Sinowealt { controller = controller_ptr; - name = "Genesis Thor 300"; + name = controller->GetNameString(); vendor = "Sinowealth"; type = DEVICE_TYPE_KEYBOARD; description = "Generic Sinowealth Keyboard"; @@ -72,7 +72,7 @@ RGBController_SinowealthKeyboard90::RGBController_SinowealthKeyboard90(Sinowealt Off.color_mode = MODE_COLORS_NONE; modes.push_back(Off); - active_mode = modes.size() - 1; + active_mode = (int)modes.size() - 1; SetupZones(); } @@ -156,14 +156,6 @@ void RGBController_SinowealthKeyboard90::UpdateSingleLED(int /*key*/) DeviceUpdateLEDs(); } -void RGBController_SinowealthKeyboard90::SetCustomMode() -{ - /*---------------------------------------------------------*\ - | In our case, custom mode is on index MODE_CUSTOM | - \*---------------------------------------------------------*/ - active_mode = MODE_CUSTOM; -} - void RGBController_SinowealthKeyboard90::DeviceUpdateMode() { if (modes[active_mode].value == MODE_CUSTOM) diff --git a/Controllers/SinowealthController/RGBController_SinowealthKeyboard90.h b/Controllers/SinowealthController/SinowealthKeyboard90Controller/RGBController_SinowealthKeyboard90.h similarity index 96% rename from Controllers/SinowealthController/RGBController_SinowealthKeyboard90.h rename to Controllers/SinowealthController/SinowealthKeyboard90Controller/RGBController_SinowealthKeyboard90.h index 1fe22985..175f3650 100644 --- a/Controllers/SinowealthController/RGBController_SinowealthKeyboard90.h +++ b/Controllers/SinowealthController/SinowealthKeyboard90Controller/RGBController_SinowealthKeyboard90.h @@ -26,7 +26,6 @@ public: void UpdateZoneLEDs(int zone); void UpdateSingleLED(int led); - void SetCustomMode(); void DeviceUpdateMode(); private: diff --git a/Controllers/SinowealthController/SinowealthKeyboard90Controller.cpp b/Controllers/SinowealthController/SinowealthKeyboard90Controller/SinowealthKeyboard90Controller.cpp similarity index 92% rename from Controllers/SinowealthController/SinowealthKeyboard90Controller.cpp rename to Controllers/SinowealthController/SinowealthKeyboard90Controller/SinowealthKeyboard90Controller.cpp index 31bb6a92..16cb98d8 100644 --- a/Controllers/SinowealthController/SinowealthKeyboard90Controller.cpp +++ b/Controllers/SinowealthController/SinowealthKeyboard90Controller/SinowealthKeyboard90Controller.cpp @@ -8,16 +8,18 @@ | Jan Baier 30/06/2022 | \*-----------------------------------------=*/ -#include "SinowealthKeyboard90Controller.h" -#include "LogManager.h" #include +#include "LogManager.h" +#include "SinowealthKeyboard90Controller.h" +#include "StringUtils.h" using namespace thor300; -SinowealthKeyboard90Controller::SinowealthKeyboard90Controller(hid_device* dev_handle, const char* path, const unsigned short pid) +SinowealthKeyboard90Controller::SinowealthKeyboard90Controller(hid_device* dev_handle, const char* path, const unsigned short pid, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; usb_pid = pid; } @@ -31,6 +33,11 @@ std::string SinowealthKeyboard90Controller::GetDeviceLocation() return("HID: " + location); } +std::string SinowealthKeyboard90Controller::GetNameString() +{ + return(name); +} + std::string SinowealthKeyboard90Controller::GetSerialString() { wchar_t serial_string[128]; @@ -41,10 +48,7 @@ std::string SinowealthKeyboard90Controller::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } unsigned short SinowealthKeyboard90Controller::GetUSBPID() diff --git a/Controllers/SinowealthController/SinowealthKeyboard90Controller.h b/Controllers/SinowealthController/SinowealthKeyboard90Controller/SinowealthKeyboard90Controller.h similarity index 98% rename from Controllers/SinowealthController/SinowealthKeyboard90Controller.h rename to Controllers/SinowealthController/SinowealthKeyboard90Controller/SinowealthKeyboard90Controller.h index 3719442f..bc4184e3 100644 --- a/Controllers/SinowealthController/SinowealthKeyboard90Controller.h +++ b/Controllers/SinowealthController/SinowealthKeyboard90Controller/SinowealthKeyboard90Controller.h @@ -11,7 +11,7 @@ #include "RGBController.h" #include "RGBControllerKeyNames.h" #include -#include +#include #pragma once @@ -201,11 +201,13 @@ namespace thor300 class SinowealthKeyboard90Controller { public: - SinowealthKeyboard90Controller(hid_device* dev_handle, const char* path, const unsigned short pid); + SinowealthKeyboard90Controller(hid_device* dev_handle, const char* path, const unsigned short pid, std::string dev_name); ~SinowealthKeyboard90Controller(); std::string GetDeviceLocation(); + std::string GetNameString(); std::string GetSerialString(); + unsigned short GetUSBPID(); void SendMode @@ -228,7 +230,6 @@ public: private: hid_device* dev; - device_type type; std::string name; std::string location; unsigned short usb_pid; diff --git a/Controllers/SinowealthController/SinowealthKeyboardController/RGBController_SinowealthKeyboard.cpp b/Controllers/SinowealthController/SinowealthKeyboardController/RGBController_SinowealthKeyboard.cpp new file mode 100644 index 00000000..36fca8a7 --- /dev/null +++ b/Controllers/SinowealthController/SinowealthKeyboardController/RGBController_SinowealthKeyboard.cpp @@ -0,0 +1,479 @@ +/*------------------------------------------*\ +| RGBController_SinowealthKeyboard.cpp | +| | +| Definitions and types for Sinowealth | +| Keyboard, Hopefully generic, this was | +| made spefically for FL eSports F11 KB | +| | +| Dmitri Kalinichenko (Dima-Kal) 23/06/2021 | +\*-----------------------------------------=*/ + +#include "RGBControllerKeyNames.h" +#include "RGBController_SinowealthKeyboard.h" + +#define NA 0xFFFFFFFF + +static unsigned int tkl_matrix_map[6][17] = + { { 8, NA, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}, + { 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45}, + { 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66}, + { 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 84, NA, NA, NA, NA}, + { 93, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 106, NA, NA, NA, 107, NA}, + { 113, 114, 115, NA, NA, NA, 118, NA, NA, NA, NA, 121, 122, 123, 127, 128, 129}}; + + +static const char *led_names_tkl[] = +{ + KEY_EN_ESCAPE, + KEY_EN_F1, + KEY_EN_F2, + KEY_EN_F3, + KEY_EN_F4, + KEY_EN_F5, + KEY_EN_F6, + KEY_EN_F7, + KEY_EN_F8, + KEY_EN_F9, + KEY_EN_F10, + KEY_EN_F11, + KEY_EN_F12, + KEY_EN_PRINT_SCREEN, + KEY_EN_SCROLL_LOCK, + "Key: Pause", + + KEY_EN_BACK_TICK, + KEY_EN_1, + KEY_EN_2, + KEY_EN_3, + KEY_EN_4, + KEY_EN_5, + KEY_EN_6, + KEY_EN_7, + KEY_EN_8, + KEY_EN_9, + KEY_EN_0, + KEY_EN_MINUS, + KEY_EN_EQUALS, + KEY_EN_BACKSPACE, + KEY_EN_INSERT, + KEY_EN_HOME, + KEY_EN_PAGE_UP, + + KEY_EN_TAB, + KEY_EN_Q, + KEY_EN_W, + KEY_EN_E, + KEY_EN_R, + KEY_EN_T, + KEY_EN_Y, + KEY_EN_U, + KEY_EN_I, + KEY_EN_O, + KEY_EN_P, + KEY_EN_LEFT_BRACKET, + KEY_EN_RIGHT_BRACKET, + KEY_EN_ANSI_BACK_SLASH, + KEY_EN_DELETE, + KEY_EN_END, + KEY_EN_PAGE_DOWN, + + KEY_EN_CAPS_LOCK, + KEY_EN_A, + KEY_EN_S, + KEY_EN_D, + KEY_EN_F, + KEY_EN_G, + KEY_EN_H, + KEY_EN_J, + KEY_EN_K, + KEY_EN_L, + KEY_EN_SEMICOLON, + KEY_EN_QUOTE, + KEY_EN_ANSI_ENTER, + + KEY_EN_LEFT_SHIFT, + KEY_EN_Z, + KEY_EN_X, + KEY_EN_C, + KEY_EN_V, + KEY_EN_B, + KEY_EN_N, + KEY_EN_M, + KEY_EN_COMMA, + KEY_EN_PERIOD, + KEY_EN_FORWARD_SLASH, + KEY_EN_RIGHT_SHIFT, + KEY_EN_UP_ARROW, + + KEY_EN_LEFT_CONTROL, + KEY_EN_LEFT_WINDOWS, + KEY_EN_LEFT_ALT, + KEY_EN_SPACE, + KEY_EN_RIGHT_CONTROL, + KEY_EN_RIGHT_ALT, + KEY_EN_RIGHT_WINDOWS, + KEY_EN_RIGHT_FUNCTION, + KEY_EN_LEFT_ARROW, + KEY_EN_DOWN_ARROW, + KEY_EN_RIGHT_ARROW, +}; + +/**------------------------------------------------------------------*\ + @name Sinowealth Keyboard + @category Keyboard + @type USB + @save :x: + @direct :x: + @effects :white_check_mark: + @detectors DetectSinowealthKeyboard + @comment +\*-------------------------------------------------------------------*/ + +RGBController_SinowealthKeyboard::RGBController_SinowealthKeyboard(SinowealthKeyboardController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + type = DEVICE_TYPE_KEYBOARD; + description = "Sinowealth Keyboard Device"; + location = controller->GetLocation(); + serial = controller->GetSerialString(); + + mode Static; + Static.name = "Static"; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.value = MODE_STATIC; + Static.colors_min = 1; + Static.colors_max = 1; + Static.colors.resize(1); + modes.push_back(Static); + + mode Custom; + Custom.name = "Custom"; + Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Custom.color_mode = MODE_COLORS_PER_LED; + Custom.value = MODE_PER_KEY; + modes.push_back(Custom); + + mode Off; + Off.name = "Off"; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; + Off.value = MODE_OFF; + modes.push_back(Off); + + mode Respire; + Respire.name = "Respire"; + Respire.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Respire.speed_min = SPEED_SLOW; + Respire.speed = SPEED_NORMAL; + Respire.speed_max = SPEED_FASTEST; + Respire.color_mode = MODE_COLORS_RANDOM; + Respire.value = MODE_RESPIRE; + Respire.colors_min = 1; + Respire.colors_max = 1; + Respire.colors.resize(1); + modes.push_back(Respire); + + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Rainbow.speed_min = SPEED_SLOW; + Rainbow.speed = SPEED_NORMAL; + Rainbow.speed_max = SPEED_FASTEST; + Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.value = MODE_RAINBOW; + modes.push_back(Rainbow); + + mode FlashAway; + FlashAway.name = "Flash Away"; + FlashAway.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + FlashAway.speed_min = SPEED_SLOW; + FlashAway.speed = SPEED_NORMAL; + FlashAway.speed_max = SPEED_FASTEST; + FlashAway.color_mode = MODE_COLORS_RANDOM; + FlashAway.value = MODE_FLASH_AWAY; + FlashAway.colors_min = 1; + FlashAway.colors_max = 1; + FlashAway.colors.resize(1); + modes.push_back(FlashAway); + + mode Raindrops; + Raindrops.name = "Raindrops"; + Raindrops.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Raindrops.speed_min = SPEED_SLOW; + Raindrops.speed = SPEED_NORMAL; + Raindrops.speed_max = SPEED_FASTEST; + Raindrops.color_mode = MODE_COLORS_RANDOM; + Raindrops.value = MODE_RAINDROPS; + Raindrops.colors_min = 1; + Raindrops.colors_max = 1; + Raindrops.colors.resize(1); + modes.push_back(Raindrops); + + mode RainbowWheel; + RainbowWheel.name = "Rainbow Wheel"; + RainbowWheel.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + RainbowWheel.speed_min = SPEED_SLOW; + RainbowWheel.speed = SPEED_NORMAL; + RainbowWheel.speed_max = SPEED_FASTEST; + RainbowWheel.color_mode = MODE_COLORS_RANDOM; + RainbowWheel.value = MODE_RAINBOW_WHEEL; + RainbowWheel.colors_min = 1; + RainbowWheel.colors_max = 1; + RainbowWheel.colors.resize(1); + modes.push_back(RainbowWheel); + + mode RipplesShining; + RipplesShining.name = "Ripples Shining"; + RipplesShining.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + RipplesShining.speed_min = SPEED_SLOW; + RipplesShining.speed = SPEED_NORMAL; + RipplesShining.speed_max = SPEED_FASTEST; + RipplesShining.color_mode = MODE_COLORS_RANDOM; + RipplesShining.value = MODE_RIPPLES_SHINING; + RipplesShining.colors_min = 1; + RipplesShining.colors_max = 1; + RipplesShining.colors.resize(1); + modes.push_back(RipplesShining); + + mode StarsTwinkle; + StarsTwinkle.name = "Stars Twinkle"; + StarsTwinkle.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + StarsTwinkle.speed_min = SPEED_SLOW; + StarsTwinkle.speed = SPEED_NORMAL; + StarsTwinkle.speed_max = SPEED_FASTEST; + StarsTwinkle.color_mode = MODE_COLORS_RANDOM; + StarsTwinkle.value = MODE_STARS_TWINKLE; + StarsTwinkle.colors_min = 1; + StarsTwinkle.colors_max = 1; + StarsTwinkle.colors.resize(1); + modes.push_back(StarsTwinkle); + + mode ShadowDisappear; + ShadowDisappear.name = "Shadow Disappear"; + ShadowDisappear.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + ShadowDisappear.speed_min = SPEED_SLOW; + ShadowDisappear.speed = SPEED_NORMAL; + ShadowDisappear.speed_max = SPEED_FASTEST; + ShadowDisappear.color_mode = MODE_COLORS_RANDOM; + ShadowDisappear.value = MODE_SHADOW_DISAPPEAR; + ShadowDisappear.colors_min = 1; + ShadowDisappear.colors_max = 1; + ShadowDisappear.colors.resize(1); + modes.push_back(ShadowDisappear); + + mode RetroSnake; + RetroSnake.name = "Retro Snake"; + RetroSnake.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + RetroSnake.speed_min = SPEED_SLOW; + RetroSnake.speed = SPEED_NORMAL; + RetroSnake.speed_max = SPEED_FASTEST; + RetroSnake.color_mode = MODE_COLORS_RANDOM; + RetroSnake.value = MODE_RETRO_SNAKE; + RetroSnake.colors_min = 1; + RetroSnake.colors_max = 1; + RetroSnake.colors.resize(1); + modes.push_back(RetroSnake); + + mode NeonStream; + NeonStream.name = "Neon Stream"; + NeonStream.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + NeonStream.speed_min = SPEED_SLOW; + NeonStream.speed = SPEED_NORMAL; + NeonStream.speed_max = SPEED_FASTEST; + NeonStream.color_mode = MODE_COLORS_RANDOM; + NeonStream.value = MODE_NEON_STREAM; + NeonStream.colors_min = 1; + NeonStream.colors_max = 1; + NeonStream.colors.resize(1); + modes.push_back(NeonStream); + + mode Reaction; + Reaction.name = "Reaction"; + Reaction.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Reaction.speed_min = SPEED_SLOW; + Reaction.speed = SPEED_NORMAL; + Reaction.speed_max = SPEED_FASTEST; + Reaction.color_mode = MODE_COLORS_RANDOM; + Reaction.value = MODE_REACTION; + Reaction.colors_min = 1; + Reaction.colors_max = 1; + Reaction.colors.resize(1); + modes.push_back(Reaction); + + mode SineWave; + SineWave.name = "Sine Wave"; + SineWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + SineWave.speed_min = SPEED_SLOW; + SineWave.speed = SPEED_NORMAL; + SineWave.speed_max = SPEED_FASTEST; + SineWave.color_mode = MODE_COLORS_RANDOM; + SineWave.value = MODE_SINE_WAVE; + SineWave.colors_min = 1; + SineWave.colors_max = 1; + SineWave.colors.resize(1); + modes.push_back(SineWave); + + mode RetinueScanning; + RetinueScanning.name = "Retinue Scanning"; + RetinueScanning.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + RetinueScanning.speed_min = SPEED_SLOW; + RetinueScanning.speed = SPEED_NORMAL; + RetinueScanning.speed_max = SPEED_FASTEST; + RetinueScanning.color_mode = MODE_COLORS_RANDOM; + RetinueScanning.value = MODE_RETINUE_SCANNING; + RetinueScanning.colors_min = 1; + RetinueScanning.colors_max = 1; + RetinueScanning.colors.resize(1); + modes.push_back(RetinueScanning); + + mode RotatingWindmill; + RotatingWindmill.name = "Rotating Windmill"; + RotatingWindmill.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + RotatingWindmill.speed_min = SPEED_SLOW; + RotatingWindmill.speed = SPEED_NORMAL; + RotatingWindmill.speed_max = SPEED_FASTEST; + RotatingWindmill.color_mode = MODE_COLORS_RANDOM; + RotatingWindmill.value = MODE_ROTATING_WINDMILL; + RotatingWindmill.colors_min = 1; + RotatingWindmill.colors_max = 1; + RotatingWindmill.colors.resize(1); + modes.push_back(RotatingWindmill); + + mode ColorfulWaterfall; + ColorfulWaterfall.name = "Colorful Waterfall"; + ColorfulWaterfall.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + ColorfulWaterfall.speed_min = SPEED_SLOW; + ColorfulWaterfall.speed = SPEED_NORMAL; + ColorfulWaterfall.speed_max = SPEED_FASTEST; + ColorfulWaterfall.color_mode = MODE_COLORS_NONE; + ColorfulWaterfall.value = MODE_COLORFUL_WATERFALL; + modes.push_back(ColorfulWaterfall); + + mode Blossoming; + Blossoming.name = "Blossoming"; + Blossoming.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS; + Blossoming.speed_min = SPEED_SLOW; + Blossoming.speed = SPEED_NORMAL; + Blossoming.speed_max = SPEED_FASTEST; + Blossoming.color_mode = MODE_COLORS_NONE; + Blossoming.value = MODE_BLOSSOMING; + modes.push_back(Blossoming); + + mode RotatingStorm; + RotatingStorm.name = "Rotating Storm"; + RotatingStorm.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + RotatingStorm.speed_min = SPEED_SLOW; + RotatingStorm.speed = SPEED_NORMAL; + RotatingStorm.speed_max = SPEED_FASTEST; + RotatingStorm.color_mode = MODE_COLORS_RANDOM; + RotatingStorm.value = MODE_ROTATING_STORM; + RotatingStorm.colors_min = 1; + RotatingStorm.colors_max = 1; + RotatingStorm.colors.resize(1); + modes.push_back(RotatingStorm); + + mode Collision; + Collision.name = "Collision"; + Collision.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Collision.speed_min = SPEED_SLOW; + Collision.speed = SPEED_NORMAL; + Collision.speed_max = SPEED_FASTEST; + Collision.color_mode = MODE_COLORS_RANDOM; + Collision.value = MODE_COLLISION; + Collision.colors_min = 1; + Collision.colors_max = 1; + Collision.colors.resize(1); + modes.push_back(Collision); + + mode Perfect; + Perfect.name = "Perfect"; + Perfect.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Perfect.speed_min = SPEED_SLOW; + Perfect.speed = SPEED_NORMAL; + Perfect.speed_max = SPEED_FASTEST; + Perfect.color_mode = MODE_COLORS_RANDOM; + Perfect.value = MODE_PERFECT; + Perfect.colors_min = 1; + Perfect.colors_max = 1; + Perfect.colors.resize(1); + modes.push_back(Perfect); + + SetupZones(); +} + +RGBController_SinowealthKeyboard::~RGBController_SinowealthKeyboard() +{ + delete controller; +} + +void RGBController_SinowealthKeyboard::SetupZones() +{ + /*---------------------------------------------------------*\ + | Set up zones | + \*---------------------------------------------------------*/ + zone new_zone; + + new_zone.name = ZONE_EN_KEYBOARD; + new_zone.type = ZONE_TYPE_MATRIX; + new_zone.leds_min = 86; + new_zone.leds_max = 86; + new_zone.leds_count = 86; + new_zone.matrix_map = new matrix_map_type; + new_zone.matrix_map->height = 6; + new_zone.matrix_map->width = 17; + new_zone.matrix_map->map = (unsigned int *)&tkl_matrix_map; + + zones.push_back(new_zone); + + /*---------------------------------------------------------*\ + | Set up LEDs | + \*---------------------------------------------------------*/ + for(unsigned int led_idx = 0; led_idx < 86; led_idx++) + { + led new_led; + new_led.name = led_names_tkl[led_idx]; + leds.push_back(new_led); + } + + SetupColors(); +} + +void RGBController_SinowealthKeyboard::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_SinowealthKeyboard::DeviceUpdateLEDs() +{ + controller->SetLEDsDirect(colors); +} + +void RGBController_SinowealthKeyboard::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_SinowealthKeyboard::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_SinowealthKeyboard::DeviceUpdateMode() +{ + unsigned int brightness = BRIGHTNESS_FULL; + RGBColor* selected_color = (modes[active_mode].color_mode == MODE_COLORS_NONE) ? 0 : &modes[active_mode].colors[0]; + + if(modes[active_mode].value == MODE_STATIC) + { + controller->SetStaticColor(selected_color); + } + else + { + controller->SetMode(modes[active_mode].value, brightness, modes[active_mode].speed, modes[active_mode].color_mode); + } +} diff --git a/Controllers/SinowealthController/RGBController_SinowealthKeyboard.h b/Controllers/SinowealthController/SinowealthKeyboardController/RGBController_SinowealthKeyboard.h similarity index 100% rename from Controllers/SinowealthController/RGBController_SinowealthKeyboard.h rename to Controllers/SinowealthController/SinowealthKeyboardController/RGBController_SinowealthKeyboard.h diff --git a/Controllers/SinowealthController/SinowealthKeyboardController.cpp b/Controllers/SinowealthController/SinowealthKeyboardController/SinowealthKeyboardController.cpp similarity index 97% rename from Controllers/SinowealthController/SinowealthKeyboardController.cpp rename to Controllers/SinowealthController/SinowealthKeyboardController/SinowealthKeyboardController.cpp index 2fe6a865..cc57420b 100644 --- a/Controllers/SinowealthController/SinowealthKeyboardController.cpp +++ b/Controllers/SinowealthController/SinowealthKeyboardController/SinowealthKeyboardController.cpp @@ -8,8 +8,9 @@ | Dmitri Kalinichenko (Dima-Kal) 23/06/2021 | \*-----------------------------------------=*/ -#include "SinowealthKeyboardController.h" #include +#include "SinowealthKeyboardController.h" +#include "StringUtils.h" static unsigned char send_per_key_part_of_command_packet[] = { 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, @@ -70,10 +71,11 @@ static unsigned int keys_tkl_keys_indices_static_command[] = { 0x0022, 0x0024, 0x01E0, 0x01E2, 0x01E4, 0x01E6, 0x01E7, 0x01E8, 0x01E9, 0x01EA}; -SinowealthKeyboardController::SinowealthKeyboardController(hid_device* dev_cmd_handle, hid_device* dev_data_handle, char* path) +SinowealthKeyboardController::SinowealthKeyboardController(hid_device* dev_cmd_handle, hid_device* dev_data_handle, char* path, std::string dev_name) { - dev_cmd = dev_cmd_handle; - dev_data = dev_data_handle; + dev_cmd = dev_cmd_handle; + dev_data = dev_data_handle; + name = dev_name; led_count = sizeof(tkl_keys_per_key_index) / sizeof(*tkl_keys_per_key_index); @@ -94,6 +96,11 @@ std::string SinowealthKeyboardController::GetLocation() return("HID: " + location); } +std::string SinowealthKeyboardController::GetName() +{ + return(name); +} + unsigned char SinowealthKeyboardController::GetCurrentMode() { return current_mode; @@ -114,10 +121,7 @@ std::string SinowealthKeyboardController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void SinowealthKeyboardController::SetLEDsDirect(std::vector colors) diff --git a/Controllers/SinowealthController/SinowealthKeyboardController.h b/Controllers/SinowealthController/SinowealthKeyboardController/SinowealthKeyboardController.h similarity index 94% rename from Controllers/SinowealthController/SinowealthKeyboardController.h rename to Controllers/SinowealthController/SinowealthKeyboardController/SinowealthKeyboardController.h index 52a5bc6e..6ef5c7bc 100644 --- a/Controllers/SinowealthController/SinowealthKeyboardController.h +++ b/Controllers/SinowealthController/SinowealthKeyboardController/SinowealthKeyboardController.h @@ -10,7 +10,7 @@ #include "RGBController.h" #include -#include +#include #pragma once @@ -61,11 +61,12 @@ enum class SinowealthKeyboardController { public: - SinowealthKeyboardController(hid_device* dev_cmd_handle, hid_device* dev_data_handle, char *_path); //RGB, Command, path + SinowealthKeyboardController(hid_device* dev_cmd_handle, hid_device* dev_data_handle, char *_path, std::string dev_name); //RGB, Command, path ~SinowealthKeyboardController(); unsigned int GetLEDCount(); std::string GetLocation(); + std::string GetName(); std::string GetSerialString(); unsigned char GetCurrentMode(); @@ -79,11 +80,9 @@ private: hid_device* dev_cmd; hid_device* dev_data; device_type type; - unsigned int led_count; - unsigned char current_mode; unsigned char current_speed; - std::string location; + std::string name; }; diff --git a/Controllers/SkyloongController/RGBController_SkyloongGK104Pro.cpp b/Controllers/SkyloongController/RGBController_SkyloongGK104Pro.cpp new file mode 100644 index 00000000..725e9eb0 --- /dev/null +++ b/Controllers/SkyloongController/RGBController_SkyloongGK104Pro.cpp @@ -0,0 +1,161 @@ +/*---------------------------------------------------------*\ +| RGBController_SkyloongGK104Pro.cpp | +| | +| RGBController for Skyloong GK104 Pro | +| | +| Givo (givowo) 30 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBControllerKeyNames.h" +#include "RGBController_SkyloongGK104Pro.h" +#include "KeyboardLayoutManager.h" + +using namespace std::chrono_literals; + +/*---------------------------------------------------------------------*\ +| Skyloong GK104 Pro Keyboard KLM Layout | +\*---------------------------------------------------------------------*/ +layout_values keyboard_offset_values = +{ + { + /* ESC F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 F11 F12 PRSC SCLK PSBK */ + 0, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + /* BKTK 1 2 3 4 5 6 7 8 9 0 - = BSPC INS HOME PGUP NLCK NP/ NP* NP- */ + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, + /* TAB Q W E R T Y U I O P [ ] \ DEL END PGDN NP7 NP8 NP9 NP+ */ + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 58, 59, 60, 61, 62, 63, 64, 65, + /* CPLK A S D F G H J K L ; " # ENTR NP4 NP5 NP6 */ + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 84, 85, 86, + /* LSFT / Z X C V B N M , . / RSFT ARWU NP1 NP2 NP3 NPEN */ + 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 102, 104, 106, 107, 108, 109, + /* LCTL LWIN LALT SPC SPC SPC RALT RFNC RMNU RCTL ARWL ARWD ARWR NP0 NP. */ + 110, 111, 112, 116, 120, 121, 122, 124, 125, 126, 127, 128, 130 + }, + { + /* Add more regional layout fixes here */ + } +}; + +/**------------------------------------------------------------------*\ + @name Skyloong GK104 Pro + @category Keyboard + @type USB + @save :o: + @direct :white_check_mark: + @effects :o: + @detectors SkyloongControllerDetect + @comment +\*-------------------------------------------------------------------*/ + +RGBController_SkyloongGK104Pro::RGBController_SkyloongGK104Pro(SkyloongGK104ProController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "Skyloong"; + description = "Skyloong GK104 Pro Keyboard"; + location = controller->GetDeviceLocation(); + type = DEVICE_TYPE_KEYBOARD; + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = BRIGHTNESS_MIN; + Direct.brightness_max = BRIGHTNESS_MAX; + Direct.brightness = BRIGHTNESS_MAX; + + modes.push_back(Direct); + + SetupZones(); +} + +RGBController_SkyloongGK104Pro::~RGBController_SkyloongGK104Pro() +{ + delete controller; +} + +void RGBController_SkyloongGK104Pro::SetupZones() +{ + /*---------------------------------------------------------*\ + | Create the keyboard zone usiung Keyboard Layout Manager | + \*---------------------------------------------------------*/ + zone new_zone; + new_zone.name = ZONE_EN_KEYBOARD; + new_zone.type = ZONE_TYPE_MATRIX; + + KeyboardLayoutManager new_kb(KEYBOARD_LAYOUT_ANSI_QWERTY, KEYBOARD_SIZE_FULL, keyboard_offset_values); + + new_kb.ChangeKeys( + { + { 0, 4, 12, 0, KEY_EN_RIGHT_SHIFT, KEY_EN_UNUSED, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT }, + { 0, 4, 14, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, + { 0, 5, 4, 114, "Key: Left Space", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY }, + { 0, 5, 8, 118, "Key: Right Space", KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY } + } + ); + + matrix_map_type * new_map = new matrix_map_type; + new_zone.matrix_map = new_map; + new_zone.matrix_map->height = new_kb.GetRowCount(); + new_zone.matrix_map->width = new_kb.GetColumnCount(); + + new_zone.matrix_map->map = new unsigned int[new_map->height * new_map->width]; + new_zone.leds_count = new_kb.GetKeyCount(); + new_zone.leds_min = new_zone.leds_count; + new_zone.leds_max = new_zone.leds_count; + + /*---------------------------------------------------------*\ + | Matrix map still uses declared zone rows and columns | + | as the packet structure depends on the matrix map | + \*---------------------------------------------------------*/ + new_kb.GetKeyMap(new_map->map, KEYBOARD_MAP_FILL_TYPE_COUNT, new_map->height, new_map->width); + + /*---------------------------------------------------------*\ + | Create LEDs for the Matrix zone | + | Place keys in the layout to populate the matrix | + \*---------------------------------------------------------*/ + for(unsigned int led_idx = 0; led_idx < new_zone.leds_count; led_idx++) + { + led new_led; + + new_led.name = new_kb.GetKeyNameAt(led_idx); + new_led.value = new_kb.GetKeyValueAt(led_idx); + + leds.push_back(new_led); + } + + zones.push_back(new_zone); + + SetupColors(); +} + +void RGBController_SkyloongGK104Pro::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_SkyloongGK104Pro::DeviceUpdateLEDs() +{ + controller->SendColorPacket(colors, &leds, modes[active_mode].brightness); +} + +void RGBController_SkyloongGK104Pro::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_SkyloongGK104Pro::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_SkyloongGK104Pro::DeviceUpdateMode() +{ +} diff --git a/Controllers/SkyloongController/RGBController_SkyloongGK104Pro.h b/Controllers/SkyloongController/RGBController_SkyloongGK104Pro.h new file mode 100644 index 00000000..384f7efe --- /dev/null +++ b/Controllers/SkyloongController/RGBController_SkyloongGK104Pro.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------*\ +| RGBController_SkyloongGK104Pro.h | +| | +| RGBController for Skyloong GK104 Pro | +| | +| Givo (givowo) 30 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SkyloongGK104ProController.h" + +#define BRIGHTNESS_MIN 0 +#define BRIGHTNESS_MAX 127 + +class RGBController_SkyloongGK104Pro : public RGBController +{ +public: + RGBController_SkyloongGK104Pro(SkyloongGK104ProController* controller_ptr); + ~RGBController_SkyloongGK104Pro(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + SkyloongGK104ProController* controller; +}; diff --git a/Controllers/SkyloongController/SkyloongControllerDetect.cpp b/Controllers/SkyloongController/SkyloongControllerDetect.cpp new file mode 100644 index 00000000..464947b7 --- /dev/null +++ b/Controllers/SkyloongController/SkyloongControllerDetect.cpp @@ -0,0 +1,46 @@ +/*---------------------------------------------------------*\ +| SkyloongControllerDetect.cpp | +| | +| Detector for Skyloong Keyboards | +| | +| Givo (givowo) 30 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "SkyloongGK104ProController.h" +#include "RGBController_SkyloongGK104Pro.h" + +/*-----------------------------------------------------*\ +| Keyboard product IDs | +\*-----------------------------------------------------*/ +#define SKYLOONG_KEYBOARD_VID 0x1EA7 +#define SKYLOONG_GK104_PRO_PID 0x0907 +#define SKYLOONG_GK104_PRO_I 1 + +/******************************************************************************************\ +* * +* DetectSkyloongGK104Pro * +* * +* Tests the USB address to see if a Skyloong GK104 Pro controller exists there. * +* * +\******************************************************************************************/ +void DetectSkyloongGK104Pro(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + if(dev) + { + SkyloongGK104ProController* controller = new SkyloongGK104ProController(dev, info->path, name); + RGBController_SkyloongGK104Pro* rgb_controller = new RGBController_SkyloongGK104Pro(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +/*---------------------------------------------------------------------------------------------------------------------------------------------*\ +| Keyboards | +\*---------------------------------------------------------------------------------------------------------------------------------------------*/ +REGISTER_HID_DETECTOR_I("Skyloong GK104 Pro", DetectSkyloongGK104Pro, SKYLOONG_KEYBOARD_VID, SKYLOONG_GK104_PRO_PID, SKYLOONG_GK104_PRO_I); diff --git a/Controllers/SkyloongController/SkyloongGK104ProController.cpp b/Controllers/SkyloongController/SkyloongGK104ProController.cpp new file mode 100644 index 00000000..d471d0ea --- /dev/null +++ b/Controllers/SkyloongController/SkyloongGK104ProController.cpp @@ -0,0 +1,140 @@ +/*---------------------------------------------------------*\ +| SkyloongGK104ProController.cpp | +| | +| Driver for Skyloong GK104 Pro | +| | +| Givo (givowo) 30 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "SkyloongGK104ProController.h" + +using namespace std::chrono_literals; + +enum command +{ + ping = 0x0C, + mode = 0xB, + le_define = 0x1A +}; + +SkyloongGK104ProController::SkyloongGK104ProController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + + SendCommand(command::ping, SUBCOMMAND_NONE); + SendCommand(command::mode, MODE_ONLINE); + SendCommand(command::ping, SUBCOMMAND_NONE); +} + +SkyloongGK104ProController::~SkyloongGK104ProController() +{ + SendCommand(command::mode, MODE_OFFLINE); + hid_close(dev); +} + +std::string SkyloongGK104ProController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string SkyloongGK104ProController::GetDeviceName() +{ + return(name); +} + +void SkyloongGK104ProController::SendCommand(char command, char sub_command) +{ + unsigned char buf[PACKET_SIZE]; + memset(buf, 0x00, PACKET_SIZE); + + buf[0x01] = command; + buf[0x02] = sub_command; + + uint16_t crc = Crc16CcittFalse(buf, PACKET_SIZE); + + buf[0x07] = crc & 0xFF; + buf[0x08] = crc >> 8; + + hid_write(dev, buf, PACKET_SIZE); +} + +void SkyloongGK104ProController::SendColorPacket(std::vector colors, std::vector *leds, int brightness) +{ + unsigned char le_data[TOTAL_LED_BYTES]; + memset(le_data, 0x00, TOTAL_LED_BYTES); + + for(unsigned int i = 0; i < leds->size(); i++) + { + int index = leds->at(i).value * 4; + le_data[index++] = RGBGetRValue(colors[i]); + le_data[index++] = RGBGetGValue(colors[i]); + le_data[index++] = RGBGetBValue(colors[i]); + le_data[index++] = brightness; + } + + for(int n = 0; n < TOTAL_LED_BYTES; n += LED_BYTES_IN_CHUNK) { + if(n + LED_BYTES_IN_CHUNK <= TOTAL_LED_BYTES) + { + SetLEDefine(n, &le_data[n], LED_BYTES_IN_CHUNK); + } + else + { + SetLEDefine(n, &le_data[n], TOTAL_LED_BYTES - n); + } + } + + SendCommand(command::le_define, LE_DEFINE_SAVE); +} + +void SkyloongGK104ProController::SetLEDefine(int address, unsigned char *le_data, int le_data_length) +{ + unsigned char buf[PACKET_SIZE]; + memset(buf, 0x00, PACKET_SIZE); + + buf[0x01] = command::le_define; + buf[0x02] = LE_DEFINE_SET; + + int header = (address + ((le_data_length << 24) & 0xFF000000)) | 0; + buf[0x03] = header & 0xFF; + buf[0x04] = (header >> 8) & 0xFF; + buf[0x05] = (header >> 16) & 0xFF; + buf[0x06] = (header >> 24) & 0xFF; + + std::copy(le_data, le_data + le_data_length, buf + 9); + + uint16_t crc = Crc16CcittFalse(buf, PACKET_SIZE); + buf[0x07] = crc & 0xFF; + buf[0x08] = crc >> 8; + + hid_write(dev, buf, PACKET_SIZE); +} + +uint16_t SkyloongGK104ProController::Crc16CcittFalse(const uint8_t *buffer, uint16_t size) +{ + uint16_t crc = 0xFFFF; + + while(size--) + { + crc ^= (*buffer++ << 8); + + for(uint8_t i = 0; i < 8; ++i) + { + if(crc & 0x8000) + { + crc = (crc << 1) ^ 0x1021; + } + else + { + crc = crc << 1; + } + } + } + + return crc; +} diff --git a/Controllers/SkyloongController/SkyloongGK104ProController.h b/Controllers/SkyloongController/SkyloongGK104ProController.h new file mode 100644 index 00000000..796fbb3e --- /dev/null +++ b/Controllers/SkyloongController/SkyloongGK104ProController.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------*\ +| SkyloongGK104ProController.h | +| | +| Driver for Skyloong GK104 Pro | +| | +| Givo (givowo) 30 Jun 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" + +#define PACKET_SIZE 65 + +#define TOTAL_LED_BYTES 528 +#define LED_BYTES_IN_CHUNK 56 + +#define SUBCOMMAND_NONE 0x00 + +#define MODE_OFFLINE 0x04 +#define MODE_ONLINE 0x05 + +#define LE_DEFINE_SET 0x01 +#define LE_DEFINE_SAVE 0x02 + +class SkyloongGK104ProController +{ +public: + SkyloongGK104ProController(hid_device* dev_handle, const char* path, std::string dev_name); + ~SkyloongGK104ProController(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + + void Ping(); + void SetMode(int mode); + void SendCommand(char command, char sub_command); + void SendColorPacket(std::vector colors, std::vector *leds, int brightness); + +private: + hid_device* dev; + std::string location; + std::string name; + + uint16_t Crc16CcittFalse(const uint8_t *buffer, uint16_t size); + void SetLEDefine(int address, unsigned char *le_data, int le_data_length); + void SaveLEDefine(); +}; diff --git a/Controllers/SonyGamepadController/RGBController_SonyDS4.h b/Controllers/SonyGamepadController/RGBController_SonyDS4.h deleted file mode 100644 index cd12aae4..00000000 --- a/Controllers/SonyGamepadController/RGBController_SonyDS4.h +++ /dev/null @@ -1,29 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SonyDS4.h | -| | -| Controller for Sony Dualshock 4 | -| | -| Pol Rius (alpemwarrior) 24/09/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include "SonyDS4Controller.h" - -class RGBController_SonyDS4 : public RGBController -{ -public: - RGBController_SonyDS4(SonyDS4Controller* controller_ptr); - ~RGBController_SonyDS4(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - SonyDS4Controller* controller; -}; diff --git a/Controllers/SonyGamepadController/RGBController_SonyDualSense.cpp b/Controllers/SonyGamepadController/RGBController_SonyDualSense.cpp deleted file mode 100644 index c796c9c4..00000000 --- a/Controllers/SonyGamepadController/RGBController_SonyDualSense.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SonyDualSense.h | -| | -| Controller for Sony DualSense | -| | -| by flora 01/07/2022 | -\*-----------------------------------------*/ - -#include -#include "RGBController_SonyDualSense.h" - -/**------------------------------------------------------------------*\ - @name Sony Dual Sense controller - @category Gamepad - @type USB - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectSonyDualSenseControllers - @comment -\*-------------------------------------------------------------------*/ - -RGBController_SonyDualSense::RGBController_SonyDualSense(SonyDualSenseController* controller_ptr) -{ - controller = controller_ptr; - - name = "Sony DualSense"; - - if(controller->IsBluetooth()) - { - name.append(" (BT)"); - } - - vendor = "Sony"; - type = DEVICE_TYPE_GAMEPAD; - description = "Sony DualSense Device"; - location = controller->GetLocation(); - serial = controller->GetSerialString(); - - mode Direct; - Direct.value = SONY_DUALSENSE_DIRECT_MODE_VALUE; - Direct.name = "Direct"; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Direct.color_mode = MODE_COLORS_PER_LED; - Direct.brightness_min = SONY_DUALSENSE_BRIGHTNESS_MIN; - Direct.brightness_max = SONY_DUALSENSE_BRIGHTNESS_MAX; - Direct.brightness = SONY_DUALSENSE_DEFAULT_BRIGHTNESS; - modes.push_back(Direct); - - mode Micoff; - Micoff.value = SONY_DUALSENSE_MIC_OFF_MODE_VALUE; - Micoff.name = "Mic Off (Direct)"; - Micoff.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Micoff.color_mode = MODE_COLORS_PER_LED; - Micoff.brightness_min = SONY_DUALSENSE_BRIGHTNESS_MIN; - Micoff.brightness_max = SONY_DUALSENSE_BRIGHTNESS_MAX; - Micoff.brightness = SONY_DUALSENSE_DEFAULT_BRIGHTNESS; - modes.push_back(Micoff); - - mode Micpulse; - Micpulse.value = SONY_DUALSENSE_MIC_PULSE_MODE_VALUE; - Micpulse.name = "Mic Pulse (Direct)"; - Micpulse.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - Micpulse.color_mode = MODE_COLORS_PER_LED; - Micpulse.brightness_min = SONY_DUALSENSE_BRIGHTNESS_MIN; - Micpulse.brightness_max = SONY_DUALSENSE_BRIGHTNESS_MAX; - Micpulse.brightness = SONY_DUALSENSE_DEFAULT_BRIGHTNESS; - modes.push_back(Micpulse); - - SetupZones(); -} - -RGBController_SonyDualSense::~RGBController_SonyDualSense() -{ - delete controller; -} - -void RGBController_SonyDualSense::SetupZones() -{ - /*---------------------------------------------------------*\ - | This device only has one LED, so create a single zone and | - | LED for it | - \*---------------------------------------------------------*/ - zone lightbar; - lightbar.name = "Lightbar"; - lightbar.type = ZONE_TYPE_SINGLE; - lightbar.leds_min = SONY_DUALSENSE_LIGHTBAR_LED_COUNT; - lightbar.leds_max = SONY_DUALSENSE_LIGHTBAR_LED_COUNT; - lightbar.leds_count = SONY_DUALSENSE_LIGHTBAR_LED_COUNT; - lightbar.matrix_map = NULL; - zones.push_back(lightbar); - - zone playerleds; - playerleds.name = "Player LEDs"; - playerleds.type = ZONE_TYPE_LINEAR; - playerleds.leds_min = SONY_DUALSENSE_PLAYER_LED_COUNT; - playerleds.leds_max = SONY_DUALSENSE_PLAYER_LED_COUNT; - playerleds.leds_count = SONY_DUALSENSE_PLAYER_LED_COUNT; - playerleds.matrix_map = NULL; - zones.push_back(playerleds); - - leds.resize(SONY_DUALSENSE_LIGHTBAR_LED_COUNT + SONY_DUALSENSE_PLAYER_LED_COUNT); - - leds[0].name = "LED 1"; - - for(unsigned int i = 0 ; i < SONY_DUALSENSE_PLAYER_LED_COUNT; i++) - { - leds[i + 1].name = "Player " + std::to_string(i + 1); - } - - SetupColors(); -} - -void RGBController_SonyDualSense::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_SonyDualSense::DeviceUpdateLEDs() -{ - controller->SetColors(colors, modes[active_mode].brightness, modes[active_mode].value); -} - -void RGBController_SonyDualSense::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_SonyDualSense::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_SonyDualSense::DeviceUpdateMode() -{ -} diff --git a/Controllers/SonyGamepadController/RGBController_SonyDualSense.h b/Controllers/SonyGamepadController/RGBController_SonyDualSense.h deleted file mode 100644 index 29defddb..00000000 --- a/Controllers/SonyGamepadController/RGBController_SonyDualSense.h +++ /dev/null @@ -1,30 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SonyDualSense.h | -| | -| Controller for Sony DualSense | -| | -| by flora 01/07/2022 | -\*-----------------------------------------*/ - - -#include "RGBController.h" -#include "SonyDualSenseController.h" - -class RGBController_SonyDualSense : public RGBController -{ -public: - RGBController_SonyDualSense(SonyDualSenseController* controller_ptr); - ~RGBController_SonyDualSense(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - SonyDualSenseController* controller; -}; diff --git a/Controllers/SonyGamepadController/SonyDS4Controller.cpp b/Controllers/SonyGamepadController/SonyDS4Controller.cpp deleted file mode 100644 index af1c7f6d..00000000 --- a/Controllers/SonyGamepadController/SonyDS4Controller.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/*-----------------------------------------*\ -| SonyDS4Controller.cpp | -| | -| Controller for Sony Dualshock 4 | -| | -| Pol Rius (alpemwarrior) 24/09/2020 | -\*-----------------------------------------*/ - -#include -#include -#include "SonyDS4Controller.h" - -SonyDS4Controller::SonyDS4Controller(hid_device * device_handle, const char * device_path) -{ - this->device_handle = device_handle; - unsigned char readBuffer[64]; - unsigned char reportBuffer[64]; - reportBuffer[0] = 0x02; - - hid_get_feature_report(device_handle, reportBuffer, 64); - for (int i = 0; i < 5; i++) - { - hid_read(device_handle, readBuffer, 64); - if (readBuffer[0] == 17) - { - is_bluetooth = true; - break; - } - } - - location = device_path; -} - -SonyDS4Controller::~SonyDS4Controller() -{ - hid_close(device_handle); -} - -std::string SonyDS4Controller::GetLocation() -{ - return("HID: " + location); -} - -std::string SonyDS4Controller::GetSerialString() -{ - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(device_handle, 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 SonyDS4Controller::SetColors(unsigned char red, unsigned char green, unsigned char blue) -{ - if(is_bluetooth) - { - sendReportBT(red, green, blue); - } - else - { - sendReportUSB(red, green, blue); - } -} - -void SonyDS4Controller::sendReportBT(unsigned char red, unsigned char green, unsigned char blue) -{ - unsigned char buffer[79] = - { - 0xa2, 0x11, 0xC0, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, red, green, blue, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - uint32_t crc = CRCPP::CRC::Calculate(buffer, 75, CRCPP::CRC::CRC_32()); - unsigned char outbuffer[78]; - - /*-------------------------------------------------*\ - | The report has to be signed with the byte 0xa2. | - | However, hidapi already adds 0xa2 to the report, | - | so we need to remove it from the buffer. | - \*-------------------------------------------------*/ - for(unsigned int i = 1; i < 79; i++) - { - outbuffer[i - 1] = buffer[i]; - } - - /*-------------------------------------------------*\ - | Add the crc32 to the end of the buffer | - \*-------------------------------------------------*/ - outbuffer[74] = (0x000000FF & crc); - outbuffer[75] = (0x0000FF00 & crc) >> 8; - outbuffer[76] = (0x00FF0000 & crc) >> 16; - outbuffer[77] = (0xFF000000 & crc) >> 24; - - hid_write(device_handle, outbuffer, 78); -} - -void SonyDS4Controller::sendReportUSB(unsigned char red, unsigned char green, unsigned char blue) -{ - uint8_t buffer[11] = - { - 0x05, - 0x07, - 0x00, - 0x00, - 0x00, - 0x00, - red, - green, - blue, - 0x00, - 0x00 - }; - - hid_write(device_handle, buffer, 11); -} diff --git a/Controllers/SonyGamepadController/SonyDS4Controller.h b/Controllers/SonyGamepadController/SonyDS4Controller.h deleted file mode 100644 index 838bfb1a..00000000 --- a/Controllers/SonyGamepadController/SonyDS4Controller.h +++ /dev/null @@ -1,31 +0,0 @@ -/*-----------------------------------------*\ -| SonyDS4Controller.h | -| | -| Controller for Sony Dualshock 4 | -| | -| Pol Rius (alpemwarrior) 24/09/2020 | -\*-----------------------------------------*/ - -#include - -#include - -class SonyDS4Controller -{ -public: - SonyDS4Controller(hid_device * device_handle, const char * device_path); - ~SonyDS4Controller(); - - std::string GetLocation(); - std::string GetSerialString(); - - void SetColors(unsigned char red, unsigned char green, unsigned char blue); - -private: - hid_device* device_handle; - bool is_bluetooth = false; - std::string location; - - void sendReportUSB(unsigned char red, unsigned char green, unsigned char blue); - void sendReportBT(unsigned char red, unsigned char green, unsigned char blue); -}; diff --git a/Controllers/SonyGamepadController/RGBController_SonyDS4.cpp b/Controllers/SonyGamepadController/SonyDS4Controller/RGBController_SonyDS4.cpp similarity index 81% rename from Controllers/SonyGamepadController/RGBController_SonyDS4.cpp rename to Controllers/SonyGamepadController/SonyDS4Controller/RGBController_SonyDS4.cpp index 73caa501..0ea1bd13 100644 --- a/Controllers/SonyGamepadController/RGBController_SonyDS4.cpp +++ b/Controllers/SonyGamepadController/SonyDS4Controller/RGBController_SonyDS4.cpp @@ -1,12 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_SonyDS4.cpp | -| | -| Controller for Sony Dualshock 4 | -| | -| Pol Rius (alpemwarrior) 24/09/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_SonyDS4.cpp | +| | +| RGBController for Sony Dualshock 4 | +| | +| Pol Rius (alpemwarrior) 24 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include #include "RGBController.h" #include "RGBController_SonyDS4.h" diff --git a/Controllers/SonyGamepadController/SonyDS4Controller/RGBController_SonyDS4.h b/Controllers/SonyGamepadController/SonyDS4Controller/RGBController_SonyDS4.h new file mode 100644 index 00000000..6e8de885 --- /dev/null +++ b/Controllers/SonyGamepadController/SonyDS4Controller/RGBController_SonyDS4.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_SonyDS4.h | +| | +| RGBController for Sony Dualshock 4 | +| | +| Pol Rius (alpemwarrior) 24 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SonyDS4Controller.h" + +class RGBController_SonyDS4 : public RGBController +{ +public: + RGBController_SonyDS4(SonyDS4Controller* controller_ptr); + ~RGBController_SonyDS4(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + SonyDS4Controller* controller; +}; diff --git a/Controllers/SonyGamepadController/SonyDS4Controller/SonyDS4Controller.cpp b/Controllers/SonyGamepadController/SonyDS4Controller/SonyDS4Controller.cpp new file mode 100644 index 00000000..c14a8b20 --- /dev/null +++ b/Controllers/SonyGamepadController/SonyDS4Controller/SonyDS4Controller.cpp @@ -0,0 +1,126 @@ +/*---------------------------------------------------------*\ +| SonyDS4Controller.cpp | +| | +| Driver for Sony Dualshock 4 | +| | +| Pol Rius (alpemwarrior) 24 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "SonyDS4Controller.h" +#include "StringUtils.h" + +SonyDS4Controller::SonyDS4Controller(hid_device * device_handle, const char * device_path) +{ + this->dev = device_handle; + unsigned char readBuffer[64]; + unsigned char reportBuffer[64]; + reportBuffer[0] = 0x02; + + hid_get_feature_report(dev, reportBuffer, 64); + for (int i = 0; i < 5; i++) + { + hid_read(dev, readBuffer, 64); + if (readBuffer[0] == 17) + { + is_bluetooth = true; + break; + } + } + + location = device_path; +} + +SonyDS4Controller::~SonyDS4Controller() +{ + hid_close(dev); +} + +std::string SonyDS4Controller::GetLocation() +{ + return("HID: " + location); +} + +std::string SonyDS4Controller::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void SonyDS4Controller::SetColors(unsigned char red, unsigned char green, unsigned char blue) +{ + if(is_bluetooth) + { + sendReportBT(red, green, blue); + } + else + { + sendReportUSB(red, green, blue); + } +} + +void SonyDS4Controller::sendReportBT(unsigned char red, unsigned char green, unsigned char blue) +{ + unsigned char buffer[79] = + { + 0xa2, 0x11, 0xC0, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, red, green, blue, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + uint32_t crc = CRCPP::CRC::Calculate(buffer, 75, CRCPP::CRC::CRC_32()); + unsigned char outbuffer[78]; + + /*-------------------------------------------------*\ + | The report has to be signed with the byte 0xa2. | + | However, hidapi already adds 0xa2 to the report, | + | so we need to remove it from the buffer. | + \*-------------------------------------------------*/ + for(unsigned int i = 1; i < 79; i++) + { + outbuffer[i - 1] = buffer[i]; + } + + /*-------------------------------------------------*\ + | Add the crc32 to the end of the buffer | + \*-------------------------------------------------*/ + outbuffer[74] = (0x000000FF & crc); + outbuffer[75] = (0x0000FF00 & crc) >> 8; + outbuffer[76] = (0x00FF0000 & crc) >> 16; + outbuffer[77] = (0xFF000000 & crc) >> 24; + + hid_write(dev, outbuffer, 78); +} + +void SonyDS4Controller::sendReportUSB(unsigned char red, unsigned char green, unsigned char blue) +{ + uint8_t buffer[11] = + { + 0x05, + 0x07, + 0x00, + 0x00, + 0x00, + 0x00, + red, + green, + blue, + 0x00, + 0x00 + }; + + hid_write(dev, buffer, 11); +} diff --git a/Controllers/SonyGamepadController/SonyDS4Controller/SonyDS4Controller.h b/Controllers/SonyGamepadController/SonyDS4Controller/SonyDS4Controller.h new file mode 100644 index 00000000..7a60f33a --- /dev/null +++ b/Controllers/SonyGamepadController/SonyDS4Controller/SonyDS4Controller.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| SonyDS4Controller.h | +| | +| Driver for Sony Dualshock 4 | +| | +| Pol Rius (alpemwarrior) 24 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include + +class SonyDS4Controller +{ +public: + SonyDS4Controller(hid_device * device_handle, const char * device_path); + ~SonyDS4Controller(); + + std::string GetLocation(); + std::string GetSerialString(); + + void SetColors(unsigned char red, unsigned char green, unsigned char blue); + +private: + hid_device* dev; + bool is_bluetooth = false; + std::string location; + + void sendReportUSB(unsigned char red, unsigned char green, unsigned char blue); + void sendReportBT(unsigned char red, unsigned char green, unsigned char blue); +}; diff --git a/Controllers/SonyGamepadController/SonyDualSenseController.h b/Controllers/SonyGamepadController/SonyDualSenseController.h deleted file mode 100644 index d99a4d84..00000000 --- a/Controllers/SonyGamepadController/SonyDualSenseController.h +++ /dev/null @@ -1,47 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SonyDualSense.h | -| | -| Controller for Sony DualSense | -| | -| by flora 01/07/2022 | -\*-----------------------------------------*/ - - -#include -#include "RGBController.h" - -#include -#include - -#define SONY_DUALSENSE_LIGHTBAR_LED_COUNT 1 -#define SONY_DUALSENSE_PLAYER_LED_COUNT 5 -#define SONY_DUALSENSE_BT_PACKET_SIZE 78 -#define SONY_DUALSENSE_USB_PACKET_SIZE 48 - -enum -{ - SONY_DUALSENSE_DIRECT_MODE_VALUE = 0x01, - SONY_DUALSENSE_MIC_OFF_MODE_VALUE = 0x00, - SONY_DUALSENSE_MIC_PULSE_MODE_VALUE = 0x02, - SONY_DUALSENSE_BRIGHTNESS_MIN = 0x00, - SONY_DUALSENSE_BRIGHTNESS_MAX = 0x02, - SONY_DUALSENSE_DEFAULT_BRIGHTNESS = 0x01 -}; - -class SonyDualSenseController -{ -public: - SonyDualSenseController(hid_device * device_handle, const char * device_path, bool is_bluetooth); - ~SonyDualSenseController(); - - std::string GetLocation(); - std::string GetSerialString(); - - void SetColors(std::vector colors, unsigned char brightness, unsigned char mode_value); - bool IsBluetooth(); - -private: - hid_device* dev; - std::string location; - bool is_bluetooth; -}; diff --git a/Controllers/SonyGamepadController/SonyDualSenseController/RGBController_SonyDualSense.cpp b/Controllers/SonyGamepadController/SonyDualSenseController/RGBController_SonyDualSense.cpp new file mode 100644 index 00000000..2045017b --- /dev/null +++ b/Controllers/SonyGamepadController/SonyDualSenseController/RGBController_SonyDualSense.cpp @@ -0,0 +1,141 @@ +/*---------------------------------------------------------*\ +| RGBController_SonyDualSense.cpp | +| | +| RGBController for Sony DualSense | +| | +| Flora Aubry 01 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "RGBController_SonyDualSense.h" + +/**------------------------------------------------------------------*\ + @name Sony Dual Sense controller + @category Gamepad + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectSonyDualSenseControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_SonyDualSense::RGBController_SonyDualSense(SonyDualSenseController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetName(); + + if(controller->IsBluetooth()) + { + name.append(" (BT)"); + } + + vendor = "Sony"; + type = DEVICE_TYPE_GAMEPAD; + description = "Sony DualSense Device"; + location = controller->GetLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.value = SONY_DUALSENSE_DIRECT_MODE_VALUE; + Direct.name = "Direct"; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Direct.color_mode = MODE_COLORS_PER_LED; + Direct.brightness_min = SONY_DUALSENSE_BRIGHTNESS_MIN; + Direct.brightness_max = SONY_DUALSENSE_BRIGHTNESS_MAX; + Direct.brightness = SONY_DUALSENSE_DEFAULT_BRIGHTNESS; + modes.push_back(Direct); + + mode Micoff; + Micoff.value = SONY_DUALSENSE_MIC_OFF_MODE_VALUE; + Micoff.name = "Mic Off (Direct)"; + Micoff.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Micoff.color_mode = MODE_COLORS_PER_LED; + Micoff.brightness_min = SONY_DUALSENSE_BRIGHTNESS_MIN; + Micoff.brightness_max = SONY_DUALSENSE_BRIGHTNESS_MAX; + Micoff.brightness = SONY_DUALSENSE_DEFAULT_BRIGHTNESS; + modes.push_back(Micoff); + + mode Micpulse; + Micpulse.value = SONY_DUALSENSE_MIC_PULSE_MODE_VALUE; + Micpulse.name = "Mic Pulse (Direct)"; + Micpulse.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Micpulse.color_mode = MODE_COLORS_PER_LED; + Micpulse.brightness_min = SONY_DUALSENSE_BRIGHTNESS_MIN; + Micpulse.brightness_max = SONY_DUALSENSE_BRIGHTNESS_MAX; + Micpulse.brightness = SONY_DUALSENSE_DEFAULT_BRIGHTNESS; + modes.push_back(Micpulse); + + SetupZones(); +} + +RGBController_SonyDualSense::~RGBController_SonyDualSense() +{ + delete controller; +} + +void RGBController_SonyDualSense::SetupZones() +{ + /*---------------------------------------------------------*\ + | This device only has one LED, so create a single zone and | + | LED for it | + \*---------------------------------------------------------*/ + zone lightbar; + lightbar.name = "Lightbar"; + lightbar.type = ZONE_TYPE_SINGLE; + lightbar.leds_min = SONY_DUALSENSE_LIGHTBAR_LED_COUNT; + lightbar.leds_max = SONY_DUALSENSE_LIGHTBAR_LED_COUNT; + lightbar.leds_count = SONY_DUALSENSE_LIGHTBAR_LED_COUNT; + lightbar.matrix_map = NULL; + zones.push_back(lightbar); + + zone playerleds; + playerleds.name = "Player LEDs"; + playerleds.type = ZONE_TYPE_LINEAR; + playerleds.leds_min = SONY_DUALSENSE_PLAYER_LED_COUNT; + playerleds.leds_max = SONY_DUALSENSE_PLAYER_LED_COUNT; + playerleds.leds_count = SONY_DUALSENSE_PLAYER_LED_COUNT; + playerleds.matrix_map = NULL; + zones.push_back(playerleds); + + leds.resize(SONY_DUALSENSE_LIGHTBAR_LED_COUNT + SONY_DUALSENSE_PLAYER_LED_COUNT); + + leds[0].name = "LED 1"; + + for(unsigned int i = 0 ; i < SONY_DUALSENSE_PLAYER_LED_COUNT; i++) + { + leds[i + 1].name = "Player " + std::to_string(i + 1); + } + + SetupColors(); +} + +void RGBController_SonyDualSense::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_SonyDualSense::DeviceUpdateLEDs() +{ + controller->SetColors(colors, modes[active_mode].brightness, modes[active_mode].value); +} + +void RGBController_SonyDualSense::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_SonyDualSense::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_SonyDualSense::DeviceUpdateMode() +{ +} diff --git a/Controllers/SonyGamepadController/SonyDualSenseController/RGBController_SonyDualSense.h b/Controllers/SonyGamepadController/SonyDualSenseController/RGBController_SonyDualSense.h new file mode 100644 index 00000000..d184c4f9 --- /dev/null +++ b/Controllers/SonyGamepadController/SonyDualSenseController/RGBController_SonyDualSense.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_SonyDualSense.h | +| | +| RGBController for Sony DualSense | +| | +| Flora Aubry 01 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SonyDualSenseController.h" + +class RGBController_SonyDualSense : public RGBController +{ +public: + RGBController_SonyDualSense(SonyDualSenseController* controller_ptr); + ~RGBController_SonyDualSense(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + SonyDualSenseController* controller; +}; diff --git a/Controllers/SonyGamepadController/SonyDualSenseController.cpp b/Controllers/SonyGamepadController/SonyDualSenseController/SonyDualSenseController.cpp similarity index 78% rename from Controllers/SonyGamepadController/SonyDualSenseController.cpp rename to Controllers/SonyGamepadController/SonyDualSenseController/SonyDualSenseController.cpp index 3284f786..32c44566 100644 --- a/Controllers/SonyGamepadController/SonyDualSenseController.cpp +++ b/Controllers/SonyGamepadController/SonyDualSenseController/SonyDualSenseController.cpp @@ -1,20 +1,26 @@ -/*-----------------------------------------*\ -| RGBController_SonyDualSense.h | -| | -| Controller for Sony DualSense | -| | -| by flora 01/07/2022 | -\*-----------------------------------------*/ -#include -#include -#include -#include "SonyDualSenseController.h" +/*---------------------------------------------------------*\ +| SonyDualSenseController.cpp | +| | +| Driver for Sony DualSense | +| | +| Flora Aubry 01 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -SonyDualSenseController::SonyDualSenseController(hid_device * device_handle, const char * device_path, bool is_bluetooth) +#include +#include +#include +#include "SonyDualSenseController.h" +#include "StringUtils.h" + +SonyDualSenseController::SonyDualSenseController(hid_device * device_handle, const char * device_path, bool is_bluetooth, std::string dev_name) { - dev = device_handle; - location = device_path; - this->is_bluetooth = is_bluetooth; + dev = device_handle; + location = device_path; + name = dev_name; + this->is_bluetooth = is_bluetooth; } SonyDualSenseController::~SonyDualSenseController() @@ -27,19 +33,22 @@ std::string SonyDualSenseController::GetLocation() return("HID: " + location); } +std::string SonyDualSenseController::GetName() +{ + return(name); +} + std::string SonyDualSenseController::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); + return(StringUtils::wstring_to_string(serial_string)); } void SonyDualSenseController::SetColors(std::vector colors, unsigned char brightness, unsigned char mode_value) diff --git a/Controllers/SonyGamepadController/SonyDualSenseController/SonyDualSenseController.h b/Controllers/SonyGamepadController/SonyDualSenseController/SonyDualSenseController.h new file mode 100644 index 00000000..e2953f26 --- /dev/null +++ b/Controllers/SonyGamepadController/SonyDualSenseController/SonyDualSenseController.h @@ -0,0 +1,52 @@ +/*---------------------------------------------------------*\ +| SonyDualSenseController.h | +| | +| Driver for Sony DualSense | +| | +| Flora Aubry 01 Jul 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" + +#define SONY_DUALSENSE_LIGHTBAR_LED_COUNT 1 +#define SONY_DUALSENSE_PLAYER_LED_COUNT 5 +#define SONY_DUALSENSE_BT_PACKET_SIZE 78 +#define SONY_DUALSENSE_USB_PACKET_SIZE 48 + +enum +{ + SONY_DUALSENSE_DIRECT_MODE_VALUE = 0x01, + SONY_DUALSENSE_MIC_OFF_MODE_VALUE = 0x00, + SONY_DUALSENSE_MIC_PULSE_MODE_VALUE = 0x02, + SONY_DUALSENSE_BRIGHTNESS_MIN = 0x00, + SONY_DUALSENSE_BRIGHTNESS_MAX = 0x02, + SONY_DUALSENSE_DEFAULT_BRIGHTNESS = 0x01 +}; + +class SonyDualSenseController +{ +public: + SonyDualSenseController(hid_device * device_handle, const char * device_path, bool is_bluetooth, std::string dev_name); + ~SonyDualSenseController(); + + std::string GetLocation(); + std::string GetName(); + std::string GetSerialString(); + + void SetColors(std::vector colors, unsigned char brightness, unsigned char mode_value); + bool IsBluetooth(); + +private: + hid_device* dev; + std::string location; + std::string name; + bool is_bluetooth; +}; diff --git a/Controllers/SonyGamepadController/SonyGamepadControllerDetect.cpp b/Controllers/SonyGamepadController/SonyGamepadControllerDetect.cpp index 7ffae9da..409226ef 100644 --- a/Controllers/SonyGamepadController/SonyGamepadControllerDetect.cpp +++ b/Controllers/SonyGamepadController/SonyGamepadControllerDetect.cpp @@ -1,14 +1,18 @@ -/*-----------------------------------------*\ -| SonyDS4Controller.h | -| | -| Detector for Sony Dualshock 4 | -| | -| Pol Rius (alpemwarrior) 24/09/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| SonyGamepadControllerDetect.cpp | +| | +| Detector for Sony Gamepads | +| | +| Pol Rius (alpemwarrior) 24 Sep 2020 | +| Flora Aubry 01 Jul 2022 | +| Yoan Berthelot 06 Mar 2025 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include -#include - +#include #include "RGBController_SonyDS4.h" #include "RGBController_SonyDualSense.h" #include "Detector.h" @@ -19,28 +23,31 @@ #define SONY_DS4_V2_PID 0x09CC #define SONY_DS4_RECEIVER_PID 0x0BA0 #define SONY_DUALSENSE_PID 0x0CE6 +#define SONY_DUALSENSE_EDGE_PID 0x0DF2 void DetectSonyDS4Controllers(hid_device_info* info, const std::string&) { hid_device* dev = hid_open_path(info->path); + if(dev) { SonyDS4Controller* controller = new SonyDS4Controller(dev, info->path); RGBController_SonyDS4* rgb_controller = new RGBController_SonyDS4(controller); - // Constructor sets the name + ResourceManager::get()->RegisterRGBController(rgb_controller); } } -void DetectSonyDualSenseControllers(hid_device_info* info, const std::string&) +void DetectSonyDualSenseControllers(hid_device_info* info, const std::string& name) { hid_device* dev = hid_open_path(info->path); + if(dev) { bool is_bluetooth = info->interface_number == -1; - SonyDualSenseController* controller = new SonyDualSenseController(dev, info->path, is_bluetooth); + SonyDualSenseController* controller = new SonyDualSenseController(dev, info->path, is_bluetooth, name); RGBController_SonyDualSense* rgb_controller = new RGBController_SonyDualSense(controller); - // Constructor sets the name + ResourceManager::get()->RegisterRGBController(rgb_controller); } } @@ -49,3 +56,4 @@ REGISTER_HID_DETECTOR("Sony DualShock 4", DetectSonyDS4Controllers, SONY_V REGISTER_HID_DETECTOR("Sony DualShock 4", DetectSonyDS4Controllers, SONY_VID, SONY_DS4_V2_PID); REGISTER_HID_DETECTOR("Sony DualShock 4", DetectSonyDS4Controllers, SONY_VID, SONY_DS4_RECEIVER_PID); REGISTER_HID_DETECTOR("Sony DualSense", DetectSonyDualSenseControllers, SONY_VID, SONY_DUALSENSE_PID); +REGISTER_HID_DETECTOR("Sony DualSense Edge", DetectSonyDualSenseControllers, SONY_VID, SONY_DUALSENSE_EDGE_PID); diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesApex.h b/Controllers/SteelSeriesController/RGBController_SteelSeriesApex.h deleted file mode 100644 index db7cac79..00000000 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesApex.h +++ /dev/null @@ -1,37 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SteelSeriesApex.cpp | -| | -| Generic RGB Interface for SteelSeries | -| Apex 7 Keyboard | -| | -| Eric Samuelson (edbgon) 7/5/2020 | -\*-----------------------------------------*/ - -#pragma once -#include - -#include "RGBController.h" -#include "SteelSeriesApexBaseController.h" -#include "SteelSeriesGeneric.h" - -class RGBController_SteelSeriesApex : public RGBController -{ -public: - RGBController_SteelSeriesApex(SteelSeriesApexBaseController* controller_ptr); - ~RGBController_SteelSeriesApex(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - SteelSeriesApexBaseController* controller; - steelseries_type proto_type; - - std::chrono::time_point last_update_time; -}; diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesApex3.cpp b/Controllers/SteelSeriesController/RGBController_SteelSeriesApex3.cpp deleted file mode 100644 index 2b89b5ac..00000000 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesApex3.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SteelSeriesApexTZone.cpp | -| | -| Edbgon 06.10.21 | -\*-----------------------------------------*/ - -#include "RGBController_SteelSeriesApex3.h" - -/**------------------------------------------------------------------*\ - @name Steel Series Apex Tri Zone Keyboards - @category Keyboard - @type USB - @save :x: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectSteelSeriesApexTZone - @comment -\*-------------------------------------------------------------------*/ - -RGBController_SteelSeriesApex3::RGBController_SteelSeriesApex3(SteelSeriesApex3Controller* controller_ptr) -{ - controller = controller_ptr; - - name = "SteelSeries Apex 3 device"; - vendor = "SteelSeries"; - type = DEVICE_TYPE_KEYBOARD; - description = name; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - mode direct; - direct.name = "Direct"; - direct.value = static_cast(APEX3_MODES::DIRECT); - direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; - if(controller->SupportsSave()) - { - direct.flags |= MODE_FLAG_MANUAL_SAVE; - } - direct.color_mode = MODE_COLORS_PER_LED; - direct.brightness_min = STEELSERIES_APEX3_BRIGHTNESS_MIN; - direct.brightness_max = controller->GetMaxBrightness(); - direct.brightness = direct.brightness_max; - modes.push_back(direct); - - if(controller->SupportsRainbowWave()) - { - mode rainbow; - rainbow.name = "Rainbow Wave"; - rainbow.value = static_cast(APEX3_MODES::RAINBOW_WAVE); - rainbow.flags = MODE_FLAG_HAS_BRIGHTNESS; - rainbow.color_mode = MODE_COLORS_NONE; - rainbow.brightness_min = STEELSERIES_APEX3_BRIGHTNESS_MIN; - rainbow.brightness_max = controller->GetMaxBrightness(); - rainbow.brightness = rainbow.brightness_max; - modes.push_back(rainbow); - } - - SetupZones(); -} - -RGBController_SteelSeriesApex3::~RGBController_SteelSeriesApex3() -{ - delete controller; -} - -void RGBController_SteelSeriesApex3::DeviceSaveMode() -{ - controller->Save(); -} - -void RGBController_SteelSeriesApex3::SetupZones() -{ - uint8_t led_count = controller->GetLedCount(); - - zone curr_zone; - curr_zone.name = "Keyboard"; - curr_zone.type = ZONE_TYPE_LINEAR; - curr_zone.leds_min = led_count; - curr_zone.leds_max = led_count; - curr_zone.leds_count = led_count; - curr_zone.matrix_map = NULL; - zones.push_back(curr_zone); - - for(size_t i = 0; i < curr_zone.leds_count; i++) - { - led zone_led; - zone_led.name = "LED " + std::to_string(i); - leds.push_back(zone_led); - } - - SetupColors(); -} - -void RGBController_SteelSeriesApex3::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_SteelSeriesApex3::DeviceUpdateLEDs() -{ - controller->SetColor(colors, modes[active_mode].value, modes[active_mode].brightness); -} - -void RGBController_SteelSeriesApex3::UpdateZoneLEDs(int /*zone*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_SteelSeriesApex3::UpdateSingleLED(int /*led*/) -{ - DeviceUpdateLEDs(); -} - -void RGBController_SteelSeriesApex3::DeviceUpdateMode() -{ - if(modes[active_mode].color_mode == MODE_FLAG_HAS_PER_LED_COLOR) - { - DeviceUpdateLEDs(); - } - else - { - controller->SetColor(modes[active_mode].colors, modes[active_mode].value, modes[active_mode].brightness); - } -} diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesApex3.h b/Controllers/SteelSeriesController/RGBController_SteelSeriesApex3.h deleted file mode 100644 index a2d574b1..00000000 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesApex3.h +++ /dev/null @@ -1,36 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SteelSeriesApexTZone.h | -| | -| Edbgon 06.10.21 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "SteelSeriesApex3Controller.h" - -enum class APEX3_MODES -{ - DIRECT = 0, - RAINBOW_WAVE = 1 -}; - -class RGBController_SteelSeriesApex3 : public RGBController -{ -public: - RGBController_SteelSeriesApex3(SteelSeriesApex3Controller* controller_ptr); - ~RGBController_SteelSeriesApex3(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - SteelSeriesApex3Controller* controller; -}; diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesArctis5.cpp b/Controllers/SteelSeriesController/RGBController_SteelSeriesArctis5.cpp deleted file mode 100644 index d3c183e4..00000000 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesArctis5.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SteelSeriesArctis5.cpp | -| | -| Generic RGB Interface SteelSeriesArctis5 | -| Class | -| | -| Morgan Guimard 3/04/2022 | -\*-----------------------------------------*/ - -#include "RGBController_SteelSeriesArctis5.h" - -/**------------------------------------------------------------------*\ - @name Steelseries Arctis 5 - @category Headset - @type USB - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectSteelSeriesArctis5 - @comment -\*-------------------------------------------------------------------*/ - -RGBController_SteelSeriesArctis5::RGBController_SteelSeriesArctis5(SteelSeriesArctis5Controller* controller_ptr) -{ - controller = controller_ptr; - name = "SteelSeries Arctis 5 headset"; - vendor = "SteelSeries"; - type = DEVICE_TYPE_HEADSET; - description = name; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = 0x00; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; - - modes.push_back(Direct); - - SetupZones(); -} - -RGBController_SteelSeriesArctis5::~RGBController_SteelSeriesArctis5() -{ - delete controller; -} - -void RGBController_SteelSeriesArctis5::SetupZones() -{ - const std::string zone_names[2] = - { - "Left" , "Right" - }; - - for(const std::string& zone_name : zone_names) - { - zone zone; - zone.name = zone_name; - zone.type = ZONE_TYPE_SINGLE; - zone.leds_min = 1; - zone.leds_max = 1; - zone.leds_count = 1; - zone.matrix_map = NULL; - zones.push_back(zone); - - led mouse_led; - mouse_led.name = zone_name; - leds.push_back(mouse_led); - } - - SetupColors(); -} - -void RGBController_SteelSeriesArctis5::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_SteelSeriesArctis5::DeviceUpdateLEDs() -{ - for(unsigned int i = 0; i < zones.size(); i++) - { - UpdateZoneLEDs(i); - } -} - -void RGBController_SteelSeriesArctis5::UpdateZoneLEDs(int zone) -{ - controller->SetColor(zone, colors[zone]); -} - -void RGBController_SteelSeriesArctis5::UpdateSingleLED(int led) -{ - UpdateZoneLEDs(led); -} - -void RGBController_SteelSeriesArctis5::DeviceUpdateMode() -{ - -} diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesArctis5.h b/Controllers/SteelSeriesController/RGBController_SteelSeriesArctis5.h deleted file mode 100644 index 6085b6c2..00000000 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesArctis5.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SteelSeriesArctis5.h | -| | -| Generic RGB Interface SteelSeriesArctis5 | -| Class | -| | -| Morgan Guimard 3/04/2022 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "SteelSeriesArctis5Controller.h" - -class RGBController_SteelSeriesArctis5 : public RGBController -{ -public: - RGBController_SteelSeriesArctis5(SteelSeriesArctis5Controller* controller_ptr); - ~RGBController_SteelSeriesArctis5(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - SteelSeriesArctis5Controller* controller; -}; diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesOldApex.cpp b/Controllers/SteelSeriesController/RGBController_SteelSeriesOldApex.cpp deleted file mode 100644 index ff7887c4..00000000 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesOldApex.cpp +++ /dev/null @@ -1,202 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SteelSeriesOldApex.cpp | -| | -| Generic RGB Interface older-style | -| SteelSeriesApex Keyboards | -| (APEX/APEX Fnatic/Apex 350) | -| Class | -| | -| David Lee (RAMChYLD) 15/11/2020 | -| | -| Based on work by | -| B Horn (bahorn) 13/05/2020 | -| | -| Based on findings in ApexCtl by | -| Audrius/tuxmark5, et. al | -| https://github.com/tuxmark5/ApexCtl | -\*-----------------------------------------*/ - -#include "RGBController_SteelSeriesOldApex.h" - -/**------------------------------------------------------------------*\ - @name Steel Series Apex (Old) - @category Keyboard - @type USB - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectSteelSeriesApexOld - @comment -\*-------------------------------------------------------------------*/ - -RGBController_SteelSeriesOldApex::RGBController_SteelSeriesOldApex(SteelSeriesOldApexController* controller_ptr) -{ - controller = controller_ptr; - - name = controller->GetDeviceName(); - vendor = "SteelSeries"; - type = DEVICE_TYPE_KEYBOARD; - description = "SteelSeries old Apex device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - mode direct; - direct.name = "Direct"; - direct.value = STEELSERIES_OLDAPEX_DIRECT; - direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(direct); - - SetupZones(); -} - -RGBController_SteelSeriesOldApex::~RGBController_SteelSeriesOldApex() -{ - delete controller; -} - -void RGBController_SteelSeriesOldApex::SetupZones() -{ - /* We have 5 zones to work with. Here goes... */ - zone qwerty_zone; - qwerty_zone.name = "QWERTY"; - qwerty_zone.type = ZONE_TYPE_LINEAR; - qwerty_zone.leds_min = 1; - qwerty_zone.leds_max = 1; - qwerty_zone.leds_count = 1; - qwerty_zone.matrix_map = NULL; - zones.push_back(qwerty_zone); - - led qwerty_led; - qwerty_led.name = "QWERTY"; - leds.push_back(qwerty_led); - - zone tenkey_zone; - tenkey_zone.name = "TenKey"; - tenkey_zone.type = ZONE_TYPE_LINEAR; - tenkey_zone.leds_min = 1; - tenkey_zone.leds_max = 1; - tenkey_zone.leds_count = 1; - tenkey_zone.matrix_map = NULL; - zones.push_back(tenkey_zone); - - led tenkey_led; - tenkey_led.name = "TenKey"; - leds.push_back(tenkey_led); - - zone function_zone; - function_zone.name = "FunctionKeys"; - function_zone.type = ZONE_TYPE_LINEAR; - function_zone.leds_min = 1; - function_zone.leds_max = 1; - function_zone.leds_count = 1; - function_zone.matrix_map = NULL; - zones.push_back(function_zone); - - led function_led; - function_led.name = "FunctionKeys"; - leds.push_back(function_led); - - zone mx_zone; - mx_zone.name = "MXKeys"; - mx_zone.type = ZONE_TYPE_LINEAR; - mx_zone.leds_min = 1; - mx_zone.leds_max = 1; - mx_zone.leds_count = 1; - mx_zone.matrix_map = NULL; - zones.push_back(mx_zone); - - led mx_led; - mx_led.name = "MXKeys"; - leds.push_back(mx_led); - - zone logo_zone; - logo_zone.name = "Logo"; - logo_zone.type = ZONE_TYPE_LINEAR; - logo_zone.leds_min = 1; - logo_zone.leds_max = 1; - logo_zone.leds_count = 1; - logo_zone.matrix_map = NULL; - zones.push_back(logo_zone); - - led logo_led; - logo_led.name = "Logo"; - leds.push_back(logo_led); - - SetupColors(); -} - -void RGBController_SteelSeriesOldApex::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_SteelSeriesOldApex::DeviceUpdateLEDs() -{ - // Due to the inefficient packet design of the OG Apex - // All colors must be blasted with each update - color32 qwerty; - qwerty.red = RGBGetRValue(colors[0]); - qwerty.green = RGBGetGValue(colors[0]); - qwerty.blue = RGBGetBValue(colors[0]); - qwerty.alpha = modes[active_mode].value; - - color32 tenkey; - tenkey.red = RGBGetRValue(colors[1]); - tenkey.green = RGBGetGValue(colors[1]); - tenkey.blue = RGBGetBValue(colors[1]); - tenkey.alpha = modes[active_mode].value; - - color32 functionkey; - functionkey.red = RGBGetRValue(colors[2]); - functionkey.green = RGBGetGValue(colors[2]); - functionkey.blue = RGBGetBValue(colors[2]); - functionkey.alpha = modes[active_mode].value; - - color32 mxkey; - mxkey.red = RGBGetRValue(colors[3]); - mxkey.green = RGBGetGValue(colors[3]); - mxkey.blue = RGBGetBValue(colors[3]); - mxkey.alpha = modes[active_mode].value; - - color32 logo; - logo.red = RGBGetRValue(colors[4]); - logo.green = RGBGetGValue(colors[4]); - logo.blue = RGBGetBValue(colors[4]); - logo.alpha = modes[active_mode].value; - - controller->SetColorDetailed(qwerty, tenkey, functionkey, mxkey, logo); -} - -void RGBController_SteelSeriesOldApex::UpdateZoneLEDs(int /*zone*/) -{ - // updating for one zone is pointless, - // all zones have to be blasted anyway - // so just do a full update - DeviceUpdateLEDs(); -} - - -void RGBController_SteelSeriesOldApex::UpdateSingleLED(int /*led*/) -{ - // Each zone is one LED, however - // updating for one zone is pointless, - // all zones have to be blasted anyway - // so just do a full update - DeviceUpdateLEDs(); -} - -void RGBController_SteelSeriesOldApex::DeviceUpdateMode() -{ - // We are using SetLightingEffect to control the brightness of - // LEDs. Per-zone brightness is actually possible but we are not - // doing that for now. Brightness affects whole keyboard. - - // Because at the moment all this code does is change brightness, - // We just let the new value set in and do a device LED update - // and blast the brightness value along with the RGB values - - DeviceUpdateLEDs(); -} diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesOldApex.h b/Controllers/SteelSeriesController/RGBController_SteelSeriesOldApex.h deleted file mode 100644 index 09a2b4ab..00000000 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesOldApex.h +++ /dev/null @@ -1,42 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SteelSeriesOldApex.h | -| | -| Generic RGB Interface older-style | -| SteelSeriesApex Keyboards | -| (APEX/APEX Fnatic/Apex 350) | -| Class | -| | -| David Lee (RAMChYLD) 15/11/2020 | -| | -| Based on work by | -| B Horn (bahorn) 13/05/2020 | -| | -| Based on findings in ApexCtl by | -| Audrius/tuxmark5, et. al | -| https://github.com/tuxmark5/ApexCtl | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "SteelSeriesOldApexController.h" -#include "color32.h" - -class RGBController_SteelSeriesOldApex : public RGBController -{ -public: - RGBController_SteelSeriesOldApex(SteelSeriesOldApexController* controller_ptr); - ~RGBController_SteelSeriesOldApex(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - SteelSeriesOldApexController* controller; -}; diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesQCKMat.cpp b/Controllers/SteelSeriesController/RGBController_SteelSeriesQCKMat.cpp deleted file mode 100644 index 86c7c4ea..00000000 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesQCKMat.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SteelSeriesQCKMat.cpp | -| | -| Generic RGB Interface SteelSeriesQCK | -| Class | -| | -| Edbgon 22/05/2021 | -\*-----------------------------------------*/ - -#include "RGBController_SteelSeriesQCKMat.h" - -/**------------------------------------------------------------------*\ - @name Steel Series QCK Mat - @category Mousemat - @type USB - @save :x: - @direct :white_check_mark: - @effects :x: - @detectors DetectSteelSeriesMousemat - @comment -\*-------------------------------------------------------------------*/ - -RGBController_SteelSeriesQCKMat::RGBController_SteelSeriesQCKMat(SteelSeriesQCKMatController* controller_ptr) -{ - controller = controller_ptr; - - name = controller->GetDeviceName(); - vendor = "SteelSeries"; - type = DEVICE_TYPE_MOUSEMAT; - description = "SteelSeries QCK Mat Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - mode Direct; - Direct.name = "Direct"; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - - SetupZones(); -} - -RGBController_SteelSeriesQCKMat::~RGBController_SteelSeriesQCKMat() -{ - delete controller; -} - -void RGBController_SteelSeriesQCKMat::SetupZones() -{ - /*---------------------------------------------------------*\ - | QCK has two zones | - \*---------------------------------------------------------*/ - zone mousemat_zone; - mousemat_zone.name = "Mousemat"; - mousemat_zone.type = ZONE_TYPE_SINGLE; - mousemat_zone.leds_min = 2; - mousemat_zone.leds_max = 2; - mousemat_zone.leds_count = 2; - mousemat_zone.matrix_map = NULL; - zones.push_back(mousemat_zone); - - led bot_led; - bot_led.name = "Mat Bottom LED"; - leds.push_back(bot_led); - - led top_led; - top_led.name = "Mat Top LED"; - leds.push_back(top_led); - - SetupColors(); -} - -void RGBController_SteelSeriesQCKMat::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_SteelSeriesQCKMat::DeviceUpdateLEDs() -{ - controller->SetColors(colors); -} - -void RGBController_SteelSeriesQCKMat::UpdateZoneLEDs(int /*zone*/) -{ - /*---------------------------------------------------------*\ - | Packet expects both LEDs | - \*---------------------------------------------------------*/ - DeviceUpdateLEDs(); -} - -void RGBController_SteelSeriesQCKMat::UpdateSingleLED(int /*led*/) -{ - /*---------------------------------------------------------*\ - | Packet expects both LEDs | - \*---------------------------------------------------------*/ - DeviceUpdateLEDs(); -} - -void RGBController_SteelSeriesQCKMat::DeviceUpdateMode() -{ - DeviceUpdateLEDs(); -} diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesQCKMat.h b/Controllers/SteelSeriesController/RGBController_SteelSeriesQCKMat.h deleted file mode 100644 index 3b141544..00000000 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesQCKMat.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SteelSeriesQCKMat.h | -| | -| Generic RGB Interface SteelSeriesQCK | -| Class | -| | -| Edbgon 22/05/2021 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "SteelSeriesQCKMatController.h" - -class RGBController_SteelSeriesQCKMat : public RGBController -{ -public: - RGBController_SteelSeriesQCKMat(SteelSeriesQCKMatController* controller_ptr); - ~RGBController_SteelSeriesQCKMat(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - SteelSeriesQCKMatController* controller; -}; diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesRival.h b/Controllers/SteelSeriesController/RGBController_SteelSeriesRival.h deleted file mode 100644 index 3bb0f992..00000000 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesRival.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SteelSeriesRival.h | -| | -| Generic RGB Interface SteelSeriesRival | -| Class | -| | -| B Horn (bahorn) 13/05/2020 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "SteelSeriesRivalController.h" - -class RGBController_SteelSeriesRival : public RGBController -{ -public: - RGBController_SteelSeriesRival(SteelSeriesRivalController* controller_ptr); - ~RGBController_SteelSeriesRival(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - SteelSeriesRivalController* controller; -}; diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesRival3.h b/Controllers/SteelSeriesController/RGBController_SteelSeriesRival3.h deleted file mode 100644 index 33b13ce6..00000000 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesRival3.h +++ /dev/null @@ -1,34 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SteelSeriesRival.h | -| | -| Generic RGB Interface SteelSeriesRival3 | -| Class | -| | -| B Horn (bahorn) 29/08/2021 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "SteelSeriesAerox3Controller.h" -#include "SteelSeriesRival3Controller.h" - -class RGBController_SteelSeriesRival3 : public RGBController -{ -public: - RGBController_SteelSeriesRival3(SteelSeriesMouseController* controller_ptr); - ~RGBController_SteelSeriesRival3(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - void DeviceSaveMode(); - -private: - SteelSeriesMouseController* controller; -}; diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesSensei.cpp b/Controllers/SteelSeriesController/RGBController_SteelSeriesSensei.cpp deleted file mode 100644 index bbb59493..00000000 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesSensei.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/*------------------------------------------*\ -| RGBController_SteelSeriesSensei.cpp | -| | -| Generic RGB Interface SteelSeriesSensei | -| Class | -| Based on Rival Controller by | -| B Horn (bahorn) 13/05/2020 | -\*------------------------------------------*/ - -#include "RGBController_SteelSeriesSensei.h" - -/**------------------------------------------------------------------*\ - @name Steel Series Sensei - @category Mouse - @type USB - @save :x: - @direct :white_check_mark: - @effects :white_check_mark: - @detectors DetectSteelSeriesSensei - @comment -\*-------------------------------------------------------------------*/ - -RGBController_SteelSeriesSensei::RGBController_SteelSeriesSensei(SteelSeriesSenseiController* controller_ptr) -{ - controller = controller_ptr; - - name = controller->GetDeviceName(); - vendor = "SteelSeries"; - type = DEVICE_TYPE_MOUSE; - description = "SteelSeries Sensei Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - mode Direct; - Direct.name = "Direct"; - Direct.value = STEELSERIES_SENSEI_MODE_DIRECT; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Direct); - - mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = STEELSERIES_SENSEI_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR; - Breathing.color_mode = MODE_COLORS_PER_LED; - Breathing.speed_min = STEELSERIES_SENSEI_EFFECT_BREATHING_MIN; - Breathing.speed_max = STEELSERIES_SENSEI_EFFECT_BREATHING_MAX; - Breathing.speed = STEELSERIES_SENSEI_EFFECT_BREATHING_MID; - modes.push_back(Breathing); - - mode Rainbow; - Rainbow.name = "Rainbow"; - Rainbow.value = STEELSERIES_SENSEI_MODE_RAINBOW; - Rainbow.flags = MODE_FLAG_HAS_SPEED; - Rainbow.color_mode = MODE_COLORS_NONE; - Rainbow.speed_min = STEELSERIES_SENSEI_EFFECT_RAINBOW_MIN; - Rainbow.speed_max = STEELSERIES_SENSEI_EFFECT_RAINBOW_MAX; - Rainbow.speed = STEELSERIES_SENSEI_EFFECT_RAINBOW_MID; - modes.push_back(Rainbow); - - SetupZones(); -} - -RGBController_SteelSeriesSensei::~RGBController_SteelSeriesSensei() -{ - delete controller; -} - -void RGBController_SteelSeriesSensei::SetupZones() -{ - zone logo_zone; - logo_zone.name = "Logo"; - logo_zone.type = ZONE_TYPE_SINGLE; - logo_zone.leds_min = 1; - logo_zone.leds_max = 1; - logo_zone.leds_count = 1; - logo_zone.matrix_map = NULL; - zones.push_back(logo_zone); - - led logo_led; - logo_led.name = "Logo"; - leds.push_back(logo_led); - - zone wheel_zone; - wheel_zone.name = "Scroll Wheel"; - wheel_zone.type = ZONE_TYPE_SINGLE; - wheel_zone.leds_min = 1; - wheel_zone.leds_max = 1; - wheel_zone.leds_count = 1; - wheel_zone.matrix_map = NULL; - zones.push_back(wheel_zone); - - led wheel_led; - wheel_led.name = "Scroll Wheel"; - leds.push_back(wheel_led); - - SetupColors(); -} - -void RGBController_SteelSeriesSensei::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_SteelSeriesSensei::DeviceUpdateLEDs() -{ - UpdateZoneLEDs(0); - UpdateZoneLEDs(1); -} - -void RGBController_SteelSeriesSensei::UpdateZoneLEDs(int zone) -{ - RGBColor color = colors[zone]; - unsigned char red = RGBGetRValue(color); - unsigned char grn = RGBGetGValue(color); - unsigned char blu = RGBGetBValue(color); - - switch(modes[active_mode].value) - { - case STEELSERIES_SENSEI_MODE_DIRECT: - controller->SetColor(zone, red, grn, blu); - break; - - case STEELSERIES_SENSEI_MODE_BREATHING: - case STEELSERIES_SENSEI_MODE_RAINBOW: - controller->SetLightEffect(zone, modes[active_mode].value, modes[active_mode].speed, red, grn, blu); - break; - } -} - -void RGBController_SteelSeriesSensei::UpdateSingleLED(int led) -{ - /*---------------------------------------------------------*\ - | Each zone only has a single LED, so we can use the LED ID | - | to reference the existing zone code. | - \*---------------------------------------------------------*/ - UpdateZoneLEDs(led); -} - -void RGBController_SteelSeriesSensei::DeviceUpdateMode() -{ - /*---------------------------------------------------------*\ - | Strictly, the device actually does support different modes| - | for the different zones, but we don't support that. | - \*---------------------------------------------------------*/ - DeviceUpdateLEDs(); -} diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesSensei.h b/Controllers/SteelSeriesController/RGBController_SteelSeriesSensei.h deleted file mode 100644 index 6d3a96ff..00000000 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesSensei.h +++ /dev/null @@ -1,32 +0,0 @@ -/*------------------------------------------*\ -| RGBController_SteelSeriesSensei.h | -| | -| Generic RGB Interface SteelSeriesSensei | -| Class | -| Based on Rival controller by | -| B Horn (bahorn) 13/05/2020 | -\*------------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "SteelSeriesSenseiController.h" - -class RGBController_SteelSeriesSensei : public RGBController -{ -public: - RGBController_SteelSeriesSensei(SteelSeriesSenseiController* controller_ptr); - ~RGBController_SteelSeriesSensei(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - SteelSeriesSenseiController* controller; -}; diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesSiberia.cpp b/Controllers/SteelSeriesController/RGBController_SteelSeriesSiberia.cpp deleted file mode 100644 index 6626a86a..00000000 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesSiberia.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SteelSeriesSiberia.cpp | -| | -| Generic RGB Interface SteelSeriesSiberia | -| Class | -| | -| E Karlsson (pilophae) 18/06/2020 | -\*-----------------------------------------*/ - -#include "RGBController_SteelSeriesSiberia.h" - -/**------------------------------------------------------------------*\ - @name Steel Series Siberia - @category Headset - @type USB - @save :x: - @direct :x: - @effects :white_check_mark: - @detectors DetectSteelSeriesHeadset - @comment -\*-------------------------------------------------------------------*/ - -RGBController_SteelSeriesSiberia::RGBController_SteelSeriesSiberia(SteelSeriesSiberiaController* controller_ptr) -{ - controller = controller_ptr; - - name = controller->GetDeviceName(); - vendor = "SteelSeries"; - type = DEVICE_TYPE_HEADSET; - description = "SteelSeries Siberia Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - - mode Static; - Static.name = "Static"; - Static.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Static.color_mode = MODE_COLORS_PER_LED; - modes.push_back(Static); - - SetupZones(); -} - -RGBController_SteelSeriesSiberia::~RGBController_SteelSeriesSiberia() -{ - delete controller; -} - -void RGBController_SteelSeriesSiberia::SetupZones() -{ - /* Siberia 350 only has one Zone */ - zone earpiece_zone; - earpiece_zone.name = "Headset"; - earpiece_zone.type = ZONE_TYPE_SINGLE; - earpiece_zone.leds_min = 1; - earpiece_zone.leds_max = 1; - earpiece_zone.leds_count = 1; - earpiece_zone.matrix_map = NULL; - zones.push_back(earpiece_zone); - - led earpiece_led; - earpiece_led.name = "Headset LED"; - leds.push_back(earpiece_led); - - SetupColors(); -} - -void RGBController_SteelSeriesSiberia::ResizeZone(int /*zone*/, int /*new_size*/) -{ - /*---------------------------------------------------------*\ - | This device does not support resizing zones | - \*---------------------------------------------------------*/ -} - -void RGBController_SteelSeriesSiberia::DeviceUpdateLEDs() -{ - unsigned char red = RGBGetRValue(colors[0]); - unsigned char grn = RGBGetGValue(colors[0]); - unsigned char blu = RGBGetBValue(colors[0]); - controller->SetColor(red, grn, blu); -} - -void RGBController_SteelSeriesSiberia::UpdateZoneLEDs(int zone) -{ - RGBColor color = colors[zone]; - unsigned char red = RGBGetRValue(color); - unsigned char grn = RGBGetGValue(color); - unsigned char blu = RGBGetBValue(color); - controller->SetColor(red, grn, blu); -} - -void RGBController_SteelSeriesSiberia::UpdateSingleLED(int led) -{ - /* Each zone only has a single LED, so we can use the LED ID to reference - * the existing zone code. */ - UpdateZoneLEDs(led); -} - -void RGBController_SteelSeriesSiberia::DeviceUpdateMode() -{ - DeviceUpdateLEDs(); -} diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesSiberia.h b/Controllers/SteelSeriesController/RGBController_SteelSeriesSiberia.h deleted file mode 100644 index 9cfeeb90..00000000 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesSiberia.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_SteelSeriesSiberia.h | -| | -| Generic RGB Interface SteelSeriesSiberia | -| Class | -| | -| E Karlsson (pilophae) 18/06/2020 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "SteelSeriesSiberiaController.h" - -class RGBController_SteelSeriesSiberia : public RGBController -{ -public: - RGBController_SteelSeriesSiberia(SteelSeriesSiberiaController* controller_ptr); - ~RGBController_SteelSeriesSiberia(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - SteelSeriesSiberiaController* controller; -}; diff --git a/Controllers/SteelSeriesController/SteelSeriesAerox3Controller.h b/Controllers/SteelSeriesController/SteelSeriesAerox3Controller.h deleted file mode 100644 index 667fe1fb..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesAerox3Controller.h +++ /dev/null @@ -1,55 +0,0 @@ -/*-------------------------------------------------------------------*\ -| SteelSeriesAerox3Controller.h | -| | -| OpenRGB controller driver for the Steelseries Aerox3 Wired | -| | -| Chris M (Dr_No) 9th June 2022 | -\*-------------------------------------------------------------------*/ - -#include -#include -#include - -#include "RGBController.h" -#include "SteelSeriesGeneric.h" -#include "SteelSeriesMouseController.h" - -#pragma once - -#define STEELSERIES_AEORX3_PACKET_SIZE 65 -#define STEELSERIES_AEORX3_TIMEOUT 250 - -static const steelseries_mouse aerox_3 = -{ - { 0x04 }, - { - {"Front", 0 }, - {"Middle", 1 }, - {"Rear", 2 }, - } -}; - -class SteelSeriesAerox3Controller: public SteelSeriesMouseController -{ -public: - SteelSeriesAerox3Controller(hid_device* dev_handle, steelseries_type proto_type, const char* path); - ~SteelSeriesAerox3Controller(); - - std::string GetFirmwareVersion(); - steelseries_mouse GetMouse(); - - void Save() override; - void SetLightEffectAll(uint8_t effect); - void SetColor - ( - unsigned char zone_id, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char brightness - ); -private: - void SendInit(); - void SetBrightness(uint8_t brightness); - uint8_t current_brightness; -}; diff --git a/Controllers/SteelSeriesController/SteelSeriesAerox3Controller.cpp b/Controllers/SteelSeriesController/SteelSeriesAerox3Controller/SteelSeriesAerox3Controller.cpp similarity index 77% rename from Controllers/SteelSeriesController/SteelSeriesAerox3Controller.cpp rename to Controllers/SteelSeriesController/SteelSeriesAerox3Controller/SteelSeriesAerox3Controller.cpp index 95a22c9f..7ce220b8 100644 --- a/Controllers/SteelSeriesController/SteelSeriesAerox3Controller.cpp +++ b/Controllers/SteelSeriesController/SteelSeriesAerox3Controller/SteelSeriesAerox3Controller.cpp @@ -1,16 +1,18 @@ -/*-------------------------------------------------------------------*\ -| SteelSeriesAerox3Controller.cpp | -| | -| OpenRGB controller driver for the Steelseries Aerox3 Wired | -| | -| Chris M (Dr_No) 9th June 2022 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| SteelSeriesAerox3Controller.cpp | +| | +| Driver for SteelSeries Aerox 3 | +| | +| Chris M (Dr_No) 09 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "SteelSeriesAerox3Controller.h" #include "LogManager.h" -SteelSeriesAerox3Controller::SteelSeriesAerox3Controller(hid_device* dev_handle, steelseries_type proto_type, const char* path) - : SteelSeriesMouseController(dev_handle, proto_type, path) +SteelSeriesAerox3Controller::SteelSeriesAerox3Controller(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name) : SteelSeriesMouseController(dev_handle, proto_type, path, dev_name) { SendInit(); } @@ -37,7 +39,7 @@ std::string SteelSeriesAerox3Controller::GetFirmwareVersion() uint8_t result = 0; const uint8_t CMD = 0x90; const uint8_t sz = 16; - char version[sz]; + char version[sz + 1]; uint8_t buffer[STEELSERIES_AEORX3_PACKET_SIZE] = { 0x00, CMD, 0x00 }; @@ -45,7 +47,7 @@ std::string SteelSeriesAerox3Controller::GetFirmwareVersion() do { result = hid_read_timeout(dev, buffer, STEELSERIES_AEORX3_PACKET_SIZE, STEELSERIES_AEORX3_TIMEOUT); - LOG_DEBUG("[%s] Reading version buffer: Bytes Read %d Buffer %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", device_name, result, + LOG_DEBUG("[%s] Reading version buffer: Bytes Read %d Buffer %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", STEELSERIES_AEORX3_NAME, result, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9], buffer[10]); } while(result > 0 && buffer[0] != CMD); @@ -55,14 +57,15 @@ std::string SteelSeriesAerox3Controller::GetFirmwareVersion() | Read the version from the second character | \*-----------------------------------------------------------------*/ memcpy(version, &buffer[1], sz); + version[sz] = 0; std::string tmp = std::string(version); - LOG_DEBUG("[%s] Version: %s as string %s", device_name, version, tmp.c_str()); + LOG_DEBUG("[%s] Version: %s as string %s", STEELSERIES_AEORX3_NAME, version, tmp.c_str()); return tmp; } else { - LOG_DEBUG("[%s] Unable to get version: giving up!", device_name); + LOG_DEBUG("[%s] Unable to get version: giving up!", STEELSERIES_AEORX3_NAME); return ""; } } diff --git a/Controllers/SteelSeriesController/SteelSeriesAerox3Controller/SteelSeriesAerox3Controller.h b/Controllers/SteelSeriesController/SteelSeriesAerox3Controller/SteelSeriesAerox3Controller.h new file mode 100644 index 00000000..a802f7e0 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesAerox3Controller/SteelSeriesAerox3Controller.h @@ -0,0 +1,58 @@ +/*---------------------------------------------------------*\ +| SteelSeriesAerox3Controller.h | +| | +| Driver for SteelSeries Aerox 3 | +| | +| Chris M (Dr_No) 09 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" +#include "SteelSeriesGeneric.h" +#include "SteelSeriesMouseController.h" + +#define STEELSERIES_AEORX3_NAME "SteelSeries Aerox 3" +#define STEELSERIES_AEORX3_PACKET_SIZE 65 +#define STEELSERIES_AEORX3_TIMEOUT 250 + +static const steelseries_mouse aerox_3 = +{ + { 0x04 }, + { + {"Front", 0 }, + {"Middle", 1 }, + {"Rear", 2 }, + } +}; + +class SteelSeriesAerox3Controller: public SteelSeriesMouseController +{ +public: + SteelSeriesAerox3Controller(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name); + ~SteelSeriesAerox3Controller(); + + std::string GetFirmwareVersion() override; + steelseries_mouse GetMouse() override; + + void Save() override; + void SetLightEffectAll(uint8_t effect) override; + void SetColor + ( + unsigned char zone_id, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char brightness + ) override; +private: + void SendInit(); + void SetBrightness(uint8_t brightness); + uint8_t current_brightness; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesAerox5Controller/SteelSeriesAerox5Controller.cpp b/Controllers/SteelSeriesController/SteelSeriesAerox5Controller/SteelSeriesAerox5Controller.cpp new file mode 100644 index 00000000..a73b2b68 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesAerox5Controller/SteelSeriesAerox5Controller.cpp @@ -0,0 +1,147 @@ +/*---------------------------------------------------------*\ +| SteelSeriesAerox5Controller.cpp | +| | +| Driver for the Steelseries Aerox 5 | +| | +| Bobby Quantum (BobbyQuantum) 19 May 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "SteelSeriesAerox5Controller.h" +#include "LogManager.h" + +SteelSeriesAerox5Controller::SteelSeriesAerox5Controller(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name) : SteelSeriesMouseController(dev_handle, proto_type, path, dev_name) +{ + SendInit(); +} + +SteelSeriesAerox5Controller::~SteelSeriesAerox5Controller() +{ + hid_close(dev); +} + +void SteelSeriesAerox5Controller::SendInit() +{ + /*-----------------------------------------------------------------*\ + | This sets sensitivity and allows software mode?? max 5 uint8 | + | buffer[2] = Count eg. 0 thru 5 | + | buffer[4] to [8] = dpi / 50 range = 0x04 - 0xC7 eg. 400 = 0x08 | + \*-----------------------------------------------------------------*/ + uint8_t buffer[STEELSERIES_AEROX5_PACKET_SIZE] = { 0x00, 0x2D }; + + hid_send_feature_report(dev, buffer, STEELSERIES_AEROX5_PACKET_SIZE); +} + +std::string SteelSeriesAerox5Controller::GetFirmwareVersion() +{ + uint8_t result = 0; + const uint8_t CMD = 0x90; + const uint8_t sz = 16; + char version[sz + 1]; + + uint8_t buffer[STEELSERIES_AEROX5_PACKET_SIZE] = { 0x00, CMD, 0x00 }; + + hid_send_feature_report(dev, buffer, STEELSERIES_AEROX5_PACKET_SIZE); + do + { + result = hid_read_timeout(dev, buffer, STEELSERIES_AEROX5_PACKET_SIZE, STEELSERIES_AEROX5_TIMEOUT); + LOG_DEBUG("[%s] Reading version buffer: Bytes Read %d Buffer %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", STEELSERIES_AEROX5_NAME, result, + buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9], buffer[10]); + } while(result > 0 && buffer[0] != CMD); + + if(buffer[0] == CMD) + { + /*-----------------------------------------------------------------*\ + | Read the version from the second character | + \*-----------------------------------------------------------------*/ + memcpy(version, &buffer[1], sz); + version[sz] = 0; + std::string tmp = std::string(version); + LOG_DEBUG("[%s] Version: %s as string %s", STEELSERIES_AEROX5_NAME, version, tmp.c_str()); + + return tmp; + } + else + { + LOG_DEBUG("[%s] Unable to get version: giving up!", STEELSERIES_AEROX5_NAME); + return ""; + } +} + +steelseries_mouse SteelSeriesAerox5Controller::GetMouse() +{ + return aerox_5; +} + +void SteelSeriesAerox5Controller::SetLightEffectAll(uint8_t /*effect*/) +{ + /*-----------------------------------------------------------------*\ + | Not used by this device | + \*-----------------------------------------------------------------*/ +} + +void SteelSeriesAerox5Controller::SetColor + ( + unsigned char zone_id, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char brightness + ) +{ + uint8_t buffer[STEELSERIES_AEROX5_PACKET_SIZE] = { 0x00, 0x21, 0x01 }; + + uint8_t offset = 0x03; + + switch (zone_id) + { + case 0: + offset = 0x03; + break; + case 1: + buffer[2] = 0x02; + offset = 0x06; + break; + case 2: + buffer[2] = 0x04; + offset = 0x09; + break; + case 3: + buffer[1] = 0x26; + offset = 0x04; + break; + default: + return; + } + + buffer[offset] = red; + buffer[offset + 1] = green; + buffer[offset + 2] = blue; + + hid_write(dev, buffer, STEELSERIES_AEROX5_PACKET_SIZE); + std::this_thread::sleep_for(std::chrono::milliseconds(2)); + + if (brightness != current_brightness) + { + SetBrightness(brightness); + current_brightness = brightness; + } +} + +void SteelSeriesAerox5Controller::SetBrightness(uint8_t brightness) +{ + uint8_t buffer[3] = { 0x00, 0x23, brightness }; + + hid_write(dev, buffer, STEELSERIES_AEROX5_PACKET_SIZE); + + std::this_thread::sleep_for(std::chrono::milliseconds(2)); +} + +void SteelSeriesAerox5Controller::Save() +{ + uint8_t buffer2[3] = { 0x00, 0x11, 0x00 }; + + hid_write(dev, buffer2, STEELSERIES_AEROX5_PACKET_SIZE); +} diff --git a/Controllers/SteelSeriesController/SteelSeriesAerox5Controller/SteelSeriesAerox5Controller.h b/Controllers/SteelSeriesController/SteelSeriesAerox5Controller/SteelSeriesAerox5Controller.h new file mode 100644 index 00000000..be30691f --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesAerox5Controller/SteelSeriesAerox5Controller.h @@ -0,0 +1,61 @@ +/*---------------------------------------------------------*\ +| SteelSeriesAerox5Controller.h | +| | +| Driver for the Steelseries Aerox 5 | +| | +| Bobby Quantum (BobbyQuantum) 19 May 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" +#include "SteelSeriesGeneric.h" +#include "SteelSeriesMouseController.h" + +#define STEELSERIES_AEROX5_NAME "SteelSeries Aerox 5" +#define STEELSERIES_AEROX5_PACKET_SIZE 65 +#define STEELSERIES_AEROX5_TIMEOUT 250 + +static const steelseries_mouse aerox_5 = +{ + { 0x04 }, + { + {"Front", 0 }, + {"Middle", 1 }, + {"Rear", 2 }, + {"Reactive", 3 }, + } +}; + + +class SteelSeriesAerox5Controller : public SteelSeriesMouseController +{ +public: + SteelSeriesAerox5Controller(hid_device *dev_handle, steelseries_type proto_type, const char *path, std::string dev_name); + ~SteelSeriesAerox5Controller(); + + std::string GetFirmwareVersion() override; + steelseries_mouse GetMouse() override; + + void Save() override; + void SetLightEffectAll(uint8_t effect) override; + void SetColor + ( + unsigned char zone_id, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char brightness + ) override; + +private: + void SendInit(); + void SetBrightness(uint8_t brightness); + uint8_t current_brightness; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesAerox9Controller.cpp b/Controllers/SteelSeriesController/SteelSeriesAerox9Controller.cpp deleted file mode 100644 index 6b455aec..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesAerox9Controller.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/*----------------------------------------------------------------------*\ -| SteelSeriesAerox9Controller.cpp | -| | -| OpenRGB controller driver for the Steelseries Aerox9 Wireless (Wired) | -| | -| rom4ster 11th October 2022 | -\*---------------------------------------------------------------------*/ - -#include "SteelSeriesAerox9Controller.h" -#include "LogManager.h" - -SteelSeriesAerox9Controller::SteelSeriesAerox9Controller(hid_device* dev_handle, steelseries_type proto_type, const char* path) - : SteelSeriesMouseController(dev_handle, proto_type, path) -{ - SendInit(); -} - -SteelSeriesAerox9Controller::~SteelSeriesAerox9Controller() -{ - hid_close(dev); -} - -void SteelSeriesAerox9Controller::SendInit() -{ - /*-----------------------------------------------------------------*\ - | This sets sensitivity and allows software mode?? max 5 uint8 | - | buffer[2] = Count eg. 0 thru 5 | - | buffer[4] to [8] = dpi / 50 range = 0x04 - 0xC7 eg. 400 = 0x08 | - \*-----------------------------------------------------------------*/ - uint8_t buffer[STEELSERIES_AEORX9_PACKET_SIZE] = { 0x00, 0x2D }; - - hid_send_feature_report(dev, buffer, STEELSERIES_AEORX9_PACKET_SIZE); -} - -std::string SteelSeriesAerox9Controller::GetFirmwareVersion() -{ - uint8_t result = 0; - const uint8_t CMD = 0x90; - const uint8_t sz = 16; - char version[sz]; - - uint8_t buffer[STEELSERIES_AEORX9_PACKET_SIZE] = { 0x00, CMD, 0x00 }; - - hid_send_feature_report(dev, buffer, STEELSERIES_AEORX9_PACKET_SIZE); - do - { - result = hid_read_timeout(dev, buffer, STEELSERIES_AEORX9_PACKET_SIZE, STEELSERIES_AEORX9_TIMEOUT); - LOG_DEBUG("[%s] Reading version buffer: Bytes Read %d Buffer %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", device_name, result, - buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9], buffer[10]); - } while(result > 0 && buffer[0] != CMD); - - if(buffer[0] == CMD) - { - /*-----------------------------------------------------------------*\ - | Read the version from the second character | - \*-----------------------------------------------------------------*/ - memcpy(version, &buffer[1], sz); - std::string tmp = std::string(version); - LOG_DEBUG("[%s] Version: %s as string %s", device_name, version, tmp.c_str()); - - return tmp; - } - else - { - LOG_DEBUG("[%s] Unable to get version: giving up!", device_name); - return ""; - } -} - -steelseries_mouse SteelSeriesAerox9Controller::GetMouse() -{ - return aerox_9; -} - -void SteelSeriesAerox9Controller::SetLightEffectAll(uint8_t /*effect*/) -{ - /*-----------------------------------------------------------------*\ - | Not used by this device | - \*-----------------------------------------------------------------*/ -} - -void SteelSeriesAerox9Controller::SetColor - ( - unsigned char zone_id, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char brightness - ) -{ - - uint8_t buffer[STEELSERIES_AEORX9_PACKET_SIZE] = - { - 0x00, - 0x21 - }; - - buffer[0x02] = 0x1; - uint8_t offset = 0x3; - - if (zone_id == 3) - { - offset = 0x3; - buffer[0x01] = 0x26; - buffer[offset] = 0x00; - } else { - buffer[offset] = zone_id; - } - - - - buffer[offset + 1] = red; - buffer[offset + 2] = green; - buffer[offset + 3] = blue; - - hid_write(dev, buffer, STEELSERIES_AEORX9_PACKET_SIZE); - - if(brightness != current_brightness) - { - SetBrightness(brightness); - current_brightness = brightness; - } - Save(); -} - -void SteelSeriesAerox9Controller::SetBrightness(uint8_t brightness) -{ - uint8_t buffer[STEELSERIES_AEORX9_PACKET_SIZE] = { 0x00, 0x23, brightness }; - - hid_write(dev, buffer, STEELSERIES_AEORX9_PACKET_SIZE); -} - -void SteelSeriesAerox9Controller::Save() -{ - /*---------------------------------------------------------------------------------*\ - | Save packet was not confirmed as working but packet is verified as correct. | - | https://github.com/flozz/rivalcfg/blob/master/rivalcfg/devices/aerox3.py#L141 | - \*---------------------------------------------------------------------------------*/ - uint8_t buffer2[STEELSERIES_AEORX9_PACKET_SIZE] = { 0x00, 0x11, 0x00 }; - - hid_write(dev, buffer2, STEELSERIES_AEORX9_PACKET_SIZE); -} diff --git a/Controllers/SteelSeriesController/SteelSeriesAerox9Controller.h b/Controllers/SteelSeriesController/SteelSeriesAerox9Controller.h deleted file mode 100644 index f34970a9..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesAerox9Controller.h +++ /dev/null @@ -1,55 +0,0 @@ -/*----------------------------------------------------------------------*\ -| SteelSeriesAerox9Controller.h | -| | -| OpenRGB controller driver for the Steelseries Aerox9 Wireless (Wired) | -| | -| rom4ster 11th October 2022 | -\*---------------------------------------------------------------------*/ -#include -#include -#include - -#include "RGBController.h" -#include "SteelSeriesGeneric.h" -#include "SteelSeriesMouseController.h" - -#pragma once - -#define STEELSERIES_AEORX9_PACKET_SIZE 65 -#define STEELSERIES_AEORX9_TIMEOUT 250 - -static const steelseries_mouse aerox_9 = -{ - { 0x04 }, - { - {"Front", 0 }, - {"Middle", 1 }, - {"Rear", 2 }, - {"Reactive", 3 }, - } -}; - -class SteelSeriesAerox9Controller: public SteelSeriesMouseController -{ -public: - SteelSeriesAerox9Controller(hid_device* dev_handle, steelseries_type proto_type, const char* path); - ~SteelSeriesAerox9Controller(); - - std::string GetFirmwareVersion(); - steelseries_mouse GetMouse(); - - void Save() override; - void SetLightEffectAll(uint8_t effect); - void SetColor - ( - unsigned char zone_id, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char brightness - ); -private: - void SendInit(); - void SetBrightness(uint8_t brightness); - uint8_t current_brightness; -}; diff --git a/Controllers/SteelSeriesController/SteelSeriesAeroxWirelessController/SteelSeriesAeroxWirelessController.cpp b/Controllers/SteelSeriesController/SteelSeriesAeroxWirelessController/SteelSeriesAeroxWirelessController.cpp new file mode 100644 index 00000000..febcdb51 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesAeroxWirelessController/SteelSeriesAeroxWirelessController.cpp @@ -0,0 +1,225 @@ +/*---------------------------------------------------------*\ +| SteelSeriesAeroxWirelessController.cpp | +| | +| Driver for SteelSeries Aerox 3, 5 and 9 Wireless | +| | +| Ensar S (esensar) 09 Sep 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "SteelSeriesAeroxWirelessController.h" +#include "LogManager.h" +#include "SteelSeriesGeneric.h" + +SteelSeriesAeroxWirelessController::SteelSeriesAeroxWirelessController(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name) : SteelSeriesMouseController(dev_handle, proto_type, path, dev_name) +{ + switch(proto_type) + { + case AEROX_3_WIRELESS: + name = STEELSERIES_AEROX3_WIRELESS_NAME; + break; + case AEROX_3_WIRELESS_WIRED: + name = STEELSERIES_AEROX3_WIRELESS_WIRED_NAME; + break; + case AEROX_5_WIRELESS: + name = STEELSERIES_AEROX5_WIRELESS_NAME; + break; + case AEROX_5_WIRELESS_WIRED: + name = STEELSERIES_AEROX5_WIRELESS_WIRED_NAME; + break; + case AEROX_5_DESTINY_WIRELESS: + name = STEELSERIES_AEROX5_DESTINY_WIRELESS_NAME; + break; + case AEROX_5_DESTINY_WIRELESS_WIRED: + name = STEELSERIES_AEROX5_DESTINY_WIRELESS_WIRED_NAME; + break; + case AEROX_5_DIABLO_WIRELESS: + name = STEELSERIES_AEROX5_DIABLO_WIRELESS_NAME; + break; + case AEROX_5_DIABLO_WIRELESS_WIRED: + name = STEELSERIES_AEROX5_DIABLO_WIRELESS_WIRED_NAME; + break; + case AEROX_9_WIRELESS: + name = STEELSERIES_AEROX9_WIRELESS_NAME; + break; + case AEROX_9_WIRELESS_WIRED: + name = STEELSERIES_AEROX9_WIRELESS_WIRED_NAME; + break; + default: + name = STEELSERIES_AEROX3_WIRELESS_NAME; + break; + } + SendInit(); +} + +SteelSeriesAeroxWirelessController::~SteelSeriesAeroxWirelessController() +{ + hid_close(dev); +} + +void SteelSeriesAeroxWirelessController::SendInit() +{ + /*-----------------------------------------------------------------*\ + | This sets sensitivity and allows software mode?? max 5 uint8 | + | buffer[2] = Count eg. 0 thru 5 | + | buffer[4] to [8] = dpi / 50 range = 0x04 - 0xC7 eg. 400 = 0x08 | + \*-----------------------------------------------------------------*/ + uint8_t buffer[STEELSERIES_AEROX_WIRELESS_PACKET_SIZE] = { 0x00, 0x2D }; + + hid_send_feature_report(dev, buffer, STEELSERIES_AEROX_WIRELESS_PACKET_SIZE); +} + +bool SteelSeriesAeroxWirelessController::IsWireless() +{ + switch(proto) + { + case AEROX_3_WIRELESS: + case AEROX_5_WIRELESS: + case AEROX_5_DESTINY_WIRELESS: + case AEROX_5_DIABLO_WIRELESS: + case AEROX_9_WIRELESS: + return true; + break; + case AEROX_3_WIRELESS_WIRED: + case AEROX_5_WIRELESS_WIRED: + case AEROX_5_DESTINY_WIRELESS_WIRED: + case AEROX_5_DIABLO_WIRELESS_WIRED: + case AEROX_9_WIRELESS_WIRED: + default: + return false; + break; + } +} + +std::string SteelSeriesAeroxWirelessController::GetFirmwareVersion() +{ + uint8_t result = 0; + const uint8_t CMD = 0x90; + const uint8_t sz = 16; + char version[sz + 1]; + + uint8_t buffer[STEELSERIES_AEROX_WIRELESS_PACKET_SIZE] = { 0x00, CMD, 0x00 }; + + hid_send_feature_report(dev, buffer, STEELSERIES_AEROX_WIRELESS_PACKET_SIZE); + do + { + result = hid_read_timeout(dev, buffer, STEELSERIES_AEROX_WIRELESS_PACKET_SIZE, STEELSERIES_AEROX_WIRELESS_TIMEOUT); + LOG_DEBUG("[%s] Reading version buffer: Bytes Read %d Buffer %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", name, result, + buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9], buffer[10]); + } while(result > 0 && buffer[0] != CMD); + + if(buffer[0] == CMD) + { + /*-----------------------------------------------------------------*\ + | Read the version from the second character | + \*-----------------------------------------------------------------*/ + memcpy(version, &buffer[1], sz); + version[sz] = 0; + std::string tmp = std::string(version); + LOG_DEBUG("[%s] Version: %s as string %s", name, version, tmp.c_str()); + + return tmp; + } + else + { + LOG_DEBUG("[%s] Unable to get version: giving up!", name); + return ""; + } +} + +steelseries_mouse SteelSeriesAeroxWirelessController::GetMouse() +{ + switch(proto) + { + case AEROX_9_WIRELESS: + case AEROX_9_WIRELESS_WIRED: + return aerox_9; + break; + default: + return aerox_3_wireless; + break; + } +} + +void SteelSeriesAeroxWirelessController::SetLightEffectAll(uint8_t effect) +{ + if(effect == 0x05) + { + uint8_t buffer[STEELSERIES_AEROX_WIRELESS_PACKET_SIZE] = { 0x00, 0x22, 0xFF }; + + WriteBuffer(buffer); + } +} + +void SteelSeriesAeroxWirelessController::SetColor + ( + unsigned char zone_id, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char brightness + ) +{ + uint8_t buffer[STEELSERIES_AEROX_WIRELESS_PACKET_SIZE] = { 0x00, 0x21, 0x01 }; + uint8_t offset = 0x04; + + if (zone_id == 3 && (proto == AEROX_9_WIRELESS_WIRED || proto == AEROX_9_WIRELESS)) + { + buffer[0x03] = 0x00; + buffer[0x01] = 0x26; + } + else + { + buffer[0x03] = zone_id; + } + buffer[offset] = red; + buffer[offset + 1] = green; + buffer[offset + 2] = blue; + + WriteBuffer(buffer); + + // Supports only 10 steps of brightness + brightness = (uint8_t)(brightness / 10); + + if(brightness != current_brightness) + { + SetBrightness(brightness); + current_brightness = brightness; + } +} + +void SteelSeriesAeroxWirelessController::SetBrightness(uint8_t brightness) +{ + uint8_t buffer[STEELSERIES_AEROX_WIRELESS_PACKET_SIZE] = { 0x00, 0x23, brightness }; + + WriteBuffer(buffer); +} + +void SteelSeriesAeroxWirelessController::Save() +{ + /*---------------------------------------------------------------------------------*\ + | Save packet was not confirmed as working but packet is verified as correct. | + | https://github.com/flozz/rivalcfg/blob/master/rivalcfg/devices/aerox3.py#L141 | + \*---------------------------------------------------------------------------------*/ + uint8_t buffer2[STEELSERIES_AEROX_WIRELESS_PACKET_SIZE] = { 0x00, 0x11, 0x00 }; + + WriteBuffer(buffer2); +} + +void SteelSeriesAeroxWirelessController::WriteBuffer(uint8_t* buffer) +{ + if(IsWireless()) + { + buffer[1] |= STEELSERIES_AEROX_WIRELESS_FLAG; + } + + hid_write(dev, buffer, STEELSERIES_AEROX_WIRELESS_PACKET_SIZE); + + if(IsWireless()) + { + // Readback required in wireless mode + hid_read_timeout(dev, buffer, STEELSERIES_AEROX_WIRELESS_PACKET_SIZE, STEELSERIES_AEROX_WIRELESS_TIMEOUT); + } +} diff --git a/Controllers/SteelSeriesController/SteelSeriesAeroxWirelessController/SteelSeriesAeroxWirelessController.h b/Controllers/SteelSeriesController/SteelSeriesAeroxWirelessController/SteelSeriesAeroxWirelessController.h new file mode 100644 index 00000000..7e5bb28b --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesAeroxWirelessController/SteelSeriesAeroxWirelessController.h @@ -0,0 +1,82 @@ +/*---------------------------------------------------------*\ +| SteelSeriesAeroxWirelessController.h | +| | +| Driver for SteelSeries Aerox 3, 5 and 9 Wireless | +| | +| Ensar S (esensar) 09 Sep 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" +#include "SteelSeriesGeneric.h" +#include "SteelSeriesMouseController.h" + +#define STEELSERIES_AEROX3_WIRELESS_NAME "SteelSeries Aerox 3 Wireless (2.4 GHz wireless mode)" +#define STEELSERIES_AEROX3_WIRELESS_WIRED_NAME "SteelSeries Aerox 3 Wireless (wired mode)" +#define STEELSERIES_AEROX5_WIRELESS_NAME "SteelSeries Aerox 5 Wireless (2.4 GHz wireless mode)" +#define STEELSERIES_AEROX5_WIRELESS_WIRED_NAME "SteelSeries Aerox 5 Wireless (wired mode)" +#define STEELSERIES_AEROX5_DESTINY_WIRELESS_NAME "SteelSeries Aerox 5 Wireless Destiny 2 Edition (2.4 GHz wireless mode)" +#define STEELSERIES_AEROX5_DESTINY_WIRELESS_WIRED_NAME "SteelSeries Aerox 5 Wireless Destiny 2 Edition (wired mode)" +#define STEELSERIES_AEROX5_DIABLO_WIRELESS_NAME "SteelSeries Aerox 5 Wireless Diablo IV Edition (2.4 GHz wireless mode)" +#define STEELSERIES_AEROX5_DIABLO_WIRELESS_WIRED_NAME "SteelSeries Aerox 5 Wireless Diablo IV Edition (wired mode)" +#define STEELSERIES_AEROX9_WIRELESS_NAME "SteelSeries Aerox 9 Wireless (2.4 GHz wireless mode)" +#define STEELSERIES_AEROX9_WIRELESS_WIRED_NAME "SteelSeries Aerox 9 Wireless (wired mode)" +#define STEELSERIES_AEROX_WIRELESS_PACKET_SIZE 64 +#define STEELSERIES_AEROX_WIRELESS_TIMEOUT 250 +#define STEELSERIES_AEROX_WIRELESS_FLAG 0b01000000 + +static const steelseries_mouse aerox_3_wireless = +{ + { 0x04, 0x05 }, + { + {"Front", 0 }, + {"Middle", 1 }, + {"Rear", 2 }, + } +}; + +static const steelseries_mouse aerox_9 = +{ + { 0x04, 0x05 }, + { + {"Front", 0 }, + {"Middle", 1 }, + {"Rear", 2 }, + {"Reactive", 3 }, + } +}; + +class SteelSeriesAeroxWirelessController: public SteelSeriesMouseController +{ +public: + SteelSeriesAeroxWirelessController(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name); + ~SteelSeriesAeroxWirelessController(); + + std::string GetFirmwareVersion() override; + steelseries_mouse GetMouse() override; + + void Save() override; + void SetLightEffectAll(uint8_t effect) override; + void SetColor + ( + unsigned char zone_id, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char brightness + ) override; +private: + bool IsWireless(); + void SendInit(); + void WriteBuffer(uint8_t* buffer); + void SetBrightness(uint8_t brightness); + uint8_t current_brightness; + const char* name; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesApex3Controller.cpp b/Controllers/SteelSeriesController/SteelSeriesApex3Controller.cpp deleted file mode 100644 index 9f84f291..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesApex3Controller.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/*-------------------------------------------------------------------*\ -| SteelSeriesApex3Controller.cpp | -| | -| Driver for Steelseries Apex3 Controllers | -| This is the base class for the Ten Zone and 8 Zone keyboards | -| | -| Chris M (Dr_No) 23rd Feb 2022 | -\*-------------------------------------------------------------------*/ - -#include -#include "SteelSeriesApex3Controller.h" - -SteelSeriesApex3Controller::SteelSeriesApex3Controller(hid_device* dev_handle, const char* path) -{ - dev = dev_handle; - location = path; -} - -SteelSeriesApex3Controller::~SteelSeriesApex3Controller() -{ - hid_close(dev); -} - -std::string SteelSeriesApex3Controller::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string SteelSeriesApex3Controller::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); -} diff --git a/Controllers/SteelSeriesController/SteelSeriesApex3Controller.h b/Controllers/SteelSeriesController/SteelSeriesApex3Controller.h deleted file mode 100644 index 5767c62c..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesApex3Controller.h +++ /dev/null @@ -1,42 +0,0 @@ -/*-------------------------------------------------------------------*\ -| SteelSeriesApex3Controller.h | -| | -| Driver for Steelseries Apex3 Controllers | -| This is the base class for the Ten Zone and 8 Zone keyboards | -| | -| Chris M (Dr_No) 23rd Feb 2022 | -\*-------------------------------------------------------------------*/ - -#include -#include - -#include "RGBController.h" -#include "SteelSeriesGeneric.h" - -#pragma once - -#define STEELSERIES_APEX3_BRIGHTNESS_MIN 0x00 -#define STEELSERIES_APEX3_HID_TIMEOUT 100 - -class SteelSeriesApex3Controller -{ -public: - SteelSeriesApex3Controller(hid_device* dev_handle, const char* path); - virtual ~SteelSeriesApex3Controller(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - steelseries_type GetKeyboardType(); - - virtual void SetColor(std::vector colors, uint8_t mode, uint8_t brightness) = 0; - virtual void Save() = 0; - virtual uint8_t GetLedCount() = 0; - virtual uint8_t GetMaxBrightness() = 0; - virtual bool SupportsRainbowWave() = 0; - virtual bool SupportsSave() = 0; - - hid_device* dev; - -private: - std::string location; -}; diff --git a/Controllers/SteelSeriesController/SteelSeriesApex3Controller/RGBController_SteelSeriesApex3.cpp b/Controllers/SteelSeriesController/SteelSeriesApex3Controller/RGBController_SteelSeriesApex3.cpp new file mode 100644 index 00000000..5c6c7ee7 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesApex3Controller/RGBController_SteelSeriesApex3.cpp @@ -0,0 +1,131 @@ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesApex3.cpp | +| | +| RGBController for SteelSeries Apex 3 | +| | +| Chris M (Dr_No) 23 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_SteelSeriesApex3.h" + +/**------------------------------------------------------------------*\ + @name Steel Series Apex Tri Zone Keyboards + @category Keyboard + @type USB + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectSteelSeriesApexTZone + @comment +\*-------------------------------------------------------------------*/ + +RGBController_SteelSeriesApex3::RGBController_SteelSeriesApex3(SteelSeriesApex3Controller* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "SteelSeries"; + type = DEVICE_TYPE_KEYBOARD; + description = "SteelSeries Apex 3 Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode direct; + direct.name = "Direct"; + direct.value = static_cast(APEX3_MODES::DIRECT); + direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + if(controller->SupportsSave()) + { + direct.flags |= MODE_FLAG_MANUAL_SAVE; + } + direct.color_mode = MODE_COLORS_PER_LED; + direct.brightness_min = STEELSERIES_APEX3_BRIGHTNESS_MIN; + direct.brightness_max = controller->GetMaxBrightness(); + direct.brightness = direct.brightness_max; + modes.push_back(direct); + + if(controller->SupportsRainbowWave()) + { + mode rainbow; + rainbow.name = "Rainbow Wave"; + rainbow.value = static_cast(APEX3_MODES::RAINBOW_WAVE); + rainbow.flags = MODE_FLAG_HAS_BRIGHTNESS; + rainbow.color_mode = MODE_COLORS_NONE; + rainbow.brightness_min = STEELSERIES_APEX3_BRIGHTNESS_MIN; + rainbow.brightness_max = controller->GetMaxBrightness(); + rainbow.brightness = rainbow.brightness_max; + modes.push_back(rainbow); + } + + SetupZones(); +} + +RGBController_SteelSeriesApex3::~RGBController_SteelSeriesApex3() +{ + delete controller; +} + +void RGBController_SteelSeriesApex3::DeviceSaveMode() +{ + controller->Save(); +} + +void RGBController_SteelSeriesApex3::SetupZones() +{ + uint8_t led_count = controller->GetLedCount(); + + zone curr_zone; + curr_zone.name = "Keyboard"; + curr_zone.type = ZONE_TYPE_LINEAR; + curr_zone.leds_min = led_count; + curr_zone.leds_max = led_count; + curr_zone.leds_count = led_count; + curr_zone.matrix_map = NULL; + zones.push_back(curr_zone); + + for(size_t i = 0; i < curr_zone.leds_count; i++) + { + led zone_led; + zone_led.name = "LED " + std::to_string(i); + leds.push_back(zone_led); + } + + SetupColors(); +} + +void RGBController_SteelSeriesApex3::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_SteelSeriesApex3::DeviceUpdateLEDs() +{ + controller->SetColor(colors, modes[active_mode].value, modes[active_mode].brightness); +} + +void RGBController_SteelSeriesApex3::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_SteelSeriesApex3::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_SteelSeriesApex3::DeviceUpdateMode() +{ + if(modes[active_mode].color_mode == MODE_FLAG_HAS_PER_LED_COLOR) + { + DeviceUpdateLEDs(); + } + else + { + controller->SetColor(modes[active_mode].colors, modes[active_mode].value, modes[active_mode].brightness); + } +} diff --git a/Controllers/SteelSeriesController/SteelSeriesApex3Controller/RGBController_SteelSeriesApex3.h b/Controllers/SteelSeriesController/SteelSeriesApex3Controller/RGBController_SteelSeriesApex3.h new file mode 100644 index 00000000..832c4911 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesApex3Controller/RGBController_SteelSeriesApex3.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesApex3.h | +| | +| RGBController for SteelSeries Apex 3 | +| | +| Chris M (Dr_No) 23 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SteelSeriesApex3Controller.h" + +enum class APEX3_MODES +{ + DIRECT = 0, + RAINBOW_WAVE = 1 +}; + +class RGBController_SteelSeriesApex3 : public RGBController +{ +public: + RGBController_SteelSeriesApex3(SteelSeriesApex3Controller* controller_ptr); + ~RGBController_SteelSeriesApex3(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + SteelSeriesApex3Controller* controller; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesApex3Controller/SteelSeriesApex3Controller.cpp b/Controllers/SteelSeriesController/SteelSeriesApex3Controller/SteelSeriesApex3Controller.cpp new file mode 100644 index 00000000..9a70de8f --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesApex3Controller/SteelSeriesApex3Controller.cpp @@ -0,0 +1,49 @@ +/*---------------------------------------------------------*\ +| SteelSeriesApex3Controller.cpp | +| | +| Driver for SteelSeries Apex 3 | +| | +| Chris M (Dr_No) 23 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "SteelSeriesApex3Controller.h" +#include "StringUtils.h" + +SteelSeriesApex3Controller::SteelSeriesApex3Controller(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; +} + +SteelSeriesApex3Controller::~SteelSeriesApex3Controller() +{ + hid_close(dev); +} + +std::string SteelSeriesApex3Controller::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string SteelSeriesApex3Controller::GetNameString() +{ + return(name); +} + +std::string SteelSeriesApex3Controller::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} diff --git a/Controllers/SteelSeriesController/SteelSeriesApex3Controller/SteelSeriesApex3Controller.h b/Controllers/SteelSeriesController/SteelSeriesApex3Controller/SteelSeriesApex3Controller.h new file mode 100644 index 00000000..ab49112c --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesApex3Controller/SteelSeriesApex3Controller.h @@ -0,0 +1,45 @@ +/*---------------------------------------------------------*\ +| SteelSeriesApex3Controller.h | +| | +| Driver for SteelSeries Apex 3 | +| | +| Chris M (Dr_No) 23 Feb 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" +#include "SteelSeriesGeneric.h" + +#define STEELSERIES_APEX3_BRIGHTNESS_MIN 0x00 +#define STEELSERIES_APEX3_HID_TIMEOUT 100 + +class SteelSeriesApex3Controller +{ +public: + SteelSeriesApex3Controller(hid_device* dev_handle, const char* path, std::string dev_name); + virtual ~SteelSeriesApex3Controller(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + steelseries_type GetKeyboardType(); + + virtual void SetColor(std::vector colors, uint8_t mode, uint8_t brightness) = 0; + virtual void Save() = 0; + virtual uint8_t GetLedCount() = 0; + virtual uint8_t GetMaxBrightness() = 0; + virtual bool SupportsRainbowWave() = 0; + virtual bool SupportsSave() = 0; + + hid_device* dev; + +private: + std::string location; + std::string name; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesApex8ZoneController.cpp b/Controllers/SteelSeriesController/SteelSeriesApex8ZoneController.cpp deleted file mode 100644 index ba25bfa9..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesApex8ZoneController.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/*-------------------------------------------------------------------*\ -| SteelSeriesApex8ZoneController.cpp | -| | -| Driver for Steelseries Apex3 TKL 8 Zone Keyboard | -| | -| Chris M (Dr_No) 23rd Feb 2022 | -| Paul K. Gerke 27.10.2022 | -\*-------------------------------------------------------------------*/ - -#include "LogManager.h" - -#include -#include "SteelSeriesApex8ZoneController.h" - -SteelSeriesApex8ZoneController::SteelSeriesApex8ZoneController(hid_device* dev_handle, const char* path) : SteelSeriesApex3Controller(dev_handle, path) -{ - -} - -SteelSeriesApex8ZoneController::~SteelSeriesApex8ZoneController() -{ - -} - -uint8_t SteelSeriesApex8ZoneController::GetLedCount() -{ - return STEELSERIES_8Z_LED_COUNT; -} - -uint8_t SteelSeriesApex8ZoneController::GetMaxBrightness() -{ - return STEELSERIES_8Z_BRIGHTNESS_MAX; -} - -bool SteelSeriesApex8ZoneController::SupportsRainbowWave() -{ - return true; -} - -bool SteelSeriesApex8ZoneController::SupportsSave() -{ - return false; -} - -void SteelSeriesApex8ZoneController::Save() -{ - /*---------------------------------------------------------*\ - | This device does not yet support saving | - \*---------------------------------------------------------*/ -} - -void SteelSeriesApex8ZoneController::SetBrightness(uint8_t brightness) -{ - uint8_t buffer[STEELSERIES_8Z_WRITE_PACKET_SIZE] = { 0x00, 0x23, brightness }; - - hid_write(dev, buffer, STEELSERIES_8Z_WRITE_PACKET_SIZE); -} - -uint8_t SteelSeriesApex8ZoneController::GetBrightness() -{ - uint8_t buffer[STEELSERIES_8Z_WRITE_PACKET_SIZE] = { 0x00, 0xA3 }; - - hid_write(dev, buffer, STEELSERIES_8Z_WRITE_PACKET_SIZE); - - int result = hid_read_timeout(dev, buffer, STEELSERIES_8Z_WRITE_PACKET_SIZE, STEELSERIES_APEX3_HID_TIMEOUT); - if (result > 1 && buffer[0x00] == 0xA3) - { - return(buffer[0x01]); - } - - return(STEELSERIES_8Z_BRIGHTNESS_MAX); -} - -void SteelSeriesApex8ZoneController::SetColor(std::vector colors, uint8_t mode, uint8_t brightness) -{ - uint8_t buffer[STEELSERIES_8Z_WRITE_PACKET_SIZE] = { 0x00, 0x21, 0xFF }; - - buffer[1] += mode; - - for(unsigned int i = 0; i < colors.size(); i++) - { - uint8_t index = i * 3; - - buffer[index + 3] = RGBGetRValue(colors[i]);; - buffer[index + 4] = RGBGetGValue(colors[i]);; - buffer[index + 5] = RGBGetBValue(colors[i]);; - } - - hid_write(dev, buffer, STEELSERIES_8Z_WRITE_PACKET_SIZE); - - if(current_brightness != brightness) - { - SetBrightness(brightness); - } -} diff --git a/Controllers/SteelSeriesController/SteelSeriesApex8ZoneController/SteelSeriesApex8ZoneController.cpp b/Controllers/SteelSeriesController/SteelSeriesApex8ZoneController/SteelSeriesApex8ZoneController.cpp new file mode 100644 index 00000000..a4dfa285 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesApex8ZoneController/SteelSeriesApex8ZoneController.cpp @@ -0,0 +1,99 @@ +/*---------------------------------------------------------*\ +| SteelSeriesApex8ZoneController.cpp | +| | +| Driver for SteelSeries Apex 8 Zone | +| | +| Chris M (Dr_No) 23 Feb 2022 | +| Paul K. Gerke 27 Oct 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "SteelSeriesApex8ZoneController.h" +#include "LogManager.h" + +SteelSeriesApex8ZoneController::SteelSeriesApex8ZoneController(hid_device* dev_handle, const char* path, std::string dev_name) : SteelSeriesApex3Controller(dev_handle, path, dev_name) +{ + +} + +SteelSeriesApex8ZoneController::~SteelSeriesApex8ZoneController() +{ + +} + +uint8_t SteelSeriesApex8ZoneController::GetLedCount() +{ + return STEELSERIES_8Z_LED_COUNT; +} + +uint8_t SteelSeriesApex8ZoneController::GetMaxBrightness() +{ + return STEELSERIES_8Z_BRIGHTNESS_MAX; +} + +bool SteelSeriesApex8ZoneController::SupportsRainbowWave() +{ + return true; +} + +bool SteelSeriesApex8ZoneController::SupportsSave() +{ + return false; +} + +void SteelSeriesApex8ZoneController::Save() +{ + /*---------------------------------------------------------*\ + | This device does not yet support saving | + \*---------------------------------------------------------*/ +} + +void SteelSeriesApex8ZoneController::SetBrightness(uint8_t brightness) +{ + uint8_t buffer[STEELSERIES_8Z_WRITE_PACKET_SIZE] = { 0x00, 0x23, brightness }; + + hid_write(dev, buffer, STEELSERIES_8Z_WRITE_PACKET_SIZE); + + current_brightness = brightness; +} + +uint8_t SteelSeriesApex8ZoneController::GetBrightness() +{ + uint8_t buffer[STEELSERIES_8Z_WRITE_PACKET_SIZE] = { 0x00, 0xA3 }; + + hid_write(dev, buffer, STEELSERIES_8Z_WRITE_PACKET_SIZE); + + int result = hid_read_timeout(dev, buffer, STEELSERIES_8Z_WRITE_PACKET_SIZE, STEELSERIES_APEX3_HID_TIMEOUT); + if (result > 1 && buffer[0x00] == 0xA3) + { + return(buffer[0x01]); + } + + return(STEELSERIES_8Z_BRIGHTNESS_MAX); +} + +void SteelSeriesApex8ZoneController::SetColor(std::vector colors, uint8_t mode, uint8_t brightness) +{ + uint8_t buffer[STEELSERIES_8Z_WRITE_PACKET_SIZE] = { 0x00, 0x21, 0xFF }; + + buffer[1] += mode; + + for(unsigned int i = 0; i < colors.size(); i++) + { + uint8_t index = i * 3; + + buffer[index + 3] = RGBGetRValue(colors[i]);; + buffer[index + 4] = RGBGetGValue(colors[i]);; + buffer[index + 5] = RGBGetBValue(colors[i]);; + } + + hid_write(dev, buffer, STEELSERIES_8Z_WRITE_PACKET_SIZE); + + if(current_brightness != brightness) + { + SetBrightness(brightness); + } +} diff --git a/Controllers/SteelSeriesController/SteelSeriesApex8ZoneController.h b/Controllers/SteelSeriesController/SteelSeriesApex8ZoneController/SteelSeriesApex8ZoneController.h similarity index 81% rename from Controllers/SteelSeriesController/SteelSeriesApex8ZoneController.h rename to Controllers/SteelSeriesController/SteelSeriesApex8ZoneController/SteelSeriesApex8ZoneController.h index f8e32904..8cf7bd3a 100644 --- a/Controllers/SteelSeriesController/SteelSeriesApex8ZoneController.h +++ b/Controllers/SteelSeriesController/SteelSeriesApex8ZoneController/SteelSeriesApex8ZoneController.h @@ -1,21 +1,23 @@ -/*-------------------------------------------------------------------*\ -| SteelSeriesApex8ZoneController.cpp | -| | -| Driver for Steelseries Apex3 TKL 8 Zone Keyboard | -| | -| Chris M (Dr_No) 23rd Feb 2022 | -| Paul K. Gerke 27.10.2022 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| SteelSeriesApex8ZoneController.h | +| | +| Driver for SteelSeries Apex 8 Zone | +| | +| Chris M (Dr_No) 23 Feb 2022 | +| Paul K. Gerke 27 Oct 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include -#include - +#include #include "RGBController.h" #include "SteelSeriesGeneric.h" #include "SteelSeriesApex3Controller.h" -#pragma once - #define STEELSERIES_8Z_LED_COUNT 8 #define STEELSERIES_8Z_WRITE_PACKET_SIZE 65 #define STEELSERIES_8Z_BRIGHTNESS_MAX 0x10 @@ -23,7 +25,7 @@ class SteelSeriesApex8ZoneController : public SteelSeriesApex3Controller { public: - SteelSeriesApex8ZoneController(hid_device *dev_handle, const char *path); + SteelSeriesApex8ZoneController(hid_device *dev_handle, const char *path, std::string dev_name); ~SteelSeriesApex8ZoneController(); void SetColor(std::vector colors, uint8_t mode, uint8_t brightness); diff --git a/Controllers/SteelSeriesController/SteelSeriesApexBaseController.cpp b/Controllers/SteelSeriesController/SteelSeriesApexBaseController.cpp new file mode 100644 index 00000000..ea68962d --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesApexBaseController.cpp @@ -0,0 +1,148 @@ +/*---------------------------------------------------------*\ +| SteelSeriesApexBaseController.cpp | +| | +| Driver base for SteelSeries Apex | +| | +| Florian Heilmann (FHeilmann) 19 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "SteelSeriesApexBaseController.h" + +SteelSeriesApexBaseController::SteelSeriesApexBaseController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; +} + +SteelSeriesApexBaseController::~SteelSeriesApexBaseController() +{ + +} + +std::string SteelSeriesApexBaseController::GetLocation() +{ + return("HID: " + location); +}; + +std::string SteelSeriesApexBaseController::GetName() +{ + return(name); +} + +/*---------------------------------------------------------*\ +| The serial number of the keyboard is acquired by sending | +| an output report to address 0xFF and reading the result. | +| The HID capability table is not used. The serial number | +| also contains the model number which can be used to | +| determine the physical layout of different region | +| keyboards throughout the product stack. | +\*---------------------------------------------------------*/ +std::string SteelSeriesApexBaseController::GetSerial() +{ + std::string return_string = ""; + if(proto_type == APEX) + { + unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE]; + unsigned char ibuf[STEELSERIES_PACKET_IN_SIZE]; + int result; + + memset(obuf, 0x00, sizeof(obuf)); + obuf[0x00] = 0; + obuf[0x01] = 0xFF; + hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE); + + result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 2); + + /*-------------------------------------------------*\ + | Only the first 19 bytes are of value | + \*-------------------------------------------------*/ + if(result > 0) + { + std::string serialnum(ibuf, ibuf+19); + return_string = serialnum; + } + } + + return(return_string); +} + +std::string SteelSeriesApexBaseController::GetVersion() +{ + std::string return_string = "Unsupported protocol"; + + if(proto_type == APEX) + { + /*-------------------------------------------------*\ + | For the Apex Pro there are two firmware versions | + | which can be acquired, KBD and LED. We know | + | where both are located, we do not know which is | + | what. For now we'll make an assumption and fix | + | if proven wrong. | + \*-------------------------------------------------*/ + unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE]; + unsigned char ibuf[STEELSERIES_PACKET_IN_SIZE]; + int result; + + memset(obuf, 0x00, sizeof(obuf)); + obuf[0x00] = 0; + obuf[0x01] = 0x90; + hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE); + result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 2); + + if(result > 0) + { + std::string fwver(ibuf, ibuf+STEELSERIES_PACKET_IN_SIZE); + fwver = fwver.c_str(); + + /*---------------------------------------------*\ + | Find 2 periods in string, if found we can | + | form a X.Y.Z revision. | + \*---------------------------------------------*/ + std::size_t majorp = fwver.find('.'); + if(majorp != std::string::npos) + { + std::size_t minorp = fwver.find('.', majorp+1); + if(minorp != std::string::npos) + { + std::string major = fwver.substr(0, majorp); + std::string minor = fwver.substr(majorp+1, (minorp-majorp-1)); + std::string build = fwver.substr(minorp+1); + return_string = "KBD: " + major + "." + minor + "." + build; + } + } + } + + /*-------------------------------------------------*\ + | Clear and reuse buffer | + \*-------------------------------------------------*/ + memset(ibuf, 0x00, sizeof(ibuf)); + obuf[0x02] = 0x01; + hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE); + result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 10); + + if(result > 0) + { + std::string fwver(ibuf, ibuf+STEELSERIES_PACKET_IN_SIZE); + fwver = fwver.c_str(); + + std::size_t majorp = fwver.find('.'); + if(majorp != std::string::npos) + { + std::size_t minorp = fwver.find('.', majorp+1); + if(minorp != std::string::npos) + { + std::string major = fwver.substr(0, majorp); + std::string minor = fwver.substr(majorp+1, (minorp-majorp-1)); + std::string build = fwver.substr(minorp+1); + return_string = return_string + " / LED: " + major + "." + minor + "." + build; + } + } + } + } + + return(return_string); +} diff --git a/Controllers/SteelSeriesController/SteelSeriesApexBaseController.h b/Controllers/SteelSeriesController/SteelSeriesApexBaseController.h index c72b6122..adce58a7 100644 --- a/Controllers/SteelSeriesController/SteelSeriesApexBaseController.h +++ b/Controllers/SteelSeriesController/SteelSeriesApexBaseController.h @@ -1,168 +1,44 @@ -/*-----------------------------------------*\ -| SteelSeriesApexBaseController.h | -| | -| Base controller for SteelSeries Apex | -| Keyboard lighting controllers | -| | -| Florian Heilmann (FHeilmann) 19/10/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include "SteelSeriesGeneric.h" - -#include -#include +/*---------------------------------------------------------*\ +| SteelSeriesApexBaseController.h | +| | +| Driver base for SteelSeries Apex | +| | +| Florian Heilmann (FHeilmann) 19 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#define STEELSERIES_PACKET_IN_SIZE 64 +#include +#include +#include "RGBController.h" +#include "SteelSeriesGeneric.h" + +#define STEELSERIES_PACKET_IN_SIZE 64 #define STEELSERIES_PACKET_OUT_SIZE STEELSERIES_PACKET_IN_SIZE + 1 class SteelSeriesApexBaseController { public: + SteelSeriesApexBaseController(hid_device* dev_handle, const char* path, std::string dev_name); + virtual ~SteelSeriesApexBaseController(); - virtual ~SteelSeriesApexBaseController() - { + std::string GetLocation(); + std::string GetName(); + std::string GetSerial(); + std::string GetVersion(); - } + virtual void SetMode(unsigned char mode, std::vector colors) = 0; - std::string GetDeviceLocation() - { - return("HID: " + location); - }; + virtual void SetLEDsDirect(std::vector colors) = 0; - steelseries_type proto_type; - - /*----------------------------------------*\ - | The serial number of the keyboard is | - | acquired by sending an output report | - | to address 0xFF and reading the result. | - | The HID capability table is not used. | - | The serial number also contains the model| - | number which can be used to determine | - | the physical layout of different region | - | keyboards throughout the product stack. | - \*----------------------------------------*/ - - std::string GetSerialString() - { - std::string return_string = ""; - if(proto_type == APEX) - { - unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE]; - unsigned char ibuf[STEELSERIES_PACKET_IN_SIZE]; - int result; - - memset(obuf, 0x00, sizeof(obuf)); - obuf[0x00] = 0; - obuf[0x01] = 0xFF; - hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE); - - result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 2); - - /*---------------------------------------*\ - | Only the first 19 bytes are of value | - \*---------------------------------------*/ - if( result > 0) - { - std::string serialnum(ibuf, ibuf+19); - return_string = serialnum; - } - } - - return(return_string); - } - - std::string GetVersionString() - { - - std::string return_string = "Unsupported protocol"; - - if(proto_type == APEX) - { - /*--------------------------------------------*\ - | For the Apex Pro there are two firmware | - | versions which can be acquired, KBD and LED. | - | We know where both are located, we do not | - | know which is what. For now we'll make an | - | assumption and fix if proven wrong. | - \*--------------------------------------------*/ - - unsigned char obuf[STEELSERIES_PACKET_OUT_SIZE]; - unsigned char ibuf[STEELSERIES_PACKET_IN_SIZE]; - int result; - - memset(obuf, 0x00, sizeof(obuf)); - obuf[0x00] = 0; - obuf[0x01] = 0x90; - hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE); - result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 2); - - if(result > 0) - { - std::string fwver(ibuf, ibuf+STEELSERIES_PACKET_IN_SIZE); - fwver = fwver.c_str(); - - /*---------------------------------------*\ - | Find 2 periods in string, if found we | - | can form a X.Y.Z revision. | - \*---------------------------------------*/ - - std::size_t majorp = fwver.find('.'); - if(majorp != std::string::npos) - { - std::size_t minorp = fwver.find('.', majorp+1); - if(minorp != std::string::npos) - { - std::string major = fwver.substr(0, majorp); - std::string minor = fwver.substr(majorp+1, (minorp-majorp-1)); - std::string build = fwver.substr(minorp+1); - return_string = "KBD: " + major + "." + minor + "." + build; - } - } - } - - /*---------------------------------------*\ - | Clear and reuse buffer | - \*---------------------------------------*/ - memset(ibuf, 0x00, sizeof(ibuf)); - obuf[0x02] = 0x01; - hid_write(dev, obuf, STEELSERIES_PACKET_OUT_SIZE); - result = hid_read_timeout(dev, ibuf, STEELSERIES_PACKET_IN_SIZE, 10); - - if(result > 0) - { - std::string fwver(ibuf, ibuf+STEELSERIES_PACKET_IN_SIZE); - fwver = fwver.c_str(); - - std::size_t majorp = fwver.find('.'); - if(majorp != std::string::npos) - { - std::size_t minorp = fwver.find('.', majorp+1); - if(minorp != std::string::npos) - { - std::string major = fwver.substr(0, majorp); - std::string minor = fwver.substr(majorp+1, (minorp-majorp-1)); - std::string build = fwver.substr(minorp+1); - return_string = return_string + " / LED: " + major + "." + minor + "." + build; - } - } - } - } - return(return_string); - } - - virtual void SetMode - ( - unsigned char mode, - std::vector colors - ) = 0; - - virtual void SetLEDsDirect(std::vector colors) = 0; + steelseries_type proto_type; protected: - std::string location; - hid_device* dev; - unsigned char active_mode; + hid_device* dev; + unsigned char active_mode; + std::string location; + std::string name; }; diff --git a/Controllers/SteelSeriesController/SteelSeriesApexController.h b/Controllers/SteelSeriesController/SteelSeriesApexController.h deleted file mode 100644 index 0f8bb606..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesApexController.h +++ /dev/null @@ -1,44 +0,0 @@ -/*-----------------------------------------*\ -| SteelSeriesApexController.h | -| | -| Definitions and types for SteelSeries | -| Apex 7 Keyboard lighting controller | -| | -| Eric Samuelson (edbgon) 7/5/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include "SteelSeriesGeneric.h" -#include "SteelSeriesApexBaseController.h" - -#include -#include - -#pragma once - -enum -{ - APEX_PACKET_ID_DIRECT = 0x3a, /* Direct mode */ -}; - -class SteelSeriesApexController : public SteelSeriesApexBaseController -{ -public: - SteelSeriesApexController(hid_device* dev_handle, steelseries_type type, const char* path); - ~SteelSeriesApexController(); - - void SetMode - ( - unsigned char mode, - std::vector colors - ); - - void SetLEDsDirect(std::vector colors); - -private: - - void SelectProfile - ( - unsigned char profile - ); -}; diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesApex.cpp b/Controllers/SteelSeriesController/SteelSeriesApexController/RGBController_SteelSeriesApex.cpp similarity index 75% rename from Controllers/SteelSeriesController/RGBController_SteelSeriesApex.cpp rename to Controllers/SteelSeriesController/SteelSeriesApexController/RGBController_SteelSeriesApex.cpp index 108d2b89..a6079015 100644 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesApex.cpp +++ b/Controllers/SteelSeriesController/SteelSeriesApexController/RGBController_SteelSeriesApex.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_SteelSeriesApex.cpp | -| | -| Generic RGB Interface for SteelSeries | -| Apex 7 Keyboard | -| | -| Eric Samuelson (edbgon) 7/5/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesApex.cpp | +| | +| RGBController for SteelSeries Apex 7 | +| | +| Eric Samuelson (edbgon) 05 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_SteelSeriesApex.h" @@ -39,23 +41,23 @@ static const unsigned int zone_sizes[] = RGBController_SteelSeriesApex::RGBController_SteelSeriesApex(SteelSeriesApexBaseController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "SteelSeries Apex RGB Keyboard"; - vendor = "SteelSeries"; - type = DEVICE_TYPE_KEYBOARD; - description = "SteelSeries Apex RGB Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - version = controller->GetVersionString(); + name = controller->GetName(); + vendor = "SteelSeries"; + type = DEVICE_TYPE_KEYBOARD; + description = "SteelSeries Apex RGB Device"; + location = controller->GetLocation(); + serial = controller->GetSerial(); + version = controller->GetVersion(); - proto_type = controller->proto_type; + proto_type = controller->proto_type; mode Direct; - Direct.name = "Direct"; - Direct.value = 0x00; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = 0x00; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); SetupZones(); diff --git a/Controllers/SteelSeriesController/SteelSeriesApexController/RGBController_SteelSeriesApex.h b/Controllers/SteelSeriesController/SteelSeriesApexController/RGBController_SteelSeriesApex.h new file mode 100644 index 00000000..362ecc90 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesApexController/RGBController_SteelSeriesApex.h @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesApex.h | +| | +| RGBController for SteelSeries Apex 7 | +| | +| Eric Samuelson (edbgon) 05 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "SteelSeriesApexBaseController.h" +#include "SteelSeriesGeneric.h" + +class RGBController_SteelSeriesApex : public RGBController +{ +public: + RGBController_SteelSeriesApex(SteelSeriesApexBaseController* controller_ptr); + ~RGBController_SteelSeriesApex(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + SteelSeriesApexBaseController* controller; + steelseries_type proto_type; + + std::chrono::time_point last_update_time; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesApexController.cpp b/Controllers/SteelSeriesController/SteelSeriesApexController/SteelSeriesApexController.cpp similarity index 82% rename from Controllers/SteelSeriesController/SteelSeriesApexController.cpp rename to Controllers/SteelSeriesController/SteelSeriesApexController/SteelSeriesApexController.cpp index 463d4826..d7f1d1d9 100644 --- a/Controllers/SteelSeriesController/SteelSeriesApexController.cpp +++ b/Controllers/SteelSeriesController/SteelSeriesApexController/SteelSeriesApexController.cpp @@ -1,15 +1,16 @@ -/*-----------------------------------------*\ -| SteelSeriesApexController.cpp | -| | -| Driver for SteelSeries Apex 7 RGB | -| Keyboard lighting controller | -| | -| Eric Samuelson (edbgon) 7/5/2020 | -\*-----------------------------------------*/ - -#include "SteelSeriesApexController.h" +/*---------------------------------------------------------*\ +| SteelSeriesApexController.cpp | +| | +| Driver for SteelSeries Apex 7 | +| | +| Eric Samuelson (edbgon) 05 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "SteelSeriesApexController.h" using namespace std::chrono_literals; @@ -26,10 +27,8 @@ static unsigned int keys[] = {0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63 }; -SteelSeriesApexController::SteelSeriesApexController(hid_device* dev_handle, steelseries_type type, const char* path) +SteelSeriesApexController::SteelSeriesApexController(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name) : SteelSeriesApexBaseController(dev_handle, path, dev_name) { - dev = dev_handle; - location = path; proto_type = type; } diff --git a/Controllers/SteelSeriesController/SteelSeriesApexController/SteelSeriesApexController.h b/Controllers/SteelSeriesController/SteelSeriesApexController/SteelSeriesApexController.h new file mode 100644 index 00000000..440cecdf --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesApexController/SteelSeriesApexController.h @@ -0,0 +1,45 @@ +/*---------------------------------------------------------*\ +| SteelSeriesApexController.h | +| | +| Driver for SteelSeries Apex 7 | +| | +| Eric Samuelson (edbgon) 05 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" +#include "SteelSeriesGeneric.h" +#include "SteelSeriesApexBaseController.h" + +enum +{ + APEX_PACKET_ID_DIRECT = 0x3a, /* Direct mode */ +}; + +class SteelSeriesApexController : public SteelSeriesApexBaseController +{ +public: + SteelSeriesApexController(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name); + ~SteelSeriesApexController(); + + void SetMode + ( + unsigned char mode, + std::vector colors + ); + + void SetLEDsDirect(std::vector colors); + +private: + + void SelectProfile + ( + unsigned char profile + ); +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesApexMController.h b/Controllers/SteelSeriesController/SteelSeriesApexMController.h deleted file mode 100644 index 77b3ea6b..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesApexMController.h +++ /dev/null @@ -1,40 +0,0 @@ -/*-----------------------------------------*\ -| SteelSeriesApexMController.h | -| | -| Definitions and types for SteelSeries | -| Apex M750 Keyboard lighting controller | -| | -| Florian Heilmann (FHeilmann) 12/10/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include "SteelSeriesGeneric.h" -#include "SteelSeriesApexBaseController.h" - -#include -#include - -#pragma once - -class SteelSeriesApexMController : public SteelSeriesApexBaseController -{ -public: - SteelSeriesApexMController(hid_device* dev_handle, steelseries_type type, const char* path); - ~SteelSeriesApexMController(); - - void SetMode - ( - unsigned char mode, - std::vector colors - ); - - void SetLEDsDirect(std::vector colors); - -private: - - void EnableLEDControl(); - void SelectProfile - ( - unsigned char profile - ); -}; diff --git a/Controllers/SteelSeriesController/SteelSeriesApexMController.cpp b/Controllers/SteelSeriesController/SteelSeriesApexMController/SteelSeriesApexMController.cpp similarity index 85% rename from Controllers/SteelSeriesController/SteelSeriesApexMController.cpp rename to Controllers/SteelSeriesController/SteelSeriesApexMController/SteelSeriesApexMController.cpp index 4f89db40..23942ca7 100644 --- a/Controllers/SteelSeriesController/SteelSeriesApexMController.cpp +++ b/Controllers/SteelSeriesController/SteelSeriesApexMController/SteelSeriesApexMController.cpp @@ -1,18 +1,20 @@ -/*-----------------------------------------*\ -| SteelSeriesApexMController.cpp | -| | -| Definitions and types for SteelSeries | -| Apex M750 Keyboard lighting controller | -| | -| Florian Heilmann (FHeilmann) 12/10/2020 | -\*-----------------------------------------*/ - -#include "SteelSeriesApexMController.h" +/*---------------------------------------------------------*\ +| SteelSeriesApexMController.cpp | +| | +| Driver for SteelSeries Apex M750 | +| | +| Florian Heilmann (FHeilmann) 12 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "SteelSeriesApexMController.h" #define SS_APEX_M_PACKET_SIZE 513 #define NA 0xFF + static unsigned int keys_m[] = { /* LCTRL LWIN LALT XXX SPACE XXX XXX XXX XXX RALT RWIN FNC RCTRL XXX XXX LEFT DOWN RIGHT XXX #0 XXX #. */ @@ -34,10 +36,8 @@ static unsigned int keys_m[] = 37, 53, 54, 55, 56, NA, 57, 58, 59, 60, NA, 61, 62, 63, 64, 65, 66, 67, NA, NA, NA, NA }; -SteelSeriesApexMController::SteelSeriesApexMController(hid_device* dev_handle, steelseries_type type, const char* path) +SteelSeriesApexMController::SteelSeriesApexMController(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name) : SteelSeriesApexBaseController(dev_handle, path, dev_name) { - dev = dev_handle; - location = path; proto_type = type; EnableLEDControl(); } diff --git a/Controllers/SteelSeriesController/SteelSeriesApexMController/SteelSeriesApexMController.h b/Controllers/SteelSeriesController/SteelSeriesApexMController/SteelSeriesApexMController.h new file mode 100644 index 00000000..8e4c4a49 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesApexMController/SteelSeriesApexMController.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------*\ +| SteelSeriesApexMController.cpp | +| | +| Driver for SteelSeries Apex M750 | +| | +| Florian Heilmann (FHeilmann) 12 Oct 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" +#include "SteelSeriesGeneric.h" +#include "SteelSeriesApexBaseController.h" + +class SteelSeriesApexMController : public SteelSeriesApexBaseController +{ +public: + SteelSeriesApexMController(hid_device* dev_handle, steelseries_type type, const char* path, std::string dev_name); + ~SteelSeriesApexMController(); + + void SetMode + ( + unsigned char mode, + std::vector colors + ); + + void SetLEDsDirect(std::vector colors); + +private: + void EnableLEDControl(); + void SelectProfile + ( + unsigned char profile + ); +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesApexRegions.h b/Controllers/SteelSeriesController/SteelSeriesApexRegions.h index 336851cc..b2fddc30 100644 --- a/Controllers/SteelSeriesController/SteelSeriesApexRegions.h +++ b/Controllers/SteelSeriesController/SteelSeriesApexRegions.h @@ -1,22 +1,24 @@ -/*-----------------------------------------*\ -| SteelSeriesApexRegions.h | -| | -| Region specific SKU settings for the | -| Apex 5/7/Pro and TKL keyboards | -| | -| Joseph East (dripsnek) 2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| SteelSeriesApexRegions.h | +| | +| Region settings for SteelSeries Apex 5/7/Pro and TKL | +| | +| Joseph East (dripsnek) 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#define NA 0xFFFFFFFF - -#include #include +#include #include #include "RGBController_SteelSeriesApex.h" #include "RGBControllerKeyNames.h" +#define NA 0xFFFFFFFF + /*----------------------------------------------------------------------*\ | As of firmware 4.1.0 there are in total 111 possible standard keys | | which are shared across the Apex Pro / 7 / TKL / 5 and their regional | @@ -288,13 +290,13 @@ static const std::map apex_uk_keyname_lookup = static const std::map apex_nor_keyname_lookup = { {36, KEY_EN_ISO_ENTER}, - {41, KEY_NORD_PLUS}, - {42, KEY_NORD_BACKSLASH}, + {41, KEY_NORD_PLUS_QUESTION}, + {42, KEY_NORD_ACUTE_GRAVE}, {43, KEY_NORD_AAL}, - {44, KEY_NORD_CHEVRON}, + {44, KEY_NORD_DOTS_CARET}, {45, KEY_NORD_QUOTE}, - {46, KEY_NORD_OE}, - {47, KEY_NORD_AE}, + {46, KEY_NORD_A_OE}, + {47, KEY_NORD_O_AE}, {48, KEY_NORD_HALF}, {51, KEY_NORD_HYPHEN}, {78, KEY_NORD_ANGLE_BRACKET}, @@ -313,6 +315,7 @@ static const std::map patch_lookup = { "64739", { apex_tkl_us_region_patch, apex_iso_region_patch, apex_uk_keyname_lookup }}, { "64738", { apex_tkl_us_region_patch, apex_iso_region_patch, apex_nor_keyname_lookup }}, { "64737", { apex_tkl_us_region_patch, apex_jp_region_patch, apex_jp_keyname_lookup }}, + { "64856", { apex_tkl_us_region_patch, apex_iso_region_patch, apex_uk_keyname_lookup }}, { "64734", { apex_tkl_us_region_patch, {}, {} }}, { "64631", { {}, apex_iso_region_patch, apex_nor_keyname_lookup }}, diff --git a/Controllers/SteelSeriesController/SteelSeriesApexTZoneController.cpp b/Controllers/SteelSeriesController/SteelSeriesApexTZoneController.cpp deleted file mode 100644 index 4a0c56c0..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesApexTZoneController.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/*-----------------------------------------*\ -| SteelSeriesApexTZoneController.cpp | -| | -| Edbgon 06.10.21 | -\*-----------------------------------------*/ - -#include "SteelSeriesApexTZoneController.h" -#include - -SteelSeriesApexTZoneController::SteelSeriesApexTZoneController(hid_device* dev_handle, const char* path) : SteelSeriesApex3Controller(dev_handle, path) -{ - -} - -SteelSeriesApexTZoneController::~SteelSeriesApexTZoneController() -{ - -} - -uint8_t SteelSeriesApexTZoneController::GetLedCount() -{ - return STEELSERIES_TZ_LED_COUNT; -} - -uint8_t SteelSeriesApexTZoneController::GetMaxBrightness() -{ - return STEELSERIES_TZ_BRIGHTNESS_MAX; -} - -bool SteelSeriesApexTZoneController::SupportsRainbowWave() -{ - return false; -} - -bool SteelSeriesApexTZoneController::SupportsSave() -{ - return true; -} - -void SteelSeriesApexTZoneController::Save() -{ - unsigned char buf[STEELSERIES_TZ_WRITE_PACKET_SIZE] = { 0x00, 0x06, 0x00, 0x08 }; - - hid_write(dev, buf, STEELSERIES_TZ_WRITE_PACKET_SIZE); - - buf[0x01] = 0x09; - buf[0x03] = 0x00; - hid_write(dev, buf, STEELSERIES_TZ_WRITE_PACKET_SIZE); -} - -void SteelSeriesApexTZoneController::SetColor(std::vector colors, uint8_t /*mode*/, uint8_t brightness) -{ - unsigned char buf[STEELSERIES_TZ_WRITE_PACKET_SIZE] = { 0x00 }; - - /*-----------------------------------------------------*\ - | Zero out buffer, set up packet and send | - \*-----------------------------------------------------*/ - memset(buf, 0x00, STEELSERIES_TZ_WRITE_PACKET_SIZE); - - buf[0x01] = 0x0A; - buf[0x03] = brightness; - hid_write(dev, buf, STEELSERIES_TZ_WRITE_PACKET_SIZE); - - buf[0x01] = 0x0B; - for(size_t i = 0; i < colors.size(); i++) - { - uint8_t index = i * 3; - - buf[index + 3] = RGBGetRValue(colors[i]);; - buf[index + 4] = RGBGetGValue(colors[i]);; - buf[index + 5] = RGBGetBValue(colors[i]);; - } - - hid_write(dev, buf, STEELSERIES_TZ_WRITE_PACKET_SIZE); -} diff --git a/Controllers/SteelSeriesController/SteelSeriesApexTZoneController.h b/Controllers/SteelSeriesController/SteelSeriesApexTZoneController.h deleted file mode 100644 index b27ba3d6..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesApexTZoneController.h +++ /dev/null @@ -1,35 +0,0 @@ -/*-----------------------------------------*\ -| SteelSeriesApexTZoneController.h | -| | -| Edbgon 06.10.21 | -\*-----------------------------------------*/ - -#include -#include - -#include "RGBController.h" -#include "SteelSeriesGeneric.h" -#include "SteelSeriesApex3Controller.h" - -#pragma once - -#define STEELSERIES_TZ_LED_COUNT 10 -#define STEELSERIES_TZ_WRITE_PACKET_SIZE 33 -#define STEELSERIES_TZ_BRIGHTNESS_MAX 0x64 - -class SteelSeriesApexTZoneController : public SteelSeriesApex3Controller -{ -public: - SteelSeriesApexTZoneController(hid_device *dev_handle, const char *path); - ~SteelSeriesApexTZoneController(); - - void SetColor(std::vector colors, uint8_t mode, uint8_t brightness); - void Save(); - uint8_t GetLedCount(); - uint8_t GetMaxBrightness(); - bool SupportsRainbowWave(); - bool SupportsSave(); - -private: - -}; diff --git a/Controllers/SteelSeriesController/SteelSeriesApexTZoneController/SteelSeriesApexTZoneController.cpp b/Controllers/SteelSeriesController/SteelSeriesApexTZoneController/SteelSeriesApexTZoneController.cpp new file mode 100644 index 00000000..4d2b3d3a --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesApexTZoneController/SteelSeriesApexTZoneController.cpp @@ -0,0 +1,80 @@ +/*---------------------------------------------------------*\ +| SteelSeriesApexTZoneController.cpp | +| | +| Driver for SteelSeries Apex T Zone | +| | +| Edbgon 06 Oct 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "SteelSeriesApexTZoneController.h" + +SteelSeriesApexTZoneController::SteelSeriesApexTZoneController(hid_device* dev_handle, const char* path, std::string dev_name) : SteelSeriesApex3Controller(dev_handle, path, dev_name) +{ + +} + +SteelSeriesApexTZoneController::~SteelSeriesApexTZoneController() +{ + +} + +uint8_t SteelSeriesApexTZoneController::GetLedCount() +{ + return STEELSERIES_TZ_LED_COUNT; +} + +uint8_t SteelSeriesApexTZoneController::GetMaxBrightness() +{ + return STEELSERIES_TZ_BRIGHTNESS_MAX; +} + +bool SteelSeriesApexTZoneController::SupportsRainbowWave() +{ + return false; +} + +bool SteelSeriesApexTZoneController::SupportsSave() +{ + return true; +} + +void SteelSeriesApexTZoneController::Save() +{ + unsigned char buf[STEELSERIES_TZ_WRITE_PACKET_SIZE] = { 0x00, 0x06, 0x00, 0x08 }; + + hid_write(dev, buf, STEELSERIES_TZ_WRITE_PACKET_SIZE); + + buf[0x01] = 0x09; + buf[0x03] = 0x00; + hid_write(dev, buf, STEELSERIES_TZ_WRITE_PACKET_SIZE); +} + +void SteelSeriesApexTZoneController::SetColor(std::vector colors, uint8_t /*mode*/, uint8_t brightness) +{ + unsigned char buf[STEELSERIES_TZ_WRITE_PACKET_SIZE] = { 0x00 }; + + /*-----------------------------------------------------*\ + | Zero out buffer, set up packet and send | + \*-----------------------------------------------------*/ + memset(buf, 0x00, STEELSERIES_TZ_WRITE_PACKET_SIZE); + + buf[0x01] = 0x0A; + buf[0x03] = brightness; + hid_write(dev, buf, STEELSERIES_TZ_WRITE_PACKET_SIZE); + + buf[0x01] = 0x0B; + for(size_t i = 0; i < colors.size(); i++) + { + uint8_t index = (uint8_t)(i * 3); + + buf[index + 3] = RGBGetRValue(colors[i]);; + buf[index + 4] = RGBGetGValue(colors[i]);; + buf[index + 5] = RGBGetBValue(colors[i]);; + } + + hid_write(dev, buf, STEELSERIES_TZ_WRITE_PACKET_SIZE); +} diff --git a/Controllers/SteelSeriesController/SteelSeriesApexTZoneController/SteelSeriesApexTZoneController.h b/Controllers/SteelSeriesController/SteelSeriesApexTZoneController/SteelSeriesApexTZoneController.h new file mode 100644 index 00000000..e37966ee --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesApexTZoneController/SteelSeriesApexTZoneController.h @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| SteelSeriesApexTZoneController.h | +| | +| Driver for SteelSeries Apex T Zone | +| | +| Edbgon 06 Oct 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" +#include "SteelSeriesGeneric.h" +#include "SteelSeriesApex3Controller.h" + +#define STEELSERIES_TZ_LED_COUNT 10 +#define STEELSERIES_TZ_WRITE_PACKET_SIZE 33 +#define STEELSERIES_TZ_BRIGHTNESS_MAX 0x64 + +class SteelSeriesApexTZoneController : public SteelSeriesApex3Controller +{ +public: + SteelSeriesApexTZoneController(hid_device *dev_handle, const char *path, std::string dev_name); + ~SteelSeriesApexTZoneController(); + + void SetColor(std::vector colors, uint8_t mode, uint8_t brightness); + void Save(); + uint8_t GetLedCount(); + uint8_t GetMaxBrightness(); + bool SupportsRainbowWave(); + bool SupportsSave(); + +private: + +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesArctis5Controller.cpp b/Controllers/SteelSeriesController/SteelSeriesArctis5Controller.cpp deleted file mode 100644 index 67b64253..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesArctis5Controller.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/*-----------------------------------------*\ -| SteelSeriesArctis5Controller.h | -| | -| Definitions and types for SteelSeries | -| Arctis 5 lighting controller | -| | -| Morgan Guimard 3/4/2022 | -\*-----------------------------------------*/ - -#include "SteelSeriesArctis5Controller.h" -#include - -SteelSeriesArctis5Controller::SteelSeriesArctis5Controller(hid_device* dev_handle, const hid_device_info& info) -{ - dev = dev_handle; - location = info.path; - version = ""; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } -} - -SteelSeriesArctis5Controller::~SteelSeriesArctis5Controller() -{ - hid_close(dev); -} - -std::string SteelSeriesArctis5Controller::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string SteelSeriesArctis5Controller::GetSerialString() -{ - return(serial_number); -} - -std::string SteelSeriesArctis5Controller::GetFirmwareVersion() -{ - return(version); -} - -void SteelSeriesArctis5Controller::SetColor(unsigned char zone_id, RGBColor color) -{ - unsigned char usb_buf[ARCTIS_5_REPORT_SIZE]; - - /*----------------------------------------------*\ - | Two packets are sent before a color change | - \*----------------------------------------------*/ - memset(usb_buf, 0x00, ARCTIS_5_REPORT_SIZE); - - usb_buf[0x00] = ARCTIS_5_REPORT_ID; - usb_buf[0x01] = 0x81; - usb_buf[0x02] = 0x43; - usb_buf[0x03] = 0x01; - usb_buf[0x04] = 0x22; - - hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE); - - usb_buf[0x04] = 0x23; - - hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE); - - /*----------------------------------------------*\ - | First packet: send color | - \*----------------------------------------------*/ - memset(usb_buf, 0x00, ARCTIS_5_REPORT_SIZE); - - usb_buf[0x00] = ARCTIS_5_REPORT_ID; - usb_buf[0x01] = 0x8A; - usb_buf[0x02] = 0x42; - - usb_buf[0x04] = 0x20; - usb_buf[0x05] = 0x41; - - usb_buf[0x07] = RGBGetRValue(color); - usb_buf[0x08] = RGBGetGValue(color); - usb_buf[0x09] = RGBGetBValue(color); - - usb_buf[0x0A] = 0xFF; - usb_buf[0x0B] = 0x32; - usb_buf[0x0C] = 0xC8; - usb_buf[0x0D] = 0xC8; - - hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE); - - /*-----------------------------------------*\ - | Second packet: apply to zone | - \*-----------------------------------------*/ - memset(usb_buf, 0x00, ARCTIS_5_REPORT_SIZE); - - usb_buf[0x00] = ARCTIS_5_REPORT_ID; - usb_buf[0x01] = 0x8A; - usb_buf[0x02] = 0x42; - - usb_buf[0x04] = 0x20; - usb_buf[0x05] = 0x41; - usb_buf[0x06] = 0x08; - usb_buf[0x07] = zone_id; - usb_buf[0x08] = 0x01; - - hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE); - - /*-----------------------------------------*\ - | Thrid packet: apply to zone | - \*-----------------------------------------*/ - memset(usb_buf, 0x00, ARCTIS_5_REPORT_SIZE); - - usb_buf[0x00] = ARCTIS_5_REPORT_ID; - usb_buf[0x01] = 0x8A; - usb_buf[0x02] = 0x42; - - usb_buf[0x04] = 0x20; - usb_buf[0x05] = 0x60; - usb_buf[0x06] = zone_id; - - hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE); - - /*-----------------------------------------*\ - | Last packet: apply | - \*-----------------------------------------*/ - memset(usb_buf, 0x00, ARCTIS_5_REPORT_SIZE); - - usb_buf[0x00] = ARCTIS_5_REPORT_ID; - usb_buf[0x01] = 0x8A; - usb_buf[0x02] = 0x42; - - usb_buf[0x04] = 0x20; - usb_buf[0x05] = 0x05; - - hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE); -} diff --git a/Controllers/SteelSeriesController/SteelSeriesArctis5Controller.h b/Controllers/SteelSeriesController/SteelSeriesArctis5Controller.h deleted file mode 100644 index 6734d0fa..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesArctis5Controller.h +++ /dev/null @@ -1,36 +0,0 @@ -/*-----------------------------------------*\ -| SteelSeriesArctis5Controller.h | -| | -| Definitions and types for SteelSeries | -| Arctis 5 lighting controller | -| | -| Morgan Guimard 3/4/2022 | -\*-----------------------------------------*/ -#pragma once - -#define ARCTIS_5_REPORT_SIZE 37 -#define ARCTIS_5_REPORT_ID 0x06 - -#include "RGBController.h" -#include -#include - -class SteelSeriesArctis5Controller -{ -public: - SteelSeriesArctis5Controller(hid_device* dev_handle, const hid_device_info& info); - - ~SteelSeriesArctis5Controller(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - std::string GetFirmwareVersion(); - void SetColor(unsigned char zone_id, RGBColor color); - -private: - std::string location; - std::string serial_number; - std::string version; - - hid_device* dev; -}; diff --git a/Controllers/SteelSeriesController/SteelSeriesArctis5Controller/RGBController_SteelSeriesArctis5.cpp b/Controllers/SteelSeriesController/SteelSeriesArctis5Controller/RGBController_SteelSeriesArctis5.cpp new file mode 100644 index 00000000..9272e96e --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesArctis5Controller/RGBController_SteelSeriesArctis5.cpp @@ -0,0 +1,106 @@ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesArctis5.cpp | +| | +| RGBController for SteelSeries Arctis 5 | +| | +| Morgan Guimard 04 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_SteelSeriesArctis5.h" + +/**------------------------------------------------------------------*\ + @name Steelseries Arctis 5 + @category Headset + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectSteelSeriesArctis5 + @comment +\*-------------------------------------------------------------------*/ + +RGBController_SteelSeriesArctis5::RGBController_SteelSeriesArctis5(SteelSeriesArctis5Controller* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "SteelSeries"; + type = DEVICE_TYPE_HEADSET; + description = "SteelSeries Arctis 5 Headset Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0x00; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + + modes.push_back(Direct); + + SetupZones(); +} + +RGBController_SteelSeriesArctis5::~RGBController_SteelSeriesArctis5() +{ + delete controller; +} + +void RGBController_SteelSeriesArctis5::SetupZones() +{ + const std::string zone_names[2] = + { + "Left" , "Right" + }; + + for(const std::string& zone_name : zone_names) + { + zone zone; + zone.name = zone_name; + zone.type = ZONE_TYPE_SINGLE; + zone.leds_min = 1; + zone.leds_max = 1; + zone.leds_count = 1; + zone.matrix_map = NULL; + zones.push_back(zone); + + led mouse_led; + mouse_led.name = zone_name; + leds.push_back(mouse_led); + } + + SetupColors(); +} + +void RGBController_SteelSeriesArctis5::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_SteelSeriesArctis5::DeviceUpdateLEDs() +{ + for(unsigned int i = 0; i < zones.size(); i++) + { + UpdateZoneLEDs(i); + } +} + +void RGBController_SteelSeriesArctis5::UpdateZoneLEDs(int zone) +{ + controller->SetColor(zone, colors[zone]); +} + +void RGBController_SteelSeriesArctis5::UpdateSingleLED(int led) +{ + UpdateZoneLEDs(led); +} + +void RGBController_SteelSeriesArctis5::DeviceUpdateMode() +{ + +} diff --git a/Controllers/SteelSeriesController/SteelSeriesArctis5Controller/RGBController_SteelSeriesArctis5.h b/Controllers/SteelSeriesController/SteelSeriesArctis5Controller/RGBController_SteelSeriesArctis5.h new file mode 100644 index 00000000..d7129d89 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesArctis5Controller/RGBController_SteelSeriesArctis5.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesArctis5.h | +| | +| RGBController for SteelSeries Arctis 5 | +| | +| Morgan Guimard 04 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SteelSeriesArctis5Controller.h" + +class RGBController_SteelSeriesArctis5 : public RGBController +{ +public: + RGBController_SteelSeriesArctis5(SteelSeriesArctis5Controller* controller_ptr); + ~RGBController_SteelSeriesArctis5(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + SteelSeriesArctis5Controller* controller; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesArctis5Controller/SteelSeriesArctis5Controller.cpp b/Controllers/SteelSeriesController/SteelSeriesArctis5Controller/SteelSeriesArctis5Controller.cpp new file mode 100644 index 00000000..9e03d86a --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesArctis5Controller/SteelSeriesArctis5Controller.cpp @@ -0,0 +1,140 @@ +/*---------------------------------------------------------*\ +| SteelSeriesArctis5Controller.cpp | +| | +| Driver for SteelSeries Arctis 5 | +| | +| Morgan Guimard 04 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "SteelSeriesArctis5Controller.h" +#include "StringUtils.h" + +SteelSeriesArctis5Controller::SteelSeriesArctis5Controller(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) +{ + dev = dev_handle; + location = info.path; + name = dev_name; +} + +SteelSeriesArctis5Controller::~SteelSeriesArctis5Controller() +{ + hid_close(dev); +} + +std::string SteelSeriesArctis5Controller::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string SteelSeriesArctis5Controller::GetNameString() +{ + return(name); +} + +std::string SteelSeriesArctis5Controller::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void SteelSeriesArctis5Controller::SetColor(unsigned char zone_id, RGBColor color) +{ + unsigned char usb_buf[ARCTIS_5_REPORT_SIZE]; + + /*----------------------------------------------*\ + | Two packets are sent before a color change | + \*----------------------------------------------*/ + memset(usb_buf, 0x00, ARCTIS_5_REPORT_SIZE); + + usb_buf[0x00] = ARCTIS_5_REPORT_ID; + usb_buf[0x01] = 0x81; + usb_buf[0x02] = 0x43; + usb_buf[0x03] = 0x01; + usb_buf[0x04] = 0x22; + + hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE); + + usb_buf[0x04] = 0x23; + + hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE); + + /*----------------------------------------------*\ + | First packet: send color | + \*----------------------------------------------*/ + memset(usb_buf, 0x00, ARCTIS_5_REPORT_SIZE); + + usb_buf[0x00] = ARCTIS_5_REPORT_ID; + usb_buf[0x01] = 0x8A; + usb_buf[0x02] = 0x42; + + usb_buf[0x04] = 0x20; + usb_buf[0x05] = 0x41; + + usb_buf[0x07] = RGBGetRValue(color); + usb_buf[0x08] = RGBGetGValue(color); + usb_buf[0x09] = RGBGetBValue(color); + + usb_buf[0x0A] = 0xFF; + usb_buf[0x0B] = 0x32; + usb_buf[0x0C] = 0xC8; + usb_buf[0x0D] = 0xC8; + + hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE); + + /*-----------------------------------------*\ + | Second packet: apply to zone | + \*-----------------------------------------*/ + memset(usb_buf, 0x00, ARCTIS_5_REPORT_SIZE); + + usb_buf[0x00] = ARCTIS_5_REPORT_ID; + usb_buf[0x01] = 0x8A; + usb_buf[0x02] = 0x42; + + usb_buf[0x04] = 0x20; + usb_buf[0x05] = 0x41; + usb_buf[0x06] = 0x08; + usb_buf[0x07] = zone_id; + usb_buf[0x08] = 0x01; + + hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE); + + /*-----------------------------------------*\ + | Thrid packet: apply to zone | + \*-----------------------------------------*/ + memset(usb_buf, 0x00, ARCTIS_5_REPORT_SIZE); + + usb_buf[0x00] = ARCTIS_5_REPORT_ID; + usb_buf[0x01] = 0x8A; + usb_buf[0x02] = 0x42; + + usb_buf[0x04] = 0x20; + usb_buf[0x05] = 0x60; + usb_buf[0x06] = zone_id; + + hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE); + + /*-----------------------------------------*\ + | Last packet: apply | + \*-----------------------------------------*/ + memset(usb_buf, 0x00, ARCTIS_5_REPORT_SIZE); + + usb_buf[0x00] = ARCTIS_5_REPORT_ID; + usb_buf[0x01] = 0x8A; + usb_buf[0x02] = 0x42; + + usb_buf[0x04] = 0x20; + usb_buf[0x05] = 0x05; + + hid_write(dev, usb_buf, ARCTIS_5_REPORT_SIZE); +} diff --git a/Controllers/SteelSeriesController/SteelSeriesArctis5Controller/SteelSeriesArctis5Controller.h b/Controllers/SteelSeriesController/SteelSeriesArctis5Controller/SteelSeriesArctis5Controller.h new file mode 100644 index 00000000..fe523c5a --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesArctis5Controller/SteelSeriesArctis5Controller.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------*\ +| SteelSeriesArctis5Controller.h | +| | +| Driver for SteelSeries Arctis 5 | +| | +| Morgan Guimard 04 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define ARCTIS_5_REPORT_SIZE 37 +#define ARCTIS_5_REPORT_ID 0x06 + +class SteelSeriesArctis5Controller +{ +public: + SteelSeriesArctis5Controller(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~SteelSeriesArctis5Controller(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SetColor(unsigned char zone_id, RGBColor color); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesControllerDetect.cpp b/Controllers/SteelSeriesController/SteelSeriesControllerDetect.cpp index 84a81bd5..eb78d708 100644 --- a/Controllers/SteelSeriesController/SteelSeriesControllerDetect.cpp +++ b/Controllers/SteelSeriesController/SteelSeriesControllerDetect.cpp @@ -1,358 +1,482 @@ -#include -#include "Detector.h" -#include "RGBController.h" -#include "SteelSeriesGeneric.h" - -#include "SteelSeriesAerox9Controller.h" -#include "SteelSeriesArctis5Controller.h" -#include "SteelSeriesApex8ZoneController.h" -#include "SteelSeriesApexController.h" -#include "SteelSeriesApexMController.h" -#include "SteelSeriesApexTZoneController.h" -#include "SteelSeriesOldApexController.h" -#include "SteelSeriesQCKMatController.h" -#include "SteelSeriesRivalController.h" -#include "SteelSeriesRival3Controller.h" -#include "SteelSeriesSenseiController.h" -#include "SteelSeriesSiberiaController.h" - -#include "RGBController_SteelSeriesArctis5.h" -#include "RGBController_SteelSeriesApex.h" -#include "RGBController_SteelSeriesApex3.h" -#include "RGBController_SteelSeriesOldApex.h" -#include "RGBController_SteelSeriesQCKMat.h" -#include "RGBController_SteelSeriesRival.h" -#include "RGBController_SteelSeriesRival3.h" -#include "RGBController_SteelSeriesSensei.h" -#include "RGBController_SteelSeriesSiberia.h" - -/*-----------------------------------------------------*\ -| Vendor ID | -\*-----------------------------------------------------*/ -#define STEELSERIES_VID 0x1038 -/*-----------------------------------------------------*\ -| Mouse product IDs | -\*-----------------------------------------------------*/ -#define STEELSERIES_AEROX_3_PID 0x1836 -#define STEELSERIES_AEROX_9_PID 0x185A -#define STEELSERIES_RIVAL_100_PID 0x1702 -#define STEELSERIES_RIVAL_100_DOTA_PID 0x170c -#define STEELSERIES_RIVAL_105_PID 0x1814 -#define STEELSERIES_RIVAL_106_PID 0x1816 -#define STEELSERIES_RIVAL_110_PID 0x1729 -#define STEELSERIES_RIVAL_300_PID 0x1710 -#define ACER_PREDATOR_RIVAL_300_PID 0x1714 -#define STEELSERIES_RIVAL_300_CSGO_PID 0x1394 -#define STEELSERIES_RIVAL_300_CSGO_STM32_PID 0x1716 -#define STEELSERIES_RIVAL_300_CSGO_HYPERBEAST_PID 0x171a -#define STEELSERIES_RIVAL_300_DOTA_PID 0x1392 -#define STEELSERIES_RIVAL_300_HP_PID 0x1718 -#define STEELSERIES_RIVAL_300_BLACKOPS_PID 0x1710 -#define STEELSERIES_RIVAL_310_PID 0x1720 -#define STEELSERIES_RIVAL_310_CSGO_HOWL_PID 0x171e -#define STEELSERIES_RIVAL_310_PUBG_PID 0x1736 -#define STEELSERIES_RIVAL_600_PID 0x1724 -#define STEELSERIES_RIVAL_600_DOTA_2_PID 0x172E -#define STEELSERIES_RIVAL_650_PID 0x172B -#define STEELSERIES_RIVAL_650_WIRELESS_PID 0x1726 -#define STEELSERIES_RIVAL_700_PID 0x1700 -#define STEELSERIES_RIVAL_710_PID 0x1730 -#define STEELSERIES_RIVAL_3_OLD_PID 0x1824 -#define STEELSERIES_RIVAL_3_PID 0x184C -#define STEELSERIES_SENSEI_TEN_PID 0x1832 -#define STEELSERIES_SENSEI_TEN_CSGO_NEON_RIDER_PID 0x1834 -#define STEELSERIES_SENSEI_310_PID 0x1722 -/*-----------------------------------------------------*\ -| Headset product IDs | -\*-----------------------------------------------------*/ -#define STEELSERIES_SIBERIA_350_PID 0x1229 -#define STEELSERIES_ARCTIS_5_PID 0x12AA -/*--------------------------------------------------------------*\ -| Mousemat product IDs | -\*--------------------------------------------------------------*/ -#define STEELSERIES_QCK_PRISM_CLOTH_MED_PID 0x150A -#define STEELSERIES_QCK_PRISM_CLOTH_XL_PID 0x150D -#define STEELSERIES_QCK_PRISM_CLOTH_XL_DESTINY_PID 0x151E -#define STEELSERIES_QCK_PRISM_CLOTH_XL_CSGO_NEON_RIDER_PID 0x1514 -#define STEELSERIES_QCK_PRISM_CLOTH_3XL_PID 0x1516 -#define STEELSERIES_QCK_PRISM_CLOTH_4XL_PID 0x1518 -/*-----------------------------------------------------*\ -| Keyboard product IDs | -\*-----------------------------------------------------*/ -#define STEELSERIES_APEX_3_PID 0x161A -#define STEELSERIES_APEX_3_TKL_PID 0x1622 -#define STEELSERIES_APEX_5_PID 0x161C -#define STEELSERIES_APEX_7_PID 0x1612 -#define STEELSERIES_APEX_7_TKL_PID 0x1618 -#define STEELSERIES_APEX_PRO_PID 0x1610 -#define STEELSERIES_APEX_PRO_TKL_PID 0x1614 -#define STEELSERIES_APEX_M750_PID 0x0616 -#define STEELSERIES_APEX_OG_PID 0x1202 -#define STEELSERIES_APEX_350_PID 0x1206 - -void DetectSteelSeriesAerox3(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - if(dev) - { - SteelSeriesAerox3Controller* controller = new SteelSeriesAerox3Controller(dev, AEROX_3, info->path); - RGBController_SteelSeriesRival3* rgb_controller = new RGBController_SteelSeriesRival3(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -void DetectSteelSeriesAerox9(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - if(dev) - { - SteelSeriesAerox9Controller* controller = new SteelSeriesAerox9Controller(dev, AEROX_3, info->path); - RGBController_SteelSeriesRival3* rgb_controller = new RGBController_SteelSeriesRival3(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -void DetectSteelSeriesApex3Full(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - if(dev) - { - SteelSeriesApexTZoneController* controller = new SteelSeriesApexTZoneController(dev, info->path); - RGBController_SteelSeriesApex3* rgb_controller = new RGBController_SteelSeriesApex3(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -void DetectSteelSeriesApex3TKL(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - if(dev) - { - SteelSeriesApex8ZoneController* controller = new SteelSeriesApex8ZoneController(dev, info->path); - RGBController_SteelSeriesApex3* rgb_controller = new RGBController_SteelSeriesApex3(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -void DetectSteelSeriesApex(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - if(dev) - { - SteelSeriesApexController* controller = new SteelSeriesApexController(dev, APEX, info->path); - RGBController_SteelSeriesApex* rgb_controller = new RGBController_SteelSeriesApex(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -void DetectSteelSeriesApexM(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - if(dev) - { - SteelSeriesApexMController* controller = new SteelSeriesApexMController(dev, APEX_M, info->path); - RGBController_SteelSeriesApex* rgb_controller = new RGBController_SteelSeriesApex(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -void DetectSteelSeriesApexOld(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - if(dev) - { - SteelSeriesOldApexController* controller = new SteelSeriesOldApexController(dev, APEX_OLD, info->path); - RGBController_SteelSeriesOldApex* rgb_controller = new RGBController_SteelSeriesOldApex(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -void DetectSteelSeriesHeadset(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - if(dev) - { - SteelSeriesSiberiaController* controller = new SteelSeriesSiberiaController(dev, info->path); - RGBController_SteelSeriesSiberia* rgb_controller = new RGBController_SteelSeriesSiberia(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -void DetectSteelSeriesMousemat(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - if(dev) - { - SteelSeriesQCKMatController* controller = new SteelSeriesQCKMatController(dev, info->path); - RGBController_SteelSeriesQCKMat* rgb_controller = new RGBController_SteelSeriesQCKMat(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -void DetectSteelSeriesRival100(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - if(dev) - { - SteelSeriesRivalController* controller = new SteelSeriesRivalController(dev, RIVAL_100, info->path); - RGBController_SteelSeriesRival* rgb_controller = new RGBController_SteelSeriesRival(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -void DetectSteelSeriesRival300(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - if(dev) - { - SteelSeriesRivalController* controller = new SteelSeriesRivalController(dev, RIVAL_300, info->path); - RGBController_SteelSeriesRival* rgb_controller = new RGBController_SteelSeriesRival(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -void DetectSteelSeriesRival600(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - if(dev) - { - SteelSeriesRivalController* controller = new SteelSeriesRivalController(dev, RIVAL_600, info->path); - RGBController_SteelSeriesRival* rgb_controller = new RGBController_SteelSeriesRival(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - - -void DetectSteelSeriesRival650(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - if(dev) - { - SteelSeriesRivalController* controller = new SteelSeriesRivalController(dev, RIVAL_650, info->path); - RGBController_SteelSeriesRival* rgb_controller = new RGBController_SteelSeriesRival(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -void DetectSteelSeriesRival700(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - if(dev) - { - SteelSeriesRivalController* controller = new SteelSeriesRivalController(dev, RIVAL_700, info->path); - RGBController_SteelSeriesRival* rgb_controller = new RGBController_SteelSeriesRival(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - - -void DetectSteelSeriesRival3(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - if(dev) - { - SteelSeriesRival3Controller* controller = new SteelSeriesRival3Controller(dev, RIVAL_3, info->path); - RGBController_SteelSeriesRival3* rgb_controller = new RGBController_SteelSeriesRival3(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -void DetectSteelSeriesSensei(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - if(dev) - { - SteelSeriesSenseiController* controller = new SteelSeriesSenseiController(dev, SENSEI, info->path); - RGBController_SteelSeriesSensei* rgb_controller = new RGBController_SteelSeriesSensei(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -void DetectSteelSeriesArctis5(hid_device_info* info, const std::string& name) -{ - hid_device* dev = hid_open_path(info->path); - - if(dev) - { - SteelSeriesArctis5Controller* controller = new SteelSeriesArctis5Controller(dev, *info); - RGBController_SteelSeriesArctis5* rgb_controller = new RGBController_SteelSeriesArctis5(controller); - rgb_controller->name = name; - ResourceManager::get()->RegisterRGBController(rgb_controller); - } -} - -/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*\ -| Mice | -\*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ -REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 3 Wired", DetectSteelSeriesAerox3, STEELSERIES_VID, STEELSERIES_AEROX_3_PID, 3, 0xFFC0, 1 ); -REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 9 Wired", DetectSteelSeriesAerox9, STEELSERIES_VID, STEELSERIES_AEROX_9_PID, 3, 0xFFC0, 1 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 100", DetectSteelSeriesRival100, STEELSERIES_VID, STEELSERIES_RIVAL_100_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 100 DotA 2 Edition", DetectSteelSeriesRival100, STEELSERIES_VID, STEELSERIES_RIVAL_100_DOTA_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 105", DetectSteelSeriesRival100, STEELSERIES_VID, STEELSERIES_RIVAL_105_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 106", DetectSteelSeriesRival100, STEELSERIES_VID, STEELSERIES_RIVAL_106_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 110", DetectSteelSeriesRival100, STEELSERIES_VID, STEELSERIES_RIVAL_110_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 300", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_PID, 0 ); -REGISTER_HID_DETECTOR_I("Acer Predator Gaming Mouse (Rival 300)", DetectSteelSeriesRival300, STEELSERIES_VID, ACER_PREDATOR_RIVAL_300_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 CS:GO Fade Edition", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_CSGO_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 CS:GO Fade Edition (stm32)", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_CSGO_STM32_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 CS:GO Hyperbeast Edition", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_CSGO_HYPERBEAST_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 Dota 2 Edition", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_DOTA_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 HP Omen Edition", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_HP_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 Black Ops Edition", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_BLACKOPS_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 310", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_RIVAL_310_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 310 CS:GO Howl Edition", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_RIVAL_310_CSGO_HOWL_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 310 PUBG Edition", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_RIVAL_310_PUBG_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 600", DetectSteelSeriesRival600, STEELSERIES_VID, STEELSERIES_RIVAL_600_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 600 Dota 2 Edition", DetectSteelSeriesRival600, STEELSERIES_VID, STEELSERIES_RIVAL_600_DOTA_2_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 650", DetectSteelSeriesRival650, STEELSERIES_VID, STEELSERIES_RIVAL_650_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 650 Wireless", DetectSteelSeriesRival650, STEELSERIES_VID, STEELSERIES_RIVAL_650_WIRELESS_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 700", DetectSteelSeriesRival700, STEELSERIES_VID, STEELSERIES_RIVAL_700_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 710", DetectSteelSeriesRival700, STEELSERIES_VID, STEELSERIES_RIVAL_710_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 3 (Old Firmware)", DetectSteelSeriesRival3, STEELSERIES_VID, STEELSERIES_RIVAL_3_OLD_PID, 3 ); -REGISTER_HID_DETECTOR_I("SteelSeries Rival 3", DetectSteelSeriesRival3, STEELSERIES_VID, STEELSERIES_RIVAL_3_PID, 3 ); -REGISTER_HID_DETECTOR_I("SteelSeries Sensei TEN", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_SENSEI_TEN_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Sensei TEN CS:GO Neon Rider Edition", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_SENSEI_TEN_CSGO_NEON_RIDER_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries Sensei 310", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_SENSEI_310_PID, 0 ); -/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*\ -| Headsets | -\*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ -REGISTER_HID_DETECTOR_I("SteelSeries Siberia 350", DetectSteelSeriesHeadset, STEELSERIES_VID, STEELSERIES_SIBERIA_350_PID, 3 ); -REGISTER_HID_DETECTOR_I("SteelSeries Arctis 5", DetectSteelSeriesArctis5, STEELSERIES_VID, STEELSERIES_ARCTIS_5_PID, 5 ); -/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*\ -| Mousemats | -\*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ -REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth Medium", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_MED_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth XL", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_XL_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth XL Destiny Ed.", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_XL_DESTINY_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth XL CS:GO Neon Rider Ed.", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_XL_CSGO_NEON_RIDER_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth 3XL", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_3XL_PID, 0 ); -REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth 4XL", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_4XL_PID, 0 ); -/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*\ -| Keyboards | -\*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ -REGISTER_HID_DETECTOR_I ("SteelSeries Apex 3", DetectSteelSeriesApex3Full, STEELSERIES_VID, STEELSERIES_APEX_3_PID, 3 ); -REGISTER_HID_DETECTOR_IPU("SteelSeries Apex 3 TKL", DetectSteelSeriesApex3TKL, STEELSERIES_VID, STEELSERIES_APEX_3_TKL_PID, 1, 0xFFC0, 1 ); -REGISTER_HID_DETECTOR_I ("SteelSeries Apex 5", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_5_PID, 1 ); -REGISTER_HID_DETECTOR_I ("SteelSeries Apex 7", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_7_PID, 1 ); -REGISTER_HID_DETECTOR_I ("SteelSeries Apex 7 TKL", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_7_TKL_PID, 1 ); -REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_PID, 1 ); -REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro TKL", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_PID, 1 ); -REGISTER_HID_DETECTOR_I ("SteelSeries Apex M750", DetectSteelSeriesApexM, STEELSERIES_VID, STEELSERIES_APEX_M750_PID, 2 ); -REGISTER_HID_DETECTOR_I ("SteelSeries Apex (OG)/Apex Fnatic", DetectSteelSeriesApexOld, STEELSERIES_VID, STEELSERIES_APEX_OG_PID, 0 ); -REGISTER_HID_DETECTOR_I ("SteelSeries Apex 350", DetectSteelSeriesApexOld, STEELSERIES_VID, STEELSERIES_APEX_350_PID, 0 ); +/*---------------------------------------------------------*\ +| SteelSeriesControllerDetect.cpp | +| | +| Detector for SteelSeries devices | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "SteelSeriesGeneric.h" +#include "SteelSeriesAeroxWirelessController.h" +#include "SteelSeriesAerox5Controller.h" +#include "SteelSeriesArctis5Controller.h" +#include "SteelSeriesApex8ZoneController.h" +#include "SteelSeriesApexController.h" +#include "SteelSeriesApexMController.h" +#include "SteelSeriesApexTZoneController.h" +#include "SteelSeriesOldApexController.h" +#include "SteelSeriesQCKMatController.h" +#include "SteelSeriesRivalController.h" +#include "SteelSeriesRival3Controller.h" +#include "SteelSeriesSenseiController.h" +#include "SteelSeriesSiberiaController.h" +#include "RGBController_SteelSeriesArctis5.h" +#include "RGBController_SteelSeriesApex.h" +#include "RGBController_SteelSeriesApex3.h" +#include "RGBController_SteelSeriesOldApex.h" +#include "RGBController_SteelSeriesQCKMat.h" +#include "RGBController_SteelSeriesRival.h" +#include "RGBController_SteelSeriesRival3.h" +#include "RGBController_SteelSeriesSensei.h" +#include "RGBController_SteelSeriesSiberia.h" + +/*-----------------------------------------------------*\ +| Vendor ID | +\*-----------------------------------------------------*/ +#define STEELSERIES_VID 0x1038 + +/*-----------------------------------------------------*\ +| Mouse product IDs | +\*-----------------------------------------------------*/ +#define STEELSERIES_AEROX_3_PID 0x1836 +#define STEELSERIES_AEROX_3_WIRELESS_PID 0x1838 +#define STEELSERIES_AEROX_3_WIRELESS_WIRED_PID 0x183A +#define STEELSERIES_AEROX_5_WIRELESS_PID 0x1852 +#define STEELSERIES_AEROX_5_WIRELESS_WIRED_PID 0x1854 +#define STEELSERIES_AEROX_5_DESTINY_WIRELESS_PID 0x185C +#define STEELSERIES_AEROX_5_DESTINY_WIRELESS_WIRED_PID 0x185E +#define STEELSERIES_AEROX_5_DIABLO_WIRELESS_PID 0x1860 +#define STEELSERIES_AEROX_5_DIABLO_WIRELESS_WIRED_PID 0x1862 +#define STEELSERIES_AEROX_9_WIRELESS_PID 0x1858 +#define STEELSERIES_AEROX_9_WIRELESS_WIRED_PID 0x185A +#define STEELSERIES_AEROX_5_PID 0x1850 +#define STEELSERIES_AEROX_9_PID 0x185A +#define STEELSERIES_RIVAL_100_PID 0x1702 +#define STEELSERIES_RIVAL_100_DOTA_PID 0x170C +#define STEELSERIES_RIVAL_105_PID 0x1814 +#define STEELSERIES_RIVAL_106_PID 0x1816 +#define STEELSERIES_RIVAL_110_PID 0x1729 +#define STEELSERIES_RIVAL_300_PID 0x1710 +#define ACER_PREDATOR_RIVAL_300_PID 0x1714 +#define STEELSERIES_RIVAL_300_CSGO_PID 0x1394 +#define STEELSERIES_RIVAL_300_CSGO_STM32_PID 0x1716 +#define STEELSERIES_RIVAL_300_CSGO_HYPERBEAST_PID 0x171A +#define STEELSERIES_RIVAL_300_DOTA_PID 0x1392 +#define STEELSERIES_RIVAL_300_HP_PID 0x1718 +#define STEELSERIES_RIVAL_300_BLACKOPS_PID 0x1710 +#define STEELSERIES_RIVAL_310_PID 0x1720 +#define STEELSERIES_RIVAL_310_CSGO_HOWL_PID 0x171E +#define STEELSERIES_RIVAL_310_PUBG_PID 0x1736 +#define STEELSERIES_RIVAL_600_PID 0x1724 +#define STEELSERIES_RIVAL_600_DOTA_2_PID 0x172E +#define STEELSERIES_RIVAL_650_PID 0x172B +#define STEELSERIES_RIVAL_650_WIRELESS_PID 0x1726 +#define STEELSERIES_RIVAL_700_PID 0x1700 +#define STEELSERIES_RIVAL_710_PID 0x1730 +#define STEELSERIES_RIVAL_3_OLD_PID 0x1824 +#define STEELSERIES_RIVAL_3_PID 0x184C +#define STEELSERIES_SENSEI_TEN_PID 0x1832 +#define STEELSERIES_SENSEI_TEN_CSGO_NEON_RIDER_PID 0x1834 +#define STEELSERIES_SENSEI_310_PID 0x1722 + +/*-----------------------------------------------------*\ +| Headset product IDs | +\*-----------------------------------------------------*/ +#define STEELSERIES_SIBERIA_350_PID 0x1229 +#define STEELSERIES_ARCTIS_5_PID 0x1250 +#define STEELSERIES_ARCTIS_5_V2_PID 0x12AA + +/*------------------------------------------------------------------*\ +| Mousemat product IDs | +\*------------------------------------------------------------------*/ +#define STEELSERIES_QCK_PRISM_CLOTH_MED_PID 0x150A +#define STEELSERIES_QCK_PRISM_CLOTH_XL_PID 0x150D +#define STEELSERIES_QCK_PRISM_CLOTH_XL_DESTINY_PID 0x151E +#define STEELSERIES_QCK_PRISM_CLOTH_XL_CSGO_NEON_RIDER_PID 0x1514 +#define STEELSERIES_QCK_PRISM_CLOTH_XL_CSGO_NEO_NOIR_PID 0x151C +#define STEELSERIES_QCK_PRISM_CLOTH_3XL_PID 0x1516 +#define STEELSERIES_QCK_PRISM_CLOTH_4XL_PID 0x1518 +#define STEELSERIES_QCK_PRISM_CLOTH_XL_DESTINY_LIGHTFALL_ED_PID 0X1520 + +/*-----------------------------------------------------*\ +| Keyboard product IDs | +\*-----------------------------------------------------*/ +#define STEELSERIES_APEX_3_PID 0x161A +#define STEELSERIES_APEX_3_TKL_PID 0x1622 +#define STEELSERIES_APEX_5_PID 0x161C +#define STEELSERIES_APEX_7_PID 0x1612 +#define STEELSERIES_APEX_7_TKL_PID 0x1618 +#define STEELSERIES_APEX_PRO_PID 0x1610 +#define STEELSERIES_APEX_PRO_TKL_PID 0x1614 +#define STEELSERIES_APEX_PRO_TKL_2023_PID 0x1628 +#define STEELSERIES_APEX_M750_PID 0x0616 +#define STEELSERIES_APEX_OG_PID 0x1202 +#define STEELSERIES_APEX_350_PID 0x1206 +#define STEELSERIES_APEX_PRO3_PID 0x1640 + +void DetectSteelSeriesAerox3(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesAerox3Controller* controller = new SteelSeriesAerox3Controller(dev, AEROX_3, info->path, name); + RGBController_SteelSeriesRival3* rgb_controller = new RGBController_SteelSeriesRival3(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectSteelSeriesAeroxWireless(hid_device_info* info, const std::string& name, steelseries_type proto_type) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesAeroxWirelessController* controller = new SteelSeriesAeroxWirelessController(dev, proto_type, info->path, name); + RGBController_SteelSeriesRival3* rgb_controller = new RGBController_SteelSeriesRival3(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectSteelSeriesAerox3Wireless(hid_device_info* info, const std::string& name) +{ + DetectSteelSeriesAeroxWireless(info, name, AEROX_3_WIRELESS); +} + +void DetectSteelSeriesAerox3WirelessWired(hid_device_info* info, const std::string& name) +{ + DetectSteelSeriesAeroxWireless(info, name, AEROX_3_WIRELESS_WIRED); +} + +void DetectSteelSeriesAerox5(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesAerox5Controller* controller = new SteelSeriesAerox5Controller(dev, AEROX_3, info->path, name); + RGBController_SteelSeriesRival3* rgb_controller = new RGBController_SteelSeriesRival3(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectSteelSeriesAerox5Wireless(hid_device_info* info, const std::string& name) +{ + DetectSteelSeriesAeroxWireless(info, name, AEROX_5_WIRELESS); +} + +void DetectSteelSeriesAerox5WirelessWired(hid_device_info* info, const std::string& name) +{ + DetectSteelSeriesAeroxWireless(info, name, AEROX_5_WIRELESS_WIRED); +} + +void DetectSteelSeriesAerox5DestinyWireless(hid_device_info* info, const std::string& name) +{ + DetectSteelSeriesAeroxWireless(info, name, AEROX_5_DESTINY_WIRELESS); +} + +void DetectSteelSeriesAerox5DestinyWirelessWired(hid_device_info* info, const std::string& name) +{ + DetectSteelSeriesAeroxWireless(info, name, AEROX_5_DESTINY_WIRELESS_WIRED); +} + +void DetectSteelSeriesAerox5DiabloWireless(hid_device_info* info, const std::string& name) +{ + DetectSteelSeriesAeroxWireless(info, name, AEROX_5_DIABLO_WIRELESS); +} + +void DetectSteelSeriesAerox5DiabloWirelessWired(hid_device_info* info, const std::string& name) +{ + DetectSteelSeriesAeroxWireless(info, name, AEROX_5_DIABLO_WIRELESS_WIRED); +} + +void DetectSteelSeriesAerox9Wireless(hid_device_info* info, const std::string& name) +{ + DetectSteelSeriesAeroxWireless(info, name, AEROX_9_WIRELESS); +} + +void DetectSteelSeriesAerox9WirelessWired(hid_device_info* info, const std::string& name) +{ + DetectSteelSeriesAeroxWireless(info, name, AEROX_9_WIRELESS_WIRED); +} + +void DetectSteelSeriesApex3Full(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesApexTZoneController* controller = new SteelSeriesApexTZoneController(dev, info->path, name); + RGBController_SteelSeriesApex3* rgb_controller = new RGBController_SteelSeriesApex3(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectSteelSeriesApex3TKL(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesApex8ZoneController* controller = new SteelSeriesApex8ZoneController(dev, info->path, name); + RGBController_SteelSeriesApex3* rgb_controller = new RGBController_SteelSeriesApex3(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectSteelSeriesApex(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesApexController* controller = new SteelSeriesApexController(dev, APEX, info->path, name); + RGBController_SteelSeriesApex* rgb_controller = new RGBController_SteelSeriesApex(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectSteelSeriesApexM(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesApexMController* controller = new SteelSeriesApexMController(dev, APEX_M, info->path, name); + RGBController_SteelSeriesApex* rgb_controller = new RGBController_SteelSeriesApex(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectSteelSeriesApexOld(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesOldApexController* controller = new SteelSeriesOldApexController(dev, APEX_OLD, info->path, name); + RGBController_SteelSeriesOldApex* rgb_controller = new RGBController_SteelSeriesOldApex(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectSteelSeriesHeadset(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesSiberiaController* controller = new SteelSeriesSiberiaController(dev, info->path, name); + RGBController_SteelSeriesSiberia* rgb_controller = new RGBController_SteelSeriesSiberia(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectSteelSeriesMousemat(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesQCKMatController* controller = new SteelSeriesQCKMatController(dev, info->path, name); + RGBController_SteelSeriesQCKMat* rgb_controller = new RGBController_SteelSeriesQCKMat(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectSteelSeriesRival100(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesRivalController* controller = new SteelSeriesRivalController(dev, RIVAL_100, info->path, name); + RGBController_SteelSeriesRival* rgb_controller = new RGBController_SteelSeriesRival(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectSteelSeriesRival300(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesRivalController* controller = new SteelSeriesRivalController(dev, RIVAL_300, info->path, name); + RGBController_SteelSeriesRival* rgb_controller = new RGBController_SteelSeriesRival(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectSteelSeriesRival600(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesRivalController* controller = new SteelSeriesRivalController(dev, RIVAL_600, info->path, name); + RGBController_SteelSeriesRival* rgb_controller = new RGBController_SteelSeriesRival(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + + +void DetectSteelSeriesRival650(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesRivalController* controller = new SteelSeriesRivalController(dev, RIVAL_650, info->path, name); + RGBController_SteelSeriesRival* rgb_controller = new RGBController_SteelSeriesRival(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectSteelSeriesRival700(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesRivalController* controller = new SteelSeriesRivalController(dev, RIVAL_700, info->path, name); + RGBController_SteelSeriesRival* rgb_controller = new RGBController_SteelSeriesRival(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + + +void DetectSteelSeriesRival3(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesRival3Controller* controller = new SteelSeriesRival3Controller(dev, RIVAL_3, info->path, name); + RGBController_SteelSeriesRival3* rgb_controller = new RGBController_SteelSeriesRival3(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectSteelSeriesSensei(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesSenseiController* controller = new SteelSeriesSenseiController(dev, SENSEI, info->path, name); + RGBController_SteelSeriesSensei* rgb_controller = new RGBController_SteelSeriesSensei(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +void DetectSteelSeriesArctis5(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + SteelSeriesArctis5Controller* controller = new SteelSeriesArctis5Controller(dev, *info, name); + RGBController_SteelSeriesArctis5* rgb_controller = new RGBController_SteelSeriesArctis5(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*\ +| Mice | +\*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 3 Wireless", DetectSteelSeriesAerox3Wireless, STEELSERIES_VID, STEELSERIES_AEROX_3_WIRELESS_PID, 3, 0xFFC0, 1 ); +REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 3 Wireless Wired", DetectSteelSeriesAerox3WirelessWired, STEELSERIES_VID, STEELSERIES_AEROX_3_WIRELESS_WIRED_PID, 3, 0xFFC0, 1 ); +REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 3 Wired", DetectSteelSeriesAerox3, STEELSERIES_VID, STEELSERIES_AEROX_3_PID, 3, 0xFFC0, 1 ); +REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 5 Wireless", DetectSteelSeriesAerox5Wireless, STEELSERIES_VID, STEELSERIES_AEROX_5_WIRELESS_PID, 3, 0xFFC0, 1 ); +REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 5 Wireless Wired", DetectSteelSeriesAerox5WirelessWired, STEELSERIES_VID, STEELSERIES_AEROX_5_WIRELESS_WIRED_PID, 3, 0xFFC0, 1 ); +REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 5 Destiny 2 Edition Wireless", DetectSteelSeriesAerox5DestinyWireless, STEELSERIES_VID, STEELSERIES_AEROX_5_DESTINY_WIRELESS_PID, 3, 0xFFC0, 1 ); +REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 5 Destiny 2 Edition Wireless Wired", DetectSteelSeriesAerox5DestinyWirelessWired, STEELSERIES_VID, STEELSERIES_AEROX_5_DESTINY_WIRELESS_WIRED_PID, 3, 0xFFC0, 1 ); +REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 5 Diablo IV Edition Wireless", DetectSteelSeriesAerox5DiabloWireless, STEELSERIES_VID, STEELSERIES_AEROX_5_DIABLO_WIRELESS_PID, 3, 0xFFC0, 1 ); +REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 5 Diablo IV Edition Wireless Wired", DetectSteelSeriesAerox5DiabloWirelessWired, STEELSERIES_VID, STEELSERIES_AEROX_5_DIABLO_WIRELESS_WIRED_PID, 3, 0xFFC0, 1 ); +REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 5 Wired", DetectSteelSeriesAerox5, STEELSERIES_VID, STEELSERIES_AEROX_5_PID, 3, 0xFFC0, 1 ); +REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 9 Wireless", DetectSteelSeriesAerox9Wireless, STEELSERIES_VID, STEELSERIES_AEROX_9_WIRELESS_PID, 3, 0xFFC0, 1 ); +REGISTER_HID_DETECTOR_IPU("SteelSeries Aerox 9 Wireless Wired", DetectSteelSeriesAerox9WirelessWired, STEELSERIES_VID, STEELSERIES_AEROX_9_WIRELESS_WIRED_PID, 3, 0xFFC0, 1 ); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 100", DetectSteelSeriesRival100, STEELSERIES_VID, STEELSERIES_RIVAL_100_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 100 DotA 2 Edition", DetectSteelSeriesRival100, STEELSERIES_VID, STEELSERIES_RIVAL_100_DOTA_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 105", DetectSteelSeriesRival100, STEELSERIES_VID, STEELSERIES_RIVAL_105_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 106", DetectSteelSeriesRival100, STEELSERIES_VID, STEELSERIES_RIVAL_106_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 110", DetectSteelSeriesRival100, STEELSERIES_VID, STEELSERIES_RIVAL_110_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 300", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_PID, 0); +REGISTER_HID_DETECTOR_I("Acer Predator Gaming Mouse (Rival 300)", DetectSteelSeriesRival300, STEELSERIES_VID, ACER_PREDATOR_RIVAL_300_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 CS:GO Fade Edition", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_CSGO_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 CS:GO Fade Edition (stm32)", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_CSGO_STM32_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 CS:GO Hyperbeast Edition", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_CSGO_HYPERBEAST_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 Dota 2 Edition", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_DOTA_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 HP Omen Edition", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_HP_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 300 Black Ops Edition", DetectSteelSeriesRival300, STEELSERIES_VID, STEELSERIES_RIVAL_300_BLACKOPS_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 310", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_RIVAL_310_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 310 CS:GO Howl Edition", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_RIVAL_310_CSGO_HOWL_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 310 PUBG Edition", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_RIVAL_310_PUBG_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 600", DetectSteelSeriesRival600, STEELSERIES_VID, STEELSERIES_RIVAL_600_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 600 Dota 2 Edition", DetectSteelSeriesRival600, STEELSERIES_VID, STEELSERIES_RIVAL_600_DOTA_2_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 650", DetectSteelSeriesRival650, STEELSERIES_VID, STEELSERIES_RIVAL_650_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 650 Wireless", DetectSteelSeriesRival650, STEELSERIES_VID, STEELSERIES_RIVAL_650_WIRELESS_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 700", DetectSteelSeriesRival700, STEELSERIES_VID, STEELSERIES_RIVAL_700_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 710", DetectSteelSeriesRival700, STEELSERIES_VID, STEELSERIES_RIVAL_710_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 3 (Old Firmware)", DetectSteelSeriesRival3, STEELSERIES_VID, STEELSERIES_RIVAL_3_OLD_PID, 3); +REGISTER_HID_DETECTOR_I("SteelSeries Rival 3", DetectSteelSeriesRival3, STEELSERIES_VID, STEELSERIES_RIVAL_3_PID, 3); +REGISTER_HID_DETECTOR_I("SteelSeries Sensei TEN", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_SENSEI_TEN_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Sensei TEN CS:GO Neon Rider Edition", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_SENSEI_TEN_CSGO_NEON_RIDER_PID, 0); +REGISTER_HID_DETECTOR_I("SteelSeries Sensei 310", DetectSteelSeriesSensei, STEELSERIES_VID, STEELSERIES_SENSEI_310_PID, 0); + +/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*\ +| Headsets | +\*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +REGISTER_HID_DETECTOR_I("SteelSeries Siberia 350", DetectSteelSeriesHeadset, STEELSERIES_VID, STEELSERIES_SIBERIA_350_PID, 3 ); +REGISTER_HID_DETECTOR_I("SteelSeries Arctis 5", DetectSteelSeriesArctis5, STEELSERIES_VID, STEELSERIES_ARCTIS_5_PID, 5 ); +REGISTER_HID_DETECTOR_I("SteelSeries Arctis 5", DetectSteelSeriesArctis5, STEELSERIES_VID, STEELSERIES_ARCTIS_5_V2_PID, 5 ); + +/*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*\ +| Mousemats | +\*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth Medium", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_MED_PID, 0 ); +REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth XL", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_XL_PID, 0 ); +REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth XL Destiny Ed.", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_XL_DESTINY_PID, 0 ); +REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth XL Destiny Lightfall Ed.", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_XL_DESTINY_LIGHTFALL_ED_PID, 0 ); +REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth XL CS:GO Neon Rider Ed.", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_XL_CSGO_NEON_RIDER_PID, 0 ); +REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth XL CS:GO Neo Noir Ed.", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_XL_CSGO_NEO_NOIR_PID, 0 ); +REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth 3XL", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_3XL_PID, 0 ); +REGISTER_HID_DETECTOR_I("SteelSeries QCK Prism Cloth 4XL", DetectSteelSeriesMousemat, STEELSERIES_VID, STEELSERIES_QCK_PRISM_CLOTH_4XL_PID, 0 ); + +/*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*\ +| Keyboards | +\*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +REGISTER_HID_DETECTOR_I ("SteelSeries Apex 3", DetectSteelSeriesApex3Full, STEELSERIES_VID, STEELSERIES_APEX_3_PID, 3 ); +REGISTER_HID_DETECTOR_IPU("SteelSeries Apex 3 TKL", DetectSteelSeriesApex3TKL, STEELSERIES_VID, STEELSERIES_APEX_3_TKL_PID, 1, 0xFFC0, 1 ); +REGISTER_HID_DETECTOR_I ("SteelSeries Apex 5", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_5_PID, 1 ); +REGISTER_HID_DETECTOR_I ("SteelSeries Apex 7", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_7_PID, 1 ); +REGISTER_HID_DETECTOR_I ("SteelSeries Apex 7 TKL", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_7_TKL_PID, 1 ); +REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_PID, 1 ); +REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro TKL", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_PID, 1 ); +REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro TKL 2023", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO_TKL_2023_PID, 1 ); +REGISTER_HID_DETECTOR_I ("SteelSeries Apex M750", DetectSteelSeriesApexM, STEELSERIES_VID, STEELSERIES_APEX_M750_PID, 2 ); +REGISTER_HID_DETECTOR_I ("SteelSeries Apex (OG)/Apex Fnatic", DetectSteelSeriesApexOld, STEELSERIES_VID, STEELSERIES_APEX_OG_PID, 0 ); +REGISTER_HID_DETECTOR_I ("SteelSeries Apex 350", DetectSteelSeriesApexOld, STEELSERIES_VID, STEELSERIES_APEX_350_PID, 0 ); +REGISTER_HID_DETECTOR_I ("SteelSeries Apex Pro 3", DetectSteelSeriesApex, STEELSERIES_VID, STEELSERIES_APEX_PRO3_PID, 1 ); diff --git a/Controllers/SteelSeriesController/SteelSeriesGeneric.h b/Controllers/SteelSeriesController/SteelSeriesGeneric.h index 4c828e1c..f7e38425 100644 --- a/Controllers/SteelSeriesController/SteelSeriesGeneric.h +++ b/Controllers/SteelSeriesController/SteelSeriesGeneric.h @@ -1,35 +1,46 @@ -/*-----------------------------------------*\ -| SteelSeriesGeneric.h | -| | -| Definitions and types for the SteelSeries| -| Devices. | -| | -| B Horn (bahorn) 17/5/2020 | -\*-----------------------------------------*/ - -#include -#include +/*---------------------------------------------------------*\ +| SteelSeriesGeneric.h | +| | +| Generic file for SteelSeries devices | +| | +| B Horn (bahorn) 17 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include + /* Allows us to handle variation in the protocol. * Defined in a single enum so we can keep the device_list struct the same * for every possible device. */ typedef enum { - RIVAL_100 = 0x00, - RIVAL_300 = 0x01, - RIVAL_650 = 0x02, - SIBERIA_350 = 0x03, - APEX = 0x04, - APEX_M = 0x05, - APEX_OLD = 0x06, - SENSEI = 0x07, - RIVAL_600 = 0x08, - RIVAL_3 = 0x09, - APEX_TZONE = 0x0A, - RIVAL_700 = 0x0B, - AEROX_3 = 0x0C, - APEX_8ZONE = 0x0D, + RIVAL_100 = 0x00, + RIVAL_300 = 0x01, + RIVAL_650 = 0x02, + SIBERIA_350 = 0x03, + APEX = 0x04, + APEX_M = 0x05, + APEX_OLD = 0x06, + SENSEI = 0x07, + RIVAL_600 = 0x08, + RIVAL_3 = 0x09, + APEX_TZONE = 0x0A, + RIVAL_700 = 0x0B, + AEROX_3 = 0x0C, + APEX_8ZONE = 0x0D, + AEROX_3_WIRELESS = 0x0E, + AEROX_3_WIRELESS_WIRED = 0x0F, + AEROX_5_WIRELESS = 0x10, + AEROX_5_WIRELESS_WIRED = 0x11, + AEROX_5_DESTINY_WIRELESS = 0x12, + AEROX_5_DESTINY_WIRELESS_WIRED = 0x13, + AEROX_5_DIABLO_WIRELESS = 0x14, + AEROX_5_DIABLO_WIRELESS_WIRED = 0x15, + AEROX_9_WIRELESS = 0x16, + AEROX_9_WIRELESS_WIRED = 0x17, } steelseries_type; - diff --git a/Controllers/SteelSeriesController/SteelSeriesMouseController.cpp b/Controllers/SteelSeriesController/SteelSeriesMouseController.cpp deleted file mode 100644 index 71dd57f1..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesMouseController.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/*-------------------------------------------------------------------*\ -| SteelSeriesMouseController.cpp | -| | -| OpenRGB abstract driver for SteelSeries Mice | -| | -| Chris M (Dr_No) 9th June 2022 | -\*-------------------------------------------------------------------*/ - -#include -#include "SteelSeriesMouseController.h" - -SteelSeriesMouseController::SteelSeriesMouseController(hid_device* dev_handle, steelseries_type proto_type, const char* path) -{ - dev = dev_handle; - location = path; - proto = proto_type; -} - -SteelSeriesMouseController::~SteelSeriesMouseController() -{ - -} - -std::string SteelSeriesMouseController::GetDeviceLocation() -{ - return("HID: " + location); -} - -char* SteelSeriesMouseController::GetDeviceName() -{ - return device_name; -} - -std::string SteelSeriesMouseController::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); -} - -steelseries_type SteelSeriesMouseController::GetMouseType() -{ - return proto; -} - -void SteelSeriesMouseController::Save() -{ - const uint8_t SAVE_BUFFER_SIZE = 10; - uint8_t usb_buf[SAVE_BUFFER_SIZE] = { 0x00, 0x09 }; - - hid_write(dev, usb_buf, SAVE_BUFFER_SIZE); -} diff --git a/Controllers/SteelSeriesController/SteelSeriesMouseController/SteelSeriesMouseController.cpp b/Controllers/SteelSeriesController/SteelSeriesMouseController/SteelSeriesMouseController.cpp new file mode 100644 index 00000000..78c31881 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesMouseController/SteelSeriesMouseController.cpp @@ -0,0 +1,63 @@ +/*---------------------------------------------------------*\ +| SteelSeriesMouseController.cpp | +| | +| Driver for SteelSeries Mouse | +| | +| Chris M (Dr_No) 09 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "SteelSeriesMouseController.h" +#include "StringUtils.h" + +SteelSeriesMouseController::SteelSeriesMouseController(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + proto = proto_type; +} + +SteelSeriesMouseController::~SteelSeriesMouseController() +{ + +} + +std::string SteelSeriesMouseController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string SteelSeriesMouseController::GetNameString() +{ + return(name); +} + +std::string SteelSeriesMouseController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +steelseries_type SteelSeriesMouseController::GetMouseType() +{ + return proto; +} + +void SteelSeriesMouseController::Save() +{ + const uint8_t SAVE_BUFFER_SIZE = 10; + uint8_t usb_buf[SAVE_BUFFER_SIZE] = { 0x00, 0x09 }; + + hid_write(dev, usb_buf, SAVE_BUFFER_SIZE); +} diff --git a/Controllers/SteelSeriesController/SteelSeriesMouseController.h b/Controllers/SteelSeriesController/SteelSeriesMouseController/SteelSeriesMouseController.h similarity index 75% rename from Controllers/SteelSeriesController/SteelSeriesMouseController.h rename to Controllers/SteelSeriesController/SteelSeriesMouseController/SteelSeriesMouseController.h index a4e561a3..f0252bf9 100644 --- a/Controllers/SteelSeriesController/SteelSeriesMouseController.h +++ b/Controllers/SteelSeriesController/SteelSeriesMouseController/SteelSeriesMouseController.h @@ -1,19 +1,22 @@ -/*-------------------------------------------------------------------*\ -| SteelSeriesMouseController.h | -| | -| OpenRGB abstract driver for SteelSeries Mice | -| | -| Chris M (Dr_No) 9th June 2022 | -\*-------------------------------------------------------------------*/ - -#include -#include -#include -#include "SteelSeriesGeneric.h" -#include +/*---------------------------------------------------------*\ +| SteelSeriesMouseController.h | +| | +| Driver for SteelSeries Mouse | +| | +| Chris M (Dr_No) 09 Jun 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include +#include +#include "SteelSeriesGeneric.h" + #define STEELSERIES_MOUSE_BRIGHTNESS_MAX 0x64 /*-----------------------------------------------------------*\ @@ -45,11 +48,11 @@ typedef struct class SteelSeriesMouseController { public: - SteelSeriesMouseController(hid_device* dev_handle, steelseries_type proto_type, const char* path); + SteelSeriesMouseController(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name); virtual ~SteelSeriesMouseController(); std::string GetDeviceLocation(); - char* GetDeviceName(); + std::string GetNameString(); std::string GetSerialString(); steelseries_type GetMouseType(); @@ -71,9 +74,9 @@ public: ) = 0; protected: - char device_name[32]; hid_device* dev; std::string location; + std::string name; steelseries_type proto; private: diff --git a/Controllers/SteelSeriesController/SteelSeriesOldApexController.cpp b/Controllers/SteelSeriesController/SteelSeriesOldApexController.cpp deleted file mode 100644 index d77ab1fb..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesOldApexController.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/*-----------------------------------------*\ -| SteelSeriesOldApexController.cpp | -| | -| RGB Lighting Library for SteelSeries | -| older Apex KB lighting controller | -| (Apex, Apex Fnatic, Apex 350) | -| | -| David Lee (RAMChYLD) 15/11/2020 | -| | -| Based on work for SteelSeries Rival by | -| B Horn (bahorn) 13/5/2020 | -| | -| Based on findings in ApexCtl by | -| Audrius/tuxmark5, et. al | -| https://github.com/tuxmark5/ApexCtl | -\*-----------------------------------------*/ - - -#include "SteelSeriesOldApexController.h" -#include -#include -#include - -static void send_usb_msg(hid_device* dev, char * data_pkt, unsigned int size) -{ - char* usb_pkt = new char[size + 1]; - - usb_pkt[0] = 0x00; - for(unsigned int i = 1; i < size + 1; i++) - { - usb_pkt[i] = data_pkt[i-1]; - } - - hid_write(dev, (unsigned char *)usb_pkt, size + 1); - - delete[] usb_pkt; -} - -SteelSeriesOldApexController::SteelSeriesOldApexController - ( - hid_device* dev_handle, - steelseries_type proto_type, - const char* path - ) -{ - dev = dev_handle; - location = path; - proto = proto_type; -} - -SteelSeriesOldApexController::~SteelSeriesOldApexController() -{ - hid_close(dev); -} - -std::string SteelSeriesOldApexController::GetDeviceLocation() -{ - return("HID: " + location); -} - -char* SteelSeriesOldApexController::GetDeviceName() -{ - return device_name; -} - -std::string SteelSeriesOldApexController::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); -} - -steelseries_type SteelSeriesOldApexController::GetKeyboardType() -{ - return proto; -} - -void SteelSeriesOldApexController::SetColorDetailed(color32 qwerty, color32 tenkey, color32 functionkey, color32 mxkey, color32 logo) -{ - char usb_buf[32]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0x00] = 0x07; - usb_buf[0x01] = 0x00; // All zones - - // QWERTY Zone - usb_buf[0x02] = qwerty.red; - usb_buf[0x03] = qwerty.green; - usb_buf[0x04] = qwerty.blue; - usb_buf[0x05] = qwerty.alpha; - - // Tenkey Zone - usb_buf[0x06] = tenkey.red; - usb_buf[0x07] = tenkey.green; - usb_buf[0x08] = tenkey.blue; - usb_buf[0x09] = tenkey.alpha; - - // FunctionKey Zone - usb_buf[0x0A] = functionkey.red; - usb_buf[0x0B] = functionkey.green; - usb_buf[0x0C] = functionkey.blue; - usb_buf[0x0D] = functionkey.alpha; - - // MXKey Zone - usb_buf[0x0E] = mxkey.red; - usb_buf[0x0F] = mxkey.green; - usb_buf[0x10] = mxkey.blue; - usb_buf[0x11] = mxkey.alpha; - - //Logo Zone - usb_buf[0x12] = logo.red; - usb_buf[0x13] = logo.green; - usb_buf[0x14] = logo.blue; - usb_buf[0x15] = logo.alpha; - - send_usb_msg(dev, usb_buf, 32); -} diff --git a/Controllers/SteelSeriesController/SteelSeriesOldApexController.h b/Controllers/SteelSeriesController/SteelSeriesOldApexController.h deleted file mode 100644 index b5b0c523..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesOldApexController.h +++ /dev/null @@ -1,72 +0,0 @@ -/*-----------------------------------------*\ -| SteelSeriesOldApexController.h | -| | -| Definitions and types for SteelSeries | -| older Apex KB lighting controller | -| (Apex, Apex Fnatic, Apex 350) | -| | -| David Lee (RAMChYLD) 15/11/2020 | -| | -| Based on work for SteelSeries Rival by | -| B Horn (bahorn) 13/5/2020 | -| | -| Based on findings in ApexCtl by | -| Audrius/tuxmark5, et. al | -| https://github.com/tuxmark5/ApexCtl | -\*-----------------------------------------*/ - -#include -#include - -#include "color32.h" -#include "SteelSeriesGeneric.h" - -#pragma once - -/* Mode, we then use these to set actual effect based on speed. */ -enum -{ - STEELSERIES_OLDAPEX_DIRECT = 0x08, -}; - -/* Effects */ -enum -{ - STEELSERIES_OLDAPEX_EFFECT_DIRECT = 0x08, -}; - -class SteelSeriesOldApexController -{ -public: - SteelSeriesOldApexController - ( - hid_device* dev_handle, - steelseries_type proto_type, - const char* path - ); - - ~SteelSeriesOldApexController(); - - std::string GetDeviceLocation(); - char* GetDeviceName(); - std::string GetSerialString(); - - steelseries_type GetKeyboardType(); - - void SetColorDetailed - ( - color32 qwerty, - color32 tenkey, - color32 functionkey, - color32 mxkey, - color32 logo - ); - - void DoUpdateLEDs(); - -private: - char device_name[32]; - hid_device* dev; - std::string location; - steelseries_type proto; -}; diff --git a/Controllers/SteelSeriesController/SteelSeriesOldApexController/RGBController_SteelSeriesOldApex.cpp b/Controllers/SteelSeriesController/SteelSeriesOldApexController/RGBController_SteelSeriesOldApex.cpp new file mode 100644 index 00000000..26d18f6c --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesOldApexController/RGBController_SteelSeriesOldApex.cpp @@ -0,0 +1,200 @@ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesOldApex.cpp | +| | +| RGBController for older SteelSeries Apex keyboards | +| (Apex/Apex Fnatic/Apex 350) | +| | +| Based on findings in ApexCtl by Audrius/tuxmark5, et. | +| al, https://github.com/tuxmark5/ApexCtl | +| | +| David Lee (RAMChYLD) 15 Nov 2020 | +| Based on work by B Horn (bahorn) 13 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_SteelSeriesOldApex.h" + +/**------------------------------------------------------------------*\ + @name Steel Series Apex (Old) + @category Keyboard + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectSteelSeriesApexOld + @comment +\*-------------------------------------------------------------------*/ + +RGBController_SteelSeriesOldApex::RGBController_SteelSeriesOldApex(SteelSeriesOldApexController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "SteelSeries"; + type = DEVICE_TYPE_KEYBOARD; + description = "SteelSeries Old Apex Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode direct; + direct.name = "Direct"; + direct.value = STEELSERIES_OLDAPEX_DIRECT; + direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(direct); + + SetupZones(); +} + +RGBController_SteelSeriesOldApex::~RGBController_SteelSeriesOldApex() +{ + delete controller; +} + +void RGBController_SteelSeriesOldApex::SetupZones() +{ + /* We have 5 zones to work with. Here goes... */ + zone qwerty_zone; + qwerty_zone.name = "QWERTY"; + qwerty_zone.type = ZONE_TYPE_LINEAR; + qwerty_zone.leds_min = 1; + qwerty_zone.leds_max = 1; + qwerty_zone.leds_count = 1; + qwerty_zone.matrix_map = NULL; + zones.push_back(qwerty_zone); + + led qwerty_led; + qwerty_led.name = "QWERTY"; + leds.push_back(qwerty_led); + + zone tenkey_zone; + tenkey_zone.name = "TenKey"; + tenkey_zone.type = ZONE_TYPE_LINEAR; + tenkey_zone.leds_min = 1; + tenkey_zone.leds_max = 1; + tenkey_zone.leds_count = 1; + tenkey_zone.matrix_map = NULL; + zones.push_back(tenkey_zone); + + led tenkey_led; + tenkey_led.name = "TenKey"; + leds.push_back(tenkey_led); + + zone function_zone; + function_zone.name = "FunctionKeys"; + function_zone.type = ZONE_TYPE_LINEAR; + function_zone.leds_min = 1; + function_zone.leds_max = 1; + function_zone.leds_count = 1; + function_zone.matrix_map = NULL; + zones.push_back(function_zone); + + led function_led; + function_led.name = "FunctionKeys"; + leds.push_back(function_led); + + zone mx_zone; + mx_zone.name = "MXKeys"; + mx_zone.type = ZONE_TYPE_LINEAR; + mx_zone.leds_min = 1; + mx_zone.leds_max = 1; + mx_zone.leds_count = 1; + mx_zone.matrix_map = NULL; + zones.push_back(mx_zone); + + led mx_led; + mx_led.name = "MXKeys"; + leds.push_back(mx_led); + + zone logo_zone; + logo_zone.name = "Logo"; + logo_zone.type = ZONE_TYPE_LINEAR; + logo_zone.leds_min = 1; + logo_zone.leds_max = 1; + logo_zone.leds_count = 1; + logo_zone.matrix_map = NULL; + zones.push_back(logo_zone); + + led logo_led; + logo_led.name = "Logo"; + leds.push_back(logo_led); + + SetupColors(); +} + +void RGBController_SteelSeriesOldApex::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_SteelSeriesOldApex::DeviceUpdateLEDs() +{ + // Due to the inefficient packet design of the OG Apex + // All colors must be blasted with each update + color32 qwerty; + qwerty.red = RGBGetRValue(colors[0]); + qwerty.green = RGBGetGValue(colors[0]); + qwerty.blue = RGBGetBValue(colors[0]); + qwerty.alpha = modes[active_mode].value; + + color32 tenkey; + tenkey.red = RGBGetRValue(colors[1]); + tenkey.green = RGBGetGValue(colors[1]); + tenkey.blue = RGBGetBValue(colors[1]); + tenkey.alpha = modes[active_mode].value; + + color32 functionkey; + functionkey.red = RGBGetRValue(colors[2]); + functionkey.green = RGBGetGValue(colors[2]); + functionkey.blue = RGBGetBValue(colors[2]); + functionkey.alpha = modes[active_mode].value; + + color32 mxkey; + mxkey.red = RGBGetRValue(colors[3]); + mxkey.green = RGBGetGValue(colors[3]); + mxkey.blue = RGBGetBValue(colors[3]); + mxkey.alpha = modes[active_mode].value; + + color32 logo; + logo.red = RGBGetRValue(colors[4]); + logo.green = RGBGetGValue(colors[4]); + logo.blue = RGBGetBValue(colors[4]); + logo.alpha = modes[active_mode].value; + + controller->SetColorDetailed(qwerty, tenkey, functionkey, mxkey, logo); +} + +void RGBController_SteelSeriesOldApex::UpdateZoneLEDs(int /*zone*/) +{ + // updating for one zone is pointless, + // all zones have to be blasted anyway + // so just do a full update + DeviceUpdateLEDs(); +} + + +void RGBController_SteelSeriesOldApex::UpdateSingleLED(int /*led*/) +{ + // Each zone is one LED, however + // updating for one zone is pointless, + // all zones have to be blasted anyway + // so just do a full update + DeviceUpdateLEDs(); +} + +void RGBController_SteelSeriesOldApex::DeviceUpdateMode() +{ + // We are using SetLightingEffect to control the brightness of + // LEDs. Per-zone brightness is actually possible but we are not + // doing that for now. Brightness affects whole keyboard. + + // Because at the moment all this code does is change brightness, + // We just let the new value set in and do a device LED update + // and blast the brightness value along with the RGB values + + DeviceUpdateLEDs(); +} diff --git a/Controllers/SteelSeriesController/SteelSeriesOldApexController/RGBController_SteelSeriesOldApex.h b/Controllers/SteelSeriesController/SteelSeriesOldApexController/RGBController_SteelSeriesOldApex.h new file mode 100644 index 00000000..ada2fe21 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesOldApexController/RGBController_SteelSeriesOldApex.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesOldApex.h | +| | +| RGBController for older SteelSeries Apex keyboards | +| (Apex/Apex Fnatic/Apex 350) | +| | +| Based on findings in ApexCtl by Audrius/tuxmark5, et. | +| al, https://github.com/tuxmark5/ApexCtl | +| | +| David Lee (RAMChYLD) 15 Nov 2020 | +| Based on work by B Horn (bahorn) 13 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SteelSeriesOldApexController.h" +#include "color32.h" + +class RGBController_SteelSeriesOldApex : public RGBController +{ +public: + RGBController_SteelSeriesOldApex(SteelSeriesOldApexController* controller_ptr); + ~RGBController_SteelSeriesOldApex(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + SteelSeriesOldApexController* controller; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesOldApexController/SteelSeriesOldApexController.cpp b/Controllers/SteelSeriesController/SteelSeriesOldApexController/SteelSeriesOldApexController.cpp new file mode 100644 index 00000000..855ee0de --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesOldApexController/SteelSeriesOldApexController.cpp @@ -0,0 +1,124 @@ +/*---------------------------------------------------------*\ +| SteelSeriesOldApexController.cpp | +| | +| Driver for older SteelSeries Apex keyboards | +| (Apex/Apex Fnatic/Apex 350) | +| | +| Based on findings in ApexCtl by Audrius/tuxmark5, et. | +| al, https://github.com/tuxmark5/ApexCtl | +| | +| David Lee (RAMChYLD) 15 Nov 2020 | +| Based on work by B Horn (bahorn) 13 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include "SteelSeriesOldApexController.h" +#include "StringUtils.h" + +static void send_usb_msg(hid_device* dev, char * data_pkt, unsigned int size) +{ + char* usb_pkt = new char[size + 1]; + + usb_pkt[0] = 0x00; + for(unsigned int i = 1; i < size + 1; i++) + { + usb_pkt[i] = data_pkt[i-1]; + } + + hid_write(dev, (unsigned char *)usb_pkt, size + 1); + + delete[] usb_pkt; +} + +SteelSeriesOldApexController::SteelSeriesOldApexController + ( + hid_device* dev_handle, + steelseries_type proto_type, + const char* path, + std::string dev_name + ) +{ + dev = dev_handle; + location = path; + name = dev_name; + proto = proto_type; +} + +SteelSeriesOldApexController::~SteelSeriesOldApexController() +{ + hid_close(dev); +} + +std::string SteelSeriesOldApexController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string SteelSeriesOldApexController::GetDeviceName() +{ + return(name); +} + +std::string SteelSeriesOldApexController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +steelseries_type SteelSeriesOldApexController::GetKeyboardType() +{ + return proto; +} + +void SteelSeriesOldApexController::SetColorDetailed(color32 qwerty, color32 tenkey, color32 functionkey, color32 mxkey, color32 logo) +{ + char usb_buf[32]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0x00] = 0x07; + usb_buf[0x01] = 0x00; // All zones + + // QWERTY Zone + usb_buf[0x02] = qwerty.red; + usb_buf[0x03] = qwerty.green; + usb_buf[0x04] = qwerty.blue; + usb_buf[0x05] = qwerty.alpha; + + // Tenkey Zone + usb_buf[0x06] = tenkey.red; + usb_buf[0x07] = tenkey.green; + usb_buf[0x08] = tenkey.blue; + usb_buf[0x09] = tenkey.alpha; + + // FunctionKey Zone + usb_buf[0x0A] = functionkey.red; + usb_buf[0x0B] = functionkey.green; + usb_buf[0x0C] = functionkey.blue; + usb_buf[0x0D] = functionkey.alpha; + + // MXKey Zone + usb_buf[0x0E] = mxkey.red; + usb_buf[0x0F] = mxkey.green; + usb_buf[0x10] = mxkey.blue; + usb_buf[0x11] = mxkey.alpha; + + //Logo Zone + usb_buf[0x12] = logo.red; + usb_buf[0x13] = logo.green; + usb_buf[0x14] = logo.blue; + usb_buf[0x15] = logo.alpha; + + send_usb_msg(dev, usb_buf, 32); +} diff --git a/Controllers/SteelSeriesController/SteelSeriesOldApexController/SteelSeriesOldApexController.h b/Controllers/SteelSeriesController/SteelSeriesOldApexController/SteelSeriesOldApexController.h new file mode 100644 index 00000000..c85cf117 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesOldApexController/SteelSeriesOldApexController.h @@ -0,0 +1,71 @@ +/*---------------------------------------------------------*\ +| SteelSeriesOldApexController.h | +| | +| Driver for older SteelSeries Apex keyboards | +| (Apex/Apex Fnatic/Apex 350) | +| | +| Based on findings in ApexCtl by Audrius/tuxmark5, et. | +| al, https://github.com/tuxmark5/ApexCtl | +| | +| David Lee (RAMChYLD) 15 Nov 2020 | +| Based on work by B Horn (bahorn) 13 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "color32.h" +#include "SteelSeriesGeneric.h" + +/* Mode, we then use these to set actual effect based on speed. */ +enum +{ + STEELSERIES_OLDAPEX_DIRECT = 0x08, +}; + +/* Effects */ +enum +{ + STEELSERIES_OLDAPEX_EFFECT_DIRECT = 0x08, +}; + +class SteelSeriesOldApexController +{ +public: + SteelSeriesOldApexController + ( + hid_device* dev_handle, + steelseries_type proto_type, + const char* path, + std::string dev_name + ); + + ~SteelSeriesOldApexController(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + std::string GetSerialString(); + + steelseries_type GetKeyboardType(); + + void SetColorDetailed + ( + color32 qwerty, + color32 tenkey, + color32 functionkey, + color32 mxkey, + color32 logo + ); + + void DoUpdateLEDs(); + +private: + hid_device* dev; + std::string location; + std::string name; + steelseries_type proto; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesQCKMatController.cpp b/Controllers/SteelSeriesController/SteelSeriesQCKMatController.cpp deleted file mode 100644 index ea69cc79..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesQCKMatController.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/*-----------------------------------------*\ -| SteelSeriesQCKControllerMat.cpp | -| | -| Generic RGB Interface SteelSeriesQCK | -| Class | -| | -| Edbgon 22/05/2021 | -\*-----------------------------------------*/ - -#include "SteelSeriesQCKMatController.h" -#include - -SteelSeriesQCKMatController::SteelSeriesQCKMatController(hid_device* dev_handle, const char* path) -{ - dev = dev_handle; - location = path; -} - -SteelSeriesQCKMatController::~SteelSeriesQCKMatController() -{ - hid_close(dev); -} - -std::string SteelSeriesQCKMatController::GetDeviceLocation() -{ - return("HID: " + location); -} - -char* SteelSeriesQCKMatController::GetDeviceName() -{ - return device_name; -} - -std::string SteelSeriesQCKMatController::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 SteelSeriesQCKMatController::SetColors(std::vector colors) -{ - unsigned char buf[525]; - unsigned char cbuf[65]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(buf, 0x00, sizeof(buf)); - memset(cbuf, 0x00, sizeof(cbuf)); - - /*-----------------------------------------------------*\ - | Set up Direct packet | - \*-----------------------------------------------------*/ - buf[0x00] = 0x00; - buf[0x01] = 0x0E; - buf[0x03] = 0x02; - - buf[0x08] = 0xFF; - buf[0x09] = 0x32; - buf[0x0A] = 0xC8; - buf[0x0E] = 0x01; - - buf[0x14] = 0xFF; - buf[0x15] = 0x32; - buf[0x16] = 0xC8; - buf[0x19] = 0x01; - - buf[0x1A] = 0x01; - buf[0x1C] = 0x01; - - /*-----------------------------------------------------*\ - | Fill in color data | - \*-----------------------------------------------------*/ - buf[0x05] = RGBGetRValue(colors[0]); - buf[0x06] = RGBGetGValue(colors[0]); - buf[0x07] = RGBGetBValue(colors[0]); - - buf[0x11] = RGBGetRValue(colors[1]); - buf[0x12] = RGBGetGValue(colors[1]); - buf[0x13] = RGBGetBValue(colors[1]); - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_send_feature_report(dev, buf, 525); - - cbuf[0x01] = 0x0D; - hid_write(dev, cbuf, 65); -} diff --git a/Controllers/SteelSeriesController/SteelSeriesQCKMatController.h b/Controllers/SteelSeriesController/SteelSeriesQCKMatController.h deleted file mode 100644 index d1b5c74a..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesQCKMatController.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| SteelSeriesQCKControllerMat.h | -| | -| Generic RGB Interface SteelSeriesQCK | -| Class | -| | -| Edbgon 22/05/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include - -#pragma once - -class SteelSeriesQCKMatController -{ -public: - SteelSeriesQCKMatController(hid_device* dev_handle, const char* path); - - ~SteelSeriesQCKMatController(); - - std::string GetDeviceLocation(); - char* GetDeviceName(); - std::string GetSerialString(); - - void SetColors(std::vector colors); - -private: - char device_name[32]; - hid_device* dev; - std::string location; -}; diff --git a/Controllers/SteelSeriesController/SteelSeriesQCKMatController/RGBController_SteelSeriesQCKMat.cpp b/Controllers/SteelSeriesController/SteelSeriesQCKMatController/RGBController_SteelSeriesQCKMat.cpp new file mode 100644 index 00000000..4ab83e5e --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesQCKMatController/RGBController_SteelSeriesQCKMat.cpp @@ -0,0 +1,106 @@ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesQCKMat.cpp | +| | +| RGBController for SteelSeries Mouse | +| | +| Edbgon 22 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_SteelSeriesQCKMat.h" + +/**------------------------------------------------------------------*\ + @name Steel Series QCK Mat + @category Mousemat + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectSteelSeriesMousemat + @comment +\*-------------------------------------------------------------------*/ + +RGBController_SteelSeriesQCKMat::RGBController_SteelSeriesQCKMat(SteelSeriesQCKMatController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "SteelSeries"; + type = DEVICE_TYPE_MOUSEMAT; + description = "SteelSeries QCK Mat Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + SetupZones(); +} + +RGBController_SteelSeriesQCKMat::~RGBController_SteelSeriesQCKMat() +{ + delete controller; +} + +void RGBController_SteelSeriesQCKMat::SetupZones() +{ + /*---------------------------------------------------------*\ + | QCK has two zones | + \*---------------------------------------------------------*/ + zone mousemat_zone; + mousemat_zone.name = "Mousemat"; + mousemat_zone.type = ZONE_TYPE_SINGLE; + mousemat_zone.leds_min = 2; + mousemat_zone.leds_max = 2; + mousemat_zone.leds_count = 2; + mousemat_zone.matrix_map = NULL; + zones.push_back(mousemat_zone); + + led bot_led; + bot_led.name = "Mat Bottom LED"; + leds.push_back(bot_led); + + led top_led; + top_led.name = "Mat Top LED"; + leds.push_back(top_led); + + SetupColors(); +} + +void RGBController_SteelSeriesQCKMat::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_SteelSeriesQCKMat::DeviceUpdateLEDs() +{ + controller->SetColors(colors); +} + +void RGBController_SteelSeriesQCKMat::UpdateZoneLEDs(int /*zone*/) +{ + /*---------------------------------------------------------*\ + | Packet expects both LEDs | + \*---------------------------------------------------------*/ + DeviceUpdateLEDs(); +} + +void RGBController_SteelSeriesQCKMat::UpdateSingleLED(int /*led*/) +{ + /*---------------------------------------------------------*\ + | Packet expects both LEDs | + \*---------------------------------------------------------*/ + DeviceUpdateLEDs(); +} + +void RGBController_SteelSeriesQCKMat::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} diff --git a/Controllers/SteelSeriesController/SteelSeriesQCKMatController/RGBController_SteelSeriesQCKMat.h b/Controllers/SteelSeriesController/SteelSeriesQCKMatController/RGBController_SteelSeriesQCKMat.h new file mode 100644 index 00000000..11c7ee92 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesQCKMatController/RGBController_SteelSeriesQCKMat.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesQCKMat.h | +| | +| RGBController for SteelSeries Mouse | +| | +| Edbgon 22 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SteelSeriesQCKMatController.h" + +class RGBController_SteelSeriesQCKMat : public RGBController +{ +public: + RGBController_SteelSeriesQCKMat(SteelSeriesQCKMatController* controller_ptr); + ~RGBController_SteelSeriesQCKMat(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + SteelSeriesQCKMatController* controller; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesQCKMatController/SteelSeriesQCKMatController.cpp b/Controllers/SteelSeriesController/SteelSeriesQCKMatController/SteelSeriesQCKMatController.cpp new file mode 100644 index 00000000..42601f4a --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesQCKMatController/SteelSeriesQCKMatController.cpp @@ -0,0 +1,100 @@ +/*---------------------------------------------------------*\ +| SteelSeriesQCKControllerMat.cpp | +| | +| Driver for SteelSeries Mouse | +| | +| Edbgon 22 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "SteelSeriesQCKMatController.h" +#include "StringUtils.h" + +SteelSeriesQCKMatController::SteelSeriesQCKMatController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; +} + +SteelSeriesQCKMatController::~SteelSeriesQCKMatController() +{ + hid_close(dev); +} + +std::string SteelSeriesQCKMatController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string SteelSeriesQCKMatController::GetDeviceName() +{ + return(name); +} + +std::string SteelSeriesQCKMatController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void SteelSeriesQCKMatController::SetColors(std::vector colors) +{ + unsigned char buf[525]; + unsigned char cbuf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(buf, 0x00, sizeof(buf)); + memset(cbuf, 0x00, sizeof(cbuf)); + + /*-----------------------------------------------------*\ + | Set up Direct packet | + \*-----------------------------------------------------*/ + buf[0x00] = 0x00; + buf[0x01] = 0x0E; + buf[0x03] = 0x02; + + buf[0x08] = 0xFF; + buf[0x09] = 0x32; + buf[0x0A] = 0xC8; + buf[0x0E] = 0x01; + + buf[0x14] = 0xFF; + buf[0x15] = 0x32; + buf[0x16] = 0xC8; + buf[0x19] = 0x01; + + buf[0x1A] = 0x01; + buf[0x1C] = 0x01; + + /*-----------------------------------------------------*\ + | Fill in color data | + \*-----------------------------------------------------*/ + buf[0x05] = RGBGetRValue(colors[0]); + buf[0x06] = RGBGetGValue(colors[0]); + buf[0x07] = RGBGetBValue(colors[0]); + + buf[0x11] = RGBGetRValue(colors[1]); + buf[0x12] = RGBGetGValue(colors[1]); + buf[0x13] = RGBGetBValue(colors[1]); + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_send_feature_report(dev, buf, 525); + + cbuf[0x01] = 0x0D; + hid_write(dev, cbuf, 65); +} diff --git a/Controllers/SteelSeriesController/SteelSeriesQCKMatController/SteelSeriesQCKMatController.h b/Controllers/SteelSeriesController/SteelSeriesQCKMatController/SteelSeriesQCKMatController.h new file mode 100644 index 00000000..da6fcb2d --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesQCKMatController/SteelSeriesQCKMatController.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| SteelSeriesQCKControllerMat.h | +| | +| Driver for SteelSeries Mouse | +| | +| Edbgon 22 May 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +class SteelSeriesQCKMatController +{ +public: + SteelSeriesQCKMatController(hid_device* dev_handle, const char* path, std::string dev_name); + ~SteelSeriesQCKMatController(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + std::string GetSerialString(); + + void SetColors(std::vector colors); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesRival3Controller.cpp b/Controllers/SteelSeriesController/SteelSeriesRival3Controller.cpp deleted file mode 100644 index 1a49955b..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesRival3Controller.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/*-----------------------------------------*\ -| SteelSeriesRival3Controller.h | -| | -| Definitions and types for SteelSeries | -| Rival 3 lighting controller | -| | -| B Horn (bahorn) 29/8/2021 | -\*-----------------------------------------*/ - -#include "SteelSeriesRival3Controller.h" -#include -#include -#include - -SteelSeriesRival3Controller::SteelSeriesRival3Controller - ( - hid_device* dev_handle, - steelseries_type proto_type, - const char* path - ) : SteelSeriesMouseController(dev_handle, proto_type, path) -{ - //dev = dev_handle; - //location = path; - //proto = proto_type; -} - -SteelSeriesRival3Controller::~SteelSeriesRival3Controller() -{ - hid_close(dev); -} - -/* -std::string SteelSeriesRival3Controller::GetDeviceLocation() -{ - return("HID: " + location); -} - -char* SteelSeriesRival3Controller::GetDeviceName() -{ - return device_name; -} - -std::string SteelSeriesRival3Controller::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); -} -*/ - -std::string SteelSeriesRival3Controller::GetFirmwareVersion() -{ - const uint8_t FW_BUFFER_SIZE = 3; - uint8_t usb_buf[FW_BUFFER_SIZE] = { 0x00, 0x10, 0x00 }; - uint16_t version; - std::string return_string; - - hid_write(dev, usb_buf, FW_BUFFER_SIZE); - hid_read(dev, (unsigned char *)&version, 2); - - return_string = std::to_string(version); - return return_string; -} - -steelseries_mouse SteelSeriesRival3Controller::GetMouse() -{ - return rival_3; -} - -/* -steelseries_type SteelSeriesRival3Controller::GetMouseType() -{ - return proto; -} - -void SteelSeriesRival3Controller::Save() -{ - const uint8_t SAVE_BUFFER_SIZE = 10; - uint8_t usb_buf[SAVE_BUFFER_SIZE] = { 0x00, 0x09 }; - - hid_write(dev, usb_buf, SAVE_BUFFER_SIZE); -} -*/ - -void SteelSeriesRival3Controller::SetLightEffectAll(uint8_t effect) -{ - const uint8_t EFFECT_BUFFER_SIZE = 4; - uint8_t usb_buf[EFFECT_BUFFER_SIZE] = { 0x00, 0x06, 0x00, effect }; - - hid_write(dev, usb_buf, EFFECT_BUFFER_SIZE); -} - -void SteelSeriesRival3Controller::SetColor - ( - unsigned char zone_id, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char brightness - ) -{ - const uint8_t COLOR_BUFFER_SIZE = 8; - uint8_t usb_buf[COLOR_BUFFER_SIZE]; - - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0x05; - usb_buf[0x02] = 0x00; - usb_buf[0x03] = zone_id; - - usb_buf[0x04] = red; - usb_buf[0x05] = green; - usb_buf[0x06] = blue; - usb_buf[0x07] = brightness; - - hid_write(dev, usb_buf, COLOR_BUFFER_SIZE); -} diff --git a/Controllers/SteelSeriesController/SteelSeriesRival3Controller.h b/Controllers/SteelSeriesController/SteelSeriesRival3Controller.h deleted file mode 100644 index c3eb8713..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesRival3Controller.h +++ /dev/null @@ -1,76 +0,0 @@ -/*-----------------------------------------*\ -| SteelSeriesRival3Controller.h | -| | -| Definitions and types for SteelSeries | -| Rival 3 lighting controller | -| | -| B Horn (bahorn) 29/8/2021 | -\*-----------------------------------------*/ - -#include -#include - -#include "SteelSeriesGeneric.h" -#include "SteelSeriesMouseController.h" - -#pragma once - -//#define STEELSERIES_RIVAL_3_BRIGHTNESS_MAX 0x64 - -/*static const steelseries_mouse_led_info rival_3_leds[]= -{ - {"Front", 0x01}, - {"Middle", 0x02}, - {"Rear", 0x03}, - {"Logo", 0x04} -};*/ - -static const steelseries_mouse rival_3 = -{ - { 0x04, 0x03, 0x00, 0x05 }, - { - {"Front", 0x01}, - {"Middle", 0x02}, - {"Rear", 0x03}, - {"Logo", 0x04} - } -}; - -class SteelSeriesRival3Controller: public SteelSeriesMouseController -{ -public: - SteelSeriesRival3Controller - ( - hid_device* dev_handle, - steelseries_type proto_type, - const char* path - ); - - ~SteelSeriesRival3Controller(); - - //std::string GetDeviceLocation(); - //char* GetDeviceName(); - //std::string GetSerialString(); - std::string GetFirmwareVersion(); - steelseries_mouse GetMouse(); - //steelseries_type GetMouseType(); - - //void Save(); - - void SetLightEffectAll(uint8_t effect); - - void SetColor - ( - unsigned char zone_id, - unsigned char red, - unsigned char green, - unsigned char blue, - unsigned char brightness - ); - -private: - //char device_name[32]; - //hid_device* dev; - //std::string location; - //steelseries_type proto; -}; diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesRival3.cpp b/Controllers/SteelSeriesController/SteelSeriesRival3Controller/RGBController_SteelSeriesRival3.cpp similarity index 87% rename from Controllers/SteelSeriesController/RGBController_SteelSeriesRival3.cpp rename to Controllers/SteelSeriesController/SteelSeriesRival3Controller/RGBController_SteelSeriesRival3.cpp index 158ce973..0a6c4509 100644 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesRival3.cpp +++ b/Controllers/SteelSeriesController/SteelSeriesRival3Controller/RGBController_SteelSeriesRival3.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_SteelSeriesRival.cpp | -| | -| Generic RGB Interface SteelSeriesRival3 | -| Class | -| | -| B Horn (bahorn) 29/08/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesRival3.cpp | +| | +| RGBController for SteelSeries Rival 3 | +| | +| B Horn (bahorn) 29 Aug 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_SteelSeriesRival3.h" @@ -16,7 +18,7 @@ @save :white_check_mark: @direct :white_check_mark: @effects :white_check_mark: - @detectors DetectSteelSeriesRival3 + @detectors DetectSteelSeriesRival3,DetectSteelSeriesAerox3,DetectSteelSeriesAerox5,DetectSteelSeriesAerox9 @comment \*-------------------------------------------------------------------*/ @@ -24,7 +26,7 @@ RGBController_SteelSeriesRival3::RGBController_SteelSeriesRival3(SteelSeriesMous { controller = controller_ptr; - name = controller->GetDeviceName(); + name = controller->GetNameString(); vendor = "SteelSeries"; type = DEVICE_TYPE_MOUSE; description = "SteelSeries Mouse Device"; diff --git a/Controllers/SteelSeriesController/SteelSeriesRival3Controller/RGBController_SteelSeriesRival3.h b/Controllers/SteelSeriesController/SteelSeriesRival3Controller/RGBController_SteelSeriesRival3.h new file mode 100644 index 00000000..c4862e80 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesRival3Controller/RGBController_SteelSeriesRival3.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesRival3.h | +| | +| RGBController for SteelSeries Rival 3 | +| | +| B Horn (bahorn) 29 Aug 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SteelSeriesAerox3Controller.h" +#include "SteelSeriesRival3Controller.h" + +class RGBController_SteelSeriesRival3 : public RGBController +{ +public: + RGBController_SteelSeriesRival3(SteelSeriesMouseController* controller_ptr); + ~RGBController_SteelSeriesRival3(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + SteelSeriesMouseController* controller; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesRival3Controller/SteelSeriesRival3Controller.cpp b/Controllers/SteelSeriesController/SteelSeriesRival3Controller/SteelSeriesRival3Controller.cpp new file mode 100644 index 00000000..4f60c333 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesRival3Controller/SteelSeriesRival3Controller.cpp @@ -0,0 +1,77 @@ +/*---------------------------------------------------------*\ +| SteelSeriesRival3Controller.cpp | +| | +| Driver for SteelSeries Rival 3 | +| | +| B Horn (bahorn) 29 Aug 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include "SteelSeriesRival3Controller.h" + +SteelSeriesRival3Controller::SteelSeriesRival3Controller(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name) : SteelSeriesMouseController(dev_handle, proto_type, path, dev_name) +{ + +} + +SteelSeriesRival3Controller::~SteelSeriesRival3Controller() +{ + hid_close(dev); +} + +std::string SteelSeriesRival3Controller::GetFirmwareVersion() +{ + const uint8_t FW_BUFFER_SIZE = 3; + uint8_t usb_buf[FW_BUFFER_SIZE] = { 0x00, 0x10, 0x00 }; + uint16_t version; + std::string return_string; + + hid_write(dev, usb_buf, FW_BUFFER_SIZE); + hid_read(dev, (unsigned char *)&version, 2); + + return_string = std::to_string(version); + return return_string; +} + +steelseries_mouse SteelSeriesRival3Controller::GetMouse() +{ + return rival_3; +} + +void SteelSeriesRival3Controller::SetLightEffectAll(uint8_t effect) +{ + const uint8_t EFFECT_BUFFER_SIZE = 4; + uint8_t usb_buf[EFFECT_BUFFER_SIZE] = { 0x00, 0x06, 0x00, effect }; + + hid_write(dev, usb_buf, EFFECT_BUFFER_SIZE); +} + +void SteelSeriesRival3Controller::SetColor + ( + unsigned char zone_id, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char brightness + ) +{ + const uint8_t COLOR_BUFFER_SIZE = 8; + uint8_t usb_buf[COLOR_BUFFER_SIZE]; + + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x05; + usb_buf[0x02] = 0x00; + usb_buf[0x03] = zone_id; + + usb_buf[0x04] = red; + usb_buf[0x05] = green; + usb_buf[0x06] = blue; + usb_buf[0x07] = brightness; + + hid_write(dev, usb_buf, COLOR_BUFFER_SIZE); +} diff --git a/Controllers/SteelSeriesController/SteelSeriesRival3Controller/SteelSeriesRival3Controller.h b/Controllers/SteelSeriesController/SteelSeriesRival3Controller/SteelSeriesRival3Controller.h new file mode 100644 index 00000000..c431e9d7 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesRival3Controller/SteelSeriesRival3Controller.h @@ -0,0 +1,49 @@ +/*---------------------------------------------------------*\ +| SteelSeriesRival3Controller.h | +| | +| Driver for SteelSeries Rival 3 | +| | +| B Horn (bahorn) 29 Aug 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "SteelSeriesGeneric.h" +#include "SteelSeriesMouseController.h" + +static const steelseries_mouse rival_3 = +{ + { 0x04, 0x03, 0x00, 0x05 }, + { + {"Front", 0x01}, + {"Middle", 0x02}, + {"Rear", 0x03}, + {"Logo", 0x04} + } +}; + +class SteelSeriesRival3Controller: public SteelSeriesMouseController +{ +public: + SteelSeriesRival3Controller(hid_device* dev_handle, steelseries_type proto_type, const char* path, std::string dev_name); + ~SteelSeriesRival3Controller(); + + std::string GetFirmwareVersion(); + steelseries_mouse GetMouse(); + + void SetLightEffectAll(uint8_t effect); + + void SetColor + ( + unsigned char zone_id, + unsigned char red, + unsigned char green, + unsigned char blue, + unsigned char brightness + ); +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesRivalController.h b/Controllers/SteelSeriesController/SteelSeriesRivalController.h deleted file mode 100644 index 3b48cfd2..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesRivalController.h +++ /dev/null @@ -1,108 +0,0 @@ -/*-----------------------------------------*\ -| SteelSeriesRivalController.h | -| | -| Definitions and types for SteelSeries | -| Rival lighting controller | -| | -| B Horn (bahorn) 13/5/2020 | -\*-----------------------------------------*/ - -#include -#include - -#include "SteelSeriesGeneric.h" - -#pragma once - -/* Mode, we then use these to set actual effect based on speed. */ -enum -{ - STEELSERIES_RIVAL_DIRECT = 0x00, - STEELSERIES_RIVAL_PULSATE = 0x01 -}; - -/* Effects */ -enum -{ - STEELSERIES_RIVAL_EFFECT_DIRECT = 0x01, - STEELSERIES_RIVAL_EFFECT_PULSATE_MIN = 0x02, - STEELSERIES_RIVAL_EFFECT_PULSATE_MID = 0x03, - STEELSERIES_RIVAL_EFFECT_PULSATE_MAX = 0x04 -}; - -class SteelSeriesRivalController -{ -public: - SteelSeriesRivalController - ( - hid_device* dev_handle, - steelseries_type proto_type, - const char* path - ); - - ~SteelSeriesRivalController(); - - std::string GetDeviceLocation(); - char* GetDeviceName(); - std::string GetSerialString(); - std::string GetFirmwareVersion(); - - steelseries_type GetMouseType(); - - void SaveMode(); - - void SetLightEffect - ( - unsigned char zone_id, - unsigned char effect - ); - - void SetLightEffectAll - ( - unsigned char effect - ); - - void SetColor - ( - unsigned char zone_id, - unsigned char red, - unsigned char green, - unsigned char blue - ); - void SetColorAll - ( - unsigned char red, - unsigned char green, - unsigned char blue - ); - -private: - char device_name[32]; - hid_device* dev; - std::string location; - steelseries_type proto; - - void SetRival650Color - ( - unsigned char zone_id, - unsigned char red, - unsigned char green, - unsigned char blue - ); - - void SetRival600Color - ( - unsigned char zone_id, - unsigned char red, - unsigned char green, - unsigned char blue - ); - - void SetRival700Color - ( - unsigned char zone_id, - unsigned char red, - unsigned char green, - unsigned char blue - ); -}; diff --git a/Controllers/SteelSeriesController/RGBController_SteelSeriesRival.cpp b/Controllers/SteelSeriesController/SteelSeriesRivalController/RGBController_SteelSeriesRival.cpp similarity index 80% rename from Controllers/SteelSeriesController/RGBController_SteelSeriesRival.cpp rename to Controllers/SteelSeriesController/SteelSeriesRivalController/RGBController_SteelSeriesRival.cpp index d6f6be21..6308a4e3 100644 --- a/Controllers/SteelSeriesController/RGBController_SteelSeriesRival.cpp +++ b/Controllers/SteelSeriesController/SteelSeriesRivalController/RGBController_SteelSeriesRival.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_SteelSeriesRival.cpp | -| | -| Generic RGB Interface SteelSeriesRival | -| Class | -| | -| B Horn (bahorn) 13/05/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesRival.cpp | +| | +| RGBController for SteelSeries Rival | +| | +| B Horn (bahorn) 13 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_SteelSeriesRival.h" @@ -48,31 +50,31 @@ static const steelseries_rival_led_info rival_600_leds[]= RGBController_SteelSeriesRival::RGBController_SteelSeriesRival(SteelSeriesRivalController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = controller->GetDeviceName(); - vendor = "SteelSeries"; - type = DEVICE_TYPE_MOUSE; - description = "SteelSeries Rival Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); + name = controller->GetDeviceName(); + vendor = "SteelSeries"; + type = DEVICE_TYPE_MOUSE; + description = "SteelSeries Rival Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + version = controller->GetFirmwareVersion(); mode Direct; - Direct.name = "Direct"; - Direct.value = STEELSERIES_RIVAL_DIRECT; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = STEELSERIES_RIVAL_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); mode Pulsate; - Pulsate.name = "Pulsate"; - Pulsate.value = STEELSERIES_RIVAL_PULSATE; - Pulsate.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; - Pulsate.color_mode = MODE_COLORS_PER_LED; - Pulsate.speed_min = STEELSERIES_RIVAL_EFFECT_PULSATE_MIN; - Pulsate.speed_max = STEELSERIES_RIVAL_EFFECT_PULSATE_MAX; - Pulsate.speed = STEELSERIES_RIVAL_EFFECT_PULSATE_MID; + Pulsate.name = "Pulsate"; + Pulsate.value = STEELSERIES_RIVAL_PULSATE; + Pulsate.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_MANUAL_SAVE; + Pulsate.color_mode = MODE_COLORS_PER_LED; + Pulsate.speed_min = STEELSERIES_RIVAL_EFFECT_PULSATE_MIN; + Pulsate.speed_max = STEELSERIES_RIVAL_EFFECT_PULSATE_MAX; + Pulsate.speed = STEELSERIES_RIVAL_EFFECT_PULSATE_MID; modes.push_back(Pulsate); SetupZones(); diff --git a/Controllers/SteelSeriesController/SteelSeriesRivalController/RGBController_SteelSeriesRival.h b/Controllers/SteelSeriesController/SteelSeriesRivalController/RGBController_SteelSeriesRival.h new file mode 100644 index 00000000..600eb567 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesRivalController/RGBController_SteelSeriesRival.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesRival.h | +| | +| RGBController for SteelSeries Rival | +| | +| B Horn (bahorn) 13 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SteelSeriesRivalController.h" + +class RGBController_SteelSeriesRival : public RGBController +{ +public: + RGBController_SteelSeriesRival(SteelSeriesRivalController* controller_ptr); + ~RGBController_SteelSeriesRival(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + void DeviceSaveMode(); + +private: + SteelSeriesRivalController* controller; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesRivalController.cpp b/Controllers/SteelSeriesController/SteelSeriesRivalController/SteelSeriesRivalController.cpp similarity index 78% rename from Controllers/SteelSeriesController/SteelSeriesRivalController.cpp rename to Controllers/SteelSeriesController/SteelSeriesRivalController/SteelSeriesRivalController.cpp index 367e9175..24526a09 100644 --- a/Controllers/SteelSeriesController/SteelSeriesRivalController.cpp +++ b/Controllers/SteelSeriesController/SteelSeriesRivalController/SteelSeriesRivalController.cpp @@ -1,30 +1,33 @@ -/*-----------------------------------------*\ -| SteelSeriesRivalController.h | -| | -| Definitions and types for SteelSeries | -| Rival lighting controller | -| | -| B Horn (bahorn) 13/5/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| SteelSeriesRivalController.cpp | +| | +| Driver for SteelSeries Rival | +| | +| B Horn (bahorn) 13 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "SteelSeriesRivalController.h" +#include #include #include #include -#include +#include "SteelSeriesRivalController.h" +#include "StringUtils.h" -static void send_usb_msg(hid_device* dev, char * data_pkt, unsigned int size) +static void send_usb_msg(hid_device* dev, unsigned char * data_pkt, unsigned int size) { - char* usb_pkt = new char[size + 1]; - + unsigned char* usb_pkt = new unsigned char[size + 1]; + usb_pkt[0] = 0x00; for(unsigned int i = 1; i < size + 1; i++) { usb_pkt[i] = data_pkt[i-1]; } - - hid_write(dev, (unsigned char *)usb_pkt, size + 1); - + + hid_write(dev, usb_pkt, size + 1); + delete[] usb_pkt; } @@ -32,11 +35,13 @@ SteelSeriesRivalController::SteelSeriesRivalController ( hid_device* dev_handle, steelseries_type proto_type, - const char* path + const char* path, + std::string dev_name ) { dev = dev_handle; location = path; + name = dev_name; proto = proto_type; } @@ -50,32 +55,29 @@ std::string SteelSeriesRivalController::GetDeviceLocation() return("HID: " + location); } -char* SteelSeriesRivalController::GetDeviceName() +std::string SteelSeriesRivalController::GetDeviceName() { - return device_name; + return(name); } std::string SteelSeriesRivalController::GetSerialString() { wchar_t serial_string[128]; int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if (ret != 0) + + if(ret != 0) { return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } std::string SteelSeriesRivalController::GetFirmwareVersion() { if (proto != RIVAL_300 && proto != RIVAL_700) return ""; - char usb_buf[2] = { 0x10, 0x00 }; + unsigned char usb_buf[2] = { 0x10, 0x00 }; uint16_t version; std::string return_string; @@ -94,7 +96,7 @@ steelseries_type SteelSeriesRivalController::GetMouseType() /* Saves to the internal configuration */ void SteelSeriesRivalController::SaveMode() { - char usb_buf[9]; + unsigned char usb_buf[9]; memset(usb_buf, 0x00, sizeof(usb_buf)); usb_buf[0x00] = 0x09; send_usb_msg(dev, usb_buf, 9); @@ -106,9 +108,10 @@ void SteelSeriesRivalController::SetLightEffect unsigned char effect ) { - char usb_buf[9]; + unsigned char usb_buf[9]; memset(usb_buf, 0x00, sizeof(usb_buf)); - switch (proto) + + switch(proto) { case RIVAL_100: usb_buf[0x00] = 0x07; @@ -166,7 +169,7 @@ void SteelSeriesRivalController::SetRival650Color unsigned char blue ) { - char usb_buf[60]; + unsigned char usb_buf[60]; memset(usb_buf, 0x00, sizeof(usb_buf)); @@ -247,7 +250,7 @@ void SteelSeriesRivalController::SetRival700Color { const uint16_t REPORT_SIZE = 578; - uint8_t usb_buf[REPORT_SIZE]; + unsigned char usb_buf[REPORT_SIZE]; memset(usb_buf, 0x00, sizeof(usb_buf)); usb_buf[0x00] = 0x05; @@ -260,7 +263,7 @@ void SteelSeriesRivalController::SetRival700Color usb_buf[0x0b] = zone_id; usb_buf[0x0c] = 0x01; - char *usb_pkt = new char[REPORT_SIZE + 1]; + unsigned char *usb_pkt = new unsigned char[REPORT_SIZE + 1]; usb_pkt[0] = 0x00; for (unsigned int i = 1; i < REPORT_SIZE + 1; i++) @@ -268,7 +271,7 @@ void SteelSeriesRivalController::SetRival700Color usb_pkt[i] = usb_buf[i - 1]; } - hid_send_feature_report(dev, (unsigned char *)usb_pkt, REPORT_SIZE + 1); + hid_send_feature_report(dev, usb_pkt, REPORT_SIZE + 1); delete[] usb_pkt; } @@ -281,9 +284,10 @@ void SteelSeriesRivalController::SetColor unsigned char blue ) { - char usb_buf[9]; + unsigned char usb_buf[9]; memset(usb_buf, 0x00, sizeof(usb_buf)); - switch (proto) + + switch(proto) { case RIVAL_100: usb_buf[0x00] = 0x05; @@ -347,4 +351,3 @@ void SteelSeriesRivalController::SetColorAll break; } } - diff --git a/Controllers/SteelSeriesController/SteelSeriesRivalController/SteelSeriesRivalController.h b/Controllers/SteelSeriesController/SteelSeriesRivalController/SteelSeriesRivalController.h new file mode 100644 index 00000000..e48000a2 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesRivalController/SteelSeriesRivalController.h @@ -0,0 +1,110 @@ +/*---------------------------------------------------------*\ +| SteelSeriesRivalController.h | +| | +| Driver for SteelSeries Rival | +| | +| B Horn (bahorn) 13 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "SteelSeriesGeneric.h" + +/* Mode, we then use these to set actual effect based on speed. */ +enum +{ + STEELSERIES_RIVAL_DIRECT = 0x00, + STEELSERIES_RIVAL_PULSATE = 0x01 +}; + +/* Effects */ +enum +{ + STEELSERIES_RIVAL_EFFECT_DIRECT = 0x01, + STEELSERIES_RIVAL_EFFECT_PULSATE_MIN = 0x02, + STEELSERIES_RIVAL_EFFECT_PULSATE_MID = 0x03, + STEELSERIES_RIVAL_EFFECT_PULSATE_MAX = 0x04 +}; + +class SteelSeriesRivalController +{ +public: + SteelSeriesRivalController + ( + hid_device* dev_handle, + steelseries_type proto_type, + const char* path, + std::string dev_name + ); + + ~SteelSeriesRivalController(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + std::string GetSerialString(); + std::string GetFirmwareVersion(); + + steelseries_type GetMouseType(); + + void SaveMode(); + + void SetLightEffect + ( + unsigned char zone_id, + unsigned char effect + ); + + void SetLightEffectAll + ( + unsigned char effect + ); + + void SetColor + ( + unsigned char zone_id, + unsigned char red, + unsigned char green, + unsigned char blue + ); + void SetColorAll + ( + unsigned char red, + unsigned char green, + unsigned char blue + ); + +private: + hid_device* dev; + std::string location; + std::string name; + steelseries_type proto; + + void SetRival650Color + ( + unsigned char zone_id, + unsigned char red, + unsigned char green, + unsigned char blue + ); + + void SetRival600Color + ( + unsigned char zone_id, + unsigned char red, + unsigned char green, + unsigned char blue + ); + + void SetRival700Color + ( + unsigned char zone_id, + unsigned char red, + unsigned char green, + unsigned char blue + ); +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesSenseiController.h b/Controllers/SteelSeriesController/SteelSeriesSenseiController.h deleted file mode 100644 index 6c533989..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesSenseiController.h +++ /dev/null @@ -1,99 +0,0 @@ -/*-----------------------------------------*\ -| SteelSeriesSenseiController.h | -| | -| Definitions and types for SteelSeries | -| Sensei lighting controller | -| Based on Rival controller by | -| B Horn (bahorn) 13/5/2020 | -\*-----------------------------------------*/ - -#include -#include - -#include "SteelSeriesGeneric.h" - -#pragma once - -/*-------------------------------------------------------------*\ -| Mode, we then use these to set actual effect based on speed. | -\*-------------------------------------------------------------*/ -enum -{ - STEELSERIES_SENSEI_MODE_DIRECT = 0x00, - STEELSERIES_SENSEI_MODE_BREATHING = 0x01, - STEELSERIES_SENSEI_MODE_RAINBOW = 0x02 -}; - -/*-------------------------------------------------------------*\ -| Effects | -\*-------------------------------------------------------------*/ -enum -{ - STEELSERIES_SENSEI_EFFECT_DIRECT = 0x01, - STEELSERIES_SENSEI_EFFECT_BREATHING_MIN = 0x02, - STEELSERIES_SENSEI_EFFECT_BREATHING_MID = 0x03, - STEELSERIES_SENSEI_EFFECT_BREATHING_MAX = 0x04, - STEELSERIES_SENSEI_EFFECT_RAINBOW_MIN = 0x05, - STEELSERIES_SENSEI_EFFECT_RAINBOW_MID = 0x06, - STEELSERIES_SENSEI_EFFECT_RAINBOW_MAX = 0x07 -}; - -class SteelSeriesSenseiController -{ -public: - SteelSeriesSenseiController - ( - hid_device* dev_handle, - steelseries_type proto_type, - const char* path - ); - - ~SteelSeriesSenseiController(); - - std::string GetDeviceLocation(); - char* GetDeviceName(); - std::string GetSerialString(); - - steelseries_type GetMouseType(); - - void Save(); - - void SetLightEffect - ( - unsigned char zone_id, - unsigned char effect, - unsigned char speed, - unsigned char red, - unsigned char green, - unsigned char blue - ); - - void SetLightEffectAll - ( - unsigned char effect, - unsigned char speed, - unsigned char red, - unsigned char green, - unsigned char blue - ); - - void SetColor - ( - unsigned char zone_id, - unsigned char red, - unsigned char green, - unsigned char blue - ); - void SetColorAll - ( - unsigned char red, - unsigned char green, - unsigned char blue - ); - -private: - char device_name[32]; - hid_device* dev; - std::string location; - steelseries_type proto; -}; diff --git a/Controllers/SteelSeriesController/SteelSeriesSenseiController/RGBController_SteelSeriesSensei.cpp b/Controllers/SteelSeriesController/SteelSeriesSenseiController/RGBController_SteelSeriesSensei.cpp new file mode 100644 index 00000000..99722356 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesSenseiController/RGBController_SteelSeriesSensei.cpp @@ -0,0 +1,152 @@ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesSensei.cpp | +| | +| RGBController for SteelSeries Sensei | +| | +| Based on SteelSeries Rival controller | +| B Horn (bahorn) 13 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_SteelSeriesSensei.h" + +/**------------------------------------------------------------------*\ + @name Steel Series Sensei + @category Mouse + @type USB + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectSteelSeriesSensei + @comment +\*-------------------------------------------------------------------*/ + +RGBController_SteelSeriesSensei::RGBController_SteelSeriesSensei(SteelSeriesSenseiController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "SteelSeries"; + type = DEVICE_TYPE_MOUSE; + description = "SteelSeries Sensei Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = STEELSERIES_SENSEI_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = STEELSERIES_SENSEI_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR; + Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.speed_min = STEELSERIES_SENSEI_EFFECT_BREATHING_MIN; + Breathing.speed_max = STEELSERIES_SENSEI_EFFECT_BREATHING_MAX; + Breathing.speed = STEELSERIES_SENSEI_EFFECT_BREATHING_MID; + modes.push_back(Breathing); + + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = STEELSERIES_SENSEI_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_SPEED; + Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.speed_min = STEELSERIES_SENSEI_EFFECT_RAINBOW_MIN; + Rainbow.speed_max = STEELSERIES_SENSEI_EFFECT_RAINBOW_MAX; + Rainbow.speed = STEELSERIES_SENSEI_EFFECT_RAINBOW_MID; + modes.push_back(Rainbow); + + SetupZones(); +} + +RGBController_SteelSeriesSensei::~RGBController_SteelSeriesSensei() +{ + delete controller; +} + +void RGBController_SteelSeriesSensei::SetupZones() +{ + zone logo_zone; + logo_zone.name = "Logo"; + logo_zone.type = ZONE_TYPE_SINGLE; + logo_zone.leds_min = 1; + logo_zone.leds_max = 1; + logo_zone.leds_count = 1; + logo_zone.matrix_map = NULL; + zones.push_back(logo_zone); + + led logo_led; + logo_led.name = "Logo"; + leds.push_back(logo_led); + + zone wheel_zone; + wheel_zone.name = "Scroll Wheel"; + wheel_zone.type = ZONE_TYPE_SINGLE; + wheel_zone.leds_min = 1; + wheel_zone.leds_max = 1; + wheel_zone.leds_count = 1; + wheel_zone.matrix_map = NULL; + zones.push_back(wheel_zone); + + led wheel_led; + wheel_led.name = "Scroll Wheel"; + leds.push_back(wheel_led); + + SetupColors(); +} + +void RGBController_SteelSeriesSensei::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_SteelSeriesSensei::DeviceUpdateLEDs() +{ + UpdateZoneLEDs(0); + UpdateZoneLEDs(1); +} + +void RGBController_SteelSeriesSensei::UpdateZoneLEDs(int zone) +{ + RGBColor color = colors[zone]; + unsigned char red = RGBGetRValue(color); + unsigned char grn = RGBGetGValue(color); + unsigned char blu = RGBGetBValue(color); + + switch(modes[active_mode].value) + { + case STEELSERIES_SENSEI_MODE_DIRECT: + controller->SetColor(zone, red, grn, blu); + break; + + case STEELSERIES_SENSEI_MODE_BREATHING: + case STEELSERIES_SENSEI_MODE_RAINBOW: + controller->SetLightEffect(zone, modes[active_mode].value, modes[active_mode].speed, red, grn, blu); + break; + } +} + +void RGBController_SteelSeriesSensei::UpdateSingleLED(int led) +{ + /*---------------------------------------------------------*\ + | Each zone only has a single LED, so we can use the LED ID | + | to reference the existing zone code. | + \*---------------------------------------------------------*/ + UpdateZoneLEDs(led); +} + +void RGBController_SteelSeriesSensei::DeviceUpdateMode() +{ + /*---------------------------------------------------------*\ + | Strictly, the device actually does support different modes| + | for the different zones, but we don't support that. | + \*---------------------------------------------------------*/ + DeviceUpdateLEDs(); +} diff --git a/Controllers/SteelSeriesController/SteelSeriesSenseiController/RGBController_SteelSeriesSensei.h b/Controllers/SteelSeriesController/SteelSeriesSenseiController/RGBController_SteelSeriesSensei.h new file mode 100644 index 00000000..ed09f551 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesSenseiController/RGBController_SteelSeriesSensei.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesSensei.h | +| | +| RGBController for SteelSeries Sensei | +| | +| Based on SteelSeries Rival controller | +| B Horn (bahorn) 13 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SteelSeriesSenseiController.h" + +class RGBController_SteelSeriesSensei : public RGBController +{ +public: + RGBController_SteelSeriesSensei(SteelSeriesSenseiController* controller_ptr); + ~RGBController_SteelSeriesSensei(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + SteelSeriesSenseiController* controller; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesSenseiController.cpp b/Controllers/SteelSeriesController/SteelSeriesSenseiController/SteelSeriesSenseiController.cpp similarity index 86% rename from Controllers/SteelSeriesController/SteelSeriesSenseiController.cpp rename to Controllers/SteelSeriesController/SteelSeriesSenseiController/SteelSeriesSenseiController.cpp index c469f387..97955435 100644 --- a/Controllers/SteelSeriesController/SteelSeriesSenseiController.cpp +++ b/Controllers/SteelSeriesController/SteelSeriesSenseiController/SteelSeriesSenseiController.cpp @@ -1,20 +1,24 @@ -/*-----------------------------------------*\ -| SteelSeriesSenseiController.h | -| | -| Definitions and types for SteelSeries | -| Sensei lighting controller | -| Based on Rival controller by | -| B Horn (bahorn) 13/5/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| SteelSeriesSenseiController.cpp | +| | +| Driver for SteelSeries Sensei | +| | +| Based on SteelSeries Rival controller | +| B Horn (bahorn) 13 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "SteelSeriesSenseiController.h" #include #include #include +#include "SteelSeriesSenseiController.h" +#include "StringUtils.h" -static void send_usb_msg(hid_device* dev, char * data_pkt, unsigned int size) +static void send_usb_msg(hid_device* dev, unsigned char * data_pkt, unsigned int size) { - char* usb_pkt = new char[size + 1]; + unsigned char* usb_pkt = new unsigned char[size + 1]; usb_pkt[0] = 0x00; for(unsigned int i = 1; i < size + 1; i++) @@ -22,7 +26,7 @@ static void send_usb_msg(hid_device* dev, char * data_pkt, unsigned int size) usb_pkt[i] = data_pkt[i-1]; } - hid_write(dev, (unsigned char *)usb_pkt, size + 1); + hid_write(dev, usb_pkt, size + 1); delete[] usb_pkt; } @@ -31,11 +35,13 @@ SteelSeriesSenseiController::SteelSeriesSenseiController ( hid_device* dev_handle, steelseries_type proto_type, - const char* path + const char* path, + std::string dev_name ) { dev = dev_handle; location = path; + name = dev_name; proto = proto_type; } @@ -49,24 +55,22 @@ std::string SteelSeriesSenseiController::GetDeviceLocation() return("HID: " + location); } -char* SteelSeriesSenseiController::GetDeviceName() +std::string SteelSeriesSenseiController::GetDeviceName() { - return device_name; + return(name); } std::string SteelSeriesSenseiController::GetSerialString() { wchar_t serial_string[128]; int ret = hid_get_serial_number_string(dev, serial_string, 128); - if (ret != 0) + + if(ret != 0) { return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } steelseries_type SteelSeriesSenseiController::GetMouseType() @@ -80,7 +84,7 @@ void SteelSeriesSenseiController::Save() /*-----------------------------------------------------*\ | Saves to the internal configuration | \*-----------------------------------------------------*/ - char usb_buf[9]; + unsigned char usb_buf[9]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -109,7 +113,7 @@ void SteelSeriesSenseiController::SetLightEffect unsigned char blue ) { - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -119,8 +123,8 @@ void SteelSeriesSenseiController::SetLightEffect /*-----------------------------------------------------*\ | Set up Light Effect packet | \*-----------------------------------------------------*/ - char dur1 = 0x27; - char dur2 = 0x10; //10 sec cycle + unsigned char dur1 = 0x27; + unsigned char dur2 = 0x10; //10 sec cycle switch(effect) { @@ -248,7 +252,7 @@ void SteelSeriesSenseiController::SetColor unsigned char blue ) { - char usb_buf[65]; + unsigned char usb_buf[65]; /*-----------------------------------------------------*\ | Zero out buffer | @@ -291,4 +295,3 @@ void SteelSeriesSenseiController::SetColorAll SetColor(0, red, green, blue); SetColor(1, red, green, blue); } - diff --git a/Controllers/SteelSeriesController/SteelSeriesSenseiController/SteelSeriesSenseiController.h b/Controllers/SteelSeriesController/SteelSeriesSenseiController/SteelSeriesSenseiController.h new file mode 100644 index 00000000..56c08c30 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesSenseiController/SteelSeriesSenseiController.h @@ -0,0 +1,103 @@ +/*---------------------------------------------------------*\ +| SteelSeriesSenseiController.h | +| | +| Driver for SteelSeries Sensei | +| | +| Based on SteelSeries Rival controller | +| B Horn (bahorn) 13 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "SteelSeriesGeneric.h" + +/*-------------------------------------------------------------*\ +| Mode, we then use these to set actual effect based on speed. | +\*-------------------------------------------------------------*/ +enum +{ + STEELSERIES_SENSEI_MODE_DIRECT = 0x00, + STEELSERIES_SENSEI_MODE_BREATHING = 0x01, + STEELSERIES_SENSEI_MODE_RAINBOW = 0x02 +}; + +/*-------------------------------------------------------------*\ +| Effects | +\*-------------------------------------------------------------*/ +enum +{ + STEELSERIES_SENSEI_EFFECT_DIRECT = 0x01, + STEELSERIES_SENSEI_EFFECT_BREATHING_MIN = 0x02, + STEELSERIES_SENSEI_EFFECT_BREATHING_MID = 0x03, + STEELSERIES_SENSEI_EFFECT_BREATHING_MAX = 0x04, + STEELSERIES_SENSEI_EFFECT_RAINBOW_MIN = 0x05, + STEELSERIES_SENSEI_EFFECT_RAINBOW_MID = 0x06, + STEELSERIES_SENSEI_EFFECT_RAINBOW_MAX = 0x07 +}; + +class SteelSeriesSenseiController +{ +public: + SteelSeriesSenseiController + ( + hid_device* dev_handle, + steelseries_type proto_type, + const char* path, + std::string dev_name + ); + + ~SteelSeriesSenseiController(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + std::string GetSerialString(); + + steelseries_type GetMouseType(); + + void Save(); + + void SetLightEffect + ( + unsigned char zone_id, + unsigned char effect, + unsigned char speed, + unsigned char red, + unsigned char green, + unsigned char blue + ); + + void SetLightEffectAll + ( + unsigned char effect, + unsigned char speed, + unsigned char red, + unsigned char green, + unsigned char blue + ); + + void SetColor + ( + unsigned char zone_id, + unsigned char red, + unsigned char green, + unsigned char blue + ); + + void SetColorAll + ( + unsigned char red, + unsigned char green, + unsigned char blue + ); + +private: + hid_device* dev; + std::string location; + std::string name; + steelseries_type proto; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesSiberiaController.cpp b/Controllers/SteelSeriesController/SteelSeriesSiberiaController.cpp deleted file mode 100644 index cca454ae..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesSiberiaController.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/*-----------------------------------------*\ -| SteelSeriesSiberiaController.cpp | -| | -| Definitions and types for SteelSeries | -| Siberia lighting controller | -| | -| E Karlsson (pilophae) 18/6/2020 | -| -\*-----------------------------------------*/ - -#include "SteelSeriesSiberiaController.h" -#include - -static void send_usb_msg(hid_device* dev, char * data_pkt, unsigned int size) -{ - unsigned char usb_pkt[16]; - memset(usb_pkt, 0x00, sizeof(usb_pkt)); - - // Report number - usb_pkt[0] = 0x01; - // Magic - usb_pkt[1] = 0x00; - // Command - usb_pkt[2] = data_pkt[0]; - // Payload length - usb_pkt[3] = size - 1; - - for(unsigned int i = 0; i < (size - 1); i++) - { - usb_pkt[4 + i] = data_pkt[1 + i]; - } - - hid_write(dev, usb_pkt, 16); -} - -SteelSeriesSiberiaController::SteelSeriesSiberiaController - ( - hid_device* dev_handle, - const char* path - ) -{ - dev = dev_handle; - location = path; -} - -SteelSeriesSiberiaController::~SteelSeriesSiberiaController() -{ - hid_close(dev); -} - -std::string SteelSeriesSiberiaController::GetDeviceLocation() -{ - return("HID: " + location); -} - -char* SteelSeriesSiberiaController::GetDeviceName() -{ - return device_name; -} - -std::string SteelSeriesSiberiaController::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 SteelSeriesSiberiaController::SetColor - ( - unsigned char red, - unsigned char green, - unsigned char blue - ) -{ - char usb_buf[4]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - - // Command 1 - usb_buf[0] = 0x95; - usb_buf[1] = 0x80; - usb_buf[2] = 0xbf; - send_usb_msg(dev, usb_buf, 3); - - // Command 2 - memset(usb_buf, 0x00, sizeof(usb_buf)); - usb_buf[0] = 0x80; - usb_buf[1] = 0x52; - usb_buf[2] = 0x20; - send_usb_msg(dev, usb_buf, 3); - - // Command 3 (Set color) - memset(usb_buf, 0x00, sizeof(usb_buf)); - usb_buf[0] = 0x83; - usb_buf[1] = red; - usb_buf[2] = green; - usb_buf[3] = blue; - send_usb_msg(dev, usb_buf, 4); - - // Command 4 - memset(usb_buf, 0x00, sizeof(usb_buf)); - usb_buf[0] = 0x93; - usb_buf[1] = 0x03; - usb_buf[2] = 0x80; - send_usb_msg(dev, usb_buf, 3); -} diff --git a/Controllers/SteelSeriesController/SteelSeriesSiberiaController.h b/Controllers/SteelSeriesController/SteelSeriesSiberiaController.h deleted file mode 100644 index 8b872b85..00000000 --- a/Controllers/SteelSeriesController/SteelSeriesSiberiaController.h +++ /dev/null @@ -1,41 +0,0 @@ -/*-----------------------------------------*\ -| SteelSeriesSiberiaController.h | -| | -| Definitions and types for SteelSeries | -| Siberia lighting controller | -| | -| E Karlsson (pilophae) 18/6/2020 | -\*-----------------------------------------*/ - -#include -#include - -#pragma once - -class SteelSeriesSiberiaController -{ -public: - SteelSeriesSiberiaController - ( - hid_device* dev_handle, - const char* path - ); - - ~SteelSeriesSiberiaController(); - - std::string GetDeviceLocation(); - char* GetDeviceName(); - std::string GetSerialString(); - - void SetColor - ( - unsigned char red, - unsigned char green, - unsigned char blue - ); - -private: - char device_name[32]; - hid_device* dev; - std::string location; -}; diff --git a/Controllers/SteelSeriesController/SteelSeriesSiberiaController/RGBController_SteelSeriesSiberia.cpp b/Controllers/SteelSeriesController/SteelSeriesSiberiaController/RGBController_SteelSeriesSiberia.cpp new file mode 100644 index 00000000..9c526ce6 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesSiberiaController/RGBController_SteelSeriesSiberia.cpp @@ -0,0 +1,103 @@ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesSiberia.cpp | +| | +| RGBController for SteelSeries Siberia | +| | +| E Karlsson (pilophae) 18 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_SteelSeriesSiberia.h" + +/**------------------------------------------------------------------*\ + @name Steel Series Siberia + @category Headset + @type USB + @save :x: + @direct :x: + @effects :white_check_mark: + @detectors DetectSteelSeriesHeadset + @comment +\*-------------------------------------------------------------------*/ + +RGBController_SteelSeriesSiberia::RGBController_SteelSeriesSiberia(SteelSeriesSiberiaController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetDeviceName(); + vendor = "SteelSeries"; + type = DEVICE_TYPE_HEADSET; + description = "SteelSeries Siberia Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Static; + Static.name = "Static"; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Static.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Static); + + SetupZones(); +} + +RGBController_SteelSeriesSiberia::~RGBController_SteelSeriesSiberia() +{ + delete controller; +} + +void RGBController_SteelSeriesSiberia::SetupZones() +{ + /* Siberia 350 only has one Zone */ + zone earpiece_zone; + earpiece_zone.name = "Headset"; + earpiece_zone.type = ZONE_TYPE_SINGLE; + earpiece_zone.leds_min = 1; + earpiece_zone.leds_max = 1; + earpiece_zone.leds_count = 1; + earpiece_zone.matrix_map = NULL; + zones.push_back(earpiece_zone); + + led earpiece_led; + earpiece_led.name = "Headset LED"; + leds.push_back(earpiece_led); + + SetupColors(); +} + +void RGBController_SteelSeriesSiberia::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_SteelSeriesSiberia::DeviceUpdateLEDs() +{ + unsigned char red = RGBGetRValue(colors[0]); + unsigned char grn = RGBGetGValue(colors[0]); + unsigned char blu = RGBGetBValue(colors[0]); + controller->SetColor(red, grn, blu); +} + +void RGBController_SteelSeriesSiberia::UpdateZoneLEDs(int zone) +{ + RGBColor color = colors[zone]; + unsigned char red = RGBGetRValue(color); + unsigned char grn = RGBGetGValue(color); + unsigned char blu = RGBGetBValue(color); + controller->SetColor(red, grn, blu); +} + +void RGBController_SteelSeriesSiberia::UpdateSingleLED(int led) +{ + /* Each zone only has a single LED, so we can use the LED ID to reference + * the existing zone code. */ + UpdateZoneLEDs(led); +} + +void RGBController_SteelSeriesSiberia::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} diff --git a/Controllers/SteelSeriesController/SteelSeriesSiberiaController/RGBController_SteelSeriesSiberia.h b/Controllers/SteelSeriesController/SteelSeriesSiberiaController/RGBController_SteelSeriesSiberia.h new file mode 100644 index 00000000..a17d566d --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesSiberiaController/RGBController_SteelSeriesSiberia.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_SteelSeriesSiberia.h | +| | +| RGBController for SteelSeries Siberia | +| | +| E Karlsson (pilophae) 18 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "SteelSeriesSiberiaController.h" + +class RGBController_SteelSeriesSiberia : public RGBController +{ +public: + RGBController_SteelSeriesSiberia(SteelSeriesSiberiaController* controller_ptr); + ~RGBController_SteelSeriesSiberia(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + SteelSeriesSiberiaController* controller; +}; diff --git a/Controllers/SteelSeriesController/SteelSeriesSiberiaController/SteelSeriesSiberiaController.cpp b/Controllers/SteelSeriesController/SteelSeriesSiberiaController/SteelSeriesSiberiaController.cpp new file mode 100644 index 00000000..85198811 --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesSiberiaController/SteelSeriesSiberiaController.cpp @@ -0,0 +1,105 @@ +/*---------------------------------------------------------*\ +| SteelSeriesSiberiaController.cpp | +| | +| Driver for SteelSeries Siberia | +| | +| E Karlsson (pilophae) 18 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "SteelSeriesSiberiaController.h" +#include "StringUtils.h" + +static void send_usb_msg(hid_device* dev, unsigned char * data_pkt, unsigned int size) +{ + unsigned char usb_pkt[16]; + memset(usb_pkt, 0x00, sizeof(usb_pkt)); + + // Report number + usb_pkt[0] = 0x01; + // Magic + usb_pkt[1] = 0x00; + // Command + usb_pkt[2] = data_pkt[0]; + // Payload length + usb_pkt[3] = size - 1; + + for(unsigned int i = 0; i < (size - 1); i++) + { + usb_pkt[4 + i] = data_pkt[1 + i]; + } + + hid_write(dev, usb_pkt, 16); +} + +SteelSeriesSiberiaController::SteelSeriesSiberiaController(hid_device* dev_handle, const char* path, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; +} + +SteelSeriesSiberiaController::~SteelSeriesSiberiaController() +{ + hid_close(dev); +} + +std::string SteelSeriesSiberiaController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string SteelSeriesSiberiaController::GetDeviceName() +{ + return(name); +} + +std::string SteelSeriesSiberiaController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void SteelSeriesSiberiaController::SetColor(unsigned char red, unsigned char green, unsigned char blue) +{ + unsigned char usb_buf[4]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + + // Command 1 + usb_buf[0] = 0x95; + usb_buf[1] = 0x80; + usb_buf[2] = 0xbf; + send_usb_msg(dev, usb_buf, 3); + + // Command 2 + memset(usb_buf, 0x00, sizeof(usb_buf)); + usb_buf[0] = 0x80; + usb_buf[1] = 0x52; + usb_buf[2] = 0x20; + send_usb_msg(dev, usb_buf, 3); + + // Command 3 (Set color) + memset(usb_buf, 0x00, sizeof(usb_buf)); + usb_buf[0] = 0x83; + usb_buf[1] = red; + usb_buf[2] = green; + usb_buf[3] = blue; + send_usb_msg(dev, usb_buf, 4); + + // Command 4 + memset(usb_buf, 0x00, sizeof(usb_buf)); + usb_buf[0] = 0x93; + usb_buf[1] = 0x03; + usb_buf[2] = 0x80; + send_usb_msg(dev, usb_buf, 3); +} diff --git a/Controllers/SteelSeriesController/SteelSeriesSiberiaController/SteelSeriesSiberiaController.h b/Controllers/SteelSeriesController/SteelSeriesSiberiaController/SteelSeriesSiberiaController.h new file mode 100644 index 00000000..7aabc54c --- /dev/null +++ b/Controllers/SteelSeriesController/SteelSeriesSiberiaController/SteelSeriesSiberiaController.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------*\ +| SteelSeriesSiberiaController.h | +| | +| Driver for SteelSeries Siberia | +| | +| E Karlsson (pilophae) 18 Jun 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include + +class SteelSeriesSiberiaController +{ +public: + SteelSeriesSiberiaController(hid_device* dev_handle, const char* path, std::string dev_name); + ~SteelSeriesSiberiaController(); + + std::string GetDeviceLocation(); + std::string GetDeviceName(); + std::string GetSerialString(); + + void SetColor(unsigned char red, unsigned char green, unsigned char blue); + +private: + hid_device* dev; + std::string location; + std::string name; +}; diff --git a/Controllers/SteelSeriesController/color32.h b/Controllers/SteelSeriesController/color32.h index 1e83de45..9c065eee 100644 --- a/Controllers/SteelSeriesController/color32.h +++ b/Controllers/SteelSeriesController/color32.h @@ -1,20 +1,20 @@ -/*-----------------------------------------*\ -| color32.h | -| | -| Simple structure to allow passing of | -| 32-bit color data between classes | -| | -| David Lee (RAMChYLD) 15/11/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| color32.h | +| | +| Class to hold 32-bit color data | +| | +| David Lee (RAMChYLD) 15 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#ifndef COLOR32_H -#define COLOR32_H +#pragma once -typedef struct{ +typedef struct +{ unsigned char red; unsigned char green; unsigned char blue; unsigned char alpha; } color32; - -#endif // COLOR32_H diff --git a/Controllers/TForceXtreemController/RGBController_TForceXtreem.cpp b/Controllers/TForceXtreemController/RGBController_TForceXtreem.cpp new file mode 100644 index 00000000..35107595 --- /dev/null +++ b/Controllers/TForceXtreemController/RGBController_TForceXtreem.cpp @@ -0,0 +1,502 @@ +/*---------------------------------------------------------*\ +| RGBController_TForceXtreem.cpp | +| | +| RGBController for TeamGroup T-Force Xtreem RAM | +| | +| Milan Cermak (krysmanta) 28 Dec 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_TForceXtreem.h" +#include "LogManager.h" +#include "ResourceManager.h" + +/**------------------------------------------------------------------*\ + @name T-Force Xtreem + @category RAM + @type SMBus + @save :white_check_mark: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectTForceXtreemControllers + @comment + Verified models: + TeamGroup T-Force Xtreem ARGB DDR4 +\*-------------------------------------------------------------------*/ + +RGBController_TForceXtreem::RGBController_TForceXtreem(TForceXtreemController * controller_ptr) +{ + controller = controller_ptr; + + type = DEVICE_TYPE_DRAM; + name = "T-Force Xtreem RGB"; + vendor = "TeamGroup"; + + location = controller->GetDeviceLocation(); + description = "TeamGroup T-Force Xtreem DRAM"; + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + mode Off; + Off.name = "Off"; + Off.value = XTREEM_MODE_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + mode Static; + Static.name = "Static"; + Static.value = XTREEM_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Static.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Static); + + mode Breathing; + Breathing.name = "Breathing"; + Breathing.value = XTREEM_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED; + Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.speed_min = XTREEM_SPEED_SLOWEST; + Breathing.speed_max = XTREEM_SPEED_FASTEST; + Breathing.speed = XTREEM_SPEED_NORMAL; + modes.push_back(Breathing); + + mode Flashing; + Flashing.name = "Flashing"; + Flashing.value = XTREEM_MODE_FLASHING; + Flashing.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED; + Flashing.color_mode = MODE_COLORS_PER_LED; + Flashing.speed_min = XTREEM_SPEED_SLOWEST; + Flashing.speed_max = XTREEM_SPEED_FASTEST; + Flashing.speed = XTREEM_SPEED_NORMAL; + modes.push_back(Flashing); + + mode SpectrumCycle; + SpectrumCycle.name = "Spectrum Cycle"; + SpectrumCycle.value = XTREEM_MODE_SPECTRUM_CYCLE; + SpectrumCycle.flags = MODE_FLAG_HAS_SPEED; + SpectrumCycle.color_mode = MODE_COLORS_NONE; + SpectrumCycle.speed_min = XTREEM_SPEED_SLOWEST; + SpectrumCycle.speed_max = XTREEM_SPEED_FASTEST; + SpectrumCycle.speed = XTREEM_SPEED_NORMAL; + modes.push_back(SpectrumCycle); + + mode Rainbow; + Rainbow.name = "Rainbow"; + Rainbow.value = XTREEM_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.speed_min = XTREEM_SPEED_SLOWEST; + Rainbow.speed_max = XTREEM_SPEED_FASTEST; + Rainbow.speed = XTREEM_SPEED_NORMAL; + Rainbow.direction = MODE_DIRECTION_LEFT; + modes.push_back(Rainbow); + + mode ChaseFade; + ChaseFade.name = "Chase Fade"; + ChaseFade.value = XTREEM_MODE_CHASE_FADE; + ChaseFade.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + ChaseFade.color_mode = MODE_COLORS_PER_LED; + ChaseFade.speed_min = XTREEM_SPEED_SLOWEST; + ChaseFade.speed_max = XTREEM_SPEED_FASTEST; + ChaseFade.speed = XTREEM_SPEED_NORMAL; + ChaseFade.direction = MODE_DIRECTION_LEFT; + modes.push_back(ChaseFade); + + mode Chase; + Chase.name = "Chase"; + Chase.value = XTREEM_MODE_CHASE; + Chase.flags = MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + Chase.color_mode = MODE_COLORS_PER_LED; + Chase.speed_min = XTREEM_SPEED_SLOWEST; + Chase.speed_max = XTREEM_SPEED_FASTEST; + Chase.speed = XTREEM_SPEED_NORMAL; + ChaseFade.direction = MODE_DIRECTION_LEFT; + modes.push_back(Chase); + + mode RandomFlicker; + RandomFlicker.name = "Random Flicker"; + RandomFlicker.value = XTREEM_MODE_RANDOM_FLICKER; + RandomFlicker.flags = MODE_FLAG_HAS_SPEED; + RandomFlicker.color_mode = MODE_COLORS_NONE; + RandomFlicker.speed_min = XTREEM_SPEED_SLOWEST; + RandomFlicker.speed_max = XTREEM_SPEED_FASTEST; + RandomFlicker.speed = XTREEM_SPEED_NORMAL; + modes.push_back(RandomFlicker); + + mode Stack; + Stack.name = "Stack"; + Stack.value = XTREEM_MODE_STACK; + Stack.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + Stack.color_mode = MODE_COLORS_NONE; + Stack.speed_min = XTREEM_SPEED_SLOWEST; + Stack.speed_max = XTREEM_SPEED_FASTEST; + Stack.speed = XTREEM_SPEED_NORMAL; + modes.push_back(Stack); + + mode Pong; + Pong.name = "Pong"; + Pong.value = XTREEM_MODE_PONG; + Pong.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + Pong.color_mode = MODE_COLORS_NONE; + Pong.speed_min = XTREEM_SPEED_SLOWEST; + Pong.speed_max = XTREEM_SPEED_FASTEST; + Pong.speed = XTREEM_SPEED_NORMAL; + modes.push_back(Pong); + + mode Fillup; + Fillup.name = "Fill up"; + Fillup.value = XTREEM_MODE_FILLUP; + Fillup.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + Fillup.color_mode = MODE_COLORS_NONE; + Fillup.speed_min = XTREEM_SPEED_SLOWEST; + Fillup.speed_max = XTREEM_SPEED_FASTEST; + Fillup.speed = XTREEM_SPEED_NORMAL; + modes.push_back(Fillup); + + mode Neon; + Neon.name = "Neon Sign"; + Neon.value = XTREEM_MODE_NEON; + Neon.flags = MODE_FLAG_HAS_SPEED; + Neon.color_mode = MODE_COLORS_NONE; + Neon.speed_min = XTREEM_SPEED_SLOWEST; + Neon.speed_max = XTREEM_SPEED_FASTEST; + Neon.speed = XTREEM_SPEED_NORMAL; + modes.push_back(Neon); + + mode ColorWave; + ColorWave.name = "Wave"; + ColorWave.value = XTREEM_MODE_COLOR_WAVE; + ColorWave.flags = MODE_FLAG_HAS_SPEED; + ColorWave.color_mode = MODE_COLORS_NONE; + ColorWave.speed_min = XTREEM_SPEED_SLOWEST; + ColorWave.speed_max = XTREEM_SPEED_FASTEST; + ColorWave.speed = XTREEM_SPEED_NORMAL; + modes.push_back(ColorWave); + + mode DoubleWave; + DoubleWave.name = "Double Wave"; + DoubleWave.value = XTREEM_MODE_COLOR_DOUBLE_WAVE; + DoubleWave.flags = MODE_FLAG_HAS_SPEED; + DoubleWave.color_mode = MODE_COLORS_NONE; + DoubleWave.speed_min = XTREEM_SPEED_SLOWEST; + DoubleWave.speed_max = XTREEM_SPEED_FASTEST; + DoubleWave.speed = XTREEM_SPEED_NORMAL; + modes.push_back(DoubleWave); + + mode Mixer; + Mixer.name = "Mixer"; + Mixer.value = XTREEM_MODE_MIXER; + Mixer.flags = MODE_FLAG_HAS_SPEED; + Mixer.color_mode = MODE_COLORS_NONE; + Mixer.speed_min = XTREEM_SPEED_SLOWEST; + Mixer.speed_max = XTREEM_SPEED_FASTEST; + Mixer.speed = XTREEM_SPEED_NORMAL; + modes.push_back(Mixer); + + mode Spectrum2; + Spectrum2.name = "Spectrum Cycle 2"; + Spectrum2.value = XTREEM_MODE_SPECTRUM_CYCLE_2; + Spectrum2.flags = MODE_FLAG_HAS_SPEED; + Spectrum2.color_mode = MODE_COLORS_NONE; + Spectrum2.speed_min = XTREEM_SPEED_SLOWEST; + Spectrum2.speed_max = XTREEM_SPEED_FASTEST; + Spectrum2.speed = XTREEM_SPEED_NORMAL; + modes.push_back(Spectrum2); + + mode FireBreathing; + FireBreathing.name = "Fire Breathing"; + FireBreathing.value = XTREEM_MODE_FIRE_BREATHING; + FireBreathing.flags = MODE_FLAG_HAS_SPEED; + FireBreathing.color_mode = MODE_COLORS_NONE; + FireBreathing.speed_min = XTREEM_SPEED_SLOWEST; + FireBreathing.speed_max = XTREEM_SPEED_FASTEST; + FireBreathing.speed = XTREEM_SPEED_NORMAL; + modes.push_back(FireBreathing); + + mode Spectrum3; + Spectrum3.name = "Spectrum Cycle 3"; + Spectrum3.value = XTREEM_MODE_SPECTRUM_CYCLE_3; + Spectrum3.flags = MODE_FLAG_HAS_SPEED; + Spectrum3.color_mode = MODE_COLORS_NONE; + Spectrum3.speed_min = XTREEM_SPEED_SLOWEST; + Spectrum3.speed_max = XTREEM_SPEED_FASTEST; + Spectrum3.speed = XTREEM_SPEED_NORMAL; + modes.push_back(Spectrum3); + + mode Slither; + Slither.name = "Slither"; + Slither.value = XTREEM_MODE_SLITHER; + Slither.flags = MODE_FLAG_HAS_SPEED; + Slither.color_mode = MODE_COLORS_NONE; + Slither.speed_min = XTREEM_SPEED_SLOWEST; + Slither.speed_max = XTREEM_SPEED_FASTEST; + Slither.speed = XTREEM_SPEED_NORMAL; + modes.push_back(Slither); + + mode TForceXtreem; + TForceXtreem.name = "T-Force Xtreem"; + TForceXtreem.value = XTREEM_MODE_TFORCE_XTREEM; + TForceXtreem.flags = MODE_FLAG_HAS_SPEED; + TForceXtreem.color_mode = MODE_COLORS_NONE; + TForceXtreem.speed_min = XTREEM_SPEED_SLOWEST; + TForceXtreem.speed_max = XTREEM_SPEED_FASTEST; + TForceXtreem.speed = XTREEM_SPEED_NORMAL; + modes.push_back(TForceXtreem); + + SetupZones(); + + /*-------------------------------------------------*\ + | Initialize active mode | + \*-------------------------------------------------*/ + active_mode = GetDeviceMode(); +} + +RGBController_TForceXtreem::~RGBController_TForceXtreem() +{ + delete controller; +} + +int RGBController_TForceXtreem::GetDeviceMode() +{ + /*-----------------------------------------------------------------*\ + | Determine starting mode by reading the mode and direct registers | + \*-----------------------------------------------------------------*/ + int dev_mode = controller->ENERegisterRead(XTREEM_REG_MODE); + int color_mode = MODE_COLORS_PER_LED; + int speed = controller->ENERegisterRead(XTREEM_REG_SPEED); + int direction = controller->ENERegisterRead(XTREEM_REG_DIRECTION); + + LOG_TRACE("[%s] Retrieved ENE mode from module: %02d", name.c_str(), dev_mode); + + if(controller->ENERegisterRead(XTREEM_REG_DIRECT)) + { + dev_mode = 0xFFFF; + } + + switch(dev_mode) + { + case XTREEM_MODE_OFF: + case XTREEM_MODE_RAINBOW: + case XTREEM_MODE_SPECTRUM_CYCLE: + case XTREEM_MODE_RANDOM_FLICKER: + color_mode = MODE_COLORS_NONE; + break; + + case XTREEM_MODE_SPECTRUM_CYCLE_CHASE: + dev_mode = XTREEM_MODE_CHASE; + color_mode = MODE_COLORS_RANDOM; + break; + + case XTREEM_MODE_SPECTRUM_CYCLE_BREATHING: + dev_mode = XTREEM_MODE_BREATHING; + color_mode = MODE_COLORS_RANDOM; + break; + + case XTREEM_MODE_SPECTRUM_CYCLE_CHASE_FADE: + dev_mode = XTREEM_MODE_CHASE_FADE; + color_mode = MODE_COLORS_RANDOM; + break; + } + + for(int mode = 0; mode < (int)modes.size(); mode++) + { + if(modes[mode].value == dev_mode) + { + active_mode = mode; + modes[mode].color_mode = color_mode; + + if(modes[mode].flags & MODE_FLAG_HAS_SPEED) + { + modes[mode].speed = speed; + } + + if(modes[mode].flags & MODE_FLAG_HAS_DIRECTION_LR) + { + if(direction == XTREEM_DIRECTION_FORWARD) + { + modes[mode].direction = MODE_DIRECTION_RIGHT; + } + else + { + modes[mode].direction = MODE_DIRECTION_LEFT; + } + } + + break; + } + } + + /*---------------------------------------------------------*\ + | Initialize colors for each LED | + \*---------------------------------------------------------*/ + for(std::size_t led_idx = 0; led_idx < leds.size(); led_idx++) + { + unsigned int led = leds[led_idx].value; + unsigned char red; + unsigned char grn; + unsigned char blu; + + if(active_mode == 0) + { + red = controller->GetLEDRed(led); + grn = controller->GetLEDGreen(led); + blu = controller->GetLEDBlue(led); + } + else + { + red = controller->GetLEDRedEffect(led); + grn = controller->GetLEDGreenEffect(led); + blu = controller->GetLEDBlueEffect(led); + } + + colors[led_idx] = ToRGBColor(red, grn, blu); + } + + return(active_mode); +} + +void RGBController_TForceXtreem::DeviceUpdateLEDs() +{ + if(GetMode() == 0) + { + controller->SetAllColorsDirect(&colors[0]); + } + else + { + controller->SetAllColorsEffect(&colors[0]); + } + +} + +void RGBController_TForceXtreem::UpdateZoneLEDs(int zone) +{ + for(std::size_t led_idx = 0; led_idx < zones[zone].leds_count; led_idx++) + { + int led = zones[zone].leds[led_idx].value; + RGBColor color = colors[led]; + unsigned char red = RGBGetRValue(color); + unsigned char grn = RGBGetGValue(color); + unsigned char blu = RGBGetBValue(color); + + if(GetMode() == 0) + { + controller->SetLEDColorDirect(led, red, grn, blu); + } + else + { + controller->SetLEDColorEffect(led, red, grn, blu); + } + } +} + +void RGBController_TForceXtreem::UpdateSingleLED(int led) +{ + RGBColor color = colors[led]; + unsigned char red = RGBGetRValue(color); + unsigned char grn = RGBGetGValue(color); + unsigned char blu = RGBGetBValue(color); + + if(GetMode() == 0) + { + controller->SetLEDColorDirect(led, red, grn, blu); + } + else + { + controller->SetLEDColorEffect(led, red, grn, blu); + } +} + +void RGBController_TForceXtreem::SetupZones() +{ + /*---------------------------------------------------------*\ + | Set up zone | + \*---------------------------------------------------------*/ + zone new_zone; + new_zone.name = "DRAM"; + new_zone.type = ZONE_TYPE_LINEAR; + new_zone.leds_min = XTREEM_LED_COUNT; + new_zone.leds_max = XTREEM_LED_COUNT; + new_zone.leds_count = XTREEM_LED_COUNT; + new_zone.matrix_map = NULL; + zones.push_back(new_zone); + + /*---------------------------------------------------------*\ + | Set up LEDs | + \*---------------------------------------------------------*/ + for(std::size_t led_idx = 0; led_idx < zones[0].leds_count; led_idx++) + { + led new_led; + new_led.name = "DRAM LED "; + new_led.name.append(std::to_string(led_idx)); + leds.push_back(new_led); + } + + SetupColors(); +} + +void RGBController_TForceXtreem::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_TForceXtreem::DeviceUpdateMode() +{ + if(modes[active_mode].value == 0xFFFF) + { + controller->SetDirect(true); + } + else + { + int new_mode = modes[active_mode].value; + int new_speed = 0; + int new_direction = 0; + + if(modes[active_mode].color_mode == MODE_COLORS_RANDOM) + { + switch(new_mode) + { + case XTREEM_MODE_CHASE: + new_mode = XTREEM_MODE_SPECTRUM_CYCLE_CHASE; + break; + case XTREEM_MODE_BREATHING: + new_mode = XTREEM_MODE_SPECTRUM_CYCLE_BREATHING; + break; + case XTREEM_MODE_CHASE_FADE: + new_mode = XTREEM_MODE_SPECTRUM_CYCLE_CHASE_FADE; + break; + } + } + + if(modes[active_mode].flags & MODE_FLAG_HAS_SPEED) + { + new_speed = modes[active_mode].speed; + } + + if(modes[active_mode].flags & MODE_FLAG_HAS_DIRECTION_LR) + { + switch(modes[active_mode].direction) + { + case MODE_DIRECTION_LEFT: + new_direction = XTREEM_DIRECTION_REVERSE; + break; + + case MODE_DIRECTION_RIGHT: + new_direction = XTREEM_DIRECTION_FORWARD; + break; + } + } + + controller->SetMode(new_mode, new_speed, new_direction); + controller->SetDirect(false); + } +} diff --git a/Controllers/TForceXtreemController/RGBController_TForceXtreem.h b/Controllers/TForceXtreemController/RGBController_TForceXtreem.h new file mode 100644 index 00000000..33c4f091 --- /dev/null +++ b/Controllers/TForceXtreemController/RGBController_TForceXtreem.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------*\ +| RGBController_TForceXtreem.h | +| | +| RGBController for TeamGroup T-Force Xtreem RAM | +| | +| Milan Cermak (krysmanta) 28 Dec 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "TForceXtreemController.h" + +class RGBController_TForceXtreem : public RGBController +{ +public: + RGBController_TForceXtreem(TForceXtreemController* controller_ptr); + ~RGBController_TForceXtreem(); + + void SetupZones(); + + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + TForceXtreemController* controller; + + int GetDeviceMode(); +}; diff --git a/Controllers/TForceXtreemController/TForceXtreemController.cpp b/Controllers/TForceXtreemController/TForceXtreemController.cpp new file mode 100644 index 00000000..7e073507 --- /dev/null +++ b/Controllers/TForceXtreemController/TForceXtreemController.cpp @@ -0,0 +1,183 @@ +/*---------------------------------------------------------*\ +| TForceXtreemController.cpp | +| | +| Driver for T-Force XTreem DRAM | +| | +| Milan Cermak (krysmanta) 28 Dec 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "TForceXtreemController.h" +#include "LogManager.h" + +TForceXtreemController::TForceXtreemController(i2c_smbus_interface *bus, ene_dev_id dev) +{ + this->bus = bus; + this->dev = dev; +} + +TForceXtreemController::~TForceXtreemController() +{ +} + +std::string TForceXtreemController::GetDeviceLocation() +{ + std::string return_string(bus->device_name); + + char addr[5]; + snprintf(addr, 5, "0x%02X", dev); + return_string.append(", address "); + return_string.append(addr); + + return(return_string); +} + +unsigned int TForceXtreemController::GetLEDCount() +{ + return(XTREEM_LED_COUNT); +} + +/*---------------------------------------------------*\ +| LEDs are in a single strip that is folded in half. | +| That makes the LED order: 0-14-1-13-2-...-7-9-8 | +\*---------------------------------------------------*/ +#define XTREEM_LED_OFFSET(x) ((((x) & 0x01) > 0) ? XTREEM_LED_COUNT - 1 - ((x) >> 1) : ((x) >> 1)) + +unsigned char TForceXtreemController::GetLEDRed(unsigned int led) +{ + return(ENERegisterRead(XTREEM_REG_COLORS_DIRECT + ( 3 * XTREEM_LED_OFFSET(led) ))); +} + +unsigned char TForceXtreemController::GetLEDGreen(unsigned int led) +{ + return(ENERegisterRead(XTREEM_REG_COLORS_DIRECT + ( 3 * XTREEM_LED_OFFSET(led) ) + 2)); +} + +unsigned char TForceXtreemController::GetLEDBlue(unsigned int led) +{ + return(ENERegisterRead(XTREEM_REG_COLORS_DIRECT + ( 3 * XTREEM_LED_OFFSET(led) ) + 1)); +} + +unsigned char TForceXtreemController::GetLEDRedEffect(unsigned int led) +{ + return(ENERegisterRead(XTREEM_REG_COLORS_EFFECT + ( 3 * XTREEM_LED_OFFSET(led) ))); +} + +unsigned char TForceXtreemController::GetLEDGreenEffect(unsigned int led) +{ + return(ENERegisterRead(XTREEM_REG_COLORS_EFFECT + ( 3 * XTREEM_LED_OFFSET(led) ) + 2)); +} + +unsigned char TForceXtreemController::GetLEDBlueEffect(unsigned int led) +{ + return(ENERegisterRead(XTREEM_REG_COLORS_EFFECT + ( 3 * XTREEM_LED_OFFSET(led) ) + 1)); +} + +void TForceXtreemController::SetAllColorsDirect(RGBColor* colors) +{ + unsigned char* color_buf = new unsigned char[XTREEM_LED_COUNT * 3]; + unsigned int bytes_sent = 0; + + for(unsigned int i = 0; i < XTREEM_LED_COUNT; i++) + { + unsigned int offset = 3 * XTREEM_LED_OFFSET(i); + color_buf[offset + 0] = RGBGetRValue(colors[i]); + color_buf[offset + 1] = RGBGetBValue(colors[i]); + color_buf[offset + 2] = RGBGetGValue(colors[i]); + } + + while(bytes_sent < (XTREEM_LED_COUNT * 3)) + { + ENERegisterWriteBlock(XTREEM_REG_COLORS_DIRECT + bytes_sent, &color_buf[bytes_sent], 3); + + bytes_sent += 3; + } + + delete[] color_buf; +} + +void TForceXtreemController::SetAllColorsEffect(RGBColor* colors) +{ + unsigned char* color_buf = new unsigned char[XTREEM_LED_COUNT * 3]; + unsigned int bytes_sent = 0; + + for(unsigned int i = 0; i < XTREEM_LED_COUNT; i++) + { + unsigned int offset = 3 * XTREEM_LED_OFFSET(i); + color_buf[offset + 0] = RGBGetRValue(colors[i]); + color_buf[offset + 1] = RGBGetBValue(colors[i]); + color_buf[offset + 2] = RGBGetGValue(colors[i]); + } + + while(bytes_sent < (XTREEM_LED_COUNT * 3)) + { + ENERegisterWriteBlock(XTREEM_REG_COLORS_EFFECT + bytes_sent, &color_buf[bytes_sent], 3); + + bytes_sent += 3; + } + + ENERegisterWrite(XTREEM_REG_APPLY, XTREEM_APPLY_VAL); + + delete[] color_buf; +} + + +void TForceXtreemController::SetDirect(unsigned char direct) +{ + ENERegisterWrite(XTREEM_REG_DIRECT, direct); + ENERegisterWrite(XTREEM_REG_APPLY, XTREEM_APPLY_VAL); +} + +void TForceXtreemController::SetLEDColorDirect(unsigned int led, unsigned char red, unsigned char green, unsigned char blue) +{ + unsigned char colors[3] = { red, blue, green }; + + ENERegisterWriteBlock(XTREEM_REG_COLORS_DIRECT + ( 3 * XTREEM_LED_OFFSET(led) ), colors, 3); +} + +void TForceXtreemController::SetLEDColorEffect(unsigned int led, unsigned char red, unsigned char green, unsigned char blue) +{ + unsigned char colors[3] = { red, blue, green }; + + ENERegisterWriteBlock(XTREEM_REG_COLORS_EFFECT + (3 * XTREEM_LED_OFFSET(led)), colors, 3); + + ENERegisterWrite(XTREEM_REG_APPLY, XTREEM_APPLY_VAL); +} + +void TForceXtreemController::SetMode(unsigned char mode, unsigned char speed, unsigned char direction) +{ + ENERegisterWrite(XTREEM_REG_MODE, mode); + ENERegisterWrite(XTREEM_REG_SPEED, speed); + ENERegisterWrite(XTREEM_REG_DIRECTION, direction); + ENERegisterWrite(XTREEM_REG_APPLY, XTREEM_APPLY_VAL); +} + +unsigned char TForceXtreemController::ENERegisterRead(ene_register reg) +{ + //Write ENE register + bus->i2c_smbus_write_word_data(dev, 0x00, ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF)); + + //Read ENE value + return(bus->i2c_smbus_read_byte_data(dev, 0x81)); +} + +void TForceXtreemController::ENERegisterWrite(ene_register reg, unsigned char val) +{ + //Write ENE register + bus->i2c_smbus_write_word_data(dev, 0x00, ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF)); + + //Write ENE value + bus->i2c_smbus_write_byte_data(dev, 0x01, val); +} + +void TForceXtreemController::ENERegisterWriteBlock(ene_register reg, unsigned char * data, unsigned char sz) +{ + //Write ENE register + bus->i2c_smbus_write_word_data(dev, 0x00, ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF)); + + //Write ENE block data + bus->i2c_smbus_write_block_data(dev, 0x03, sz, data); +} diff --git a/Controllers/TForceXtreemController/TForceXtreemController.h b/Controllers/TForceXtreemController/TForceXtreemController.h new file mode 100644 index 00000000..c12bd4d9 --- /dev/null +++ b/Controllers/TForceXtreemController/TForceXtreemController.h @@ -0,0 +1,111 @@ +/*---------------------------------------------------------*\ +| TForceXtreemController.h | +| | +| Driver for T-Force Xtreem DRAM | +| | +| Milan Cermak (krysmanta) 28 Dec 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "RGBController.h" +#include "i2c_smbus.h" + +#define XTREEM_APPLY_VAL 0x01 /* Value for Apply Changes Register */ +#define XTREEM_LED_COUNT 15 + +typedef unsigned short ene_register; +typedef unsigned char ene_dev_id; + +enum +{ + XTREEM_REG_DIRECT = 0xE020, /* "Direct Access" Selection Register */ + XTREEM_REG_MODE = 0xE021, /* Mode Selection Register */ + XTREEM_REG_SPEED = 0xE022, /* Speed Control Register */ + XTREEM_REG_DIRECTION = 0xE023, /* Direction Control Register */ + XTREEM_REG_APPLY = 0xE02F, /* Apply Changes Register */ + XTREEM_REG_SLOT_INDEX = 0xE0F8, /* Slot Index Register (RAM only) */ + XTREEM_REG_I2C_ADDRESS = 0xE0F9, /* I2C Address Register (RAM only) */ + XTREEM_REG_COLORS_DIRECT = 0xE100, /* Colors for Direct Mode 45 bytes */ + XTREEM_REG_COLORS_EFFECT = 0xE300, /* Colors for Internal Effects 45 bytes */ +}; + +enum +{ + XTREEM_MODE_OFF = 0, /* OFF mode */ + XTREEM_MODE_STATIC = 1, /* Static color mode */ + XTREEM_MODE_BREATHING = 2, /* Breathing effect mode */ + XTREEM_MODE_FLASHING = 3, /* Flashing effect mode */ + XTREEM_MODE_SPECTRUM_CYCLE = 4, /* Spectrum Cycle mode */ + XTREEM_MODE_RAINBOW = 5, /* Rainbow effect mode */ + XTREEM_MODE_SPECTRUM_CYCLE_BREATHING = 6, /* Rainbow Breathing effect mode */ + XTREEM_MODE_CHASE_FADE = 7, /* Chase with Fade effect mode */ + XTREEM_MODE_SPECTRUM_CYCLE_CHASE_FADE = 8, /* Chase with Fade, Rainbow effect mode */ + XTREEM_MODE_CHASE = 9, /* Chase effect mode */ + XTREEM_MODE_SPECTRUM_CYCLE_CHASE = 10, /* Chase with Rainbow effect mode */ + XTREEM_MODE_SPECTRUM_CYCLE_WAVE = 11, /* Wave effect mode */ + XTREEM_MODE_CHASE_RAINBOW_PULSE = 12, /* Chase with Rainbow Pulse effect mode*/ + XTREEM_MODE_RANDOM_FLICKER = 13, /* Random flicker effect mode */ + XTREEM_MODE_STACK = 14, /* Stacking effect mode */ + XTREEM_MODE_PONG = 15, /* Pong effect mode */ + XTREEM_MODE_FILLUP = 16, /* Fill up effect mode */ + XTREEM_MODE_NEON = 17, /* Neon effect mode */ + XTREEM_MODE_COLOR_WAVE = 18, /* Color Wave effect mode */ + XTREEM_MODE_COLOR_DOUBLE_WAVE = 19, /* Color double wave effect mode */ + XTREEM_MODE_MIXER = 20, /* Mixer effect mode */ + XTREEM_MODE_SPECTRUM_CYCLE_2 = 21, /* Spectrum cycle 2 effect mode */ + XTREEM_MODE_FIRE_BREATHING = 22, /* Color shift breathing effect mode */ + XTREEM_MODE_SPECTRUM_CYCLE_3 = 23, /* Spectrum cycle 3 effect mode */ + XTREEM_MODE_SLITHER = 24, /* Slither effect mode */ + XTREEM_MODE_TFORCE_XTREEM = 25, /* Default T-Force Xtreem mode */ + XTREEM_NUMBER_MODES /* Number of Aura modes */ +}; + +enum +{ + XTREEM_SPEED_SLOWEST = 0x04, /* Slowest effect speed */ + XTREEM_SPEED_SLOW = 0x03, /* Slow effect speed */ + XTREEM_SPEED_NORMAL = 0x02, /* Normal effect speed */ + XTREEM_SPEED_FAST = 0x01, /* Fast effect speed */ + XTREEM_SPEED_FASTEST = 0x00, /* Fastest effect speed */ +}; + +enum +{ + XTREEM_DIRECTION_FORWARD = 0x0, /* Forward effect direction */ + XTREEM_DIRECTION_REVERSE = 0x1, /* Reverse effect direction */ +}; + +class TForceXtreemController +{ +public: + TForceXtreemController(i2c_smbus_interface *bus, ene_dev_id dev); + ~TForceXtreemController(); + + std::string GetDeviceLocation(); + unsigned int GetLEDCount(); + unsigned char GetLEDRed(unsigned int led); + unsigned char GetLEDGreen(unsigned int led); + unsigned char GetLEDBlue(unsigned int led); + unsigned char GetLEDRedEffect(unsigned int led); + unsigned char GetLEDGreenEffect(unsigned int led); + unsigned char GetLEDBlueEffect(unsigned int led); + void SetAllColorsDirect(RGBColor* colors); + void SetAllColorsEffect(RGBColor* colors); + void SetDirect(unsigned char direct); + void SetLEDColorDirect(unsigned int led, unsigned char red, unsigned char green, unsigned char blue); + void SetLEDColorEffect(unsigned int led, unsigned char red, unsigned char green, unsigned char blue); + void SetMode(unsigned char mode, unsigned char speed, unsigned char direction); + + unsigned char ENERegisterRead(ene_register reg); + void ENERegisterWrite(ene_register reg, unsigned char val); + void ENERegisterWriteBlock(ene_register reg, unsigned char * data, unsigned char sz); + +private: + i2c_smbus_interface * bus; + ene_dev_id dev; +}; diff --git a/Controllers/TForceXtreemController/TForceXtreemControllerDetect.cpp b/Controllers/TForceXtreemController/TForceXtreemControllerDetect.cpp new file mode 100644 index 00000000..a8637ae2 --- /dev/null +++ b/Controllers/TForceXtreemController/TForceXtreemControllerDetect.cpp @@ -0,0 +1,184 @@ +/*---------------------------------------------------------*\ +| TForceXtreemControllerDetect.cpp | +| | +| Detector for T-Force Xtreem RAM | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "TForceXtreemController.h" +#include "LogManager.h" +#include "RGBController_TForceXtreem.h" +#include "i2c_smbus.h" + +#define DETECTOR_NAME "TForce Xtreem Controller" + +using namespace std::chrono_literals; + +/*----------------------------------------------------------------------*\ +| Windows defines "interface" for some reason. Work around this | +\*----------------------------------------------------------------------*/ +#ifdef interface +#undef interface +#endif + +/*----------------------------------------------------------------------*\ +| This list contains the available SMBus addresses for mapping ENE RAM | +\*----------------------------------------------------------------------*/ +#define XTREEM_RAM_ADDRESS_COUNT 13 + +static const unsigned char xtreem_ram_addresses[] = +{ + 0x70, + 0x71, + 0x72, + 0x73, + 0x74, + 0x75, + 0x76, + 0x78, + 0x39, + 0x3A, + 0x3B, + 0x3C, + 0x3D +}; + +/******************************************************************************************\ +* * +* XtreemRegisterWrite * +* * +* A standalone version of the TForceXtreemController::ENERegisterWrite function for * +* access to ENE devices without instancing the TForceXtreemController class. * +* * +\******************************************************************************************/ + +static void XtreemRegisterWrite(i2c_smbus_interface* bus, ene_dev_id dev, ene_register reg, unsigned char val) +{ + //Write ENE register + bus->i2c_smbus_write_word_data(dev, 0x00, ((reg << 8) & 0xFF00) | ((reg >> 8) & 0x00FF)); + + //Write ENE value + bus->i2c_smbus_write_byte_data(dev, 0x01, val); +} + +/******************************************************************************************\ +* * +* TestForENESMBusController * +* * +* Tests the given address to see if an ENE controller exists there. First does a * +* quick write to test for a response, and if so does a simple read at 0x90 to test * +* for incrementing values 10...1F which was observed at this location * +* * +\******************************************************************************************/ + +bool TestForTForceXtreemController(i2c_smbus_interface* bus, unsigned char address) +{ + bool pass = false; + + LOG_DEBUG("[%s] looking for devices at 0x%02X...", DETECTOR_NAME, address); + + int res = bus->i2c_smbus_read_byte(address); + + if(res < 0) + { + res = bus->i2c_smbus_read_byte_data(address, 0x00); + } + + if(res >= 0) + { + pass = true; + + LOG_DEBUG("[%s] Detected an I2C device at address %02X, testing register range", DETECTOR_NAME, address); + + for(int i = 0x90; i < 0xA1; i++) + { + res = bus->i2c_smbus_read_byte_data(address, i); + + if(res != (i - 0x80)) + { + LOG_VERBOSE("[%s] Detection failed testing register %02X. Expected %02X, got %02X.", DETECTOR_NAME, i, (i - 0x80), res); + + pass = false; + break; + } + } + } + + return(pass); + +} /* TestForTForceXtreemController() */ + +/******************************************************************************************\ +* * +* DetectTForceXtreemDRAMControllers * +* * +* Detects T-Force Xtreem controllers on DRAM devices * +* * +* bus - pointer to i2c_smbus_interface where device is connected * +* slots - SPD accessors to occupied slots * +* * +\******************************************************************************************/ + +void DetectTForceXtreemControllers(i2c_smbus_interface* bus, std::vector &slots, const std::string &/*name*/) +{ + + LOG_DEBUG("[%s] Remapping ENE SMBus RAM modules on 0x77", DETECTOR_NAME); + + for(SPDWrapper *slot : slots) + { + int address_list_idx = slot->index() - 1; + int res; + + /*-------------------------------------------------*\ + | Full test to avoid conflicts with other ENE DRAMs | + \*-------------------------------------------------*/ + if(!TestForTForceXtreemController(bus, 0x77)) + { + LOG_DEBUG("[%s] No device detected at 0x77, aborting remap", DETECTOR_NAME); + + break; + } + + do + { + address_list_idx++; + + if(address_list_idx < XTREEM_RAM_ADDRESS_COUNT) + { + LOG_DEBUG("[%s] Testing address %02X to see if there is a device there", DETECTOR_NAME, xtreem_ram_addresses[address_list_idx]); + + res = bus->i2c_smbus_write_quick(xtreem_ram_addresses[address_list_idx], I2C_SMBUS_WRITE); + } + else + { + break; + } + } while(res >= 0); + + if(address_list_idx < XTREEM_RAM_ADDRESS_COUNT) + { + LOG_DEBUG("[%s] Remapping slot %d to address %02X", DETECTOR_NAME, slot, xtreem_ram_addresses[address_list_idx]); + + XtreemRegisterWrite(bus, 0x77, XTREEM_REG_SLOT_INDEX, slot->index()); + XtreemRegisterWrite(bus, 0x77, XTREEM_REG_I2C_ADDRESS, (xtreem_ram_addresses[address_list_idx] << 1)); + } + } + + // Add ENE controllers at their remapped addresses + for(unsigned int address_list_idx = 0; address_list_idx < XTREEM_RAM_ADDRESS_COUNT; address_list_idx++) + { + if(TestForTForceXtreemController(bus, xtreem_ram_addresses[address_list_idx])) + { + TForceXtreemController* controller = new TForceXtreemController(bus, xtreem_ram_addresses[address_list_idx]); + RGBController_TForceXtreem* rgb_controller = new RGBController_TForceXtreem(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + } +} /* DetectTForceXtreemControllers() */ + +REGISTER_I2C_DIMM_DETECTOR("T-Force Xtreem DDR4 DRAM", DetectTForceXtreemControllers, JEDEC_TEAMGROUP, SPD_DDR4_SDRAM); diff --git a/Controllers/TecknetController/RGBController_Tecknet.cpp b/Controllers/TecknetController/RGBController_Tecknet.cpp index bca5667c..08f02300 100644 --- a/Controllers/TecknetController/RGBController_Tecknet.cpp +++ b/Controllers/TecknetController/RGBController_Tecknet.cpp @@ -1,11 +1,13 @@ -/*-------------------------------------------------------------------*\ -| RGBController_Tecknet.cpp | -| | -| Driver for Tecknet Devices | -| | -| Chris M (Dr_No) 29th Jul 2020 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Tecknet.cpp | +| | +| RGBController for Tecknet devices | +| | +| Chris M (Dr_No) 29 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_Tecknet.h" diff --git a/Controllers/TecknetController/RGBController_Tecknet.h b/Controllers/TecknetController/RGBController_Tecknet.h index 7dfb04a8..8d332402 100644 --- a/Controllers/TecknetController/RGBController_Tecknet.h +++ b/Controllers/TecknetController/RGBController_Tecknet.h @@ -1,14 +1,15 @@ -/*-------------------------------------------------------------------*\ -| RGBController_Tecknet.h | -| | -| Driver for Tecknet Devices | -| | -| Chris M (Dr_No) 29th Jul 2020 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Tecknet.h | +| | +| RGBController for Tecknet devices | +| | +| Chris M (Dr_No) 29 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#ifndef RGBCONTROLLER_TECKNET_H -#define RGBCONTROLLER_TECKNET_H +#pragma once #include "RGBController.h" #include "TecknetController.h" @@ -31,5 +32,3 @@ public: private: TecknetController* controller; }; - -#endif // RGBCONTROLLER_TECKNET_H diff --git a/Controllers/TecknetController/TecknetController.cpp b/Controllers/TecknetController/TecknetController.cpp index 043b34fc..15487dab 100644 --- a/Controllers/TecknetController/TecknetController.cpp +++ b/Controllers/TecknetController/TecknetController.cpp @@ -1,12 +1,15 @@ -/*-------------------------------------------------------------------*\ -| TecknetController.cpp | -| | -| Driver for Technet Devices | -| | -| Chris M (Dr_No) 29th Jul 2020 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| TecknetController.cpp | +| | +| Driver for Tecknet devices | +| | +| Chris M (Dr_No) 29 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include "StringUtils.h" #include "TecknetController.h" static unsigned char tecknet_colour_mode_data[][16] = @@ -23,25 +26,20 @@ static unsigned char tecknet_speed_mode_data[][9] = TecknetController::TecknetController(hid_device* dev_handle, char *_path) { - const int szTemp = 256; - wchar_t tmpName[szTemp]; - - dev = dev_handle; - - hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - device_name = std::string(wName.begin(), wName.end()); - - hid_get_product_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); - - hid_get_serial_number_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - serial = std::string(wName.begin(), wName.end()); - + dev = dev_handle; location = _path; + /*---------------------------------------------------------*\ + | Get device name from HID manufacturer and product strings | + \*---------------------------------------------------------*/ + wchar_t name_string[HID_MAX_STR]; + + hid_get_manufacturer_string(dev, name_string, HID_MAX_STR); + device_name = StringUtils::wstring_to_string(name_string); + + hid_get_product_string(dev, name_string, HID_MAX_STR); + device_name.append(" ").append(StringUtils::wstring_to_string(name_string)); + current_mode = TECKNET_MODE_DIRECT; current_speed = TECKNET_SPEED_NORMAL; current_brightness = TECKNET_BRIGHTNESS_HIGH; @@ -59,7 +57,15 @@ std::string TecknetController::GetDeviceName() std::string TecknetController::GetSerial() { - return serial; + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } std::string TecknetController::GetLocation() diff --git a/Controllers/TecknetController/TecknetController.h b/Controllers/TecknetController/TecknetController.h index 3fdd1ce1..25ea1149 100644 --- a/Controllers/TecknetController/TecknetController.h +++ b/Controllers/TecknetController/TecknetController.h @@ -1,21 +1,23 @@ -/*-------------------------------------------------------------------*\ -| TecknetController.h | -| | -| Driver for Tecknet Devices | -| | -| Chris M (Dr_No) 29th Jul 2020 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| TecknetController.h | +| | +| Driver for Tecknet devices | +| | +| Chris M (Dr_No) 29 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#ifndef TECKNETCONTROLLER_H -#define TECKNETCONTROLLER_H +#pragma once #include -#include +#include +#define HID_MAX_STR 255 #define TECKNET_COLOUR_MODE_DATA_SIZE (sizeof(tecknet_colour_mode_data[0]) / sizeof(tecknet_colour_mode_data[0][0])) -#define TECKNET_DEVICE_NAME_SIZE (sizeof(device_name) / sizeof(device_name[ 0 ])) -#define TECKNET_PACKET_LENGTH 0x10 //16 bytes +#define TECKNET_DEVICE_NAME_SIZE (sizeof(device_name) / sizeof(device_name[ 0 ])) +#define TECKNET_PACKET_LENGTH 0x10 //16 bytes enum { @@ -64,7 +66,6 @@ public: private: std::string device_name; - std::string serial; std::string location; hid_device* dev; @@ -78,5 +79,3 @@ private: void SendUpdate(); }; - -#endif // TECKNETCONTROLLER_H diff --git a/Controllers/TecknetController/TecknetControllerDetect.cpp b/Controllers/TecknetController/TecknetControllerDetect.cpp index 5597e129..a7a5f12c 100644 --- a/Controllers/TecknetController/TecknetControllerDetect.cpp +++ b/Controllers/TecknetController/TecknetControllerDetect.cpp @@ -1,17 +1,18 @@ -/*-------------------------------------------------------------------*\ -| TecknetControllerDetect.cpp | -| | -| Driver for Tecknet Devices | -| | -| Chris M (Dr_No) 29th Jul 2020 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| TecknetControllerDetect.cpp | +| | +| Detector for Tecknet devices | +| | +| Chris M (Dr_No) 29 Jul 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include "Detector.h" #include "TecknetController.h" -#include "RGBController.h" #include "RGBController_Tecknet.h" -#include #define TECKNET_VID 0x04D9 diff --git a/Controllers/ThermaltakePoseidonZRGBController/RGBController_ThermaltakePoseidonZRGB.cpp b/Controllers/ThermaltakePoseidonZRGBController/RGBController_ThermaltakePoseidonZRGB.cpp index b19d0f62..a6f333cc 100644 --- a/Controllers/ThermaltakePoseidonZRGBController/RGBController_ThermaltakePoseidonZRGB.cpp +++ b/Controllers/ThermaltakePoseidonZRGBController/RGBController_ThermaltakePoseidonZRGB.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_ThermaltakePoseidonZRGB.cpp| -| | -| Generic RGB Interface for Thermaltake | -| Poseidon Z RGB Keyboard | -| | -| Adam Honse (CalcProgrammer1) 12/25/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ThermaltakePoseidonZRGB.cpp | +| | +| RGBController for Thermaltake Poseidon Z RGB | +| | +| Adam Honse (CalcProgrammer1) 25 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_ThermaltakePoseidonZRGB.h" diff --git a/Controllers/ThermaltakePoseidonZRGBController/RGBController_ThermaltakePoseidonZRGB.h b/Controllers/ThermaltakePoseidonZRGBController/RGBController_ThermaltakePoseidonZRGB.h index 743c8d9a..e430f342 100644 --- a/Controllers/ThermaltakePoseidonZRGBController/RGBController_ThermaltakePoseidonZRGB.h +++ b/Controllers/ThermaltakePoseidonZRGBController/RGBController_ThermaltakePoseidonZRGB.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_ThermaltakePoseidonZRGB.h | -| | -| Generic RGB Interface for Thermaltake | -| Poseidon Z RGB Keyboard | -| | -| Adam Honse (CalcProgrammer1) 12/25/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ThermaltakePoseidonZRGB.h | +| | +| RGBController for Thermaltake Poseidon Z RGB | +| | +| Adam Honse (CalcProgrammer1) 25 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "ThermaltakePoseidonZRGBController.h" @@ -19,7 +22,7 @@ public: void SetupZones(); void ResizeZone(int zone, int new_size); - + void DeviceUpdateLEDs(); void UpdateZoneLEDs(int zone); void UpdateSingleLED(int led); @@ -28,4 +31,4 @@ public: private: PoseidonZRGBController* controller; -}; \ No newline at end of file +}; diff --git a/Controllers/ThermaltakePoseidonZRGBController/ThermaltakePoseidonZRGBController.cpp b/Controllers/ThermaltakePoseidonZRGBController/ThermaltakePoseidonZRGBController.cpp index a0ffeb9c..136f2ba9 100644 --- a/Controllers/ThermaltakePoseidonZRGBController/ThermaltakePoseidonZRGBController.cpp +++ b/Controllers/ThermaltakePoseidonZRGBController/ThermaltakePoseidonZRGBController.cpp @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| ThermaltakePoseidonZRGBController.cpp | -| | -| Driver for Thermaltake Poseidon Z RGB | -| Keyboard lighting controller | -| | -| Adam Honse (CalcProgrammer1) 12/25/2019 | -\*-----------------------------------------*/ - -#include "ThermaltakePoseidonZRGBController.h" +/*---------------------------------------------------------*\ +| ThermaltakePoseidonZRGBController.cpp | +| | +| Driver for Thermaltake Poseidon Z RGB | +| | +| Adam Honse (CalcProgrammer1) 25 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "StringUtils.h" +#include "ThermaltakePoseidonZRGBController.h" using namespace std::chrono_literals; @@ -48,10 +50,7 @@ std::string PoseidonZRGBController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void PoseidonZRGBController::SetMode(unsigned char mode, unsigned char direction, unsigned char speed) @@ -121,7 +120,7 @@ void PoseidonZRGBController::SetLEDsDirect(std::vector colors) hid_send_feature_report(dev, red_grn_buf, 264); std::this_thread::sleep_for(5ms); - + hid_send_feature_report(dev, blu_buf, 264); } diff --git a/Controllers/ThermaltakePoseidonZRGBController/ThermaltakePoseidonZRGBController.h b/Controllers/ThermaltakePoseidonZRGBController/ThermaltakePoseidonZRGBController.h index d6ff43a6..fcc916ed 100644 --- a/Controllers/ThermaltakePoseidonZRGBController/ThermaltakePoseidonZRGBController.h +++ b/Controllers/ThermaltakePoseidonZRGBController/ThermaltakePoseidonZRGBController.h @@ -1,20 +1,20 @@ -/*-----------------------------------------*\ -| ThermaltakePoseidonZRGBController.h | -| | -| Definitions and types for Thermaltake | -| Poseidon Z RGB Keyboard lighting | -| controller | -| | -| Adam Honse (CalcProgrammer1) 12/25/2019 | -\*-----------------------------------------*/ - -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| ThermaltakePoseidonZRGBController.h | +| | +| Driver for Thermaltake Poseidon Z RGB | +| | +| Adam Honse (CalcProgrammer1) 25 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + #define POSEIDONZ_START 0x07 #define POSEIDONZ_PROFILE 0x01 #define POSEIDONZ_LED_CMD 0x0E @@ -83,7 +83,7 @@ public: void SetMode(unsigned char mode, unsigned char direction, unsigned char speed); void SetLEDsDirect(std::vector colors); void SetLEDs(std::vector colors); - + private: hid_device* dev; unsigned char active_mode; @@ -100,7 +100,7 @@ private: unsigned char brightness, unsigned char speed ); - + void SendColor ( unsigned char profile_to_edit, diff --git a/Controllers/ThermaltakePoseidonZRGBController/ThermaltakePoseidonZRGBControllerDetect.cpp b/Controllers/ThermaltakePoseidonZRGBController/ThermaltakePoseidonZRGBControllerDetect.cpp index a7dfcdef..d55650ee 100644 --- a/Controllers/ThermaltakePoseidonZRGBController/ThermaltakePoseidonZRGBControllerDetect.cpp +++ b/Controllers/ThermaltakePoseidonZRGBController/ThermaltakePoseidonZRGBControllerDetect.cpp @@ -1,9 +1,18 @@ +/*---------------------------------------------------------*\ +| ThermaltakePoseidonZRGBControllerDetect.cpp | +| | +| Detector for Thermaltake Poseidon Z RGB | +| | +| Adam Honse (CalcProgrammer1) 25 Dec 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "ThermaltakePoseidonZRGBController.h" -#include "RGBController.h" #include "RGBController_ThermaltakePoseidonZRGB.h" -#include -#include #define TT_POSEIDON_Z_RGB_VID 0x264A #define TT_POSEIDON_Z_RGB_PID 0x3006 diff --git a/Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiing.h b/Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiing.h deleted file mode 100644 index bd571f72..00000000 --- a/Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiing.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_ThermaltakeRiing.h | -| | -| Generic RGB Interface for Thermaltake | -| Riing controller | -| | -| Adam Honse (CalcProgrammer1) 2/9/2020 | -\*-----------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "ThermaltakeRiingController.h" - -class RGBController_ThermaltakeRiing : public RGBController -{ -public: - RGBController_ThermaltakeRiing(ThermaltakeRiingController* controller_ptr); - ~RGBController_ThermaltakeRiing(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - ThermaltakeRiingController* controller; - std::vector leds_channel; - std::vector zones_channel; -}; diff --git a/Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiingQuad.h b/Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiingQuad.h deleted file mode 100644 index 2f278341..00000000 --- a/Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiingQuad.h +++ /dev/null @@ -1,33 +0,0 @@ -/*-------------------------------------------------------------------*\ -| RGBController_ThermaltakeRiingQuad.cpp | -| | -| Driver for Thermaltake Riing Quad Controller | -| | -| Chris M (Dr_No) 15th Feb 2021 | -| | -\*-------------------------------------------------------------------*/ - -#pragma once -#include "RGBController.h" -#include "ThermaltakeRiingQuadController.h" - -class RGBController_ThermaltakeRiingQuad : public RGBController -{ -public: - RGBController_ThermaltakeRiingQuad(ThermaltakeRiingQuadController* controller_ptr); - ~RGBController_ThermaltakeRiingQuad(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - ThermaltakeRiingQuadController* controller; - std::vector leds_channel; - std::vector zones_channel; -}; diff --git a/Controllers/ThermaltakeRiingController/ThermaltakeRiingController.cpp b/Controllers/ThermaltakeRiingController/ThermaltakeRiingController.cpp deleted file mode 100644 index c11e1a54..00000000 --- a/Controllers/ThermaltakeRiingController/ThermaltakeRiingController.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/*-----------------------------------------*\ -| ThermaltakeRiingController.cpp | -| | -| Definitions and types for Thermaltake | -| Riing Plus lighting controller | -| | -| Adam Honse (CalcProgrammer1) 2/7/2020 | -\*-----------------------------------------*/ - -#include "ThermaltakeRiingController.h" - -#include - -ThermaltakeRiingController::ThermaltakeRiingController(hid_device* dev_handle, const char* path) -{ - dev = dev_handle; - location = path; - - SendInit(); -} - -ThermaltakeRiingController::~ThermaltakeRiingController() -{ - hid_close(dev); -} - -std::string ThermaltakeRiingController::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string ThermaltakeRiingController::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 ThermaltakeRiingController::SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors) -{ - unsigned char* color_data = new unsigned char[3 * num_colors]; - - for(std::size_t color = 0; color < num_colors; color++) - { - int color_idx = color * 3; - color_data[color_idx + 0] = RGBGetGValue(colors[color]); - color_data[color_idx + 1] = RGBGetRValue(colors[color]); - color_data[color_idx + 2] = RGBGetBValue(colors[color]); - } - - SendRGB(channel + 1, current_mode, current_speed, num_colors, color_data); - - delete[] color_data; -} - -void ThermaltakeRiingController::SetMode(unsigned char mode, unsigned char speed) -{ - current_mode = mode; - current_speed = speed; -} - -/*-------------------------------------------------------------------------------------------------*\ -| Private packet sending functions. | -\*-------------------------------------------------------------------------------------------------*/ - -void ThermaltakeRiingController::SendInit() -{ - unsigned char usb_buf[65]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, sizeof(usb_buf)); - - /*-----------------------------------------------------*\ - | Set up Init packet | - \*-----------------------------------------------------*/ - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0xFE; - usb_buf[0x02] = 0x33; - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); - hid_read(dev, usb_buf, 65); -} - -void ThermaltakeRiingController::SendRGB - ( - unsigned char port, - unsigned char mode, - unsigned char speed, - unsigned char num_colors, - unsigned char* color_data - ) -{ - unsigned char usb_buf[65]; - - /*-----------------------------------------------------*\ - | Zero out buffer | - \*-----------------------------------------------------*/ - memset(usb_buf, 0x00, sizeof(usb_buf)); - - /*-----------------------------------------------------*\ - | Set up RGB packet | - \*-----------------------------------------------------*/ - usb_buf[0x00] = 0x00; - usb_buf[0x01] = 0x32; - usb_buf[0x02] = 0x52; - usb_buf[0x03] = port; - usb_buf[0x04] = mode + ( speed & 0x03 ); - - /*-----------------------------------------------------*\ - | Copy in GRB color data | - \*-----------------------------------------------------*/ - memcpy(&usb_buf[0x05], color_data, (num_colors * 3)); - - /*-----------------------------------------------------*\ - | Send packet | - \*-----------------------------------------------------*/ - hid_write(dev, usb_buf, 65); - hid_read(dev, usb_buf, 65); -} diff --git a/Controllers/ThermaltakeRiingController/ThermaltakeRiingController.h b/Controllers/ThermaltakeRiingController/ThermaltakeRiingController.h deleted file mode 100644 index 5424562e..00000000 --- a/Controllers/ThermaltakeRiingController/ThermaltakeRiingController.h +++ /dev/null @@ -1,79 +0,0 @@ -/*-----------------------------------------*\ -| ThermaltakeRiingController.h | -| | -| Definitions and types for Thermaltake | -| Riing Plus lighting controller | -| | -| Adam Honse (CalcProgrammer1) 2/7/2020 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include - -#pragma once - -enum -{ - THERMALTAKE_PORT_1 = 0x01, - THERMALTAKE_PORT_2 = 0x02, - THERMALTAKE_PORT_3 = 0x03, - THERMALTAKE_PORT_4 = 0x04, - THERMALTAKE_PORT_5 = 0x05 -}; - -enum -{ - THERMALTAKE_MODE_FLOW = 0x00, - THERMALTAKE_MODE_SPECTRUM = 0x04, - THERMALTAKE_MODE_RIPPLE = 0x08, - THERMALTAKE_MODE_BLINK = 0x0C, - THERMALTAKE_MODE_PULSE = 0x10, - THERMALTAKE_MODE_WAVE = 0x14, - THERMALTAKE_MODE_PER_LED = 0x18, - THERMALTAKE_MODE_FULL = 0x19 -}; - -enum -{ - THERMALTAKE_SPEED_SLOW = 0x03, - THERMALTAKE_SPEED_NORMAL = 0x02, - THERMALTAKE_SPEED_FAST = 0x01, - THERMALTAKE_SPEED_EXTREME = 0x00 -}; - -#define THERMALTAKE_NUM_CHANNELS 5 - -class ThermaltakeRiingController -{ -public: - ThermaltakeRiingController(hid_device* dev_handle, const char* path); - ~ThermaltakeRiingController(); - - std::string GetDeviceLocation(); - std::string GetSerialString(); - - void SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors); - void SetMode(unsigned char mode, unsigned char speed); - -private: - hid_device* dev; - - unsigned char current_mode; - unsigned char current_speed; - std::string location; - - void SendInit(); - - void SendRGB - ( - unsigned char port, - unsigned char mode, - unsigned char speed, - unsigned char num_colors, - unsigned char* color_data - ); - - void SendFan(); - void SendSave(); -}; diff --git a/Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiing.cpp b/Controllers/ThermaltakeRiingController/ThermaltakeRiingController/RGBController_ThermaltakeRiing.cpp similarity index 88% rename from Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiing.cpp rename to Controllers/ThermaltakeRiingController/ThermaltakeRiingController/RGBController_ThermaltakeRiing.cpp index 6c9afa8e..93154251 100644 --- a/Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiing.cpp +++ b/Controllers/ThermaltakeRiingController/ThermaltakeRiingController/RGBController_ThermaltakeRiing.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_ThermaltakeRiing.cpp | -| | -| Generic RGB Interface for Thermaltake | -| Riing controller | -| | -| Adam Honse (CalcProgrammer1) 2/9/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ThermaltakeRiing.cpp | +| | +| RGBController for Thermaltake Riing | +| | +| Adam Honse (CalcProgrammer1) 09 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_ThermaltakeRiing.h" @@ -30,6 +32,7 @@ RGBController_ThermaltakeRiing::RGBController_ThermaltakeRiing(ThermaltakeRiingC description = "Thermaltake Riing Device"; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); + version = controller->GetFirmwareVersion(); mode Direct; Direct.name = "Direct"; @@ -205,7 +208,7 @@ void RGBController_ThermaltakeRiing::DeviceUpdateLEDs() { for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) { - controller->SetChannelLEDs(zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); + controller->SetChannelLEDs((unsigned char)zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); } } @@ -226,6 +229,6 @@ void RGBController_ThermaltakeRiing::DeviceUpdateMode() for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) { controller->SetMode(modes[active_mode].value, modes[active_mode].speed); - controller->SetChannelLEDs(zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); + controller->SetChannelLEDs((unsigned char)zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); } } diff --git a/Controllers/ThermaltakeRiingController/ThermaltakeRiingController/RGBController_ThermaltakeRiing.h b/Controllers/ThermaltakeRiingController/ThermaltakeRiingController/RGBController_ThermaltakeRiing.h new file mode 100644 index 00000000..bd4807d0 --- /dev/null +++ b/Controllers/ThermaltakeRiingController/ThermaltakeRiingController/RGBController_ThermaltakeRiing.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_ThermaltakeRiing.h | +| | +| RGBController for Thermaltake Riing | +| | +| Adam Honse (CalcProgrammer1) 09 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "ThermaltakeRiingController.h" + +class RGBController_ThermaltakeRiing : public RGBController +{ +public: + RGBController_ThermaltakeRiing(ThermaltakeRiingController* controller_ptr); + ~RGBController_ThermaltakeRiing(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + ThermaltakeRiingController* controller; + std::vector leds_channel; + std::vector zones_channel; +}; diff --git a/Controllers/ThermaltakeRiingController/ThermaltakeRiingController/ThermaltakeRiingController.cpp b/Controllers/ThermaltakeRiingController/ThermaltakeRiingController/ThermaltakeRiingController.cpp new file mode 100644 index 00000000..a32ea421 --- /dev/null +++ b/Controllers/ThermaltakeRiingController/ThermaltakeRiingController/ThermaltakeRiingController.cpp @@ -0,0 +1,158 @@ +/*---------------------------------------------------------*\ +| ThermaltakeRiingController.cpp | +| | +| Driver for Thermaltake Riing | +| | +| Adam Honse (CalcProgrammer1) 07 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "StringUtils.h" +#include "ThermaltakeRiingController.h" + +ThermaltakeRiingController::ThermaltakeRiingController(hid_device* dev_handle, const char* path) +{ + dev = dev_handle; + location = path; + + SendInit(); +} + +ThermaltakeRiingController::~ThermaltakeRiingController() +{ + hid_close(dev); +} + +std::string ThermaltakeRiingController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string ThermaltakeRiingController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +std::string ThermaltakeRiingController::GetFirmwareVersion() +{ + unsigned char usb_buf[64]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Get Firmware Version packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x33; + usb_buf[0x01] = 0x50; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 64); + hid_read(dev, usb_buf, 64); + + std::string ret_str = std::to_string(usb_buf[2]) + "." + std::to_string(usb_buf[3]) + "." + std::to_string(usb_buf[4]); + + return(ret_str); +} + +void ThermaltakeRiingController::SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors) +{ + unsigned char* color_data = new unsigned char[3 * num_colors]; + + for(unsigned int color = 0; color < num_colors; color++) + { + unsigned int color_idx = color * 3; + color_data[color_idx + 0] = RGBGetGValue(colors[color]); + color_data[color_idx + 1] = RGBGetRValue(colors[color]); + color_data[color_idx + 2] = RGBGetBValue(colors[color]); + } + + SendRGB(channel + 1, current_mode, current_speed, num_colors, color_data); + + delete[] color_data; +} + +void ThermaltakeRiingController::SetMode(unsigned char mode, unsigned char speed) +{ + current_mode = mode; + current_speed = speed; +} + +/*-------------------------------------------------------------------------------------------------*\ +| Private packet sending functions. | +\*-------------------------------------------------------------------------------------------------*/ + +void ThermaltakeRiingController::SendInit() +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Init packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0xFE; + usb_buf[0x02] = 0x33; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); + hid_read(dev, usb_buf, 65); +} + +void ThermaltakeRiingController::SendRGB + ( + unsigned char port, + unsigned char mode, + unsigned char speed, + unsigned char num_colors, + unsigned char* color_data + ) +{ + unsigned char usb_buf[65]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up RGB packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0x32; + usb_buf[0x02] = 0x52; + usb_buf[0x03] = port; + usb_buf[0x04] = mode + ( speed & 0x03 ); + + /*-----------------------------------------------------*\ + | Copy in GRB color data | + \*-----------------------------------------------------*/ + memcpy(&usb_buf[0x05], color_data, (num_colors * 3)); + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, 65); + hid_read(dev, usb_buf, 65); +} diff --git a/Controllers/ThermaltakeRiingController/ThermaltakeRiingController/ThermaltakeRiingController.h b/Controllers/ThermaltakeRiingController/ThermaltakeRiingController/ThermaltakeRiingController.h new file mode 100644 index 00000000..538984e0 --- /dev/null +++ b/Controllers/ThermaltakeRiingController/ThermaltakeRiingController/ThermaltakeRiingController.h @@ -0,0 +1,82 @@ +/*---------------------------------------------------------*\ +| ThermaltakeRiingController.h | +| | +| Driver for Thermaltake Riing | +| | +| Adam Honse (CalcProgrammer1) 07 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +enum +{ + THERMALTAKE_PORT_1 = 0x01, + THERMALTAKE_PORT_2 = 0x02, + THERMALTAKE_PORT_3 = 0x03, + THERMALTAKE_PORT_4 = 0x04, + THERMALTAKE_PORT_5 = 0x05 +}; + +enum +{ + THERMALTAKE_MODE_FLOW = 0x00, + THERMALTAKE_MODE_SPECTRUM = 0x04, + THERMALTAKE_MODE_RIPPLE = 0x08, + THERMALTAKE_MODE_BLINK = 0x0C, + THERMALTAKE_MODE_PULSE = 0x10, + THERMALTAKE_MODE_WAVE = 0x14, + THERMALTAKE_MODE_PER_LED = 0x18, + THERMALTAKE_MODE_FULL = 0x19 +}; + +enum +{ + THERMALTAKE_SPEED_SLOW = 0x03, + THERMALTAKE_SPEED_NORMAL = 0x02, + THERMALTAKE_SPEED_FAST = 0x01, + THERMALTAKE_SPEED_EXTREME = 0x00 +}; + +#define THERMALTAKE_NUM_CHANNELS 5 + +class ThermaltakeRiingController +{ +public: + ThermaltakeRiingController(hid_device* dev_handle, const char* path); + ~ThermaltakeRiingController(); + + std::string GetDeviceLocation(); + std::string GetSerialString(); + std::string GetFirmwareVersion(); + + void SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors); + void SetMode(unsigned char mode, unsigned char speed); + +private: + hid_device* dev; + + unsigned char current_mode; + unsigned char current_speed; + std::string location; + + void SendInit(); + + void SendRGB + ( + unsigned char port, + unsigned char mode, + unsigned char speed, + unsigned char num_colors, + unsigned char* color_data + ); + + void SendFan(); + void SendSave(); +}; diff --git a/Controllers/ThermaltakeRiingController/ThermaltakeRiingControllerDetect.cpp b/Controllers/ThermaltakeRiingController/ThermaltakeRiingControllerDetect.cpp index fc61013b..e15c8901 100644 --- a/Controllers/ThermaltakeRiingController/ThermaltakeRiingControllerDetect.cpp +++ b/Controllers/ThermaltakeRiingController/ThermaltakeRiingControllerDetect.cpp @@ -1,11 +1,25 @@ +/*---------------------------------------------------------*\ +| ThermaltakeRiingControllerDetect.cpp | +| | +| Detector for Thermaltake Riing devices | +| | +| Adam Honse (CalcProgrammer1) 07 Feb 2020 | +| Chris M (Dr_No) 15 Feb 2021 | +| Sam B (4rcheria) 24 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "ThermaltakeRiingController.h" #include "ThermaltakeRiingQuadController.h" -#include "RGBController.h" +#include "ThermaltakeRiingTrioController.h" #include "RGBController_ThermaltakeRiing.h" #include "RGBController_ThermaltakeRiingQuad.h" -#include -#include +#include "RGBController_ThermaltakeRiingTrio.h" + #define THERMALTAKE_RIING_VID 0x264A #define THERMALTAKE_RIING_PID_BEGIN 0x1FA5 @@ -43,6 +57,18 @@ void DetectThermaltakeRiingQuadControllers(hid_device_info* info, const std::str } } +void DetectThermaltakeRiingTrioControllers(hid_device_info* info, const std::string&) +{ + hid_device* dev = hid_open_path(info->path); + if(dev) + { + ThermaltakeRiingTrioController* controller = new ThermaltakeRiingTrioController(dev, info->path); + RGBController_ThermaltakeRiingTrio* rgb_controller = new RGBController_ThermaltakeRiingTrio(controller); + // Constructor sets the name + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + REGISTER_HID_DETECTOR("Thermaltake Riing (PID 0x1FA5)", DetectThermaltakeRiingControllers, THERMALTAKE_RIING_VID, 0x1FA5); REGISTER_HID_DETECTOR("Thermaltake Riing (PID 0x1FA6)", DetectThermaltakeRiingControllers, THERMALTAKE_RIING_VID, 0x1FA6); REGISTER_HID_DETECTOR("Thermaltake Riing (PID 0x1FA7)", DetectThermaltakeRiingControllers, THERMALTAKE_RIING_VID, 0x1FA7); @@ -78,3 +104,21 @@ REGISTER_HID_DETECTOR("Thermaltake Riing Quad (PID 0x226D)", DetectThermaltakeRi REGISTER_HID_DETECTOR("Thermaltake Riing Quad (PID 0x226E)", DetectThermaltakeRiingQuadControllers, THERMALTAKE_RIING_VID, 0x226E); REGISTER_HID_DETECTOR("Thermaltake Riing Quad (PID 0x226F)", DetectThermaltakeRiingQuadControllers, THERMALTAKE_RIING_VID, 0x226F); REGISTER_HID_DETECTOR("Thermaltake Riing Quad (PID 0x2270)", DetectThermaltakeRiingQuadControllers, THERMALTAKE_RIING_VID, 0x2270); +REGISTER_HID_DETECTOR("Thermaltake Riing Quad (PID 0x232B)", DetectThermaltakeRiingQuadControllers, THERMALTAKE_RIING_VID, 0x232B); + +REGISTER_HID_DETECTOR("Thermaltake Riing Trio (PID 0x2135)", DetectThermaltakeRiingTrioControllers, THERMALTAKE_RIING_VID, 0x2135); +REGISTER_HID_DETECTOR("Thermaltake Riing Trio (PID 0x2136)", DetectThermaltakeRiingTrioControllers, THERMALTAKE_RIING_VID, 0x2136); +REGISTER_HID_DETECTOR("Thermaltake Riing Trio (PID 0x2137)", DetectThermaltakeRiingTrioControllers, THERMALTAKE_RIING_VID, 0x2137); +REGISTER_HID_DETECTOR("Thermaltake Riing Trio (PID 0x2138)", DetectThermaltakeRiingTrioControllers, THERMALTAKE_RIING_VID, 0x2138); +REGISTER_HID_DETECTOR("Thermaltake Riing Trio (PID 0x2139)", DetectThermaltakeRiingTrioControllers, THERMALTAKE_RIING_VID, 0x2139); +REGISTER_HID_DETECTOR("Thermaltake Riing Trio (PID 0x213A)", DetectThermaltakeRiingTrioControllers, THERMALTAKE_RIING_VID, 0x213A); +REGISTER_HID_DETECTOR("Thermaltake Riing Trio (PID 0x213B)", DetectThermaltakeRiingTrioControllers, THERMALTAKE_RIING_VID, 0x213B); +REGISTER_HID_DETECTOR("Thermaltake Riing Trio (PID 0x213C)", DetectThermaltakeRiingTrioControllers, THERMALTAKE_RIING_VID, 0x213C); +REGISTER_HID_DETECTOR("Thermaltake Riing Trio (PID 0x213D)", DetectThermaltakeRiingTrioControllers, THERMALTAKE_RIING_VID, 0x213D); +REGISTER_HID_DETECTOR("Thermaltake Riing Trio (PID 0x213E)", DetectThermaltakeRiingTrioControllers, THERMALTAKE_RIING_VID, 0x213E); +REGISTER_HID_DETECTOR("Thermaltake Riing Trio (PID 0x213F)", DetectThermaltakeRiingTrioControllers, THERMALTAKE_RIING_VID, 0x213F); +REGISTER_HID_DETECTOR("Thermaltake Riing Trio (PID 0x2141)", DetectThermaltakeRiingTrioControllers, THERMALTAKE_RIING_VID, 0x2141); +REGISTER_HID_DETECTOR("Thermaltake Riing Trio (PID 0x2142)", DetectThermaltakeRiingTrioControllers, THERMALTAKE_RIING_VID, 0x2142); +REGISTER_HID_DETECTOR("Thermaltake Riing Trio (PID 0x2143)", DetectThermaltakeRiingTrioControllers, THERMALTAKE_RIING_VID, 0x2143); +REGISTER_HID_DETECTOR("Thermaltake Riing Trio (PID 0x2144)", DetectThermaltakeRiingTrioControllers, THERMALTAKE_RIING_VID, 0x2144); +REGISTER_HID_DETECTOR("Thermaltake Riing Trio (PID 0x2145)", DetectThermaltakeRiingTrioControllers, THERMALTAKE_RIING_VID, 0x2145); diff --git a/Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiingQuad.cpp b/Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController/RGBController_ThermaltakeRiingQuad.cpp similarity index 83% rename from Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiingQuad.cpp rename to Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController/RGBController_ThermaltakeRiingQuad.cpp index bf9790a2..40509078 100644 --- a/Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiingQuad.cpp +++ b/Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController/RGBController_ThermaltakeRiingQuad.cpp @@ -1,11 +1,13 @@ -/*-------------------------------------------------------------------*\ -| RGBController_ThermaltakeRiingQuad.cpp | -| | -| Driver for Thermaltake Riing Quad Controller | -| | -| Chris M (Dr_No) 15th Feb 2021 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ThermaltakeRiingQuad.cpp | +| | +| RGBController for Thermaltake Riing Quad | +| | +| Chris M (Dr_No) 15 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_ThermaltakeRiingQuad.h" @@ -85,7 +87,7 @@ void RGBController_ThermaltakeRiingQuad::SetupZones() | Riing Quad protocol is 54 | \*-------------------------------------------------*/ zones[channel_idx].leds_min = 0; - zones[channel_idx].leds_max = 54; + zones[channel_idx].leds_max = 60; if(first_run) { @@ -132,7 +134,7 @@ void RGBController_ThermaltakeRiingQuad::DeviceUpdateLEDs() { for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) { - controller->SetChannelLEDs(zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); + controller->SetChannelLEDs((unsigned char)zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); } } @@ -153,6 +155,6 @@ void RGBController_ThermaltakeRiingQuad::DeviceUpdateMode() for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) { controller->SetMode(modes[active_mode].value, modes[active_mode].speed); - controller->SetChannelLEDs(zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); + controller->SetChannelLEDs((unsigned char)zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); } } diff --git a/Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController/RGBController_ThermaltakeRiingQuad.h b/Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController/RGBController_ThermaltakeRiingQuad.h new file mode 100644 index 00000000..bfd36d09 --- /dev/null +++ b/Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController/RGBController_ThermaltakeRiingQuad.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_ThermaltakeRiingQuad.h | +| | +| RGBController for Thermaltake Riing Quad | +| | +| Chris M (Dr_No) 15 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "ThermaltakeRiingQuadController.h" + +class RGBController_ThermaltakeRiingQuad : public RGBController +{ +public: + RGBController_ThermaltakeRiingQuad(ThermaltakeRiingQuadController* controller_ptr); + ~RGBController_ThermaltakeRiingQuad(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + ThermaltakeRiingQuadController* controller; + std::vector leds_channel; + std::vector zones_channel; +}; diff --git a/Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController.cpp b/Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController/ThermaltakeRiingQuadController.cpp similarity index 76% rename from Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController.cpp rename to Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController/ThermaltakeRiingQuadController.cpp index a6e1c669..42574cbd 100644 --- a/Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController.cpp +++ b/Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController/ThermaltakeRiingQuadController.cpp @@ -1,34 +1,33 @@ -/*-------------------------------------------------------------------*\ -| ThermaltakeRiingQuadController.cpp | -| | -| Driver for Thermaltake Riing Quad Controller | -| | -| Chris M (Dr_No) 15th Feb 2021 | -| | -\*-------------------------------------------------------------------*/ - -#include "ThermaltakeRiingQuadController.h" +/*---------------------------------------------------------*\ +| ThermaltakeRiingQuadController.cpp | +| | +| Driver for Thermaltake Riing Quad | +| | +| Chris M (Dr_No) 15 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "StringUtils.h" +#include "ThermaltakeRiingQuadController.h" ThermaltakeRiingQuadController::ThermaltakeRiingQuadController(hid_device* dev_handle, const char* path) { - wchar_t tmpName[HID_MAX_STR]; - dev = dev_handle; location = path; - hid_get_manufacturer_string(dev, tmpName, HID_MAX_STR); - std::wstring wName = std::wstring(tmpName); - device_name = std::string(wName.begin(), wName.end()); + /*---------------------------------------------------------*\ + | Get device name from HID manufacturer and product strings | + \*---------------------------------------------------------*/ + wchar_t name_string[HID_MAX_STR]; - hid_get_product_string(dev, tmpName, HID_MAX_STR); - wName = std::wstring(tmpName); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); + hid_get_manufacturer_string(dev, name_string, HID_MAX_STR); + device_name = StringUtils::wstring_to_string(name_string); - hid_get_serial_number_string(dev, tmpName, HID_MAX_STR); - wName = std::wstring(tmpName); - serial = std::string(wName.begin(), wName.end()); + hid_get_product_string(dev, name_string, HID_MAX_STR); + device_name.append(" ").append(StringUtils::wstring_to_string(name_string)); SendInit(); @@ -86,16 +85,24 @@ std::string ThermaltakeRiingQuadController::GetDeviceLocation() std::string ThermaltakeRiingQuadController::GetSerial() { - return(serial); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } void ThermaltakeRiingQuadController::SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors) { unsigned char* color_data = new unsigned char[3 * num_colors]; - for(std::size_t color = 0; color < num_colors; color++) + for(unsigned int color = 0; color < num_colors; color++) { - int color_idx = color * 3; + unsigned int color_idx = color * 3; color_data[color_idx + 0] = RGBGetGValue(colors[color]); color_data[color_idx + 1] = RGBGetRValue(colors[color]); color_data[color_idx + 2] = RGBGetBValue(colors[color]); @@ -104,7 +111,7 @@ void ThermaltakeRiingQuadController::SetChannelLEDs(unsigned char channel, RGBCo tt_quad_buffer[channel][THERMALTAKE_QUAD_ZONE_BYTE] = channel + 1; tt_quad_buffer[channel][THERMALTAKE_QUAD_MODE_BYTE] = current_mode + ( current_speed & 0x03 ); memcpy(&tt_quad_buffer[channel][THERMALTAKE_QUAD_DATA_BYTE], color_data, (num_colors * 3)); - + hid_write(dev, tt_quad_buffer[channel], THERMALTAKE_QUAD_PACKET_SIZE); delete[] color_data; diff --git a/Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController.h b/Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController/ThermaltakeRiingQuadController.h similarity index 75% rename from Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController.h rename to Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController/ThermaltakeRiingQuadController.h index dab51396..de196a2f 100644 --- a/Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController.h +++ b/Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController/ThermaltakeRiingQuadController.h @@ -1,19 +1,21 @@ -/*-------------------------------------------------------------------*\ -| ThermaltakeRiingQuadController.h | -| | -| Driver for Thermaltake Riing Quad Controller | -| | -| Chris M (Dr_No) 15th Feb 2021 | -| | -\*-------------------------------------------------------------------*/ - -#include "RGBController.h" -#include -#include -#include +/*---------------------------------------------------------*\ +| ThermaltakeRiingQuadController.h | +| | +| Driver for Thermaltake Riing Quad | +| | +| Chris M (Dr_No) 15 Feb 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include +#include "RGBController.h" + #define THERMALTAKE_QUAD_PACKET_SIZE 193 #define THERMALTAKE_QUAD_INTERRUPT_TIMEOUT 250 #define THERMALTAKE_QUAD_KEEPALIVE 3 @@ -62,7 +64,6 @@ private: unsigned char current_mode; unsigned char current_speed; std::string device_name; - std::string serial; std::string location; uint8_t tt_quad_buffer[THERMALTAKE_QUAD_NUM_CHANNELS][THERMALTAKE_QUAD_PACKET_SIZE]; diff --git a/Controllers/ThermaltakeRiingController/ThermaltakeRiingTrioController/RGBController_ThermaltakeRiingTrio.cpp b/Controllers/ThermaltakeRiingController/ThermaltakeRiingTrioController/RGBController_ThermaltakeRiingTrio.cpp new file mode 100644 index 00000000..5f1bc721 --- /dev/null +++ b/Controllers/ThermaltakeRiingController/ThermaltakeRiingTrioController/RGBController_ThermaltakeRiingTrio.cpp @@ -0,0 +1,160 @@ +/*---------------------------------------------------------*\ +| RGBController_ThermaltakeRiingTrio.cpp | +| | +| RGBController for Thermaltake Riing Trio | +| | +| Sam B (4rcheria) 24 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_ThermaltakeRiingTrio.h" + +/**------------------------------------------------------------------*\ + @name Thermaltake Riing Trio + @category Cooler + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectThermaltakeRiingTrioControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_ThermaltakeRiingTrio::RGBController_ThermaltakeRiingTrio(ThermaltakeRiingTrioController* controller_ptr) +{ + controller = controller_ptr; + + name = "Thermaltake Trio"; + vendor = "Thermaltake"; + type = DEVICE_TYPE_COOLER; + description = "Thermaltake Riing Trio Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerial(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = THERMALTAKE_TRIO_MODE_DIRECT; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.speed_min = 0; + Direct.speed_max = 0; + Direct.speed = 0; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + SetupZones(); +} + +RGBController_ThermaltakeRiingTrio::~RGBController_ThermaltakeRiingTrio() +{ + delete controller; +} + +void RGBController_ThermaltakeRiingTrio::SetupZones() +{ + /*-------------------------------------------------*\ + | Only set LED count on the first run | + \*-------------------------------------------------*/ + bool first_run = false; + + if(zones.size() == 0) + { + first_run = true; + } + + /*-------------------------------------------------*\ + | Clear any existing color/LED configuration | + \*-------------------------------------------------*/ + leds.clear(); + colors.clear(); + zones.resize(THERMALTAKE_TRIO_NUM_CHANNELS); + + /*-------------------------------------------------*\ + | Set zones and leds | + \*-------------------------------------------------*/ + for (unsigned int channel_idx = 0; channel_idx < THERMALTAKE_TRIO_NUM_CHANNELS; channel_idx++) + { + char ch_idx_string[2]; + snprintf(ch_idx_string, 2, "%d", channel_idx + 1); + + zones[channel_idx].name = "Riing Channel "; + zones[channel_idx].name.append(ch_idx_string); + zones[channel_idx].type = ZONE_TYPE_LINEAR; + + /*-------------------------------------------------*\ + | The maximum number of colors that would fit in the| + | Riing Trio protocol is 54 | + \*-------------------------------------------------*/ + zones[channel_idx].leds_min = 0; + zones[channel_idx].leds_max = 54; + + if(first_run) + { + zones[channel_idx].leds_count = 0; + } + + zones[channel_idx].matrix_map = NULL; + + for (unsigned int led_ch_idx = 0; led_ch_idx < zones[channel_idx].leds_count; led_ch_idx++) + { + char led_idx_string[3]; + snprintf(led_idx_string, 3, "%d", led_ch_idx + 1); + + led new_led; + new_led.name = "Riing Channel "; + new_led.name.append(ch_idx_string); + new_led.name.append(", LED "); + new_led.name.append(led_idx_string); + + leds.push_back(new_led); + leds_channel.push_back(channel_idx); + } + } + + SetupColors(); +} + +void RGBController_ThermaltakeRiingTrio::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_ThermaltakeRiingTrio::DeviceUpdateLEDs() +{ + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + controller->SetChannelLEDs((unsigned char)zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); + } +} + +void RGBController_ThermaltakeRiingTrio::UpdateZoneLEDs(int zone) +{ + controller->SetChannelLEDs(zone, zones[zone].colors, zones[zone].leds_count); +} + +void RGBController_ThermaltakeRiingTrio::UpdateSingleLED(int led) +{ + unsigned int channel = leds_channel[led]; + + controller->SetChannelLEDs(channel, zones[channel].colors, zones[channel].leds_count); +} + +void RGBController_ThermaltakeRiingTrio::DeviceUpdateMode() +{ + for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) + { + controller->SetMode(modes[active_mode].value, modes[active_mode].speed); + controller->SetChannelLEDs((unsigned char)zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); + } +} diff --git a/Controllers/ThermaltakeRiingController/ThermaltakeRiingTrioController/RGBController_ThermaltakeRiingTrio.h b/Controllers/ThermaltakeRiingController/ThermaltakeRiingTrioController/RGBController_ThermaltakeRiingTrio.h new file mode 100644 index 00000000..0cda3b80 --- /dev/null +++ b/Controllers/ThermaltakeRiingController/ThermaltakeRiingTrioController/RGBController_ThermaltakeRiingTrio.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------*\ +| RGBController_ThermaltakeRiingTrio.h | +| | +| RGBController for Thermaltake Riing Trio | +| | +| Sam B (4rcheria) 24 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "ThermaltakeRiingTrioController.h" + +class RGBController_ThermaltakeRiingTrio : public RGBController +{ +public: + RGBController_ThermaltakeRiingTrio(ThermaltakeRiingTrioController* controller_ptr); + ~RGBController_ThermaltakeRiingTrio(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + ThermaltakeRiingTrioController* controller; + std::vector leds_channel; + std::vector zones_channel; +}; diff --git a/Controllers/ThermaltakeRiingController/ThermaltakeRiingTrioController/ThermaltakeRiingTrioController.cpp b/Controllers/ThermaltakeRiingController/ThermaltakeRiingTrioController/ThermaltakeRiingTrioController.cpp new file mode 100644 index 00000000..3d10e78b --- /dev/null +++ b/Controllers/ThermaltakeRiingController/ThermaltakeRiingTrioController/ThermaltakeRiingTrioController.cpp @@ -0,0 +1,146 @@ +/*---------------------------------------------------------*\ +| ThermaltakeRiingTrioController.cpp | +| | +| Driver for Thermaltake Riing Trio | +| | +| Sam B (4rcheria) 24 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "StringUtils.h" +#include "ThermaltakeRiingTrioController.h" + +ThermaltakeRiingTrioController::ThermaltakeRiingTrioController(hid_device* dev_handle, const char* path) +{ + dev = dev_handle; + location = path; + + /*---------------------------------------------------------*\ + | Get device name from HID manufacturer and product strings | + \*---------------------------------------------------------*/ + wchar_t name_string[HID_MAX_STR]; + + hid_get_manufacturer_string(dev, name_string, HID_MAX_STR); + device_name = StringUtils::wstring_to_string(name_string); + + hid_get_product_string(dev, name_string, HID_MAX_STR); + device_name.append(" ").append(StringUtils::wstring_to_string(name_string)); + + SendInit(); + + memset(tt_trio_buffer, 0x00, sizeof(tt_trio_buffer)); + unsigned char temp_buffer[3] = { 0x00, 0x32, 0x52 }; + + for(std::size_t zone_index = 0; zone_index < THERMALTAKE_TRIO_NUM_CHANNELS; zone_index++) + { + /*-------------------------------------------------*\ + | Add the constant bytes for the mode info buffer | + \*-------------------------------------------------*/ + memcpy(&tt_trio_buffer[zone_index][0], temp_buffer, 3); + } +} + +ThermaltakeRiingTrioController::~ThermaltakeRiingTrioController() +{ + hid_close(dev); +} + +std::string ThermaltakeRiingTrioController::GetDeviceName() +{ + return device_name; +} + +std::string ThermaltakeRiingTrioController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string ThermaltakeRiingTrioController::GetSerial() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void ThermaltakeRiingTrioController::SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors) +{ + if(num_colors == 0) return; + + unsigned char* color_data = new unsigned char[3 * num_colors]; + + for(unsigned int color = 0; color < num_colors; color++) + { + unsigned int color_idx = color * 3; + color_data[color_idx + 0] = RGBGetGValue(colors[color]); + color_data[color_idx + 1] = RGBGetRValue(colors[color]); + color_data[color_idx + 2] = RGBGetBValue(colors[color]); + } + + tt_trio_buffer[channel][THERMALTAKE_TRIO_ZONE_BYTE] = channel + 1; + tt_trio_buffer[channel][THERMALTAKE_TRIO_MODE_BYTE] = 0x24; + tt_trio_buffer[channel][5] = 0x03; + tt_trio_buffer[channel][7] = 0x00; + + /*-------------------------------------------------*\ + | create and send chunks min = 2 max = 4 | + \*-------------------------------------------------*/ + for(unsigned int i = 0; (num_colors > (THERMALTAKE_TRIO_CHUNK_LENGTH * i)) || i < 2; i++) + { + unsigned int colors_transmitted = THERMALTAKE_TRIO_CHUNK_LENGTH * i; + unsigned int colors_to_transmit = (num_colors > colors_transmitted) ? num_colors - colors_transmitted : 0; + + memset(&tt_trio_buffer[channel][THERMALTAKE_TRIO_CHUNK_ID], 0x00, sizeof(tt_trio_buffer[channel]) - THERMALTAKE_TRIO_CHUNK_ID); + tt_trio_buffer[channel][THERMALTAKE_TRIO_CHUNK_ID] = i + 1; + if(colors_to_transmit < THERMALTAKE_TRIO_CHUNK_LENGTH) + { + memcpy(&tt_trio_buffer[channel][THERMALTAKE_TRIO_DATA_BYTE], &color_data[colors_transmitted * 3], (colors_to_transmit * 3)); + } + else + { + memcpy(&tt_trio_buffer[channel][THERMALTAKE_TRIO_DATA_BYTE], &color_data[colors_transmitted * 3], (THERMALTAKE_TRIO_CHUNK_LENGTH * 3)); + } + + hid_write(dev, tt_trio_buffer[channel], THERMALTAKE_TRIO_PACKET_SIZE); + } + + delete[] color_data; +} + +void ThermaltakeRiingTrioController::SetMode(unsigned char mode, unsigned char speed) +{ + current_mode = mode; + current_speed = speed; +} + +void ThermaltakeRiingTrioController::SendInit() +{ + unsigned char usb_buf[THERMALTAKE_TRIO_PACKET_SIZE]; + + /*-----------------------------------------------------*\ + | Zero out buffer | + \*-----------------------------------------------------*/ + memset(usb_buf, 0x00, sizeof(usb_buf)); + + /*-----------------------------------------------------*\ + | Set up Init packet | + \*-----------------------------------------------------*/ + usb_buf[0x00] = 0x00; + usb_buf[0x01] = 0xFE; + usb_buf[0x02] = 0x33; + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_write(dev, usb_buf, THERMALTAKE_TRIO_PACKET_SIZE); + hid_read_timeout(dev, usb_buf, THERMALTAKE_TRIO_PACKET_SIZE, THERMALTAKE_TRIO_INTERRUPT_TIMEOUT); +} + diff --git a/Controllers/ThermaltakeRiingController/ThermaltakeRiingTrioController/ThermaltakeRiingTrioController.h b/Controllers/ThermaltakeRiingController/ThermaltakeRiingTrioController/ThermaltakeRiingTrioController.h new file mode 100644 index 00000000..fd06b2e1 --- /dev/null +++ b/Controllers/ThermaltakeRiingController/ThermaltakeRiingTrioController/ThermaltakeRiingTrioController.h @@ -0,0 +1,77 @@ +/*---------------------------------------------------------*\ +| ThermaltakeRiingTrioController.h | +| | +| Driver for Thermaltake Riing Trio | +| | +| Sam B (4rcheria) 24 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" + +#define THERMALTAKE_TRIO_PACKET_SIZE 65 +#define THERMALTAKE_TRIO_INTERRUPT_TIMEOUT 250 +#define THERMALTAKE_TRIO_KEEPALIVE 3 +#define HID_MAX_STR 255 + +enum +{ + THERMALTAKE_TRIO_COMMAND_BYTE = 1, + THERMALTAKE_TRIO_FUNCTION_BYTE = 2, + THERMALTAKE_TRIO_ZONE_BYTE = 3, + THERMALTAKE_TRIO_MODE_BYTE = 4, + THERMALTAKE_TRIO_CHUNK_ID = 6, + THERMALTAKE_TRIO_DATA_BYTE = 8, + THERMALTAKE_TRIO_CHUNK_LENGTH = 19, +}; + +enum +{ + THERMALTAKE_TRIO_MODE_DIRECT = 0x24 +}; + +enum +{ + THERMALTAKE_TRIO_SPEED_EXTREME = 0x00, + THERMALTAKE_TRIO_SPEED_FAST = 0x01, + THERMALTAKE_TRIO_SPEED_NORMAL = 0x02, + THERMALTAKE_TRIO_SPEED_SLOW = 0x03, +}; + +#define THERMALTAKE_TRIO_NUM_CHANNELS 5 + +class ThermaltakeRiingTrioController +{ +public: + ThermaltakeRiingTrioController(hid_device* dev_handle, const char* path); + ~ThermaltakeRiingTrioController(); + + std::string GetDeviceName(); + std::string GetDeviceLocation(); + std::string GetSerial(); + + void SetChannelLEDs(unsigned char channel, RGBColor * colors, unsigned int num_colors); + void SetMode(unsigned char mode, unsigned char speed); + +private: + hid_device* dev; + + unsigned char current_mode; + unsigned char current_speed; + std::string device_name; + std::string location; + + uint8_t tt_trio_buffer[THERMALTAKE_TRIO_NUM_CHANNELS][THERMALTAKE_TRIO_PACKET_SIZE]; + + void SendInit(); + + void SendFan(); + void SendSave(); +}; diff --git a/Controllers/ThingMController/BlinkController.cpp b/Controllers/ThingMController/BlinkController.cpp index 3eb3169f..119fb159 100644 --- a/Controllers/ThingMController/BlinkController.cpp +++ b/Controllers/ThingMController/BlinkController.cpp @@ -1,34 +1,33 @@ -/*-------------------------------------------------------------------*\ -| BlinkController.cpp | -| | -| Driver for ThingM Blink device | -| | -| Eric S (edbgon) 1st Oct 2021 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| BlinkController.cpp | +| | +| Driver for ThingM Blink | +| | +| Eric S (edbgon) 01 Oct 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "BlinkController.h" #include +#include "BlinkController.h" +#include "StringUtils.h" BlinkController::BlinkController(hid_device* dev_handle, char *_path) { dev = dev_handle; location = _path; - const int szTemp = 256; - wchar_t tmpName[szTemp]; + /*---------------------------------------------------------*\ + | Get device name from HID manufacturer and product strings | + \*---------------------------------------------------------*/ + wchar_t name_string[HID_MAX_STR]; - hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - device_name = std::string(wName.begin(), wName.end()); - - hid_get_product_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - device_name.append(" ").append(std::string(wName.begin(), wName.end())); - - hid_get_serial_number_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - serial = std::string(wName.begin(), wName.end()); + hid_get_manufacturer_string(dev, name_string, HID_MAX_STR); + device_name = StringUtils::wstring_to_string(name_string); + hid_get_product_string(dev, name_string, HID_MAX_STR); + device_name.append(" ").append(StringUtils::wstring_to_string(name_string)); } BlinkController::~BlinkController() @@ -46,7 +45,15 @@ std::string BlinkController::GetDeviceName() std::string BlinkController::GetSerial() { - return serial; + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } std::string BlinkController::GetLocation() @@ -55,24 +62,24 @@ std::string BlinkController::GetLocation() } void BlinkController::SendUpdate(unsigned char led, unsigned char red, unsigned char green, unsigned char blue, unsigned int speed) -{ +{ - unsigned char buffer[BLINK_PACKET_SIZE] = { 0x00 }; - memset(buffer, 0x00, BLINK_PACKET_SIZE); + unsigned char buffer[BLINK_PACKET_SIZE] = { 0x00 }; + memset(buffer, 0x00, BLINK_PACKET_SIZE); - buffer[0x00] = 0x01; - buffer[0x01] = 0x63; - buffer[0x02] = red; - buffer[0x03] = green; - buffer[0x04] = blue; + buffer[0x00] = 0x01; + buffer[0x01] = 0x63; + buffer[0x02] = red; + buffer[0x03] = green; + buffer[0x04] = blue; - if(speed > 0) - { - buffer[0x05] = (speed & 0xff00) >> 8; - buffer[0x06] = speed & 0x00ff; - } + if(speed > 0) + { + buffer[0x05] = (speed & 0xff00) >> 8; + buffer[0x06] = speed & 0x00ff; + } - buffer[0x07] = led; + buffer[0x07] = led; - hid_send_feature_report(dev, buffer, BLINK_PACKET_SIZE); + hid_send_feature_report(dev, buffer, BLINK_PACKET_SIZE); } diff --git a/Controllers/ThingMController/BlinkController.h b/Controllers/ThingMController/BlinkController.h index be0c39f4..946c5a01 100644 --- a/Controllers/ThingMController/BlinkController.h +++ b/Controllers/ThingMController/BlinkController.h @@ -1,23 +1,28 @@ -/*-------------------------------------------------------------------*\ -| BlinkController.h | -| | -| Driver for ThingM Blink device | -| | -| Eric S (edbgon) 1st Oct 2021 | -\*-------------------------------------------------------------------*/ - -#include -#include -#include +/*---------------------------------------------------------*\ +| BlinkController.h | +| | +| Driver for ThingM Blink | +| | +| Eric S (edbgon) 01 Oct 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include + #define BLINK_PACKET_SIZE 9 //Includes extra first byte for non HID Report packets #define BLINK_MODE_OFF 0 #define BLINK_MODE_DIRECT 1 #define BLINK_MODE_FADE 2 +#define HID_MAX_STR 255 + class BlinkController { public: diff --git a/Controllers/ThingMController/RGBController_BlinkController.cpp b/Controllers/ThingMController/RGBController_BlinkController.cpp index e8d87d13..859df1c4 100644 --- a/Controllers/ThingMController/RGBController_BlinkController.cpp +++ b/Controllers/ThingMController/RGBController_BlinkController.cpp @@ -1,10 +1,13 @@ -/*-------------------------------------------------------------------*\ -| RGBController_BlinkController.cpp | -| | -| Driver for ThingM Blink device | -| | -| Eric S (edbgon) 1st Oct 2021 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_BlinkController.cpp | +| | +| RGBController for ThingM Blink | +| | +| Eric S (edbgon) 01 Oct 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_BlinkController.h" @@ -102,9 +105,9 @@ void RGBController_BlinkController::ResizeZone(int /*zone*/, int /*new_size*/) void RGBController_BlinkController::DeviceUpdateLEDs() { - for (std::size_t led = 0; led < colors.size(); led++) + for(std::size_t led = 0; led < colors.size(); led++) { - UpdateSingleLED(led); + UpdateSingleLED((int)led); } } diff --git a/Controllers/ThingMController/RGBController_BlinkController.h b/Controllers/ThingMController/RGBController_BlinkController.h index effea10f..76a5cb0f 100644 --- a/Controllers/ThingMController/RGBController_BlinkController.h +++ b/Controllers/ThingMController/RGBController_BlinkController.h @@ -1,12 +1,16 @@ -/*-------------------------------------------------------------------*\ -| RGBController_BlinkController.h | -| | -| Driver for ThingM Blink device | -| | -| Eric S (edbgon) 1st Oct 2021 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_BlinkController.h | +| | +| RGBController for ThingM Blink | +| | +| Eric S (edbgon) 01 Oct 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "BlinkController.h" diff --git a/Controllers/ThingMController/ThingMControllerDetect.cpp b/Controllers/ThingMController/ThingMControllerDetect.cpp index 3b811804..a055539f 100644 --- a/Controllers/ThingMController/ThingMControllerDetect.cpp +++ b/Controllers/ThingMController/ThingMControllerDetect.cpp @@ -1,8 +1,18 @@ +/*---------------------------------------------------------*\ +| ThingMControllerDetect.cpp | +| | +| Detector for ThingM Blink | +| | +| Eric S (edbgon) 01 Oct 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "BlinkController.h" -#include "RGBController.h" #include "RGBController_BlinkController.h" -#include #define THINGM_VID 0x27B8 diff --git a/Controllers/TrustController/RGBController_TrustGXT114.h b/Controllers/TrustController/RGBController_TrustGXT114.h deleted file mode 100644 index aa9cf520..00000000 --- a/Controllers/TrustController/RGBController_TrustGXT114.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_TrustGXT114.h | -| | -| Generic RGB Interface for OpenRGB | -| Trust GXT 114 USB Driver | -| | -| Guimard Morgan (morg) 1/24/2022 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "TrustGXT114Controller.h" - -class RGBController_TrustGXT114 : public RGBController -{ -public: - RGBController_TrustGXT114(TrustGXT114Controller* controller_ptr); - ~RGBController_TrustGXT114(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - TrustGXT114Controller* controller; -}; diff --git a/Controllers/TrustController/RGBController_TrustGXT180.h b/Controllers/TrustController/RGBController_TrustGXT180.h deleted file mode 100644 index b03d486b..00000000 --- a/Controllers/TrustController/RGBController_TrustGXT180.h +++ /dev/null @@ -1,32 +0,0 @@ -/*-----------------------------------------*\ -| RGBController_TrustGXT180.h | -| | -| Generic RGB Interface for OpenRGB | -| Trust GXT 180 USB Driver | -| | -| Guimard Morgan (morg) 3/24/2022 | -\*-----------------------------------------*/ - -#pragma once - -#include "RGBController.h" -#include "TrustGXT180Controller.h" - -class RGBController_TrustGXT180 : public RGBController -{ -public: - RGBController_TrustGXT180(TrustGXT180Controller* controller_ptr); - ~RGBController_TrustGXT180(); - - void SetupZones(); - void ResizeZone(int zone, int new_size); - - void DeviceUpdateLEDs(); - void UpdateZoneLEDs(int zone); - void UpdateSingleLED(int led); - - void DeviceUpdateMode(); - -private: - TrustGXT180Controller* controller; -}; diff --git a/Controllers/TrustController/TrustControllerDetect.cpp b/Controllers/TrustController/TrustControllerDetect.cpp index f0b0e03b..7c01990b 100644 --- a/Controllers/TrustController/TrustControllerDetect.cpp +++ b/Controllers/TrustController/TrustControllerDetect.cpp @@ -1,7 +1,17 @@ +/*---------------------------------------------------------*\ +| TrustControllerDetect.cpp | +| | +| Detector for Trust devices | +| | +| Morgan Guimard (morg) 24 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "TrustGXT114Controller.h" #include "TrustGXT180Controller.h" -#include "RGBController.h" #include "RGBController_TrustGXT114.h" #include "RGBController_TrustGXT180.h" @@ -22,12 +32,12 @@ void DetectTrustGXT114Controllers(hid_device_info* info, const std::string& name if(dev) { - TrustGXT114Controller* controller = new TrustGXT114Controller(dev, *info); + TrustGXT114Controller* controller = new TrustGXT114Controller(dev, *info, name); if(controller->Test()) { RGBController_TrustGXT114* rgb_controller = new RGBController_TrustGXT114(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } else @@ -43,9 +53,9 @@ void DetectTrustGXT180Controllers(hid_device_info* info, const std::string& name if(dev) { - TrustGXT180Controller* controller = new TrustGXT180Controller(dev, *info); + TrustGXT180Controller* controller = new TrustGXT180Controller(dev, *info, name); RGBController_TrustGXT180* rgb_controller = new RGBController_TrustGXT180(controller); - rgb_controller->name = name; + ResourceManager::get()->RegisterRGBController(rgb_controller); } } diff --git a/Controllers/TrustController/TrustGXT114Controller.h b/Controllers/TrustController/TrustGXT114Controller.h deleted file mode 100644 index 791c8ee7..00000000 --- a/Controllers/TrustController/TrustGXT114Controller.h +++ /dev/null @@ -1,58 +0,0 @@ -/*-----------------------------------------*\ -| TrustGXT114Controller.h | -| | -| Driver for Trust GXT 114 | -| controller - header file | -| | -| Guimard Morgan (morg) 1/24/2022 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include - -#pragma once - -#define TRUST_GXT_114_REPORT_SIZE 154 -#define TRUST_GXT_114_NUMBER_OF_LEDS 1 -#define TRUST_GXT_114_REPORT_ID 0x04 - -enum -{ - STATIC_MODE_VALUE = 0x28, - BREATHING_MODE_VALUE = 0x22, - BLINK_MODE_VALUE = 0x42 -}; - -enum -{ - TRUST_GXT_114_BRIGHTNESS_MIN = 0x12, - TRUST_GXT_114_BRIGHTNESS_MAX = 0xA2 -}; - -enum -{ - TRUST_GXT_114_SPEED_MIN = 0x12, - TRUST_GXT_114_SPEED_MAX = 0x62 -}; - -class TrustGXT114Controller -{ -public: - TrustGXT114Controller(hid_device* dev_handle, const hid_device_info& info); - ~TrustGXT114Controller(); - - std::string GetSerialString(); - std::string GetDeviceLocation(); - std::string GetFirmwareVersion(); - bool Test(); - void SetMode(RGBColor color, unsigned char brightness, unsigned char speed, unsigned char mode_value); - -protected: - hid_device* dev; - -private: - std::string location; - std::string serial_number; - std::string version; -}; diff --git a/Controllers/TrustController/RGBController_TrustGXT114.cpp b/Controllers/TrustController/TrustGXT114Controller/RGBController_TrustGXT114.cpp similarity index 84% rename from Controllers/TrustController/RGBController_TrustGXT114.cpp rename to Controllers/TrustController/TrustGXT114Controller/RGBController_TrustGXT114.cpp index 04c5092f..061626ad 100644 --- a/Controllers/TrustController/RGBController_TrustGXT114.cpp +++ b/Controllers/TrustController/TrustGXT114Controller/RGBController_TrustGXT114.cpp @@ -1,16 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_TrustGXT114.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Trust GXT 114 USB Driver | -| | -| Guimard Morgan (morg) 1/24/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_TrustGXT114.cpp | +| | +| RGBController for Trust GXT 114 | +| | +| Morgan Guimard (morg) 24 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_TrustGXT114.h" - -#include #include +#include +#include "RGBController_TrustGXT114.h" /**------------------------------------------------------------------*\ @name Trust GXT 114 @@ -26,13 +27,13 @@ RGBController_TrustGXT114::RGBController_TrustGXT114(TrustGXT114Controller* controller_ptr) { controller = controller_ptr; - name = "Trust GXT 114"; + + name = controller->GetNameString(); vendor = "Trust"; type = DEVICE_TYPE_MOUSE; - description = name; + description = "Trust GXT 114 Device"; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); mode Static; Static.name = "Static"; diff --git a/Controllers/TrustController/TrustGXT114Controller/RGBController_TrustGXT114.h b/Controllers/TrustController/TrustGXT114Controller/RGBController_TrustGXT114.h new file mode 100644 index 00000000..9aba41d5 --- /dev/null +++ b/Controllers/TrustController/TrustGXT114Controller/RGBController_TrustGXT114.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_TrustGXT114.h | +| | +| RGBController for Trust GXT 114 | +| | +| Morgan Guimard (morg) 24 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "TrustGXT114Controller.h" + +class RGBController_TrustGXT114 : public RGBController +{ +public: + RGBController_TrustGXT114(TrustGXT114Controller* controller_ptr); + ~RGBController_TrustGXT114(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + TrustGXT114Controller* controller; +}; diff --git a/Controllers/TrustController/TrustGXT114Controller.cpp b/Controllers/TrustController/TrustGXT114Controller/TrustGXT114Controller.cpp similarity index 79% rename from Controllers/TrustController/TrustGXT114Controller.cpp rename to Controllers/TrustController/TrustGXT114Controller/TrustGXT114Controller.cpp index 0fd3e351..3f40a502 100644 --- a/Controllers/TrustController/TrustGXT114Controller.cpp +++ b/Controllers/TrustController/TrustGXT114Controller/TrustGXT114Controller.cpp @@ -1,32 +1,23 @@ -/*-----------------------------------------*\ -| TrustGXT114Controller.cpp | -| | -| Driver for Trust GXT 114 controller | -| | -| Guimard Morgan (morg) 1/24/2022 | -\*-----------------------------------------*/ -#include "TrustGXT114Controller.h" +/*---------------------------------------------------------*\ +| TrustGXT114Controller.cpp | +| | +| Driver for Trust GXT 114 | +| | +| Morgan Guimard (morg) 24 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include +#include "StringUtils.h" +#include "TrustGXT114Controller.h" -TrustGXT114Controller::TrustGXT114Controller(hid_device* dev_handle, const hid_device_info& info) +TrustGXT114Controller::TrustGXT114Controller(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) { - dev = dev_handle; - location = info.path; - version = ""; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } - + dev = dev_handle; + location = info.path; + name = dev_name; } TrustGXT114Controller::~TrustGXT114Controller() @@ -39,14 +30,22 @@ std::string TrustGXT114Controller::GetDeviceLocation() return("HID: " + location); } -std::string TrustGXT114Controller::GetSerialString() +std::string TrustGXT114Controller::GetNameString() { - return(serial_number); + return(name); } -std::string TrustGXT114Controller::GetFirmwareVersion() +std::string TrustGXT114Controller::GetSerialString() { - return(version); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } bool TrustGXT114Controller::Test() @@ -61,7 +60,7 @@ bool TrustGXT114Controller::Test() void TrustGXT114Controller::SetMode(RGBColor color, unsigned char brightness, unsigned char speed, unsigned char mode_value) { - unsigned char speed_bright = mode_value == STATIC_MODE_VALUE ? brightness : speed; + unsigned char speed_bright = mode_value == STATIC_MODE_VALUE ? brightness : speed; /*-----------------------------------------*\ | Create and zero out the buffer | diff --git a/Controllers/TrustController/TrustGXT114Controller/TrustGXT114Controller.h b/Controllers/TrustController/TrustGXT114Controller/TrustGXT114Controller.h new file mode 100644 index 00000000..b10bc1e4 --- /dev/null +++ b/Controllers/TrustController/TrustGXT114Controller/TrustGXT114Controller.h @@ -0,0 +1,60 @@ +/*---------------------------------------------------------*\ +| TrustGXT114Controller.h | +| | +| Driver for Trust GXT 114 | +| | +| Morgan Guimard (morg) 24 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define TRUST_GXT_114_REPORT_SIZE 154 +#define TRUST_GXT_114_NUMBER_OF_LEDS 1 +#define TRUST_GXT_114_REPORT_ID 0x04 + +enum +{ + STATIC_MODE_VALUE = 0x28, + BREATHING_MODE_VALUE = 0x22, + BLINK_MODE_VALUE = 0x42 +}; + +enum +{ + TRUST_GXT_114_BRIGHTNESS_MIN = 0x12, + TRUST_GXT_114_BRIGHTNESS_MAX = 0xA2 +}; + +enum +{ + TRUST_GXT_114_SPEED_MIN = 0x12, + TRUST_GXT_114_SPEED_MAX = 0x62 +}; + +class TrustGXT114Controller +{ +public: + TrustGXT114Controller(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~TrustGXT114Controller(); + + std::string GetSerialString(); + std::string GetDeviceLocation(); + std::string GetNameString(); + + bool Test(); + void SetMode(RGBColor color, unsigned char brightness, unsigned char speed, unsigned char mode_value); + +protected: + hid_device* dev; + +private: + std::string name; + std::string location; +}; diff --git a/Controllers/TrustController/TrustGXT180Controller.cpp b/Controllers/TrustController/TrustGXT180Controller.cpp deleted file mode 100644 index 53655435..00000000 --- a/Controllers/TrustController/TrustGXT180Controller.cpp +++ /dev/null @@ -1,82 +0,0 @@ -/*-----------------------------------------*\ -| TrustGXT180Controller.cpp | -| | -| Driver for Trust GXT 180 controller | -| | -| Guimard Morgan (morg) 3/24/2022 | -\*-----------------------------------------*/ -#include "TrustGXT180Controller.h" -#include - -TrustGXT180Controller::TrustGXT180Controller(hid_device* dev_handle, const hid_device_info& info) -{ - dev = dev_handle; - location = info.path; - version = ""; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } - -} - -TrustGXT180Controller::~TrustGXT180Controller() -{ - hid_close(dev); -} - -std::string TrustGXT180Controller::GetDeviceLocation() -{ - return("HID: " + location); -} - -std::string TrustGXT180Controller::GetSerialString() -{ - return(serial_number); -} - -std::string TrustGXT180Controller::GetFirmwareVersion() -{ - return(version); -} - -void TrustGXT180Controller::SetMode(RGBColor color, unsigned char brightness, unsigned char speed, unsigned char mode_value) -{ - /*-----------------------------------------*\ - | Create and zero out the buffer | - \*-----------------------------------------*/ - unsigned char usb_buf[TRUST_GXT_180_REPORT_SIZE]; - memset(usb_buf, 0x00, sizeof(usb_buf)); - - usb_buf[0] = TRUST_GXT_180_REPORT_ID; - usb_buf[1] = 0x06; - usb_buf[2] = 0xBB; - usb_buf[3] = 0xAA; - usb_buf[4] = 0x2A; - usb_buf[6] = 0x0A; - - if(mode_value != TRUST_GXT_180_OFF_MODE_VALUE) - { - usb_buf[8] = RGBGetRValue(color); - usb_buf[9] = RGBGetGValue(color); - usb_buf[10] = RGBGetBValue(color); - } - - usb_buf[11] = mode_value; - usb_buf[13] = brightness; - usb_buf[14] = speed; - - /*-----------------------------------------*\ - | Send the feature report | - \*-----------------------------------------*/ - hid_send_feature_report(dev, usb_buf, TRUST_GXT_180_REPORT_SIZE); -} diff --git a/Controllers/TrustController/TrustGXT180Controller.h b/Controllers/TrustController/TrustGXT180Controller.h deleted file mode 100644 index 841fe1bd..00000000 --- a/Controllers/TrustController/TrustGXT180Controller.h +++ /dev/null @@ -1,58 +0,0 @@ -/*-----------------------------------------*\ -| TrustGXT180Controller.h | -| | -| Driver for Trust GXT 180 | -| controller - header file | -| | -| Guimard Morgan (morg) 3/24/2022 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include - -#pragma once - -#define TRUST_GXT_180_REPORT_SIZE 64 -#define TRUST_GXT_180_NUMBER_OF_LEDS 1 -#define TRUST_GXT_180_REPORT_ID 0x03 - -enum -{ - TRUST_GXT_180_STATIC_MODE_VALUE = 0x01, - TRUST_GXT_180_BREATHING_MODE_VALUE = 0x02, - TRUST_GXT_180_COLORSHIFT_MODE_VALUE = 0x03, - TRUST_GXT_180_OFF_MODE_VALUE = 0x04 -}; - -enum -{ - TRUST_GXT_180_BRIGHTNESS_MIN = 0x00, - TRUST_GXT_180_BRIGHTNESS_MAX = 0x05 -}; - -enum -{ - TRUST_GXT_180_SPEED_MIN = 0x0A, - TRUST_GXT_180_SPEED_MAX = 0x00 -}; - -class TrustGXT180Controller -{ -public: - TrustGXT180Controller(hid_device* dev_handle, const hid_device_info& info); - ~TrustGXT180Controller(); - - std::string GetSerialString(); - std::string GetDeviceLocation(); - std::string GetFirmwareVersion(); - void SetMode(RGBColor color, unsigned char brightness, unsigned char speed, unsigned char mode_value); - -protected: - hid_device* dev; - -private: - std::string location; - std::string serial_number; - std::string version; -}; diff --git a/Controllers/TrustController/RGBController_TrustGXT180.cpp b/Controllers/TrustController/TrustGXT180Controller/RGBController_TrustGXT180.cpp similarity index 86% rename from Controllers/TrustController/RGBController_TrustGXT180.cpp rename to Controllers/TrustController/TrustGXT180Controller/RGBController_TrustGXT180.cpp index eb946475..30bf39d6 100644 --- a/Controllers/TrustController/RGBController_TrustGXT180.cpp +++ b/Controllers/TrustController/TrustGXT180Controller/RGBController_TrustGXT180.cpp @@ -1,16 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_TrustGXT180.cpp | -| | -| Generic RGB Interface for OpenRGB | -| Trust GXT 180 USB Driver | -| | -| Guimard Morgan (morg) 3/24/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_TrustGXT180.cpp | +| | +| RGBController for Trust GXT 180 | +| | +| Morgan Guimard (morg) 24 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController_TrustGXT180.h" - -#include #include +#include +#include "RGBController_TrustGXT180.h" /**------------------------------------------------------------------*\ @name Trust GXT 180 @@ -26,13 +27,13 @@ RGBController_TrustGXT180::RGBController_TrustGXT180(TrustGXT180Controller* controller_ptr) { controller = controller_ptr; - name = "Trust GXT 180"; + + name = controller->GetNameString(); vendor = "Trust"; type = DEVICE_TYPE_MOUSE; - description = name; + description = "Trust GXT 180 Device"; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); mode Static; Static.name = "Static"; diff --git a/Controllers/TrustController/TrustGXT180Controller/RGBController_TrustGXT180.h b/Controllers/TrustController/TrustGXT180Controller/RGBController_TrustGXT180.h new file mode 100644 index 00000000..996d0e61 --- /dev/null +++ b/Controllers/TrustController/TrustGXT180Controller/RGBController_TrustGXT180.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------*\ +| RGBController_TrustGXT180.h | +| | +| RGBController for Trust GXT 180 | +| | +| Morgan Guimard (morg) 24 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "TrustGXT180Controller.h" + +class RGBController_TrustGXT180 : public RGBController +{ +public: + RGBController_TrustGXT180(TrustGXT180Controller* controller_ptr); + ~RGBController_TrustGXT180(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + + void DeviceUpdateMode(); + +private: + TrustGXT180Controller* controller; +}; diff --git a/Controllers/TrustController/TrustGXT180Controller/TrustGXT180Controller.cpp b/Controllers/TrustController/TrustGXT180Controller/TrustGXT180Controller.cpp new file mode 100644 index 00000000..fc6d6b16 --- /dev/null +++ b/Controllers/TrustController/TrustGXT180Controller/TrustGXT180Controller.cpp @@ -0,0 +1,81 @@ +/*---------------------------------------------------------*\ +| TrustGXT180Controller.cpp | +| | +| Driver for Trust GXT 180 | +| | +| Morgan Guimard (morg) 24 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "StringUtils.h" +#include "TrustGXT180Controller.h" + +TrustGXT180Controller::TrustGXT180Controller(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) +{ + dev = dev_handle; + location = info.path; + name = dev_name; +} + +TrustGXT180Controller::~TrustGXT180Controller() +{ + hid_close(dev); +} + +std::string TrustGXT180Controller::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string TrustGXT180Controller::GetNameString() +{ + return(name); +} + +std::string TrustGXT180Controller::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +void TrustGXT180Controller::SetMode(RGBColor color, unsigned char brightness, unsigned char speed, unsigned char mode_value) +{ + /*-----------------------------------------*\ + | Create and zero out the buffer | + \*-----------------------------------------*/ + unsigned char usb_buf[TRUST_GXT_180_REPORT_SIZE]; + memset(usb_buf, 0x00, sizeof(usb_buf)); + + usb_buf[0] = TRUST_GXT_180_REPORT_ID; + usb_buf[1] = 0x06; + usb_buf[2] = 0xBB; + usb_buf[3] = 0xAA; + usb_buf[4] = 0x2A; + usb_buf[6] = 0x0A; + + if(mode_value != TRUST_GXT_180_OFF_MODE_VALUE) + { + usb_buf[8] = RGBGetRValue(color); + usb_buf[9] = RGBGetGValue(color); + usb_buf[10] = RGBGetBValue(color); + } + + usb_buf[11] = mode_value; + usb_buf[13] = brightness; + usb_buf[14] = speed; + + /*-----------------------------------------*\ + | Send the feature report | + \*-----------------------------------------*/ + hid_send_feature_report(dev, usb_buf, TRUST_GXT_180_REPORT_SIZE); +} diff --git a/Controllers/TrustController/TrustGXT180Controller/TrustGXT180Controller.h b/Controllers/TrustController/TrustGXT180Controller/TrustGXT180Controller.h new file mode 100644 index 00000000..cc764f68 --- /dev/null +++ b/Controllers/TrustController/TrustGXT180Controller/TrustGXT180Controller.h @@ -0,0 +1,60 @@ +/*---------------------------------------------------------*\ +| TrustGXT180Controller.h | +| | +| Driver for Trust GXT 180 | +| | +| Morgan Guimard (morg) 24 Mar 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +#define TRUST_GXT_180_REPORT_SIZE 64 +#define TRUST_GXT_180_NUMBER_OF_LEDS 1 +#define TRUST_GXT_180_REPORT_ID 0x03 + +enum +{ + TRUST_GXT_180_STATIC_MODE_VALUE = 0x01, + TRUST_GXT_180_BREATHING_MODE_VALUE = 0x02, + TRUST_GXT_180_COLORSHIFT_MODE_VALUE = 0x03, + TRUST_GXT_180_OFF_MODE_VALUE = 0x04 +}; + +enum +{ + TRUST_GXT_180_BRIGHTNESS_MIN = 0x00, + TRUST_GXT_180_BRIGHTNESS_MAX = 0x05 +}; + +enum +{ + TRUST_GXT_180_SPEED_MIN = 0x0A, + TRUST_GXT_180_SPEED_MAX = 0x00 +}; + +class TrustGXT180Controller +{ +public: + TrustGXT180Controller(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); + ~TrustGXT180Controller(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + + void SetMode(RGBColor color, unsigned char brightness, unsigned char speed, unsigned char mode_value); + +protected: + hid_device* dev; + +private: + std::string location; + std::string name; +}; diff --git a/Controllers/ValkyrieKeyboardController/RGBController_ValkyrieKeyboard.cpp b/Controllers/ValkyrieKeyboardController/RGBController_ValkyrieKeyboard.cpp new file mode 100644 index 00000000..389bbb6c --- /dev/null +++ b/Controllers/ValkyrieKeyboardController/RGBController_ValkyrieKeyboard.cpp @@ -0,0 +1,418 @@ +/*---------------------------------------------------------*\ +| RGBController_ValkyrieKeyboard.cpp | +| | +| RGBController for Valkyrie keyboard | +| | +| Nollie (Nuonuo) 06 Dec 2023 | +| Bartholomew Ho (imnotmental) 01 Feb 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBControllerKeyNames.h" +#include "RGBController_ValkyrieKeyboard.h" + +//0xFFFFFFFF indicates an unused entry in matrix +#define NA 0xFFFFFFFF + +static unsigned int matrix_map[6][22] = + { { 0, NA, 1, 2, 3, 4, NA, 5, 6, 7, 8, NA, 9, 10, 11, 12, NA, 13, NA, NA, NA, NA }, + { 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, NA, NA, NA, 28, 29, 30, 31, 32 }, + { 33, NA, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, NA, NA, 47, 48, 49, 50, 51 }, + { 52, NA, NA, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, NA, 63, 64, NA, 65, 66, 67, 68, NA }, + { 69, NA, NA, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, NA, NA, 81, NA, 82, 83, 84, 85 }, + { 86, 87, 88, NA, NA, NA, NA, 89, NA, NA, NA, NA, 90, 91, 92, 93, 94, 95, NA, 96, 97, NA } }; + +static unsigned int normal_matrix_map[6][22] = + {{ 0, NA, 1, 2, 3, 4, NA, 5, 6, 7, 8, NA, 9, 10, 11, 12, NA, 13, 14, 15, 16, 17 }, + { 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, NA, NA, NA, 32, 33, 34, 35, 36 }, + { 37, NA, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, NA, NA, 51, 52, 53, 54, 55 }, + { 56, NA, NA, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, NA, 67, 68, NA, 69, 70, 71, 72, NA }, + { 73, NA, NA, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, NA, NA, 85, NA, 86, 87, 88, 89 }, + { 90, 91, 92, NA, NA, NA, NA, 93, NA, NA, NA, NA, 94, 95, 96, 97, 98, 99, NA, 100, 101, NA } }; + +static const char* zone_names[] = +{ + ZONE_EN_KEYBOARD +}; + +static zone_type zone_types[] = +{ + ZONE_TYPE_MATRIX, +}; + +static const unsigned int zone_sizes[] = +{ + 98 +}; + +static const unsigned int normal_zone_sizes[] = +{ + 102 +}; + +static const char *led_names[] = +{ + KEY_EN_ESCAPE, + KEY_EN_F1, + KEY_EN_F2, + KEY_EN_F3, + KEY_EN_F4, + KEY_EN_F5, + KEY_EN_F6, + KEY_EN_F7, + KEY_EN_F8, + KEY_EN_F9, + KEY_EN_F10, + KEY_EN_F11, + KEY_EN_F12, + KEY_EN_DELETE, + KEY_EN_BACK_TICK, + KEY_EN_1, + KEY_EN_2, + KEY_EN_3, + KEY_EN_4, + KEY_EN_5, + KEY_EN_6, + KEY_EN_7, + KEY_EN_8, + KEY_EN_9, + KEY_EN_0, + KEY_EN_MINUS, + KEY_EN_PLUS, + KEY_EN_BACKSPACE, + KEY_EN_INSERT, + KEY_EN_NUMPAD_LOCK, + KEY_EN_NUMPAD_DIVIDE, + KEY_EN_NUMPAD_TIMES, + KEY_EN_NUMPAD_MINUS, + KEY_EN_TAB, + KEY_EN_Q, + KEY_EN_W, + KEY_EN_E, + KEY_EN_R, + KEY_EN_T, + KEY_EN_Y, + KEY_EN_U, + KEY_EN_I, + KEY_EN_O, + KEY_EN_P, + KEY_EN_LEFT_BRACKET, + KEY_EN_RIGHT_BRACKET, + KEY_EN_BACK_SLASH, + KEY_EN_PAGE_UP, + KEY_EN_NUMPAD_7, + KEY_EN_NUMPAD_8, + KEY_EN_NUMPAD_9, + KEY_EN_NUMPAD_PLUS, + KEY_EN_CAPS_LOCK, + KEY_EN_A, + KEY_EN_S, + KEY_EN_D, + KEY_EN_F, + KEY_EN_G, + KEY_EN_H, + KEY_EN_J, + KEY_EN_K, + KEY_EN_L, + KEY_EN_SEMICOLON, + KEY_EN_QUOTE, + KEY_EN_ANSI_ENTER, + KEY_EN_PAGE_DOWN, + KEY_EN_NUMPAD_4, + KEY_EN_NUMPAD_5, + KEY_EN_NUMPAD_6, + KEY_EN_LEFT_SHIFT, + KEY_EN_Z, + KEY_EN_X, + KEY_EN_C, + KEY_EN_V, + KEY_EN_B, + KEY_EN_N, + KEY_EN_M, + KEY_EN_COMMA, + KEY_EN_PERIOD, + KEY_EN_FORWARD_SLASH, + KEY_EN_RIGHT_SHIFT, + KEY_EN_UP_ARROW, + KEY_EN_NUMPAD_1, + KEY_EN_NUMPAD_2, + KEY_EN_NUMPAD_3, + KEY_EN_NUMPAD_ENTER, + KEY_EN_LEFT_CONTROL, + KEY_EN_LEFT_WINDOWS, + KEY_EN_LEFT_ALT, + KEY_EN_SPACE, + KEY_EN_RIGHT_ALT, + KEY_EN_RIGHT_FUNCTION, + KEY_EN_RIGHT_CONTROL, + KEY_EN_LEFT_ARROW, + KEY_EN_DOWN_ARROW, + KEY_EN_RIGHT_ARROW, + KEY_EN_NUMPAD_0, + KEY_EN_NUMPAD_PERIOD +}; + +static const char *normal_led_names[] = + { + KEY_EN_ESCAPE, + KEY_EN_F1, + KEY_EN_F2, + KEY_EN_F3, + KEY_EN_F4, + KEY_EN_F5, + KEY_EN_F6, + KEY_EN_F7, + KEY_EN_F8, + KEY_EN_F9, + KEY_EN_F10, + KEY_EN_F11, + KEY_EN_F12, + KEY_EN_DELETE, + KEY_EN_PRINT_SCREEN, + KEY_EN_PAUSE_BREAK, + KEY_EN_HOME, + KEY_EN_END, + KEY_EN_BACK_TICK, + KEY_EN_1, + KEY_EN_2, + KEY_EN_3, + KEY_EN_4, + KEY_EN_5, + KEY_EN_6, + KEY_EN_7, + KEY_EN_8, + KEY_EN_9, + KEY_EN_0, + KEY_EN_MINUS, + KEY_EN_PLUS, + KEY_EN_BACKSPACE, + KEY_EN_INSERT, + KEY_EN_NUMPAD_LOCK, + KEY_EN_NUMPAD_DIVIDE, + KEY_EN_NUMPAD_TIMES, + KEY_EN_NUMPAD_MINUS, + KEY_EN_TAB, + KEY_EN_Q, + KEY_EN_W, + KEY_EN_E, + KEY_EN_R, + KEY_EN_T, + KEY_EN_Y, + KEY_EN_U, + KEY_EN_I, + KEY_EN_O, + KEY_EN_P, + KEY_EN_LEFT_BRACKET, + KEY_EN_RIGHT_BRACKET, + KEY_EN_BACK_SLASH, + KEY_EN_PAGE_UP, + KEY_EN_NUMPAD_7, + KEY_EN_NUMPAD_8, + KEY_EN_NUMPAD_9, + KEY_EN_NUMPAD_PLUS, + KEY_EN_CAPS_LOCK, + KEY_EN_A, + KEY_EN_S, + KEY_EN_D, + KEY_EN_F, + KEY_EN_G, + KEY_EN_H, + KEY_EN_J, + KEY_EN_K, + KEY_EN_L, + KEY_EN_SEMICOLON, + KEY_EN_QUOTE, + KEY_EN_ANSI_ENTER, + KEY_EN_PAGE_DOWN, + KEY_EN_NUMPAD_4, + KEY_EN_NUMPAD_5, + KEY_EN_NUMPAD_6, + KEY_EN_LEFT_SHIFT, + KEY_EN_Z, + KEY_EN_X, + KEY_EN_C, + KEY_EN_V, + KEY_EN_B, + KEY_EN_N, + KEY_EN_M, + KEY_EN_COMMA, + KEY_EN_PERIOD, + KEY_EN_FORWARD_SLASH, + KEY_EN_RIGHT_SHIFT, + KEY_EN_UP_ARROW, + KEY_EN_NUMPAD_1, + KEY_EN_NUMPAD_2, + KEY_EN_NUMPAD_3, + KEY_EN_NUMPAD_ENTER, + KEY_EN_LEFT_CONTROL, + KEY_EN_LEFT_WINDOWS, + KEY_EN_LEFT_ALT, + KEY_EN_SPACE, + KEY_EN_RIGHT_ALT, + KEY_EN_RIGHT_FUNCTION, + KEY_EN_RIGHT_CONTROL, + KEY_EN_LEFT_ARROW, + KEY_EN_DOWN_ARROW, + KEY_EN_RIGHT_ARROW, + KEY_EN_NUMPAD_0, + KEY_EN_NUMPAD_PERIOD +}; +/**------------------------------------------------------------------*\ + @name Valkyrie + @category Keyboard + @type USB + @save :x: + @direct :white_check_mark: + @effects :x: + @detectors DetectValkyrieKeyboardControllers + @comment +\*-------------------------------------------------------------------*/ + +RGBController_ValkyrieKeyboard::RGBController_ValkyrieKeyboard(ValkyrieKeyboardController* controller_ptr) +{ + controller = controller_ptr; + + name = controller->GetNameString(); + vendor = "Valkyrie"; + type = DEVICE_TYPE_KEYBOARD; + description = "Valkyrie Keyboard Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); + + mode Direct; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; + modes.push_back(Direct); + + SetupZones(); +} + +RGBController_ValkyrieKeyboard::~RGBController_ValkyrieKeyboard() +{ + /*---------------------------------------------------------*\ + | Delete the matrix map | + \*---------------------------------------------------------*/ + 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; + } + break; + } + + delete controller; +} + +void RGBController_ValkyrieKeyboard::SetupZones() +{ + ValkyrieKeyboardMappingLayoutType layout; + switch(controller->GetInterfaceNum()) + { + case 3: + layout = PRO_LAYOUT; + break; + default: + layout = NORMAL_LAYOUT; + break; + } + + /*---------------------------------------------------------*\ + | Set up zones | + \*---------------------------------------------------------*/ + unsigned int total_led_count = 0; + for(unsigned int zone_idx = 0; zone_idx < 1; zone_idx++) + { + unsigned int zone_size = 0; + unsigned int matrix_width = 0; + unsigned int* matrix_map_ptr = NULL; + + switch(layout) + { + case PRO_LAYOUT: + zone_size = zone_sizes[zone_idx]; + matrix_width = 22; + matrix_map_ptr = (unsigned int *)&matrix_map; + break; + + default: + zone_size = normal_zone_sizes[zone_idx]; + matrix_width = 22; + matrix_map_ptr = (unsigned int *)&normal_matrix_map; + break; + } + + zone new_zone; + new_zone.name = zone_names[zone_idx]; + new_zone.type = zone_types[zone_idx]; + new_zone.leds_min = zone_size; + new_zone.leds_max = zone_size; + new_zone.leds_count = zone_size; + new_zone.matrix_map = new matrix_map_type; + new_zone.matrix_map->height = 6; + new_zone.matrix_map->width = matrix_width; + new_zone.matrix_map->map = matrix_map_ptr; + zones.push_back(new_zone); + + total_led_count += zone_size; + } + + for(unsigned int led_idx = 0; led_idx < total_led_count; led_idx++) + { + led new_led; + + switch(layout) + { + case PRO_LAYOUT: + new_led.name = led_names[led_idx]; + break; + default: + new_led.name = normal_led_names[led_idx]; + break; + } + + leds.push_back(new_led); + } + + SetupColors(); +} + +void RGBController_ValkyrieKeyboard::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_ValkyrieKeyboard::DeviceUpdateLEDs() +{ + unsigned char colordata[1024]; + + for(std::size_t color_idx = 0; color_idx < colors.size(); color_idx++) + { + colordata[(color_idx*3)+0] = RGBGetRValue(colors[color_idx]); + colordata[(color_idx*3)+1] = RGBGetGValue(colors[color_idx]); + colordata[(color_idx*3)+2] = RGBGetBValue(colors[color_idx]); + } + + controller->SendColors(colordata, sizeof(colordata)); +} + +void RGBController_ValkyrieKeyboard::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_ValkyrieKeyboard::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_ValkyrieKeyboard::DeviceUpdateMode() +{ + +} diff --git a/Controllers/ValkyrieKeyboardController/RGBController_ValkyrieKeyboard.h b/Controllers/ValkyrieKeyboardController/RGBController_ValkyrieKeyboard.h new file mode 100644 index 00000000..f1d790d1 --- /dev/null +++ b/Controllers/ValkyrieKeyboardController/RGBController_ValkyrieKeyboard.h @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| RGBController_ValkyrieKeyboard.h | +| | +| RGBController for Valkyrie keyboard | +| | +| Nollie (Nuonuo) 06 Dec 2023 | +| Bartholomew Ho (imnotmental) 01 Feb 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "ValkyrieKeyboardController.h" + +enum ValkyrieKeyboardMappingLayoutType +{ + NORMAL_LAYOUT, + PRO_LAYOUT, +}; + +class RGBController_ValkyrieKeyboard : public RGBController +{ +public: + RGBController_ValkyrieKeyboard(ValkyrieKeyboardController* controller_ptr); + ~RGBController_ValkyrieKeyboard(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + void DeviceUpdateMode(); + +private: + ValkyrieKeyboardController* controller; +}; diff --git a/Controllers/ValkyrieKeyboardController/ValkyrieKeyboardController.cpp b/Controllers/ValkyrieKeyboardController/ValkyrieKeyboardController.cpp new file mode 100644 index 00000000..6e0f5358 --- /dev/null +++ b/Controllers/ValkyrieKeyboardController/ValkyrieKeyboardController.cpp @@ -0,0 +1,166 @@ +/*---------------------------------------------------------*\ +| ValkyrieKeyboardController.cpp | +| | +| Driver for Valkyrie keyboard | +| | +| Nollie (Nuonuo) 06 Dec 2023 | +| Bartholomew Ho (imnotmental) 01 Feb 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "StringUtils.h" +#include "ValkyrieKeyboardController.h" + +ValkyrieKeyboardController::ValkyrieKeyboardController(hid_device* dev_handle, const char* path, const unsigned short pid, const int interface, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + usb_pid = pid; + interface_num = interface; +} + +ValkyrieKeyboardController::~ValkyrieKeyboardController() +{ + hid_close(dev); +} + +std::string ValkyrieKeyboardController::GetDeviceLocation() +{ + return("HID: " + location); +} + +std::string ValkyrieKeyboardController::GetNameString() +{ + return(name); +} + +std::string ValkyrieKeyboardController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +unsigned short ValkyrieKeyboardController::GetUSBPID() +{ + return(usb_pid); +} + +int ValkyrieKeyboardController::GetInterfaceNum() +{ + return(interface_num); +} + +void ValkyrieKeyboardController::SendColors(unsigned char* color_data, unsigned int /*color_data_size*/) +{ + unsigned char usb_buf_pro[392]; + unsigned char usb_buf_normal[408]; + int led_num = 0; + + switch(interface_num) + { + case 3: + led_num = 98; + for(int i = 0; i < led_num; i++) + { + usb_buf_pro[i * 4] = key_code_99[i]; + usb_buf_pro[i * 4 + 1] = color_data[i * 3]; + usb_buf_pro[i * 4 + 2] = color_data[i * 3 + 1]; + usb_buf_pro[i * 4 + 3] = color_data[i * 3 + 2]; + } + break; + default: + led_num = 102; + for(int i = 0; i < led_num; i++) + { + usb_buf_normal[i * 4] = key_code_103[i]; + usb_buf_normal[i * 4 + 1] = color_data[i * 3]; + usb_buf_normal[i * 4 + 2] = color_data[i * 3 + 1]; + usb_buf_normal[i * 4 + 3] = color_data[i * 3 + 2]; + } + } + + SendInitializeColorPacket(); + + for(int i = 0; i <= 6; i++) + { + unsigned int usb_data_num = 16; + if(i == 6) + { + usb_data_num = led_num - usb_data_num * 6; + } + char send_usb_buf[65]; + memset(send_usb_buf, 0x00, sizeof(send_usb_buf)); + + switch(interface_num) + { + case 3: + for(unsigned int index = 0; index < usb_data_num; index++) + { + send_usb_buf[index * 4 + 1] = usb_buf_pro[index * 4 + i * 64 ]; + send_usb_buf[index * 4 + 2] = usb_buf_pro[index * 4 + i * 64 + 1]; + send_usb_buf[index * 4 + 3] = usb_buf_pro[index * 4 + i * 64 + 2]; + send_usb_buf[index * 4 + 4] = usb_buf_pro[index * 4 + i * 64 + 3]; + } + break; + default: + for(unsigned int index = 0; index < usb_data_num; index++) + { + send_usb_buf[index * 4 + 1] = usb_buf_normal[index * 4 + i * 64 ]; + send_usb_buf[index * 4 + 2] = usb_buf_normal[index * 4 + i * 64 + 1]; + send_usb_buf[index * 4 + 3] = usb_buf_normal[index * 4 + i * 64 + 2]; + send_usb_buf[index * 4 + 4] = usb_buf_normal[index * 4 + i * 64 + 3]; + } + break; + } + + /*-----------------------------------------------------*\ + | Send packet | + \*-----------------------------------------------------*/ + hid_send_feature_report(dev, (unsigned char *)send_usb_buf, 65); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + SendTerminateColorPacket(); + std::this_thread::sleep_for(std::chrono::milliseconds(33)); +} + +void ValkyrieKeyboardController::SendInitializeColorPacket() +{ + uint8_t usb_write_buf[65]; + uint8_t usb_read_buf[65]; + memset(usb_write_buf, 0x00, sizeof(usb_write_buf)); + memset(usb_read_buf, 0x00, sizeof(usb_read_buf)); + usb_write_buf[1] = 0x04; + usb_write_buf[2] = 0x20; + usb_write_buf[9] = 0x08; + hid_send_feature_report(dev, (unsigned char *)usb_write_buf, 65); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + hid_get_feature_report (dev, (unsigned char *)usb_read_buf, 65); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); +} + +void ValkyrieKeyboardController::SendTerminateColorPacket() +{ + uint8_t usb_write_buf[65]; + uint8_t usb_read_buf[65]; + memset(usb_write_buf, 0x00, sizeof(usb_write_buf)); + memset(usb_read_buf, 0x00, sizeof(usb_read_buf)); + hid_send_feature_report(dev, (unsigned char *)usb_write_buf, 65); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + usb_write_buf[1] = 0x04; + usb_write_buf[2] = 0x02; + hid_send_feature_report(dev, (unsigned char *)usb_write_buf, 65); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + hid_get_feature_report (dev, (unsigned char *)usb_read_buf, 65); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); +} diff --git a/Controllers/ValkyrieKeyboardController/ValkyrieKeyboardController.h b/Controllers/ValkyrieKeyboardController/ValkyrieKeyboardController.h new file mode 100644 index 00000000..793be80e --- /dev/null +++ b/Controllers/ValkyrieKeyboardController/ValkyrieKeyboardController.h @@ -0,0 +1,78 @@ +/*---------------------------------------------------------*\ +| ValkyrieKeyboardController.h | +| | +| Driver for Valkyrie keyboard | +| | +| Nollie (Nuonuo) 06 Dec 2023 | +| Bartholomew Ho (imnotmental) 01 Feb 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "RGBController.h" + +/*-----------------------------------------------------*\ +| Valkyrie vendor ID | +\*-----------------------------------------------------*/ +#define VALKYRIE_VID 0x05AC + +/*-----------------------------------------------------*\ +| Keyboard product IDs | +\*-----------------------------------------------------*/ +#define VALKYRIE_99_PRO_PID 0x024F +#define VALKYRIE_99_NORMAL_PID 0x024F + +class ValkyrieKeyboardController +{ +public: + ValkyrieKeyboardController(hid_device* dev_handle, const char* path, const unsigned short pid, const int interface, std::string dev_name); + ~ValkyrieKeyboardController(); + + std::string GetDeviceLocation(); + std::string GetNameString(); + std::string GetSerialString(); + unsigned short GetUSBPID(); + int GetInterfaceNum(); + + void SendColors + ( + unsigned char* color_data, + unsigned int color_data_size + ); + +private: + hid_device* dev; + std::string location; + std::string name; + unsigned short usb_pid; + int interface_num; + + int key_code_99[98] = + { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x77, + 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x67, + 0x74,0x20,0x21,0x22,0x7A,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D, + 0x2E,0x2F,0x30,0x31,0x43,0x76,0x32,0x33,0x34,0x7B,0x37,0x38,0x39,0x3A, + 0x3B,0x3C,0x3D,0x3E,0x3F,0x40,0x41,0x42,0x55,0x79,0x44,0x45,0x46,0x49, + 0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,0x65,0x56,0x57, + 0x58,0x6A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60,0x62,0x63,0x64,0x66,0x68,0x69 + }; + int key_code_103[102] = + { + 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x77,0x70,0x73, + 0x75,0x78,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x67, + 0x74,0x20,0x21,0x22,0x7A,0x25,0x26,0x27,0x28,0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F, + 0x30,0x31,0x43,0x76,0x32,0x33,0x34,0x7B,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E, + 0x3F,0x40,0x41,0x42,0x55,0x79,0x44,0x45,0x46,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F, + 0x50,0x51,0x52,0x53,0x54,0x65,0x56,0x57,0x58,0x6A,0x5B,0x5C,0x5D,0x5E,0x5F,0x60, + 0x62,0x63,0x64,0x66,0x68,0x69 + }; + + void SendInitializeColorPacket(); + void SendTerminateColorPacket(); +}; diff --git a/Controllers/ValkyrieKeyboardController/ValkyrieKeyboardControllerDetect.cpp b/Controllers/ValkyrieKeyboardController/ValkyrieKeyboardControllerDetect.cpp new file mode 100644 index 00000000..c3415533 --- /dev/null +++ b/Controllers/ValkyrieKeyboardController/ValkyrieKeyboardControllerDetect.cpp @@ -0,0 +1,31 @@ +/*---------------------------------------------------------*\ +| ValkyrieKeyboardControllerDetect.cpp | +| | +| Detector for Valkyrie keyboard | +| | +| Nollie (Nuonuo) 06 Dec 2023 | +| Bartholomew Ho (imnotmental) 01 Feb 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "RGBController_ValkyrieKeyboard.h" + +void DetectValkyrieKeyboardControllers(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + if(dev) + { + ValkyrieKeyboardController* controller = new ValkyrieKeyboardController(dev, info->path, info->product_id, info->interface_number, name); + RGBController_ValkyrieKeyboard* rgb_controller = new RGBController_ValkyrieKeyboard(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} + +/* DetectValkyrieKeyboardControllers() */ +REGISTER_HID_DETECTOR_IPU("Valkyrie VK99 Pro", DetectValkyrieKeyboardControllers, VALKYRIE_VID, VALKYRIE_99_PRO_PID, 3, 0xFF13, 0x0001); +REGISTER_HID_DETECTOR_IPU("Valkyrie VK99", DetectValkyrieKeyboardControllers, VALKYRIE_VID, VALKYRIE_99_NORMAL_PID, 2, 0xFF13, 0x0001); diff --git a/Controllers/ViewSonicController/RGBController_XG270QG.cpp b/Controllers/ViewSonicController/RGBController_XG270QG.cpp index 05d72e3f..54a28fa8 100644 --- a/Controllers/ViewSonicController/RGBController_XG270QG.cpp +++ b/Controllers/ViewSonicController/RGBController_XG270QG.cpp @@ -1,12 +1,16 @@ -/*------------------------------------*\ -| RGBController_XG270QG.cpp | -| Lanzaa 1/23/2022 | -\*------------------------------------*/ - -#include "RGBController_XG270QG.h" -#include "LogManager.h" +/*---------------------------------------------------------*\ +| RGBController_XG270QG.cpp | +| | +| RGBController for ViewSonic XG270QG | +| | +| Lanzaa 23 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "RGBController_XG270QG.h" /**------------------------------------------------------------------*\ @name Viewsonic Monitor @@ -21,14 +25,14 @@ RGBController_XG270QG::RGBController_XG270QG(VS_XG270QG_Controller* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "ViewSonic Elite XG270QG"; - vendor = "ViewSonic"; - type = DEVICE_TYPE_ACCESSORY; - description = "ViewSonic Monitor"; - location = controller->GetLocation(); - serial = controller->GetSerial(); + name = controller->GetName(); + vendor = "ViewSonic"; + type = DEVICE_TYPE_MONITOR; + description = "ViewSonic Monitor Device"; + location = controller->GetLocation(); + serial = controller->GetSerial(); mode Off; Off.name = "Off"; @@ -36,15 +40,15 @@ RGBController_XG270QG::RGBController_XG270QG(VS_XG270QG_Controller* controller_p Off.color_mode = MODE_COLORS_NONE; modes.push_back(Off); - mode StaticColor; - StaticColor.name = "Static"; - StaticColor.value = VS_MODE_STATIC; - StaticColor.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE; - StaticColor.colors_min = 1; - StaticColor.colors_max = 1; - StaticColor.color_mode = MODE_COLORS_MODE_SPECIFIC; - StaticColor.colors.resize(1); - modes.push_back(StaticColor); + mode Custom; + Custom.name = "Custom"; + Custom.value = VS_MODE_STATIC; + Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Custom.colors_min = 1; + Custom.colors_max = 1; + Custom.color_mode = MODE_COLORS_PER_LED; + Custom.colors.resize(1); + modes.push_back(Custom); mode Rainbow; Rainbow.name = "Rainbow Wave"; @@ -56,10 +60,10 @@ RGBController_XG270QG::RGBController_XG270QG(VS_XG270QG_Controller* controller_p mode Breath; Breath.name = "Breathing"; Breath.value = VS_MODE_BREATHING; - Breath.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Breath.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; Breath.colors_min = 1; Breath.colors_max = 1; - Breath.color_mode = MODE_COLORS_MODE_SPECIFIC; + Breath.color_mode = MODE_COLORS_PER_LED; Breath.colors.resize(1); modes.push_back(Breath); @@ -73,10 +77,10 @@ RGBController_XG270QG::RGBController_XG270QG(VS_XG270QG_Controller* controller_p mode Elite; Elite.name = "Elite"; Elite.value = VS_MODE_ELITE; - Elite.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_AUTOMATIC_SAVE; + Elite.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_AUTOMATIC_SAVE; Elite.colors_min = 1; Elite.colors_max = 1; - Elite.color_mode = MODE_COLORS_MODE_SPECIFIC; + Elite.color_mode = MODE_COLORS_PER_LED; Elite.colors.resize(1); modes.push_back(Elite); @@ -103,34 +107,34 @@ RGBController_XG270QG::RGBController_XG270QG(VS_XG270QG_Controller* controller_p void RGBController_XG270QG::SetupZones() { - zone back_circle; - back_circle.name = "Back Circle"; - back_circle.type = ZONE_TYPE_SINGLE; - back_circle.leds_min = 1; - back_circle.leds_max = 1; - back_circle.leds_count = 1; - back_circle.matrix_map = NULL; - zones.push_back(back_circle); + zone base; + base.name = "Base"; + base.type = ZONE_TYPE_SINGLE; + base.leds_min = 1; + base.leds_max = 1; + base.leds_count = 1; + base.matrix_map = NULL; + zones.push_back(base); - zone down; - down.name = "Down Stuff"; - down.type = ZONE_TYPE_SINGLE; - down.leds_min = 1; - down.leds_max = 1; - down.leds_count = 1; - down.matrix_map = NULL; - zones.push_back(down); - - led back; - back.name = "Back"; - back.value = 0x00; - leds.push_back(back); + zone rear; + rear.name = "Rear"; + rear.type = ZONE_TYPE_SINGLE; + rear.leds_min = 1; + rear.leds_max = 1; + rear.leds_count = 1; + rear.matrix_map = NULL; + zones.push_back(rear); led d; - d.name = "Down"; - d.value = 0x01; + d.name = "Base"; + d.value = 0x00; leds.push_back(d); + led back; + back.name = "Rear"; + back.value = 0x01; + leds.push_back(back); + SetupColors(); } @@ -143,9 +147,7 @@ void RGBController_XG270QG::ResizeZone(int /*zone*/, int /*new_size*/) void RGBController_XG270QG::DeviceUpdateLEDs() { - /*---------------------------------------------------------*\ - | This device does not include any per-LED modes | - \*---------------------------------------------------------*/ + DeviceUpdateMode(); } void RGBController_XG270QG::UpdateZoneLEDs(int /*zone*/) @@ -160,14 +162,28 @@ void RGBController_XG270QG::UpdateSingleLED(int /*led*/) void RGBController_XG270QG::DeviceUpdateMode() { - uint8_t r = 0; - uint8_t g = 0; - uint8_t b = 0; + uint8_t r1 = 0; + uint8_t g1 = 0; + uint8_t b1 = 0; + uint8_t r2 = 0; + uint8_t g2 = 0; + uint8_t b2 = 0; + if(modes[active_mode].flags & MODE_FLAG_HAS_MODE_SPECIFIC_COLOR) { - r = RGBGetRValue(modes[active_mode].colors[0]); - g = RGBGetGValue(modes[active_mode].colors[0]); - b = RGBGetBValue(modes[active_mode].colors[0]); + r1 = r2 = RGBGetRValue(modes[active_mode].colors[0]); + g1 = g2 = RGBGetGValue(modes[active_mode].colors[0]); + b1 = b2 = RGBGetBValue(modes[active_mode].colors[0]); } - controller->SetMode(modes[active_mode].value, r, g, b); + else if (modes[active_mode].flags & MODE_FLAG_HAS_PER_LED_COLOR) + { + r1 = RGBGetRValue(colors[0]); + g1 = RGBGetGValue(colors[0]); + b1 = RGBGetBValue(colors[0]); + + r2 = RGBGetRValue(colors[1]); + g2 = RGBGetGValue(colors[1]); + b2 = RGBGetBValue(colors[1]); + } + controller->SetMode(modes[active_mode].value, r1, g1, b1, modes[active_mode].value, r2, g2, b2); } diff --git a/Controllers/ViewSonicController/RGBController_XG270QG.h b/Controllers/ViewSonicController/RGBController_XG270QG.h index 9cd3dff0..e2ab0061 100644 --- a/Controllers/ViewSonicController/RGBController_XG270QG.h +++ b/Controllers/ViewSonicController/RGBController_XG270QG.h @@ -1,13 +1,16 @@ -/*------------------------------------*\ -| RGBController_XG270QG.h | -| Lanzaa 1/23/2022 | -\*------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_XG270QG.h | +| | +| RGBController for ViewSonic XG270QG | +| | +| Lanzaa 23 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include -#include - #include "VS_XG270QG_Controller.h" #include "RGBController.h" diff --git a/Controllers/ViewSonicController/VS_XG270QG_Controller.cpp b/Controllers/ViewSonicController/VS_XG270QG_Controller.cpp index 401cc9df..f6365c3b 100644 --- a/Controllers/ViewSonicController/VS_XG270QG_Controller.cpp +++ b/Controllers/ViewSonicController/VS_XG270QG_Controller.cpp @@ -1,17 +1,24 @@ -/*-----------------------------------*\ -| VS_XG270QG_Controller.cpp | -| Lanzaa 1/23/2022 | -\*-----------------------------------*/ - -#include "VS_XG270QG_Controller.h" -#include "LogManager.h" +/*---------------------------------------------------------*\ +| VS_XG270QG_Controller.cpp | +| | +| Driver for ViewSonic XG270QG | +| | +| Lanzaa 23 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "LogManager.h" +#include "StringUtils.h" +#include "VS_XG270QG_Controller.h" -VS_XG270QG_Controller::VS_XG270QG_Controller(hid_device* device, const char* path) +VS_XG270QG_Controller::VS_XG270QG_Controller(hid_device* device, const char* path, std::string dev_name) { - dev = device; - location = path; + dev = device; + location = path; + name = dev_name; } VS_XG270QG_Controller::~VS_XG270QG_Controller() @@ -21,7 +28,12 @@ VS_XG270QG_Controller::~VS_XG270QG_Controller() std::string VS_XG270QG_Controller::GetLocation() { - return location; + return(location); +} + +std::string VS_XG270QG_Controller::GetName() +{ + return(name); } std::string VS_XG270QG_Controller::GetSerial() @@ -34,16 +46,12 @@ std::string VS_XG270QG_Controller::GetSerial() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); - return serial; + return(StringUtils::wstring_to_string(serial_string)); } -void VS_XG270QG_Controller::SetMode(uint8_t mode, uint8_t r, uint8_t g, uint8_t b) +void VS_XG270QG_Controller::SetMode(uint8_t mode1, uint8_t r1, uint8_t g1, uint8_t b1, uint8_t mode2, uint8_t r2, uint8_t g2, uint8_t b2) { - SendModeComplete(mode, r, g, b, mode, r, g, b); + SendModeComplete(mode1, r1, g1, b1, mode2, r2, g2, b2); } void VS_XG270QG_Controller::SendModeComplete @@ -52,7 +60,8 @@ void VS_XG270QG_Controller::SendModeComplete uint8_t mode2, uint8_t r2, uint8_t g2, uint8_t b2 ) { - uint8_t data[] = { + uint8_t data[] = + { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, diff --git a/Controllers/ViewSonicController/VS_XG270QG_Controller.h b/Controllers/ViewSonicController/VS_XG270QG_Controller.h index 619b55e8..d4dc3c82 100644 --- a/Controllers/ViewSonicController/VS_XG270QG_Controller.h +++ b/Controllers/ViewSonicController/VS_XG270QG_Controller.h @@ -1,22 +1,22 @@ -/*---------------------------------------*\ -| VS_XG270QG_Controller.h | -| | -| Definitions and types for ViewSonic | -| Elite XG270QG Monitor | -| | -| Lanzaa 1/23/2022 | -\*---------------------------------------*/ +/*---------------------------------------------------------*\ +| VS_XG270QG_Controller.h | +| | +| Driver for ViewSonic XG270QG | +| | +| Lanzaa 23 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once #include #include #include - +#include #include "RGBController.h" -#include - enum { VS_MODE_OFF = 0x00, @@ -32,19 +32,20 @@ enum class VS_XG270QG_Controller { public: - VS_XG270QG_Controller(hid_device* device, const char* path); + VS_XG270QG_Controller(hid_device* device, const char* path, std::string dev_name); ~VS_XG270QG_Controller(); std::string GetLocation(); + std::string GetName(); std::string GetSerial(); - void SetMode(uint8_t mode, uint8_t r, uint8_t g, uint8_t b); + void SetMode(uint8_t mode1, uint8_t r1, uint8_t g1, uint8_t b1, + uint8_t mode2, uint8_t r2, uint8_t g2, uint8_t b2); private: hid_device* dev; std::string location; - - std::string version; + std::string name; std::string serial; std::string ReadVersion(); diff --git a/Controllers/ViewSonicController/ViewSonicControllerDetect.cpp b/Controllers/ViewSonicController/ViewSonicControllerDetect.cpp index 5d95cd16..41865b15 100644 --- a/Controllers/ViewSonicController/ViewSonicControllerDetect.cpp +++ b/Controllers/ViewSonicController/ViewSonicControllerDetect.cpp @@ -1,12 +1,23 @@ +/*---------------------------------------------------------*\ +| ViewSonicControllerDetect.cpp | +| | +| Detector for ViewSonic XG270QG | +| | +| Lanzaa 23 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "VS_XG270QG_Controller.h" #include "RGBController_XG270QG.h" -#include -#include "LogManager.h" - -#define VIEWSONIC_VID 0x0416 +#define WINBOND_VID 0x0416 +#define VIEWSONIC_VID 0x0543 #define VS_XG270QG_PID 0x5020 +#define VS_XG271QG_PID 0xA004 void DetectViewSonic(hid_device_info* info, const std::string& name) { @@ -14,12 +25,12 @@ void DetectViewSonic(hid_device_info* info, const std::string& name) if(dev) { - VS_XG270QG_Controller* controller = new VS_XG270QG_Controller(dev, info->path); + VS_XG270QG_Controller* controller = new VS_XG270QG_Controller(dev, info->path, name); RGBController_XG270QG* rgb_controller = new RGBController_XG270QG(controller); - rgb_controller->name = name; - + ResourceManager::get()->RegisterRGBController(rgb_controller); } } -REGISTER_HID_DETECTOR("ViewSonic Monitor XG270QG", DetectViewSonic, VIEWSONIC_VID, VS_XG270QG_PID); +REGISTER_HID_DETECTOR_IPU("ViewSonic Monitor XG270QG", DetectViewSonic, WINBOND_VID, VS_XG270QG_PID, 0, 0xFF00, 1); +REGISTER_HID_DETECTOR_IP( "ViewSonic Monitor XG271QG", DetectViewSonic, VIEWSONIC_VID, VS_XG271QG_PID, 0, 0x0001); diff --git a/Controllers/WinbondGamingKeyboardController/RGBController_WinbondGamingKeyboard.cpp b/Controllers/WinbondGamingKeyboardController/RGBController_WinbondGamingKeyboard.cpp new file mode 100644 index 00000000..1e136aac --- /dev/null +++ b/Controllers/WinbondGamingKeyboardController/RGBController_WinbondGamingKeyboard.cpp @@ -0,0 +1,851 @@ +/*---------------------------------------------------------*\ +| RGBController_WinbondGamingKeyboard.cpp | +| | +| RGBController for Winbond Gaming Keyboard | +| | +| Daniel Gibson 03 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBController_WinbondGamingKeyboard.h" +#include "RGBControllerKeyNames.h" +#include "KeyboardLayoutManager.h" +#include "LogManager.h" + +/**------------------------------------------------------------------*\ + @name Winbond Gaming Keyboard + @category Keyboard + @type USB + @save :robot: + @direct :x: + @effects :white_check_mark: + @detectors DetectWinbondGamingKeyboard + @comment Also known as Pulsar PCMK, and KT108 (by various manufacturers) +\*-------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------------------------------*\ +| - MSG_NUM is between 0 and (incl) 7, indicating which HID message contains the key's LED | +| - IDX is between 0 and (incl.) 17 (0 to 5 for message 7), | +| indicating the index of that LED within the message. | +| - 1 << 16 is set so KV(0,0) doesn't have the same value as 0 (the default "not assigned" value) | +\*-----------------------------------------------------------------------------------------------*/ +#define KV(MSG_NUM, IDX) ((MSG_NUM) << 8 | (IDX) | (1 << 16)) + +static std::vector additional_mm_leds = +{ + { + 0, // zone + 0, // row + 17, // col + KV(1,0), // value + KEY_EN_MEDIA_VOLUME_UP, // name + KEY_EN_UNUSED, // translated name + KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT // opcode + }, + { + 0, // zone + 0, // row + 18, // col + KV(1,1), // value + KEY_EN_MEDIA_VOLUME_DOWN, // name + KEY_EN_UNUSED, // translated name + KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT // opcode + }, + { + 0, // zone + 0, // row + 19, // col + KV(1,2), // value + KEY_EN_MEDIA_MUTE, // name + KEY_EN_UNUSED, // translated name + KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT // opcode + }, + { + 0, // zone + 0, // row + 20, // col + KV(1,3), // value + "Key: Cylinder?!", // name; TODO: no idea what the symbol meant, was a cylinder.. + KEY_EN_UNUSED, // translated name + KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT // opcode + } +}; + +static layout_values winbond_gaming_keyboard_full_layouts = +{ + {}, // "std::vector default_values" is set in InitLayouts() + { // std::map > regional_overlay; + { KEYBOARD_LAYOUT_ISO_QWERTY, + { + /*---------------------------------------------------------*\ + | just setting the values for some keys that should already | + | be defined by KeyboardLayoutManager's keyboard_zone_main | + \*---------------------------------------------------------*/ + { + 0, // zone + 3, // row + 12, // col + KV(4,7), // value + KEY_EN_POUND, // name + KEY_EN_UNUSED, // translated name + KEYBOARD_OPCODE_SWAP_ONLY // opcode + }, + { + 0, // zone + 4, // row + 1, // col + KV(4,17), // value + KEY_EN_ISO_BACK_SLASH, // name + KEY_EN_UNUSED, // translated name + KEYBOARD_OPCODE_SWAP_ONLY // opcode + }, + } + }, + { KEYBOARD_LAYOUT_JIS, + { + /*------------------------------------------------*\ + | that extra key before backspace on JIS keyboards | + \*------------------------------------------------*/ + { + 0, // zone + 1, // row + 13, // col + KV(1,17), // value + KEY_JP_YEN, // name + KEY_EN_UNUSED, // translated name + KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT // opcode + } + } + } + /*----------------------------------------------------------------------------------*\ + | TODO: KV(5,10) could be that extra key left of right shift on ABNT keyboards (/ ?) | + \*----------------------------------------------------------------------------------*/ + } +}; + +static layout_values winbond_gaming_keyboard_tkl_layouts = +{ + {}, // "std::vector default_values" is set in InitLayouts() + { // std::map > regional_overlay; + { KEYBOARD_LAYOUT_ISO_QWERTY, + { + /*---------------------------------------------------------*\ + | just setting the values for some keys that should already | + | be defined by KeyboardLayoutManager's keyboard_zone_main | + \*---------------------------------------------------------*/ + { + 0, // zone + 3, // row + 12, // col + KV(4,7), // value + KEY_EN_POUND, // name + KEY_EN_UNUSED, // translated name + KEYBOARD_OPCODE_SWAP_ONLY // opcode + }, + { + 0, // zone + 4, // row + 1, // col + KV(4,17), // value + KEY_EN_ISO_BACK_SLASH, // name + KEY_EN_UNUSED, // translated name + KEYBOARD_OPCODE_SWAP_ONLY // opcode + }, + } + }, + { KEYBOARD_LAYOUT_JIS, + { + /*------------------------------------------------*\ + | that extra key before backspace on JIS keyboards | + \*------------------------------------------------*/ + { + 0, // zone + 1, // row + 13, // col + KV(1,17), // value + KEY_JP_YEN, // name + KEY_EN_UNUSED, // translated name + KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT // opcode + } + } + } + /*----------------------------------------------------------------------------------*\ + | TODO: KV(5,10) could be that extra key left of right shift on ABNT keyboards (/ ?) | + \*----------------------------------------------------------------------------------*/ + } +}; + +static layout_values winbond_gaming_keyboard_60_layouts = +{ + {}, // "std::vector default_values" is set in InitLayouts() + { // std::map > regional_overlay; + { KEYBOARD_LAYOUT_ISO_QWERTY, + { + /*---------------------------------------------------------*\ + | just setting the values for some keys that should already | + | be defined by KeyboardLayoutManager's keyboard_zone_main | + \*---------------------------------------------------------*/ + { + 0, // zone + 3, // row + 12, // col + KV(4,7), // value + KEY_EN_POUND, // name + KEY_EN_UNUSED, // translated name + KEYBOARD_OPCODE_SWAP_ONLY // opcode + }, + { + 0, // zone + 4, // row + 1, // col + KV(4,17), // value + KEY_EN_ISO_BACK_SLASH, // name + KEY_EN_UNUSED, // translated name + KEYBOARD_OPCODE_SWAP_ONLY // opcode + }, + } + }, + { KEYBOARD_LAYOUT_JIS, + { + /*------------------------------------------------*\ + | that extra key before backspace on JIS keyboards | + \*------------------------------------------------*/ + { + 0, // zone + 1, // row + 13, // col + KV(1,17), // value + KEY_JP_YEN, // name + KEY_EN_UNUSED, // translated name + KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT // opcode + } + } + } + /*----------------------------------------------------------------------------------*\ + | TODO: KV(5,10) could be that extra key left of right shift on ABNT keyboards (/ ?) | + \*----------------------------------------------------------------------------------*/ + } +}; + +static void InitLayouts(layout_values& keyboard_layouts, KEYBOARD_SIZE kb_size, std::string vendor) +{ + /*-------------------------------------------------------------------*\ + | using kvs ("keyvals" or sth like that) as an alias for | + | keyboard_layouts.default_values, to make the code below | + | shorter/more readable | + \*-------------------------------------------------------------------*/ + std::vector& kvs = keyboard_layouts.default_values; + + /*------------------------------------------------------------------------------------*\ + | Message X: what indices the keys have within the USB HID messages to set their color | + | "??" means "that index exists, but doesn't seem to be used on my TKL ISO keyboard" | + | | + | A Note regarding kb_size: I wrote this with my Pulsar PCMK TKL keyboard, there the | + | LED positions ( KV(MSGNUM, IDX) ) were like on a fullsize keyboard, | + | i.e. there USB messages had space for NumPad keys (or their LEDs). | + | No idea if that's also true for e.g. 60% keyboards, and it's also possible that | + | some positions of NumPad LEDs are incorrect, I only guessed them. | + \*------------------------------------------------------------------------------------*/ + + /* Message 0: ---------------------------------------------------------------*\ + | 0 = Esc, ??, 2 = F1, F2, F3, F4, ??, 7 = F5, F6, F7, F8, F9, F10, F11, F12, | + | 15 = Print, ScrollLock, 17 = Pause | + \*---------------------------------------------------------------------------*/ + + if(kb_size & KEYBOARD_ZONE_FN_ROW) + { + kvs.push_back( KV(0,0) ); // Esc + // F1 to F4 + for(int i=2; i <= 5; ++i) + { + kvs.push_back( KV(0,i) ); + } + + // F5 to F12 + for(int i=7; i <= 14; ++i) + { + kvs.push_back( KV(0,i) ); + } + } + + if(kb_size & KEYBOARD_ZONE_EXTRA) + { + // PrintScreen, ScrollLock, Pause + for(int i=15; i <= 17; ++i) + { + kvs.push_back( KV(0,i) ); + } + } + + /* Message 1: ------------------------------------------------------------------------*\ + | 0-3 = (could be multimedia keys above numblock?), 4 = BKTK, 1, 2, 3, 4, 5, | + | 10 = 6, 7, 8, 9, 0, '-', 16 = '=', 17 = (that extra key before backspace on JIS?) | + \*------------------------------------------------------------------------------------*/ + + // KV(1,0) to KV(1,3) are probably 4 extra multimedia keys above the numblock + + // BKTK ("Quake console key"), 1, 2, ... 0, -, = + if(kb_size & KEYBOARD_ZONE_MAIN) + { + for(int i=4; i <= 16; ++i) + { + kvs.push_back( KV(1,i) ); + } + + // KV(1,17) might be that extra Yen key before backspace on JIS keyboards + } + + /* Message 2: ------------------------------------------------------------*\ + | 0 = Backspace, Ins, Pos1, 3 = PgUp, 4-7 = (NumLock, Num/, Num*, Num- ?), | + | 8 = Tab, Q, W, E, R, T, ..., 16 = I, 17 = O | + \*------------------------------------------------------------------------*/ + + // Backspace + if(kb_size & KEYBOARD_ZONE_MAIN) + { + kvs.push_back( KV(2,0) ); + } + + // Ins, Home, PgUp + if(kb_size & KEYBOARD_ZONE_EXTRA) + { + for(int i=1; i <= 3; ++i) + { + kvs.push_back( KV(2,i) ); + } + } + + // NumLock, NP/, NP*, NP- + if(kb_size & KEYBOARD_ZONE_NUMPAD) + { + for(int i=4; i <= 7; ++i) + { + kvs.push_back( KV(2,i) ); + } + } + + // Tab, Q, ..., I, O + if(kb_size & KEYBOARD_ZONE_MAIN) + { + for(int i=8; i <= 17; ++i) + { + kvs.push_back( KV(2,i) ); + } + } + + /* Message 3: -----------------------------------------------------------*\ + | 0 = P, [ (Ü), ] (+), 3 = (US-\ ?), ??, 5 = Del, End, 7 = PgDown, | + | 8-1 = (Num7, Num8, Num9, Num+ ?), 12 = CapsLock, ??, 14 = A, S, D, F | + \*-----------------------------------------------------------------------*/ + + // P, Ü/[, +/] + if(kb_size & KEYBOARD_ZONE_MAIN) + { + for(int i=0; i <= 2; ++i) + { + kvs.push_back( KV(3,i) ); + } + // Backslash + if(vendor != "Hator") + { + kvs.push_back( KV(3,3) ); + } + else + { + kvs.push_back( KV(3,4) ); + } + } + + // Del, End, PgDown + if(kb_size & KEYBOARD_ZONE_EXTRA) + { + for(int i=5; i <= 7; ++i) + { + kvs.push_back( KV(3,i) ); + } + } + + // NP7-NP9, NP+ + if(kb_size & KEYBOARD_ZONE_NUMPAD) + { + for(int i=8; i <= 11; ++i) + { + kvs.push_back( KV(3,i) ); + } + } + + + if(kb_size & KEYBOARD_ZONE_MAIN) + { + // CapsLock + kvs.push_back( KV(3,12) ); + // A, S, D, F + for(int i=14; i <= 17; ++i) + { + kvs.push_back( KV(3,i) ); + } + } + + /* Message 4: -------------------------------------------------------------*\ + | 0 = G, H, J, K, L, ; (Ö), " (Ä), 7 = #, 8 = Enter, 9 - 15 = ?? | + | (maybe 12-14 are Num4-6, maybe 15 = Num+ ?), 16 = Shift, 17 = ISO-\ (<) | + \*-------------------------------------------------------------------------*/ + + if(kb_size & KEYBOARD_ZONE_MAIN) + { + // G, H, ..., L, Ö/;, Ä/" + for(int i=0; i <= 6; ++i) + { + kvs.push_back( KV(4,i) ); + } + + // KV(4,7) is the ISO # key that doesn't exist on ANSI (set in overlay) + // even though # is no ANSI key, that default_values array expects it to be there.. + kvs.push_back( KV(4,7) ); + + // Enter - assuming that on ANSI it uses the same LED index + kvs.push_back( KV(4,8) ); + } + + + if(kb_size & KEYBOARD_ZONE_NUMPAD) + { + // NP4-6 - not sure if those are really at 12-14, would fit though + for(int i=12; i <= 14; ++i) + { + kvs.push_back( KV(4,i) ); + } + } + + if(kb_size & KEYBOARD_ZONE_MAIN) + { + // Left Shift + kvs.push_back( KV(4,16) ); + + // KV(4,17) is the ISO |\ (or <) key that doesn't exist on ANSI (set in overlay) + // apparently it must be listed anyway.. + kvs.push_back( KV(4,17) ); + } + + /* Message 5: --------------------------------------------------------*\ + | 0 = Z/Y, X, C, V, B, N, M, ',', '.' , 9 = / or -, ??, ??, | + | 12 = Shift, ??, 14 = Up, 15-17 ?? (maybe 16 and 17 are Num1, Num2, | + | and Num3, NumEnter are in next msg?) | + \*--------------------------------------------------------------------*/ + + if(kb_size & KEYBOARD_ZONE_MAIN) + { + // Z (Y), X, .., M, ',', '.', / (- on DE) + for(int i=0; i <= 9; ++i) + { + kvs.push_back( KV(5,i) ); + } + + // KV(5,10) could be that extra key left of right shift on ABNT keyboards (/ ?) + + kvs.push_back( KV(5,12) ); // Right Shift + } + + if(kb_size & KEYBOARD_ZONE_EXTRA) + { + kvs.push_back( KV(5,14) ); // Up + } + + if(kb_size & KEYBOARD_ZONE_NUMPAD) + { + kvs.push_back( KV(5,16) ); // Num1 + kvs.push_back( KV(5,17) ); // Num2 + } + + /* Message 6: -------------------------------------------------------------*\ + | 0 = (Num3 ?), (Num Enter ?), 2 = Ctrl, Win, 4 = Alt, .. ?? .., 8 = Space, | + | .. ?? .., 12 = AltGr, Fn, Menu, 15 = Ctrl, ??, 17 = Left | + \*-------------------------------------------------------------------------*/ + + // Num3, Num Enter + if(kb_size & KEYBOARD_ZONE_NUMPAD) + { + for(int i=0; i <= 1; ++i) + { + kvs.push_back( KV(6,i) ); + } + } + + if(kb_size & KEYBOARD_ZONE_MAIN) + { + // LeftCtrl, Win, LeftAlt + for(int i=2; i <= 4; ++i) + { + kvs.push_back( KV(6,i) ); + } + // Space + kvs.push_back( KV(6,8) ); + // RightAlt, Fn, RMenu, RightCtrl + for(int i=12; i <= 15; ++i) + { + kvs.push_back( KV(6,i) ); + } + } + + if(kb_size & KEYBOARD_ZONE_EXTRA) + kvs.push_back( KV(6,17) ); // Left + + /* Message 7: -------------------------------------------------------*\ + | 0 = Down, 1 = Right, 2-5 = ?? (maybe 2 or 3 = Num0, 4 = NumDecimal, | + | 5 = NumEnter, more likely: 3 = Num0, 5 = NumDec) | + \*-------------------------------------------------------------------*/ + + if(kb_size & KEYBOARD_ZONE_EXTRA) + { + kvs.push_back( KV(7,0) ); // Down + kvs.push_back( KV(7,1) ); // Right + } + + if(kb_size & KEYBOARD_ZONE_NUMPAD) + { + kvs.push_back( KV(7,3) ); // Num0 - TODO: or 7,2 or 7,4 ? + kvs.push_back( KV(7,5) ); // NumDec - TODO: or 7,4 ? + } + + /*-------------------------------------------------------------------*\ + | for fullsize keyboards, add multimedia keys to all layouts/overlays | + \*-------------------------------------------------------------------*/ + if(kb_size == KEYBOARD_SIZE_FULL) + { + for(std::pair>& overlay: keyboard_layouts.regional_overlay) + { + for(const keyboard_led& mm_key_led : additional_mm_leds) + { + overlay.second.push_back(mm_key_led); + } + } + + /*---------------------------------------------------------------------------------*\ + | there is no overlay for the ANSI layout defined yet, add one just for the MM keys | + \*---------------------------------------------------------------------------------*/ + keyboard_layouts.regional_overlay.insert({ KEYBOARD_LAYOUT_ANSI_QWERTY, additional_mm_leds }); + } +} + + + +RGBController_WinbondGamingKeyboard::RGBController_WinbondGamingKeyboard(WinbondGamingKeyboardController* ctrl) + : controller(ctrl) +{ + type = DEVICE_TYPE_KEYBOARD; + name = ctrl->GetName(); + vendor = ctrl->GetVendor(); + description = ctrl->GetDescription(); + location = ctrl->GetDeviceLocation(); + serial = ctrl->GetSerialString(); + version = ctrl->GetVersion(); + + { + mode m; + m.name = "Custom"; + m.value = WINBOND_GK_MODE_CUSTOM; + m.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + m.color_mode = MODE_COLORS_PER_LED; + m.brightness_min = 0; + m.brightness_max = 4; + m.brightness = 1; + m.speed_min = 0; + m.speed_max = 4; + m.speed = 2; + modes.push_back(m); + } + + { + mode m; + m.name = "Static"; + m.value = WINBOND_GK_MODE_STATIC; + m.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + m.color_mode = MODE_COLORS_MODE_SPECIFIC; + m.colors_min = m.colors_max = 1; // one color for all keys + m.colors.push_back(ToRGBColor(255,255,255)); // default to white + m.brightness_min = 0; + m.brightness_max = 4; + m.brightness = 1; + m.speed_min = 0; + m.speed_max = 4; + m.speed = 2; + modes.push_back(m); + } + + { + mode m; + m.name = "Neon"; + m.value = WINBOND_GK_MODE_NEON; + m.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + m.colors.push_back(ToRGBColor(255,0,0)); + m.colors.push_back(ToRGBColor(0,0,0)); + m.colors_min = 0; + m.colors_max = 2; + m.color_mode = MODE_COLORS_RANDOM; + m.brightness_min = 0; + m.brightness_max = 4; + m.brightness = 1; + m.speed_min = 0; + m.speed_max = 4; + m.speed = 2; + modes.push_back(m); + } + + { + mode m; + m.name = "Breathing"; + m.value = WINBOND_GK_MODE_BREATHE; + m.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + m.colors.push_back(ToRGBColor(255,0,0)); + m.colors.push_back(ToRGBColor(0,0,0)); + m.colors_min = 0; + m.colors_max = 2; + m.color_mode = MODE_COLORS_RANDOM; + m.brightness_min = 0; + m.brightness_max = 4; + m.brightness = 1; + m.speed_min = 0; + m.speed_max = 4; + m.speed = 2; + modes.push_back(m); + } + + { + mode m; + m.name = "Wave"; + m.value = WINBOND_GK_MODE_WAVE; + m.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE + | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_DIRECTION_UD + | MODE_FLAG_HAS_DIRECTION_HV; // NOTE: this is really outer to inner or inner to outer + m.direction = MODE_DIRECTION_RIGHT; + m.colors.push_back(ToRGBColor(255,0,0)); + m.colors.push_back(ToRGBColor(0,0,0)); + m.colors_min = 0; + m.colors_max = 2; + m.color_mode = MODE_COLORS_RANDOM; + m.brightness_min = 0; + m.brightness_max = 4; + m.brightness = 1; + m.speed_min = 0; + m.speed_max = 4; + m.speed = 2; + modes.push_back(m); + } + + { + mode m; + m.name = "Snake"; + m.value = WINBOND_GK_MODE_SNAKE; + m.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE + | MODE_FLAG_HAS_DIRECTION_UD; // NOTE: more like CW/CCW + m.direction = MODE_DIRECTION_DOWN; + m.colors.push_back(ToRGBColor(255,0,0)); + m.colors.push_back(ToRGBColor(0,0,0)); + m.colors_min = 0; + m.colors_max = 2; + m.color_mode = MODE_COLORS_RANDOM; + m.brightness_min = 0; + m.brightness_max = 4; + m.brightness = 1; + m.speed_min = 0; + m.speed_max = 4; + m.speed = 2; + modes.push_back(m); + } + + /*------------------------------------------------------------------------*\ + |the following modes are ones that only show effects when a key is pressed | + | and otherwise only a background color | + \*------------------------------------------------------------------------*/ + { + mode m; + m.name = "Aurora (on keypress)"; + m.value = WINBOND_GK_MODE_AURORA; + m.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE + | MODE_FLAG_HAS_DIRECTION_HV; // NOTE: more like to inner/to outer + m.direction = MODE_DIRECTION_HORIZONTAL; + m.colors.push_back(ToRGBColor(255,0,0)); + m.colors.push_back(ToRGBColor(0,0,0)); // TODO: set background to white so keyboard isn't dark? + m.colors_min = 0; + m.colors_max = 2; + m.color_mode = MODE_COLORS_RANDOM; + m.brightness_min = 0; + m.brightness_max = 4; + m.brightness = 1; + m.speed_min = 0; + m.speed_max = 4; + m.speed = 2; + modes.push_back(m); + } + + { + mode m; + m.name = "Ripple (on keypress)"; + m.value = WINBOND_GK_MODE_RIPPLE; + m.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + m.colors.push_back(ToRGBColor(255,0,0)); + m.colors.push_back(ToRGBColor(0,0,0)); // TODO: set background to white so keyboard isn't dark? + m.colors_min = 0; + m.colors_max = 2; + m.color_mode = MODE_COLORS_RANDOM; + m.brightness_min = 0; + m.brightness_max = 4; + m.brightness = 1; + m.speed_min = 0; + m.speed_max = 4; + m.speed = 2; + modes.push_back(m); + } + + { + mode m; + m.name = "Reactive (on keypress)"; + m.value = WINBOND_GK_MODE_REACTIVE; + m.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + m.colors.push_back(ToRGBColor(255,0,0)); + m.colors.push_back(ToRGBColor(0,0,0)); // TODO: set background to white so keyboard isn't dark? + m.colors_min = 0; + m.colors_max = 2; + m.color_mode = MODE_COLORS_RANDOM; + m.brightness_min = 0; + m.brightness_max = 4; + m.brightness = 1; + m.speed_min = 0; + m.speed_max = 4; + m.speed = 2; + modes.push_back(m); + } + + /*--------------------------------------------------------------------------------*\ + | NOTE: logo light has static, neon (WINBOND_GK_MODE_LOGO_NEON), breathe, wave | + | all logo modes have brightness, all but static have speed and 2 colors + random | + \*--------------------------------------------------------------------------------*/ + + SetupZones(); +} + + +RGBController_WinbondGamingKeyboard::~RGBController_WinbondGamingKeyboard() +{ + delete controller; +} + +void RGBController_WinbondGamingKeyboard::SetupZones() +{ + zone new_zone; + new_zone.name = ZONE_EN_KEYBOARD; + new_zone.type = ZONE_TYPE_MATRIX; + + layout_values* layouts = &winbond_gaming_keyboard_full_layouts; + KEYBOARD_SIZE kb_size = controller->GetSize(); + std::string vendor = controller->GetVendor(); + + if(kb_size == KEYBOARD_SIZE_TKL) + { + layouts = &winbond_gaming_keyboard_tkl_layouts; + } + else if(kb_size == KEYBOARD_SIZE_SIXTY) + { + layouts = &winbond_gaming_keyboard_60_layouts; + } + else // size is full or something not supported directly - default to full + { + kb_size = KEYBOARD_SIZE_FULL; + } + + if(layouts->default_values.empty()) + { + InitLayouts(*layouts, kb_size, vendor); + } + + KeyboardLayoutManager new_kb(controller->GetLayout(), kb_size, *layouts); + + matrix_map_type * new_map = new matrix_map_type; + new_zone.matrix_map = new_map; + new_zone.matrix_map->height = new_kb.GetRowCount(); + new_zone.matrix_map->width = new_kb.GetColumnCount(); + + new_zone.matrix_map->map = new unsigned int[new_map->height * new_map->width]; + new_zone.leds_count = new_kb.GetKeyCount(); + new_zone.leds_min = new_zone.leds_count; + new_zone.leds_max = new_zone.leds_count; + + /*---------------------------------------------------------*\ + | Matrix map still uses declared zone rows and columns | + | as the packet structure depends on the matrix map | + \*---------------------------------------------------------*/ + new_kb.GetKeyMap(new_map->map, KEYBOARD_MAP_FILL_TYPE_COUNT); + + /*---------------------------------------------------------*\ + | Create LEDs for the Matrix zone | + | Place keys in the layout to populate the matrix | + \*---------------------------------------------------------*/ + for(size_t led_idx = 0; led_idx < new_zone.leds_count; led_idx++) + { + led new_led; + + new_led.name = new_kb.GetKeyNameAt((unsigned int)led_idx); + new_led.value = new_kb.GetKeyValueAt((unsigned int)led_idx); + + leds.push_back(new_led); + } + + zones.push_back(new_zone); + + /*---------------------------------------------------------------------------*\ + | special case: logo LEDs | + | it's 3 LEDs, but the colors can't be set separately, so represent it as one | + \*---------------------------------------------------------------------------*/ + + if(controller->HasLogoLight()) + { + zone logo_zone; + logo_zone.name = "Logo Light"; + logo_zone.type = ZONE_TYPE_SINGLE; + logo_zone.leds_min = 1; + logo_zone.leds_max = 1; + logo_zone.leds_count = 1; + logo_zone.matrix_map = NULL; + + led zone_led; + zone_led.name = "Logo LEDs"; + zone_led.value = KV(255, 0); // using message num 255 as special case for logo LED + leds.push_back(zone_led); + + zones.push_back(logo_zone); + } + + SetupColors(); +} + +#undef KV + +void RGBController_WinbondGamingKeyboard::ResizeZone(int /*zone*/, int /*new_size*/) +{ + /*---------------------------------------------------------*\ + | This device does not support resizing zones | + \*---------------------------------------------------------*/ +} + +void RGBController_WinbondGamingKeyboard::DeviceUpdateLEDs() +{ + controller->SetLEDsData(colors, leds, modes[active_mode].brightness); +} + +void RGBController_WinbondGamingKeyboard::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_WinbondGamingKeyboard::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +void RGBController_WinbondGamingKeyboard::DeviceUpdateMode() +{ + controller->SetMode(modes[active_mode]); +} diff --git a/Controllers/WinbondGamingKeyboardController/RGBController_WinbondGamingKeyboard.h b/Controllers/WinbondGamingKeyboardController/RGBController_WinbondGamingKeyboard.h new file mode 100644 index 00000000..b97cfeb8 --- /dev/null +++ b/Controllers/WinbondGamingKeyboardController/RGBController_WinbondGamingKeyboard.h @@ -0,0 +1,52 @@ +/*---------------------------------------------------------*\ +| RGBController_WinbondGamingKeyboard.h | +| | +| RGBController for Winbond Gaming Keyboard | +| | +| Daniel Gibson 03 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "WinbondGamingKeyboardController.h" + +enum +{ + WINBOND_GK_MODE_STATIC = 0, + WINBOND_GK_MODE_BREATHE = 1, + WINBOND_GK_MODE_WAVE = 2, + WINBOND_GK_MODE_NEON = 3, + WINBOND_GK_MODE_LOGO_NEON = 4, // logo-only! + WINBOND_GK_MODE_SNAKE = 5, + /*-------------------------------------------------------------------------*\ + | the following modes are ones that only show effects when a key is pressed | + | and otherwise only a background color | + \*-------------------------------------------------------------------------*/ + WINBOND_GK_MODE_REACTIVE = 6, + WINBOND_GK_MODE_AURORA = 7, + WINBOND_GK_MODE_RIPPLE = 8, + WINBOND_GK_MODE_CUSTOM = 10 +}; + +class RGBController_WinbondGamingKeyboard : public RGBController +{ +public: + RGBController_WinbondGamingKeyboard(WinbondGamingKeyboardController* ctrl); + ~RGBController_WinbondGamingKeyboard(); + + void SetupZones() override; + void ResizeZone(int zone, int new_size) override; + + void DeviceUpdateLEDs() override; + void UpdateZoneLEDs(int zone) override; + void UpdateSingleLED(int led) override; + + void DeviceUpdateMode() override; + +private: + WinbondGamingKeyboardController* controller; +}; diff --git a/Controllers/WinbondGamingKeyboardController/WinbondGamingKeyboardController.cpp b/Controllers/WinbondGamingKeyboardController/WinbondGamingKeyboardController.cpp new file mode 100644 index 00000000..114997af --- /dev/null +++ b/Controllers/WinbondGamingKeyboardController/WinbondGamingKeyboardController.cpp @@ -0,0 +1,427 @@ +/*---------------------------------------------------------*\ +| WinbondGamingKeyboardController.cpp | +| | +| Driver for Winbond Gaming Keyboard | +| | +| Daniel Gibson 03 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "LogManager.h" +#include "StringUtils.h" +#include "WinbondGamingKeyboardController.h" +#include "RGBController_WinbondGamingKeyboard.h" + +#define WINBOND_HID_DATA_LEN 64 + +WinbondGamingKeyboardController::WinbondGamingKeyboardController(hid_device *dev_handle, const hid_device_info &info, const std::string& name) + : dev(dev_handle) +{ + location = "HID: "; + location += info.path; + + SetNameVendorDescription(info, name); + SetVersionLayout(); +} + + +void WinbondGamingKeyboardController::SetNameVendorDescription(const hid_device_info &info, const std::string& devname) +{ + bool using_product_string = false; + if(info.product_string != nullptr && info.product_string[0] != 0) + { + using_product_string = true; + /*----------------------------------------------------------------------------------------------------*\ + | info->product_string can have at most 126 wchars + terminating 0 | + | (according to | + | https://stackoverflow.com/questions/7193645/how-long-is-the-string-of-manufacturer-of-a-usb-device) | + | in UTF-8 that's at most 126*4 chars + terminating 0 | + \*----------------------------------------------------------------------------------------------------*/ + char product_name[126*4 + 1]; + snprintf(product_name, sizeof(product_name), "%ls", info.product_string); + name = product_name; + } + else + { + name = devname; + } + + /*----------------------------------------------------------------------------*\ + | the Pulsar PCMK TKL keyboard (barebone) uses "PCMK TKL" as product string, | + | at least with the latest firmware. I assume that other Pulsar keyboards also | + | contain "PCMK", so use that to set the vendor to Pulsar (unfortunately, | + | Pulsar doesn't seem to set iManufacturer in the USB device descriptor) | + \*----------------------------------------------------------------------------*/ + if(name.find("PCMK") != std::string::npos) + { + vendor = "Pulsar"; + if(name.find("TKL") != std::string::npos) + { + kb_size = KEYBOARD_SIZE_TKL; + hasLogoLight = true; + } + else if(name.find("60") != std::string::npos) + { + /*---------------------------------------------------*\ + | I *guess* that the PCMK 60% has 60 in its name here | + | (if it even uses the same USB PID:VID ...) | + \*---------------------------------------------------*/ + kb_size = KEYBOARD_SIZE_SIXTY; + } + + } + else if((name.find("Rockfall") != std::string::npos) || (name.find("Skyfall") != std::string::npos)) + { + vendor = "Hator"; + layout = KEYBOARD_LAYOUT_ANSI_QWERTY; + if(name.find("TKL") != std::string::npos) + { + kb_size = KEYBOARD_SIZE_TKL; + } + } + else + { + vendor = "Winbond"; + } + + if(using_product_string) + { + description = vendor + " " + name; + } + else + { + description = name; + } +} + +void WinbondGamingKeyboardController::ParseVersionString(const char *str) +{ + /*------------------------------------------------------------------------------*\ + | str should be something like "2NUC,01,KB,FL,K221UKCVRGB,V1.05.03" (for ISO/UK) | + | we're interested in the chars before "CVRGB" for the layout, | + | and the last "V" and following for the version string | + \*------------------------------------------------------------------------------*/ + const char* ver = strrchr(str, 'V'); + if(ver != nullptr) + { + version = ver; + } + else + { + version = "???"; + } + + LOG_DEBUG("[%s] Version response was: '%s'", name.c_str(), str); + + const char* cvrgb = strstr(str, "CVRGB"); + if(cvrgb != nullptr && cvrgb > str + 2) + { + const char* lang = cvrgb - 2; + + if(lang[0] == 'U' && lang[1] == 'K') + { + LOG_DEBUG("[%s] Detected ISO layout from that version string", name.c_str()); + layout = KEYBOARD_LAYOUT_ISO_QWERTY; + } + else if(lang[0] == 'J' && lang[1] == 'P') + { + LOG_DEBUG("[%s] Detected JIS layout from that version string", name.c_str()); + layout = KEYBOARD_LAYOUT_JIS; + } + else + { + LOG_DEBUG("[%s] Detected ANSI layout from that version string", name.c_str()); + layout = KEYBOARD_LAYOUT_ANSI_QWERTY; + } + } + else + { + LOG_DEBUG("[%s] Couldn't detect any layout from that string (didn't contain \"CVRGB\"), defaulting to ISO", name.c_str()); + } + + /*------------------------------------------------------------------------------------------*\ + | NOTE: I don't know exactly how the string would look like on ANSI or JIS keyboards, | + | but the firmware updaters for Pulsar PCMK TKL are called | + | K221CVRGB_V10507.exe for ANSI | + | K221JPCVRGB_V10503.exe for JIS | + | K221UKCVRGB_V10503.exe for ISO | + | so I assume that ANSI indeed has no extra string before CVRGB and JIS has "JP" there | + | | + | For future reference, PCMK 60% JIS firmware name: GD147CKB_M252KBFL_K225JPCVRGB_V10408.exe | + | no idea if that even uses the same chip, and how the LEDs are handled, though | + | | + | Furthermore, no idea how to detect the layout of other Winbond Gaming Keyboards, | + | like KT108 or KT87 (if that one really uses the same chip). | + | Maybe they use a similar version reply, maybe not... | + \*------------------------------------------------------------------------------------------*/ +} + +void WinbondGamingKeyboardController::SetVersionLayout() +{ + { + /*-------------------------------------------------------------*\ + | this requests a string with information about the version etc | + \*-------------------------------------------------------------*/ + unsigned char msg[WINBOND_HID_DATA_LEN] = { 0x01, 0x0D, 0 }; + hid_write(dev, msg, WINBOND_HID_DATA_LEN); + } + + /*--------------------------------------------------------*\ + | the reply looks like | + | 0x1, 0x0D, 0, 0, 0, "2NUC,01,KB,FL,K221UKCVRGB,V1.05.03" | + \*--------------------------------------------------------*/ + for(int i=0; i<10; ++i) // 10 retries + { + /*-----------------------------------------------------------------------------*\ + | +1 to make sure there's always a terminating \0 byte at the end of the string | + \*-----------------------------------------------------------------------------*/ + unsigned char reply[WINBOND_HID_DATA_LEN + 1] = {}; + int len = hid_read_timeout(dev, reply, WINBOND_HID_DATA_LEN, 150); + if(len < 0) + { + continue; + } + if(reply[0] != 1 || reply[1] != 0x0D || reply[4] != 0) // not the message we want + { + continue; + } + + const char* str = (const char*)reply + 2; // skip 0x01 0x0D bytes + /*-----------------------------------------------------------------*\ + | skip any leading whitespace, \0 bytes and other unprintable chars | + \*-----------------------------------------------------------------*/ + for(int j=0; j < WINBOND_HID_DATA_LEN - 2; ++j, ++str) + { + if(*str > ' ' ) + break; + } + if(*str != '\0') + { + ParseVersionString(str); + return; + } + } + + /*--------------*\ + | fallback | + \*--------------*/ + version = "???"; +} + +std::string WinbondGamingKeyboardController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +static void setModeImpl(hid_device* dev, bool is_logo, unsigned char effect_mode, unsigned char colors[2][3], + bool full_color, unsigned char direction, unsigned char speed, unsigned char brightness) +{ + unsigned char buf[WINBOND_HID_DATA_LEN] = + { + 1, // byte 0: Report ID (always 1) + 7, // byte 1: the "command", in this case 7 (set key LED mode) or 8 (set logo LED mode) + 0, 0, 0, 0x0E, // bytes 2-5: not sure about the meaning, they were like this.. + effect_mode, // byte 6 (effect mode, like WINBOND_GK_MODE_STATIC) + brightness, // byte 7 + speed // byte 8 + // the remaining bytes are set below or remain 0 + }; + + if(is_logo) + { + buf[1] = 8; + buf[5] = 0x0D; + } + + /*------------------------------*\ + | bytes 9-14 are fg and bg color | + \*------------------------------*/ + memcpy(buf+9, colors, 2*3); + + buf[15] = direction; + buf[16] = full_color; + // the rest of the buffer remains 0 + + hid_write(dev, buf, WINBOND_HID_DATA_LEN); +} + +void WinbondGamingKeyboardController::SetLEDsData(const std::vector& colors, const std::vector& leds, int brightness) +{ + /*---------------------------------------------------------------------------*\ + | There are 8 HID messages to set the LEDs. | + | Each message starts with the bytes shown below, followed by 18 RGB triplets | + | (except for the last message that has 12 RGB triplets). These triplets only | + | use values up to 0xC1 (193), instead of the usual 0xFF (255). | + | Byte 0 is the Report ID (1), 1 is the command (9), 2 and 3 are always 0 (?),| + | 4 is the message index, 5 is the length of the following RGB data in bytes | + \*---------------------------------------------------------------------------*/ + unsigned char msgs[8][WINBOND_HID_DATA_LEN] = + { + { 1, 9, 0, 0, 0, 0x36, 0 }, + { 1, 9, 0, 0, 1, 0x36, 0 }, + { 1, 9, 0, 0, 2, 0x36, 0 }, + { 1, 9, 0, 0, 3, 0x36, 0 }, + { 1, 9, 0, 0, 4, 0x36, 0 }, + { 1, 9, 0, 0, 5, 0x36, 0 }, + { 1, 9, 0, 0, 6, 0x36, 0 }, + { 1, 9, 0, 0, 7, 0x12, 0 }, + }; + + RGBColor logo_color = ToRGBColor(128, 128, 128); + + for(size_t i = 0, n = colors.size(); i < n; ++i) + { + unsigned val = leds[i].value; + if(val == 0) // no value set + { + continue; + } + + /*--------------------------------------------------------------------------------------------------*\ + | the following two lines are the inverse of the KV() macro in RGBController_WinbondGamingKeyboard.h | + \*--------------------------------------------------------------------------------------------------*/ + int msg_num = (val >> 8) & 255; + int r_offset = (val & 255); + r_offset = r_offset*3 + 6; // 6 is position of first color byte in message + /*----------------------------*\ + | special case: logo LED color | + \*----------------------------*/ + if(msg_num == 255) + { + logo_color = colors[i]; + // logo light is set separately, just remember its color + continue; + } + + msg_num &= 7; // 0..7 + + /*----------------------------*\ + | transform 0..0xFF to 0..0xC1 | + \*----------------------------*/ + int r = (RGBGetRValue(colors[i]) * 0xC1) / 0xFF; + int g = (RGBGetGValue(colors[i]) * 0xC1) / 0xFF; + int b = (RGBGetBValue(colors[i]) * 0xC1) / 0xFF; + msgs[msg_num][r_offset] = r & 255; + msgs[msg_num][r_offset+1] = g & 255; + msgs[msg_num][r_offset+2] = b & 255; + } + + for(int i=0; i<8; ++i) + { + hid_write(dev, msgs[i], WINBOND_HID_DATA_LEN); + } + + if(hasLogoLight) + { + unsigned char colors[2][3] = {}; + colors[0][0] = RGBGetRValue(logo_color); + colors[0][1] = RGBGetGValue(logo_color); + colors[0][2] = RGBGetBValue(logo_color); + setModeImpl(dev, true, WINBOND_GK_MODE_STATIC, colors, false, 0, 3, brightness); + } +} + +static unsigned char getDirection(unsigned int dir, int effect) +{ + /*---------------------------------------------------------------*\ + | Winbond effect directions: 0: right, 1: left, 2: up, 3: down, | + | 4: to outside, 5: to inside, 6: clockwise, 7: counter-clockwise | + \*---------------------------------------------------------------*/ + + switch(effect) + { + case WINBOND_GK_MODE_WAVE: + /*-----------------------------------*\ + | LR, UD; HV for to inside/to outside | + \*-----------------------------------*/ + switch(dir) + { + case MODE_DIRECTION_LEFT: + return 1; + case MODE_DIRECTION_RIGHT: + return 0; + case MODE_DIRECTION_UP: + return 2; + case MODE_DIRECTION_DOWN: + return 3; + case MODE_DIRECTION_HORIZONTAL: + return 4; + case MODE_DIRECTION_VERTICAL: + return 5; + } + + break; + case WINBOND_GK_MODE_SNAKE: // DOWN/UP for CW/CCW + return dir == MODE_DIRECTION_DOWN ? 6 : 7; + case WINBOND_GK_MODE_AURORA: // HORIZONTAL/VERTICAL for to outside/to inside + return dir == MODE_DIRECTION_HORIZONTAL ? 4 : 5; + } + return 0; // effects without a direction +} + +void WinbondGamingKeyboardController::SetMode(const mode& m) +{ + unsigned char colors[2][3] = { {0, 0, 255}, {0, 0, 0} }; + + for(size_t i=0; i < std::min((size_t)2, m.colors.size()); ++i) + { + RGBColor c = m.colors[i]; + colors[i][0] = RGBGetRValue(c); + colors[i][1] = RGBGetGValue(c); + colors[i][2] = RGBGetBValue(c); + } + + unsigned char direction = getDirection(m.direction, m.value); + bool full_color = (m.color_mode == MODE_COLORS_RANDOM || m.value == WINBOND_GK_MODE_CUSTOM); + + setModeImpl(dev, false, m.value, colors, full_color, direction, m.speed, m.brightness); + + if(hasLogoLight) + { + /*---------------------------------------------------------------------------------*\ + | logo light supports static, neon (WINBOND_GK_MODE_LOGO_NEON), breathe, wave | + | all logo modes have brightness, all but static have speed and 2 colors + random | + | select a mode supported by the logo that matches the key mode | + | | + | TODO: the keyboard allows selecting completely different modes for keys and the | + | logo light, but OpenRGB currently doesn't support different modes per zone. | + | if OpenRGB ever supports that, change the code accordingly | + \*---------------------------------------------------------------------------------*/ + int mode = m.value; + int speed = m.speed; + if(mode == WINBOND_GK_MODE_NEON) + { + mode = WINBOND_GK_MODE_LOGO_NEON; + } + else if(mode == WINBOND_GK_MODE_SNAKE) + { + mode = WINBOND_GK_MODE_WAVE; + direction = (direction == 6) ? 1 : 0; + } + else if(mode > WINBOND_GK_MODE_SNAKE) + { + /*------------------------------------------------------*\ + | these remaining modes are reactive, no real equivalent | + | => use static | + \*------------------------------------------------------*/ + mode = WINBOND_GK_MODE_STATIC; + direction = 0; + speed = 0; + } + // else: the other modes < WINBOND_GK_MODE_SNAKE are supported as is + + setModeImpl(dev, true, mode, colors, full_color, direction, speed, m.brightness); + } +} diff --git a/Controllers/WinbondGamingKeyboardController/WinbondGamingKeyboardController.h b/Controllers/WinbondGamingKeyboardController/WinbondGamingKeyboardController.h new file mode 100644 index 00000000..ea25794e --- /dev/null +++ b/Controllers/WinbondGamingKeyboardController/WinbondGamingKeyboardController.h @@ -0,0 +1,87 @@ +/*---------------------------------------------------------*\ +| WinbondGamingKeyboardController.h | +| | +| Driver for Winbond Gaming Keyboard | +| | +| Daniel Gibson 03 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include +#include "RGBController.h" +#include "KeyboardLayoutManager.h" + +class WinbondGamingKeyboardController +{ + void SetNameVendorDescription(const hid_device_info &info, const std::string& name); + void SetVersionLayout(); + void ParseVersionString(const char* str); + +public: + WinbondGamingKeyboardController(hid_device *dev_handle, const hid_device_info &info, const std::string& name); + + std::string GetSerialString(); + + const char* GetDeviceLocation() const + { + return location.c_str(); + } + + const char* GetName() const + { + return name.c_str(); + } + + const char* GetVendor() const + { + return vendor.c_str(); + } + + const char* GetDescription() const + { + return description.c_str(); + } + + const char* GetVersion() const + { + return version.c_str(); + } + + KEYBOARD_LAYOUT GetLayout() const + { + return layout; + } + + bool HasLogoLight() const + { + return hasLogoLight; + } + + KEYBOARD_SIZE GetSize() const + { + return kb_size; + } + + void SetLEDsData(const std::vector& colors, const std::vector& leds, int brightness); + + void SetMode(const mode& m); + +protected: + hid_device* dev = nullptr; + +private: + std::string location; + std::string name; + std::string description; + std::string vendor; + std::string version; + KEYBOARD_LAYOUT layout = KEYBOARD_LAYOUT_ISO_QWERTY; // default to ISO so most keys can be configured + KEYBOARD_SIZE kb_size = KEYBOARD_SIZE_FULL; + bool hasLogoLight = false; +}; diff --git a/Controllers/WinbondGamingKeyboardController/WinbondGamingKeyboardControllerDetect.cpp b/Controllers/WinbondGamingKeyboardController/WinbondGamingKeyboardControllerDetect.cpp new file mode 100644 index 00000000..d372bb27 --- /dev/null +++ b/Controllers/WinbondGamingKeyboardController/WinbondGamingKeyboardControllerDetect.cpp @@ -0,0 +1,66 @@ +/*---------------------------------------------------------*\ +| WinbondGamingKeyboardControllerDetect.cpp | +| | +| Detector for Winbond Gaming Keyboard | +| | +| Daniel Gibson 03 Dec 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "Detector.h" +#include "RGBController_WinbondGamingKeyboard.h" +#include "LogManager.h" + +/*-----------------------------------------------------*\ +| Winbond vendor ID | +\*-----------------------------------------------------*/ +#define WINBOND_VID 0x0416 + +/*-----------------------------------------------------*\ +| Winbond product ID | +\*-----------------------------------------------------*/ +#define WINBOND_GAMING_KEYBOARD_PID 0xB23C + +void DetectWinbondGamingKeyboard(hid_device_info* info, const std::string& name) +{ + hid_device* dev = hid_open_path(info->path); + + /*--------------------------------------------------------------------------------------------------*\ + | NOTE: according to https://4pda.to/forum/index.php?showtopic=1061923, | + | the "KT108" keyboard, which has the same VID:PID, uses the product_string "KT108 keyboard" | + | that could be used for KT108-specific settings? OTOH, according to | + | https://usb-ids.gowdy.us/read/UD/0416/b23c there are also variants of KT108 with | + | product string "Gaming Keyboard". | + | Apart from the KT108, there's also a KT87, but no idea about its product_string, | + | or even its VID/PID (I *assume* it's also 0416:B23C) | + | KT87 and KT108 seem to be sold under the brands WIANXP, Nautilus and Capturer | + | | + | Apart from those noname keyboards that one might only find on aliexpress and similar shops, | + | the Pulsar PCMK TKL keyboard (barebone) uses this VID+PID, and that is the one this is | + | tested with - the ISO variant, specifically. | + | ANSI and JIS variants also exist, I'll try to support them as best as I can. | + | | + | Pulsar also offers a 60% barebone in ISO, ANSI and JIS, but no idea about its VID or PID, | + | or product_string, much less about its protocol (even if it uses the same firmware, | + | I don't know which key corresponds to which bytes in the HID message that sets the per-key colors) | + \*--------------------------------------------------------------------------------------------------*/ + + if(dev) + { + LOG_INFO("Detected WinbondGamingKeyboard at %s, product_string is %ls name is %s", info->path, info->product_string, name.c_str()); + + WinbondGamingKeyboardController* controller = new WinbondGamingKeyboardController(dev, *info, name); + RGBController* rgb_controller = new RGBController_WinbondGamingKeyboard(controller); + + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + else + { + LOG_WARNING("Couldn't open hid dev %s: %ls", info->path, hid_error(NULL)); + } +} + +REGISTER_HID_DETECTOR_PU("Winbond Gaming Keyboard", DetectWinbondGamingKeyboard, WINBOND_VID, WINBOND_GAMING_KEYBOARD_PID, 0xFF1B, 0x91); diff --git a/Controllers/WootingKeyboardController/RGBController_WootingKeyboard.cpp b/Controllers/WootingKeyboardController/RGBController_WootingKeyboard.cpp index 120bc93d..c2af5d37 100644 --- a/Controllers/WootingKeyboardController/RGBController_WootingKeyboard.cpp +++ b/Controllers/WootingKeyboardController/RGBController_WootingKeyboard.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_WootingKeyboard.cpp | -| | -| Generic RGB Interface for Wooting RGB | -| keyboard devices | -| | -| Diogo Trindade (diogotr7) 3/4/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_WootingKeyboard.cpp | +| | +| RGBController for Wooting keyboard | +| | +| Diogo Trindade (diogotr7) 04 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_WootingKeyboard.h" @@ -25,6 +27,16 @@ static unsigned int matrix_map_tkl[6][17] = { 5, 11, 17, NA, NA, NA, 41, NA, NA, NA, 65, 71, 77, 83, 89, 95, 101} }; +static unsigned int matrix_map_80HE[6][17] = +{ + { 0, 6, 12, 18, 24, 30, 36, 42, 48, NA, 60, 66, 72, 78, 84, 90, 100}, + { 1, 7, 13, 19, 25, 31, 37, 43, 49, 55, 61, 67, 73, 79, 85, 91, 97}, + { 2, 8, 14, 20, 26, 32, 38, 44, 50, 56, 62, 68, 74, 80, 86, 92, 98}, + { 3, 9, 15, 21, 27, 33, 39, 45, 51, 57, 63, 69, 75, 81, 87, NA, NA}, + { 4, 10, 16, 22, 28, 34, 40, 46, 52, 58, 64, 70, NA, 82, 88, 94, NA}, + { 5, 11, 17, NA, NA, NA, 41, NA, NA, NA, 65, 71, 77, NA, 89, 95, 101} +}; + static unsigned int matrix_map_full[6][21] = { { 0, NA, 12, 18, 24, 30, 36, 42, 48, 54, 60, 66, 72, 78, 84, 90, 100, 102, 108, 114, 120}, @@ -38,10 +50,11 @@ static unsigned int matrix_map_full[6][21] = static const unsigned int zone_sizes[] = { 102, - 126 + 126, + 102 }; -static const char *led_names[] = +static const char *led_names_default[] = { KEY_EN_ESCAPE, KEY_EN_BACK_TICK, @@ -171,6 +184,112 @@ static const char *led_names[] = KEY_EN_UNUSED }; +static const char *led_names_80HE[] = +{ + KEY_EN_ESCAPE, + KEY_EN_BACK_TICK, + KEY_EN_TAB, + KEY_EN_CAPS_LOCK, + KEY_EN_LEFT_SHIFT, + KEY_EN_LEFT_CONTROL, + KEY_EN_F1, + KEY_EN_1, + KEY_EN_Q, + KEY_EN_A, + KEY_EN_ISO_BACK_SLASH, //iso key - 10 + KEY_EN_LEFT_WINDOWS, + KEY_EN_F2, + KEY_EN_2, + KEY_EN_W, + KEY_EN_S, + KEY_EN_Z, + KEY_EN_LEFT_ALT, + KEY_EN_F3, + KEY_EN_3, + KEY_EN_E, //20 + KEY_EN_D, + KEY_EN_X, + KEY_EN_UNUSED, //space + KEY_EN_F4, + KEY_EN_4, + KEY_EN_R, + KEY_EN_F, + KEY_EN_C, + KEY_EN_UNUSED, //space + KEY_EN_F5, //30 + KEY_EN_5, + KEY_EN_T, + KEY_EN_G, + KEY_EN_V, + KEY_EN_UNUSED, //space + KEY_EN_F6, + KEY_EN_6, + KEY_EN_Y, + KEY_EN_H, + KEY_EN_B, //40 + KEY_EN_SPACE, + KEY_EN_F7, + KEY_EN_7, + KEY_EN_U, + KEY_EN_J, + KEY_EN_N, + KEY_EN_UNUSED, //space + KEY_EN_F8, + KEY_EN_8, + KEY_EN_I, //50 + KEY_EN_K, + KEY_EN_M, + KEY_EN_UNUSED, //space + KEY_EN_UNUSED, + KEY_EN_9, + KEY_EN_O, + KEY_EN_L, + KEY_EN_COMMA, + KEY_EN_UNUSED, //space + KEY_EN_F9, //60 + KEY_EN_0, + KEY_EN_P, + KEY_EN_SEMICOLON, + KEY_EN_PERIOD, + KEY_EN_RIGHT_ALT, + KEY_EN_F10, + KEY_EN_MINUS, + KEY_EN_LEFT_BRACKET, + KEY_EN_QUOTE, + KEY_EN_FORWARD_SLASH, //70 + KEY_EN_RIGHT_WINDOWS, + KEY_EN_F11, + KEY_EN_EQUALS, + KEY_EN_RIGHT_BRACKET, + KEY_EN_POUND, //iso only + KEY_EN_UNUSED, + KEY_EN_RIGHT_FUNCTION, + KEY_EN_F12, + KEY_EN_UNUSED, + KEY_EN_ANSI_BACK_SLASH, //80 + KEY_EN_UNUSED, + KEY_EN_UNUSED, + KEY_EN_RIGHT_CONTROL, + "Key: Mode", + KEY_EN_BACKSPACE, + KEY_EN_UNUSED, + KEY_EN_ANSI_ENTER, + KEY_EN_RIGHT_SHIFT, + KEY_EN_LEFT_ARROW, + KEY_EN_PRINT_SCREEN, //90 + KEY_EN_HOME, + KEY_EN_END, + KEY_EN_UNUSED, + KEY_EN_UP_ARROW, + KEY_EN_DOWN_ARROW, + KEY_EN_UNUSED, + KEY_EN_PAGE_UP, + KEY_EN_PAGE_DOWN, + KEY_EN_UNUSED, + KEY_EN_PAUSE_BREAK, //100 - Scroll lock for WootingTwo KB's + KEY_EN_RIGHT_ARROW +}; + /**------------------------------------------------------------------*\ @name Wooting Keyboards @category Keyboard @@ -184,22 +303,22 @@ static const char *led_names[] = RGBController_WootingKeyboard::RGBController_WootingKeyboard(WootingKeyboardController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; LOG_DEBUG("%sAdding meta data", WOOTING_CONTROLLER_NAME); - name = controller->GetName(); - vendor = controller->GetVendor(); - type = DEVICE_TYPE_KEYBOARD; - description = controller->GetDescription(); - location = controller->GetLocation(); - serial = controller->GetSerial(); + name = controller->GetName(); + vendor = controller->GetVendor(); + type = DEVICE_TYPE_KEYBOARD; + description = controller->GetDescription(); + location = controller->GetLocation(); + serial = controller->GetSerial(); LOG_DEBUG("%sAdding modes", WOOTING_CONTROLLER_NAME); mode Direct; - Direct.name = "Direct"; - Direct.value = 0xFFFF; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); SetupZones(); @@ -245,6 +364,11 @@ void RGBController_WootingKeyboard::SetupZones() new_zone.matrix_map->width = WOOTING_ONE_RGB_COLUMNS; new_zone.matrix_map->map = (unsigned int *)&matrix_map_tkl; } + else if(wooting_type == WOOTING_80HE) + { + new_zone.matrix_map->width = WOOTING_ONE_RGB_COLUMNS; + new_zone.matrix_map->map = (unsigned int *)&matrix_map_80HE; + } else { new_zone.matrix_map->width = WOOTING_TWO_RGB_COLUMNS; @@ -254,6 +378,8 @@ void RGBController_WootingKeyboard::SetupZones() zones.push_back(new_zone); LOG_DEBUG("%sCreating LED array - total_led_count %03i", WOOTING_CONTROLLER_NAME, total_led_count); + + static const char **led_names = (wooting_type == WOOTING_80HE) ? led_names_80HE : led_names_default; for (unsigned int led_idx = 0; led_idx < total_led_count; led_idx++) { led new_led; @@ -278,7 +404,7 @@ void RGBController_WootingKeyboard::ResizeZone(int /*zone*/, int /*new_size*/) void RGBController_WootingKeyboard::DeviceUpdateLEDs() { - controller->SendDirect(&colors[0], colors.size()); + controller->SendDirect(&colors[0], (uint8_t)colors.size()); } void RGBController_WootingKeyboard::UpdateZoneLEDs(int /*zone*/) diff --git a/Controllers/WootingKeyboardController/RGBController_WootingKeyboard.h b/Controllers/WootingKeyboardController/RGBController_WootingKeyboard.h index f0a9291c..b34451eb 100644 --- a/Controllers/WootingKeyboardController/RGBController_WootingKeyboard.h +++ b/Controllers/WootingKeyboardController/RGBController_WootingKeyboard.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_WootingKeyboard.h | -| | -| Generic RGB Interface for Wooting RGB | -| keyboard devices | -| | -| Diogo Trindade (diogotr7) 3/4/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_WootingKeyboard.h | +| | +| RGBController for Wooting keyboard | +| | +| Diogo Trindade (diogotr7) 04 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "WootingKeyboardController.h" @@ -19,7 +22,7 @@ public: void SetupZones(); void ResizeZone(int zone, int new_size); - + void DeviceUpdateLEDs(); void UpdateZoneLEDs(int zone); void UpdateSingleLED(int led); diff --git a/Controllers/WootingKeyboardController/WootingKeyboardController.cpp b/Controllers/WootingKeyboardController/WootingKeyboardController.cpp index 1d666bb7..ad57c756 100644 --- a/Controllers/WootingKeyboardController/WootingKeyboardController.cpp +++ b/Controllers/WootingKeyboardController/WootingKeyboardController.cpp @@ -1,13 +1,16 @@ -/*-------------------------------------------------------------------*\ -| WootingKeyboardController.cpp | -| | -| OpenRGB driver for Wooting RGB keyboardlighting controller | -| https://github.com/WootingKb/wooting-rgb-sdk | -| | -| Chris M (Dr_No) 9th July 2021 | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| WootingKeyboardController.cpp | +| | +| Driver for Wooting keyboard | +| | +| Chris M (Dr_No) 09 Jul 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "StringUtils.h" #include "WootingKeyboardController.h" WootingKeyboardController::WootingKeyboardController() @@ -42,7 +45,15 @@ std::string WootingKeyboardController::GetDescription() std::string WootingKeyboardController::GetSerial() { - return serial; + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } uint8_t WootingKeyboardController::GetWootingType() diff --git a/Controllers/WootingKeyboardController/WootingKeyboardController.h b/Controllers/WootingKeyboardController/WootingKeyboardController.h index 7bb09885..317c7634 100644 --- a/Controllers/WootingKeyboardController/WootingKeyboardController.h +++ b/Controllers/WootingKeyboardController/WootingKeyboardController.h @@ -1,19 +1,21 @@ -/*-------------------------------------------------------------------*\ -| WootingKeyboardController.h | -| | -| OpenRGB driver for Wooting RGB keyboardlighting controller | -| https://github.com/WootingKb/wooting-rgb-sdk | -| | -| Chris M (Dr_No) 9th July 2021 | -\*-------------------------------------------------------------------*/ - -#include "RGBController.h" -#include "LogManager.h" -#include -#include +/*---------------------------------------------------------*\ +| WootingKeyboardController.h | +| | +| Driver for Wooting keyboard | +| | +| Chris M (Dr_No) 09 Jul 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" +#include "LogManager.h" + #define WOOTING_COMMAND_SIZE 8 #define WOOTING_REPORT_SIZE 129 #define WOOTING_RAW_COLORS_REPORT 11 @@ -38,7 +40,8 @@ enum WOOTING_DEVICE_TYPE { WOOTING_KB_TKL = 0, - WOOTING_KB_FULL = 1 + WOOTING_KB_FULL = 1, + WOOTING_80HE = 2 }; enum RGB_PARTS @@ -61,7 +64,6 @@ public: std::string vendor; std::string description; std::string location; - std::string serial; uint8_t wooting_type; uint8_t key_code_limit; diff --git a/Controllers/WootingKeyboardController/WootingKeyboardControllerDetect.cpp b/Controllers/WootingKeyboardController/WootingKeyboardControllerDetect.cpp index 1a24a4de..4a0f06e1 100644 --- a/Controllers/WootingKeyboardController/WootingKeyboardControllerDetect.cpp +++ b/Controllers/WootingKeyboardController/WootingKeyboardControllerDetect.cpp @@ -1,11 +1,20 @@ +/*---------------------------------------------------------*\ +| WootingKeyboardControllerDetect.cpp | +| | +| Detector for Wooting keyboard | +| | +| Diogo Trindade (diogotr7) 04 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "WootingOneKeyboardController.h" #include "WootingTwoKeyboardController.h" -#include "RGBController.h" #include "RGBController_WootingKeyboard.h" #include "LogManager.h" -#include -#include /*-----------------------------------------------------*\ | Wooting vendor ID | @@ -40,6 +49,10 @@ #define WOOTING_TWO_60_HE_ARM_X_PID 0x1310 #define WOOTING_TWO_60_HE_ARM_C_PID 0x1311 #define WOOTING_TWO_60_HE_ARM_N_PID 0x1312 +#define WOOTING_TWO_UWU_RGB_X_PID 0x1510 +#define WOOTING_TWO_UWU_RGB_C_PID 0x1511 +#define WOOTING_TWO_UWU_RGB_N_PID 0x1512 +#define WOOTING_TWO_80HE_PID 0x1400 void DetectWootingOneKeyboardControllers(hid_device_info* info, const std::string& name) { @@ -54,11 +67,10 @@ void DetectWootingOneKeyboardControllers(hid_device_info* info, const std::strin uint8_t wooting_type = (info->product_id == WOOTING_ONE_OLD_PID) ? WOOTING_KB_TKL : WOOTING_KB_FULL; LOG_DEBUG("[%s] Device type %i opened - creating Controller", controller_name, wooting_type); - WootingOneKeyboardController* controller = new WootingOneKeyboardController(dev, info->path, wooting_type); + WootingOneKeyboardController* controller = new WootingOneKeyboardController(dev, info->path, wooting_type, name); LOG_DEBUG("[%s] Controller created - creating RGBController", controller_name); RGBController_WootingKeyboard* rgb_controller = new RGBController_WootingKeyboard(controller); - rgb_controller->name = name; LOG_DEBUG("[%s] Initialization complete - Registering controller\t%s", controller_name, name.c_str()); ResourceManager::get()->RegisterRGBController(rgb_controller); @@ -74,12 +86,18 @@ void DetectWootingTwoKeyboardControllers(hid_device_info* info, const std::strin if(dev) { - LOG_DEBUG("[%s] Device type %i opened - creating Controller", controller_name, WOOTING_KB_FULL); - WootingTwoKeyboardController* controller = new WootingTwoKeyboardController(dev, info->path, WOOTING_KB_FULL); + uint8_t wooting_type; + switch(info->product_id) + { + case WOOTING_TWO_80HE_PID : wooting_type = WOOTING_80HE; break; + default : wooting_type = WOOTING_KB_FULL; break; + } + + LOG_DEBUG("[%s] Device type %i opened - creating Controller", controller_name, wooting_type); + WootingTwoKeyboardController* controller = new WootingTwoKeyboardController(dev, info->path, wooting_type, name); LOG_DEBUG("[%s] Controller created - creating RGBController", controller_name); RGBController_WootingKeyboard* rgb_controller = new RGBController_WootingKeyboard(controller); - rgb_controller->name = name; LOG_DEBUG("[%s] Initialization complete - Registering controller\t%s", controller_name, name.c_str()); ResourceManager::get()->RegisterRGBController(rgb_controller); @@ -109,3 +127,7 @@ REGISTER_HID_DETECTOR_PU("Wooting Two 60HE (None)", DetectWootingTwoKey REGISTER_HID_DETECTOR_PU("Wooting Two 60HE (ARM) (Xbox)", DetectWootingTwoKeyboardControllers, WOOTING_NEW_VID, WOOTING_TWO_60_HE_ARM_X_PID, 0x1337, 1); REGISTER_HID_DETECTOR_PU("Wooting Two 60HE (ARM) (Classic)", DetectWootingTwoKeyboardControllers, WOOTING_NEW_VID, WOOTING_TWO_60_HE_ARM_C_PID, 0x1337, 1); REGISTER_HID_DETECTOR_PU("Wooting Two 60HE (ARM) (None)", DetectWootingTwoKeyboardControllers, WOOTING_NEW_VID, WOOTING_TWO_60_HE_ARM_N_PID, 0x1337, 1); +REGISTER_HID_DETECTOR_PU("Wooting Two UwU RGB (Xbox)", DetectWootingTwoKeyboardControllers, WOOTING_NEW_VID, WOOTING_TWO_UWU_RGB_X_PID, 0x1337, 1); +REGISTER_HID_DETECTOR_PU("Wooting Two UwU RGB (Classic)", DetectWootingTwoKeyboardControllers, WOOTING_NEW_VID, WOOTING_TWO_UWU_RGB_C_PID, 0x1337, 1); +REGISTER_HID_DETECTOR_PU("Wooting Two UwU RGB (None)", DetectWootingTwoKeyboardControllers, WOOTING_NEW_VID, WOOTING_TWO_UWU_RGB_N_PID, 0x1337, 1); +REGISTER_HID_DETECTOR_PU("Wooting Two 80HE", DetectWootingTwoKeyboardControllers, WOOTING_NEW_VID, WOOTING_TWO_80HE_PID, 0x1337, 1); diff --git a/Controllers/WootingKeyboardController/WootingOneKeyboardController.h b/Controllers/WootingKeyboardController/WootingOneKeyboardController.h deleted file mode 100644 index 9799f5c8..00000000 --- a/Controllers/WootingKeyboardController/WootingOneKeyboardController.h +++ /dev/null @@ -1,25 +0,0 @@ -/*-----------------------------------------*\ -| WootingKeyboardController.h | -| | -| Definitions and types for Wooting RGB | -| keyboard lighting controller | -| | -| Diogo Trindade (diogotr7) 3/4/2021 | -\*-----------------------------------------*/ - -#include "WootingKeyboardController.h" - -#pragma once - -class WootingOneKeyboardController : public WootingKeyboardController -{ -public: - WootingOneKeyboardController(hid_device* dev_handle, const char *path, uint8_t wooting_type); - ~WootingOneKeyboardController(); - - void SendDirect(RGBColor* colors, uint8_t colour_count); - -private: - void SendInitialize(); - bool wooting_usb_send_buffer(RGB_PARTS part_number, uint8_t* report_buffer); -}; diff --git a/Controllers/WootingKeyboardController/WootingOneKeyboardController.cpp b/Controllers/WootingKeyboardController/WootingOneKeyboardController/WootingOneKeyboardController.cpp similarity index 86% rename from Controllers/WootingKeyboardController/WootingOneKeyboardController.cpp rename to Controllers/WootingKeyboardController/WootingOneKeyboardController/WootingOneKeyboardController.cpp index 2ecc7f90..be7ca6b5 100644 --- a/Controllers/WootingKeyboardController/WootingOneKeyboardController.cpp +++ b/Controllers/WootingKeyboardController/WootingOneKeyboardController/WootingOneKeyboardController.cpp @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| WootingKeyboardController.cpp | -| | -| Driver for Wooting RGB keyboardlighting | -| controller | -| | -| Diogo Trindade (diogotr7) 3/4/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| WootingOneKeyboardController.cpp | +| | +| Driver for Wooting One keyboard | +| | +| Diogo Trindade (diogotr7) 04 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include +#include "StringUtils.h" #include "WootingOneKeyboardController.h" #undef WOOTING_CONTROLLER_NAME @@ -50,27 +53,25 @@ static uint16_t getCrc16ccitt(const uint8_t* buffer, uint16_t size) return crc; } -WootingOneKeyboardController::WootingOneKeyboardController(hid_device* dev_handle, const char *path, uint8_t wooting_type) +WootingOneKeyboardController::WootingOneKeyboardController(hid_device* dev_handle, const char *path, uint8_t wooting_type, std::string dev_name) { - const int szTemp = 256; - wchar_t tmpName[szTemp]; - dev = dev_handle; location = path; + name = dev_name; this->wooting_type = wooting_type; key_code_limit = (wooting_type == WOOTING_KB_TKL) ? WOOTING_ONE_KEY_CODE_LIMIT : WOOTING_TWO_KEY_CODE_LIMIT; + /*---------------------------------------------------------*\ + | Get device HID manufacturer and product strings | + \*---------------------------------------------------------*/ + const int szTemp = 256; + wchar_t tmpName[szTemp]; + hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - vendor = std::string(wName.begin(), wName.end()); + vendor = std::string(StringUtils::wstring_to_string(tmpName)); hid_get_product_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - description = std::string(wName.begin(), wName.end()); - - hid_get_serial_number_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - serial = std::string(wName.begin(), wName.end()); + description = std::string(StringUtils::wstring_to_string(tmpName)); SendInitialize(); } diff --git a/Controllers/WootingKeyboardController/WootingOneKeyboardController/WootingOneKeyboardController.h b/Controllers/WootingKeyboardController/WootingOneKeyboardController/WootingOneKeyboardController.h new file mode 100644 index 00000000..7f1339c6 --- /dev/null +++ b/Controllers/WootingKeyboardController/WootingOneKeyboardController/WootingOneKeyboardController.h @@ -0,0 +1,27 @@ +/*---------------------------------------------------------*\ +| WootingOneKeyboardController.h | +| | +| Driver for Wooting One keyboard | +| | +| Diogo Trindade (diogotr7) 04 Mar 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "WootingKeyboardController.h" + +class WootingOneKeyboardController : public WootingKeyboardController +{ +public: + WootingOneKeyboardController(hid_device* dev_handle, const char *path, uint8_t wooting_type, std::string dev_name); + ~WootingOneKeyboardController(); + + void SendDirect(RGBColor* colors, uint8_t colour_count); + +private: + void SendInitialize(); + bool wooting_usb_send_buffer(RGB_PARTS part_number, uint8_t* report_buffer); +}; diff --git a/Controllers/WootingKeyboardController/WootingTwoKeyboardController.cpp b/Controllers/WootingKeyboardController/WootingTwoKeyboardController.cpp deleted file mode 100644 index 16cab360..00000000 --- a/Controllers/WootingKeyboardController/WootingTwoKeyboardController.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/*-------------------------------------------------------------------*\ -| WootingTwoKeyboardController.cpp | -| | -| OpenRGB driver for Wooting RGB keyboardlighting controller | -| https://github.com/WootingKb/wooting-rgb-sdk | -| | -| Chris M (Dr_No) 9th July 2021 | -\*-------------------------------------------------------------------*/ - -#include -#include "WootingTwoKeyboardController.h" - -#define WOOTING_TWO_REPORT_SIZE 257 - -#undef WOOTING_CONTROLLER_NAME -#define WOOTING_CONTROLLER_NAME "[WootingTWO] " - -//Indicates an unused entry in matrix -#define NA 0x7D - -//WootingTwo uses a 16bit color space -typedef uint16_t R5G6B5_color; -#define RGB888ToRGBcolor16(r, g, b) ((R5G6B5_color)((red & 0xF8) << 8 | (green & 0xFC) << 3 | (b & 0xF8) >> 3)) -#define RGB32ToRGBcolor16(color32) ((R5G6B5_color)((color32 & 0xF8) << 8 | (color32 & 0xFC00) >> 5 | (color32 & 0xF80000) >> 19)) - -static unsigned int matrix_to_led_index_map_full[WOOTING_RGB_ROWS * WOOTING_TWO_RGB_COLUMNS] = -{ - 0, 21, 42, 63, 84, 105, NA, 22, 43, 64, 85, 106, 2, 23, 44, 65, 86, 107, 3, 24, 45, - 66, 87, NA, 4, 25, 46, 67, 88, NA, 5, 26, 47, 68, 89, NA, 6, 27, 48, 69, 90, 111, - 7, 28, 49, 70, 91, NA, 8, 29, 50, 71, 92, NA, 9, 30, 51, 72, 93, NA, 10, 31, 52, - 73, 94, 115, 11, 32, 53, 74, 95, 116, 12, 33, 54, 75, NA, 117, 13, 34, 55, 76, 97, 118, - 14, 35, 56, NA, NA, 119, 15, 36, 57, NA, 99, 120, NA, 37, 58, NA, 16, 121, 17, 38, 59, - 80, 101, NA, 18, 39, 60, 81, 102, 123, 19, 40, 61, 82, 103, 124, 20, 41, 62, NA, 104, NA -}; - -WootingTwoKeyboardController::WootingTwoKeyboardController(hid_device* dev_handle, const char *path, uint8_t wooting_type) -{ - const int szTemp = 256; - wchar_t tmpName[szTemp]; - - dev = dev_handle; - location = path; - this->wooting_type = wooting_type; - key_code_limit = (wooting_type == WOOTING_KB_TKL) ? WOOTING_ONE_KEY_CODE_LIMIT : WOOTING_TWO_KEY_CODE_LIMIT; - - hid_get_manufacturer_string(dev, tmpName, szTemp); - std::wstring wName = std::wstring(tmpName); - vendor = std::string(wName.begin(), wName.end()); - - hid_get_product_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - description = std::string(wName.begin(), wName.end()); - - hid_get_serial_number_string(dev, tmpName, szTemp); - wName = std::wstring(tmpName); - serial = std::string(wName.begin(), wName.end()); - - SendInitialize(); -} - -WootingTwoKeyboardController::~WootingTwoKeyboardController() -{ - -} - -void WootingTwoKeyboardController::SendDirect(RGBColor* colors, uint8_t color_count) -{ - uint8_t rgb_buffer[WOOTING_TWO_REPORT_SIZE] = { 0, 0xD0, 0xDA, WOOTING_RAW_COLORS_REPORT}; - - for(std::size_t index = 0; index < color_count; index++) - { - uint8_t buffer_index = 4 + (matrix_to_led_index_map_full[index] * 2); - R5G6B5_color color16 = RGB32ToRGBcolor16(colors[index]); - - LOG_TRACE("%sSetting LED %03i @ buffer %03i - RGB32 %08X RGB16 %04X", WOOTING_CONTROLLER_NAME, index, buffer_index, colors[index], color16); - rgb_buffer[buffer_index] = color16 & 0xFF; - rgb_buffer[buffer_index+1] = color16 >> 8; - } - - wooting_usb_send_buffer(RGB_PARTS::PART0, rgb_buffer); -} - -void WootingTwoKeyboardController::SendInitialize() -{ - wooting_usb_send_feature(WOOTING_COLOR_INIT_COMMAND, 0,0,0,0); - - std::this_thread::sleep_for(std::chrono::milliseconds(50)); -} - -bool WootingTwoKeyboardController::wooting_usb_send_buffer(RGB_PARTS /*part_number*/, uint8_t* report_buffer) -{ - uint16_t report_size = hid_write(dev, report_buffer, WOOTING_TWO_REPORT_SIZE); - LOG_DEBUG("%sSend buffer returned - %04i expected %04i", WOOTING_CONTROLLER_NAME, report_size, WOOTING_TWO_REPORT_SIZE); - return (report_size == WOOTING_TWO_REPORT_SIZE); -} diff --git a/Controllers/WootingKeyboardController/WootingTwoKeyboardController.h b/Controllers/WootingKeyboardController/WootingTwoKeyboardController.h deleted file mode 100644 index 45ff1a20..00000000 --- a/Controllers/WootingKeyboardController/WootingTwoKeyboardController.h +++ /dev/null @@ -1,25 +0,0 @@ -/*-------------------------------------------------------------------*\ -| WootingTwoKeyboardController.h | -| | -| OpenRGB driver for Wooting RGB keyboardlighting controller | -| https://github.com/WootingKb/wooting-rgb-sdk | -| | -| Chris M (Dr_No) 9th July 2021 | -\*-------------------------------------------------------------------*/ - -#include "WootingKeyboardController.h" - -#pragma once - -class WootingTwoKeyboardController : public WootingKeyboardController -{ -public: - WootingTwoKeyboardController(hid_device* dev_handle, const char *path, uint8_t wooting_type); - ~WootingTwoKeyboardController(); - - void SendDirect(RGBColor* colors, uint8_t colour_count); - -private: - void SendInitialize(); - bool wooting_usb_send_buffer(RGB_PARTS part_number, uint8_t* report_buffer); -}; diff --git a/Controllers/WootingKeyboardController/WootingTwoKeyboardController/WootingTwoKeyboardController.cpp b/Controllers/WootingKeyboardController/WootingTwoKeyboardController/WootingTwoKeyboardController.cpp new file mode 100644 index 00000000..8fedefc6 --- /dev/null +++ b/Controllers/WootingKeyboardController/WootingTwoKeyboardController/WootingTwoKeyboardController.cpp @@ -0,0 +1,96 @@ +/*---------------------------------------------------------*\ +| WootingTwoKeyboardController.cpp | +| | +| Driver for Wooting Two keyboard | +| | +| Chris M (Dr_No) 09 Jul 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "StringUtils.h" +#include "WootingTwoKeyboardController.h" + +#define WOOTING_TWO_REPORT_SIZE 257 + +#undef WOOTING_CONTROLLER_NAME +#define WOOTING_CONTROLLER_NAME "[WootingTWO] " + +//Indicates an unused entry in matrix +#define NA 0x7D + +//WootingTwo uses a 16bit color space +typedef uint16_t R5G6B5_color; +#define RGB888ToRGBcolor16(r, g, b) ((R5G6B5_color)((red & 0xF8) << 8 | (green & 0xFC) << 3 | (b & 0xF8) >> 3)) +#define RGB32ToRGBcolor16(color32) ((R5G6B5_color)((color32 & 0xF8) << 8 | (color32 & 0xFC00) >> 5 | (color32 & 0xF80000) >> 19)) + +static unsigned int matrix_to_led_index_map_full[WOOTING_RGB_ROWS * WOOTING_TWO_RGB_COLUMNS] = +{ + 0, 21, 42, 63, 84, 105, 1, 22, 43, 64, 85, 106, 2, 23, 44, 65, 86, 107, 3, 24, 45, + 66, 87, NA, 4, 25, 46, 67, 88, NA, 5, 26, 47, 68, 89, NA, 6, 27, 48, 69, 90, 111, + 7, 28, 49, 70, 91, NA, 8, 29, 50, 71, 92, NA, 9, 30, 51, 72, 93, NA, 10, 31, 52, + 73, 94, 115, 11, 32, 53, 74, 95, 116, 12, 33, 54, 75, NA, 117, 13, 34, 55, 76, 97, 118, + 14, 35, 56, 77, 98, 119, 15, 36, 57, NA, 99, 120, 16, 37, 58, NA, 16, 121, 17, 38, 59, + 80, 101, NA, 18, 39, 60, 81, 102, 123, 19, 40, 61, 82, 103, 124, 20, 41, 62, NA, 104, NA +}; + +WootingTwoKeyboardController::WootingTwoKeyboardController(hid_device* dev_handle, const char *path, uint8_t wooting_type, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + this->wooting_type = wooting_type; + key_code_limit = (wooting_type == WOOTING_KB_TKL) ? WOOTING_ONE_KEY_CODE_LIMIT : WOOTING_TWO_KEY_CODE_LIMIT; + + /*---------------------------------------------------------*\ + | Get device HID manufacturer and product strings | + \*---------------------------------------------------------*/ + const int szTemp = 256; + wchar_t tmpName[szTemp]; + + hid_get_manufacturer_string(dev, tmpName, szTemp); + vendor = std::string(StringUtils::wstring_to_string(tmpName)); + + hid_get_product_string(dev, tmpName, szTemp); + description = std::string(StringUtils::wstring_to_string(tmpName)); + + SendInitialize(); +} + +WootingTwoKeyboardController::~WootingTwoKeyboardController() +{ + +} + +void WootingTwoKeyboardController::SendDirect(RGBColor* colors, uint8_t color_count) +{ + uint8_t rgb_buffer[WOOTING_TWO_REPORT_SIZE] = { 0, 0xD0, 0xDA, WOOTING_RAW_COLORS_REPORT}; + + for(std::size_t index = 0; index < color_count; index++) + { + uint8_t buffer_index = 4 + (matrix_to_led_index_map_full[index] * 2); + R5G6B5_color color16 = RGB32ToRGBcolor16(colors[index]); + + LOG_TRACE("%sSetting LED %03i @ buffer %03i - RGB32 %08X RGB16 %04X", WOOTING_CONTROLLER_NAME, index, buffer_index, colors[index], color16); + rgb_buffer[buffer_index] = color16 & 0xFF; + rgb_buffer[buffer_index+1] = color16 >> 8; + } + + wooting_usb_send_buffer(RGB_PARTS::PART0, rgb_buffer); +} + +void WootingTwoKeyboardController::SendInitialize() +{ + wooting_usb_send_feature(WOOTING_COLOR_INIT_COMMAND, 0,0,0,0); + + std::this_thread::sleep_for(std::chrono::milliseconds(50)); +} + +bool WootingTwoKeyboardController::wooting_usb_send_buffer(RGB_PARTS /*part_number*/, uint8_t* report_buffer) +{ + uint16_t report_size = hid_write(dev, report_buffer, WOOTING_TWO_REPORT_SIZE); + LOG_DEBUG("%sSend buffer returned - %04i expected %04i", WOOTING_CONTROLLER_NAME, report_size, WOOTING_TWO_REPORT_SIZE); + return (report_size == WOOTING_TWO_REPORT_SIZE); +} diff --git a/Controllers/WootingKeyboardController/WootingTwoKeyboardController/WootingTwoKeyboardController.h b/Controllers/WootingKeyboardController/WootingTwoKeyboardController/WootingTwoKeyboardController.h new file mode 100644 index 00000000..c6d40e4f --- /dev/null +++ b/Controllers/WootingKeyboardController/WootingTwoKeyboardController/WootingTwoKeyboardController.h @@ -0,0 +1,27 @@ +/*---------------------------------------------------------*\ +| WootingTwoKeyboardController.h | +| | +| Driver for Wooting Two keyboard | +| | +| Chris M (Dr_No) 09 Jul 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "WootingKeyboardController.h" + +class WootingTwoKeyboardController : public WootingKeyboardController +{ +public: + WootingTwoKeyboardController(hid_device* dev_handle, const char *path, uint8_t wooting_type, std::string dev_name); + ~WootingTwoKeyboardController(); + + void SendDirect(RGBColor* colors, uint8_t colour_count); + +private: + void SendInitialize(); + bool wooting_usb_send_buffer(RGB_PARTS part_number, uint8_t* report_buffer); +}; diff --git a/Controllers/WushiController/RGBController_WushiL50USB.cpp b/Controllers/WushiController/RGBController_WushiL50USB.cpp index 0eefe7be..157c399f 100644 --- a/Controllers/WushiController/RGBController_WushiL50USB.cpp +++ b/Controllers/WushiController/RGBController_WushiL50USB.cpp @@ -1,8 +1,11 @@ -/*-------------------------------------*\ -| RGBController_WushiL50USB.cpp | -| | -| interface for Wushi L50 Devices | -\*-------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_WushiL50USB.cpp | +| | +| RGBController for Wushi L50 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_WushiL50USB.h" diff --git a/Controllers/WushiController/RGBController_WushiL50USB.h b/Controllers/WushiController/RGBController_WushiL50USB.h index a0796ff9..57b2b7e6 100644 --- a/Controllers/WushiController/RGBController_WushiL50USB.h +++ b/Controllers/WushiController/RGBController_WushiL50USB.h @@ -1,16 +1,18 @@ -/*-------------------------------------*\ -| RGBController_WushiL50USB.h | -| | -| interface for Wushi L50 Devices | -\*-------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_WushiL50USB.h | +| | +| RGBController for Wushi L50 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include #include "WushiL50USBController.h" #include "RGBController.h" -#include - class RGBController_WushiL50USB : public RGBController { public: diff --git a/Controllers/WushiController/WushiL50USBController.cpp b/Controllers/WushiController/WushiL50USBController.cpp index d8364424..008155bf 100644 --- a/Controllers/WushiController/WushiL50USBController.cpp +++ b/Controllers/WushiController/WushiL50USBController.cpp @@ -1,18 +1,22 @@ -/*-------------------------------------*\ -| WushiL50USBController.h | -| | -| interface for Wushi L50 Devices | -\*-------------------------------------*/ +/*---------------------------------------------------------*\ +| WushiL50USBController.cpp | +| | +| Driver for Wushi L50 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include - +#include "StringUtils.h" #include "WushiL50USBController.h" -WushiL50USBController::WushiL50USBController(hidapi_wrapper hid_wrapper, hid_device* dev_handle, const char* path) +WushiL50USBController::WushiL50USBController(hidapi_wrapper hid_wrapper, hid_device* dev_handle, const char* path, std::string dev_name) { wrapper = hid_wrapper; dev = dev_handle; location = path; + name = dev_name; } WushiL50USBController::~WushiL50USBController() @@ -20,6 +24,29 @@ WushiL50USBController::~WushiL50USBController() wrapper.hid_close(dev); } +std::string WushiL50USBController::getName() +{ + return name; +} + +std::string WushiL50USBController::getLocation() +{ + return location; +} + +std::string WushiL50USBController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = wrapper.hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + void WushiL50USBController::setMode(WushiL50State * in_mode) { unsigned char usb_buf[WUSHI_L50_HID_PACKET_SIZE]; @@ -59,18 +86,3 @@ void WushiL50USBController::setMode(WushiL50State * in_mode) \*-----------------------------------------------------*/ wrapper.hid_send_feature_report(dev, usb_buf, WUSHI_L50_HID_PACKET_SIZE); } - -std::string WushiL50USBController::getName() -{ - return name; -} - -std::string WushiL50USBController::getLocation() -{ - return location; -} - -std::string WushiL50USBController::GetSerialString() -{ - return(serial_number); -} diff --git a/Controllers/WushiController/WushiL50USBController.h b/Controllers/WushiController/WushiL50USBController.h index af4a59ef..7355b61f 100644 --- a/Controllers/WushiController/WushiL50USBController.h +++ b/Controllers/WushiController/WushiL50USBController.h @@ -1,16 +1,17 @@ -/*-------------------------------------*\ -| WushiL50USBController.h | -| | -| interface for Wushi L50 Devices | -\*-------------------------------------*/ +/*---------------------------------------------------------*\ +| WushiL50USBController.h | +| | +| Driver for Wushi L50 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include "RGBController.h" - #include -#include - +#include +#include "RGBController.h" #include "hidapi_wrapper.h" #ifndef HID_MAX_STR @@ -94,19 +95,18 @@ public: class WushiL50USBController { public: - WushiL50USBController(hidapi_wrapper hid_wrapper, hid_device* dev_handle, const char* path); + WushiL50USBController(hidapi_wrapper hid_wrapper, hid_device* dev_handle, const char* path, std::string dev_name); ~WushiL50USBController(); - void setMode(WushiL50State * in_mode); - std::string getName(); std::string getLocation(); std::string GetSerialString(); + void setMode(WushiL50State * in_mode); + private: - std::string name; hidapi_wrapper wrapper; hid_device * dev; std::string location; - std::string serial_number; + std::string name; }; diff --git a/Controllers/WushiController/WushiL50USBDetect.cpp b/Controllers/WushiController/WushiL50USBDetect.cpp index 831b6886..0d9554cd 100644 --- a/Controllers/WushiController/WushiL50USBDetect.cpp +++ b/Controllers/WushiController/WushiL50USBDetect.cpp @@ -1,9 +1,16 @@ +/*---------------------------------------------------------*\ +| WushiL50USBControllerDetect.cpp | +| | +| Detector for Wushi L50 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" -#include "LogManager.h" -#include "RGBController.h" #include "WushiL50USBController.h" #include "RGBController_WushiL50USB.h" -#include /*-----------------------------------------------------*\ | Wushi vendor ID | @@ -21,9 +28,8 @@ void DetectWushiL50USBControllers(hidapi_wrapper wrapper, hid_device_info* info, if(dev) { - WushiL50USBController* controller = new WushiL50USBController(wrapper, dev, info->path); + WushiL50USBController* controller = new WushiL50USBController(wrapper, dev, info->path, name); RGBController_WushiL50USB* rgb_controller = new RGBController_WushiL50USB(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } diff --git a/Controllers/XPGSummonerKeyboardController/RGBController_XPGSummoner.cpp b/Controllers/XPGSummonerKeyboardController/RGBController_XPGSummoner.cpp new file mode 100644 index 00000000..4e465f0e --- /dev/null +++ b/Controllers/XPGSummonerKeyboardController/RGBController_XPGSummoner.cpp @@ -0,0 +1,430 @@ +/*---------------------------------------------------------*\ +| RGBController_XPGSummoner.cpp | +| | +| RGBController for XPG Summoner keyboard | +| | +| Erick Granados (eriosgamer) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "RGBControllerKeyNames.h" +#include "RGBController_XPGSummoner.h" + +#define NA 0xFFFFFFFF +#define LED_REAL_COUNT (6 * 21) +#define LED_COUNT (LED_REAL_COUNT - 22) + +/*---------------------------------------------------------*\ +| ordered_matrix: Physical LED layout | +\*---------------------------------------------------------*/ +static unsigned int ordered_matrix[6][21] = +{ + {0, NA, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, NA, NA, NA, NA}, + {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36}, + {37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57}, + {58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, NA, 70, NA, NA, NA, 71, 72, 73, NA}, + {74, NA, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, NA, NA, 86, NA, 87, 88, 89, 90}, + {91, 92, 93, NA, NA, NA, 94, NA, NA, NA, 95, 96, 97, 98, 99, 100, 101, 102, NA, 103, NA} +}; + +/*---------------------------------------------------------*\ +| matrix_map: Logical LED mapping | +\*---------------------------------------------------------*/ +static unsigned int matrix_map[6][21] = +{ + {11, NA, 22, 30, 25, 27, 7, 51, 57, 62, 86, 87, 83, 85, 79, 72, 0, NA, NA, NA, NA}, + {14, 15, 23, 31, 39, 38, 46, 47, 55, 63, 71, 70, 54, 81, 102, 118, 110, 92, 100, 108, 109}, + {9, 8, 16, 24, 32, 33, 41, 40, 48, 56, 64, 65, 49, 82, 94, 119, 111, 88, 96, 104, 112}, + {17, 10, 18, 26, 34, 35, 43, 42, 50, 58, 66, 67, NA, 84, NA, NA, NA, 89, 97, 105, NA}, + {121, NA, 12, 20, 28, 36, 37, 45, 44, 52, 60, 69, 122, NA, NA, 115, NA, 90, 98, 106, 114}, + {6, 124, 75, NA, NA, NA, 91, NA, NA, NA, 77, 125, 61, 4, 117, 93, 101, 99, NA, 107, NA} +}; + +/*---------------------------------------------------------*\ +| zone_names: Zone names | +\*---------------------------------------------------------*/ +const char *zone_names[] = +{ + ZONE_EN_KEYBOARD +}; + +zone_type zone_types[] = +{ + ZONE_TYPE_MATRIX +}; + +const unsigned int zone_sizes[] = +{ + LED_COUNT +}; + +/*---------------------------------------------------------*\ +| led_names: LED names | +\*---------------------------------------------------------*/ +static const char *led_names[] = +{ + KEY_EN_ESCAPE, // Esc + KEY_EN_F1, // F1 + KEY_EN_F2, // F2 + KEY_EN_F3, // F3 + KEY_EN_F4, // F4 + KEY_EN_F5, // F5 + KEY_EN_F6, // F6 + KEY_EN_F7, // F7 + KEY_EN_F8, // F8 + KEY_EN_F9, // F9 + KEY_EN_F10, // F10 + KEY_EN_F11, // F11 + KEY_EN_F12, // F12 + KEY_EN_PRINT_SCREEN, // PrtSc + KEY_EN_SCROLL_LOCK, // Scroll + KEY_EN_PAUSE_BREAK, // Pause + KEY_EN_BACK_TICK, // ` + KEY_EN_1, // 1 + KEY_EN_2, // 2 + KEY_EN_3, // 3 + KEY_EN_4, // 4 + KEY_EN_5, // 5 + KEY_EN_6, // 6 + KEY_EN_7, // 7 + KEY_EN_8, // 8 + KEY_EN_9, // 9 + KEY_EN_0, // 0 + KEY_EN_MINUS, // - + KEY_EN_EQUALS, // = + KEY_EN_BACKSPACE, // Backspace + KEY_EN_INSERT, // Insert + KEY_EN_HOME, // Home + KEY_EN_PAGE_UP, // PgUp + KEY_EN_NUMPAD_LOCK, // NumLock + KEY_EN_NUMPAD_DIVIDE, // / + KEY_EN_NUMPAD_TIMES, // * + KEY_EN_NUMPAD_MINUS, // - + KEY_EN_TAB, // Tab + KEY_EN_Q, // Q + KEY_EN_W, // W + KEY_EN_E, // E + KEY_EN_R, // R + KEY_EN_T, // T + KEY_EN_Y, // Y + KEY_EN_U, // U + KEY_EN_I, // I + KEY_EN_O, // O + KEY_EN_P, // P + KEY_EN_LEFT_BRACKET, // [ + KEY_EN_RIGHT_BRACKET, // ] + KEY_EN_ANSI_BACK_SLASH, // Backslash + KEY_EN_DELETE, // Del + KEY_EN_END, // End + KEY_EN_PAGE_DOWN, // PgDn + KEY_EN_NUMPAD_7, // 7 + KEY_EN_NUMPAD_8, // 8 + KEY_EN_NUMPAD_9, // 9 + KEY_EN_NUMPAD_PLUS, // + + KEY_EN_CAPS_LOCK, // Caps + KEY_EN_A, // A + KEY_EN_S, // S + KEY_EN_D, // D + KEY_EN_F, // F + KEY_EN_G, // G + KEY_EN_H, // H + KEY_EN_J, // J + KEY_EN_K, // K + KEY_EN_L, // L + KEY_EN_SEMICOLON, // ; + KEY_EN_QUOTE, // ' + KEY_EN_ISO_ENTER, // Enter + KEY_EN_NUMPAD_4, // 4 + KEY_EN_NUMPAD_5, // 5 + KEY_EN_NUMPAD_6, // 6 + KEY_EN_LEFT_SHIFT, // Shift + KEY_EN_Z, // Z + KEY_EN_X, // X + KEY_EN_C, // C + KEY_EN_V, // V + KEY_EN_B, // B + KEY_EN_N, // N + KEY_EN_M, // M + KEY_EN_COMMA, // , + KEY_EN_PERIOD, // . + KEY_EN_FORWARD_SLASH, // / + KEY_EN_RIGHT_SHIFT, // Shift + KEY_EN_UP_ARROW, // ↑ + KEY_EN_NUMPAD_1, // 1 + KEY_EN_NUMPAD_2, // 2 + KEY_EN_NUMPAD_3, // 3 + KEY_EN_NUMPAD_ENTER, // Enter + KEY_EN_LEFT_CONTROL, // Ctrl + KEY_EN_LEFT_WINDOWS, // Win + KEY_EN_LEFT_ALT, // Alt + KEY_EN_SPACE, // Space + KEY_EN_RIGHT_ALT, // AltGr + KEY_EN_RIGHT_FUNCTION, // Fn + KEY_EN_MENU, // Menu + KEY_EN_RIGHT_CONTROL, // Ctrl + KEY_EN_LEFT_ARROW, // ↠+ KEY_EN_DOWN_ARROW, // ↓ + KEY_EN_RIGHT_ARROW, // → + KEY_EN_NUMPAD_0, // 0 + KEY_EN_NUMPAD_PERIOD // . +}; + +/**------------------------------------------------------------------*\ + @name XPG Summoner Keyboard + @category Keyboard + @type USB + @save :x: + @direct :white_check_mark: + @effects :white_check_mark: + @detectors DetectXPGSummonerControllers + @comment +\*-------------------------------------------------------------------*/ + +/*---------------------------------------------------------*\ +| RGBController_XPGSummoner constructor | +\*---------------------------------------------------------*/ +RGBController_XPGSummoner::RGBController_XPGSummoner(XPGSummonerController *controller_ptr) +{ + controller = controller_ptr; + name = controller->GetNameString(); + vendor = "XPG"; + description = "XPG Summoner Keyboard Device"; + location = controller->GetLocationString(); + serial = controller->GetSerialString(); + type = DEVICE_TYPE_KEYBOARD; + + mode Direct; + Direct.name = "Direct"; + Direct.value = XPG_SUMMONER_MODE_DIRECT; + 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 = XPG_SUMMONER_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors_min = 1; + Static.colors_max = 1; + Static.brightness_min = 5; + Static.brightness_max = 64; + Static.colors.resize(1); + modes.push_back(Static); + + mode Stars; + Stars.name = "Stars"; + Stars.value = XPG_SUMMONER_MODE_STARS; + Stars.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Stars.colors_min = 1; + Stars.colors_max = 1; + Stars.color_mode = MODE_COLORS_MODE_SPECIFIC; + Stars.colors.resize(1); + modes.push_back(Stars); + + mode Off; + Off.name = "Off"; + Off.value = XPG_SUMMONER_MODE_OFF; + Off.flags = 0; + Off.color_mode = MODE_COLORS_NONE; + modes.push_back(Off); + + SetupZones(); +} + +/*---------------------------------------------------------*\ +| Destructor | +\*---------------------------------------------------------*/ +RGBController_XPGSummoner::~RGBController_XPGSummoner() +{ + 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; + } + } + delete controller; +} + +/*---------------------------------------------------------*\ +| SetupZones: Initializes zones and LEDs | +\*---------------------------------------------------------*/ +void RGBController_XPGSummoner::SetupZones() +{ + leds.clear(); + colors.clear(); + zones.clear(); + leds.reserve(LED_COUNT); + colors.reserve(LED_COUNT); + zones.reserve(1); + + zone new_zone; + new_zone.name = zone_names[0]; + new_zone.type = zone_types[0]; + new_zone.leds_min = zone_sizes[0]; + new_zone.leds_max = zone_sizes[0]; + new_zone.leds_count = zone_sizes[0]; + + if(new_zone.type == ZONE_TYPE_MATRIX) + { + new_zone.matrix_map = new matrix_map_type; + new_zone.matrix_map->height = 6; + new_zone.matrix_map->width = 21; + new_zone.matrix_map->map = (unsigned int *)&ordered_matrix; + } + else + { + new_zone.matrix_map = NULL; + } + zones.push_back(new_zone); + + size_t linear_idx = 0; + for(int row = 0; row < 6; ++row) + { + for(int col = 0; col < 21; ++col) + { + unsigned int led_id = matrix_map[row][col]; + if(led_id == NA) + continue; + led new_led; + new_led.name = led_names[linear_idx]; + new_led.value = led_id; + leds.push_back(new_led); + ++linear_idx; + } + } + colors.assign(LED_COUNT, 0x000000); + + SetupColors(); +} + +/*---------------------------------------------------------*\ +| ResizeZone: Not supported for this device | +\*---------------------------------------------------------*/ +void RGBController_XPGSummoner::ResizeZone(int /*zone*/, int /*new_size*/) +{ + // This device does not support resizing zones +} + +/*---------------------------------------------------------*\ +| DeviceUpdateLEDs: Updates LED colors | +\*---------------------------------------------------------*/ +void RGBController_XPGSummoner::DeviceUpdateLEDs() +{ + const unsigned char brightness = 0x64; + const unsigned int frame_buf_length = 126 * 4; + unsigned char frame_buf[frame_buf_length] = {0}; + + for(std::size_t led_idx = 0; led_idx < leds.size(); led_idx++) + { + if(leds[led_idx].value == NA) + continue; + if(modes[active_mode].color_mode == MODE_COLORS_PER_LED) + { + std::size_t real_idx = leds[led_idx].value; + frame_buf[(real_idx * 4) + 0] = brightness; + frame_buf[(real_idx * 4) + 1] = RGBGetRValue(colors[led_idx]); + frame_buf[(real_idx * 4) + 2] = RGBGetGValue(colors[led_idx]); + frame_buf[(real_idx * 4) + 3] = RGBGetBValue(colors[led_idx]); + } + else if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC && modes[active_mode].value == XPG_SUMMONER_MODE_STATIC) + { + std::size_t real_idx = leds[led_idx].value; + frame_buf[(real_idx * 4) + 0] = modes[active_mode].brightness; + frame_buf[(real_idx * 4) + 1] = RGBGetRValue(modes[active_mode].colors[0]); + frame_buf[(real_idx * 4) + 2] = RGBGetGValue(modes[active_mode].colors[0]); + frame_buf[(real_idx * 4) + 3] = RGBGetBValue(modes[active_mode].colors[0]); + } + else if(modes[active_mode].color_mode == MODE_COLORS_MODE_SPECIFIC && modes[active_mode].value == XPG_SUMMONER_MODE_STARS) + { + for(std::size_t i = 0; i < leds.size(); ++i) + { + std::size_t real_idx = leds[i].value; + frame_buf[(real_idx * 4) + 0] = 0; + frame_buf[(real_idx * 4) + 1] = 0; + frame_buf[(real_idx * 4) + 2] = 0; + frame_buf[(real_idx * 4) + 3] = 0; + } + controller->SendColors(frame_buf, sizeof(frame_buf)); + + /*---------------------------------------------------*\ + | Select a random central LED in the physical matrix | + \*---------------------------------------------------*/ + int rows = 6; + int cols = 21; + int center_row = rand() % rows; + int center_col = rand() % cols; + unsigned int center_led = matrix_map[center_row][center_col]; + + if(center_led != NA) + { + frame_buf[(center_led * 4) + 0] = brightness; + frame_buf[(center_led * 4) + 1] = RGBGetRValue(modes[active_mode].colors[0]); + frame_buf[(center_led * 4) + 2] = RGBGetGValue(modes[active_mode].colors[0]); + frame_buf[(center_led * 4) + 3] = RGBGetBValue(modes[active_mode].colors[0]); + } + + /*---------------------------------------------------*\ + | Neighbors (fade effect) | + \*---------------------------------------------------*/ + unsigned char fade_brightness = 0x32; + int neighbor_offsets[4][2] = { {0, -1}, {0, +1}, {-1, 0}, {+1, 0} }; + + for(int k = 0; k < 4; ++k) + { + int n_row = center_row + neighbor_offsets[k][0]; + int n_col = center_col + neighbor_offsets[k][1]; + if(n_row >= 0 && n_row < rows && n_col >= 0 && n_col < cols) + { + unsigned int neighbor_led = matrix_map[n_row][n_col]; + if(neighbor_led != NA) + { + frame_buf[(neighbor_led * 4) + 0] = fade_brightness; + frame_buf[(neighbor_led * 4) + 1] = RGBGetRValue(modes[active_mode].colors[0]); + frame_buf[(neighbor_led * 4) + 2] = RGBGetGValue(modes[active_mode].colors[0]); + frame_buf[(neighbor_led * 4) + 3] = RGBGetBValue(modes[active_mode].colors[0]); + } + } + } + controller->SendColors(frame_buf, sizeof(frame_buf)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + } + else if(modes[active_mode].color_mode == MODE_COLORS_NONE) + { + std::size_t real_idx = leds[led_idx].value; + frame_buf[(real_idx * 4) + 0] = 0; + frame_buf[(real_idx * 4) + 1] = 0; + frame_buf[(real_idx * 4) + 2] = 0; + frame_buf[(real_idx * 4) + 3] = 0; + } + } + controller->SendColors(frame_buf, sizeof(frame_buf)); +} + +/*---------------------------------------------------------*\ +| UpdateZoneLEDs: Updates all LEDs in a zone | +\*---------------------------------------------------------*/ +void RGBController_XPGSummoner::UpdateZoneLEDs(int /*zone*/) +{ + DeviceUpdateLEDs(); +} + +/*---------------------------------------------------------*\ +| UpdateSingleLED: Updates a single LED | +\*---------------------------------------------------------*/ +void RGBController_XPGSummoner::UpdateSingleLED(int /*led*/) +{ + DeviceUpdateLEDs(); +} + +/*---------------------------------------------------------*\ +| DeviceUpdateMode: Updates device mode | +\*---------------------------------------------------------*/ +void RGBController_XPGSummoner::DeviceUpdateMode() +{ + DeviceUpdateLEDs(); +} + diff --git a/Controllers/XPGSummonerKeyboardController/RGBController_XPGSummoner.h b/Controllers/XPGSummonerKeyboardController/RGBController_XPGSummoner.h new file mode 100644 index 00000000..8bd3b867 --- /dev/null +++ b/Controllers/XPGSummonerKeyboardController/RGBController_XPGSummoner.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------*\ +| RGBController_XPGSummoner.h | +| | +| RGBController for XPG Summoner keyboard | +| | +| Erick Granados (eriosgamer) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "RGBController.h" +#include "XPGSummonerController.h" + +class RGBController_XPGSummoner : public RGBController +{ +public: + RGBController_XPGSummoner(XPGSummonerController* controller_ptr); + ~RGBController_XPGSummoner(); + + void SetupZones(); + void ResizeZone(int zone, int new_size); + void DeviceUpdateLEDs(); + void UpdateZoneLEDs(int zone); + void UpdateSingleLED(int led); + void DeviceUpdateMode(); + +private: + XPGSummonerController* controller; +}; diff --git a/Controllers/XPGSummonerKeyboardController/XPGSummonerController.cpp b/Controllers/XPGSummonerKeyboardController/XPGSummonerController.cpp new file mode 100644 index 00000000..8c688496 --- /dev/null +++ b/Controllers/XPGSummonerKeyboardController/XPGSummonerController.cpp @@ -0,0 +1,125 @@ +/*---------------------------------------------------------*\ +| XPGSummonerController.cpp | +| | +| Driver for XPG Summoner keyboard | +| | +| Erick Granados (eriosgamer) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "XPGSummonerController.h" +#include "StringUtils.h" + +XPGSummonerController::XPGSummonerController(hid_device *dev_handle, const char *path, const unsigned short pid, std::string dev_name) +{ + dev = dev_handle; + location = path; + name = dev_name; + usb_pid = pid; + + SendInitialize(); +} + +XPGSummonerController::~XPGSummonerController() +{ + hid_close(dev); +} + +void XPGSummonerController::SendInitialize() +{ + unsigned char init_buf[265] = + { + 0x07, 0xEA, 0x00, 0x00, + }; + memset(init_buf + 4, 0x00, 261); + hid_write(dev, init_buf, 265); + std::this_thread::sleep_for(std::chrono::milliseconds(2)); +} + +std::string XPGSummonerController::GetLocationString() +{ + return("HID: " + location); +} + +std::string XPGSummonerController::GetNameString() +{ + return(name); +} + +std::string XPGSummonerController::GetSerialString() +{ + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); +} + +unsigned short XPGSummonerController::GetUSBPID() +{ + return(usb_pid); +} + +void XPGSummonerController::SendColors(unsigned char *color_data, unsigned int color_data_size) +{ + const int leds_count = 126; + const int bytes_per_led = 4; + const int total_bytes = leds_count * bytes_per_led; + const int block_size = 256; + int zones = 2; + + for(int zone = 0; zone < zones; zone++) + { + int offset = zone * block_size; + int remaining = total_bytes - offset; + color_data_size = (remaining > block_size) ? block_size : remaining; + + SendColorDataPacket(zone, &color_data[offset], color_data_size); + } +} + +unsigned int XPGSummonerController::SendColorDataPacket( + unsigned char packet_id, + unsigned char *color_data, + unsigned int color_size) +{ + unsigned char packet[265] = {0}; + packet[0] = 0x07; + packet[1] = 0xA3; + packet[2] = 0x08; + packet[3] = 0x00; + packet[4] = packet_id; + packet[5] = 0x00; + + unsigned int copy_size = (color_size > 256) ? 256 : color_size; + memcpy(&packet[6], color_data, copy_size); + + hid_write(dev, packet, 265); + + std::this_thread::sleep_for(std::chrono::milliseconds(2)); + return copy_size; +} + +void XPGSummonerController::SendTerminateColorPacket() +{ + /*-------------------------------*\ + | Set up Terminate Color packet | + | This packet is used to stop | + | any active color effects on the | + | keyboard. | + \*-------------------------------*/ + unsigned char terminate_buf[265] = + { + 0x07, 0xEA, 0x00, 0x00, + }; + memset(terminate_buf + 4, 0x00, 261); + hid_write(dev, terminate_buf, 265); + std::this_thread::sleep_for(std::chrono::milliseconds(2)); +} diff --git a/Controllers/XPGSummonerKeyboardController/XPGSummonerController.h b/Controllers/XPGSummonerKeyboardController/XPGSummonerController.h new file mode 100644 index 00000000..70d224ca --- /dev/null +++ b/Controllers/XPGSummonerKeyboardController/XPGSummonerController.h @@ -0,0 +1,69 @@ +/*---------------------------------------------------------*\ +| XPGSummonerController.h | +| | +| Driver for XPG Summoner keyboard | +| | +| Erick Granados (eriosgamer) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "hidapi.h" +#include "RGBController.h" + +/*-----------------------------------------------------*\ +| XPG vendor ID | +\*-----------------------------------------------------*/ +#define XPG_VID 0x125F + +/*-----------------------------------------------------*\ +| Keyboard product ID | +\*-----------------------------------------------------*/ +#define XPG_SUMMONER_PID 0x9418 + +enum +{ + XPG_SUMMONER_MODE_OFF = 0x00, + XPG_SUMMONER_MODE_DIRECT = 0x01, + XPG_SUMMONER_MODE_STATIC = 0x02, + XPG_SUMMONER_MODE_STARS = 0x03 +}; + +class XPGSummonerController +{ +public: + XPGSummonerController(hid_device *dev_handle, const char *path, const unsigned short pid, std::string dev_name); + ~XPGSummonerController(); + + std::string GetLocationString(); + std::string GetNameString(); + std::string GetSerialString(); + unsigned short GetUSBPID(); + + void SendColors + ( + unsigned char *color_data, + unsigned int color_data_size + ); + + unsigned int SendColorDataPacket + ( + unsigned char packet_id, + unsigned char *color_data, + unsigned int color_size + ); + + void SendTerminateColorPacket(); + + void SendInitialize(); + +private: + hid_device *dev; + std::string location; + std::string name; + unsigned short usb_pid; +}; diff --git a/Controllers/XPGSummonerKeyboardController/XPGSummonerControllerDetect.cpp b/Controllers/XPGSummonerKeyboardController/XPGSummonerControllerDetect.cpp new file mode 100644 index 00000000..2d81f38f --- /dev/null +++ b/Controllers/XPGSummonerKeyboardController/XPGSummonerControllerDetect.cpp @@ -0,0 +1,37 @@ +/*---------------------------------------------------------*\ +| XPGSummonerControllerDetect.cpp | +| | +| Detector for XPG Summoner keyboard | +| | +| Erick Granados (eriosgamer) | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "Detector.h" +#include "XPGSummonerController.h" +#include "RGBController_XPGSummoner.h" +#include + +/******************************************************************************************\ +* * +* DetectXPGSummonerControllers * +* * +* Tests the USB address to see if a XPG Summoner Keyboard controller exists there. * +* * +\******************************************************************************************/ + +void DetectXPGSummonerControllers(hid_device_info *info, const std::string &name) +{ + hid_device *dev = hid_open_path(info->path); + + if(dev) + { + XPGSummonerController *controller = new XPGSummonerController(dev, info->path, info->product_id, name); + RGBController_XPGSummoner *rgb_controller = new RGBController_XPGSummoner(controller); + ResourceManager::get()->RegisterRGBController(rgb_controller); + } +} /* DetectXPGSummonerControllers() */ + +REGISTER_HID_DETECTOR_IPU("XPG Summoner Gaming Keyboard", DetectXPGSummonerControllers, XPG_VID, XPG_SUMMONER_PID, 2, 0xFF01, 0x0001); diff --git a/Controllers/YeelightController/RGBController_Yeelight.cpp b/Controllers/YeelightController/RGBController_Yeelight.cpp index bdebfefa..18091fbb 100644 --- a/Controllers/YeelightController/RGBController_Yeelight.cpp +++ b/Controllers/YeelightController/RGBController_Yeelight.cpp @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_Yeelight.cpp | -| | -| Generic RGB Interface for Yeelight | -| | -| Adam Honse (CalcProgrammer1) 1/18/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Yeelight.cpp | +| | +| RGBController for Yeelight | +| | +| Adam Honse (CalcProgrammer1) 18 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_Yeelight.h" diff --git a/Controllers/YeelightController/RGBController_Yeelight.h b/Controllers/YeelightController/RGBController_Yeelight.h index e50144d6..56391702 100644 --- a/Controllers/YeelightController/RGBController_Yeelight.h +++ b/Controllers/YeelightController/RGBController_Yeelight.h @@ -1,12 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_Yeelight.h | -| | -| Generic RGB Interface for Yeelight | -| | -| Adam Honse (CalcProgrammer1) 1/18/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Yeelight.h | +| | +| RGBController for Yeelight | +| | +| Adam Honse (CalcProgrammer1) 18 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "YeelightController.h" diff --git a/Controllers/YeelightController/YeelightController.cpp b/Controllers/YeelightController/YeelightController.cpp index f330326a..e73e7f03 100644 --- a/Controllers/YeelightController/YeelightController.cpp +++ b/Controllers/YeelightController/YeelightController.cpp @@ -1,11 +1,16 @@ /*---------------------------------------------------------*\ -| Driver for Yeelight | +| YeelightController.cpp | | | -| Adam Honse (calcprogrammer1@gmail.com), 1/18/2021 | +| Driver for Yeelight | +| | +| Adam Honse (CalcProgrammer1) 18 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ #include "YeelightController.h" -#include "json.hpp" +#include using json = nlohmann::json; @@ -152,7 +157,7 @@ void YeelightController::SetMusicMode() std::string command_str = command.dump().append("\r\n"); port.tcp_client_connect(); - port.tcp_client_write((char *)command_str.c_str(), command_str.length() + 1); + port.tcp_client_write((char *)command_str.c_str(), (int)command_str.length() + 1); port.tcp_close(); } @@ -178,7 +183,7 @@ void YeelightController::SetPower() std::string command_str = command.dump().append("\r\n"); port.tcp_client_connect(); - port.tcp_client_write((char *)command_str.c_str(), command_str.length() + 1); + port.tcp_client_write((char *)command_str.c_str(), (int)command_str.length() + 1); port.tcp_close(); } @@ -235,12 +240,12 @@ void YeelightController::SetColor(unsigned char red, unsigned char green, unsign if(music_mode) { - send(*music_mode_sock, (char *)command_str.c_str(), command_str.length(), 0); + send(*music_mode_sock, (char *)command_str.c_str(), (int)command_str.length(), 0); } else { port.tcp_client_connect(); - port.tcp_client_write((char *)command_str.c_str(), command_str.length() + 1); + port.tcp_client_write((char *)command_str.c_str(), (int)command_str.length() + 1); port.tcp_close(); } } diff --git a/Controllers/YeelightController/YeelightController.h b/Controllers/YeelightController/YeelightController.h index 2de99aa8..fd91931b 100644 --- a/Controllers/YeelightController/YeelightController.h +++ b/Controllers/YeelightController/YeelightController.h @@ -1,17 +1,21 @@ /*---------------------------------------------------------*\ -| Definitions for Yeelight | +| YeelightController.h | | | -| Adam Honse (calcprogrammer1@gmail.com), 1/18/2021 | +| Driver for Yeelight | +| | +| Adam Honse (CalcProgrammer1) 18 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | \*---------------------------------------------------------*/ -#include "RGBController.h" -#include "net_port.h" +#pragma once #include #include #include - -#pragma once +#include "RGBController.h" +#include "net_port.h" class YeelightController { diff --git a/Controllers/YeelightController/YeelightControllerDetect.cpp b/Controllers/YeelightController/YeelightControllerDetect.cpp index 9dca69a6..d2f22939 100644 --- a/Controllers/YeelightController/YeelightControllerDetect.cpp +++ b/Controllers/YeelightController/YeelightControllerDetect.cpp @@ -1,11 +1,18 @@ +/*---------------------------------------------------------*\ +| YeelightControllerDetect.cpp | +| | +| Detector for Yeelight | +| | +| Adam Honse (CalcProgrammer1) 18 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "YeelightController.h" -#include "RGBController.h" #include "RGBController_Yeelight.h" #include "SettingsManager.h" -#include -#include -#include /******************************************************************************************\ * * diff --git a/Controllers/ZETEdgeAirProController/RGBController_ZETEdgeAirPro.cpp b/Controllers/ZETEdgeAirProController/RGBController_ZETEdgeAirPro.cpp index 564e9454..04c540a3 100644 --- a/Controllers/ZETEdgeAirProController/RGBController_ZETEdgeAirPro.cpp +++ b/Controllers/ZETEdgeAirProController/RGBController_ZETEdgeAirPro.cpp @@ -1,15 +1,17 @@ -/*-----------------------------------------*\ -| RGBController_ZETEdgeAirPro.cpp | -| | -| Generic RGB Interface for OpenRGB | -| ZET Edge Air Pro RGB USB Driver | -| | -| Guimard Morgan (morg) 1/29/2022 | -\*-----------------------------------------*/ -#include "RGBController_ZETEdgeAirPro.h" +/*---------------------------------------------------------*\ +| RGBController_ZETEdgeAirPro.cpp | +| | +| RGBController for ZET Edge Air Pro | +| | +| Morgan Guimard (morg) 29 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include #include +#include +#include "RGBController_ZETEdgeAirPro.h" /**------------------------------------------------------------------*\ @name ZET Edge Air Pro @@ -25,13 +27,13 @@ RGBController_ZETEdgeAirPro::RGBController_ZETEdgeAirPro(ZETEdgeAirProController* controller_ptr) { controller = controller_ptr; - name = "ZET Edge Air Pro"; + + name = controller->GetNameString(); vendor = "ZET Gaming"; type = DEVICE_TYPE_MOUSE; - description = name; + description = "ZET Edge Air Pro Device"; location = controller->GetDeviceLocation(); serial = controller->GetSerialString(); - version = controller->GetFirmwareVersion(); mode Static; Static.name = "Static"; diff --git a/Controllers/ZETEdgeAirProController/RGBController_ZETEdgeAirPro.h b/Controllers/ZETEdgeAirProController/RGBController_ZETEdgeAirPro.h index 3e1f1be9..81de4d4b 100644 --- a/Controllers/ZETEdgeAirProController/RGBController_ZETEdgeAirPro.h +++ b/Controllers/ZETEdgeAirProController/RGBController_ZETEdgeAirPro.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_ZETEdgeAirPro.h | -| | -| Generic RGB Interface for OpenRGB | -| ZET Edge Air Pro RGB USB Driver | -| | -| Guimard Morgan (morg) 1/29/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ZETEdgeAirPro.h | +| | +| RGBController for ZET Edge Air Pro | +| | +| Morgan Guimard (morg) 29 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/ZETEdgeAirProController/ZETEdgeAirProController.cpp b/Controllers/ZETEdgeAirProController/ZETEdgeAirProController.cpp index 65f7e3b8..4f0fa73b 100644 --- a/Controllers/ZETEdgeAirProController/ZETEdgeAirProController.cpp +++ b/Controllers/ZETEdgeAirProController/ZETEdgeAirProController.cpp @@ -1,32 +1,23 @@ -/*-----------------------------------------*\ -| ZETEdgeAirProController.cpp | -| | -| Driver for ZET Edge Air Pro mouse | -| lighting controller | -| | -| Guimard Morgan (morg) 1/29/2022 | -\*-----------------------------------------*/ -#include "ZETEdgeAirProController.h" -#include +/*---------------------------------------------------------*\ +| ZETEdgeAirProController.cpp | +| | +| Driver for ZET Edge Air Pro | +| | +| Morgan Guimard (morg) 29 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -ZETEdgeAirProController::ZETEdgeAirProController(hid_device* dev_handle, const hid_device_info& info) +#include +#include "StringUtils.h" +#include "ZETEdgeAirProController.h" + +ZETEdgeAirProController::ZETEdgeAirProController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name) { dev = dev_handle; location = info.path; - version = ""; - - wchar_t serial_string[128]; - int ret = hid_get_serial_number_string(dev, serial_string, 128); - - if(ret != 0) - { - serial_number = ""; - } - else - { - std::wstring return_wstring = serial_string; - serial_number = std::string(return_wstring.begin(), return_wstring.end()); - } + name = dev_name; } ZETEdgeAirProController::~ZETEdgeAirProController() @@ -39,14 +30,22 @@ std::string ZETEdgeAirProController::GetDeviceLocation() return("HID: " + location); } -std::string ZETEdgeAirProController::GetSerialString() +std::string ZETEdgeAirProController::GetNameString() { - return(serial_number); + return(name); } -std::string ZETEdgeAirProController::GetFirmwareVersion() +std::string ZETEdgeAirProController::GetSerialString() { - return(version); + wchar_t serial_string[128]; + int ret = hid_get_serial_number_string(dev, serial_string, 128); + + if(ret != 0) + { + return(""); + } + + return(StringUtils::wstring_to_string(serial_string)); } void ZETEdgeAirProController::SetMode(RGBColor color, unsigned char brightness, unsigned char speed, unsigned char mode_value) diff --git a/Controllers/ZETEdgeAirProController/ZETEdgeAirProController.h b/Controllers/ZETEdgeAirProController/ZETEdgeAirProController.h index f45e0ce7..c7182063 100644 --- a/Controllers/ZETEdgeAirProController/ZETEdgeAirProController.h +++ b/Controllers/ZETEdgeAirProController/ZETEdgeAirProController.h @@ -1,16 +1,19 @@ -/*-----------------------------------------*\ -| ZETEdgeAirProController.h | -| | -| Driver for ZET Edge Air Pro mouse | -| lighting controller - header file | -| | -| Guimard Morgan (morg) 1/29/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| ZETEdgeAirProController.h | +| | +| Driver for ZET Edge Air Pro | +| | +| Morgan Guimard (morg) 29 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once -#include "RGBController.h" #include -#include +#include +#include "RGBController.h" #define ZET_EDGE_AIR_PRO_PACKET_SIZE 17 #define ZET_EDGE_AIR_PRO_REPORT_ID 0x08 @@ -35,12 +38,12 @@ enum class ZETEdgeAirProController { public: - ZETEdgeAirProController(hid_device* dev_handle, const hid_device_info& info); + ZETEdgeAirProController(hid_device* dev_handle, const hid_device_info& info, std::string dev_name); ~ZETEdgeAirProController(); - std::string GetSerialString(); std::string GetDeviceLocation(); - std::string GetFirmwareVersion(); + std::string GetNameString(); + std::string GetSerialString(); void SetMode(RGBColor color, unsigned char brightness, unsigned char speed, unsigned char mode_value); @@ -49,6 +52,5 @@ protected: private: std::string location; - std::string serial_number; - std::string version; + std::string name; }; diff --git a/Controllers/ZETEdgeAirProController/ZETEdgeAirProControllerDetect.cpp b/Controllers/ZETEdgeAirProController/ZETEdgeAirProControllerDetect.cpp index c0f217dd..7e297856 100644 --- a/Controllers/ZETEdgeAirProController/ZETEdgeAirProControllerDetect.cpp +++ b/Controllers/ZETEdgeAirProController/ZETEdgeAirProControllerDetect.cpp @@ -1,6 +1,16 @@ +/*---------------------------------------------------------*\ +| ZETEdgeAirProControllerDetect.cpp | +| | +| Detector for ZET Edge Air Pro | +| | +| Morgan Guimard (morg) 29 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "ZETEdgeAirProController.h" -#include "RGBController.h" #include "RGBController_ZETEdgeAirPro.h" /*---------------------------------------------------------*\ @@ -22,15 +32,14 @@ void DetectZETGAMINGEdgeAirProControllers(hid_device_info* info, const std::stri if(dev) { - ZETEdgeAirProController* controller = new ZETEdgeAirProController(dev, *info); + ZETEdgeAirProController* controller = new ZETEdgeAirProController(dev, *info, name); RGBController_ZETEdgeAirPro* rgb_controller = new RGBController_ZETEdgeAirPro(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } -REGISTER_HID_DETECTOR_IPU("ZET GAMING Edge Air Pro (Wireless)", DetectZETGAMINGEdgeAirProControllers, ZET_GAMING_VID, ZET_GAMING_EDGE_AIR_PRO_WIRELESS_PID, 1, 0xFF02, 2); -REGISTER_HID_DETECTOR_IPU("ZET GAMING Edge Air Pro", DetectZETGAMINGEdgeAirProControllers, ZET_GAMING_VID, ZET_GAMING_EDGE_AIR_PRO_PID, 1, 0xFF02, 2); -REGISTER_HID_DETECTOR_IPU("ZET GAMING Edge Air Elit (Wireless)", DetectZETGAMINGEdgeAirProControllers, ZET_GAMING_VID, ZET_GAMING_EDGE_AIR_ELIT_WIRELESS_PID, 1, 0xFF02, 2); -REGISTER_HID_DETECTOR_IPU("ZET GAMING Edge Air Elit", DetectZETGAMINGEdgeAirProControllers, ZET_GAMING_VID, ZET_GAMING_EDGE_AIR_ELIT_PID, 1, 0xFF02, 2); +REGISTER_HID_DETECTOR_IPU("ZET GAMING Edge Air Pro (Wireless)", DetectZETGAMINGEdgeAirProControllers, ZET_GAMING_VID, ZET_GAMING_EDGE_AIR_PRO_WIRELESS_PID, 1, 0xFF02, 2); +REGISTER_HID_DETECTOR_IPU("ZET GAMING Edge Air Pro", DetectZETGAMINGEdgeAirProControllers, ZET_GAMING_VID, ZET_GAMING_EDGE_AIR_PRO_PID, 1, 0xFF02, 2); +REGISTER_HID_DETECTOR_IPU("ZET GAMING Edge Air Elit (Wireless)", DetectZETGAMINGEdgeAirProControllers, ZET_GAMING_VID, ZET_GAMING_EDGE_AIR_ELIT_WIRELESS_PID, 1, 0xFF02, 2); +REGISTER_HID_DETECTOR_IPU("ZET GAMING Edge Air Elit", DetectZETGAMINGEdgeAirProControllers, ZET_GAMING_VID, ZET_GAMING_EDGE_AIR_ELIT_PID, 1, 0xFF02, 2); diff --git a/Controllers/ZETKeyboardController/RGBController_ZETBladeOptical.cpp b/Controllers/ZETKeyboardController/RGBController_ZETBladeOptical.cpp index 9417e3d9..7302ebf9 100644 --- a/Controllers/ZETKeyboardController/RGBController_ZETBladeOptical.cpp +++ b/Controllers/ZETKeyboardController/RGBController_ZETBladeOptical.cpp @@ -1,14 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_ZETBladeOptical.cpp | -| | -| Generic RGB Interface for ZET Blade | -| Optical Keyboard | -| | -| Based on HyperX Alloy Elite2 impl by | -| KundaPanda | -| | -| Moon_darker (Vaker) 23/01/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ZETBladeOptical.cpp | +| | +| RGBController for ZET Blade | +| | +| Based on HyperX Alloy Elite2 implementation by | +| KundaPanda | +| | +| Moon_darker (Vaker) 23 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" #include "RGBController_ZETBladeOptical.h" @@ -183,246 +185,246 @@ static const char *led_names[] = RGBController_ZETBladeOptical::RGBController_ZETBladeOptical(ZETBladeOpticalController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "ZET Blade Optical Keyboard Device"; - vendor = "ZET"; - type = DEVICE_TYPE_KEYBOARD; - description = "ZET Blade Optical Keyboard Device"; - location = controller->GetDeviceLocation(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "ZET"; + type = DEVICE_TYPE_KEYBOARD; + description = "ZET Blade Optical Keyboard Device"; + location = controller->GetDeviceLocation(); + serial = controller->GetSerialString(); mode Custom; - Custom.name = "Custom"; - Custom.value = ZET_BLADE_OPTICAL_MODE_CUSTOM; - Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Custom.color_mode = MODE_COLORS_PER_LED; - Custom.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; - Custom.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; - Custom.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + Custom.name = "Custom"; + Custom.value = ZET_BLADE_OPTICAL_MODE_CUSTOM; + Custom.flags = MODE_FLAG_HAS_PER_LED_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Custom.color_mode = MODE_COLORS_PER_LED; + Custom.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; + Custom.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; + Custom.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; modes.push_back(Custom); mode Static; - Static.name = "Static"; - Static.value = ZET_BLADE_OPTICAL_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; - Static.colors_min = 1; - Static.colors_max = 1; + Static.name = "Static"; + Static.value = ZET_BLADE_OPTICAL_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.colors_min = 1; + Static.colors_max = 1; Static.colors.resize(Static.colors_max); - Static.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; - Static.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; - Static.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; - Static.speed = ZET_BLADE_OPTICAL_SPEED_DEF; + Static.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; + Static.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; + Static.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + Static.speed = ZET_BLADE_OPTICAL_SPEED_DEF; modes.push_back(Static); mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = ZET_BLADE_OPTICAL_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Breathing.color_mode = MODE_COLORS_RANDOM; - Breathing.colors_min = 1; - Breathing.colors_max = 1; + Breathing.name = "Breathing"; + Breathing.value = ZET_BLADE_OPTICAL_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Breathing.color_mode = MODE_COLORS_RANDOM; + Breathing.colors_min = 1; + Breathing.colors_max = 1; Breathing.colors.resize(Breathing.colors_max); - Breathing.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; - Breathing.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; - Breathing.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; - Breathing.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; - Breathing.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; - Breathing.speed = ZET_BLADE_OPTICAL_SPEED_DEF; + Breathing.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; + Breathing.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; + Breathing.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + Breathing.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; + Breathing.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; + Breathing.speed = ZET_BLADE_OPTICAL_SPEED_DEF; modes.push_back(Breathing); mode OnPress; - OnPress.name = "Reactive"; - OnPress.value = ZET_BLADE_OPTICAL_MODE_ON_PRESS; - OnPress.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - OnPress.color_mode = MODE_COLORS_RANDOM; - OnPress.colors_min = 1; - OnPress.colors_max = 1; + OnPress.name = "Reactive"; + OnPress.value = ZET_BLADE_OPTICAL_MODE_ON_PRESS; + OnPress.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + OnPress.color_mode = MODE_COLORS_RANDOM; + OnPress.colors_min = 1; + OnPress.colors_max = 1; OnPress.colors.resize(OnPress.colors_max); - OnPress.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; - OnPress.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; - OnPress.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; - OnPress.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; - OnPress.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; - OnPress.speed = ZET_BLADE_OPTICAL_SPEED_DEF; + OnPress.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; + OnPress.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; + OnPress.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + OnPress.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; + OnPress.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; + OnPress.speed = ZET_BLADE_OPTICAL_SPEED_DEF; modes.push_back(OnPress); mode Raindrop; - Raindrop.name = "Reactive Raindrop"; - Raindrop.value = ZET_BLADE_OPTICAL_MODE_RAINDROP; - Raindrop.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Raindrop.color_mode = MODE_COLORS_RANDOM; - Raindrop.colors_min = 1; - Raindrop.colors_max = 1; + Raindrop.name = "Reactive Raindrop"; + Raindrop.value = ZET_BLADE_OPTICAL_MODE_RAINDROP; + Raindrop.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Raindrop.color_mode = MODE_COLORS_RANDOM; + Raindrop.colors_min = 1; + Raindrop.colors_max = 1; Raindrop.colors.resize(Raindrop.colors_max); - Raindrop.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; - Raindrop.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; - Raindrop.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; - Raindrop.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; - Raindrop.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; - Raindrop.speed = ZET_BLADE_OPTICAL_SPEED_DEF; + Raindrop.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; + Raindrop.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; + Raindrop.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + Raindrop.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; + Raindrop.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; + Raindrop.speed = ZET_BLADE_OPTICAL_SPEED_DEF; modes.push_back(Raindrop); mode Ripple; - Ripple.name = "Reactive Ripple"; - Ripple.value = ZET_BLADE_OPTICAL_MODE_RIPPLE; - Ripple.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Ripple.color_mode = MODE_COLORS_RANDOM; - Ripple.colors_min = 1; - Ripple.colors_max = 1; + Ripple.name = "Reactive Ripple"; + Ripple.value = ZET_BLADE_OPTICAL_MODE_RIPPLE; + Ripple.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Ripple.color_mode = MODE_COLORS_RANDOM; + Ripple.colors_min = 1; + Ripple.colors_max = 1; Ripple.colors.resize(Ripple.colors_max); - Ripple.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; - Ripple.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; - Ripple.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; - Ripple.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; - Ripple.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; - Ripple.speed = ZET_BLADE_OPTICAL_SPEED_DEF; + Ripple.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; + Ripple.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; + Ripple.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + Ripple.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; + Ripple.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; + Ripple.speed = ZET_BLADE_OPTICAL_SPEED_DEF; modes.push_back(Ripple); mode Laser; - Laser.name = "Reactive Laser"; - Laser.value = ZET_BLADE_OPTICAL_MODE_LASER; - Laser.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Laser.color_mode = MODE_COLORS_RANDOM; - Laser.colors_min = 1; - Laser.colors_max = 1; + Laser.name = "Reactive Laser"; + Laser.value = ZET_BLADE_OPTICAL_MODE_LASER; + Laser.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Laser.color_mode = MODE_COLORS_RANDOM; + Laser.colors_min = 1; + Laser.colors_max = 1; Laser.colors.resize(Laser.colors_max); - Laser.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; - Laser.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; - Laser.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; - Laser.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; - Laser.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; - Laser.speed = ZET_BLADE_OPTICAL_SPEED_DEF; + Laser.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; + Laser.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; + Laser.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + Laser.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; + Laser.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; + Laser.speed = ZET_BLADE_OPTICAL_SPEED_DEF; modes.push_back(Laser); mode Waves; - Waves.name = "Waves"; - Waves.value = ZET_BLADE_OPTICAL_MODE_WAVES; - Waves.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Waves.color_mode = MODE_COLORS_RANDOM; - Waves.colors_min = 1; - Waves.colors_max = 1; + Waves.name = "Waves"; + Waves.value = ZET_BLADE_OPTICAL_MODE_WAVES; + Waves.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Waves.color_mode = MODE_COLORS_RANDOM; + Waves.colors_min = 1; + Waves.colors_max = 1; Waves.colors.resize(Waves.colors_max); - Waves.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; - Waves.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; - Waves.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; - Waves.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; - Waves.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; - Waves.speed = ZET_BLADE_OPTICAL_SPEED_DEF; + Waves.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; + Waves.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; + Waves.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + Waves.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; + Waves.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; + Waves.speed = ZET_BLADE_OPTICAL_SPEED_DEF; modes.push_back(Waves); mode Rain; - Rain.name = "Rain"; - Rain.value = ZET_BLADE_OPTICAL_MODE_RAIN; - Rain.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Rain.color_mode = MODE_COLORS_NONE; - Rain.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; - Rain.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; - Rain.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; - Rain.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; - Rain.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; - Rain.speed = ZET_BLADE_OPTICAL_SPEED_DEF; + Rain.name = "Rain"; + Rain.value = ZET_BLADE_OPTICAL_MODE_RAIN; + Rain.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Rain.color_mode = MODE_COLORS_NONE; + Rain.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; + Rain.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; + Rain.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + Rain.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; + Rain.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; + Rain.speed = ZET_BLADE_OPTICAL_SPEED_DEF; modes.push_back(Rain); mode Spectrum; - Spectrum.name = "Spectrum Cycle"; - Spectrum.value = ZET_BLADE_OPTICAL_MODE_SPECTRUM; - Spectrum.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Spectrum.color_mode = MODE_COLORS_NONE; - Spectrum.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; - Spectrum.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; - Spectrum.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; - Spectrum.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; - Spectrum.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; - Spectrum.speed = ZET_BLADE_OPTICAL_SPEED_DEF; + Spectrum.name = "Spectrum Cycle"; + Spectrum.value = ZET_BLADE_OPTICAL_MODE_SPECTRUM; + Spectrum.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Spectrum.color_mode = MODE_COLORS_NONE; + Spectrum.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; + Spectrum.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; + Spectrum.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + Spectrum.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; + Spectrum.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; + Spectrum.speed = ZET_BLADE_OPTICAL_SPEED_DEF; modes.push_back(Spectrum); mode SurfingRight; // Now, you might be thinking... it'd be better to use .direction here, right? WRONG! There is no Surfing Left /._. - SurfingRight.name = "Rainbow Wave"; - SurfingRight.value = ZET_BLADE_OPTICAL_MODE_SURFING_RIGHT; - SurfingRight.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - SurfingRight.color_mode = MODE_COLORS_NONE; - SurfingRight.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; - SurfingRight.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; - SurfingRight.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; - SurfingRight.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; - SurfingRight.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; - SurfingRight.speed = ZET_BLADE_OPTICAL_SPEED_DEF; + SurfingRight.name = "Rainbow Wave"; + SurfingRight.value = ZET_BLADE_OPTICAL_MODE_SURFING_RIGHT; + SurfingRight.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + SurfingRight.color_mode = MODE_COLORS_NONE; + SurfingRight.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; + SurfingRight.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; + SurfingRight.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + SurfingRight.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; + SurfingRight.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; + SurfingRight.speed = ZET_BLADE_OPTICAL_SPEED_DEF; modes.push_back(SurfingRight); mode SurfingCenter; - SurfingCenter.name = "Rainbow Wave Center"; - SurfingCenter.value = ZET_BLADE_OPTICAL_MODE_SURFING_CENTER; - SurfingCenter.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - SurfingCenter.color_mode = MODE_COLORS_NONE; - SurfingCenter.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; - SurfingCenter.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; - SurfingCenter.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; - SurfingCenter.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; - SurfingCenter.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; - SurfingCenter.speed = ZET_BLADE_OPTICAL_SPEED_DEF; + SurfingCenter.name = "Rainbow Wave Center"; + SurfingCenter.value = ZET_BLADE_OPTICAL_MODE_SURFING_CENTER; + SurfingCenter.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + SurfingCenter.color_mode = MODE_COLORS_NONE; + SurfingCenter.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; + SurfingCenter.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; + SurfingCenter.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + SurfingCenter.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; + SurfingCenter.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; + SurfingCenter.speed = ZET_BLADE_OPTICAL_SPEED_DEF; modes.push_back(SurfingCenter); mode SurfingCross; - SurfingCross.name = "Rainbow Wave Cross"; - SurfingCross.value = ZET_BLADE_OPTICAL_MODE_SURFING_CROSS; - SurfingCross.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - SurfingCross.color_mode = MODE_COLORS_NONE; - SurfingCross.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; - SurfingCross.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; - SurfingCross.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; - SurfingCross.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; - SurfingCross.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; - SurfingCross.speed = ZET_BLADE_OPTICAL_SPEED_DEF; + SurfingCross.name = "Rainbow Wave Cross"; + SurfingCross.value = ZET_BLADE_OPTICAL_MODE_SURFING_CROSS; + SurfingCross.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + SurfingCross.color_mode = MODE_COLORS_NONE; + SurfingCross.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; + SurfingCross.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; + SurfingCross.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + SurfingCross.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; + SurfingCross.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; + SurfingCross.speed = ZET_BLADE_OPTICAL_SPEED_DEF; modes.push_back(SurfingCross); mode RotateMarquee; - RotateMarquee.name = "Vortex"; - RotateMarquee.value = ZET_BLADE_OPTICAL_MODE_ROTATE_MARQUEE; - RotateMarquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - RotateMarquee.color_mode = MODE_COLORS_NONE; - RotateMarquee.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; - RotateMarquee.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; - RotateMarquee.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; - RotateMarquee.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; - RotateMarquee.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; - RotateMarquee.speed = ZET_BLADE_OPTICAL_SPEED_DEF; + RotateMarquee.name = "Vortex"; + RotateMarquee.value = ZET_BLADE_OPTICAL_MODE_ROTATE_MARQUEE; + RotateMarquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + RotateMarquee.color_mode = MODE_COLORS_NONE; + RotateMarquee.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; + RotateMarquee.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; + RotateMarquee.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + RotateMarquee.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; + RotateMarquee.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; + RotateMarquee.speed = ZET_BLADE_OPTICAL_SPEED_DEF; modes.push_back(RotateMarquee); mode Traffic; - Traffic.name = "Traffic"; - Traffic.value = ZET_BLADE_OPTICAL_MODE_TRAFFIC; - Traffic.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Traffic.color_mode = MODE_COLORS_NONE; - Traffic.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; - Traffic.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; - Traffic.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; - Traffic.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; - Traffic.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; - Traffic.speed = ZET_BLADE_OPTICAL_SPEED_DEF; + Traffic.name = "Traffic"; + Traffic.value = ZET_BLADE_OPTICAL_MODE_TRAFFIC; + Traffic.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Traffic.color_mode = MODE_COLORS_NONE; + Traffic.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; + Traffic.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; + Traffic.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + Traffic.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; + Traffic.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; + Traffic.speed = ZET_BLADE_OPTICAL_SPEED_DEF; modes.push_back(Traffic); mode Gradient; - Gradient.name = "Gradient"; - Gradient.value = ZET_BLADE_OPTICAL_MODE_GRADIENT; - Gradient.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; - Gradient.color_mode = MODE_COLORS_NONE; - Gradient.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; - Gradient.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; - Gradient.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; - Gradient.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; - Gradient.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; - Gradient.speed = ZET_BLADE_OPTICAL_SPEED_DEF; + Gradient.name = "Gradient"; + Gradient.value = ZET_BLADE_OPTICAL_MODE_GRADIENT; + Gradient.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_AUTOMATIC_SAVE; + Gradient.color_mode = MODE_COLORS_NONE; + Gradient.brightness_min = ZET_BLADE_OPTICAL_BRIGHTNESS_MIN; + Gradient.brightness_max = ZET_BLADE_OPTICAL_BRIGHTNESS_MAX; + Gradient.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + Gradient.speed_min = ZET_BLADE_OPTICAL_SPEED_MIN; + Gradient.speed_max = ZET_BLADE_OPTICAL_SPEED_MAX; + Gradient.speed = ZET_BLADE_OPTICAL_SPEED_DEF; modes.push_back(Gradient); mode Off; - Off.name = "Off"; - Off.value = ZET_BLADE_OPTICAL_MODE_OFF; - Off.flags = MODE_FLAG_AUTOMATIC_SAVE; - Off.color_mode = MODE_COLORS_NONE; - Off.speed = ZET_BLADE_OPTICAL_SPEED_DEF; - Off.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; + Off.name = "Off"; + Off.value = ZET_BLADE_OPTICAL_MODE_OFF; + Off.flags = MODE_FLAG_AUTOMATIC_SAVE; + Off.color_mode = MODE_COLORS_NONE; + Off.speed = ZET_BLADE_OPTICAL_SPEED_DEF; + Off.brightness = ZET_BLADE_OPTICAL_BRIGHTNESS_DEF; modes.push_back(Off); SetupZones(); diff --git a/Controllers/ZETKeyboardController/RGBController_ZETBladeOptical.h b/Controllers/ZETKeyboardController/RGBController_ZETBladeOptical.h index 03171c8f..427c5fa1 100644 --- a/Controllers/ZETKeyboardController/RGBController_ZETBladeOptical.h +++ b/Controllers/ZETKeyboardController/RGBController_ZETBladeOptical.h @@ -1,20 +1,22 @@ -/*-----------------------------------------*\ -| RGBController_ZETBladeOptical.cpp | -| | -| Generic RGB Interface for ZET Blade | -| Optical Keyboard | -| | -| Based on HyperX Alloy Elite2 impl by | -| KundaPanda | -| | -| Moon_darker (Vaker) 23/01/2022 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ZETBladeOptical.h | +| | +| RGBController for ZET Blade | +| | +| Based on HyperX Alloy Elite2 implementation by | +| KundaPanda | +| | +| Moon_darker (Vaker) 23 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include #include #include - #include "RGBController.h" #include "ZETBladeOpticalController.h" diff --git a/Controllers/ZETKeyboardController/ZETBladeOpticalController.cpp b/Controllers/ZETKeyboardController/ZETBladeOpticalController.cpp index c8620386..b1f715ad 100644 --- a/Controllers/ZETKeyboardController/ZETBladeOpticalController.cpp +++ b/Controllers/ZETKeyboardController/ZETBladeOpticalController.cpp @@ -1,18 +1,20 @@ -/*-----------------------------------------*\ -| ZETBladeOpticalController.cpp | -| | -| Driver for ZET Blade Optical Keyboard | -| | -| Based on HyperX Alloy Elite2 impl by | -| KundaPanda | -| | -| Moon_darker (Vaker) 23/01/2022 | -\*-----------------------------------------*/ - -#include "ZETBladeOpticalController.h" +/*---------------------------------------------------------*\ +| ZETBladeOpticalController.cpp | +| | +| Driver for ZET Blade | +| | +| Based on HyperX Alloy Elite2 implementation by | +| KundaPanda | +| | +| Moon_darker (Vaker) 23 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include -#include "dependencies/dmiinfo.h" +#include "StringUtils.h" +#include "ZETBladeOpticalController.h" using namespace std::chrono_literals; @@ -25,10 +27,11 @@ using namespace std::chrono_literals; static const unsigned int SKIP_INDICES[] = { 1, 17, 18, 19, 20, 75, 77, 78, 79, 83, 85, 96, 98, 100, 108, 109, 111, 112, 113, 116, 123, 125 }; -ZETBladeOpticalController::ZETBladeOpticalController(hid_device* dev_handle, const char* path) +ZETBladeOpticalController::ZETBladeOpticalController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; effect_mode = ZET_BLADE_OPTICAL_MODE_STATIC; } @@ -43,20 +46,22 @@ std::string ZETBladeOpticalController::GetDeviceLocation() return("HID " + location); } +std::string ZETBladeOpticalController::GetNameString() +{ + return(name); +} + std::string ZETBladeOpticalController::GetSerialString() { wchar_t serial_string[128]; int ret = hid_get_serial_number_string(dev, serial_string, 128); - if (ret != 0) + if(ret != 0) { return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void ZETBladeOpticalController::PrepareHeader(unsigned char* packet, unsigned char brightness) @@ -126,7 +131,7 @@ void ZETBladeOpticalController::SetLEDDirect(const std::vector& colors | Packets have colors in groups of 4 bytes, with | | the first byte being key id and then R, G, B. | \*-------------------------------------------------*/ - buf[buf_idx] = color_idx + skipped + ZET_BLADE_OPTICAL_KEY_OFFSET; + buf[buf_idx] = (unsigned char)(color_idx + skipped + ZET_BLADE_OPTICAL_KEY_OFFSET); buf[buf_idx + 1] = RGBGetRValue(colors[color_idx]); buf[buf_idx + 2] = RGBGetGValue(colors[color_idx]); buf[buf_idx + 3] = RGBGetBValue(colors[color_idx]); diff --git a/Controllers/ZETKeyboardController/ZETBladeOpticalController.h b/Controllers/ZETKeyboardController/ZETBladeOpticalController.h index c4743d9a..b1d49a17 100644 --- a/Controllers/ZETKeyboardController/ZETBladeOpticalController.h +++ b/Controllers/ZETKeyboardController/ZETBladeOpticalController.h @@ -1,21 +1,23 @@ -/*-----------------------------------------*\ -| ZETBladeOpticalController.h | -| | -| Definitions and types for ZET Blade | -| Optical Keyboard lighting controller | -| | -| Based on HyperX Alloy Elite2 impl by | -| KundaPanda | -| | -| Moon_darker (Vaker) 23/01/2022 | -\*-----------------------------------------*/ -#include "RGBController.h" - -#include -#include +/*---------------------------------------------------------*\ +| ZETBladeOpticalController.h | +| | +| Driver for ZET Blade | +| | +| Based on HyperX Alloy Elite2 implementation by | +| KundaPanda | +| | +| Moon_darker (Vaker) 23 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include "RGBController.h" + #define ZET_BLADE_OPTICAL_DELAY 12ms #define ZET_BLADE_OPTICAL_HEADER_LEN 9 #define ZET_BLADE_OPTICAL_COLOR_LEN 4 @@ -49,10 +51,11 @@ class ZETBladeOpticalController { public: - ZETBladeOpticalController(hid_device* dev_handle, const char* path); + ZETBladeOpticalController(hid_device* dev_handle, const char* path, std::string dev_name); ~ZETBladeOpticalController(); std::string GetDeviceLocation(); + std::string GetNameString(); std::string GetSerialString(); void SetLEDDirect(const std::vector& colors, unsigned char brightness); @@ -61,8 +64,10 @@ public: private: hid_device* dev; std::string location; + std::string name; unsigned int effect_mode; bool custom_mode; + void PrepareHeader(unsigned char *packet, unsigned char brightness); void PrepareHeader(unsigned char *packet, unsigned char mode, unsigned char speed, unsigned char brightness, unsigned char color); unsigned char RGBToPalette(unsigned char red, unsigned char grn, unsigned char blu); diff --git a/Controllers/ZETKeyboardController/ZETKeyboardControllerDetect.cpp b/Controllers/ZETKeyboardController/ZETKeyboardControllerDetect.cpp index 2abc2a0d..177dc2d0 100644 --- a/Controllers/ZETKeyboardController/ZETKeyboardControllerDetect.cpp +++ b/Controllers/ZETKeyboardController/ZETKeyboardControllerDetect.cpp @@ -1,8 +1,21 @@ +/*---------------------------------------------------------*\ +| ZETKeyboardControllerDetect.cpp | +| | +| Detector for ZET Blade | +| | +| Based on HyperX Alloy Elite2 implementation by | +| KundaPanda | +| | +| Moon_darker (Vaker) 23 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "ZETBladeOpticalController.h" -#include "RGBController.h" #include "RGBController_ZETBladeOptical.h" -#include /*-----------------------------------------------------*\ | ZET keyboard VID/PID pairs | @@ -16,9 +29,8 @@ void DetectZETBladeOptical(hid_device_info* info, const std::string& name) if (dev) { - ZETBladeOpticalController* controller = new ZETBladeOpticalController(dev, info->path); + ZETBladeOpticalController* controller = new ZETBladeOpticalController(dev, info->path, name); RGBController_ZETBladeOptical* rgb_controller = new RGBController_ZETBladeOptical(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } diff --git a/Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.cpp b/Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.cpp index 2d8a2879..f37b5259 100644 --- a/Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.cpp +++ b/Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_ZalmanZSync.cpp | -| | -| Generic RGB Interface for Zalman Z Sync | -| lighting devices | -| | -| Adam Honse (CalcProgrammer1) 1/30/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ZalmanZSync.cpp | +| | +| RGBController for Zalman Z Sync | +| | +| Adam Honse (CalcProgrammer1) 30 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_ZalmanZSync.h" @@ -22,156 +24,156 @@ RGBController_ZalmanZSync::RGBController_ZalmanZSync(ZalmanZSyncController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "Zalman Z Sync Device"; - vendor = "Zalman"; - description = "Zalman Z Sync Device"; - type = DEVICE_TYPE_LEDSTRIP; - version = controller->GetFirmwareString(); - location = controller->GetLocationString(); - serial = controller->GetSerialString(); + name = controller->GetNameString(); + vendor = "Zalman"; + description = "Zalman Z Sync Device"; + type = DEVICE_TYPE_LEDSTRIP; + version = controller->GetFirmwareString(); + location = controller->GetLocationString(); + serial = controller->GetSerialString(); mode Direct; - Direct.name = "Direct"; - Direct.value = 0xFFFF; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = 0xFFFF; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); mode RainbowWave; - RainbowWave.name = "Rainbow Wave"; - RainbowWave.value = ZALMAN_Z_SYNC_MODE_RAINBOW_WAVE; - RainbowWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; - RainbowWave.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; - RainbowWave.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; - RainbowWave.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; - RainbowWave.direction = MODE_DIRECTION_RIGHT; - RainbowWave.color_mode = MODE_COLORS_NONE; + RainbowWave.name = "Rainbow Wave"; + RainbowWave.value = ZALMAN_Z_SYNC_MODE_RAINBOW_WAVE; + RainbowWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + RainbowWave.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + RainbowWave.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + RainbowWave.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + RainbowWave.direction = MODE_DIRECTION_RIGHT; + RainbowWave.color_mode = MODE_COLORS_NONE; modes.push_back(RainbowWave); mode ColorShift; - ColorShift.name = "Color Shift"; - ColorShift.value = ZALMAN_Z_SYNC_MODE_COLOR_SHIFT; - ColorShift.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; - ColorShift.colors_min = 2; - ColorShift.colors_max = 2; - ColorShift.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; - ColorShift.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; - ColorShift.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; - ColorShift.color_mode = MODE_COLORS_MODE_SPECIFIC; + ColorShift.name = "Color Shift"; + ColorShift.value = ZALMAN_Z_SYNC_MODE_COLOR_SHIFT; + ColorShift.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + ColorShift.colors_min = 2; + ColorShift.colors_max = 2; + ColorShift.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + ColorShift.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + ColorShift.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + ColorShift.color_mode = MODE_COLORS_MODE_SPECIFIC; ColorShift.colors.resize(2); modes.push_back(ColorShift); mode ColorPulse; - ColorPulse.name = "Color Pulse"; - ColorPulse.value = ZALMAN_Z_SYNC_MODE_COLOR_PULSE; - ColorPulse.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; - ColorPulse.colors_min = 2; - ColorPulse.colors_max = 2; - ColorPulse.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; - ColorPulse.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; - ColorPulse.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; - ColorPulse.color_mode = MODE_COLORS_MODE_SPECIFIC; + ColorPulse.name = "Color Pulse"; + ColorPulse.value = ZALMAN_Z_SYNC_MODE_COLOR_PULSE; + ColorPulse.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + ColorPulse.colors_min = 2; + ColorPulse.colors_max = 2; + ColorPulse.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + ColorPulse.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + ColorPulse.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + ColorPulse.color_mode = MODE_COLORS_MODE_SPECIFIC; ColorPulse.colors.resize(2); modes.push_back(ColorPulse); mode ColorWave; - ColorWave.name = "Color Wave"; - ColorWave.value = ZALMAN_Z_SYNC_MODE_COLOR_WAVE; - ColorWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; - ColorWave.colors_min = 2; - ColorWave.colors_max = 2; - ColorWave.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; - ColorWave.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; - ColorWave.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; - ColorWave.direction = MODE_DIRECTION_RIGHT; - ColorWave.color_mode = MODE_COLORS_MODE_SPECIFIC; + ColorWave.name = "Color Wave"; + ColorWave.value = ZALMAN_Z_SYNC_MODE_COLOR_WAVE; + ColorWave.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + ColorWave.colors_min = 2; + ColorWave.colors_max = 2; + ColorWave.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + ColorWave.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + ColorWave.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + ColorWave.direction = MODE_DIRECTION_RIGHT; + ColorWave.color_mode = MODE_COLORS_MODE_SPECIFIC; ColorWave.colors.resize(2); modes.push_back(ColorWave); mode Static; - Static.name = "Static"; - Static.value = ZALMAN_Z_SYNC_MODE_STATIC; - Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Static.colors_min = 1; - Static.colors_max = 1; - Static.color_mode = MODE_COLORS_MODE_SPECIFIC; + Static.name = "Static"; + Static.value = ZALMAN_Z_SYNC_MODE_STATIC; + Static.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Static.colors_min = 1; + Static.colors_max = 1; + Static.color_mode = MODE_COLORS_MODE_SPECIFIC; Static.colors.resize(1); modes.push_back(Static); mode Temperature; - Temperature.name = "Temperature"; - Temperature.value = ZALMAN_Z_SYNC_MODE_TEMPERATURE; - Temperature.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - Temperature.colors_min = 3; - Temperature.colors_max = 3; - Temperature.color_mode = MODE_COLORS_MODE_SPECIFIC; + Temperature.name = "Temperature"; + Temperature.value = ZALMAN_Z_SYNC_MODE_TEMPERATURE; + Temperature.flags = MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + Temperature.colors_min = 3; + Temperature.colors_max = 3; + Temperature.color_mode = MODE_COLORS_MODE_SPECIFIC; Temperature.colors.resize(3); modes.push_back(Temperature); mode Visor; - Visor.name = "Visor"; - Visor.value = ZALMAN_Z_SYNC_MODE_VISOR; - Visor.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; - Visor.colors_min = 2; - Visor.colors_max = 2; - Visor.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; - Visor.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; - Visor.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; - Visor.color_mode = MODE_COLORS_MODE_SPECIFIC; + Visor.name = "Visor"; + Visor.value = ZALMAN_Z_SYNC_MODE_VISOR; + Visor.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + Visor.colors_min = 2; + Visor.colors_max = 2; + Visor.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + Visor.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + Visor.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + Visor.color_mode = MODE_COLORS_MODE_SPECIFIC; Visor.colors.resize(2); modes.push_back(Visor); mode Marquee; - Marquee.name = "Marquee"; - Marquee.value = ZALMAN_Z_SYNC_MODE_MARQUEE; - Marquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; - Marquee.colors_min = 1; - Marquee.colors_max = 1; - Marquee.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; - Marquee.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; - Marquee.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; - Marquee.direction = MODE_DIRECTION_RIGHT; - Marquee.color_mode = MODE_COLORS_MODE_SPECIFIC; + Marquee.name = "Marquee"; + Marquee.value = ZALMAN_Z_SYNC_MODE_MARQUEE; + Marquee.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + Marquee.colors_min = 1; + Marquee.colors_max = 1; + Marquee.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + Marquee.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + Marquee.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + Marquee.direction = MODE_DIRECTION_RIGHT; + Marquee.color_mode = MODE_COLORS_MODE_SPECIFIC; Marquee.colors.resize(1); modes.push_back(Marquee); mode Blink; - Blink.name = "Blink"; - Blink.value = ZALMAN_Z_SYNC_MODE_BLINK; - Blink.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; - Blink.colors_min = 2; - Blink.colors_max = 2; - Blink.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; - Blink.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; - Blink.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; - Blink.color_mode = MODE_COLORS_MODE_SPECIFIC; + Blink.name = "Blink"; + Blink.value = ZALMAN_Z_SYNC_MODE_BLINK; + Blink.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + Blink.colors_min = 2; + Blink.colors_max = 2; + Blink.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + Blink.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + Blink.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + Blink.color_mode = MODE_COLORS_MODE_SPECIFIC; Blink.colors.resize(2); modes.push_back(Blink); mode Sequential; - Sequential.name = "Sequential"; - Sequential.value = ZALMAN_Z_SYNC_MODE_SEQUENTIAL; - Sequential.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; - Sequential.colors_min = 1; - Sequential.colors_max = 1; - Sequential.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; - Sequential.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; - Sequential.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; - Sequential.direction = MODE_DIRECTION_RIGHT; - Sequential.color_mode = MODE_COLORS_MODE_SPECIFIC; + Sequential.name = "Sequential"; + Sequential.value = ZALMAN_Z_SYNC_MODE_SEQUENTIAL; + Sequential.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_RANDOM_COLOR; + Sequential.colors_min = 1; + Sequential.colors_max = 1; + Sequential.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + Sequential.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + Sequential.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + Sequential.direction = MODE_DIRECTION_RIGHT; + Sequential.color_mode = MODE_COLORS_MODE_SPECIFIC; Sequential.colors.resize(1); modes.push_back(Sequential); mode Rainbow; - Rainbow.name = "Rainbow"; - Rainbow.value = ZALMAN_Z_SYNC_MODE_RAINBOW; - Rainbow.flags = MODE_FLAG_HAS_SPEED; - Rainbow.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; - Rainbow.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; - Rainbow.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; - Rainbow.color_mode = MODE_COLORS_NONE; + Rainbow.name = "Rainbow"; + Rainbow.value = ZALMAN_Z_SYNC_MODE_RAINBOW; + Rainbow.flags = MODE_FLAG_HAS_SPEED; + Rainbow.speed_min = ZALMAN_Z_SYNC_SPEED_SLOW; + Rainbow.speed_max = ZALMAN_Z_SYNC_SPEED_FAST; + Rainbow.speed = ZALMAN_Z_SYNC_SPEED_MEDIUM; + Rainbow.color_mode = MODE_COLORS_NONE; modes.push_back(Rainbow); SetupZones(); @@ -266,7 +268,7 @@ void RGBController_ZalmanZSync::DeviceUpdateLEDs() { if(zones[zone_idx].leds_count > 0) { - controller->SetChannelLEDs(zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); + controller->SetChannelLEDs((unsigned char)zone_idx, zones[zone_idx].colors, zones[zone_idx].leds_count); } } } diff --git a/Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.h b/Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.h index 8b25426b..1c60f76c 100644 --- a/Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.h +++ b/Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.h @@ -1,13 +1,16 @@ -/*-----------------------------------------*\ -| RGBController_ZalmanZSync.h | -| | -| Generic RGB Interface for Zalman Z Sync | -| lighting devices | -| | -| Adam Honse (CalcProgrammer1) 1/30/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ZalmanZSync.h | +| | +| RGBController for Zalman Z Sync | +| | +| Adam Honse (CalcProgrammer1) 30 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once + #include "RGBController.h" #include "ZalmanZSyncController.h" diff --git a/Controllers/ZalmanZSyncController/ZalmanZSyncController.cpp b/Controllers/ZalmanZSyncController/ZalmanZSyncController.cpp index f478fbea..8f3f05bb 100644 --- a/Controllers/ZalmanZSyncController/ZalmanZSyncController.cpp +++ b/Controllers/ZalmanZSyncController/ZalmanZSyncController.cpp @@ -1,32 +1,32 @@ -/*-----------------------------------------*\ -| ZalmanZSyncController.cpp | -| | -| Definitions and types for Zalman Z Sync | -| lighting controller | -| | -| The Zalman Z Sync device uses the same | -| protocol as the Corsair Lighting Node | -| devices except supports 8 channels. | -| | -| This code copied from the | -| CorsairLightingNodeController files | -| | -| Adam Honse (CalcProgrammer1) 1/30/2021 | -\*-----------------------------------------*/ - -#include "ZalmanZSyncController.h" +/*---------------------------------------------------------*\ +| ZalmanZSyncController.cpp | +| | +| Driver for Zalman Z Sync | +| | +| Based on CorsairLightingNodeConroller, the protocol is | +| the same as the Corsair Lighting Node except with 8 | +| channels | +| | +| Adam Honse (CalcProgrammer1) 30 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include #include #include -#include +#include "StringUtils.h" +#include "ZalmanZSyncController.h" using namespace std::chrono_literals; -ZalmanZSyncController::ZalmanZSyncController(hid_device* dev_handle, const char* path) +ZalmanZSyncController::ZalmanZSyncController(hid_device* dev_handle, const char* path, std::string dev_name) { dev = dev_handle; location = path; + name = dev_name; SendFirmwareRequest(); @@ -71,6 +71,11 @@ std::string ZalmanZSyncController::GetLocationString() return("HID: " + location); } +std::string ZalmanZSyncController::GetNameString() +{ + return(name); +} + std::string ZalmanZSyncController::GetSerialString() { wchar_t serial_string[128]; @@ -81,10 +86,7 @@ std::string ZalmanZSyncController::GetSerialString() return(""); } - std::wstring return_wstring = serial_string; - std::string return_string(return_wstring.begin(), return_wstring.end()); - - return(return_string); + return(StringUtils::wstring_to_string(serial_string)); } void ZalmanZSyncController::SetChannelEffect(unsigned char channel, @@ -178,7 +180,7 @@ void ZalmanZSyncController::SetChannelLEDs(unsigned char channel, RGBColor * col { pkt_size = 50; } - + for(int color_idx = 0; color_idx < pkt_size; color_idx++) { red_color_data[color_idx] = RGBGetRValue(colors[pkt_offset + color_idx]); diff --git a/Controllers/ZalmanZSyncController/ZalmanZSyncController.h b/Controllers/ZalmanZSyncController/ZalmanZSyncController.h index 10008661..429afef9 100644 --- a/Controllers/ZalmanZSyncController/ZalmanZSyncController.h +++ b/Controllers/ZalmanZSyncController/ZalmanZSyncController.h @@ -1,26 +1,25 @@ -/*-----------------------------------------*\ -| ZalmanZSyncController.h | -| | -| Definitions and types for Zalman Z Sync | -| lighting controller | -| | -| The Zalman Z Sync device uses the same | -| protocol as the Corsair Lighting Node | -| devices except supports 8 channels. | -| | -| This code copied from the | -| CorsairLightingNodeController files | -| | -| Adam Honse (CalcProgrammer1) 1/30/2021 | -\*-----------------------------------------*/ - -#include "RGBController.h" -#include -#include -#include +/*---------------------------------------------------------*\ +| ZalmanZSyncController.h | +| | +| Driver for Zalman Z Sync | +| | +| Based on CorsairLightingNodeConroller, the protocol is | +| the same as the Corsair Lighting Node except with 8 | +| channels | +| | +| Adam Honse (CalcProgrammer1) 30 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once +#include +#include +#include +#include "RGBController.h" + enum { ZALMAN_Z_SYNC_PACKET_ID_FIRMWARE = 0x02, /* Get firmware version */ @@ -95,11 +94,12 @@ enum class ZalmanZSyncController { public: - ZalmanZSyncController(hid_device* dev_handle, const char* path); + ZalmanZSyncController(hid_device* dev_handle, const char* path, std::string dev_name); ~ZalmanZSyncController(); std::string GetFirmwareString(); std::string GetLocationString(); + std::string GetNameString(); std::string GetSerialString(); unsigned int GetStripsOnChannel(unsigned int channel); @@ -129,6 +129,7 @@ private: hid_device* dev; std::string firmware_version; std::string location; + std::string name; std::thread* keepalive_thread; std::atomic keepalive_thread_run; std::chrono::time_point last_commit_time; diff --git a/Controllers/ZalmanZSyncController/ZalmanZSyncControllerDetect.cpp b/Controllers/ZalmanZSyncController/ZalmanZSyncControllerDetect.cpp index 3075c3f7..0238a341 100644 --- a/Controllers/ZalmanZSyncController/ZalmanZSyncControllerDetect.cpp +++ b/Controllers/ZalmanZSyncController/ZalmanZSyncControllerDetect.cpp @@ -1,9 +1,18 @@ +/*---------------------------------------------------------*\ +| ZalmanZSyncControllerDetect.cpp | +| | +| Detector for Zalman Z Sync | +| | +| Adam Honse (CalcProgrammer1) 30 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "Detector.h" #include "ZalmanZSyncController.h" -#include "RGBController.h" #include "RGBController_ZalmanZSync.h" -#include -#include #define ZALMAN_VID 0x1C57 #define ZALMAN_Z_SYNC_PID 0x7ED0 @@ -22,9 +31,8 @@ void DetectZalmanZSyncControllers(hid_device_info* info, const std::string& name if(dev) { - ZalmanZSyncController* controller = new ZalmanZSyncController(dev, info->path); + ZalmanZSyncController* controller = new ZalmanZSyncController(dev, info->path, name); RGBController_ZalmanZSync* rgb_controller = new RGBController_ZalmanZSync(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } diff --git a/Controllers/ZotacTuringGPUController/RGBController_ZotacTuringGPU.cpp b/Controllers/ZotacTuringGPUController/RGBController_ZotacTuringGPU.cpp index 27c6b1eb..907d60d9 100644 --- a/Controllers/ZotacTuringGPUController/RGBController_ZotacTuringGPU.cpp +++ b/Controllers/ZotacTuringGPUController/RGBController_ZotacTuringGPU.cpp @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_ZotacTuringGPU.cpp | -| | -| Generic RGB Interface for OpenRGB | -| ZOTAC Turing GPU Driver | -| | -| David Henry 1/07/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ZotacTuringGPU.cpp | +| | +| RGBController for Zotac Turing GPU | +| | +| David Henry 07 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_ZotacTuringGPU.h" @@ -22,19 +24,19 @@ RGBController_ZotacTuringGPU::RGBController_ZotacTuringGPU(ZotacTuringGPUController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "ZOTAC GPU"; - vendor = "ZOTAC"; - description = "ZOTAC Turing-based RGB GPU Device"; - location = controller->GetDeviceLocation(); - type = DEVICE_TYPE_GPU; + name = controller->GetDeviceName(); + vendor = "ZOTAC"; + description = "ZOTAC Turing-based RGB GPU Device"; + location = controller->GetDeviceLocation(); + type = DEVICE_TYPE_GPU; mode Direct; - Direct.name = "Direct"; - Direct.value = ZOTAC_GPU_MODE_STATIC; - Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; - Direct.color_mode = MODE_COLORS_PER_LED; + Direct.name = "Direct"; + Direct.value = ZOTAC_GPU_MODE_STATIC; + Direct.flags = MODE_FLAG_HAS_PER_LED_COLOR; + Direct.color_mode = MODE_COLORS_PER_LED; modes.push_back(Direct); mode Flashing; @@ -48,33 +50,33 @@ RGBController_ZotacTuringGPU::RGBController_ZotacTuringGPU(ZotacTuringGPUControl modes.push_back(Flashing); mode Wave; - Wave.name = "Rainbow Wave"; - Wave.value = ZOTAC_GPU_MODE_WAVE; - Wave.flags = MODE_FLAG_HAS_SPEED; - Wave.speed_min = ZOTAC_GPU_SPEED_SLOWEST; - Wave.speed_max = ZOTAC_GPU_SPEED_FASTEST; - Wave.speed = ZOTAC_GPU_SPEED_NORMAL; - Wave.color_mode = MODE_COLORS_NONE; + Wave.name = "Rainbow Wave"; + Wave.value = ZOTAC_GPU_MODE_WAVE; + Wave.flags = MODE_FLAG_HAS_SPEED; + Wave.speed_min = ZOTAC_GPU_SPEED_SLOWEST; + Wave.speed_max = ZOTAC_GPU_SPEED_FASTEST; + Wave.speed = ZOTAC_GPU_SPEED_NORMAL; + Wave.color_mode = MODE_COLORS_NONE; modes.push_back(Wave); mode Breathing; - Breathing.name = "Breathing"; - Breathing.value = ZOTAC_GPU_MODE_BREATHING; - Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR; - Breathing.speed_min = ZOTAC_GPU_SPEED_SLOWEST; - Breathing.speed_max = ZOTAC_GPU_SPEED_FASTEST; - Breathing.speed = ZOTAC_GPU_SPEED_NORMAL; - Breathing.color_mode = MODE_COLORS_PER_LED; + Breathing.name = "Breathing"; + Breathing.value = ZOTAC_GPU_MODE_BREATHING; + Breathing.flags = MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_PER_LED_COLOR; + Breathing.speed_min = ZOTAC_GPU_SPEED_SLOWEST; + Breathing.speed_max = ZOTAC_GPU_SPEED_FASTEST; + Breathing.speed = ZOTAC_GPU_SPEED_NORMAL; + Breathing.color_mode = MODE_COLORS_PER_LED; modes.push_back(Breathing); mode ColorCycle; - ColorCycle.name = "Spectrum Cycle"; - ColorCycle.value = ZOTAC_GPU_MODE_COLOR_CYCLE; - ColorCycle.flags = MODE_FLAG_HAS_SPEED; - ColorCycle.speed_min = ZOTAC_GPU_SPEED_SLOWEST; - ColorCycle.speed_max = ZOTAC_GPU_SPEED_FASTEST; - ColorCycle.speed = ZOTAC_GPU_SPEED_NORMAL; - ColorCycle.color_mode = MODE_COLORS_NONE; + ColorCycle.name = "Spectrum Cycle"; + ColorCycle.value = ZOTAC_GPU_MODE_COLOR_CYCLE; + ColorCycle.flags = MODE_FLAG_HAS_SPEED; + ColorCycle.speed_min = ZOTAC_GPU_SPEED_SLOWEST; + ColorCycle.speed_max = ZOTAC_GPU_SPEED_FASTEST; + ColorCycle.speed = ZOTAC_GPU_SPEED_NORMAL; + ColorCycle.color_mode = MODE_COLORS_NONE; modes.push_back(ColorCycle); SetupZones(); @@ -122,7 +124,7 @@ void RGBController_ZotacTuringGPU::SetupInitialValues() controller->GetMode(colors[0], active_mode, speed); modes[active_mode].speed = speed; - + SignalUpdate(); } diff --git a/Controllers/ZotacTuringGPUController/RGBController_ZotacTuringGPU.h b/Controllers/ZotacTuringGPUController/RGBController_ZotacTuringGPU.h index 4d7c3c19..8a57f90f 100644 --- a/Controllers/ZotacTuringGPUController/RGBController_ZotacTuringGPU.h +++ b/Controllers/ZotacTuringGPUController/RGBController_ZotacTuringGPU.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_ZotacTuringGPU.h | -| | -| Generic RGB Interface for OpenRGB | -| ZOTAC Turing GPU Driver | -| | -| David Henry 1/07/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ZotacTuringGPU.h | +| | +| RGBController for Zotac Turing GPU | +| | +| David Henry 07 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/ZotacTuringGPUController/ZotacTuringGPUController.cpp b/Controllers/ZotacTuringGPUController/ZotacTuringGPUController.cpp index 51841cf5..1c6dde6e 100644 --- a/Controllers/ZotacTuringGPUController/ZotacTuringGPUController.cpp +++ b/Controllers/ZotacTuringGPUController/ZotacTuringGPUController.cpp @@ -1,18 +1,21 @@ -/*-----------------------------------------*\ -| ZotacTuringGPUController.cpp | -| | -| Driver for ZOTAC GeForce RTX 20 series | -| GPU lighting controller | -| | -| David Henry 1/07/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| ZotacTuringGPUController.cpp | +| | +| Driver for Zotac Turing GPU | +| | +| David Henry 07 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "ZotacTuringGPUController.h" -ZotacTuringGPUController::ZotacTuringGPUController(i2c_smbus_interface* bus, u8 dev) +ZotacTuringGPUController::ZotacTuringGPUController(i2c_smbus_interface* bus, u8 dev, std::string dev_name) { - this->bus = bus; - this->dev = dev; + this->bus = bus; + this->dev = dev; + this->name = dev_name; } ZotacTuringGPUController::~ZotacTuringGPUController() @@ -29,6 +32,11 @@ std::string ZotacTuringGPUController::GetDeviceLocation() return("I2C: " + return_string); } +std::string ZotacTuringGPUController::GetDeviceName() +{ + return(name); +} + void ZotacTuringGPUController::GetMode(RGBColor& color, int& mode, unsigned int& speed) { u8 rdata_pkt[I2C_SMBUS_BLOCK_MAX] = { 0x00 }; diff --git a/Controllers/ZotacTuringGPUController/ZotacTuringGPUController.h b/Controllers/ZotacTuringGPUController/ZotacTuringGPUController.h index 51e669f6..b8e2c231 100644 --- a/Controllers/ZotacTuringGPUController/ZotacTuringGPUController.h +++ b/Controllers/ZotacTuringGPUController/ZotacTuringGPUController.h @@ -1,18 +1,20 @@ -/*-----------------------------------------*\ -| ZotacTuringGPUController.cpp | -| | -| Definitions and types for ZOTAC GeForce | -| RTX 20 series GPU lighting controller | -| | -| David Henry 1/07/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| ZotacTuringGPUController.h | +| | +| Driver for Zotac Turing GPU | +| | +| David Henry 07 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" #include "RGBController.h" -#pragma once - enum { ZOTAC_TURING_GPU_REG_COLOR_AND_MODE = 0xA0, @@ -37,16 +39,18 @@ enum class ZotacTuringGPUController { public: - ZotacTuringGPUController(i2c_smbus_interface* bus, u8 dev); + ZotacTuringGPUController(i2c_smbus_interface* bus, u8 dev, std::string dev_name); ~ZotacTuringGPUController(); - std::string GetDeviceLocation(); + std::string GetDeviceLocation(); + std::string GetDeviceName(); - void GetMode(RGBColor& color, int& mode, unsigned int& speed); - void SetMode(RGBColor color, int mode, unsigned int speed); + void GetMode(RGBColor& color, int& mode, unsigned int& speed); + void SetMode(RGBColor color, int mode, unsigned int speed); private: - i2c_smbus_interface* bus; - u8 dev; + i2c_smbus_interface* bus; + u8 dev; + std::string name; }; diff --git a/Controllers/ZotacTuringGPUController/ZotacTuringGPUControllerDetect.cpp b/Controllers/ZotacTuringGPUController/ZotacTuringGPUControllerDetect.cpp index 6caa2ca0..5e4351ee 100644 --- a/Controllers/ZotacTuringGPUController/ZotacTuringGPUControllerDetect.cpp +++ b/Controllers/ZotacTuringGPUController/ZotacTuringGPUControllerDetect.cpp @@ -1,6 +1,16 @@ +/*---------------------------------------------------------*\ +| ZotacTuringGPUControllerDetect.cpp | +| | +| Detector for Zotac Turing GPU | +| | +| David Henry 07 Jan 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "ZotacTuringGPUController.h" -#include "RGBController.h" #include "RGBController_ZotacTuringGPU.h" #include "i2c_smbus.h" #include "pci_ids.h" @@ -41,12 +51,14 @@ void DetectZotacTuringGPUControllers(i2c_smbus_interface* bus, u8 i2c_addr, cons { if(TestForZotacTuringGPUController(bus, i2c_addr)) { - ZotacTuringGPUController* controller = new ZotacTuringGPUController(bus, i2c_addr); + ZotacTuringGPUController* controller = new ZotacTuringGPUController(bus, i2c_addr, name); RGBController_ZotacTuringGPU* rgb_controller = new RGBController_ZotacTuringGPU(controller); - rgb_controller->name = name; ResourceManager::get()->RegisterRGBController(rgb_controller); } } REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 2070 SUPER Twin Fan", DetectZotacTuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2070S_OC_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX2070S_GAMING_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 2080 SUPER Twin Fan", DetectZotacTuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080S_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX2080S_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 2080 AMP", DetectZotacTuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080_A_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX2080_AMP_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 2080 Ti AMP", DetectZotacTuringGPUControllers, NVIDIA_VEN, NVIDIA_RTX2080TI_A_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX2080_AMP_TI_SUB_DEV, 0x49); diff --git a/Controllers/ZotacV2GPUController/RGBController_ZotacV2GPU.cpp b/Controllers/ZotacV2GPUController/RGBController_ZotacV2GPU.cpp index 93804c9d..aa4358af 100644 --- a/Controllers/ZotacV2GPUController/RGBController_ZotacV2GPU.cpp +++ b/Controllers/ZotacV2GPUController/RGBController_ZotacV2GPU.cpp @@ -1,23 +1,31 @@ -/*-----------------------------------------*\ -| RGBController_ZotacV2GPU.cpp | -| | -| Generic RGB Interface for OpenRGB | -| ZOTAC RTX 30/40 series GPU Driver | -| | -| Krzysztof Haładyn (krzys_h) 3/16/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ZotacV2GPU.cpp | +| | +| RGBController for Zotac V2 GPU | +| | +| Krzysztof Haładyn (krzys_h) 16 Mar 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include "RGBController_ZotacV2GPU.h" #include "LogManager.h" -#include std::map ZOTAC_V2_GPU_CONFIG = { { "N653E-1013", { 2, false } }, // ZOTAC GAMING GeForce RTX 3070 Ti Trinity OC + { "N653A-1013", { 1, false } }, // ZOTAC GAMING GeForce RTX 3070 Ti AMP Holo + { "N612E-1011", { 2, false } }, // ZOTAC GAMING GeForce RTX 3080 Trinity OC LHR 12GB & 3090 Trinity & 3070 Ti { "N612A-1012", { 2, false } }, // ZOTAC GAMING GeForce RTX 3080 Ti AMP Holo + { "N617E-1011", { 3, false } }, // ZOTAC GAMING GeForce RTX 3070 AMP Holo LHR { "N618A-1015", { 4, true } }, // ZOTAC GAMING GeForce RTX 3090 AMP Extreme Holo + { "N696E-1040", { 1, false } }, // ZOTAC GAMING GeForce RTX 4070 Ti Trinity OC { "N675E-1019", { 1, true } }, // ZOTAC GAMING GeForce RTX 4090 Trinity OC - { "N675A-1019", { 5, true } }, // ZOTAC GAMING GeForce RTX 4090 AMP Extreme AIRO + { "N675E-1062", { 1, true } }, // ZOTAC GAMING GeForce RTX 4090 Trinity OC Alternate Controller Version + { "N675A-1019", { 5, true } }, // ZOTAC GAMING GeForce RTX 4080 16GB AMP Extreme AIRO + { "N675A-1062", { 5, true } }, // ZOTAC GAMING GeForce RTX 4090 AMP Extreme AIRO }; std::vector> ZOTAC_V2_GPU_DUET_PRESETS = @@ -41,79 +49,122 @@ std::vector> ZOTAC_V2_GPU_DUET_PRESETS = the synchronized mode is supported for now. Sound based effects are not supported. Idle/active config is not supported. + + To add new cards, in addition to entries in `pci_ids/pci_ids.h` + and `Controllers/ZotacV2GPUController/ZotacV2GPUControllerDetect.cpp` + an entry associating the controller version with the LED + configuration must be added to the [ZotacV2GPUConfig map](https://gitlab.com/CalcProgrammer1/OpenRGB/-/blob/master/Controllers/ZotacV2GPUController/RGBController_ZotacV2GPU.cpp?ref_type=heads#L14) in + `Controllers/ZotacV2GPUController/RGBController_ZotacV2GPU.cpp`. + + Controller version is identified by polling the controller on address + 0x49 (so far for all known cards) at register 0xA0 with the following + packet `0xF1 0x00 0x00 0x00 0x00 0x00 0x00` + + The first ten bytes when read back from that address are the version, + this must be converted into Unicode. + + The polling and reading is done by the ZOTAC Firestorm app on startup + and can be monitored using NvAPIspy on Windows. + + For RTX 3080 Trinity OC LHR 12GB the relevant NvAPISpy log entries are: + + > ```plaintext + > NvAPI_I2CWrite: Dev: 0x49 RegSize: 0x00 Reg: Size: 0x08 Data: 0xA0 0xF1 0x00 0x00 0x00 0x00 0x00 0x00 + > NvAPI_I2CRead: Dev: 0x49 RegSize: 0x01 Reg: 0xA0 Size: 0x20 Data: 0x4E 0x36 0x31 0x32 0x45 0x2D 0x31 0x30 0x31 0x31 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 + > ``` + + The read data `0x4E 0x36 0x31 0x32 0x45 0x2D 0x31 0x30 0x31 0x31` converts + to Unicode `N612E-1011` + + Cards with correct entries in `pci_ids/pci_ids.h` and `Controllers/ZotacV2GPUController/ZotacV2GPUControllerDetect.cpp` + but not in `Controllers/ZotacV2GPUController/RGBController_ZotacV2GPU.cpp` + should produce a log error with the controller version read from the card. + + The LED configuration is the number of independently configurable + zones followed by a bool representing support for external led stip. + These can be determined by looking at the Spectra tab in Firestorm. \*-------------------------------------------------------------------*/ RGBController_ZotacV2GPU::RGBController_ZotacV2GPU(ZotacV2GPUController* controller_ptr) { - controller = controller_ptr; + controller = controller_ptr; - name = "ZOTAC GPU"; - vendor = "ZOTAC"; - description = "ZOTAC 30/40 series RGB GPU Device (" + controller->GetVersion() + ")"; - location = controller->GetDeviceLocation(); - type = DEVICE_TYPE_GPU; + name = controller->GetName(); + vendor = "ZOTAC"; + description = "ZOTAC 30/40 series RGB GPU Device (" + controller->GetVersion() + ")"; + location = controller->GetDeviceLocation(); + type = DEVICE_TYPE_GPU; + + if(ZOTAC_V2_GPU_CONFIG.count(controller->GetVersion()) > 0) + { + config = ZOTAC_V2_GPU_CONFIG.at(controller->GetVersion()); + } + else + { + LOG_ERROR("[%s] Unrecognized controller version %s", name.c_str(), controller->GetVersion().c_str()); + config = { 0, false }; + } - config = ZOTAC_V2_GPU_CONFIG.at(controller->GetVersion()); version += std::to_string(config.numberOfZones) + " zones, " + (config.supportsExternalLEDStrip ? "with" : "without") + " external LED strip support"; mode STATIC; - STATIC.name = "Static"; - STATIC.value = ZOTAC_V2_GPU_MODE_STATIC; - STATIC.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - STATIC.brightness_min = 0; - STATIC.brightness_max = 100; - STATIC.brightness = 100; - STATIC.color_mode = MODE_COLORS_MODE_SPECIFIC; - STATIC.colors_min = 1; - STATIC.colors_max = 1; + STATIC.name = "Static"; + STATIC.value = ZOTAC_V2_GPU_MODE_STATIC; + STATIC.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + STATIC.brightness_min = 0; + STATIC.brightness_max = 100; + STATIC.brightness = 100; + STATIC.color_mode = MODE_COLORS_MODE_SPECIFIC; + STATIC.colors_min = 1; + STATIC.colors_max = 1; STATIC.colors.resize(1); - STATIC.colors[0] = ToRGBColor(0, 0, 255); + STATIC.colors[0] = ToRGBColor(0, 0, 255); modes.push_back(STATIC); mode BREATH; - BREATH.name = "Breath"; - BREATH.value = ZOTAC_V2_GPU_MODE_BREATH; - BREATH.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - BREATH.brightness_min = 0; - BREATH.brightness_max = 100; - BREATH.brightness = 100; - BREATH.speed_min = 0; - BREATH.speed_max = 100; - BREATH.speed = 20; - BREATH.color_mode = MODE_COLORS_MODE_SPECIFIC; - BREATH.colors_min = 1; - BREATH.colors_max = 1; + BREATH.name = "Breath"; + BREATH.value = ZOTAC_V2_GPU_MODE_BREATH; + BREATH.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + BREATH.brightness_min = 0; + BREATH.brightness_max = 100; + BREATH.brightness = 100; + BREATH.speed_min = 0; + BREATH.speed_max = 100; + BREATH.speed = 20; + BREATH.color_mode = MODE_COLORS_MODE_SPECIFIC; + BREATH.colors_min = 1; + BREATH.colors_max = 1; BREATH.colors.resize(1); - BREATH.colors[0] = ToRGBColor(0, 0, 255); + BREATH.colors[0] = ToRGBColor(0, 0, 255); modes.push_back(BREATH); mode FADE; - FADE.name = "Fade"; - FADE.value = ZOTAC_V2_GPU_MODE_FADE; - FADE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED; - FADE.speed_min = 0; - FADE.speed_max = 100; - FADE.speed = 20; - FADE.color_mode = MODE_COLORS_NONE; + FADE.name = "Fade"; + FADE.value = ZOTAC_V2_GPU_MODE_FADE; + FADE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED; + FADE.speed_min = 0; + FADE.speed_max = 100; + FADE.speed = 20; + FADE.color_mode = MODE_COLORS_NONE; modes.push_back(FADE); mode WINK; - WINK.name = "Wink"; - WINK.value = ZOTAC_V2_GPU_MODE_WINK; - WINK.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - WINK.brightness_min = 0; - WINK.brightness_max = 100; - WINK.brightness = 100; - WINK.speed_min = 0; - WINK.speed_max = 100; - WINK.speed = 20; - WINK.color_mode = MODE_COLORS_MODE_SPECIFIC; - WINK.colors_min = 1; - WINK.colors_max = 1; + WINK.name = "Wink"; + WINK.value = ZOTAC_V2_GPU_MODE_WINK; + WINK.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + WINK.brightness_min = 0; + WINK.brightness_max = 100; + WINK.brightness = 100; + WINK.speed_min = 0; + WINK.speed_max = 100; + WINK.speed = 20; + WINK.color_mode = MODE_COLORS_MODE_SPECIFIC; + WINK.colors_min = 1; + WINK.colors_max = 1; WINK.colors.resize(1); - WINK.colors[0] = ToRGBColor(0, 0, 255); + WINK.colors[0] = ToRGBColor(0, 0, 255); modes.push_back(WINK); if(config.numberOfZones > 1) @@ -125,113 +176,113 @@ RGBController_ZotacV2GPU::RGBController_ZotacV2GPU(ZotacV2GPUController* control // thing this RGBController supports for now anyway) mode FLASH; - FLASH.name = "Flash"; - FLASH.value = ZOTAC_V2_GPU_MODE_FLASH; - FLASH.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED; - FLASH.speed_min = 0; - FLASH.speed_max = 100; - FLASH.speed = 20; - FLASH.color_mode = MODE_COLORS_NONE; + FLASH.name = "Flash"; + FLASH.value = ZOTAC_V2_GPU_MODE_FLASH; + FLASH.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED; + FLASH.speed_min = 0; + FLASH.speed_max = 100; + FLASH.speed = 20; + FLASH.color_mode = MODE_COLORS_NONE; modes.push_back(FLASH); } // (Sound activated - not supported) //mode SHINE; - //SHINE.name = "Shine"; - //SHINE.value = ZOTAC_V2_GPU_MODE_SHINE; - //SHINE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - //SHINE.brightness_min = 0; - //SHINE.brightness_max = 100; - //SHINE.brightness = 100; - //SHINE.color_mode = MODE_COLORS_MODE_SPECIFIC; - //SHINE.colors_min = 1; - //SHINE.colors_max = 1; + //SHINE.name = "Shine"; + //SHINE.value = ZOTAC_V2_GPU_MODE_SHINE; + //SHINE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + //SHINE.brightness_min = 0; + //SHINE.brightness_max = 100; + //SHINE.brightness = 100; + //SHINE.color_mode = MODE_COLORS_MODE_SPECIFIC; + //SHINE.colors_min = 1; + //SHINE.colors_max = 1; //SHINE.colors.resize(1); - //SHINE.colors[0] = ToRGBColor(0, 0, 255); + //SHINE.colors[0] = ToRGBColor(0, 0, 255); //modes.push_back(SHINE); mode RANDOM; - RANDOM.name = "Random"; - RANDOM.value = ZOTAC_V2_GPU_MODE_RANDOM; - RANDOM.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; - RANDOM.brightness_min = 0; - RANDOM.brightness_max = 100; - RANDOM.brightness = 100; - RANDOM.speed_min = 0; - RANDOM.speed_max = 100; - RANDOM.speed = 20; - RANDOM.color_mode = MODE_COLORS_MODE_SPECIFIC; - RANDOM.colors_min = 1; - RANDOM.colors_max = 1; + RANDOM.name = "Random"; + RANDOM.value = ZOTAC_V2_GPU_MODE_RANDOM; + RANDOM.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR; + RANDOM.brightness_min = 0; + RANDOM.brightness_max = 100; + RANDOM.brightness = 100; + RANDOM.speed_min = 0; + RANDOM.speed_max = 100; + RANDOM.speed = 20; + RANDOM.color_mode = MODE_COLORS_MODE_SPECIFIC; + RANDOM.colors_min = 1; + RANDOM.colors_max = 1; RANDOM.colors.resize(1); - RANDOM.colors[0] = ToRGBColor(0, 0, 255); + RANDOM.colors[0] = ToRGBColor(0, 0, 255); modes.push_back(RANDOM); mode SLIDE; - SLIDE.name = "Slide"; - SLIDE.value = ZOTAC_V2_GPU_MODE_SLIDE; - SLIDE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; - SLIDE.brightness_min = 0; - SLIDE.brightness_max = 100; - SLIDE.brightness = 100; - SLIDE.speed_min = 0; - SLIDE.speed_max = 100; - SLIDE.speed = 20; - SLIDE.color_mode = MODE_COLORS_MODE_SPECIFIC; - SLIDE.colors_min = 1; - SLIDE.colors_max = 1; + SLIDE.name = "Slide"; + SLIDE.value = ZOTAC_V2_GPU_MODE_SLIDE; + SLIDE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + SLIDE.brightness_min = 0; + SLIDE.brightness_max = 100; + SLIDE.brightness = 100; + SLIDE.speed_min = 0; + SLIDE.speed_max = 100; + SLIDE.speed = 20; + SLIDE.color_mode = MODE_COLORS_MODE_SPECIFIC; + SLIDE.colors_min = 1; + SLIDE.colors_max = 1; SLIDE.colors.resize(1); - SLIDE.colors[0] = ToRGBColor(0, 0, 255); + SLIDE.colors[0] = ToRGBColor(0, 0, 255); modes.push_back(SLIDE); mode RAINBOW; - RAINBOW.name = "Rainbow"; - RAINBOW.value = ZOTAC_V2_GPU_MODE_RAINBOW; - RAINBOW.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; - RAINBOW.speed_min = 0; - RAINBOW.speed_max = 100; - RAINBOW.speed = 20; - RAINBOW.color_mode = MODE_COLORS_NONE; + RAINBOW.name = "Rainbow"; + RAINBOW.value = ZOTAC_V2_GPU_MODE_RAINBOW; + RAINBOW.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + RAINBOW.speed_min = 0; + RAINBOW.speed_max = 100; + RAINBOW.speed = 20; + RAINBOW.color_mode = MODE_COLORS_NONE; modes.push_back(RAINBOW); - mode RAINBOW_CIRCUIT = RAINBOW; - RAINBOW_CIRCUIT.name = "Rainbow (circuit)"; + mode RAINBOW_CIRCUIT = RAINBOW; + RAINBOW_CIRCUIT.name = "Rainbow (circuit)"; modes.push_back(RAINBOW_CIRCUIT); mode MARQUEE; - MARQUEE.name = "Marquee"; - MARQUEE.value = ZOTAC_V2_GPU_MODE_MARQUEE; - MARQUEE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; - MARQUEE.brightness_min = 0; - MARQUEE.brightness_max = 100; - MARQUEE.brightness = 100; - MARQUEE.speed_min = 0; - MARQUEE.speed_max = 100; - MARQUEE.speed = 20; - MARQUEE.color_mode = MODE_COLORS_MODE_SPECIFIC; - MARQUEE.colors_min = 1; - MARQUEE.colors_max = 1; + MARQUEE.name = "Marquee"; + MARQUEE.value = ZOTAC_V2_GPU_MODE_MARQUEE; + MARQUEE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + MARQUEE.brightness_min = 0; + MARQUEE.brightness_max = 100; + MARQUEE.brightness = 100; + MARQUEE.speed_min = 0; + MARQUEE.speed_max = 100; + MARQUEE.speed = 20; + MARQUEE.color_mode = MODE_COLORS_MODE_SPECIFIC; + MARQUEE.colors_min = 1; + MARQUEE.colors_max = 1; MARQUEE.colors.resize(1); - MARQUEE.colors[0] = ToRGBColor(0, 0, 255); + MARQUEE.colors[0] = ToRGBColor(0, 0, 255); modes.push_back(MARQUEE); - mode MARQUEE_CIRCUIT = MARQUEE; - MARQUEE_CIRCUIT.name = "Marquee (circuit)"; + mode MARQUEE_CIRCUIT = MARQUEE; + MARQUEE_CIRCUIT.name = "Marquee (circuit)"; modes.push_back(MARQUEE_CIRCUIT); mode DRIP; - DRIP.name = "Drip"; - DRIP.value = ZOTAC_V2_GPU_MODE_DRIP; - DRIP.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; - DRIP.brightness_min = 0; - DRIP.brightness_max = 100; - DRIP.brightness = 100; - DRIP.speed_min = 0; - DRIP.speed_max = 100; - DRIP.speed = 20; - DRIP.color_mode = MODE_COLORS_MODE_SPECIFIC; - DRIP.colors_min = 1; - DRIP.colors_max = 1; + DRIP.name = "Drip"; + DRIP.value = ZOTAC_V2_GPU_MODE_DRIP; + DRIP.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + DRIP.brightness_min = 0; + DRIP.brightness_max = 100; + DRIP.brightness = 100; + DRIP.speed_min = 0; + DRIP.speed_max = 100; + DRIP.speed = 20; + DRIP.color_mode = MODE_COLORS_MODE_SPECIFIC; + DRIP.colors_min = 1; + DRIP.colors_max = 1; DRIP.colors.resize(1); - DRIP.colors[0] = ToRGBColor(0, 0, 255); + DRIP.colors[0] = ToRGBColor(0, 0, 255); modes.push_back(DRIP); mode DRIP_CIRCUIT = DRIP; DRIP_CIRCUIT.name = "Drip (circuit)"; @@ -239,49 +290,49 @@ RGBController_ZotacV2GPU::RGBController_ZotacV2GPU(ZotacV2GPUController* control // (Sound activated - not supported) //mode DANCE; - //DANCE.name = "Dance (sound activated)"; - //DANCE.value = ZOTAC_V2_GPU_MODE_DANCE; - //DANCE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; - //DANCE.brightness_min = 0; - //DANCE.brightness_max = 100; - //DANCE.brightness = 100; - //DANCE.color_mode = MODE_COLORS_MODE_SPECIFIC; - //DANCE.colors_min = 1; - //DANCE.colors_max = 1; + //DANCE.name = "Dance (sound activated)"; + //DANCE.value = ZOTAC_V2_GPU_MODE_DANCE; + //DANCE.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + //DANCE.brightness_min = 0; + //DANCE.brightness_max = 100; + //DANCE.brightness = 100; + //DANCE.color_mode = MODE_COLORS_MODE_SPECIFIC; + //DANCE.colors_min = 1; + //DANCE.colors_max = 1; //DANCE.colors.resize(1); - //DANCE.colors[0] = ToRGBColor(0, 0, 255); + //DANCE.colors[0] = ToRGBColor(0, 0, 255); //modes.push_back(DANCE); mode DUET; - DUET.name = "Duet"; - DUET.value = ZOTAC_V2_GPU_MODE_DUET; - DUET.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; - DUET.speed_min = 0; - DUET.speed_max = 100; - DUET.speed = 20; - DUET.color_mode = MODE_COLORS_MODE_SPECIFIC; - DUET.colors_min = 2; - DUET.colors_max = 2; + DUET.name = "Duet"; + DUET.value = ZOTAC_V2_GPU_MODE_DUET; + DUET.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_MODE_SPECIFIC_COLOR | MODE_FLAG_HAS_DIRECTION_LR; + DUET.speed_min = 0; + DUET.speed_max = 100; + DUET.speed = 20; + DUET.color_mode = MODE_COLORS_MODE_SPECIFIC; + DUET.colors_min = 2; + DUET.colors_max = 2; DUET.colors.resize(2); - DUET.colors[0] = ZOTAC_V2_GPU_DUET_PRESETS[1].first; - DUET.colors[1] = ZOTAC_V2_GPU_DUET_PRESETS[1].second; + DUET.colors[0] = ZOTAC_V2_GPU_DUET_PRESETS[1].first; + DUET.colors[1] = ZOTAC_V2_GPU_DUET_PRESETS[1].second; modes.push_back(DUET); - mode DUET_CIRCUIT = DUET; + mode DUET_CIRCUIT = DUET; DUET_CIRCUIT.name = "Duet (circuit)"; modes.push_back(DUET_CIRCUIT); mode PATH; - PATH.name = "Path"; - PATH.value = ZOTAC_V2_GPU_MODE_PATH; - PATH.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; - PATH.brightness_min = 0; - PATH.brightness_max = 100; - PATH.brightness = 100; - PATH.speed_min = 0; - PATH.speed_max = 100; - PATH.speed = 20; - PATH.color_mode = MODE_COLORS_NONE; + PATH.name = "Path"; + PATH.value = ZOTAC_V2_GPU_MODE_PATH; + PATH.flags = MODE_FLAG_AUTOMATIC_SAVE | MODE_FLAG_HAS_BRIGHTNESS | MODE_FLAG_HAS_SPEED | MODE_FLAG_HAS_DIRECTION_LR; + PATH.brightness_min = 0; + PATH.brightness_max = 100; + PATH.brightness = 100; + PATH.speed_min = 0; + PATH.speed_max = 100; + PATH.speed = 20; + PATH.color_mode = MODE_COLORS_NONE; modes.push_back(PATH); SetupZones(); @@ -400,13 +451,13 @@ void RGBController_ZotacV2GPU::DeviceUpdateMode() zoneConfig.colorPreset = 0; if(zoneConfig.mode == ZOTAC_V2_GPU_MODE_DUET) { - zoneConfig.colorPreset = ZOTAC_V2_GPU_DUET_PRESETS.size(); // custom + zoneConfig.colorPreset = (unsigned int)ZOTAC_V2_GPU_DUET_PRESETS.size(); // custom for(size_t i = 0; i < ZOTAC_V2_GPU_DUET_PRESETS.size(); ++i) { if(zoneConfig.color1 == ZOTAC_V2_GPU_DUET_PRESETS[i].first && zoneConfig.color2 == ZOTAC_V2_GPU_DUET_PRESETS[i].second) { - zoneConfig.colorPreset = i; + zoneConfig.colorPreset = (unsigned int)i; } } } diff --git a/Controllers/ZotacV2GPUController/RGBController_ZotacV2GPU.h b/Controllers/ZotacV2GPUController/RGBController_ZotacV2GPU.h index 31d3304a..567241b4 100644 --- a/Controllers/ZotacV2GPUController/RGBController_ZotacV2GPU.h +++ b/Controllers/ZotacV2GPUController/RGBController_ZotacV2GPU.h @@ -1,11 +1,13 @@ -/*-----------------------------------------*\ -| RGBController_ZotacV2GPU.h | -| | -| Generic RGB Interface for OpenRGB | -| ZOTAC RTX 30/40 series GPU Driver | -| | -| Krzysztof Haładyn (krzys_h) 3/16/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_ZotacV2GPU.h | +| | +| RGBController for Zotac V2 GPU | +| | +| Krzysztof Haładyn (krzys_h) 16 Mar 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/Controllers/ZotacV2GPUController/ZotacV2GPUController.cpp b/Controllers/ZotacV2GPUController/ZotacV2GPUController.cpp index 5f1335d1..7f3300a5 100644 --- a/Controllers/ZotacV2GPUController/ZotacV2GPUController.cpp +++ b/Controllers/ZotacV2GPUController/ZotacV2GPUController.cpp @@ -1,19 +1,22 @@ -/*------------------------------------------*\ -| ZotacV2GPUController.cpp | -| | -| Driver for ZOTAC GeForce RTX 30/40 series | -| GPU lighting controller | -| | -| Krzysztof Haładyn (krzys_h) 3/16/2023 | -\*------------------------------------------*/ +/*---------------------------------------------------------*\ +| ZotacV2GPUController.cpp | +| | +| Driver for Zotac V2 GPU | +| | +| Krzysztof Haładyn (krzys_h) 16 Mar 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "ZotacV2GPUController.h" #include "LogManager.h" -ZotacV2GPUController::ZotacV2GPUController(i2c_smbus_interface* bus, u8 dev) +ZotacV2GPUController::ZotacV2GPUController(i2c_smbus_interface* bus, u8 dev, std::string dev_name) { - this->bus = bus; - this->dev = dev; + this->bus = bus; + this->dev = dev; + this->name = dev_name; if(dev) { @@ -35,9 +38,14 @@ std::string ZotacV2GPUController::GetDeviceLocation() return ("I2C: " + return_string); } +std::string ZotacV2GPUController::GetName() +{ + return(name); +} + std::string ZotacV2GPUController::GetVersion() { - return version; + return(version); } bool ZotacV2GPUController::ReadVersion() @@ -56,6 +64,7 @@ bool ZotacV2GPUController::ReadVersion() } version = std::string((char*)rdata_pkt); + return true; } @@ -158,16 +167,6 @@ bool ZotacV2GPUController::SendCommand(bool on, bool reset, int zone, int idleAc (u8)RGBGetGValue(zoneConfig.color2), (u8)RGBGetBValue(zoneConfig.color2), (u8)zoneConfig.colorPreset, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, }; if(bus->i2c_write_block(dev, sizeof(data_pkt), data_pkt) < 0) diff --git a/Controllers/ZotacV2GPUController/ZotacV2GPUController.h b/Controllers/ZotacV2GPUController/ZotacV2GPUController.h index bdd0cb07..194ebcbe 100644 --- a/Controllers/ZotacV2GPUController/ZotacV2GPUController.h +++ b/Controllers/ZotacV2GPUController/ZotacV2GPUController.h @@ -1,18 +1,20 @@ -/*-----------------------------------------*\ -| ZotacV2GPUController.cpp | -| | -| Definitions and types for ZOTAC GeForce | -| RTX 30/40 series GPU lighting controller | -| | -| Krzysztof Haładyn (krzys_h) 3/16/2023 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| ZotacV2GPUController.h | +| | +| Driver for Zotac V2 GPU | +| | +| Krzysztof Haładyn (krzys_h) 16 Mar 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once #include #include "i2c_smbus.h" #include "RGBController.h" -#pragma once - enum { ZOTAC_V2_GPU_REG_RGB = 0xA0, @@ -83,24 +85,25 @@ struct ZotacV2GPUZone class ZotacV2GPUController { public: - ZotacV2GPUController(i2c_smbus_interface* bus, u8 dev); + ZotacV2GPUController(i2c_smbus_interface* bus, u8 dev, std::string dev_name); ~ZotacV2GPUController(); - std::string GetDeviceLocation(); - std::string GetVersion(); + std::string GetDeviceLocation(); + std::string GetName(); + std::string GetVersion(); - bool TurnOnOff(bool on); - bool ResetToDefaults(); - bool GetMode(int zone, int idleActive, int& syncMode, ZotacV2GPUZone& zoneConfig, bool& on); - bool SetMode(int zone, int idleActive, int syncMode, ZotacV2GPUZone zoneConfig); + bool TurnOnOff(bool on); + bool ResetToDefaults(); + bool GetMode(int zone, int idleActive, int& syncMode, ZotacV2GPUZone& zoneConfig, bool& on); + bool SetMode(int zone, int idleActive, int syncMode, ZotacV2GPUZone zoneConfig); private: - bool ReadVersion(); - bool SendCommand(bool on, bool reset, int zone, int idleActive, int syncMode, ZotacV2GPUZone zoneConfig); - bool ParseCommand(bool& on, bool& reset, int& zone, int& idleActive, int& syncMode, ZotacV2GPUZone& zoneConfig); - - i2c_smbus_interface* bus; - u8 dev; - std::string version; + i2c_smbus_interface* bus; + u8 dev; + std::string name; + std::string version; + bool ReadVersion(); + bool SendCommand(bool on, bool reset, int zone, int idleActive, int syncMode, ZotacV2GPUZone zoneConfig); + bool ParseCommand(bool& on, bool& reset, int& zone, int& idleActive, int& syncMode, ZotacV2GPUZone& zoneConfig); }; diff --git a/Controllers/ZotacV2GPUController/ZotacV2GPUControllerDetect.cpp b/Controllers/ZotacV2GPUController/ZotacV2GPUControllerDetect.cpp index 5a62ca16..37f67770 100644 --- a/Controllers/ZotacV2GPUController/ZotacV2GPUControllerDetect.cpp +++ b/Controllers/ZotacV2GPUController/ZotacV2GPUControllerDetect.cpp @@ -1,9 +1,20 @@ +/*---------------------------------------------------------*\ +| ZotacV2GPUControllerDetect.cpp | +| | +| Detector for Zotac V2 GPU | +| | +| Krzysztof Haładyn (krzys_h) 16 Mar 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "Detector.h" #include "ZotacV2GPUController.h" -#include "RGBController.h" #include "RGBController_ZotacV2GPU.h" #include "i2c_smbus.h" #include "pci_ids.h" +#include "LogManager.h" /******************************************************************************************\ * * @@ -19,18 +30,38 @@ void DetectZotacV2GPUControllers(i2c_smbus_interface* bus, u8 i2c_addr, const std::string& name) { - ZotacV2GPUController* controller = new ZotacV2GPUController(bus, i2c_addr); - RGBController_ZotacV2GPU* rgb_controller = new RGBController_ZotacV2GPU(controller); - rgb_controller->name = name; + u8 rdata_pkt[I2C_SMBUS_BLOCK_MAX] = { 0x00 }; + int rdata_len = sizeof(rdata_pkt); - if(rgb_controller->config.numberOfZones > 0) + if(bus->i2c_read_block(i2c_addr, &rdata_len, rdata_pkt) >= 0) { - ResourceManager::get()->RegisterRGBController(rgb_controller); + ZotacV2GPUController* controller = new ZotacV2GPUController(bus, i2c_addr, name); + RGBController_ZotacV2GPU* rgb_controller = new RGBController_ZotacV2GPU(controller); + + if(rgb_controller->config.numberOfZones > 0) + { + ResourceManager::get()->RegisterRGBController(rgb_controller); + } + else + { + LOG_ERROR("[%s] RGB controller not registered.", name.c_str()); + } } } -REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 3070 Ti Trinity OC", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX3070TI_TRINITY_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 3080 Ti AMP Holo", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX3080TI_AMP_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 3090 AMP Extreme Holo", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX3090_AMP_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 4090 Trinity OC", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX4090_TRINITY_SUB_DEV, 0x49); -REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 4090 AMP Extreme AIRO", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX4090_AMP_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 3070 AMP Holo LHR", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3070_LHR_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX3070_AMP_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 3070 Ti", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_GA102_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX3070TI_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 3070 Ti Trinity OC/AMP Holo", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3070TI_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX3070TI_TRINITY_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 3080 Trinity OC", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX3080_TRINITY_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 3080 Trinity LHR", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX3080_TRINITY_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 3080 AMP Holo", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX3080_AMP_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 3080 AMP Holo LHR", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_LHR_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX3080_AMP_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 3080 12GB Trinity OC LHR", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080_12G_LHR_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX3080_12G_LHR_TRINITY_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 3080 Ti AMP Holo", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3080TI_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX3080TI_AMP_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 3090 AMP Extreme Holo", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX3090_AMP_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 3090 Trinity", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX3090_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX3090_TRINITY_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 4070 Ti Trinity OC", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4070TI_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX4070TI_TRINITY_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 4080 AMP Extreme AIRO", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX4080_AMP_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 4080 AMP Extreme AIRO", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4080_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX4080_AMP_ALT_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 4090 Trinity OC", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX4090_TRINITY_SUB_DEV, 0x49); +REGISTER_I2C_PCI_DETECTOR("ZOTAC GAMING GeForce RTX 4090 AMP Extreme AIRO", DetectZotacV2GPUControllers, NVIDIA_VEN, NVIDIA_RTX4090_DEV, ZOTAC_SUB_VEN, ZOTAC_RTX4090_AMP_SUB_DEV, 0x49); diff --git a/Detector.h b/Detector.h index 6c6cc391..cdaf9c89 100644 --- a/Detector.h +++ b/Detector.h @@ -1,9 +1,19 @@ +/*---------------------------------------------------------*\ +| Detector.h | +| | +| Macros for registering detectors | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #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_DIMM_DETECTOR(name, func, jedec_id, dimm_type) static I2CDIMMDeviceDetector device_detector_obj_##func##jedec_id(name, func, jedec_id, dimm_type) #define REGISTER_I2C_PCI_DETECTOR(name, func, ven, dev, subven, subdev, addr) static I2CPCIDeviceDetector device_detector_obj_##ven##dev##subven##subdev##addr##func(name, func, ven, dev, subven, subdev, addr) #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) @@ -20,6 +30,7 @@ #define REGISTER_PRE_DETECTION_HOOK(func) static PreDetectionHook device_detector_obj_##func(func) #define REGISTER_DYNAMIC_I2C_DETECTOR(name, func) I2CDeviceDetector device_detector_obj_##func(name, func) +#define REGISTER_DYNAMIC_I2C_DIMM_DETECTOR(name, func, jedec_id, dimm_type) I2CDIMMDeviceDetector device_detector_obj_##func(name, func, jedec_id, dimm_type) #define REGISTER_DYNAMIC_I2C_PCI_DETECTOR(name, func, ven, dev, subven, subdev, addr) I2CPCIDeviceDetector device_detector_obj_##ven##dev##subven##subdev##addr##func(name, func, ven, dev, subven, subdev, addr) #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) diff --git a/DeviceDetector.h b/DeviceDetector.h index 6d40d996..66d3bdac 100644 --- a/DeviceDetector.h +++ b/DeviceDetector.h @@ -1,3 +1,12 @@ +/*---------------------------------------------------------*\ +| DeviceDetector.h | +| | +| Device detector functionality | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include @@ -24,6 +33,15 @@ public: } }; +class I2CDIMMDeviceDetector +{ +public: + I2CDIMMDeviceDetector(std::string name, I2CDIMMDeviceDetectorFunction detector, uint16_t jedec_id, uint8_t dimm_type) + { + ResourceManager::get()->RegisterI2CDIMMDeviceDetector(name, detector, jedec_id, dimm_type); + } +}; + class I2CPCIDeviceDetector { public: @@ -45,7 +63,7 @@ public: class HIDDeviceDetector { public: - HIDDeviceDetector(std::string name, HIDDeviceDetectorFunction detector, uint16_t vid, uint16_t pid, int64_t interface, int usage_page, int usage) + HIDDeviceDetector(std::string name, HIDDeviceDetectorFunction detector, uint16_t vid, uint16_t pid, int interface, int usage_page, int usage) { ResourceManager::get()->RegisterHIDDeviceDetector(name, detector, vid, pid, interface, usage_page, usage); } @@ -54,7 +72,7 @@ public: class HIDWrappedDeviceDetector { public: - HIDWrappedDeviceDetector(std::string name, HIDWrappedDeviceDetectorFunction detector, uint16_t vid, uint16_t pid, int64_t interface, int usage_page, int usage) + HIDWrappedDeviceDetector(std::string name, HIDWrappedDeviceDetectorFunction detector, uint16_t vid, uint16_t pid, int interface, int usage_page, int usage) { ResourceManager::get()->RegisterHIDWrappedDeviceDetector(name, detector, vid, pid, interface, usage_page, usage); } diff --git a/Documentation/Common-Modes.md b/Documentation/Common-Modes.md new file mode 100644 index 00000000..d2110668 --- /dev/null +++ b/Documentation/Common-Modes.md @@ -0,0 +1,19 @@ +# Common Modes in OpenRGB + +OpenRGB uses "modes" to describe RGB effects built into a device’s firmware. These effects can be changed by selecting a mode in the OpenRGB interface. The patterns are generated by the device’s RGB controller, not by OpenRGB, and run independently of the PC. In the interest of being able to better describe these modes, we are trying to standardize the mode names across all supported devices. + +There are several effects that are pretty common across many brands and vendors of RGB hardware. Manufacturers often use different names for the same mode. For example, a fade-in/fade-out effect might be called "Fading", "Breathing", or "Breath". A color-cycling effect might appear as "Cycle", "Spectrum Cycle", "Spectrum", or "Rainbow". A lot of OpenRGB's existing code simply copies the same names the official software gave to the modes, but these differences in name prevent us from being able to apply what is essentially the same effect across multiple devices when the names don't match. It also limits our ability to provide clear descriptions of modes through tooltips. To remedy this, we have compiled a list of common modes and providing names that we can use across all devices for any mode that implements a certain style of effect. If all devices have their fade on/fade off mode called "Breathing", we can just set "Breathing" across all devices and end up with something that looks at least sort of uniform, if not synchronized in time. + +# Common OpenRGB Modes + +| Standardized Name | Description | Example GIF | +| ----------------- | ----------- | ----------- | +| Direct | Direct mode is a mode that allows setting individual LEDs to static colors that does not fade or flicker upon color changes and does not save the updated colors to device memory. Used for effect engine software to rapidly update the LEDs for PC software driven effects. Some devices require a continuous packet stream to remain in direct mode, otherwise they revert to built-in effects. | | +| Custom | Custom mode is a mode that allows setting individual LEDs to static colors, but does not meet the criteria for being a Direct mode. This means it either flickers, fades, or saves to device memory. Generally unsuitable for effect engine software. | | +| Static | Static mode is a mode that sets the entire device or device zones, but not individual LEDs, to a static color. This mode may fade or flicker and may save to device memory. | | +| Breathing | Light gradually fades from fully off to fully on over some period of time and then gradually fades back to fully off. | | +| Flashing | Light abruptly changes from fully off to fully on instantly, then instantly turns back off after a period of time. | | +| Spectrum Cycle | Light gradually cycles through the entire color spectrum. All lights on the device are the same color. | | +| Rainbow Wave | Light gradually cycles through the entire color spectrum. Lights are staggered as to produce a rainbow pattern that moves. | | +| Reactive | Generally only available on input devices, this is a mode that lights one or more LEDs when an input (key, mouse button, etc) is pressed. | | +| Off | All lights are disabled. | | diff --git a/Documentation/Compiling.md b/Documentation/Compiling.md new file mode 100644 index 00000000..8b6f165e --- /dev/null +++ b/Documentation/Compiling.md @@ -0,0 +1,71 @@ +# Compiling + +This document details the process to compile OpenRGB from source on supported operating systems. + +## Windows + + * You will need the **Microsoft Visual 2019 C++ runtime** installed. You can get it [here](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist) + * To build the application yourself on Windows: + 1. [Install Git](https://git-scm.com/download) + 2. Clone the [OpenRGB-Qt-Packages](https://gitlab.com/OpenRGBDevelopers/OpenRGB-Qt-Packages) git repo and run `install.bat` (or optionally `install-chocolatey.bat` if you use the Chocolatey package manager). + 3. In the OpenRGB source directory, run the `scripts\build-windows.bat` file with arguments ` `. + * Qt versions provided by `OpenRGB-Qt-Packages` include `5.15.0` (using MSVC `2019`) and `6.8.3` (using MSVC `2022`). + * For example, for a Qt5 64-bit build, `.\scripts\build-windows.bat 5.15.0 2019 64` + 4. You can also use Qt Creator to build and debug the project, you will need to install it from the Qt Online Installer or by downloading and extracting a binary release and manually configuring it. + +## Linux + + 1. Install build dependencies + - 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 libmbedtls-dev qttools5-dev-tools` + - Fedora: `sudo dnf install automake gcc-c++ git hidapi-devel libusbx-devel mbedtls-devel pkgconf qt5-qtbase-devel qt5-linguist` + 2. `git clone https://gitlab.com/CalcProgrammer1/OpenRGB` + 3. `cd OpenRGB` + 4. `mkdir build` + 5. `cd build` + 4. `qmake ../OpenRGB.pro` + 5. `make -j$(nproc)` + 6. You can then run the application from the compile directory with `./openrgb` or install with `make install` + 7. You will also need to [install the latest udev rules](UdevRules.md). + +#### Packaging + +You can also build OpenRGB generic AppImage packages and distribution-specific packages for Debian-based and Fedora-based distros. Install the build dependencies from the section above for your distribution before proceeding. + + * AppImage: + + * Debian/Ubuntu: + * Make sure OpenRGB is cloned in ~/OpenRGB before proceeding. Output .deb is in ~/. + 1. `sudo apt install debhelper` + 2. `cd ~/OpenRGB` + 3. `scripts/build-package-files.sh debian/changelog` + 4. `dpkg-buildpackage -us -B` + + * Fedora: + * Make sure OpenRGB is cloned in ~/OpenRGB before proceeding. Output .rpm is in ~/rpmbuild/RPMS/. + 1. `sudo dnf install rpmdevtools dnf-plugins-core` + 2. `cd ~/` + 3. `rpmdev-setuptree` + 4. `tar -cf rpmbuild/SOURCES/OpenRGB.tar.gz OpenRGB/` + 4. `cd OpenRGB` + 5. `./scripts/build-package-files.sh fedora/OpenRGB.spec` + 6. `cd ~/` + 7. `cp OpenRGB/fedora/OpenRGB.spec rpmbuild/SPECS/` + 8. `sudo dnf builddep rpmbuild/SPECS/OpenRGB.spec -y` + 9. `cd rpmbuild/SOURCES` + 10. `tar -xf OpenRGB.tar.gz` + 11. `cd ~/` + 12. `rpmbuild -ba rpmbuild/SPECS/OpenRGB.spec` + +## MacOS + + 1. Install build dependencies with Homebrew + - Install Homebrew by following the instructions at https://brew.sh/ + - `brew install git qt5 hidapi libusb mbedtls@2` + - `brew link qt5` + 2. [Create a local certificate](https://support.apple.com/guide/keychain-access/create-self-signed-certificates-kyca8916/mac) called OpenRGB with code signing capability + 3. git clone https://gitlab.com/CalcProgrammer1/OpenRGB + 4. cd OpenRGB + 5. qmake OpenRGB.pro + 6. make -j8 + 7. macdeployqt OpenRGB.app -codesign=OpenRGB + 8. Copy the OpenRGB.app application package to Applications diff --git a/Documentation/Images/OpenRGB.png b/Documentation/Images/OpenRGB.png new file mode 100644 index 00000000..8c6ec366 Binary files /dev/null and b/Documentation/Images/OpenRGB.png differ diff --git a/Documentation/Images/OpenRGB_Screenshot.png b/Documentation/Images/OpenRGB_Screenshot.png new file mode 100644 index 00000000..3e921c75 Binary files /dev/null and b/Documentation/Images/OpenRGB_Screenshot.png differ diff --git a/Documentation/KernelParameters.md b/Documentation/KernelParameters.md new file mode 100644 index 00000000..b9a0e035 --- /dev/null +++ b/Documentation/KernelParameters.md @@ -0,0 +1,17 @@ +# Kernel Parameters + + * To resolve an ACPI conflict add the `acpi_enforce_resources=lax` kernel parameter. + * If you want to check if the kernel was loaded with this option you can execute this command from the terminal once you've rebooted: `cat /proc/cmdline`. + +### Arch Linux + + * Please see [the Arch wiki](https://wiki.archlinux.org/title/kernel_parameters) for details on how to update your bootloader. + +### Debian/Ubuntu + + * Please see [the Ubuntu Documentation](https://wiki.ubuntu.com/Kernel/KernelBootParameters) for Kernel Parameters for more information on updating your boot parameters. + +### Fedora + + * On Fedora, install `grubby` and then following command: `grubby --update-kernel=ALL --args="acpi_enforce_resources=lax"`. + * For more information please refer to the Fedora docs for [grubby](https://docs.fedoraproject.org/en-US/fedora/latest/system-administrators-guide/kernel-module-driver-configuration/Working_with_the_GRUB_2_Boot_Loader/#sec-Making_Persistent_Changes_to_a_GRUB_2_Menu_Using_the_grubby_Tool). diff --git a/Documentation/OpenRGBSDK.md b/Documentation/OpenRGBSDK.md new file mode 100644 index 00000000..8c04e599 --- /dev/null +++ b/Documentation/OpenRGBSDK.md @@ -0,0 +1,405 @@ +# OpenRGB SDK Documentation + +OpenRGB provides a network-based Software Development Kit (SDK) interface for third-party software applications to integrate with OpenRGB to control lighting on OpenRGB-supported devices. This protocol is a binary, packet-based protocol designed for efficient, lightweight transfer of lighting data over a TCP/IP connection. It may be used locally or over a physical network between computers. The protocol is versioned. Client and server must negotiate a minimum supported protocol version upon connection. The selected protocol version determines what capabilities are available and can change packet format for certain packets as new information is added to the protocol. + +The protocol mimics the [RGBController API](The-RGBController-API) closely. It can be thought of as "RGBController over IP" in that the protocol is designed so that a network RGBController object can be created on the client that is a direct copy of the real RGBController object on the server. Calls to the network client RGBController object send packets to the server which trigger calls to the real object, updating the necessary object data before the call. + +# Protocol Versions + +| Protocol Version | OpenRGB Release | Description | +| ---------------- | --------------- | -------------------------------------------------------------------------------------------------------------- | +| 0 | 0.3 | Initial (unversioned) protocol | +| 1 | 0.5 | Add versioning, add vendor string | +| 2 | 0.6 | Add profile controls | +| 3 | 0.7 | Add brightness field to modes, add SaveMode() | +| 4 | 0.9 | Add segments field to zones, plugin interface | +| 5 | 1.0 | Add zone flags, controller flags, effects-only zones, alternative LED names, add ClearSegments and AddSegments | + +\* Denotes unreleased version, reflects status of current pipeline + +# Protocol Basics + +The default port for the OpenRGB SDK server is 6742. This is "ORGB" on a telephone keypad. + +Each packet starts with a header that indicates the packet is an OpenRGB SDK packet and provides the device and packet IDs. The header format is described in the following table. + +### NetPacketHeader structure + +| Size | Format | Name | Description | +| ---- | ------------ | ----------- | ------------------- | +| 4 | char[4] | pkt_magic | Magic value, "ORGB" | +| 4 | unsigned int | pkt_dev_idx | Device Index | +| 4 | unsigned int | pkt_id | Packet ID | +| 4 | unsigned int | pkt_size | Packet Size | + +`pkt_magic`: Always set this to the literal value "ORGB". + +`pkt_dev_idx`: The device index that the command is targeting. + +`pkt_id`: The command ID, see IDs table below + +`pkt_size`: The size, in bytes, of the packet data + +### Packet IDs + +The following IDs represent different SDK commands. Each ID packet has a certain format of data associated with it, which will be explained under each ID's section of this document. Gaps have been left in the ID values to allow for future expansion. The same ID values are often used for both request and response packets. + +| Value | Name | Description | Protocol Version | +| ----- | ------------------------------------------------------------------------------------------- | ------------------------------------------------ | ---------------- | +| 0 | [NET_PACKET_ID_REQUEST_CONTROLLER_COUNT](#net_packet_id_request_controller_count) | Request RGBController device count from server | 0 | +| 1 | [NET_PACKET_ID_REQUEST_CONTROLLER_DATA](#net_packet_id_request_controller_data) | Request RGBController data block | 0 | +| 40 | [NET_PACKET_ID_REQUEST_PROTOCOL_VERSION](#net_packet_id_request_protocol_version) | Request OpenRGB SDK protocol version from server | 1* | +| 50 | [NET_PACKET_ID_SET_CLIENT_NAME](#net_packet_id_set_client_name) | Send client name string to server | 0 | +| 100 | [NET_PACKET_ID_DEVICE_LIST_UPDATED](#net_packet_id_device_list_updated) | Indicate to clients that device list has updated | 1 | +| 140 | [NET_PACKET_ID_REQUEST_RESCAN_DEVICES](#net_packet_id_request_rescan_devices) | Request server to rescan devices | 5 | +| 150 | [NET_PACKET_ID_REQUEST_PROFILE_LIST](#net_packet_id_request_profile_list) | Request profile list | 2 | +| 151 | [NET_PACKET_ID_REQUEST_SAVE_PROFILE](#net_packet_id_request_save_profile) | Save current configuration in a new profile | 2 | +| 152 | [NET_PACKET_ID_REQUEST_LOAD_PROFILE](#net_packet_id_request_load_profile) | Load a given profile | 2 | +| 153 | [NET_PACKET_ID_REQUEST_DELETE_PROFILE](#net_packet_id_request_delete_profile) | Delete a given profile | 2 | +| 200 | [NET_PACKET_ID_REQUEST_PLUGIN_LIST](#net_packet_id_request_plugin_list) | Request plugin list | 4 | +| 201 | [NET_PACKET_ID_PLUGIN_SPECIFIC](#net_packet_id_plugin_specific) | Plugin specific | 4 | +| 1000 | [NET_PACKET_ID_RGBCONTROLLER_RESIZEZONE](#net_packet_id_rgbcontroller_resizezone) | RGBController::ResizeZone() | 0 | +| 1001 | [NET_PACKET_ID_RGBCONTROLLER_CLEARSEGMENTS](#net_packet_id_rgbcontroller_clearsegments) | RGBController::ClearSegments() | 5 | +| 1002 | [NET_PACKET_ID_RGBCONTROLLER_ADDSEGMENT](#net_packet_id_rgbcontroller_addsegment) | RGBController::AddSegment() | 5 | +| 1050 | [NET_PACKET_ID_RGBCONTROLLER_UPDATELEDS](#net_packet_id_rgbcontroller_updateleds) | RGBController::UpdateLEDs() | 0 | +| 1051 | [NET_PACKET_ID_RGBCONTROLLER_UPDATEZONELEDS](#net_packet_id_rgbcontroller_updatezoneleds) | RGBController::UpdateZoneLEDs() | 0 | +| 1052 | [NET_PACKET_ID_RGBCONTROLLER_UPDATESINGLELED](#net_packet_id_rgbcontroller_updatesingleled) | RGBController::UpdateSingleLED() | 0 | +| 1100 | [NET_PACKET_ID_RGBCONTROLLER_SETCUSTOMMODE](#net_packet_id_rgbcontroller_setcustommode) | RGBController::SetCustomMode() | 0 | +| 1101 | [NET_PACKET_ID_RGBCONTROLLER_UPDATEMODE](#net_packet_id_rgbcontroller_updatemode) | RGBController::UpdateMode() | 0 | +| 1102 | [NET_PACKET_ID_RGBCONTROLLER_SAVEMODE](#net_packet_id_rgbcontroller_savemode) | RGBController::SaveMode() | 3 | + +\* The NET_PACKET_ID_REQUEST_PROTOCOL_VERSION packet was not present in protocol version 0, but clients supporting protocol versions 1+ should always send this packet. If no response is received, it should be assumed that the server is using protocol 0. + +# Packet-Specific Documentation + +## NET_PACKET_ID_REQUEST_CONTROLLER_COUNT + +### Request [Size: 0] + +The client uses this ID to request the number of controllers on the server. The request contains no data. + +### Response [Size: 4] + +The server responds to this request with the number of controllers in the device list. The response contains a single `unsigned int`, size 4, holding this value. + +## NET_PACKET_ID_REQUEST_CONTROLLER_DATA + +### Request [Protocol 0 Size: 0] [Protocol 1+ Size: 4] + +The client uses this ID to request the controller data for a given controller. For protocol 0, this request contains no data. For protocol 1 or higher, this request contains a single `unsigned int`, size 4, holding the highest protocol version supported by both the client and the server. The `pkt_dev_idx` of this request's header indicates which controller you are requesting data for. Upon connecting, the client should request controller data from 0 to [controller count], where [controller count] is the value from NET_PACKET_ID_REQUEST_CONTROLLER_COUNT. + +NOTE: Before sending this request, the client should request the protocol version from the server and determine the value to send, if any. If the server is using protocol version 0, even if the SDK implementation supports higher, send this packet with no data. + +### Response [Size: Variable] + +The server responds to this request with a large data block. The format of the block is shown below. Portions of this block are omitted if the requested protocol level is below the listed value. The receiver is expected to parse this data block using the same protocol version sent in the request (or protocol 0 if the request is sent with no data). + +| Size | Format | Name | Protocol Version | Description | +| ------------------- | ------------------------------------- | ------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------ | +| 4 | unsigned int | data_size | 0 | Size of all data in packet | +| 4 | int | type | 0 | RGBController type field value | +| 2 | unsigned short | name_len | 0 | Length of RGBController name field string, including null termination | +| name_len | char[name_len] | name | 0 | RGBController name field string value, including null termination | +| 2 | unsigned short | vendor_len | 1 | Length of RGBController vendor field string, including null termination | +| vendor_len | char[vendor_len] | vendor | 1 | RGBController vendor field string value, including null termination | +| 2 | unsigned short | description_len | 0 | Length of RGBController description field string, including null termination | +| description_len | char[description_len] | description | 0 | RGBController description field string value, including null termination | +| 2 | unsigned short | version_len | 0 | Length of RGBController version field string, including null termination | +| version_len | char[version_len] | version | 0 | RGBController version field string value, including null termination | +| 2 | unsigned short | serial_len | 0 | Length of RGBController serial field string, including null termination | +| serial_len | char[serial_len] | serial | 0 | RGBController serial field string value, including null termination | +| 2 | unsigned short | location_len | 0 | Length of RGBController location field string, including null termination | +| location_len | char[location_len] | location | 0 | RGBController location field string value, including null termination | +| 2 | unsigned short | num_modes | 0 | Number of modes in RGBController | +| 4 | int | active_mode | 0 | RGBController active_mode field value | +| Variable | Mode Data[num_modes] | modes | 0 | See [Mode Data](#mode-data) block format table. Repeat num_modes times | +| 2 | unsigned short | num_zones | 0 | Number of zones in RGBController | +| Variable | Zone Data[num_zones] | zones | 0 | See [Zone Data](#zone-data) block format table. Repeat num_zones times | +| 2 | unsigned short | num_leds | 0 | Number of LEDs in RGBController | +| Variable | LED Data[num_leds] | leds | 0 | See [LED Data](#led-data) block format table. Repeat num_leds times | +| 2 | unsigned short | num_colors | 0 | Number of colors in RGBController | +| 4 * num_colors | RGBColor[num_colors] | colors | 0 | RGBController colors field values | +| 2 | unsigned short | num_led_alt_names | 5 | Number of LED alternate name strings | +| Variable | LED Alternate Name[num_led_alt_names] | led_alt_names | 5 | See [LED Alternate Name Data](#led-alternate-names-data) block format table. Repeat num_led_alt_names times | +| 4 | unsigned int | flags | 5 | RGBController flags field value | + +## Mode Data + +The Mode Data block represents one entry in the `RGBController::modes` vector. Portions of this block are omitted if the requested protocol level is below the listed value. + +| Size | Format | Name | Protocol Version | Description | +| ------------------- | ------------------------- | ------------------- | ---------------- | ------------------------------------------------------ | +| 2 | unsigned short | mode_name_len | 0 | Length of mode name string, including null termination | +| mode_name_len | char[mode_name_len] | mode_name | 0 | Mode name string value, including null termination | +| 4 | int | mode_value | 0 | Mode value field value | +| 4 | unsigned int | mode_flags | 0 | Mode flags field value | +| 4 | unsigned int | mode_speed_min | 0 | Mode speed_min field value | +| 4 | unsigned int | mode_speed_max | 0 | Mode speed_max field value | +| 4 | unsigned int | mode_brightness_min | 3 | Mode brightness_min field value | +| 4 | unsigned int | mode_brightness_max | 3 | Mode brightness_max field value | +| 4 | unsigned int | mode_colors_min | 0 | Mode colors_min field value | +| 4 | unsigned int | mode_colors_max | 0 | Mode colors_max field value | +| 4 | unsigned int | mode_speed | 0 | Mode speed value | +| 4 | unsigned int | mode_brightness | 3 | Mode brightness value | +| 4 | unsigned int | mode_direction | 0 | Mode direction value | +| 4 | unsigned int | mode_color_mode | 0 | Mode color_mode value | +| 2 | unsigned short | mode_num_colors | 0 | Mode number of colors | +| 4 * mode_num_colors | RGBColor[mode_num_colors] | mode_colors | 0 | Mode color values | + +## Zone Data + +The Zone Data block represents one entry in the `RGBController::zones` vector. + +| Size | Format | Name | Protocol Version | Description | +| ---------------------- | --------------------------------- | ------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------ | +| 2 | unsigned short | zone_name_len | 0 | Length of zone name string, including null termination | +| zone_name_len | char[zone_name_len] | zone_name | 0 | Zone name string value, including null termination | +| 4 | int | zone_type | 0 | Zone type value | +| 4 | unsigned int | zone_leds_min | 0 | Zone leds_min value | +| 4 | unsigned int | zone_leds_max | 0 | Zone leds_max value | +| 4 | unsigned int | zone_leds_count | 0 | Zone leds_count value | +| 2 | unsigned short | zone_matrix_len | 0 | Zone matrix length if matrix_map exists: (matrix_map width * height * 4) + 8 OTHERWISE 0 if matrix_map NULL | +| 4* | unsigned int | zone_matrix_height | 0 | Zone matrix_map height (*only if matrix_map exists) | +| 4* | unsigned int | zone_matrix_width | 0 | Zone matrix_map width (*only if matrix_map exists) | +| (zone_matrix_len - 8)* | unsigned int[zone_matrix_len - 8] | zone_matrix_data | 0 | Zone matrix_map data (*only if matrix_map exists) | +| 2 | unsigned short | num_segments | 4 | Number of segments in zone | +| Variable | Segment Data[num_segments] | segments | 4 | See [Segment Data](#segment-data) block format table. Repeat num_segments times | +| 4 | unsigned int | zone_flags | 5 | Zone flags value | + +## Segment Data + +The Segment Data block represents one entry in the `RGBController::zones::segments` vector. This data block was introduced in protocol version 4. + +| Size | Format | Name | Protocol Version | Description | +| ---------------- | ---------------------- | ------------------ | ---------------- | --------------------------------------------------------- | +| 2 | unsigned short | segment_name_len | 4 | Length of segment name string, including null termination | +| segment_name_len | char[segment_name_len] | segment_name | 4 | Segment name string value, including null termination | +| 4 | int | segment_type | 4 | Segment type value | +| 4 | unsigned int | segment_start_idx | 4 | Segment start_idx value | +| 4 | unsigned int | segment_leds_count | 4 | Segment leds_count value | + +## LED Data + +The LED Data block represents one entry in the `RGBController::leds` vector. + +| Size | Format | Name | Protocol Version | Description | +| ------------------- | ------------------------- | ------------------- | ---------------- | ------------------------------------------------------ | +| 2 | unsigned short | led_name_len | 0 | Length of LED name string, including null termination | +| led_name_len | char[led_name_len] | led_name | 0 | LED name string value, including null termination | +| 4 | unsigned int | led_value | 0 | LED value field value | + +## LED Alternate Name Data + +The LED Alternate Name Data block represents one entry in the `RGBController::led_alt_names` vector. This data block was introduced in protocol version 5. + +| Size | Format | Name | Protocol Version | Description | +| ---------------- | ---------------------- | ---------------- | ---------------- | --------------------------------------------------------------- | +| 2 | unsigned short | led_alt_name_len | 5 | Length of LED alternate name string, including null termination | +| led_alt_name_len | char[led_alt_name_len] | led_alt_name | 5 | LED alternate name string value, including null termination | + +## NET_PACKET_ID_REQUEST_PROTOCOL_VERSION + +### Request [Size: 4] + +The client uses this ID to request the server's highest supported protocol version as well as to indicate to the server the client's highest supported protocol version. The request contains a single `unsigned int`, size 4, containing the client's highest supported protocol version. + +### Response [Size: 4] + +The server responds to this request with a single `unsigned int`, size 4, containing the server's highest supported protocol version. If the server is using protocol version 0, it will not send a response. If no response is received, assume the server's highest supported protocol version is version 0. + +## NET_PACKET_ID_SET_CLIENT_NAME + +### Client Only [Size: Variable] + +The client uses this ID to send the client's null-terminated name string to the server. The size of the packet is the size of the string including the null terminator. In C, this is strlen() + 1. There is no response from the server for this packet. + +## NET_PACKET_ID_DEVICE_LIST_UPDATED + +### Server Only [Size: 0] + +The server uses this ID to notify a client that the server's device list has been updated. Upon receiving this packet, clients should synchronize their local device lists with the server by requesting size and controller data again. This packet contains no data. + +## NET_PACKET_ID_REQUEST_RESCAN_DEVICES + +### Client Only [Size: 0] + +The client uses this ID to request the server rescan its devices. + +## NET_PACKET_ID_REQUEST_PROFILE_LIST + +### Request [Size: 0] + +The client uses this ID to request the server's profile list. The request contains no data. + +### Response [Size: Variable] + +The server responds to this request with a data block. The format of the block is shown below. + +| Size | Format | Name | Protocol Version | Description | +| -------- | -------------------------- | ------------ | ---------------- | -------------------------------------------------------------------------------- | +| 4 | unsigned int | data_size | 2 | Size of all data in packet | +| 2 | unsigned short | num_profiles | 2 | Number of profiles on server | +| Variable | Profile Data[num_profiles] | profiles | 2 | See [Profile Data](#profile-data) block format table. Repeat num_profiles times | + +## Profile Data + +The profile data block represents the information of one profile. This data block was introduced in protocol version 2. + +| Size | Format | Name | Protocol Version | Description | +| ---------------- | ---------------------- | ---------------- | ---------------- | --------------------------------------------------------- | +| 2 | unsigned short | profile_name_len | 2 | Length of profile name string, including null termination | +| profile_name_len | char[profile_name_len] | profile_name | 2 | Profile name string value, including null termination | + +## NET_PACKET_ID_REQUEST_SAVE_PROFILE + +### Client Only [Size: Variable] + +The client uses this ID to command the server to save the current configuration to a profile. It passes the name of the profile to save as a null-terminated string. The size of the packet is the size of the string including the null terminator. In C, this is strlen() + 1. There is no response from the server for this packet. + +## NET_PACKET_ID_REQUEST_LOAD_PROFILE + +### Client Only [Size: Variable] + +The client uses this ID to command the server to load the given profile. It passes the name of the profile to load as a null-terminated string. The size of the packet is the size of the string including the null terminator. In C, this is strlen() + 1. There is no response from the server for this packet. + +Calling this function will not actually update the controllers. Instead, the controller states will be updated from the profile on the server side. After sending this request, the client should re-request all controller states from the server so that the client controller states match the server states loaded from the profile. After requesting all of the controller data, the client shall call UpdateMode() on all controllers to apply the updated state. + +## NET_PACKET_ID_REQUEST_DELETE_PROFILE + +### Client Only [Size: Variable] + +The client uses this ID to command the server to delete the given profile. It passes the name of the profile to delete as a null-terminated string. The size of the packet is the size of the string including the null terminator. In C, this is strlen() + 1. There is no response from the server for this packet. + +## NET_PACKET_ID_REQUEST_PLUGIN_LIST + +### Request [Size: 0] + +The client uses this ID to request the server's plugin list. The request contains no data. + +### Response [Size: Variable] + +The server responds to this request with a data block. The format of the block is shown below. + +| Size | Format | Name | Protocol Version | Description | +| -------- | ------------------------ | ----------- | ---------------- | ----------------------------------------------------------------------------- | +| 4 | unsigned int | data_size | 4 | Size of all data in packet | +| 2 | unsigned short | num_plugins | 4 | Number of plugins on server | +| Variable | Plugin Data[num_plugins] | plugins | 4 | See [Plugin Data](#plugin-data) block format table. Repeat num_plugins times | + +## Plugin Data + +The plugin data block represents the information of one plugin. This data block was introduced in protocol version 4. + +| Size | Format | Name | Protocol Version | Description | +| ---------------------- | ---------------------------- | ----------------------- | ---------------- | --------------------------------------------------------------- | +| 2 | unsigned short | plugin_name_len | 4 | Length of plugin name string, including null termination | +| plugin_name_len | char[plugin_name_len] | plugin_name | 4 | Plugin name string value, including null termination | +| 2 | unsigned short | plugin_description_len | 4 | Length of plugin description string, including null termination | +| plugin_description_len | char[plugin_description_len] | plugin_description | 4 | Plugin description string value, including null termination | +| 2 | unsigned short | plugin_version_len | 4 | Length of plugin version string, including null termination | +| plugin_version_len | char[plugin_version_len] | plugin_version | 4 | Plugin version string value, including null termination | +| 4 | unsigned int | plugin_index | 4 | Plugin index value | +| 4 | unsigned int | plugin_protocol_version | 4 | Plugin protocol version value | + +## NET_PACKET_ID_PLUGIN_SPECIFIC + +### Request [Size: Variable] + +This packet is used to send data to a plugin. The `pkt_dev_idx` field in the header specifies which plugin to send to and corresponds to the `plugin_index` field in the plugin list. The first 4 bytes of the data is the plugin packet type, the rest of the packet is plugin-specific. + +List of plugins that currently support this: + +- [Effects plugin](https://gitlab.com/OpenRGBDevelopers/OpenRGBEffectsPlugin/-/blob/master/SDK.md) + +### Response [Size: Variable] + +The response is optionally generated by the plugin. The data in the packet is plugin-specific. + +## NET_PACKET_ID_RGBCONTROLLER_RESIZEZONE + +### Client Only [Size: 8] + +The client uses this ID to call the ResizeZone() function of an RGBController device. The packet data contains a data block. The format of the block is shown below. The `pkt_dev_idx` of this request's header indicates which controller you are calling ResizeZone() on. + +| Size | Format | Name | Description | +| ---- | ------ | -------- | -------------------- | +| 4 | int | zone_idx | Zone index to resize | +| 4 | int | new_size | New size of the zone | + +## NET_PACKET_ID_RGBCONTROLLER_CLEARSEGMENTS + +### Client Only [Size: 4] + +The client uses this ID to call the ClearSegments() function of an RGBController device. The packet contains the index of the zone to clear segments on, type int (size 4). The `pkt_dev_idx` of this request's header indicates which controller you are calling ClearSegments() on. + +## NET_PACKET_ID_RGBCONTROLLER_ADDSEGMENT + +### Client Only [Size: Variable] + +The client uses this ID to call the AddSegment() function of an RGBController device. The packet contains a data block. The format of the block is shown below. The `pkt_dev_idx` of this request's header indicates which controller you are calling AddSegment() on. + +| Size | Format | Name | Description | +| ---------------- | ---------------------- | ---------------- | --------------------------------------------------------- | +| 4 | unsigned int | data_size | Size of all data in packet | +| 4 | unsigned int | zone_idx | Zone index to add segment to | +| Variable | Segment Data | segment | See [Segment Data](#segment-data) block format table. | + +## NET_PACKET_ID_RGBCONTROLLER_UPDATELEDS + +### Client Only [Size: Variable] + +The client uses this ID to call the UpdateLEDs() function of an RGBController device. The packet data contains a data block. The format of the block is shown below. The `pkt_dev_idx` of this request's header indicates which controller you are calling UpdateLEDs() on. + +| Size | Format | Name | Description | +| -------------- | -------------------- | ---------- | ----------------------------------- | +| 4 | unsigned int | data_size | Size of all data in packet | +| 2 | unsigned short | num_colors | Number of color values in packet | +| 4 * num_colors | RGBColor[num_colors] | led_color | Color values for each LED in device | + +## NET_PACKET_ID_RGBCONTROLLER_UPDATEZONELEDS + +### Client Only [Size: Variable] + +The client uses this ID to call the UpdateZoneLEDs() function of an RGBController device. The packet data contains a data block. The format of the data block is shown below. The `pkt_dev_idx` of this request's header indicates which controller you are calling UpdateZoneLEDs() on. + +| Size | Format | Name | Description | +| -------------- | -------------------- | ---------- | --------------------------------- | +| 4 | unsigned int | data_size | Size of all data in packet | +| 4 | unsigned int | zone_idx | Zone index to update | +| 2 | unsigned short | num_colors | Number of color values in packet | +| 4 * num_colors | RGBColor[num_colors] | led_color | Color values for each LED in zone | + +## NET_PACKET_ID_RGBCONTROLLER_UPDATESINGLELED + +### Client Only [Size: 8] + +The client uses this ID to call the UpdateSingleLED() function of an RGBController device. The packet data contains a data block. The format of the data block is shown below. The `pkt_dev_idx` of this request's header indicates which controller you are calling UpdateSingleLED() on. + +| Size | Format | Name | Description | +| ---- | -------- | --------- | ----------- | +| 4 | int | led_idx | LED index | +| 4 | RGBColor | led_color | LED color | + +## NET_PACKET_ID_RGBCONTROLLER_SETCUSTOMMODE + +### Client Only [Size: 0] + +The client uses this ID to call the SetCustomMode() function of an RGBController device. The packet contains no data. The `pkt_dev_idx` of this request's header indicates which controller you are calling SetCustomMode() on. + +## NET_PACKET_ID_RGBCONTROLLER_UPDATEMODE + +### Client Only [Size: Variable] + +The client uses this ID to call the UpdateMode() function of an RGBController device. The packet contains a data block. The format of the data block is shown below. The `pkt_dev_idx` of this request's header indicates which controller you are calling UpdateMode() on. + +| Size | Format | Name | Protocol Version | Description | +| ------------------- | ------------------------- | ------------------- | ---------------- | ------------------------------------------------------ | +| 4 | unsigned int | data_size | 0 | Size of all data in packet | +| 4 | int | mode_idx | 0 | Mode index to update | +| Variable | Mode Data | mode | 0 | See [Mode Data](#mode-data) block format table. | + +## NET_PACKET_ID_RGBCONTROLLER_SAVEMODE + +### Client Only [Size: Variable] + +The client uses this ID to call the SaveMode() function of an RGBController device. The packet contains a data block. The format of the data block is the same as for [NET_PACKET_ID_RGBCONTROLLER_UPDATEMODE](#net_packet_id_rgbcontroller_updatemode). The `pkt_dev_idx` of this request's header indicates which controller you are calling SaveMode() on. diff --git a/Documentation/RGBControllerAPI.md b/Documentation/RGBControllerAPI.md new file mode 100644 index 00000000..e84d666c --- /dev/null +++ b/Documentation/RGBControllerAPI.md @@ -0,0 +1,325 @@ +# RGBController API + +Device support in OpenRGB can be broken down into three major components. + +* Controller +* Detector +* RGBController + +## **Controller** + +A device's Controller class is a free-form class that provides whatever functionality is necessary to communicate with a device. This class should implement functions to send control packets to a device and receive information packets from a device. It should provide the capability to set device colors and modes. The Controller header file should provide defined constants for mode, speed, and other control values specific to the device's protocol. If possible, this class should provide the capability to retrieve firmware version and serial number information from the device. This class can also provide additional device protocol functionality even if it goes unused in OpenRGB currently. For instance, you may provide functions for controlling mouse DPI, polling rate, fan speed, or any other device-specific capability you want. If OpenRGB ever implements these extra functions in the future, having them implemented already in the Controller will make that easier. + +The Controller class files are kept in the Controllers/ folder. + +## **Detector** + +A device's Detector function scans the system's interfaces to see if a particular device (Controller/RGBController) exists. Several types of detectors exist and are listed below. Each detector type is passed different arguments based on the interface it is detecting. The REGISTER_DETECTOR macros are used to register a detector function with the ResourceManager which is responsible for calling detector functions at detection time. Detector functions are then responsible for creating instances of Controllers and RGBControllers and registering them with the ResourceManager by calling the `ResourceManager::RegisterRGBController` interface. + +HID Detectors + +HID (Human Interface Device) is the most common interface for USB devices with RGB capabilities, especially for peripherals such as keyboards and mice. While it is usually used over USB, HID can also be used over Bluetooth. The `hidapi` library is used for interfacing with HID devices. The following detector formats can be registered: + +```C++ +REGISTER_HID_DETECTOR("HID Detector Name", DetectHIDDevicesFunction, HID_VID, HID_PID); +REGISTER_HID_DETECTOR_I("HID Detector Name", DetectHIDDevicesFunction, HID_VID, HID_PID, HID_INTERFACE); +REGISTER_HID_DETECTOR_IP("HID Detector Name", DetectHIDDevicesFunction, HID_VID, HID_PID, HID_INTERFACE, HID_PAGE); +REGISTER_HID_DETECTOR_IPU("HID Detector Name", DetectHIDDevicesFunction, HID_VID, HID_PID, HID_INTERFACE, HID_PAGE, HID_USAGE); +REGISTER_HID_DETECTOR_P("HID Detector Name", DetectHIDDevicesFunction, HID_VID, HID_PID, HID_PAGE); +REGISTER_HID_DETECTOR_PU("HID Detector Name", DetectHIDDevicesFunction, HID_VID, HID_PID, HID_PAGE, HID_USAGE); +``` + +The I/IP/IPU/P/PU variants add filtering for specific HID interfaces, pages, and usages as many HID devices expose multiple interfaces and not all are used for RGB control. + +I2C/SMBus Detectors + +I2C (Inter-Integrated Circuit), or SMBus (System Management Bus, a compatible subset of I2C), is the second most common interface used by RGB devices and is used for on-board RGB on certrain motherboards, most graphics cards, and all RAM modules. Each I2C device has a 7-bit address. As I2C does not offer a standardized means of identifying a device on the bus, we have several different options for detecting I2C devices that can narrow down the search to a specific I2C bus. + +```C++ +REGISTER_I2C_DETECTOR("I2C Detector Name", DetectI2CDevicesFunction); +REGISTER_I2C_DIMM_DETECTOR("I2C Detector Name", DetectI2CDevicesFunction, JEDEC_ID, DIMM_TYPE); +REGISTER_I2C_PCI_DETECTOR("I2C Detector Name", DetectI2CDevicesFunction, PCI_VEN, PCI_DEV, PCI_SUBVEN, PCI_SUBDEV, I2C_ADDR); +``` + +The standard version of the I2C detector calls the detector function with a vector of all available I2C buses. The detector can then perform any chip specific detection necessary to determine if the device exists on any of the given buses. Only use this version of the detector if the DIMM or PCI variants are not suitable for your device. There are additional macros that can be used to narrow down I2C bus detection such as `IF_MOBO_SMBUS` for motherboard buses and `IF_DRAM_SMBUS` for DRAM buses. + +The DIMM version of the detector can be used to filter for specific DRAM modules using SPD information. Only the I2C bus for the DRAM will be provided and the detector will only be called if the JEDEC ID and DIMM type match. + +The PCI version of the detector can be used to filter for I2C devices on specific PCI cards, usually graphics cards. The detector will only be called for I2C buses with matching PCI IDs. The detector can also provide a specific address, though it is possible for the detector function to ignore this address if more complex address determination is needed. + +Generic Detectors + +The generic detector type is used for any device that doesn't fit into one of the previous detection types. This detector is frequently used for manually configured devices such as network and serial port devices. It is also used for USB devices that cannot be accessed via `hidapi` or serial and instead requiring direct USB access via `libusb`. + +```C++ +REGISTER_DETECTOR("Generic Detector Name", DetectDevicesFunction); +``` + +The Detector files are kept in the Controllers/ folder. + +## **RGBController** + +OpenRGB uses an internal API called RGBController to standardize the interface to RGB devices from multiple vendors and categories. This API uses vectors to describe each device. This API is implemented as an RGBController class that is inherited by each implementation, for example the RGBController_CorsairPeripheral is defined like so: + +```C++ +#include "RGBController.h" + +class RGBController_CorsairPeripheral : public RGBController +{ +``` + +The RGBController files for a controller implementation are kept in the Controllers/ folder alongside the Controller and Detector files. + +The RGBController class specification contains the following: + +* Device Name +* Device Vendor +* Device Description +* Device Version +* Device Serial +* Device Location +* Vector of LEDs +* Vector of Zones +* Vector of Modes +* Vector of Colors (32-bit 0x00BBGGRR format) +* Device Type (enum) +* Active mode index +* Vector of LED Alternate Names +* Controller Flags + +### Device Types + +| Value | Description | +| ----- | ------------- | +| 0 | Motherboard | +| 1 | DRAM | +| 2 | GPU | +| 3 | Cooler | +| 4 | LED Strip | +| 5 | Keyboard | +| 6 | Mouse | +| 7 | Mousemat | +| 8 | Headset | +| 9 | Headset Stand | +| 10 | Gamepad | +| 11 | Light | +| 12 | Speaker | +| 13 | Virtual | +| 14 | Storage | +| 15 | Case | +| 16 | Microphone | +| 17 | Accessory | +| 18 | Keypad | +| 19 | Laptop | +| 20 | Monitor | +| 21 | Unknown | + +Additional device types may be added in the future. They are added after the last known device type. Anything out of range should be considered Unknown. + +### Controller Flags + +| Controller Flags Bit | Name | Description | +| -------------------- | ------- | --------------------------------------------------- | +| 0 | Local | Controller is provided by this OpenRGB instance | +| 1 | Remote | Controller is provided by a remote OpenRGB instance | +| 2 | Virtual | Controller is virtual (not a physical device) | + +### LED Alternate Names + +The LED Altrernate Names vector can override the base name of an LED. The intended use case for this field is providing regional key names for non-English keyboard layouts. The base key names should always be provided in English QWERYY layout for positional mapping to work on certain SDK applications, so the alternate names field can override the base name to provide the correct key name for the localized layout without disrupting SDK application mapping. If not overriding any LED names, this vector can be left empty. If only overriding certain LED names, those not being overridden can be empty strings. If used, the length of this vector must equal the length of the LEDs vector. + +## LEDs + +The LED structure contains information about an LED. + +* LED Name +* LED Value + +The Value has no defined functionality in the RGBController API and is provided for implementation-specific use. You can use this field to associate implementation-specific data with an LED. + +## Zones + +The Zone structure contains information about a zone. A zone is a logical grouping of LEDs defined by the RGBController implementation. LEDs in a zone must be contiguous in the RGBController's LEDs/Colors vectors. + +* Zone Name +* Zone Type +* LED pointer +* Color pointer +* Start Index +* LED Count +* Minimum number of LEDs +* Maximum number of LEDs +* Matrix map pointer +* Vector of segments +* Zone Flags + +The LED pointer and Color pointer point to the first LED/Color in the RGBController's LEDs/Colors vector associated with this zone. The Start Index is the index to the same LED/Color in the vectors. + +The LED count is the number of LEDs in the zone. For zones with a fixed number of LEDs, the count, min, and max values should all be equal. For zones with a user-adjustable number of LEDs, the count should be between the min and max values, inclusively. User-adjustable zones are most commonly used to represent addressable RGB (ARGB) controllers as the number of LEDs depends on what strips/devices are attached to the ARGB headers. The ResizeZone function in the RGBController API is used to resize the number of LEDs in the zone. The initial value should be zero for ARGB zones if the device does not provide a means to automatically determint the number of connected LEDs. + +### Zone Types + +The zone type enum defines the zone type. This describes the physical layout of the zone and can be used by software to generate appropriate effects for the zone. + +| Zone Type Value | Description | +| --------------- | ----------- | +| 0 | Single | +| 1 | Linear (1D) | +| 2 | Matrix (2D) | + +### Matrix Map + +Each zone has a matrix map pointer which allows an optional matrix map to be associated with the zone. The matrix map is used to provide positioning information about LEDs in a 2D grid. If a matrix map is not provided for a zone, the zone's matrix map pointer must be set to NULL. + +A matrix map has the following: + +* Height +* Width +* Map data pointer + +The height and width determine the size of the map data. The map data pointer should point to a data block of (Height * Width) unsigned 32-bit integers. This data can be accessed as if it were a Map[Y][X] 2D array. The values of the map are LED index values in the zone (so offset by Start Index from the RGBController's LEDs vector). If a spot in the matrix is unused and does not map to an LED, it should be set to 0xFFFFFFFF. + +### Segments + +Each Zone contains a vector of Segments. Segments can be used to divide a physical zone (such as an ARGB header) into multiple logical sub-zones, or segments. This is mainly used for ARGB zones with multiple components daisy-chained together. For example, segments can be used to group multiple rings on an ARGB fan or multiple daisy-chained fans connected to one header. If the device is capable of automatically detecting multiple components connected to a single output, the RGBController may create segments automatically during zone creation. Otherwise, leaving this vector empty will indicate that the zone contains no segments, though resizable zones allow the user to define their own segments. + +A segment contains the following: + +* Segment Name +* Segment Type (See Zone Type values) +* Start Index +* LED Count + +The Start Index is the index within the Zone where the Segment starts. The LED Count is the number of LEDs in the Segment. Care should be taken to ensure that the total number of LEDs across all segments equals the number of LEDs in the Zone and the start indices do not overlap. + +### Zone Flags + +The Zone Flags field is a bitfield with informational flags related to the Zone. + +| Zone Flags Bit | Name | Description | +| -------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| 0 | Resize Effects Only | This zone is resizable, but the size is only used for effects modes. The zone is treated as a single LED in the Colors vector for per-LED modes | + +## Modes + +Modes represent internal effects and have a name field that describes the effect. The mode's index in the vector is its ID. The Active Mode variable in the RGBController class specifies which mode is currently selected. A mode contains the following: + +* Mode Name +* Mode Value +* Mode Flags +* Minimum Speed +* Maximum Speed +* Minimum number of colors +* Maximum number of colors +* Speed Value +* Direction +* Color Mode +* Colors Vector + +The mode value is field is provided to hold an implementation-defined mode value. This is usually the mode's value in the hardware protocol. + +The mode flags field is a bitfield that contains information about what features a mode has. + +| Mode Flags Bit | Description | +| -------------- | ------------------------------------------------ | +| 0 | Mode has speed parameter | +| 1 | Mode has left/right direction parameter | +| 2 | Mode has up/down direction parameter | +| 3 | Mode has horizontal/vertical direction parameter | +| 4 | Mode has brightness parameter | +| 5 | Mode has per-LED color settings | +| 6 | Mode has mode specific color settings | +| 7 | Mode has random color option | + +The mode minimum and maximum speed fields should be set to the implementation-specific minimum and maximum speed values for the given mode if the mode supports speed control. The mode speed value field will be set between the minimum and maximum value, inclusively. The minimum speed may be a greater numerical value than the maximum speed if your device's speed adjustment is inverted (usually because the device takes a delay period rather than a speed value). + +The mode minimum and maximum number of colors fields should be used if the mode supports mode-specific color settings. These determine the size range of the mode's Colors vector. If the mode has a fixed number of colors, the minimum and maximum should be equal. Mode-specific colors are used when a mode has one or more configurable colors but these colors do not apply directly to individual LEDs. Example would be a breathing mode that cycles between one or more colors each breath pulse. A mode may have multiple color options available, for instance a breathing mode that can either use one or more defined colors or just cycle through random colors. The available color modes for a given mode are set with the flags. The selected color mode is set using the color mode field, which can be one of the following values. + +| Color Mode Value | Description | +| ---------------- | ------------------------------------------------------------------------------------------------- | +| 0 | None - this mode does not have configurable colors | +| 1 | Per-LED - this mode uses the RGBController's colors vector to set each LED to its specified color | +| 2 | Mode Specific - this mode has one or more configurable colors, but not individual LED control | +| 3 | Random - this mode can be switched to a random or cycling color palette | + +## Functions + +### `std::string GetName()` + +Returns the `name` string of the device. + +### `std::string GetVendor()` + +Returns the `vendor` string of the device. + +### `std::string GetDescription()` + +Returns the `description` string of the device. + +### `std::string GetVersion()` + +Returns the `version` string of the device. + +### `std::string GetSerial()` + +Returns the `serial` string of the device. + +### `std::string GetLocation()` + +Returns the `location` string of the device. + +### `std::string GetModeName(int mode)` + +Returns the `name` string of the given mode in the `modes` vector. + +### `std::string GetZoneName(int zone)` + +Returns the `name` string of the given zone in the `zones` vector. + +### `std::string GetLEDName(int led)` + +Returns the `name` string of the given LED in the `leds` vector. + +### `RGBColor GetLED(unsigned int led)` + +Returns the color value of the given LED in the `colors` vector. + +### `void SetLED(unsigned int led, RGBColor color)` + +Sets the color value of the given LED in the `colors` vector. + +### `void SetAllLEDs(RGBColor color)` + +Sets the color value of all LEDs in the `colors` vector. + +### `void SetAllZoneLEDs(int zone, RGBColor color)` + +Sets the color value of all LEDs in the given zone in the `colors` vector. + +### `int GetMode()` + +Returns the active mode index of the device. The returned int should line up with the `modes` vector. + +### `void SetMode(int mode)` + +Sets the active mode index of the device. The mode should be the index in the `modes` vector of the mode you wish to set. + +### `void SetCustomMode()` + +When called, the device should be put into its software-controlled mode. This differs between devices, but generally devices have a direct control or static effect mode. Ideally, this mode should not save to the device's internal Flash. This function sets up a device for software effect control. + +### `void UpdateLEDs()` + +Update all LEDs based on the `colors` vector. + +### `void UpdateZoneLEDs(int zone)` + +Update all LEDs in the given zone based on the `colors` vector. + +### `void UpdateSingleLED(int led)` + +Update a single LED based on the `colors` vector. + +### `void UpdateMode()` + +Update the mode based on the active mode index and the `modes` vector. diff --git a/Documentation/SMBusAccess.md b/Documentation/SMBusAccess.md new file mode 100644 index 00000000..f89b2f1e --- /dev/null +++ b/Documentation/SMBusAccess.md @@ -0,0 +1,49 @@ +# SMBus Access + +This document details the process to set up SMBus/I2C access on supported operating systems. + +SMBus, or [System Management Bus](https://en.wikipedia.org/wiki/System_Management_Bus), is a low-level interface present on most PC motherboards. Some RGB control devices are attached via SMBus. These include all DDR4 and DDR5 RAM modules with integrated RGB lighting as well as the onboard lighting on several motherboards, mostly from the X370/Z270 and X470/Z370 generations. + +If you are not using RGB RAM and you are not using a motherboard from the X370/Z270 or X470/Z370 generation you can skip these steps and ignore the SMBus warning if it appears. + +SMBus is generally not meant to be accessed by user applications, but RGB software creates an exception to this rule. This means that some steps may be necessary to allow OpenRGB permission to access the SMBus interface. These steps are listed below. + +## Windows + + * On Windows, OpenRGB uses the [WinRing0](https://github.com/GermanAizek/WinRing0) driver to access the SMBus interface. + * **You must run the application as Administrator the first time to allow WinRing0 to set up. It can be run as a normal user afterwards** + * Early versions of OpenRGB used [InpOut32](https://www.highrez.co.uk/downloads/inpout32/). This is no longer needed and should be removed to avoid warnings by some anti-cheat software. You can uninstall Inpout32 by following the instructions [here](https://gitlab.com/CalcProgrammer1/OpenRGB/-/issues/669#note_461054255). + +## Linux + + 1. Install the `i2c-tools` package. + 2. Load the i2c-dev module: `sudo modprobe i2c-dev` + 3. Load the i2c driver for your chipset: + * Intel + * `sudo modprobe i2c-i801` + * AMD + * `sudo modprobe i2c-piix4` + * Nuvoton + * This interface is used alongside `i2c-i801` on some older ASUS Intel motherboards for the on-board lighting. + * `sudo modprobe i2c-nct6793` + * Note: The i2c-nct6793 driver must be installed separately, see [i2c-nct6793-dkms](https://gitlab.com/CalcProgrammer1/i2c-nct6793-dkms) + + * If you want the i2c modules to load automatically at boot, run the following: + 1. `sudo touch /etc/modules-load.d/i2c.conf` + 2. `sudo sh -c 'echo "i2c-dev" >> /etc/modules-load.d/i2c.conf'` + 3. Run the following based on which i2c drivers you loaded in the previous section: + * `sudo sh -c 'echo "i2c-i801" >> /etc/modules-load.d/i2c.conf'` + * `sudo sh -c 'echo "i2c-piix4" >> /etc/modules-load.d/i2c.conf'` + + * You will have to enable user access to the i2c devices if you don't run OpenRGB as root. + 1. List all SMBus controllers: `sudo i2cdetect -l` + 2. Note the number(s) for piix4 or i801 controllers. + 3. Give user access to those controllers. If you have not installed OpenRGB from a distribution package then most likely you need to install the udev rules manually. + + * Some Gigabyte/Aorus motherboards have an ACPI conflict with the SMBus controller. You can bypass this conflict by adding the `acpi_enforce_resources=lax` kernel parameter to your kernel command line. See the [Kernel Parameters](Documentation/KernelParameters.md) page for more information. + + * The [spd5118 kernel driver](https://docs.kernel.org/hwmon/spd5118.html) can claim certain I2C addresses for Kingston Fury DDR5 memory and thus prevent other kernel modules from accessing them. This is the case if the `i2cdetect` command prints the character string `UU` on the I2C bus responsible for the DRAM. A solution to this problem is to unload the `spd5118` kernel driver using `rmmod spd5118`. + +## MacOS + + * For Intel devices using a controller in the i801 family you have to download and install the [macUSPCIO driver](https://github.com/ShadyNawara/macUSPCIO/releases) diff --git a/Documentation/USBAccess.md b/Documentation/USBAccess.md new file mode 100644 index 00000000..43165a55 --- /dev/null +++ b/Documentation/USBAccess.md @@ -0,0 +1,23 @@ +# USB Access + +This document details the process to set up USB access on supported operating systems. + +USB, or [Universal Serial Bus](https://en.wikipedia.org/wiki/USB) is the most common interface used to connect RGB devices to a PC. It can be used both externally, where a device has a cable which plugs into a USB port or motherboard header, or internally, where a device such as an RGB controller chip built into a motherboard is wired directly to the processor or chipset's USB interface. + +USB access permissions vary based on the type of device and the operating system. Some steps may be necessary to allow OpenRGB permission to access these devices. + +## Windows + + * Windows should not need any special setup to access USB devices. + * If a device does not get detected, try running OpenRGB as Administrator. + * Early versions of OpenRGB used the WinUSB driver, installed using Zadig. This is no longer required, and you need to uninstall the WinUSB driver if you previously installed it. You can uninstall the WinUSB driver by following [this guide](https://gitlab.com/CalcProgrammer1/OpenRGB/-/wikis/Frequently-Asked-Questions#i-installed-the-winusb-driver-for-a-device-and-i-wish-to-uninstall-it). + +## Linux + + * USB devices require [udev rules](/Documentation/UdevRules.md) to access as a normal user. + * Alternatively you can run OpenRGB as root to detect all USB devices. (Not recommended) + * USB based Gigabyte AORUS motherboards may also have an ACPI conflict. Please [add a kernel parameter](#kernel-parameters) to resolve this conflict. + +## MacOS + + * USB devices may require the Input Monitoring permission. You can add OpenRGB in System Preferences > Security & Privacy > Privacy. diff --git a/Documentation/UdevRules.md b/Documentation/UdevRules.md new file mode 100644 index 00000000..d6360486 --- /dev/null +++ b/Documentation/UdevRules.md @@ -0,0 +1,16 @@ +# Udev Rules + +On Linux, OpenRGB provides a udev rules file to configure access permissions to supported devices. + +If you install OpenRGB through a distribution-specific package, whether provided by your distribution's official repositories, from packages downloaded from OpenRGB's website or GitLab CI, or from building packages yourself, the udev rules should be installed as part of that package. You should not need to manually install them. + +If you are using OpenRGB compiled from source (not as part of a package), using OpenRGB as an AppImage, or using OpenRGB from Flatpak, you will need to install the udev rules manually. + +## Installation + + * If you have installed OpenRGB from a package then latest udev rules are installed locally at `/usr/lib/udev/rules.d/60-openrgb.rules` + * Udev rules are built from the source at compile time. When building locally they are installed with the `make install` step to `/usr/lib/udev/rules.d/60-openrgb.rules` + * If you need to install the udev rules file manually you can also download the [latest compiled udev rules](https://gitlab.com/CalcProgrammer1/OpenRGB/-/jobs/artifacts/master/raw/60-openrgb.rules?job=Linux+64+AppImage&inline=false) from Gitlab. + - Copy this 60-openrgb.rules file to `/usr/lib/udev/rules.d/` + - Then reload rules with `sudo udevadm control --reload-rules && sudo udevadm trigger` + * There is also a [udev rules installation script available at openrgb.org](https://openrgb.org/udev.html). diff --git a/KeyboardLayoutManager/KeyboardLayoutManager.cpp b/KeyboardLayoutManager/KeyboardLayoutManager.cpp index 94b6ca03..06a5071f 100644 --- a/KeyboardLayoutManager/KeyboardLayoutManager.cpp +++ b/KeyboardLayoutManager/KeyboardLayoutManager.cpp @@ -1,11 +1,13 @@ -/*---------------------------------------------------------------------*\ -| KeyboardLayoutManager.cpp | -| | -| Helper library to produce keyboard layouts | -| | -| Chris M (Dr_No) 04 Feb 2023 | -| | -\*---------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| KeyboardLayoutManager.cpp | +| | +| Helper library to produce keyboard layouts | +| | +| Chris M (Dr_No) 04 Feb 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "LogManager.h" #include "KeyboardLayoutManager.h" @@ -54,172 +56,173 @@ const char* LOG_MSG_MISSING_OPCODE = "[%s] Error: Opcode %d not found for % static const std::vector keyboard_zone_main = { - /*---------------------------------------------------------------------------------------------------------*\ - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 1, 0, 0, KEY_EN_BACK_TICK, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 1, 0, KEY_EN_1, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 2, 0, KEY_EN_2, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 3, 0, KEY_EN_3, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 4, 0, KEY_EN_4, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 5, 0, KEY_EN_5, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 6, 0, KEY_EN_6, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 7, 0, KEY_EN_7, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 8, 0, KEY_EN_8, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 9, 0, KEY_EN_9, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 10, 0, KEY_EN_0, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 11, 0, KEY_EN_MINUS, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 12, 0, KEY_EN_EQUALS, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 13, 0, KEY_EN_BACKSPACE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 0, 0, KEY_EN_TAB, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 1, 0, KEY_EN_Q, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 2, 0, KEY_EN_W, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 3, 0, KEY_EN_E, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 4, 0, KEY_EN_R, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 5, 0, KEY_EN_T, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 6, 0, KEY_EN_Y, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 7, 0, KEY_EN_U, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 8, 0, KEY_EN_I, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 9, 0, KEY_EN_O, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 10, 0, KEY_EN_P, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 11, 0, KEY_EN_LEFT_BRACKET, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 12, 0, KEY_EN_RIGHT_BRACKET, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 13, 0, KEY_EN_ANSI_BACK_SLASH, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 0, 0, KEY_EN_CAPS_LOCK, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 1, 0, KEY_EN_A, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 2, 0, KEY_EN_S, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 3, 0, KEY_EN_D, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 4, 0, KEY_EN_F, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 5, 0, KEY_EN_G, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 6, 0, KEY_EN_H, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 7, 0, KEY_EN_J, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 8, 0, KEY_EN_K, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 9, 0, KEY_EN_L, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 10, 0, KEY_EN_SEMICOLON, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 11, 0, KEY_EN_QUOTE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 12, 0, KEY_EN_POUND, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, - { 0, 3, 13, 0, KEY_EN_ANSI_ENTER, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 0, 0, KEY_EN_LEFT_SHIFT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 1, 0, KEY_EN_ISO_BACK_SLASH, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 2, 0, KEY_EN_Z, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 3, 0, KEY_EN_X, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 4, 0, KEY_EN_C, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 5, 0, KEY_EN_V, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 6, 0, KEY_EN_B, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 7, 0, KEY_EN_N, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 8, 0, KEY_EN_M, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 9, 0, KEY_EN_COMMA, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 10, 0, KEY_EN_PERIOD, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 11, 0, KEY_EN_FORWARD_SLASH, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 13, 0, KEY_EN_RIGHT_SHIFT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 0, 0, KEY_EN_LEFT_CONTROL, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 1, 0, KEY_EN_LEFT_WINDOWS, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 2, 0, KEY_EN_LEFT_ALT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 6, 0, KEY_EN_SPACE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 10, 0, KEY_EN_RIGHT_ALT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 11, 0, KEY_EN_RIGHT_FUNCTION, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 12, 0, KEY_EN_MENU, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 13, 0, KEY_EN_RIGHT_CONTROL, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + /*-----------------------------------------------------------------------------------------------------------------------------*\ + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-----------------------------------------------------------------------------------------------------------------------------*/ + { 0, 1, 0, 0, KEY_EN_BACK_TICK, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 1, 0, KEY_EN_1, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 2, 0, KEY_EN_2, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 3, 0, KEY_EN_3, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 4, 0, KEY_EN_4, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 5, 0, KEY_EN_5, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 6, 0, KEY_EN_6, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 7, 0, KEY_EN_7, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 8, 0, KEY_EN_8, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 9, 0, KEY_EN_9, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 10, 0, KEY_EN_0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 11, 0, KEY_EN_MINUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 12, 0, KEY_EN_EQUALS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 13, 0, KEY_EN_BACKSPACE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 0, 0, KEY_EN_TAB, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 1, 0, KEY_EN_Q, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 2, 0, KEY_EN_W, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 3, 0, KEY_EN_E, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 4, 0, KEY_EN_R, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 5, 0, KEY_EN_T, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 6, 0, KEY_EN_Y, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 7, 0, KEY_EN_U, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 8, 0, KEY_EN_I, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 9, 0, KEY_EN_O, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 10, 0, KEY_EN_P, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 11, 0, KEY_EN_LEFT_BRACKET, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 12, 0, KEY_EN_RIGHT_BRACKET, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 13, 0, KEY_EN_ANSI_BACK_SLASH, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 0, 0, KEY_EN_CAPS_LOCK, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 1, 0, KEY_EN_A, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 2, 0, KEY_EN_S, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 3, 0, KEY_EN_D, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 4, 0, KEY_EN_F, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 5, 0, KEY_EN_G, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 6, 0, KEY_EN_H, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 7, 0, KEY_EN_J, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 8, 0, KEY_EN_K, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 9, 0, KEY_EN_L, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 10, 0, KEY_EN_SEMICOLON, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 11, 0, KEY_EN_QUOTE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 12, 0, KEY_EN_POUND, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT }, + { 0, 3, 13, 0, KEY_EN_ANSI_ENTER, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 0, 0, KEY_EN_LEFT_SHIFT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 1, 0, KEY_EN_ISO_BACK_SLASH, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 2, 0, KEY_EN_Z, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 3, 0, KEY_EN_X, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 4, 0, KEY_EN_C, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 5, 0, KEY_EN_V, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 6, 0, KEY_EN_B, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 7, 0, KEY_EN_N, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 8, 0, KEY_EN_M, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 9, 0, KEY_EN_COMMA, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 10, 0, KEY_EN_PERIOD, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 11, 0, KEY_EN_FORWARD_SLASH, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 13, 0, KEY_EN_RIGHT_SHIFT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 0, 0, KEY_EN_LEFT_CONTROL, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 1, 0, KEY_EN_LEFT_WINDOWS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 2, 0, KEY_EN_LEFT_ALT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 6, 0, KEY_EN_SPACE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 10, 0, KEY_EN_RIGHT_ALT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 11, 0, KEY_EN_RIGHT_FUNCTION, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 12, 0, KEY_EN_MENU, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 13, 0, KEY_EN_RIGHT_CONTROL, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, }; static const std::vector keyboard_zone_fn_row = { - /*---------------------------------------------------------------------------------------------------------*\ - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 0, 0, KEY_EN_ESCAPE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 2, 0, KEY_EN_F1, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 3, 0, KEY_EN_F2, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 4, 0, KEY_EN_F3, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 5, 0, KEY_EN_F4, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 6, 0, KEY_EN_F5, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 7, 0, KEY_EN_F6, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 8, 0, KEY_EN_F7, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 9, 0, KEY_EN_F8, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 10, 0, KEY_EN_F9, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 11, 0, KEY_EN_F10, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 12, 0, KEY_EN_F11, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 13, 0, KEY_EN_F12, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + /*-----------------------------------------------------------------------------------------------------------------------------*\ + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-----------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 0, 0, KEY_EN_ESCAPE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 2, 0, KEY_EN_F1, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 3, 0, KEY_EN_F2, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 4, 0, KEY_EN_F3, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 5, 0, KEY_EN_F4, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 6, 0, KEY_EN_F5, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 7, 0, KEY_EN_F6, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 8, 0, KEY_EN_F7, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 9, 0, KEY_EN_F8, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 10, 0, KEY_EN_F9, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 11, 0, KEY_EN_F10, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 12, 0, KEY_EN_F11, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 13, 0, KEY_EN_F12, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, }; static const std::vector keyboard_zone_extras = { - /*---------------------------------------------------------------------------------------------------------*\ - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 0, 14, 0, KEY_EN_PRINT_SCREEN, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 15, 0, KEY_EN_SCROLL_LOCK, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 0, 16, 0, KEY_EN_PAUSE_BREAK, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 14, 0, KEY_EN_INSERT, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 15, 0, KEY_EN_HOME, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 16, 0, KEY_EN_PAGE_UP, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 14, 0, KEY_EN_DELETE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 15, 0, KEY_EN_END, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 16, 0, KEY_EN_PAGE_DOWN, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 15, 0, KEY_EN_UP_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 14, 0, KEY_EN_LEFT_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 15, 0, KEY_EN_DOWN_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 16, 0, KEY_EN_RIGHT_ARROW, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + /*-----------------------------------------------------------------------------------------------------------------------------*\ + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-----------------------------------------------------------------------------------------------------------------------------*/ + { 0, 0, 14, 0, KEY_EN_PRINT_SCREEN, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 15, 0, KEY_EN_SCROLL_LOCK, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 0, 16, 0, KEY_EN_PAUSE_BREAK, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 14, 0, KEY_EN_INSERT, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 15, 0, KEY_EN_HOME, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 16, 0, KEY_EN_PAGE_UP, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 14, 0, KEY_EN_DELETE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 15, 0, KEY_EN_END, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 16, 0, KEY_EN_PAGE_DOWN, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 15, 0, KEY_EN_UP_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 14, 0, KEY_EN_LEFT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 15, 0, KEY_EN_DOWN_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 16, 0, KEY_EN_RIGHT_ARROW, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, }; static const std::vector keyboard_zone_numpad = { - /*---------------------------------------------------------------------------------------------------------*\ - | Zone, Row, Column, Value, Key, OpCode, | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 1, 17, 0, KEY_EN_NUMPAD_LOCK, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 18, 0, KEY_EN_NUMPAD_DIVIDE, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 19, 0, KEY_EN_NUMPAD_TIMES, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 1, 20, 0, KEY_EN_NUMPAD_MINUS, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 17, 0, KEY_EN_NUMPAD_7, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 18, 0, KEY_EN_NUMPAD_8, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 19, 0, KEY_EN_NUMPAD_9, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 2, 20, 0, KEY_EN_NUMPAD_PLUS, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 17, 0, KEY_EN_NUMPAD_4, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 18, 0, KEY_EN_NUMPAD_5, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 3, 19, 0, KEY_EN_NUMPAD_6, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 17, 0, KEY_EN_NUMPAD_1, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 18, 0, KEY_EN_NUMPAD_2, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 19, 0, KEY_EN_NUMPAD_3, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 4, 20, 0, KEY_EN_NUMPAD_ENTER, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 18, 0, KEY_EN_NUMPAD_0, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, - { 0, 5, 19, 0, KEY_EN_NUMPAD_PERIOD, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + /*-----------------------------------------------------------------------------------------------------------------------------*\ + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-----------------------------------------------------------------------------------------------------------------------------*/ + { 0, 1, 17, 0, KEY_EN_NUMPAD_LOCK, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 18, 0, KEY_EN_NUMPAD_DIVIDE, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 19, 0, KEY_EN_NUMPAD_TIMES, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 1, 20, 0, KEY_EN_NUMPAD_MINUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 17, 0, KEY_EN_NUMPAD_7, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 18, 0, KEY_EN_NUMPAD_8, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 19, 0, KEY_EN_NUMPAD_9, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 2, 20, 0, KEY_EN_NUMPAD_PLUS, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 17, 0, KEY_EN_NUMPAD_4, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 18, 0, KEY_EN_NUMPAD_5, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 3, 19, 0, KEY_EN_NUMPAD_6, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 17, 0, KEY_EN_NUMPAD_1, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 18, 0, KEY_EN_NUMPAD_2, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 19, 0, KEY_EN_NUMPAD_3, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 4, 20, 0, KEY_EN_NUMPAD_ENTER, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 18, 0, KEY_EN_NUMPAD_0, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, + { 0, 5, 19, 0, KEY_EN_NUMPAD_PERIOD, KEY_EN_UNUSED, KEYBOARD_OPCODE_INSERT_SHIFT_RIGHT, }, }; keyboard_keymap_overlay iso_azerty { KEYBOARD_SIZE_FULL, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 3, 12, 0, KEY_FR_ASTERIX, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 4, 1, 0, KEY_NORD_ANGLE_BRACKET, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 1, 0, 0, KEY_FR_SUPER_2, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 1, 1, 0, KEY_FR_AMPERSAND, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 1, 2, 0, KEY_FR_ACUTE_E, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 1, 3, 0, KEY_FR_DOUBLEQUOTE, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 1, 4, 0, KEY_EN_QUOTE, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 1, 5, 0, KEY_FR_LEFT_PARENTHESIS, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 1, 6, 0, KEY_EN_MINUS, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 1, 7, 0, KEY_FR_GRAVE_E, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 1, 8, 0, KEY_FR_UNDERSCORE, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 1, 9, 0, KEY_FR_CEDILLA_C, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 1, 10, 0, KEY_FR_GRAVE_A, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 1, 11, 0, KEY_FR_RIGHT_PARENTHESIS, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 2, 1, 0, KEY_EN_A, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 2, 2, 0, KEY_EN_Z, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 2, 11, 0, KEY_JP_CHEVRON, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 2, 12, 0, KEY_FR_DOLLAR, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 2, 13, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 3, 1, 0, KEY_EN_Q, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 3, 10, 0, KEY_EN_M, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 3, 11, 0, KEY_FR_GRAVE_U, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 4, 2, 0, KEY_EN_W, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 4, 8, 0, KEY_EN_COMMA, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 4, 9, 0, KEY_EN_SEMICOLON, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 4, 10, 0, KEY_JP_COLON, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 4, 11, 0, KEY_FR_EXCLAIMATION, KEYBOARD_OPCODE_SWAP_ONLY, }, + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 3, 12, 0, KEY_EN_UNUSED, KEY_FR_ASTERIX, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 4, 1, 0, KEY_EN_UNUSED, KEY_NORD_ANGLE_BRACKET, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_FR_SUPER_2, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 1, 1, 0, KEY_EN_UNUSED, KEY_FR_AMPERSAND, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 1, 2, 0, KEY_EN_UNUSED, KEY_FR_ACUTE_E, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 1, 3, 0, KEY_EN_UNUSED, KEY_FR_DOUBLEQUOTE, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 1, 4, 0, KEY_EN_UNUSED, KEY_EN_QUOTE, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 1, 5, 0, KEY_EN_UNUSED, KEY_FR_LEFT_PARENTHESIS, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 1, 6, 0, KEY_EN_UNUSED, KEY_EN_MINUS, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 1, 7, 0, KEY_EN_UNUSED, KEY_FR_GRAVE_E, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 1, 8, 0, KEY_EN_UNUSED, KEY_FR_UNDERSCORE, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 1, 9, 0, KEY_EN_UNUSED, KEY_FR_CEDILLA_C, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 1, 10, 0, KEY_EN_UNUSED, KEY_FR_GRAVE_A, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 1, 11, 0, KEY_EN_UNUSED, KEY_FR_RIGHT_PARENTHESIS, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 2, 1, 0, KEY_EN_UNUSED, KEY_EN_A, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 2, 2, 0, KEY_EN_UNUSED, KEY_EN_Z, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 2, 11, 0, KEY_EN_UNUSED, KEY_JP_CHEVRON, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 2, 12, 0, KEY_EN_UNUSED, KEY_FR_DOLLAR, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 2, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 3, 1, 0, KEY_EN_UNUSED, KEY_EN_Q, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 3, 10, 0, KEY_EN_UNUSED, KEY_EN_M, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 3, 11, 0, KEY_EN_UNUSED, KEY_FR_GRAVE_U, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 4, 2, 0, KEY_EN_UNUSED, KEY_EN_W, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 4, 8, 0, KEY_EN_UNUSED, KEY_EN_COMMA, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 4, 9, 0, KEY_EN_UNUSED, KEY_EN_SEMICOLON, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 4, 10, 0, KEY_EN_UNUSED, KEY_JP_COLON, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 4, 11, 0, KEY_EN_UNUSED, KEY_FR_EXCLAIMATION, KEYBOARD_OPCODE_ADD_ALT_NAME, }, } }; @@ -227,11 +230,12 @@ keyboard_keymap_overlay ansi_qwerty { KEYBOARD_SIZE_FULL, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 3, 12, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 4, 1, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 3, 12, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + { 0, 4, 1, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, } }; @@ -239,10 +243,11 @@ keyboard_keymap_overlay iso_qwerty { KEYBOARD_SIZE_FULL, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 2, 13, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 2, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, } }; @@ -250,22 +255,23 @@ keyboard_keymap_overlay iso_qwertz { KEYBOARD_SIZE_FULL, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 3, 12, 0, KEY_EN_POUND, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 4, 1, 0, KEY_NORD_ANGLE_BRACKET, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 1, 0, 0, KEY_JP_CHEVRON, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 1, 11, 0, KEY_DE_ESZETT, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 1, 12, 0, KEY_EN_BACK_TICK, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 2, 6, 0, KEY_EN_Z, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 2, 11, 0, KEY_DE_DIAERESIS_U, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 2, 12, 0, KEY_EN_PLUS, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 2, 13, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 3, 10, 0, KEY_DE_DIAERESIS_O, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 3, 11, 0, KEY_DE_DIAERESIS_A, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 4, 2, 0, KEY_EN_Y, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 4, 11, 0, KEY_EN_MINUS, KEYBOARD_OPCODE_SWAP_ONLY, }, + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 3, 12, 0, KEY_EN_UNUSED, KEY_EN_POUND, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 4, 1, 0, KEY_EN_UNUSED, KEY_NORD_ANGLE_BRACKET, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 1, 0, 0, KEY_EN_UNUSED, KEY_JP_CHEVRON, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 1, 11, 0, KEY_EN_UNUSED, KEY_DE_ESZETT, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 1, 12, 0, KEY_EN_UNUSED, KEY_EN_BACK_TICK, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 2, 6, 0, KEY_EN_UNUSED, KEY_EN_Z, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 2, 11, 0, KEY_EN_UNUSED, KEY_DE_DIAERESIS_U, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 2, 12, 0, KEY_EN_UNUSED, KEY_EN_PLUS, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 2, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 3, 10, 0, KEY_EN_UNUSED, KEY_DE_DIAERESIS_O, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 3, 11, 0, KEY_EN_UNUSED, KEY_DE_DIAERESIS_A, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 4, 2, 0, KEY_EN_UNUSED, KEY_EN_Y, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 4, 11, 0, KEY_EN_UNUSED, KEY_EN_MINUS, KEYBOARD_OPCODE_ADD_ALT_NAME, }, } }; @@ -273,16 +279,17 @@ keyboard_keymap_overlay jis { KEYBOARD_SIZE_FULL, { - /*---------------------------------------------------------------------------------------------------------*\ - | Edit Keys | - \*---------------------------------------------------------------------------------------------------------*/ - { 0, 3, 12, 0, KEY_EN_RIGHT_BRACKET, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 4, 12, 0, KEY_EN_BACK_SLASH, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 1, 12, 0, KEY_JP_CHEVRON, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 2, 11, 0, KEY_JP_AT, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 2, 12, 0, KEY_EN_LEFT_BRACKET, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 3, 11, 0, KEY_JP_COLON, KEYBOARD_OPCODE_SWAP_ONLY, }, - { 0, 2, 13, 0, KEY_EN_UNUSED, KEYBOARD_OPCODE_SWAP_ONLY, }, + /*-------------------------------------------------------------------------------------------------------------------------------------*\ + | Edit Keys | + | Zone, Row, Column, Value, Name, Alternate Name, OpCode | + \*-------------------------------------------------------------------------------------------------------------------------------------*/ + { 0, 3, 12, 0, KEY_EN_RIGHT_BRACKET, KEY_EN_UNUSED, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 4, 12, 0, KEY_EN_BACK_SLASH, KEY_EN_UNUSED, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 1, 12, 0, KEY_JP_CHEVRON, KEY_EN_UNUSED, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 2, 11, 0, KEY_JP_AT, KEY_EN_UNUSED, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 2, 12, 0, KEY_EN_LEFT_BRACKET, KEY_EN_UNUSED, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 3, 11, 0, KEY_JP_COLON, KEY_EN_UNUSED, KEYBOARD_OPCODE_ADD_ALT_NAME, }, + { 0, 2, 13, 0, KEY_EN_UNUSED, KEY_EN_UNUSED, KEYBOARD_OPCODE_ADD_ALT_NAME, }, } }; @@ -333,9 +340,9 @@ KeyboardLayoutManager::KeyboardLayoutManager(KEYBOARD_LAYOUT layout, KEYBOARD_SI | Add any values passed into the constructor before switching layouts | | and declare a value set for any changes afterwards | \*---------------------------------------------------------------------*/ - for(size_t key_idx = 0; key_idx < values.ansi.size() && key_idx < keymap.size(); key_idx++) + for(size_t key_idx = 0; key_idx < (unsigned int)values.default_values.size() && key_idx < keymap.size(); key_idx++) { - keymap[key_idx].value = values.ansi[key_idx]; + keymap[key_idx].value = values.default_values[key_idx]; } /*---------------------------------------------------------------------*\ @@ -366,20 +373,20 @@ KeyboardLayoutManager::KeyboardLayoutManager(KEYBOARD_LAYOUT layout, KEYBOARD_SI | Non-English, non-QWERTY layouts are disabled | | until proper translation feature is implemented | \*-------------------------------------------------*/ - // case KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_ISO_AZERTY: - // ChangeKeys(iso_azerty); - // tmp_name = KEYBOARD_NAME_AZERTY; - // break; + case KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_ISO_AZERTY: + ChangeKeys(iso_azerty); + tmp_name = KEYBOARD_NAME_AZERTY; + break; - // case KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_ISO_QWERTZ: - // ChangeKeys(iso_qwertz); - // tmp_name = KEYBOARD_NAME_QWERTZ; - // break; + case KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_ISO_QWERTZ: + ChangeKeys(iso_qwertz); + tmp_name = KEYBOARD_NAME_QWERTZ; + break; - // case KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_JIS: - // ChangeKeys(jis); - // tmp_name = KEYBOARD_NAME_JIS; - // break; + case KEYBOARD_LAYOUT::KEYBOARD_LAYOUT_JIS: + ChangeKeys(jis); + tmp_name = KEYBOARD_NAME_JIS; + break; } /*---------------------------------------------------------------------*\ @@ -417,8 +424,17 @@ KeyboardLayoutManager::KeyboardLayoutManager(KEYBOARD_LAYOUT layout, KEYBOARD_SI name = KEYBOARD_NAME_TKL; break; - default: + case KEYBOARD_SIZE::KEYBOARD_SIZE_FULL: name = KEYBOARD_NAME_FULL; + break; + + default: + /*-------------------------------------------------------------*\ + | If the keyboard size is not a standard size output | + | the combined number as a string | + \*-------------------------------------------------------------*/ + name = "Size ("; + name.append(std::to_string(size) + ") "); } /*---------------------------------------------------------------------*\ @@ -453,7 +469,7 @@ void KeyboardLayoutManager::OpCodeSwitch(key_set change_keys) { LOG_DEBUG("[%s] %d keys to edit", KLM_CLASS_NAME, change_keys.size()); - for(size_t chg_key_idx = 0; chg_key_idx < change_keys.size(); chg_key_idx++) + for(size_t chg_key_idx = 0; chg_key_idx < (unsigned int)change_keys.size(); chg_key_idx++) { switch(change_keys[chg_key_idx].opcode) { @@ -474,10 +490,21 @@ void KeyboardLayoutManager::OpCodeSwitch(key_set change_keys) //SwapKey(change_keys[chg_key_idx]); break; + case KEYBOARD_OPCODE_INSERT_ROW: + if(InsertRow(change_keys[chg_key_idx].row)) + { + SwapKey(change_keys[chg_key_idx]); + } + break; + case KEYBOARD_OPCODE_REMOVE_ROW: RemoveRow(change_keys[chg_key_idx].row); break; + case KEYBOARD_OPCODE_ADD_ALT_NAME: + AddAltName(change_keys[chg_key_idx]); + break; + default: LOG_DEBUG(LOG_MSG_MISSING_OPCODE, KLM_CLASS_NAME, change_keys[chg_key_idx].opcode, change_keys[chg_key_idx].name, change_keys[chg_key_idx].row, change_keys[chg_key_idx].col); @@ -498,7 +525,7 @@ void KeyboardLayoutManager::InsertKey(keyboard_led ins_key) unsigned int key_idx = 0; - for(/*key_idx*/; key_idx < keymap.size(); key_idx++) + for(/*key_idx*/; key_idx < (unsigned int)keymap.size(); key_idx++) { /*---------------------------------------------------------------------*\ | Search through all existing keys and determine where in the list to | @@ -518,7 +545,7 @@ void KeyboardLayoutManager::InsertKey(keyboard_led ins_key) /*---------------------------------------------------------------------*\ | If the search reached the end, put the new key at the end of the list | \*---------------------------------------------------------------------*/ - if(key_idx == keymap.size()) + if(key_idx == (unsigned int)keymap.size()) { LOG_DEBUG(LOG_MSG_INSERT_BEFORE, KLM_CLASS_NAME, ins_name, "the end", ins_row, ins_col, KEY_EN_UNUSED); keymap.push_back(ins_key); @@ -548,7 +575,7 @@ void KeyboardLayoutManager::InsertKey(keyboard_led ins_key) \*---------------------------------------------------------------------*/ if(update_row) { - for(/*key_idx*/; key_idx < keymap.size(); key_idx++) + for(/*key_idx*/; key_idx < (unsigned int)keymap.size(); key_idx++) { if((keymap[key_idx].row == ins_row) && (keymap[key_idx].col >= ins_col)) { @@ -570,7 +597,7 @@ void KeyboardLayoutManager::InsertKeys(std::vector ins_keys) /*---------------------------------------------------------------------*\ | Insert new keys one by one | \*---------------------------------------------------------------------*/ - for(unsigned int ins_key_idx = 0; ins_key_idx < ins_keys.size(); ins_key_idx++) + for(unsigned int ins_key_idx = 0; ins_key_idx < (unsigned int)ins_keys.size(); ins_key_idx++) { InsertKey(ins_keys[ins_key_idx]); } @@ -604,13 +631,16 @@ void KeyboardLayoutManager::SwapKey(keyboard_led swp_key) | Otherwise, loop through and either swap an existing entry or insert | | a new entry if the given location does not already have a key present | \*---------------------------------------------------------------------*/ - for(unsigned int key_idx = 0; key_idx < keymap.size(); key_idx++) + for(unsigned int key_idx = 0; key_idx < (unsigned int)keymap.size(); key_idx++) { /*---------------------------------------------------------------------*\ | If the row and column are identical, we've found the swap location | \*---------------------------------------------------------------------*/ if((swp_row == keymap[key_idx].row) && (swp_col == keymap[key_idx].col)) { + std::string tmp_name = (strlen(swp_name) == 0) ? LOG_MSG_UNUSED_KEY : swp_name; + LOG_DEBUG("[%s] Swapping in %s and %s out @ %02d, %02d", KLM_CLASS_NAME, tmp_name.c_str(), keymap[key_idx].name, swp_row, swp_col); + /*---------------------------------------------------------------------*\ | If the key to be swapped in is an unused key, we want to remove the | | entry from the keymap rather than perform a swap | @@ -625,8 +655,6 @@ void KeyboardLayoutManager::SwapKey(keyboard_led swp_key) \*---------------------------------------------------------------------*/ else { - std::string swap_name = (strlen(swp_name) == 0) ? LOG_MSG_UNUSED_KEY : swp_name; - LOG_DEBUG("[%s] Swapping in %s and %s out @ %02d, %02d", KLM_CLASS_NAME, swap_name.c_str(), keymap[key_idx].name, swp_row, swp_col); keymap[key_idx].name = swp_name; keymap[key_idx].value = swp_value; } @@ -670,7 +698,7 @@ void KeyboardLayoutManager::SwapKeys(std::vector swp_keys) /*---------------------------------------------------------------------*\ | Swap keys one by one | \*---------------------------------------------------------------------*/ - for(unsigned int swp_key_idx = 0; swp_key_idx < swp_keys.size(); swp_key_idx++) + for(unsigned int swp_key_idx = 0; swp_key_idx < (unsigned int)swp_keys.size(); swp_key_idx++) { SwapKey(swp_keys[swp_key_idx]); } @@ -687,7 +715,7 @@ void KeyboardLayoutManager::RemoveKey(keyboard_led rmv_key) /*---------------------------------------------------------------------*\ | Loop through and find the entry to remove | \*---------------------------------------------------------------------*/ - for(unsigned int key_idx = 0; key_idx < keymap.size(); key_idx++) + for(unsigned int key_idx = 0; key_idx < (unsigned int)keymap.size(); key_idx++) { /*---------------------------------------------------------------------*\ | If the row and column are identical, we've found the swap location | @@ -697,7 +725,7 @@ void KeyboardLayoutManager::RemoveKey(keyboard_led rmv_key) LOG_DEBUG("[%s] Removing %s @ %02d, %02d and shifting keys left", KLM_CLASS_NAME, keymap[key_idx].name, rmv_row, rmv_col); keymap.erase(keymap.begin() + key_idx); - for(/*key_idx*/; key_idx < keymap.size(); key_idx++) + for(/*key_idx*/; key_idx < (unsigned int)keymap.size(); key_idx++) { if(rmv_row == keymap[key_idx].row) { @@ -716,7 +744,7 @@ void KeyboardLayoutManager::RemoveKey(keyboard_led rmv_key) { LOG_DEBUG("[%s] Removing unused key @ %02d, %02d and shifting keys left", KLM_CLASS_NAME, rmv_row, rmv_col); - for(/*key_idx*/; key_idx < keymap.size(); key_idx++) + for(/*key_idx*/; key_idx < (unsigned int)keymap.size(); key_idx++) { if(rmv_row == keymap[key_idx].row) { @@ -733,6 +761,47 @@ void KeyboardLayoutManager::RemoveKey(keyboard_led rmv_key) } } +bool KeyboardLayoutManager::InsertRow(uint8_t ins_row) +{ + /*---------------------------------------------------------------------*\ + | Check row is valid to Insert | + \*---------------------------------------------------------------------*/ + if(ins_row >= rows) + { + LOG_DEBUG("[%s] Inserting row %d failed as rows currently = %d", KLM_CLASS_NAME, ins_row, rows); + return false; + } + + /*---------------------------------------------------------------------*\ + | Loop through to find the first key in the row to insert | + \*---------------------------------------------------------------------*/ + unsigned int key_idx = 0; + + for(/*key_idx*/; key_idx < (unsigned int)keymap.size(); key_idx++) + { + if(ins_row <= keymap[key_idx].row) + { + break; + } + } + + LOG_DEBUG("[%s] Attempting to insert row %d before %s at index %d", + KLM_CLASS_NAME, ins_row, keymap[key_idx].name, key_idx); + /*---------------------------------------------------------------------*\ + | Loop through the remaining rows and adjust row number | + \*---------------------------------------------------------------------*/ + if(ins_row <= keymap[key_idx].row) + { + for(/*key_idx*/; key_idx < (unsigned int)keymap.size(); key_idx++) + { + keymap[key_idx].row++; + } + + LOG_DEBUG("[%s] Insert row %d successful", KLM_CLASS_NAME, ins_row); + } + return true; +} + void KeyboardLayoutManager::RemoveRow(uint8_t rmv_row) { /*---------------------------------------------------------------------*\ @@ -749,13 +818,17 @@ void KeyboardLayoutManager::RemoveRow(uint8_t rmv_row) \*---------------------------------------------------------------------*/ unsigned int key_idx = 0; - for(/*key_idx*/; key_idx < keymap.size() && rmv_row > keymap[key_idx].row; key_idx++) + while(key_idx < (unsigned int)keymap.size() && rmv_row >= keymap[key_idx].row) { if(rmv_row == keymap[key_idx].row) { LOG_DEBUG("[%s] Removing %s @ %02d, %02d from row %d", KLM_CLASS_NAME, keymap[key_idx].name, keymap[key_idx].row, keymap[key_idx].col, rmv_row); keymap.erase(keymap.begin() + key_idx); } + else + { + key_idx++; + } } /*---------------------------------------------------------------------*\ @@ -763,7 +836,7 @@ void KeyboardLayoutManager::RemoveRow(uint8_t rmv_row) \*---------------------------------------------------------------------*/ if(rmv_row < keymap[key_idx].row) { - for(/*key_idx*/; key_idx < keymap.size(); key_idx++) + for(/*key_idx*/; key_idx < (unsigned int)keymap.size(); key_idx++) { keymap[key_idx].row--; } @@ -772,8 +845,36 @@ void KeyboardLayoutManager::RemoveRow(uint8_t rmv_row) } } -std::string KeyboardLayoutManager::GetName() +void KeyboardLayoutManager::AddAltName(keyboard_led key) +{ + /*---------------------------------------------------------------------*\ + | Get the edit point | + \*---------------------------------------------------------------------*/ + unsigned int edit_row = key.row; + unsigned int edit_col = key.col; + const char* edit_alt_name = key.alt_name; + /*---------------------------------------------------------------------*\ + | Otherwise, loop through and find the edit location | + \*---------------------------------------------------------------------*/ + for(unsigned int key_idx = 0; key_idx < keymap.size(); key_idx++) + { + /*---------------------------------------------------------------------*\ + | If the row and column are identical, we've found the edit location | + \*---------------------------------------------------------------------*/ + if((edit_row == keymap[key_idx].row) && (edit_col == keymap[key_idx].col)) + { + /*---------------------------------------------------------------------*\ + | Update the entry at this position with the new translated name | + \*---------------------------------------------------------------------*/ + LOG_DEBUG("[%s] Adding alternate name %s to %s @ %02d, %02d", KLM_CLASS_NAME, edit_alt_name, keymap[key_idx].name, keymap[key_idx].row, keymap[key_idx].col); + keymap[key_idx].alt_name = edit_alt_name; + break; + } + } +} + +std::string KeyboardLayoutManager::GetName() { return name; } @@ -790,12 +891,12 @@ KEYBOARD_SIZE KeyboardLayoutManager::GetPhysicalSize() unsigned int KeyboardLayoutManager::GetKeyCount() { - return keymap.size(); + return (unsigned int)keymap.size(); } std::string KeyboardLayoutManager::GetKeyNameAt(unsigned int key_idx) { - if(key_idx < keymap.size()) + if(key_idx < (unsigned int)keymap.size()) { return keymap[key_idx].name; } @@ -839,6 +940,29 @@ unsigned int KeyboardLayoutManager::GetKeyValueAt(unsigned int row, unsigned int return -1; } +std::string KeyboardLayoutManager::GetKeyAltNameAt(unsigned int key_idx) +{ + if(key_idx < keymap.size()) + { + return keymap[key_idx].alt_name; + } + + return KEY_EN_UNUSED; +} + +std::string KeyboardLayoutManager::GetKeyAltNameAt(unsigned int row, unsigned int col) +{ + for(std::vector::iterator key = keymap.begin(); key != keymap.end(); ++key) + { + if(key->row == row && key->col == col) + { + return key->alt_name; + } + } + + return KEY_EN_UNUSED; +} + unsigned int KeyboardLayoutManager::GetRowCount() { return rows; @@ -865,19 +989,19 @@ void KeyboardLayoutManager::GetKeyMap(unsigned int* map_ptr, KEYBOARD_MAP_FILL_T width = std::max(width, cols); height = std::max(height, rows); - for(size_t r = 0; r < height; r++) + for(unsigned int r = 0; r < height; r++) { - size_t offset = r * width; + unsigned int offset = r * width; - for(size_t c = 0; c < width; c++) + for(unsigned int c = 0; c < width; c++) { map_ptr[offset + c] = no_key; } } - for(size_t i = 0; i < keymap.size(); i++) + for(unsigned int i = 0; i < (unsigned int)keymap.size(); i++) { - size_t offset = (keymap[i].row * width) + keymap[i].col; + unsigned int offset = (keymap[i].row * width) + keymap[i].col; switch(fill_type) { case KEYBOARD_MAP_FILL_TYPE_COUNT: @@ -907,7 +1031,7 @@ void KeyboardLayoutManager::UpdateDimensions() /*---------------------------------------------------------------------*\ | Search through the keymap and find the maximum row and column values | \*---------------------------------------------------------------------*/ - for(unsigned int key_idx = 0; key_idx < keymap.size(); key_idx++) + for(unsigned int key_idx = 0; key_idx < (unsigned int)keymap.size(); key_idx++) { if(keymap[key_idx].row > max_row) { diff --git a/KeyboardLayoutManager/KeyboardLayoutManager.h b/KeyboardLayoutManager/KeyboardLayoutManager.h index efbfdbdc..97639c61 100644 --- a/KeyboardLayoutManager/KeyboardLayoutManager.h +++ b/KeyboardLayoutManager/KeyboardLayoutManager.h @@ -1,16 +1,20 @@ -/*---------------------------------------------------------------------*\ -| KeyboardLayoutManager.h | -| | -| Helper library to produce keyboard layouts | -| | -| Chris M (Dr_No) 04 Feb 2023 | -| | -\*---------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| KeyboardLayoutManager.h | +| | +| Helper library to produce keyboard layouts | +| | +| Chris M (Dr_No) 04 Feb 2023 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include #include #include +#include #include "RGBControllerKeyNames.h" extern const char* KLM_CLASS_NAME; @@ -61,16 +65,19 @@ enum KEYBOARD_OPCODE KEYBOARD_OPCODE_SWAP_ONLY = 1, KEYBOARD_OPCODE_REMOVE_SHIFT_LEFT = 2, KEYBOARD_OPCODE_INS_SHFT_ADJACENT = 3, - KEYBOARD_OPCODE_REMOVE_ROW = 4, + KEYBOARD_OPCODE_INSERT_ROW = 4, + KEYBOARD_OPCODE_REMOVE_ROW = 5, + KEYBOARD_OPCODE_ADD_ALT_NAME = 6, }; typedef struct { - uint8_t zone; - uint8_t row; - uint8_t col; + std::uint8_t zone; + std::uint8_t row; + std::uint8_t col; unsigned int value; const char* name; + const char* alt_name; KEYBOARD_OPCODE opcode; } keyboard_led; @@ -79,7 +86,7 @@ typedef typedef struct { - std::vector ansi; + std::vector default_values; std::map regional_overlay; } layout_values; @@ -115,6 +122,8 @@ public: unsigned int GetKeyCount(); std::string GetKeyNameAt(unsigned int key_idx); std::string GetKeyNameAt(unsigned int row, unsigned int col); + std::string GetKeyAltNameAt(unsigned int key_idx); + std::string GetKeyAltNameAt(unsigned int row, unsigned int col); unsigned int GetKeyValueAt(unsigned int key_idx); unsigned int GetKeyValueAt(unsigned int row, unsigned int col); @@ -125,22 +134,24 @@ public: void GetKeyMap(unsigned int* map_ptr); void GetKeyMap(unsigned int* map_ptr, KEYBOARD_MAP_FILL_TYPE fill_type); void GetKeyMap(unsigned int* map_ptr, KEYBOARD_MAP_FILL_TYPE fill_type, - uint8_t height, uint8_t width); + std::uint8_t height, std::uint8_t width); private: void OpCodeSwitch(key_set change_keys); void InsertKey(keyboard_led key); void InsertKeys(std::vector keys); + bool InsertRow(std::uint8_t row); void SwapKey(keyboard_led keys); void SwapKeys(std::vector keys); void RemoveKey(keyboard_led keys); - void RemoveRow(uint8_t row); + void RemoveRow(std::uint8_t row); + void AddAltName(keyboard_led key); KEYBOARD_LAYOUT layout; KEYBOARD_SIZE physical_size; std::string name = KLM_CLASS_NAME; - uint8_t rows = 0; - uint8_t cols = 0; + std::uint8_t rows = 0; + std::uint8_t cols = 0; std::vector keymap; }; diff --git a/LogManager.cpp b/LogManager.cpp index 43a1596d..745c3d21 100644 --- a/LogManager.cpp +++ b/LogManager.cpp @@ -1,20 +1,36 @@ +/*---------------------------------------------------------*\ +| LogManager.cpp | +| | +| Manages log file and output to the console | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "LogManager.h" +#include #include #include #include #include -#include "ResourceManager.h" - #include "filesystem.h" const char* LogManager::log_codes[] = {"FATAL:", "ERROR:", "Warning:", "Info:", "Verbose:", "Debug:", "Trace:", "Dialog:"}; +const char* TimestampPattern = "%04d%02d%02d_%02d%02d%02d"; + +/*---------------------------------------------------------*\ +| Relies on the structure of the template above | +\*---------------------------------------------------------*/ +const char* TimestampRegex = "[0-9]{8}_[0-9]{6}"; + LogManager::LogManager() { - base_clock = std::chrono::steady_clock::now(); + base_clock = std::chrono::steady_clock::now(); log_console_enabled = false; + log_file_enabled = true; } LogManager* LogManager::get() @@ -23,14 +39,14 @@ LogManager* LogManager::get() static std::mutex instance_mutex; std::lock_guard grd(instance_mutex); - /*-------------------------------------------------*\ - | Create a new instance if one does not exist | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Create a new instance if one does not exist | + \*-----------------------------------------------------*/ if(!_instance) { _instance = new LogManager(); } - + return _instance; } @@ -48,75 +64,108 @@ unsigned int LogManager::getLoglevel() void LogManager::configure(json config, const filesystem::path& defaultDir) { - std::lock_guard grd(entry_mutex); + std::lock_guard grd(entry_mutex); - /*-------------------------------------------------*\ - | If the log is not open, create a new log file | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | If the log is not open, create a new log file | + \*-----------------------------------------------------*/ if(!log_stream.is_open()) { - std::string logname = "OpenRGB_#.log"; + /*-------------------------------------------------*\ + | If a limit is declared in the config for the | + | maximum number of log files, respect the limit | + | Log rotation will remove the files matching the | + | current "logfile", starting with the oldest ones | + | (according to the timestamp in their filename) | + | i.e. with the lexicographically smallest filename | + | 0 or less equals no limit (default) | + \*-------------------------------------------------*/ + int loglimit = 0; + if(config.contains("file_count_limit") && config["file_count_limit"].is_number_integer()) + { + loglimit = config["file_count_limit"]; + } + + if(config.contains("log_file")) + { + log_file_enabled = config["log_file"]; + } /*-------------------------------------------------*\ - | If the logfile is defined in the configuration, | - | use the configured name | + | Default template for the logfile name | + | The # symbol is replaced with a timestamp | \*-------------------------------------------------*/ - if(config.contains("logfile")) + std::string logtempl = "OpenRGB_#.log"; + + if(log_file_enabled) { - const json& logfile_obj = config["logfile"]; - if(logfile_obj.is_string()) + /*---------------------------------------------*\ + | If the logfile is defined in the | + | configuration, use the configured name | + \*---------------------------------------------*/ + if(config.contains("logfile")) { - std::string tmpname = config["logfile"]; - if(!tmpname.empty()) + const json& logfile_obj = config["logfile"]; + if(logfile_obj.is_string()) { - logname = tmpname; + std::string tmpname = config["logfile"]; + if(!tmpname.empty()) + { + logtempl = tmpname; + } } } + /*---------------------------------------------*\ + | If the # symbol is found in the log file | + | name, replace it with a timestamp | + \*---------------------------------------------*/ + time_t t = time(0); + struct tm* tmp = localtime(&t); + char time_string[64]; + snprintf(time_string, 64, TimestampPattern, 1900 + tmp->tm_year, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); + + std::string logname = logtempl; + size_t oct = logname.find("#"); + if(oct != logname.npos) + { + logname.replace(oct, 1, time_string); + } + + /*---------------------------------------------*\ + | If the path is relative, use logs dir | + \*---------------------------------------------*/ + filesystem::path p = filesystem::u8path(logname); + if(p.is_relative()) + { + p = defaultDir / "logs" / logname; + } + filesystem::create_directories(p.parent_path()); + + /*---------------------------------------------*\ + | "Log rotation": remove old log files | + | exceeding the current configured limit | + \*---------------------------------------------*/ + rotate_logs(p.parent_path(), filesystem::u8path(logtempl).filename(), loglimit); + + /*---------------------------------------------*\ + | Open the logfile | + \*---------------------------------------------*/ + log_stream.open(p); + + /*---------------------------------------------*\ + | Print Git Commit info, version, etc. | + \*---------------------------------------------*/ + log_stream << " OpenRGB v" << VERSION_STRING << std::endl; + log_stream << " Commit: " << GIT_COMMIT_ID << " from " << GIT_COMMIT_DATE << std::endl; + log_stream << " Launched: " << time_string << std::endl; + log_stream << "====================================================================================================" << std::endl; + log_stream << std::endl; } - - /*-------------------------------------------------*\ - | If the # symbol is found in the log file name, | - | replace it with a timestamp | - \*-------------------------------------------------*/ - time_t t = time(0); - struct tm* tmp = localtime(&t); - char time_string[64]; - snprintf(time_string, 64, "%04d%02d%02d_%02d%02d%02d", 1900 + tmp->tm_year, tmp->tm_mon + 1, tmp->tm_mday, tmp->tm_hour, tmp->tm_min, tmp->tm_sec); - - size_t oct = logname.find("#"); - if(oct != logname.npos) - { - logname.replace(oct, 1, time_string); - } - - /*-------------------------------------------------*\ - | If the path is relative, use logs dir | - \*-------------------------------------------------*/ - filesystem::path p = filesystem::u8path(logname); - if(p.is_relative()) - { - p = defaultDir / "logs" / logname; - } - filesystem::create_directories(p.parent_path()); - - /*-------------------------------------------------*\ - | Open the logfile | - \*-------------------------------------------------*/ - log_stream.open(p); - - /*-------------------------------------------------*\ - | Print Git Commit info, version, etc. | - \*-------------------------------------------------*/ - log_stream << " OpenRGB v" << VERSION_STRING << std::endl; - log_stream << " Commit: " << GIT_COMMIT_ID << " from " << GIT_COMMIT_DATE << std::endl; - log_stream << " Launched: " << time_string << std::endl; - log_stream << "====================================================================================================" << std::endl; - log_stream << std::endl; } - /*-------------------------------------------------*\ - | Check loglevel configuration | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check loglevel configuration | + \*-----------------------------------------------------*/ if(config.contains("loglevel")) { const json& loglevel_obj = config["loglevel"]; @@ -130,42 +179,44 @@ void LogManager::configure(json config, const filesystem::path& defaultDir) } } - /*-------------------------------------------------*\ - | Check log console configuration | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check log console configuration | + \*-----------------------------------------------------*/ if(config.contains("log_console")) { log_console_enabled = config["log_console"]; } - /*-------------------------------------------------*\ - | Flush the log | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Flush the log | + \*-----------------------------------------------------*/ _flush(); } void LogManager::_flush() { - /*-------------------------------------------------*\ - | If the log is open, write out buffered messages | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | If the log is open, write out buffered messages | + \*-----------------------------------------------------*/ if(log_stream.is_open()) { for(size_t msg = 0; msg < temp_messages.size(); ++msg) { if(temp_messages[msg]->level <= loglevel || temp_messages[msg]->level == LL_DIALOG) { - // Put the timestamp here + /*-----------------------------------------*\ + | Put the timestamp here | + \*-----------------------------------------*/ std::chrono::milliseconds counter = std::chrono::duration_cast(temp_messages[msg]->counted_second); log_stream << std::left << std::setw(6) << counter.count() << "|"; log_stream << std::left << std::setw(9) << log_codes[temp_messages[msg]->level]; log_stream << temp_messages[msg]->buffer; - + if(print_source) { log_stream << " [" << temp_messages[msg]->filename << ":" << temp_messages[msg]->line << "]"; } - + log_stream << std::endl; } } @@ -174,26 +225,26 @@ void LogManager::_flush() | Clear temp message buffers after writing them out | \*-------------------------------------------------*/ temp_messages.clear(); - } - /*-------------------------------------------------*\ - | Flush the stream | - \*-------------------------------------------------*/ - log_stream.flush(); + /*-------------------------------------------------*\ + | Flush the stream | + \*-------------------------------------------------*/ + log_stream.flush(); + } } void LogManager::flush() { - std::lock_guard grd(entry_mutex); + std::lock_guard grd(entry_mutex); _flush(); } void LogManager::_append(const char* filename, int line, unsigned int level, const char* fmt, va_list va) { - /*-------------------------------------------------*\ - | If a critical message occurs, enable source | - | printing and set loglevel and verbosity to highest| - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | If a critical message occurs, enable source | + | printing and set loglevel and verbosity to highest | + \*-----------------------------------------------------*/ if(level == LL_FATAL) { print_source = true; @@ -201,14 +252,14 @@ void LogManager::_append(const char* filename, int line, unsigned int level, con verbosity = LL_DEBUG; } - /*-------------------------------------------------*\ - | Create a new message | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Create a new message | + \*-----------------------------------------------------*/ PLogMessage mes = std::make_shared(); - /*-------------------------------------------------*\ - | Resize the buffer, then fill in the message text | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Resize the buffer, then fill in the message text | + \*-----------------------------------------------------*/ va_list va2; va_copy(va2, va); int len = vsnprintf(nullptr, 0, fmt, va); @@ -216,18 +267,18 @@ void LogManager::_append(const char* filename, int line, unsigned int level, con vsnprintf(&(mes->buffer[0]), len + 1, fmt, va2); va_end(va2); - /*-------------------------------------------------*\ - | Fill in message information | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Fill in message information | + \*-----------------------------------------------------*/ mes->level = level; mes->filename = filename; mes->line = line; mes->counted_second = std::chrono::steady_clock::now() - base_clock; - /*-------------------------------------------------*\ - | If this is a dialog message, call the dialog show | - | callback | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | If this is a dialog message, call the dialog show | + | callback | + \*-----------------------------------------------------*/ if(level == LL_DIALOG) { for(size_t idx = 0; idx < dialog_show_callbacks.size(); idx++) @@ -236,11 +287,11 @@ void LogManager::_append(const char* filename, int line, unsigned int level, con } } - /*-------------------------------------------------*\ - | If the message is within the current verbosity, | - | print it on the screen | - | TODO: Put the timestamp here | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | If the message is within the current verbosity, print | + | it on the screen | + | TODO: Put the timestamp here | + \*-----------------------------------------------------*/ if(level <= verbosity || level == LL_DIALOG) { std::cout << mes->buffer; @@ -251,9 +302,9 @@ void LogManager::_append(const char* filename, int line, unsigned int level, con std::cout << std::endl; } - /*-------------------------------------------------*\ - | Add the message to the logfile queue | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Add the message to the logfile queue | + \*-----------------------------------------------------*/ temp_messages.push_back(mes); if(log_console_enabled) @@ -261,9 +312,9 @@ void LogManager::_append(const char* filename, int line, unsigned int level, con all_messages.push_back(mes); } - /*-------------------------------------------------*\ - | Flush the queues | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Flush the queues | + \*-----------------------------------------------------*/ _flush(); } @@ -282,7 +333,7 @@ void LogManager::append(const char* filename, int line, unsigned int level, cons va_list va; va_start(va, fmt); - std::lock_guard grd(entry_mutex); + std::lock_guard grd(entry_mutex); _append(filename, line, level, fmt, va); va_end(va); @@ -290,52 +341,51 @@ void LogManager::append(const char* filename, int line, unsigned int level, cons void LogManager::setLoglevel(unsigned int level) { - /*-------------------------------------------------*\ - | Check that the new log level is valid, otherwise | - | set it within the valid range | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check that the new log level is valid, otherwise set | + | it within the valid range | + \*-----------------------------------------------------*/ if(level > LL_TRACE) { level = LL_TRACE; } - LOG_DEBUG("Loglevel set to %d", level); + LOG_DEBUG("[LogManager] Loglevel set to %d", level); - /*-------------------------------------------------*\ - | Set the new log level | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Set the new log level | + \*-----------------------------------------------------*/ loglevel = level; } void LogManager::setVerbosity(unsigned int level) { - /*-------------------------------------------------*\ - | Check that the new verbosity is valid, otherwise | - | set it within the valid range | - \*-------------------------------------------------*/ - + /*-----------------------------------------------------*\ + | Check that the new verbosity is valid, otherwise set | + | it within the valid range | + \*-----------------------------------------------------*/ if(level > LL_TRACE) { level = LL_TRACE; } - LOG_DEBUG("Verbosity set to %d", level); + LOG_DEBUG("[LogManager] Verbosity set to %d", level); - /*-------------------------------------------------*\ - | Set the new verbosity | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Set the new verbosity | + \*-----------------------------------------------------*/ verbosity = level; } void LogManager::setPrintSource(bool v) { - LOG_DEBUG("Source code location printouts were %s", v ? "enabled" : "disabled"); + LOG_DEBUG("[LogManager] Source code location printouts were %s", v ? "enabled" : "disabled"); print_source = v; } void LogManager::RegisterDialogShowCallback(LogDialogShowCallback callback, void* receiver) { - LOG_DEBUG("dialog show callback registered"); + LOG_DEBUG("[LogManager] dialog show callback registered"); dialog_show_callbacks.push_back(callback); dialog_show_callback_args.push_back(receiver); } @@ -351,3 +401,110 @@ void LogManager::UnregisterDialogShowCallback(LogDialogShowCallback callback, vo } } } + +void LogManager::rotate_logs(const filesystem::path& folder, const filesystem::path& templ, int max_count) +{ + if(max_count < 1) + { + return; + } + + std::string templ2 = templ.filename().generic_u8string(); + + /*-----------------------------------------------------*\ + | Process the templ2 into a usable regex | + | The # symbol is replaced with a timestamp regex | + | Any regex-unfriendly symbols are escaped with a | + | backslash | + \*-----------------------------------------------------*/ + std::string regex_templ = "^"; + for(size_t i = 0; i < templ2.size(); ++i) + { + switch(templ2[i]) + { + /*-------------------------------------------------*\ + | Symbols that have special meanings in regex'es | + | need backslash escaping | + \*-------------------------------------------------*/ + case '.': + case '^': + case '$': + case '(': + case ')': + case '{': + case '}': + case '+': + case '[': + case ']': + case '*': + case '-': + /*-------------------------------------------------*\ + | Should have been filtered out by the filesystem | + | processing, but... who knows | + \*-------------------------------------------------*/ + case '\\': + regex_templ.push_back('\\'); + regex_templ.push_back(templ2[i]); + break; + + /*-------------------------------------------------*\ + | The # symbol is reserved for the timestamp and | + | thus is replaced with the timestamp regex | + | template | + \*-------------------------------------------------*/ + case '#': + regex_templ.append(TimestampRegex); + break; + + default: + regex_templ.push_back(templ2[i]); + break; + } + } + regex_templ.push_back('$'); + + std::regex r(regex_templ); + + std::vector valid_paths; + std::filesystem::directory_iterator it(folder); + for(; it != filesystem::end(it); ++it) + { + if(it->is_regular_file()) + { + std::string fname = it->path().filename().u8string(); + if(std::regex_match(fname, r)) + { + valid_paths.push_back(it->path()); + } + } + } + std::sort(valid_paths.begin(), valid_paths.end()); + + /*-----------------------------------------------------*\ + | NOTE: the "1" extra file to remove creates space for | + | the one we're about to create for max_count <= 0 and | + | to prevent any possible errors in the above logic | + \*-----------------------------------------------------*/ + size_t remove_count = valid_paths.size() - max_count + 1; + if(remove_count > valid_paths.size()) + { + remove_count = valid_paths.size(); + } + + for(size_t i = 0; i < remove_count; ++i) + { + /*-------------------------------------------------*\ + | Uses error code to force the `remove` call to be | + | `noexcept` | + \*-------------------------------------------------*/ + std::error_code ec; + if(filesystem::remove(valid_paths[i], ec)) + { + LOG_VERBOSE("[LogManager] Removed log file [%s] during rotation", valid_paths[i].u8string().c_str()); + } + else + { + LOG_WARNING("[LogManager] Failed to remove log file [%s] during rotation: %s", valid_paths[i].u8string().c_str(), ec.message().c_str()); + } + } +} diff --git a/LogManager.h b/LogManager.h index cb7b384b..f099a6c5 100644 --- a/LogManager.h +++ b/LogManager.h @@ -1,3 +1,12 @@ +/*---------------------------------------------------------*\ +| LogManager.h | +| | +| Manages log file and output to the console | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #ifndef LOGMANAGER_H #define LOGMANAGER_H @@ -6,7 +15,7 @@ #include #include #include -#include "json.hpp" +#include #include "filesystem.h" /*-------------------------------------------------*\ @@ -51,7 +60,7 @@ private: LogManager(const LogManager&) = delete; LogManager(LogManager&&) = delete; ~LogManager(); - std::mutex entry_mutex; + std::recursive_mutex entry_mutex; std::mutex section_mutex; std::ofstream log_stream; @@ -69,7 +78,7 @@ private: // Logfile max level unsigned int loglevel = LL_INFO; - + // Verbosity (stdout) max level unsigned int verbosity = LL_WARNING; @@ -82,6 +91,8 @@ private: // A non-guarded flush() void _flush(); + void rotate_logs(const filesystem::path& folder, const filesystem::path& templ, int max_count); + public: static LogManager* get(); void configure(json config, const filesystem::path & defaultDir); @@ -98,6 +109,7 @@ public: std::vector messages(); bool log_console_enabled; + bool log_file_enabled; static const char* log_codes[]; }; diff --git a/NetworkClient.cpp b/NetworkClient.cpp index 90ef141a..5bbc2102 100644 --- a/NetworkClient.cpp +++ b/NetworkClient.cpp @@ -1,14 +1,17 @@ -/*-----------------------------------------*\ -| NetworkClient.cpp | -| | -| Client code for OpenRGB SDK | -| | -| Adam Honse (CalcProgrammer1) 5/9/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| NetworkClient.cpp | +| | +| OpenRGB SDK network client | +| | +| Adam Honse (CalcProgrammer1) 09 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include "NetworkClient.h" #include "RGBController_Network.h" -#include #ifdef _WIN32 #include @@ -28,12 +31,18 @@ using namespace std::chrono_literals; NetworkClient::NetworkClient(std::vector& control) : controllers(control) { - port_ip = "127.0.0.1"; - port_num = OPENRGB_SDK_PORT; - client_sock = -1; - server_connected = false; - server_controller_count = 0; - change_in_progress = false; + port_ip = "127.0.0.1"; + port_num = OPENRGB_SDK_PORT; + client_string_sent = false; + client_sock = -1; + protocol_initialized = false; + server_connected = false; + server_controller_count = 0; + server_controller_count_requested = false; + server_controller_count_received = false; + server_protocol_version = 0; + server_reinitialize = false; + change_in_progress = false; ListenThread = NULL; ConnectionThread = NULL; @@ -55,9 +64,9 @@ void NetworkClient::ClientInfoChanged() ClientInfoChangeMutex.lock(); ControllerListMutex.lock(); - /*-------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*---------------------------------------------------------*/ for(unsigned int callback_idx = 0; callback_idx < ClientInfoChangeCallbacks.size(); callback_idx++) { ClientInfoChangeCallbacks[callback_idx](ClientInfoChangeCallbackArgs[callback_idx]); @@ -100,7 +109,7 @@ bool NetworkClient::GetConnected() bool NetworkClient::GetOnline() { - return(server_connected && server_initialized); + return(server_connected && client_string_sent && protocol_initialized && server_initialized); } void NetworkClient::RegisterClientInfoChangeCallback(NetClientCallback new_callback, void * new_callback_arg) @@ -137,7 +146,9 @@ void NetworkClient::SetPort(unsigned short new_port) void NetworkClient::StartClient() { - //Start a TCP server and launch threads + /*---------------------------------------------------------*\ + | Start a TCP server and launch threads | + \*---------------------------------------------------------*/ char port_str[6]; snprintf(port_str, 6, "%d", port_num); @@ -145,20 +156,28 @@ void NetworkClient::StartClient() client_active = true; - //Start the connection thread + /*---------------------------------------------------------*\ + | Start the connection thread | + \*---------------------------------------------------------*/ ConnectionThread = new std::thread(&NetworkClient::ConnectionThreadFunction, this); - /*-------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*---------------------------------------------------------*/ ClientInfoChanged(); } void NetworkClient::StopClient() { + /*---------------------------------------------------------*\ + | Disconnect the server and set it as inactive | + \*---------------------------------------------------------*/ server_connected = false; client_active = false; + /*---------------------------------------------------------*\ + | Shut down and close the client socket | + \*---------------------------------------------------------*/ if(server_connected) { shutdown(client_sock, SD_RECEIVE); @@ -168,55 +187,75 @@ void NetworkClient::StopClient() client_active = false; server_connected = false; + /*---------------------------------------------------------*\ + | Close the listen thread | + \*---------------------------------------------------------*/ if(ListenThread) { ListenThread->join(); delete ListenThread; ListenThread = nullptr; } + + /*---------------------------------------------------------*\ + | Close the connection thread | + \*---------------------------------------------------------*/ if(ConnectionThread) { + connection_cv.notify_all(); ConnectionThread->join(); delete ConnectionThread; ConnectionThread = nullptr; } - /*-------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*---------------------------------------------------------*/ ClientInfoChanged(); } void NetworkClient::ConnectionThreadFunction() { - unsigned int requested_controllers; + std::unique_lock lock(connection_mutex); - //This thread manages the connection to the server + /*---------------------------------------------------------*\ + | This thread manages the connection to the server | + \*---------------------------------------------------------*/ while(client_active == true) { if(server_connected == false) { - //Connect to server and reconnect if the connection is lost + /*---------------------------------------------------------*\ + | Connect to server and reconnect if the connection is lost | + \*---------------------------------------------------------*/ server_initialized = false; - //Try to connect to server + /*---------------------------------------------------------*\ + | Try to connect to server | + \*---------------------------------------------------------*/ if(port.tcp_client_connect() == true) { client_sock = port.sock; printf( "Connected to server\n" ); - //Server is now connected + /*---------------------------------------------------------*\ + | Server is now connected | + \*---------------------------------------------------------*/ server_connected = true; - //Start the listener thread + /*---------------------------------------------------------*\ + | Start the listener thread | + \*---------------------------------------------------------*/ ListenThread = new std::thread(&NetworkClient::ListenThreadFunction, this); - //Server is not initialized + /*---------------------------------------------------------*\ + | Server is not initialized | + \*---------------------------------------------------------*/ server_initialized = false; - /*-------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*---------------------------------------------------------*/ ClientInfoChanged(); } else @@ -225,91 +264,152 @@ void NetworkClient::ConnectionThreadFunction() } } - if(server_initialized == false && server_connected == true) + /*-------------------------------------------------------------*\ + | Double-check client_active as it could have changed | + \*-------------------------------------------------------------*/ + if(client_active && ( protocol_initialized == false || client_string_sent == false || server_initialized == false ) && server_connected == true) { - unsigned int timeout_counter = 0; - requested_controllers = 0; - server_controller_count = 0; - server_controller_count_received = false; - server_protocol_version_received = false; - - //Wait for server to connect - std::this_thread::sleep_for(100ms); - - //Request protocol version - SendRequest_ProtocolVersion(); - - //Wait up to 1s for protocol version reply - - while(!server_protocol_version_received) + /*---------------------------------------------------------*\ + | Initialize protocol version if it hasn't already been | + | initialized | + \*---------------------------------------------------------*/ + if(!protocol_initialized) { - std::this_thread::sleep_for(5ms); + /*-----------------------------------------------------*\ + | Request protocol version | + \*-----------------------------------------------------*/ + SendRequest_ProtocolVersion(); - timeout_counter++; + /*-----------------------------------------------------*\ + | Wait up to 1s for protocol version reply | + \*-----------------------------------------------------*/ + unsigned int timeout_counter = 0; - /*-------------------------------------------------*\ - | If no protocol version received within 1s, assume | - | the server doesn't support protocol versioning | - | and use protocol version 0 | - \*-------------------------------------------------*/ - if(timeout_counter > 200) + while(!server_protocol_version_received) { - server_protocol_version = 0; - server_protocol_version_received = true; + connection_cv.wait_for(lock, 5ms); + if(!client_active) + { + break; + } + + timeout_counter++; + + /*-------------------------------------------------*\ + | If no protocol version received within 1s, assume | + | the server doesn't support protocol versioning | + | and use protocol version 0 | + \*-------------------------------------------------*/ + if(timeout_counter > 200) + { + server_protocol_version = 0; + server_protocol_version_received = true; + } + } + + protocol_initialized = true; + } + + /*---------------------------------------------------------*\ + | Send client string if it hasn't already been sent | + \*---------------------------------------------------------*/ + if(!client_string_sent) + { + /*-----------------------------------------------------*\ + | Once server is connected, send client string | + \*-----------------------------------------------------*/ + SendData_ClientString(); + + client_string_sent = true; + } + + /*---------------------------------------------------------*\ + | Initialize the server device list if it hasn't already | + | been initialized | + \*---------------------------------------------------------*/ + if(!server_initialized) + { + /*-----------------------------------------------------*\ + | Request the server controller count | + \*-----------------------------------------------------*/ + if(!server_controller_count_requested) + { + SendRequest_ControllerCount(); + + server_controller_count_requested = true; + } + else + { + /*-------------------------------------------------*\ + | Wait for the server controller count to be | + | received | + \*-------------------------------------------------*/ + if(server_controller_count_received) + { + /*---------------------------------------------*\ + | Once count is received, request controllers | + | When data is received, increment count of | + | requested controllers until all controllers | + | have been received | + \*---------------------------------------------*/ + if(requested_controllers < server_controller_count) + { + if(!controller_data_requested) + { + printf("Client: Requesting controller %d\r\n", requested_controllers); + + controller_data_received = false; + SendRequest_ControllerData(requested_controllers); + + controller_data_requested = true; + } + + if(controller_data_received) + { + requested_controllers++; + controller_data_requested = false; + } + } + else + { + ControllerListMutex.lock(); + + /*-----------------------------------------*\ + | All controllers received, add them to | + | master list | + \*-----------------------------------------*/ + printf("Client: All controllers received, adding them to master list\r\n"); + for(std::size_t controller_idx = 0; controller_idx < server_controllers.size(); controller_idx++) + { + controllers.push_back(server_controllers[controller_idx]); + } + + ControllerListMutex.unlock(); + + /*-----------------------------------------*\ + | Client info has changed, call the | + | callbacks | + \*-----------------------------------------*/ + ClientInfoChanged(); + + server_initialized = true; + } + } } } - //Once server is connected, send client string - SendData_ClientString(); - - //Request number of controllers - SendRequest_ControllerCount(); - - //Wait for server controller count - while(!server_controller_count_received) - { - std::this_thread::sleep_for(5ms); - } - - printf("Client: Received controller count from server: %d\r\n", server_controller_count); - - //Once count is received, request controllers - while(requested_controllers < server_controller_count) - { - printf("Client: Requesting controller %d\r\n", requested_controllers); - - controller_data_received = false; - SendRequest_ControllerData(requested_controllers); - - //Wait until controller is received - while(controller_data_received == false) - { - std::this_thread::sleep_for(5ms); - } - - requested_controllers++; - } - - ControllerListMutex.lock(); - - //All controllers received, add them to master list - printf("Client: All controllers received, adding them to master list\r\n"); - for(std::size_t controller_idx = 0; controller_idx < server_controllers.size(); controller_idx++) - { - controllers.push_back(server_controllers[controller_idx]); - } - - ControllerListMutex.unlock(); - - server_initialized = true; - - /*-------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*-------------------------------------------------*/ - ClientInfoChanged(); + /*---------------------------------------------------------*\ + | Wait 1 ms or until the thread is requested to stop | + \*---------------------------------------------------------*/ + connection_cv.wait_for(lock, 1ms); + } + else + { + /*---------------------------------------------------------*\ + | Wait 1 sec or until the thread is requested to stop | + \*---------------------------------------------------------*/ + connection_cv.wait_for(lock, 1s); } - - std::this_thread::sleep_for(1s); } } @@ -323,10 +423,10 @@ int NetworkClient::recv_select(SOCKET s, char *buf, int len, int flags) timeout.tv_sec = 5; timeout.tv_usec = 0; - FD_ZERO(&set); /* clear the set */ - FD_SET(s, &set); /* add our file descriptor to the set */ + FD_ZERO(&set); + FD_SET(s, &set); - int rv = select(s + 1, &set, NULL, NULL, &timeout); + int rv = select((int)s + 1, &set, NULL, NULL, &timeout); if(rv == SOCKET_ERROR || server_connected == false) { @@ -338,7 +438,6 @@ int NetworkClient::recv_select(SOCKET s, char *buf, int len, int flags) } else { - // socket has something to read return(recv(s, buf, len, flags)); } @@ -348,70 +447,41 @@ int NetworkClient::recv_select(SOCKET s, char *buf, int len, int flags) void NetworkClient::ListenThreadFunction() { printf("Network client listener started\n"); - //This thread handles messages received from the server + + /*---------------------------------------------------------*\ + | This thread handles messages received from the server | + \*---------------------------------------------------------*/ while(server_connected == true) { NetPacketHeader header; int bytes_read = 0; char * data = NULL; - //Read first byte of magic - bytes_read = recv_select(client_sock, &header.pkt_magic[0], 1, 0); - - if(bytes_read <= 0) + for(unsigned int i = 0; i < 4; i++) { - goto listen_done; + /*---------------------------------------------------------*\ + | Read byte of magic | + \*---------------------------------------------------------*/ + bytes_read = recv_select(client_sock, &header.pkt_magic[i], 1, 0); + + if(bytes_read <= 0) + { + goto listen_done; + } + + /*---------------------------------------------------------*\ + | Test characters of magic "ORGB" | + \*---------------------------------------------------------*/ + if(header.pkt_magic[i] != openrgb_sdk_magic[i]) + { + continue; + } } - //Test first character of magic - 'O' - if(header.pkt_magic[0] != 'O') - { - continue; - } - - //Read second byte of magic - bytes_read = recv_select(client_sock, &header.pkt_magic[1], 1, 0); - - if(bytes_read <= 0) - { - goto listen_done; - } - - //Test second character of magic - 'R' - if(header.pkt_magic[1] != 'R') - { - continue; - } - - //Read third byte of magic - bytes_read = recv_select(client_sock, &header.pkt_magic[2], 1, 0); - - if(bytes_read <= 0) - { - goto listen_done; - } - - //Test third character of magic - 'G' - if(header.pkt_magic[2] != 'G') - { - continue; - } - - //Read fourth byte of magic - bytes_read = recv_select(client_sock, &header.pkt_magic[3], 1, 0); - - if(bytes_read <= 0) - { - goto listen_done; - } - - //Test fourth character of magic - 'B' - if(header.pkt_magic[3] != 'B') - { - continue; - } - - //If we get to this point, the magic is correct. Read the rest of the header + /*---------------------------------------------------------*\ + | If we get to this point, the magic is correct. Read the | + | rest of the header | + \*---------------------------------------------------------*/ bytes_read = 0; do { @@ -428,7 +498,9 @@ void NetworkClient::ListenThreadFunction() } while(bytes_read != sizeof(header) - sizeof(header.pkt_magic)); - //Header received, now receive the data + /*---------------------------------------------------------*\ + | Header received, now receive the data | + \*---------------------------------------------------------*/ if(header.pkt_size > 0) { bytes_read = 0; @@ -450,7 +522,10 @@ void NetworkClient::ListenThreadFunction() } while ((unsigned int)bytes_read < header.pkt_size); } - //Entire request received, select functionality based on request ID + /*---------------------------------------------------------*\ + | Entire request received, select functionality based on | + | request ID | + \*---------------------------------------------------------*/ switch(header.pkt_id) { case NET_PACKET_ID_REQUEST_CONTROLLER_COUNT: @@ -475,8 +550,16 @@ void NetworkClient::ListenThreadFunction() listen_done: printf( "Client socket has been closed"); - server_initialized = false; - server_connected = false; + client_string_sent = false; + controller_data_requested = false; + controller_data_received = false; + protocol_initialized = false; + requested_controllers = 0; + server_controller_count = 0; + server_controller_count_requested = false; + server_controller_count_received = false; + server_initialized = false; + server_connected = false; ControllerListMutex.lock(); @@ -503,9 +586,9 @@ listen_done: ControllerListMutex.unlock(); - /*-------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*---------------------------------------------------------*/ ClientInfoChanged(); } @@ -528,35 +611,61 @@ void NetworkClient::ProcessReply_ControllerCount(unsigned int data_size, char * if(data_size == sizeof(unsigned int)) { memcpy(&server_controller_count, data, sizeof(unsigned int)); - server_controller_count_received = true; + + server_controller_count_received = true; + requested_controllers = 0; + controller_data_requested = false; + + printf("Client: Received controller count from server: %d\r\n", server_controller_count); } } -void NetworkClient::ProcessReply_ControllerData(unsigned int /*data_size*/, char * data, unsigned int dev_idx) +void NetworkClient::ProcessReply_ControllerData(unsigned int data_size, char * data, unsigned int dev_idx) { - RGBController_Network * new_controller = new RGBController_Network(this, dev_idx); - - new_controller->ReadDeviceDescription((unsigned char *)data, GetProtocolVersion()); - - ControllerListMutex.lock(); - - if(dev_idx >= server_controllers.size()) + /*---------------------------------------------------------*\ + | Verify the controller description size (first 4 bytes of | + | data) matches the packet size in the header | + \*---------------------------------------------------------*/ + if(data_size == *((unsigned int*)data)) { - server_controllers.push_back(new_controller); - } - else - { - server_controllers[dev_idx]->active_mode = new_controller->active_mode; - for(unsigned int i = 0; i < server_controllers[dev_idx]->zones.size(); i++) + RGBController_Network * new_controller = new RGBController_Network(this, dev_idx); + + new_controller->ReadDeviceDescription((unsigned char *)data, GetProtocolVersion()); + + /*-----------------------------------------------------*\ + | Mark this controller as remote owned | + \*-----------------------------------------------------*/ + new_controller->flags &= ~CONTROLLER_FLAG_LOCAL; + new_controller->flags |= CONTROLLER_FLAG_REMOTE; + + ControllerListMutex.lock(); + + if(dev_idx >= server_controllers.size()) { - server_controllers[dev_idx]->zones[i].leds_count = new_controller->zones[i].leds_count; + server_controllers.push_back(new_controller); } - delete new_controller; + else + { + server_controllers[dev_idx]->active_mode = new_controller->active_mode; + server_controllers[dev_idx]->leds.clear(); + server_controllers[dev_idx]->leds = new_controller->leds; + server_controllers[dev_idx]->colors.clear(); + server_controllers[dev_idx]->colors = new_controller->colors; + for(unsigned int i = 0; i < server_controllers[dev_idx]->zones.size(); i++) + { + server_controllers[dev_idx]->zones[i].leds_count = new_controller->zones[i].leds_count; + server_controllers[dev_idx]->zones[i].segments.clear(); + server_controllers[dev_idx]->zones[i].segments = new_controller->zones[i].segments; + } + server_controllers[dev_idx]->SetupColors(); + + delete new_controller; + } + + ControllerListMutex.unlock(); + + controller_data_received = true; } - - ControllerListMutex.unlock(); - - controller_data_received = true; } void NetworkClient::ProcessReply_ProtocolVersion(unsigned int data_size, char * data) @@ -572,6 +681,9 @@ void NetworkClient::ProcessRequest_DeviceListChanged() { change_in_progress = true; + /*---------------------------------------------------------*\ + | Delete all controllers from the server's controller list | + \*---------------------------------------------------------*/ ControllerListMutex.lock(); for(size_t server_controller_idx = 0; server_controller_idx < server_controllers.size(); server_controller_idx++) @@ -597,15 +709,23 @@ void NetworkClient::ProcessRequest_DeviceListChanged() ControllerListMutex.unlock(); - /*-------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*---------------------------------------------------------*/ ClientInfoChanged(); - /*-------------------------------------------------*\ - | Mark server as uninitialized and delete the list | - \*-------------------------------------------------*/ - server_initialized = false; + /*---------------------------------------------------------*\ + | Mark server as uninitialized and reset server | + | initialization state so that it restarts the list | + | requesting process | + \*---------------------------------------------------------*/ + controller_data_requested = false; + controller_data_received = false; + requested_controllers = 0; + server_controller_count = 0; + server_controller_count_requested = false; + server_controller_count_received = false; + server_initialized = false; change_in_progress = false; } @@ -614,33 +734,23 @@ void NetworkClient::SendData_ClientString() { NetPacketHeader reply_hdr; - reply_hdr.pkt_magic[0] = 'O'; - reply_hdr.pkt_magic[1] = 'R'; - reply_hdr.pkt_magic[2] = 'G'; - reply_hdr.pkt_magic[3] = 'B'; - - reply_hdr.pkt_dev_idx = 0; - reply_hdr.pkt_id = NET_PACKET_ID_SET_CLIENT_NAME; - reply_hdr.pkt_size = strlen(client_name.c_str()) + 1; + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_SET_CLIENT_NAME, (unsigned int)strlen(client_name.c_str()) + 1); + send_in_progress.lock(); send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); send(client_sock, (char *)client_name.c_str(), reply_hdr.pkt_size, MSG_NOSIGNAL); + send_in_progress.unlock(); } void NetworkClient::SendRequest_ControllerCount() { NetPacketHeader request_hdr; - request_hdr.pkt_magic[0] = 'O'; - request_hdr.pkt_magic[1] = 'R'; - request_hdr.pkt_magic[2] = 'G'; - request_hdr.pkt_magic[3] = 'B'; - - request_hdr.pkt_dev_idx = 0; - request_hdr.pkt_id = NET_PACKET_ID_REQUEST_CONTROLLER_COUNT; - request_hdr.pkt_size = 0; + InitNetPacketHeader(&request_hdr, 0, NET_PACKET_ID_REQUEST_CONTROLLER_COUNT, 0); + send_in_progress.lock(); send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send_in_progress.unlock(); } void NetworkClient::SendRequest_ControllerData(unsigned int dev_idx) @@ -650,10 +760,7 @@ void NetworkClient::SendRequest_ControllerData(unsigned int dev_idx) controller_data_received = false; - request_hdr.pkt_magic[0] = 'O'; - request_hdr.pkt_magic[1] = 'R'; - request_hdr.pkt_magic[2] = 'G'; - request_hdr.pkt_magic[3] = 'B'; + memcpy(request_hdr.pkt_magic, openrgb_sdk_magic, sizeof(openrgb_sdk_magic)); request_hdr.pkt_dev_idx = dev_idx; request_hdr.pkt_id = NET_PACKET_ID_REQUEST_CONTROLLER_DATA; @@ -662,7 +769,9 @@ void NetworkClient::SendRequest_ControllerData(unsigned int dev_idx) { request_hdr.pkt_size = 0; + send_in_progress.lock(); send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send_in_progress.unlock(); } else { @@ -681,8 +790,10 @@ void NetworkClient::SendRequest_ControllerData(unsigned int dev_idx) protocol_version = server_protocol_version; } + send_in_progress.lock(); send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); send(client_sock, (char *)&protocol_version, sizeof(unsigned int), MSG_NOSIGNAL); + send_in_progress.unlock(); } } @@ -691,19 +802,65 @@ void NetworkClient::SendRequest_ProtocolVersion() NetPacketHeader request_hdr; unsigned int request_data; - request_hdr.pkt_magic[0] = 'O'; - request_hdr.pkt_magic[1] = 'R'; - request_hdr.pkt_magic[2] = 'G'; - request_hdr.pkt_magic[3] = 'B'; - - request_hdr.pkt_dev_idx = 0; - request_hdr.pkt_id = NET_PACKET_ID_REQUEST_PROTOCOL_VERSION; - request_hdr.pkt_size = sizeof(unsigned int); + InitNetPacketHeader(&request_hdr, 0, NET_PACKET_ID_REQUEST_PROTOCOL_VERSION, sizeof(unsigned int)); request_data = OPENRGB_SDK_PROTOCOL_VERSION; + send_in_progress.lock(); send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); send(client_sock, (char *)&request_data, sizeof(unsigned int), MSG_NOSIGNAL); + send_in_progress.unlock(); +} + +void NetworkClient::SendRequest_RescanDevices() +{ + if(GetProtocolVersion() >= 5) + { + NetPacketHeader request_hdr; + + InitNetPacketHeader(&request_hdr, 0, NET_PACKET_ID_REQUEST_RESCAN_DEVICES, 0); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send_in_progress.unlock(); + } +} + +void NetworkClient::SendRequest_RGBController_ClearSegments(unsigned int dev_idx, int zone) +{ + if(change_in_progress) + { + return; + } + + NetPacketHeader request_hdr; + int request_data[1]; + + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_CLEARSEGMENTS, sizeof(request_data)); + + request_data[0] = zone; + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)&request_data, sizeof(request_data), MSG_NOSIGNAL); + send_in_progress.unlock(); +} + +void NetworkClient::SendRequest_RGBController_AddSegment(unsigned int dev_idx, unsigned char * data, unsigned int size) +{ + if(change_in_progress) + { + return; + } + + NetPacketHeader request_hdr; + + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_ADDSEGMENT, size); + + send_in_progress.lock(); + send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send(client_sock, (char *)data, size, 0); + send_in_progress.unlock(); } void NetworkClient::SendRequest_RGBController_ResizeZone(unsigned int dev_idx, int zone, int new_size) @@ -716,20 +873,15 @@ void NetworkClient::SendRequest_RGBController_ResizeZone(unsigned int dev_idx, i NetPacketHeader request_hdr; int request_data[2]; - request_hdr.pkt_magic[0] = 'O'; - request_hdr.pkt_magic[1] = 'R'; - request_hdr.pkt_magic[2] = 'G'; - request_hdr.pkt_magic[3] = 'B'; - - request_hdr.pkt_dev_idx = dev_idx; - request_hdr.pkt_id = NET_PACKET_ID_RGBCONTROLLER_RESIZEZONE; - request_hdr.pkt_size = sizeof(request_data); + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_RESIZEZONE, sizeof(request_data)); request_data[0] = zone; request_data[1] = new_size; + send_in_progress.lock(); send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); send(client_sock, (char *)&request_data, sizeof(request_data), MSG_NOSIGNAL); + send_in_progress.unlock(); } void NetworkClient::SendRequest_RGBController_UpdateLEDs(unsigned int dev_idx, unsigned char * data, unsigned int size) @@ -741,17 +893,12 @@ void NetworkClient::SendRequest_RGBController_UpdateLEDs(unsigned int dev_idx, u NetPacketHeader request_hdr; - request_hdr.pkt_magic[0] = 'O'; - request_hdr.pkt_magic[1] = 'R'; - request_hdr.pkt_magic[2] = 'G'; - request_hdr.pkt_magic[3] = 'B'; - - request_hdr.pkt_dev_idx = dev_idx; - request_hdr.pkt_id = NET_PACKET_ID_RGBCONTROLLER_UPDATELEDS; - request_hdr.pkt_size = size; + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_UPDATELEDS, size); + send_in_progress.lock(); send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); send(client_sock, (char *)data, size, 0); + send_in_progress.unlock(); } void NetworkClient::SendRequest_RGBController_UpdateZoneLEDs(unsigned int dev_idx, unsigned char * data, unsigned int size) @@ -763,17 +910,12 @@ void NetworkClient::SendRequest_RGBController_UpdateZoneLEDs(unsigned int dev_id NetPacketHeader request_hdr; - request_hdr.pkt_magic[0] = 'O'; - request_hdr.pkt_magic[1] = 'R'; - request_hdr.pkt_magic[2] = 'G'; - request_hdr.pkt_magic[3] = 'B'; - - request_hdr.pkt_dev_idx = dev_idx; - request_hdr.pkt_id = NET_PACKET_ID_RGBCONTROLLER_UPDATEZONELEDS; - request_hdr.pkt_size = size; + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_UPDATEZONELEDS, size); + send_in_progress.lock(); send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); send(client_sock, (char *)data, size, MSG_NOSIGNAL); + send_in_progress.unlock(); } void NetworkClient::SendRequest_RGBController_UpdateSingleLED(unsigned int dev_idx, unsigned char * data, unsigned int size) @@ -785,17 +927,12 @@ void NetworkClient::SendRequest_RGBController_UpdateSingleLED(unsigned int dev_i NetPacketHeader request_hdr; - request_hdr.pkt_magic[0] = 'O'; - request_hdr.pkt_magic[1] = 'R'; - request_hdr.pkt_magic[2] = 'G'; - request_hdr.pkt_magic[3] = 'B'; - - request_hdr.pkt_dev_idx = dev_idx; - request_hdr.pkt_id = NET_PACKET_ID_RGBCONTROLLER_UPDATESINGLELED; - request_hdr.pkt_size = size; + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_UPDATESINGLELED, size); + send_in_progress.lock(); send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); send(client_sock, (char *)data, size, MSG_NOSIGNAL); + send_in_progress.unlock(); } void NetworkClient::SendRequest_RGBController_SetCustomMode(unsigned int dev_idx) @@ -807,16 +944,11 @@ void NetworkClient::SendRequest_RGBController_SetCustomMode(unsigned int dev_idx NetPacketHeader request_hdr; - request_hdr.pkt_magic[0] = 'O'; - request_hdr.pkt_magic[1] = 'R'; - request_hdr.pkt_magic[2] = 'G'; - request_hdr.pkt_magic[3] = 'B'; - - request_hdr.pkt_dev_idx = dev_idx; - request_hdr.pkt_id = NET_PACKET_ID_RGBCONTROLLER_SETCUSTOMMODE; - request_hdr.pkt_size = 0; + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_SETCUSTOMMODE, 0); + send_in_progress.lock(); send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send_in_progress.unlock(); } void NetworkClient::SendRequest_RGBController_UpdateMode(unsigned int dev_idx, unsigned char * data, unsigned int size) @@ -828,17 +960,12 @@ void NetworkClient::SendRequest_RGBController_UpdateMode(unsigned int dev_idx, u NetPacketHeader request_hdr; - request_hdr.pkt_magic[0] = 'O'; - request_hdr.pkt_magic[1] = 'R'; - request_hdr.pkt_magic[2] = 'G'; - request_hdr.pkt_magic[3] = 'B'; - - request_hdr.pkt_dev_idx = dev_idx; - request_hdr.pkt_id = NET_PACKET_ID_RGBCONTROLLER_UPDATEMODE; - request_hdr.pkt_size = size; + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_UPDATEMODE, size); + send_in_progress.lock(); send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); send(client_sock, (char *)data, size, MSG_NOSIGNAL); + send_in_progress.unlock(); } void NetworkClient::SendRequest_RGBController_SaveMode(unsigned int dev_idx, unsigned char * data, unsigned int size) @@ -850,84 +977,59 @@ void NetworkClient::SendRequest_RGBController_SaveMode(unsigned int dev_idx, uns NetPacketHeader request_hdr; - request_hdr.pkt_magic[0] = 'O'; - request_hdr.pkt_magic[1] = 'R'; - request_hdr.pkt_magic[2] = 'G'; - request_hdr.pkt_magic[3] = 'B'; - - request_hdr.pkt_dev_idx = dev_idx; - request_hdr.pkt_id = NET_PACKET_ID_RGBCONTROLLER_SAVEMODE; - request_hdr.pkt_size = size; + InitNetPacketHeader(&request_hdr, dev_idx, NET_PACKET_ID_RGBCONTROLLER_SAVEMODE, size); + send_in_progress.lock(); send(client_sock, (char *)&request_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); send(client_sock, (char *)data, size, MSG_NOSIGNAL); + send_in_progress.unlock(); } void NetworkClient::SendRequest_LoadProfile(std::string profile_name) { NetPacketHeader reply_hdr; - reply_hdr.pkt_magic[0] = 'O'; - reply_hdr.pkt_magic[1] = 'R'; - reply_hdr.pkt_magic[2] = 'G'; - reply_hdr.pkt_magic[3] = 'B'; - - reply_hdr.pkt_dev_idx = 0; - reply_hdr.pkt_id = NET_PACKET_ID_REQUEST_LOAD_PROFILE; - reply_hdr.pkt_size = strlen(profile_name.c_str()) + 1; + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_REQUEST_LOAD_PROFILE, (unsigned int)strlen(profile_name.c_str()) + 1); + send_in_progress.lock(); send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); send(client_sock, (char *)profile_name.c_str(), reply_hdr.pkt_size, MSG_NOSIGNAL); + send_in_progress.unlock(); } void NetworkClient::SendRequest_SaveProfile(std::string profile_name) { NetPacketHeader reply_hdr; - reply_hdr.pkt_magic[0] = 'O'; - reply_hdr.pkt_magic[1] = 'R'; - reply_hdr.pkt_magic[2] = 'G'; - reply_hdr.pkt_magic[3] = 'B'; - - reply_hdr.pkt_dev_idx = 0; - reply_hdr.pkt_id = NET_PACKET_ID_REQUEST_SAVE_PROFILE; - reply_hdr.pkt_size = strlen(profile_name.c_str()) + 1; + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_REQUEST_SAVE_PROFILE, (unsigned int)strlen(profile_name.c_str()) + 1); + send_in_progress.lock(); send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); send(client_sock, (char *)profile_name.c_str(), reply_hdr.pkt_size, MSG_NOSIGNAL); + send_in_progress.unlock(); } void NetworkClient::SendRequest_DeleteProfile(std::string profile_name) { NetPacketHeader reply_hdr; - reply_hdr.pkt_magic[0] = 'O'; - reply_hdr.pkt_magic[1] = 'R'; - reply_hdr.pkt_magic[2] = 'G'; - reply_hdr.pkt_magic[3] = 'B'; - - reply_hdr.pkt_dev_idx = 0; - reply_hdr.pkt_id = NET_PACKET_ID_REQUEST_DELETE_PROFILE; - reply_hdr.pkt_size = strlen(profile_name.c_str()) + 1; + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_REQUEST_DELETE_PROFILE, (unsigned int)strlen(profile_name.c_str()) + 1); + send_in_progress.lock(); send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); send(client_sock, (char *)profile_name.c_str(), reply_hdr.pkt_size, MSG_NOSIGNAL); + send_in_progress.unlock(); } void NetworkClient::SendRequest_GetProfileList() { NetPacketHeader reply_hdr; - reply_hdr.pkt_magic[0] = 'O'; - reply_hdr.pkt_magic[1] = 'R'; - reply_hdr.pkt_magic[2] = 'G'; - reply_hdr.pkt_magic[3] = 'B'; - - reply_hdr.pkt_dev_idx = 0; - reply_hdr.pkt_id = NET_PACKET_ID_REQUEST_PROFILE_LIST; - reply_hdr.pkt_size = 0; + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_REQUEST_PROFILE_LIST, 0); + send_in_progress.lock(); send(client_sock, (char *)&reply_hdr, sizeof(NetPacketHeader), MSG_NOSIGNAL); + send_in_progress.unlock(); } std::vector * NetworkClient::ProcessReply_ProfileList(unsigned int data_size, char * data) @@ -938,7 +1040,9 @@ std::vector * NetworkClient::ProcessReply_ProfileList(unsigned int { profile_list = new std::vector(data_size); - // skip 4 first bytes (data length, unused) + /*---------------------------------------------------------*\ + | Skip 4 first bytes (data length, unused) | + \*---------------------------------------------------------*/ unsigned short data_ptr = sizeof(unsigned short); unsigned short num_profile; diff --git a/NetworkClient.h b/NetworkClient.h index 8d29287c..2fb7213b 100644 --- a/NetworkClient.h +++ b/NetworkClient.h @@ -1,19 +1,22 @@ -/*-----------------------------------------*\ -| NetworkClient.h | -| | -| Client header for OpenRGB SDK | -| | -| Adam Honse (CalcProgrammer1) 5/9/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| NetworkClient.h | +| | +| OpenRGB SDK network client | +| | +| Adam Honse (CalcProgrammer1) 09 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController.h" -#include "NetworkProtocol.h" -#include "net_port.h" +#pragma once #include #include - -#pragma once +#include +#include "RGBController.h" +#include "NetworkProtocol.h" +#include "net_port.h" typedef void (*NetClientCallback)(void *); @@ -45,7 +48,7 @@ public: void ListenThreadFunction(); void WaitOnControllerData(); - + void ProcessReply_ControllerCount(unsigned int data_size, char * data); void ProcessReply_ControllerData(unsigned int data_size, char * data, unsigned int dev_idx); void ProcessReply_ProtocolVersion(unsigned int data_size, char * data); @@ -58,6 +61,10 @@ public: void SendRequest_ControllerData(unsigned int dev_idx); void SendRequest_ProtocolVersion(); + void SendRequest_RescanDevices(); + + void SendRequest_RGBController_ClearSegments(unsigned int dev_idx, int zone); + void SendRequest_RGBController_AddSegment(unsigned int dev_idx, unsigned char * data, unsigned int size); void SendRequest_RGBController_ResizeZone(unsigned int dev_idx, int zone, int new_size); void SendRequest_RGBController_UpdateLEDs(unsigned int dev_idx, unsigned char * data, unsigned int size); @@ -91,15 +98,25 @@ private: net_port port; std::string port_ip; unsigned short port_num; - bool client_active; + std::atomic client_active; + bool client_string_sent; bool controller_data_received; + bool controller_data_requested; + bool protocol_initialized; bool server_connected; bool server_initialized; + bool server_reinitialize; unsigned int server_controller_count; + bool server_controller_count_requested; bool server_controller_count_received; unsigned int server_protocol_version; bool server_protocol_version_received; bool change_in_progress; + unsigned int requested_controllers; + std::mutex send_in_progress; + + std::mutex connection_mutex; + std::condition_variable connection_cv; std::thread * ConnectionThread; std::thread * ListenThread; diff --git a/NetworkProtocol.cpp b/NetworkProtocol.cpp index 53cb480c..53e98a46 100644 --- a/NetworkProtocol.cpp +++ b/NetworkProtocol.cpp @@ -1,20 +1,33 @@ +/*---------------------------------------------------------*\ +| NetworkProtocol.cpp | +| | +| OpenRGB SDK network protocol | +| | +| Adam Honse (CalcProgrammer1) 09 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include #include "NetworkProtocol.h" -NetPacketHeader * InitNetPacketHeader +/*-----------------------------------------------------*\ +| OpenRGB SDK Magic Value "ORGB" | +\*-----------------------------------------------------*/ +const char openrgb_sdk_magic[OPENRGB_SDK_MAGIC_SIZE] = { 'O', 'R', 'G', 'B' }; + +void InitNetPacketHeader ( + NetPacketHeader * pkt_hdr, unsigned int pkt_dev_idx, unsigned int pkt_id, unsigned int pkt_size ) { - NetPacketHeader * new_header = new NetPacketHeader; + memcpy(pkt_hdr->pkt_magic, openrgb_sdk_magic, sizeof(openrgb_sdk_magic)); - new_header->pkt_magic[0] = 'O'; - new_header->pkt_magic[1] = 'R'; - new_header->pkt_magic[2] = 'G'; - new_header->pkt_magic[3] = 'B'; - - new_header->pkt_dev_idx = pkt_dev_idx; - new_header->pkt_id = pkt_id; - new_header->pkt_size = pkt_size; -} \ No newline at end of file + pkt_hdr->pkt_dev_idx = pkt_dev_idx; + pkt_hdr->pkt_id = pkt_id; + pkt_hdr->pkt_size = pkt_size; +} diff --git a/NetworkProtocol.h b/NetworkProtocol.h index d484ce00..6719475c 100644 --- a/NetworkProtocol.h +++ b/NetworkProtocol.h @@ -1,10 +1,13 @@ -/*-----------------------------------------*\ -| NetworkProtocol.h | -| | -| Protocol header for OpenRGB SDK | -| | -| Adam Honse (CalcProgrammer1) 5/9/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| NetworkProtocol.h | +| | +| OpenRGB SDK network protocol | +| | +| Adam Honse (CalcProgrammer1) 09 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once @@ -16,8 +19,10 @@ | 2: Add profile controls (Release 0.6) | | 3: Add brightness field to modes (Release 0.7) | | 4: Add segments field to zones, network plugins (Release 0.9) | +| 5: Zone flags, controller flags, resizable effects-only zones | + (Release 1.0) | \*---------------------------------------------------------------------*/ -#define OPENRGB_SDK_PROTOCOL_VERSION 4 +#define OPENRGB_SDK_PROTOCOL_VERSION 5 /*-----------------------------------------------------*\ | Default Interface to bind to. | @@ -30,6 +35,12 @@ \*-----------------------------------------------------*/ #define OPENRGB_SDK_PORT 6742 +/*-----------------------------------------------------*\ +| OpenRGB SDK Magic Value "ORGB" | +\*-----------------------------------------------------*/ +#define OPENRGB_SDK_MAGIC_SIZE 4 +extern const char openrgb_sdk_magic[OPENRGB_SDK_MAGIC_SIZE]; + typedef struct NetPacketHeader { char pkt_magic[4]; /* Magic value "ORGB" identifies beginning of packet */ @@ -52,6 +63,8 @@ enum NET_PACKET_ID_DEVICE_LIST_UPDATED = 100, /* Indicate to clients that device list has updated */ + NET_PACKET_ID_REQUEST_RESCAN_DEVICES = 140, /* Request rescan of devices */ + NET_PACKET_ID_REQUEST_PROFILE_LIST = 150, /* Request profile list */ NET_PACKET_ID_REQUEST_SAVE_PROFILE = 151, /* Save current configuration in a new profile */ NET_PACKET_ID_REQUEST_LOAD_PROFILE = 152, /* Load a given profile */ @@ -64,6 +77,8 @@ enum | RGBController class functions | \*----------------------------------------------------------------------------------------------------------*/ NET_PACKET_ID_RGBCONTROLLER_RESIZEZONE = 1000, /* RGBController::ResizeZone() */ + NET_PACKET_ID_RGBCONTROLLER_CLEARSEGMENTS = 1001, /* RGBController::ClearSegments() */ + NET_PACKET_ID_RGBCONTROLLER_ADDSEGMENT = 1002, /* RGBController::AddSegment() */ NET_PACKET_ID_RGBCONTROLLER_UPDATELEDS = 1050, /* RGBController::UpdateLEDs() */ NET_PACKET_ID_RGBCONTROLLER_UPDATEZONELEDS = 1051, /* RGBController::UpdateZoneLEDs() */ @@ -73,3 +88,11 @@ enum NET_PACKET_ID_RGBCONTROLLER_UPDATEMODE = 1101, /* RGBController::UpdateMode() */ NET_PACKET_ID_RGBCONTROLLER_SAVEMODE = 1102, /* RGBController::SaveMode() */ }; + +void InitNetPacketHeader + ( + NetPacketHeader * pkt_hdr, + unsigned int pkt_dev_idx, + unsigned int pkt_id, + unsigned int pkt_size + ); diff --git a/NetworkServer.cpp b/NetworkServer.cpp index d0839e8d..0499a317 100644 --- a/NetworkServer.cpp +++ b/NetworkServer.cpp @@ -1,14 +1,17 @@ -/*-----------------------------------------*\ -| NetworkServer.cpp | -| | -| Server code for OpenRGB SDK | -| | -| Adam Honse (CalcProgrammer1) 5/9/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| NetworkServer.cpp | +| | +| OpenRGB SDK network server | +| | +| Adam Honse (CalcProgrammer1) 09 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ +#include #include "NetworkServer.h" #include "LogManager.h" -#include #ifndef WIN32 #include @@ -46,7 +49,7 @@ NetworkClientInfo::~NetworkClientInfo() { if(client_sock != INVALID_SOCKET) { - LOG_INFO("Closing server connection: %s", client_ip.c_str()); + LOG_INFO("[NetworkServer] Closing server connection: %s", client_ip.c_str()); delete client_listen_thread; shutdown(client_sock, SD_RECEIVE); closesocket(client_sock); @@ -55,14 +58,17 @@ NetworkClientInfo::~NetworkClientInfo() NetworkServer::NetworkServer(std::vector& control) : controllers(control) { - host = OPENRGB_SDK_HOST; - port_num = OPENRGB_SDK_PORT; - server_online = false; - server_listening = false; + host = OPENRGB_SDK_HOST; + port_num = OPENRGB_SDK_PORT; + server_online = false; + server_listening = false; + legacy_workaround_enabled = false; + for(int i = 0; i < MAXSOCK; i++) { ConnectionThread[i] = nullptr; } + profile_manager = nullptr; } @@ -75,9 +81,9 @@ void NetworkServer::ClientInfoChanged() { ClientInfoChangeMutex.lock(); - /*-------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*---------------------------------------------------------*/ for(unsigned int callback_idx = 0; callback_idx < ClientInfoChangeCallbacks.size(); callback_idx++) { ClientInfoChangeCallbacks[callback_idx](ClientInfoChangeCallbackArgs[callback_idx]); @@ -88,10 +94,10 @@ void NetworkServer::ClientInfoChanged() void NetworkServer::DeviceListChanged() { - /*-------------------------------------------------*\ - | Indicate to the clients that the controller list | - | has changed | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Indicate to the clients that the controller list has | + | changed | + \*---------------------------------------------------------*/ for(unsigned int client_idx = 0; client_idx < ServerClients.size(); client_idx++) { SendRequest_DeviceListChanged(ServerClients[client_idx]->client_sock); @@ -102,9 +108,9 @@ void NetworkServer::ServerListeningChanged() { ServerListeningChangeMutex.lock(); - /*-------------------------------------------------*\ - | Server state has changed, call the callbacks | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Server state has changed, call the callbacks | + \*---------------------------------------------------------*/ for(unsigned int callback_idx = 0; callback_idx < ServerListeningChangeCallbacks.size(); callback_idx++) { ServerListeningChangeCallbacks[callback_idx](ServerListeningChangeCallbackArgs[callback_idx]); @@ -135,7 +141,7 @@ bool NetworkServer::GetListening() unsigned int NetworkServer::GetNumClients() { - return ServerClients.size(); + return (unsigned int)ServerClients.size(); } const char * NetworkServer::GetClientString(unsigned int client_num) @@ -218,6 +224,11 @@ void NetworkServer::SetHost(std::string new_host) } } +void NetworkServer::SetLegacyWorkaroundEnable(bool enable) +{ + legacy_workaround_enabled = enable; +} + void NetworkServer::SetPort(unsigned short new_port) { if(server_online == false) @@ -230,15 +241,18 @@ void NetworkServer::StartServer() { int err; struct addrinfo hints, *res, *result; - //Start a TCP server and launch threads + + /*---------------------------------------------------------*\ + | Start a TCP server and launch threads | + \*---------------------------------------------------------*/ char port_str[6]; snprintf(port_str, 6, "%d", port_num); socket_count = 0; - /*-------------------------------------------------*\ - | Windows requires WSAStartup before using sockets | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Windows requires WSAStartup before using sockets | + \*---------------------------------------------------------*/ #ifdef WIN32 if(WSAStartup(MAKEWORD(2, 2), &wsa) != NO_ERROR) { @@ -255,64 +269,66 @@ void NetworkServer::StartServer() if(err) { - printf("Error: Unable to get address.\n"); + LOG_ERROR("[NetworkServer] Unable to get address."); WSACleanup(); return; } - /*-------------------------------------------------*\ - | Create a server socket for each address returned. | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Create a server socket for each address returned. | + \*---------------------------------------------------------*/ for(res = result; res && socket_count < MAXSOCK; res = res->ai_next) { server_sock[socket_count] = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - + if(server_sock[socket_count] == INVALID_SOCKET) { - printf("Error: network socket could not be created\n"); + LOG_ERROR("[NetworkServer] Network socket could not be created."); WSACleanup(); return; } - /*-------------------------------------------------*\ - | Bind the server socket | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Bind the server socket | + \*---------------------------------------------------------*/ if(bind(server_sock[socket_count], res->ai_addr, res->ai_addrlen) == SOCKET_ERROR) { if(errno == EADDRINUSE) { - printf("Error: Could not bind network socket \nIs port %hu already being used?\n", GetPort()); + LOG_ERROR("[NetworkServer] Could not bind network socket. Is port %hu already being used?", GetPort()); } else if(errno == EACCES) { - printf("Error: Access to socket was denied.\n"); + LOG_ERROR("[NetworkServer] Could not bind network socket. Access to socket was denied."); } else if(errno == EBADF) { - printf("Error: sockfd is not a valid file descriptor.\n"); + LOG_ERROR("[NetworkServer] Could not bind network socket. sockfd is not a valid file descriptor."); } else if(errno == EINVAL) { - printf("Error: The socket is already bound to an address, or addrlen is wrong, or addr is not a valid address for this socket's domain..\n"); + LOG_ERROR("[NetworkServer] Could not bind network socket. The socket is already bound to an address, or addrlen is wrong, or addr is not a valid address for this socket's domain."); } else if(errno == ENOTSOCK) { - printf("Error: The file descriptor sockfd does not refer to a socket.\n"); + LOG_ERROR("[NetworkServer] Could not bind network socket. The file descriptor sockfd does not refer to a socket."); } else { - // could be a linux specific error - // https://man7.org/linux/man-pages/man2/bind.2.html - printf("Error: Could not bind network socket, error code:%d\n", errno); + /*---------------------------------------------------------*\ + | errno could be a Linux specific error, see: | + | https://man7.org/linux/man-pages/man2/bind.2.html | + \*---------------------------------------------------------*/ + LOG_ERROR("[NetworkServer] Could not bind network socket. Error code: %d.", errno); } WSACleanup(); return; } - /*-------------------------------------------------*\ - | Set socket options - no delay | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Set socket options - no delay | + \*---------------------------------------------------------*/ setsockopt(server_sock[socket_count], IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)); socket_count += 1; @@ -320,10 +336,10 @@ void NetworkServer::StartServer() freeaddrinfo(result); server_online = true; - - /*-------------------------------------------------*\ - | Start the connection thread | - \*-------------------------------------------------*/ + + /*---------------------------------------------------------*\ + | Start the connection thread | + \*---------------------------------------------------------*/ for(int curr_socket = 0; curr_socket < socket_count; curr_socket++) { ConnectionThread[curr_socket] = new std::thread(&NetworkServer::ConnectionThreadFunction, this, curr_socket); @@ -364,32 +380,34 @@ void NetworkServer::StopServer() socket_count = 0; - /*-------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*---------------------------------------------------------*/ ClientInfoChanged(); } void NetworkServer::ConnectionThreadFunction(int socket_idx) { - //This thread handles client connections + /*---------------------------------------------------------*\ + | This thread handles client connections | + \*---------------------------------------------------------*/ + LOG_INFO("[NetworkServer] Network connection thread started on port %hu", GetPort()); - printf("Network connection thread started on port %hu\n", GetPort()); while(server_online == true) { - /*-------------------------------------------------*\ - | Create new socket for client connection | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Create new socket for client connection | + \*---------------------------------------------------------*/ NetworkClientInfo * client_info = new NetworkClientInfo(); - /*-------------------------------------------------*\ - | Listen for incoming client connection on the | - | server socket. This call blocks until a | - | connection is established | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Listen for incoming client connection on the server | + | socket. This call blocks until a connection is | + | established | + \*---------------------------------------------------------*/ if(listen(server_sock[socket_idx], 10) < 0) { - printf("Connection thread closed\r\n"); + LOG_INFO("[NetworkServer] Connection thread closed"); server_online = false; return; @@ -398,14 +416,14 @@ void NetworkServer::ConnectionThreadFunction(int socket_idx) server_listening = true; ServerListeningChanged(); - /*-------------------------------------------------*\ - | Accept the client connection | - \*-------------------------------------------------*/ - client_info->client_sock = accept_select(server_sock[socket_idx]); + /*---------------------------------------------------------*\ + | Accept the client connection | + \*---------------------------------------------------------*/ + client_info->client_sock = accept_select((int)server_sock[socket_idx]); if(client_info->client_sock < 0) { - printf("Connection thread closed\r\n"); + LOG_INFO("[NetworkServer] Connection thread closed"); server_online = false; server_listening = false; @@ -414,23 +432,23 @@ void NetworkServer::ConnectionThreadFunction(int socket_idx) return; } - /*-------------------------------------------------*\ - | Get the new client socket and store it in the | - | clients vector | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Get the new client socket and store it in the clients | + | vector | + \*---------------------------------------------------------*/ u_long arg = 0; ioctlsocket(client_info->client_sock, FIONBIO, &arg); setsockopt(client_info->client_sock, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)); - /*-------------------------------------------------*\ - | Discover the remote hosts IP | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Discover the remote hosts IP | + \*---------------------------------------------------------*/ struct sockaddr_storage tmp_addr; char ipstr[INET6_ADDRSTRLEN]; socklen_t len; len = sizeof(tmp_addr); getpeername(client_info->client_sock, (struct sockaddr*)&tmp_addr, &len); - + if(tmp_addr.ss_family == AF_INET) { struct sockaddr_in *s_4 = (struct sockaddr_in *)&tmp_addr; @@ -444,23 +462,27 @@ void NetworkServer::ConnectionThreadFunction(int socket_idx) client_info->client_ip = ipstr; } - /* We need to lock before the thread could possibly finish */ + /*---------------------------------------------------------*\ + | We need to lock before the thread could possibly finish | + \*---------------------------------------------------------*/ ServerClientsMutex.lock(); - //Start a listener thread for the new client socket + /*---------------------------------------------------------*\ + | Start a listener thread for the new client socket | + \*---------------------------------------------------------*/ client_info->client_listen_thread = new std::thread(&NetworkServer::ListenThreadFunction, this, client_info); client_info->client_listen_thread->detach(); ServerClients.push_back(client_info); ServerClientsMutex.unlock(); - /*-------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*---------------------------------------------------------*/ ClientInfoChanged(); } - printf("Connection thread closed\r\n"); + LOG_INFO("[NetworkServer] Connection thread closed"); server_online = false; server_listening = false; ServerListeningChanged(); @@ -476,8 +498,8 @@ int NetworkServer::accept_select(int sockfd) timeout.tv_sec = TCP_TIMEOUT_SECONDS; timeout.tv_usec = 0; - FD_ZERO(&set); /* clear the set */ - FD_SET(sockfd, &set); /* add our file descriptor to the set */ + FD_ZERO(&set); + FD_SET(sockfd, &set); int rv = select(sockfd + 1, &set, NULL, NULL, &timeout); @@ -491,8 +513,7 @@ int NetworkServer::accept_select(int sockfd) } else { - // socket has something to read - return(accept(sockfd, NULL, NULL)); + return(accept((int)sockfd, NULL, NULL)); } } } @@ -507,10 +528,10 @@ int NetworkServer::recv_select(SOCKET s, char *buf, int len, int flags) timeout.tv_sec = TCP_TIMEOUT_SECONDS; timeout.tv_usec = 0; - FD_ZERO(&set); /* clear the set */ - FD_SET(s, &set); /* add our file descriptor to the set */ + FD_ZERO(&set); + FD_SET(s, &set); - int rv = select(s + 1, &set, NULL, NULL, &timeout); + int rv = select((int)s + 1, &set, NULL, NULL, &timeout); if(rv == SOCKET_ERROR || server_online == false) { @@ -522,7 +543,6 @@ int NetworkServer::recv_select(SOCKET s, char *buf, int len, int flags) } else { - // socket has something to read return(recv(s, buf, len, flags)); } } @@ -532,71 +552,44 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) { SOCKET client_sock = client_info->client_sock; - printf("Network server started\n"); - //This thread handles messages received from clients + LOG_INFO("[NetworkServer] Network server started"); + + /*---------------------------------------------------------*\ + | This thread handles messages received from clients | + \*---------------------------------------------------------*/ while(server_online == true) { NetPacketHeader header; int bytes_read = 0; char * data = NULL; - //Read first byte of magic - bytes_read = recv_select(client_sock, &header.pkt_magic[0], 1, 0); - - if(bytes_read <= 0) + for(unsigned int i = 0; i < 4; i++) { - goto listen_done; + /*---------------------------------------------------------*\ + | Read byte of magic | + \*---------------------------------------------------------*/ + bytes_read = recv_select(client_sock, &header.pkt_magic[i], 1, 0); + + if(bytes_read <= 0) + { + LOG_ERROR("[NetworkServer] recv_select failed receiving magic, closing listener"); + goto listen_done; + } + + /*---------------------------------------------------------*\ + | Test characters of magic "ORGB" | + \*---------------------------------------------------------*/ + if(header.pkt_magic[i] != openrgb_sdk_magic[i]) + { + LOG_ERROR("[NetworkServer] Invalid magic received"); + continue; + } } - //Test first character of magic - 'O' - if(header.pkt_magic[0] != 'O') - { - continue; - } - - //Read second byte of magic - bytes_read = recv_select(client_sock, &header.pkt_magic[1], 1, 0); - - if(bytes_read <= 0) - { - goto listen_done; - } - - //Test second character of magic - 'R' - if(header.pkt_magic[1] != 'R') - { - continue; - } - - //Read third byte of magic - bytes_read = recv_select(client_sock, &header.pkt_magic[2], 1, 0); - - if(bytes_read <= 0) - { - goto listen_done; - } - - //Test third character of magic - 'G' - if(header.pkt_magic[2] != 'G') - { - continue; - } - - //Read fourth byte of magic - bytes_read = recv_select(client_sock, &header.pkt_magic[3], 1, 0); - - if(bytes_read <= 0) - { - goto listen_done; - } - - //Test fourth character of magic - 'B' - if(header.pkt_magic[3] != 'B') - { - continue; - } - - //If we get to this point, the magic is correct. Read the rest of the header + /*---------------------------------------------------------*\ + | If we get to this point, the magic is correct. Read the | + | rest of the header | + \*---------------------------------------------------------*/ bytes_read = 0; do { @@ -608,16 +601,18 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) if(tmp_bytes_read <= 0) { + LOG_ERROR("[NetworkServer] recv_select failed receiving header, closing listener"); goto listen_done; } } while(bytes_read != sizeof(header) - sizeof(header.pkt_magic)); - //Header received, now receive the data + /*---------------------------------------------------------*\ + | Header received, now receive the data | + \*---------------------------------------------------------*/ + bytes_read = 0; if(header.pkt_size > 0) { - bytes_read = 0; - data = new char[header.pkt_size]; do @@ -628,6 +623,7 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) if(tmp_bytes_read <= 0) { + LOG_ERROR("[NetworkServer] recv_select failed receiving data, closing listener"); goto listen_done; } bytes_read += tmp_bytes_read; @@ -635,7 +631,10 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) } while ((unsigned int)bytes_read < header.pkt_size); } - //Entire request received, select functionality based on request ID + /*---------------------------------------------------------*\ + | Entire request received, select functionality based on | + | request ID | + \*---------------------------------------------------------*/ switch(header.pkt_id) { case NET_PACKET_ID_REQUEST_CONTROLLER_COUNT: @@ -669,6 +668,10 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) ProcessRequest_ClientString(client_sock, header.pkt_size, data); break; + case NET_PACKET_ID_REQUEST_RESCAN_DEVICES: + ProcessRequest_RescanDevices(); + break; + case NET_PACKET_ID_RGBCONTROLLER_RESIZEZONE: if(data == NULL) { @@ -694,10 +697,30 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) break; } - if(header.pkt_dev_idx < controllers.size()) + /*---------------------------------------------------------*\ + | Verify the color description size (first 4 bytes of data) | + | matches the packet size in the header | + | | + | If protocol version is 4 or below and the legacy SDK | + | compatibility workaround is enabled, ignore this check. | + | This allows backwards compatibility with old versions of | + | SDK applications that didn't properly implement the size | + | field. | + \*---------------------------------------------------------*/ + if((header.pkt_size == *((unsigned int*)data)) + || ((client_info->client_protocol_version <= 4) + && (legacy_workaround_enabled))) { - controllers[header.pkt_dev_idx]->SetColorDescription((unsigned char *)data); - controllers[header.pkt_dev_idx]->UpdateLEDs(); + if(header.pkt_dev_idx < controllers.size()) + { + controllers[header.pkt_dev_idx]->SetColorDescription((unsigned char *)data); + controllers[header.pkt_dev_idx]->UpdateLEDs(); + } + } + else + { + LOG_ERROR("[NetworkServer] UpdateLEDs packet has invalid size. Packet size: %d, Data size: %d", header.pkt_size, *((unsigned int*)data)); + goto listen_done; } break; @@ -707,14 +730,34 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) break; } - if(header.pkt_dev_idx < controllers.size()) + /*---------------------------------------------------------*\ + | Verify the color description size (first 4 bytes of data) | + | matches the packet size in the header | + | | + | If protocol version is 4 or below and the legacy SDK | + | compatibility workaround is enabled, ignore this check. | + | This allows backwards compatibility with old versions of | + | SDK applications that didn't properly implement the size | + | field. | + \*---------------------------------------------------------*/ + if((header.pkt_size == *((unsigned int*)data)) + || ((client_info->client_protocol_version <= 4) + && (legacy_workaround_enabled))) { - int zone; + if(header.pkt_dev_idx < controllers.size()) + { + int zone; - memcpy(&zone, &data[sizeof(unsigned int)], sizeof(int)); + memcpy(&zone, &data[sizeof(unsigned int)], sizeof(int)); - controllers[header.pkt_dev_idx]->SetZoneColorDescription((unsigned char *)data); - controllers[header.pkt_dev_idx]->UpdateZoneLEDs(zone); + controllers[header.pkt_dev_idx]->SetZoneColorDescription((unsigned char *)data); + controllers[header.pkt_dev_idx]->UpdateZoneLEDs(zone); + } + } + else + { + LOG_ERROR("[NetworkServer] UpdateZoneLEDs packet has invalid size. Packet size: %d, Data size: %d", header.pkt_size, *((unsigned int*)data)); + goto listen_done; } break; @@ -724,14 +767,26 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) break; } - if(header.pkt_dev_idx < controllers.size()) + /*---------------------------------------------------------*\ + | Verify the single LED color description size (8 bytes) | + | matches the packet size in the header | + \*---------------------------------------------------------*/ + if(header.pkt_size == (sizeof(int) + sizeof(RGBColor))) { - int led; + if(header.pkt_dev_idx < controllers.size()) + { + int led; - memcpy(&led, data, sizeof(int)); + memcpy(&led, data, sizeof(int)); - controllers[header.pkt_dev_idx]->SetSingleLEDColorDescription((unsigned char *)data); - controllers[header.pkt_dev_idx]->UpdateSingleLED(led); + controllers[header.pkt_dev_idx]->SetSingleLEDColorDescription((unsigned char *)data); + controllers[header.pkt_dev_idx]->UpdateSingleLED(led); + } + } + else + { + LOG_ERROR("[NetworkServer] UpdateSingleLED packet has invalid size. Packet size: %d, Data size: %d", header.pkt_size, (sizeof(int) + sizeof(RGBColor))); + goto listen_done; } break; @@ -748,10 +803,30 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) break; } - if(header.pkt_dev_idx < controllers.size()) + /*---------------------------------------------------------*\ + | Verify the mode description size (first 4 bytes of data) | + | matches the packet size in the header | + | | + | If protocol version is 4 or below and the legacy SDK | + | compatibility workaround is enabled, ignore this check. | + | This allows backwards compatibility with old versions of | + | SDK applications that didn't properly implement the size | + | field. | + \*---------------------------------------------------------*/ + if((header.pkt_size == *((unsigned int*)data)) + || ((client_info->client_protocol_version <= 4) + && (legacy_workaround_enabled))) { - controllers[header.pkt_dev_idx]->SetModeDescription((unsigned char *)data, client_info->client_protocol_version); - controllers[header.pkt_dev_idx]->UpdateMode(); + if(header.pkt_dev_idx < controllers.size()) + { + controllers[header.pkt_dev_idx]->SetModeDescription((unsigned char *)data, client_info->client_protocol_version); + controllers[header.pkt_dev_idx]->UpdateMode(); + } + } + else + { + LOG_ERROR("[NetworkServer] UpdateMode packet has invalid size. Packet size: %d, Data size: %d", header.pkt_size, *((unsigned int*)data)); + goto listen_done; } break; @@ -761,10 +836,25 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) break; } - if(header.pkt_dev_idx < controllers.size()) + /*---------------------------------------------------------*\ + | Verify the mode description size (first 4 bytes of data) | + | matches the packet size in the header | + | | + | If protocol version is 4 or below and the legacy SDK | + | compatibility workaround is enabled, ignore this check. | + | This allows backwards compatibility with old versions of | + | SDK applications that didn't properly implement the size | + | field. | + \*---------------------------------------------------------*/ + if((header.pkt_size == *((unsigned int*)data)) + || ((client_info->client_protocol_version <= 4) + && (legacy_workaround_enabled))) { - controllers[header.pkt_dev_idx]->SetModeDescription((unsigned char *)data, client_info->client_protocol_version); - controllers[header.pkt_dev_idx]->SaveMode(); + if(header.pkt_dev_idx < controllers.size()) + { + controllers[header.pkt_dev_idx]->SetModeDescription((unsigned char *)data, client_info->client_protocol_version); + controllers[header.pkt_dev_idx]->SaveMode(); + } } break; @@ -780,7 +870,10 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) if(profile_manager) { - profile_manager->SaveProfile(data); + std::string profile_name; + profile_name.assign(data, header.pkt_size); + + profile_manager->SaveProfile(profile_name); } break; @@ -793,7 +886,10 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) if(profile_manager) { - profile_manager->LoadProfile(data); + std::string profile_name; + profile_name.assign(data, header.pkt_size); + + profile_manager->LoadProfile(profile_name); } for(RGBController* controller : controllers) @@ -811,7 +907,10 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) if(profile_manager) { - profile_manager->DeleteProfile(data); + std::string profile_name; + profile_name.assign(data, header.pkt_size); + + profile_manager->DeleteProfile(profile_name); } break; @@ -837,6 +936,41 @@ void NetworkServer::ListenThreadFunction(NetworkClientInfo * client_info) } break; } + break; + + case NET_PACKET_ID_RGBCONTROLLER_CLEARSEGMENTS: + if(data == NULL) + { + break; + } + + if((header.pkt_dev_idx < controllers.size()) && (header.pkt_size == sizeof(int))) + { + int zone; + + memcpy(&zone, data, sizeof(int)); + + controllers[header.pkt_dev_idx]->ClearSegments(zone); + profile_manager->SaveProfile("sizes", true); + } + break; + + case NET_PACKET_ID_RGBCONTROLLER_ADDSEGMENT: + { + /*---------------------------------------------------------*\ + | Verify the segment description size (first 4 bytes of | + | data) matches the packet size in the header | + \*---------------------------------------------------------*/ + if(header.pkt_size == *((unsigned int*)data)) + { + if(header.pkt_dev_idx < controllers.size()) + { + controllers[header.pkt_dev_idx]->SetSegmentDescription((unsigned char *)data); + profile_manager->SaveProfile("sizes", true); + } + } + } + break; } delete[] data; @@ -860,9 +994,9 @@ listen_done: ServerClientsMutex.unlock(); - /*-------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*---------------------------------------------------------*/ ClientInfoChanged(); } @@ -891,49 +1025,49 @@ void NetworkServer::ProcessRequest_ClientProtocolVersion(SOCKET client_sock, uns } ServerClientsMutex.unlock(); - /*-------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*---------------------------------------------------------*/ ClientInfoChanged(); } -void NetworkServer::ProcessRequest_ClientString(SOCKET client_sock, unsigned int /*data_size*/, char * data) +void NetworkServer::ProcessRequest_ClientString(SOCKET client_sock, unsigned int data_size, char * data) { ServerClientsMutex.lock(); for(unsigned int this_idx = 0; this_idx < ServerClients.size(); this_idx++) { if(ServerClients[this_idx]->client_sock == client_sock) { - ServerClients[this_idx]->client_string = data; + ServerClients[this_idx]->client_string.assign(data, data_size); break; } } ServerClientsMutex.unlock(); - /*-------------------------------------------------*\ - | Client info has changed, call the callbacks | - \*-------------------------------------------------*/ + /*---------------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*---------------------------------------------------------*/ ClientInfoChanged(); } +void NetworkServer::ProcessRequest_RescanDevices() +{ + ResourceManager::get()->DetectDevices(); +} + void NetworkServer::SendReply_ControllerCount(SOCKET client_sock) { NetPacketHeader reply_hdr; unsigned int reply_data; - reply_hdr.pkt_magic[0] = 'O'; - reply_hdr.pkt_magic[1] = 'R'; - reply_hdr.pkt_magic[2] = 'G'; - reply_hdr.pkt_magic[3] = 'B'; + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_REQUEST_CONTROLLER_COUNT, sizeof(unsigned int)); - reply_hdr.pkt_dev_idx = 0; - reply_hdr.pkt_id = NET_PACKET_ID_REQUEST_CONTROLLER_COUNT; - reply_hdr.pkt_size = sizeof(unsigned int); - - reply_data = controllers.size(); + reply_data = (unsigned int)controllers.size(); + send_in_progress.lock(); send(client_sock, (const char *)&reply_hdr, sizeof(NetPacketHeader), 0); send(client_sock, (const char *)&reply_data, sizeof(unsigned int), 0); + send_in_progress.unlock(); } void NetworkServer::SendReply_ControllerData(SOCKET client_sock, unsigned int dev_idx, unsigned int protocol_version) @@ -946,17 +1080,12 @@ void NetworkServer::SendReply_ControllerData(SOCKET client_sock, unsigned int de memcpy(&reply_size, reply_data, sizeof(reply_size)); - reply_hdr.pkt_magic[0] = 'O'; - reply_hdr.pkt_magic[1] = 'R'; - reply_hdr.pkt_magic[2] = 'G'; - reply_hdr.pkt_magic[3] = 'B'; - - reply_hdr.pkt_dev_idx = dev_idx; - reply_hdr.pkt_id = NET_PACKET_ID_REQUEST_CONTROLLER_DATA; - reply_hdr.pkt_size = reply_size; + InitNetPacketHeader(&reply_hdr, dev_idx, NET_PACKET_ID_REQUEST_CONTROLLER_DATA, reply_size); + send_in_progress.lock(); send(client_sock, (const char *)&reply_hdr, sizeof(NetPacketHeader), 0); send(client_sock, (const char *)reply_data, reply_size, 0); + send_in_progress.unlock(); delete[] reply_data; } @@ -967,35 +1096,25 @@ void NetworkServer::SendReply_ProtocolVersion(SOCKET client_sock) NetPacketHeader reply_hdr; unsigned int reply_data; - reply_hdr.pkt_magic[0] = 'O'; - reply_hdr.pkt_magic[1] = 'R'; - reply_hdr.pkt_magic[2] = 'G'; - reply_hdr.pkt_magic[3] = 'B'; + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_REQUEST_PROTOCOL_VERSION, sizeof(unsigned int)); - reply_hdr.pkt_dev_idx = 0; - reply_hdr.pkt_id = NET_PACKET_ID_REQUEST_PROTOCOL_VERSION; - reply_hdr.pkt_size = sizeof(unsigned int); - - reply_data = OPENRGB_SDK_PROTOCOL_VERSION; + reply_data = OPENRGB_SDK_PROTOCOL_VERSION; + send_in_progress.lock(); send(client_sock, (const char *)&reply_hdr, sizeof(NetPacketHeader), 0); send(client_sock, (const char *)&reply_data, sizeof(unsigned int), 0); + send_in_progress.unlock(); } void NetworkServer::SendRequest_DeviceListChanged(SOCKET client_sock) { NetPacketHeader pkt_hdr; - pkt_hdr.pkt_magic[0] = 'O'; - pkt_hdr.pkt_magic[1] = 'R'; - pkt_hdr.pkt_magic[2] = 'G'; - pkt_hdr.pkt_magic[3] = 'B'; - - pkt_hdr.pkt_dev_idx = 0; - pkt_hdr.pkt_id = NET_PACKET_ID_DEVICE_LIST_UPDATED; - pkt_hdr.pkt_size = 0; + InitNetPacketHeader(&pkt_hdr, 0, NET_PACKET_ID_DEVICE_LIST_UPDATED, 0); + send_in_progress.lock(); send(client_sock, (char *)&pkt_hdr, sizeof(NetPacketHeader), 0); + send_in_progress.unlock(); } void NetworkServer::SendReply_ProfileList(SOCKET client_sock) @@ -1011,28 +1130,23 @@ void NetworkServer::SendReply_ProfileList(SOCKET client_sock) memcpy(&reply_size, reply_data, sizeof(reply_size)); - reply_hdr.pkt_magic[0] = 'O'; - reply_hdr.pkt_magic[1] = 'R'; - reply_hdr.pkt_magic[2] = 'G'; - reply_hdr.pkt_magic[3] = 'B'; - - reply_hdr.pkt_dev_idx = 0; - reply_hdr.pkt_id = NET_PACKET_ID_REQUEST_PROFILE_LIST; - reply_hdr.pkt_size = reply_size; + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_REQUEST_PROFILE_LIST, reply_size); + send_in_progress.lock(); send(client_sock, (const char *)&reply_hdr, sizeof(NetPacketHeader), 0); send(client_sock, (const char *)reply_data, reply_size, 0); + send_in_progress.unlock(); } void NetworkServer::SendReply_PluginList(SOCKET client_sock) { unsigned int data_size = 0; unsigned int data_ptr = 0; - + /*---------------------------------------------------------*\ | Calculate data size | \*---------------------------------------------------------*/ - unsigned short num_plugins = plugins.size(); + unsigned short num_plugins = (unsigned short)plugins.size(); data_size += sizeof(data_size); data_size += sizeof(num_plugins); @@ -1040,17 +1154,17 @@ void NetworkServer::SendReply_PluginList(SOCKET client_sock) for(unsigned int i = 0; i < num_plugins; i++) { data_size += sizeof(unsigned short) * 3; - data_size += strlen(plugins[i].name.c_str()) + 1; - data_size += strlen(plugins[i].description.c_str()) + 1; - data_size += strlen(plugins[i].version.c_str()) + 1; + data_size += (unsigned int)strlen(plugins[i].name.c_str()) + 1; + data_size += (unsigned int)strlen(plugins[i].description.c_str()) + 1; + data_size += (unsigned int)strlen(plugins[i].version.c_str()) + 1; data_size += sizeof(unsigned int) * 2; } - + /*---------------------------------------------------------*\ | Create data buffer | \*---------------------------------------------------------*/ unsigned char *data_buf = new unsigned char[data_size]; - + /*---------------------------------------------------------*\ | Copy in data size | \*---------------------------------------------------------*/ @@ -1068,7 +1182,7 @@ void NetworkServer::SendReply_PluginList(SOCKET client_sock) /*---------------------------------------------------------*\ | Copy in plugin name (size+data) | \*---------------------------------------------------------*/ - unsigned short str_len = strlen(plugins[i].name.c_str()) + 1; + unsigned short str_len = (unsigned short)strlen(plugins[i].name.c_str()) + 1; memcpy(&data_buf[data_ptr], &str_len, sizeof(unsigned short)); data_ptr += sizeof(unsigned short); @@ -1079,7 +1193,7 @@ void NetworkServer::SendReply_PluginList(SOCKET client_sock) /*---------------------------------------------------------*\ | Copy in plugin description (size+data) | \*---------------------------------------------------------*/ - str_len = strlen(plugins[i].description.c_str()) + 1; + str_len = (unsigned short)strlen(plugins[i].description.c_str()) + 1; memcpy(&data_buf[data_ptr], &str_len, sizeof(unsigned short)); data_ptr += sizeof(unsigned short); @@ -1090,7 +1204,7 @@ void NetworkServer::SendReply_PluginList(SOCKET client_sock) /*---------------------------------------------------------*\ | Copy in plugin version (size+data) | \*---------------------------------------------------------*/ - str_len = strlen(plugins[i].version.c_str()) + 1; + str_len = (unsigned short)strlen(plugins[i].version.c_str()) + 1; memcpy(&data_buf[data_ptr], &str_len, sizeof(unsigned short)); data_ptr += sizeof(unsigned short); @@ -1103,30 +1217,25 @@ void NetworkServer::SendReply_PluginList(SOCKET client_sock) \*---------------------------------------------------------*/ memcpy(&data_buf[data_ptr], &i, sizeof(unsigned int)); data_ptr += sizeof(unsigned int); - + /*---------------------------------------------------------*\ | Copy in plugin sdk version (data) | \*---------------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &plugins[i].protocol_version, sizeof(int)); - data_ptr += sizeof(int); + memcpy(&data_buf[data_ptr], &plugins[i].protocol_version, sizeof(unsigned int)); + data_ptr += sizeof(unsigned int); } - + NetPacketHeader reply_hdr; unsigned int reply_size; memcpy(&reply_size, data_buf, sizeof(reply_size)); - reply_hdr.pkt_magic[0] = 'O'; - reply_hdr.pkt_magic[1] = 'R'; - reply_hdr.pkt_magic[2] = 'G'; - reply_hdr.pkt_magic[3] = 'B'; - - reply_hdr.pkt_dev_idx = 0; - reply_hdr.pkt_id = NET_PACKET_ID_REQUEST_PLUGIN_LIST; - reply_hdr.pkt_size = reply_size; + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_REQUEST_PLUGIN_LIST, reply_size); + send_in_progress.lock(); send(client_sock, (const char *)&reply_hdr, sizeof(NetPacketHeader), 0); send(client_sock, (const char *)data_buf, reply_size, 0); + send_in_progress.unlock(); delete [] data_buf; } @@ -1135,18 +1244,14 @@ void NetworkServer::SendReply_PluginSpecific(SOCKET client_sock, unsigned int pk { NetPacketHeader reply_hdr; - reply_hdr.pkt_magic[0] = 'O'; - reply_hdr.pkt_magic[1] = 'R'; - reply_hdr.pkt_magic[2] = 'G'; - reply_hdr.pkt_magic[3] = 'B'; - - reply_hdr.pkt_dev_idx = 0; - reply_hdr.pkt_id = NET_PACKET_ID_PLUGIN_SPECIFIC; - reply_hdr.pkt_size = data_size + sizeof(pkt_type); + InitNetPacketHeader(&reply_hdr, 0, NET_PACKET_ID_PLUGIN_SPECIFIC, data_size + sizeof(pkt_type)); + send_in_progress.lock(); send(client_sock, (const char *)&reply_hdr, sizeof(NetPacketHeader), 0); send(client_sock, (const char *)&pkt_type, sizeof(pkt_type), 0); send(client_sock, (const char *)data, data_size, 0); + send_in_progress.unlock(); + delete [] data; } diff --git a/NetworkServer.h b/NetworkServer.h index c7766599..84701346 100644 --- a/NetworkServer.h +++ b/NetworkServer.h @@ -1,21 +1,24 @@ -/*-----------------------------------------*\ -| NetworkServer.h | -| | -| Server header for OpenRGB SDK | -| | -| Adam Honse (CalcProgrammer1) 5/9/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| NetworkServer.h | +| | +| OpenRGB SDK network server | +| | +| Adam Honse (CalcProgrammer1) 09 May 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ -#include "RGBController.h" -#include "NetworkProtocol.h" -#include "net_port.h" -#include "ProfileManager.h" +#pragma once #include #include #include - -#pragma once +#include "RGBController.h" +#include "NetworkProtocol.h" +#include "net_port.h" +#include "ProfileManager.h" +#include "ResourceManager.h" #define MAXSOCK 32 #define TCP_TIMEOUT_SECONDS 5 @@ -69,6 +72,7 @@ public: void RegisterServerListeningChangeCallback(NetServerCallback, void * new_callback_arg); void SetHost(std::string host); + void SetLegacyWorkaroundEnable(bool enable); void SetPort(unsigned short new_port); void StartServer(); @@ -79,6 +83,7 @@ public: void ProcessRequest_ClientProtocolVersion(SOCKET client_sock, unsigned int data_size, char * data); void ProcessRequest_ClientString(SOCKET client_sock, unsigned int data_size, char * data); + void ProcessRequest_RescanDevices(); void SendReply_ControllerCount(SOCKET client_sock); void SendReply_ControllerData(SOCKET client_sock, unsigned int dev_idx, unsigned int protocol_version); @@ -90,15 +95,15 @@ public: void SendReply_PluginSpecific(SOCKET client_sock, unsigned int pkt_type, unsigned char* data, unsigned int data_size); void SetProfileManager(ProfileManagerInterface* profile_manager_pointer); - + void RegisterPlugin(NetworkPlugin plugin); void UnregisterPlugin(std::string plugin_name); protected: std::string host; unsigned short port_num; - bool server_online; - bool server_listening; + std::atomic server_online; + std::atomic server_listening; std::vector& controllers; @@ -118,11 +123,14 @@ protected: std::vector plugins; + std::mutex send_in_progress; + private: #ifdef WIN32 WSADATA wsa; #endif + bool legacy_workaround_enabled; int socket_count; SOCKET server_sock[MAXSOCK]; diff --git a/OpenRGB.patch b/OpenRGB.patch deleted file mode 100644 index 5a140ad4..00000000 --- a/OpenRGB.patch +++ /dev/null @@ -1,715 +0,0 @@ -diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig -index 2ddca08f8a76..72647850f08e 100644 ---- a/drivers/i2c/busses/Kconfig -+++ b/drivers/i2c/busses/Kconfig -@@ -217,6 +217,15 @@ config I2C_CHT_WC - combined with a FUSB302 Type-C port-controller as such it is advised - to also select CONFIG_TYPEC_FUSB302=m. - -+config I2C_NCT6775 -+ tristate "Nuvoton NCT6775 and compatible SMBus controller" -+ help -+ If you say yes to this option, support will be included for the -+ Nuvoton NCT6775 and compatible SMBus controllers. -+ -+ This driver can also be built as a module. If so, the module -+ will be called i2c-nct6775. -+ - config I2C_NFORCE2 - tristate "Nvidia nForce2, nForce3 and nForce4" - depends on PCI -diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile -index 25d60889713c..3c2a9b237ac6 100644 ---- a/drivers/i2c/busses/Makefile -+++ b/drivers/i2c/busses/Makefile -@@ -17,6 +17,7 @@ obj-$(CONFIG_I2C_CHT_WC) += i2c-cht-wc.o - obj-$(CONFIG_I2C_I801) += i2c-i801.o - obj-$(CONFIG_I2C_ISCH) += i2c-isch.o - obj-$(CONFIG_I2C_ISMT) += i2c-ismt.o -+obj-$(CONFIG_I2C_NCT6775) += i2c-nct6775.o - obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o - obj-$(CONFIG_I2C_NFORCE2_S4985) += i2c-nforce2-s4985.o - obj-$(CONFIG_I2C_NVIDIA_GPU) += i2c-nvidia-gpu.o -diff --git a/drivers/i2c/busses/i2c-nct6775.c b/drivers/i2c/busses/i2c-nct6775.c -new file mode 100644 -index 000000000000..0462f0952043 ---- /dev/null -+++ b/drivers/i2c/busses/i2c-nct6775.c -@@ -0,0 +1,647 @@ -+/* -+ * i2c-nct6775 - Driver for the SMBus master functionality of -+ * Nuvoton NCT677x Super-I/O chips -+ * -+ * Copyright (C) 2019 Adam Honse -+ * -+ * Derived from nct6775 hwmon driver -+ * Copyright (C) 2012 Guenter Roeck -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#define DRVNAME "i2c-nct6775" -+ -+/* Nuvoton SMBus address offsets */ -+#define SMBHSTDAT (0 + nuvoton_nct6793d_smba) -+#define SMBBLKSZ (1 + nuvoton_nct6793d_smba) -+#define SMBHSTCMD (2 + nuvoton_nct6793d_smba) -+#define SMBHSTIDX (3 + nuvoton_nct6793d_smba) //Index field is the Command field on other controllers -+#define SMBHSTCTL (4 + nuvoton_nct6793d_smba) -+#define SMBHSTADD (5 + nuvoton_nct6793d_smba) -+#define SMBHSTERR (9 + nuvoton_nct6793d_smba) -+#define SMBHSTSTS (0xE + nuvoton_nct6793d_smba) -+ -+/* Command register */ -+#define NCT6793D_READ_BYTE 0 -+#define NCT6793D_READ_WORD 1 -+#define NCT6793D_READ_BLOCK 2 -+#define NCT6793D_BLOCK_WRITE_READ_PROC_CALL 3 -+#define NCT6793D_PROC_CALL 4 -+#define NCT6793D_WRITE_BYTE 8 -+#define NCT6793D_WRITE_WORD 9 -+#define NCT6793D_WRITE_BLOCK 10 -+ -+/* Control register */ -+#define NCT6793D_MANUAL_START 128 -+#define NCT6793D_SOFT_RESET 64 -+ -+/* Error register */ -+#define NCT6793D_NO_ACK 32 -+ -+/* Status register */ -+#define NCT6793D_FIFO_EMPTY 1 -+#define NCT6793D_FIFO_FULL 2 -+#define NCT6793D_MANUAL_ACTIVE 4 -+ -+#define NCT6775_LD_SMBUS 0x0B -+ -+/* Other settings */ -+#define MAX_RETRIES 400 -+ -+enum kinds { nct6106, nct6775, nct6776, nct6779, nct6791, nct6792, nct6793, -+ nct6795, nct6796, nct6798 }; -+ -+struct nct6775_sio_data { -+ int sioreg; -+ enum kinds kind; -+}; -+ -+/* used to set data->name = nct6775_device_names[data->sio_kind] */ -+static const char * const nct6775_device_names[] = { -+ "nct6106", -+ "nct6775", -+ "nct6776", -+ "nct6779", -+ "nct6791", -+ "nct6792", -+ "nct6793", -+ "nct6795", -+ "nct6796", -+ "nct6798", -+}; -+ -+static const char * const nct6775_sio_names[] __initconst = { -+ "NCT6106D", -+ "NCT6775F", -+ "NCT6776D/F", -+ "NCT6779D", -+ "NCT6791D", -+ "NCT6792D", -+ "NCT6793D", -+ "NCT6795D", -+ "NCT6796D", -+ "NCT6798D", -+}; -+ -+#define SIO_REG_LDSEL 0x07 /* Logical device select */ -+#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ -+#define SIO_REG_SMBA 0x62 /* SMBus base address register */ -+ -+#define SIO_NCT6106_ID 0xc450 -+#define SIO_NCT6775_ID 0xb470 -+#define SIO_NCT6776_ID 0xc330 -+#define SIO_NCT6779_ID 0xc560 -+#define SIO_NCT6791_ID 0xc800 -+#define SIO_NCT6792_ID 0xc910 -+#define SIO_NCT6793_ID 0xd120 -+#define SIO_NCT6795_ID 0xd350 -+#define SIO_NCT6796_ID 0xd420 -+#define SIO_NCT6798_ID 0xd428 -+#define SIO_ID_MASK 0xFFF0 -+ -+static inline void -+superio_outb(int ioreg, int reg, int val) -+{ -+ outb(reg, ioreg); -+ outb(val, ioreg + 1); -+} -+ -+static inline int -+superio_inb(int ioreg, int reg) -+{ -+ outb(reg, ioreg); -+ return inb(ioreg + 1); -+} -+ -+static inline void -+superio_select(int ioreg, int ld) -+{ -+ outb(SIO_REG_LDSEL, ioreg); -+ outb(ld, ioreg + 1); -+} -+ -+static inline int -+superio_enter(int ioreg) -+{ -+ /* -+ * Try to reserve and for exclusive access. -+ */ -+ if (!request_muxed_region(ioreg, 2, DRVNAME)) -+ return -EBUSY; -+ -+ outb(0x87, ioreg); -+ outb(0x87, ioreg); -+ -+ return 0; -+} -+ -+static inline void -+superio_exit(int ioreg) -+{ -+ outb(0xaa, ioreg); -+ outb(0x02, ioreg); -+ outb(0x02, ioreg + 1); -+ release_region(ioreg, 2); -+} -+ -+/* -+ * ISA constants -+ */ -+ -+#define IOREGION_ALIGNMENT (~7) -+#define IOREGION_LENGTH 2 -+#define ADDR_REG_OFFSET 0 -+#define DATA_REG_OFFSET 1 -+ -+#define NCT6775_REG_BANK 0x4E -+#define NCT6775_REG_CONFIG 0x40 -+ -+static struct i2c_adapter *nct6775_adapter; -+ -+struct i2c_nct6775_adapdata { -+ unsigned short smba; -+}; -+ -+/* Return negative errno on error. */ -+static s32 nct6775_access(struct i2c_adapter * adap, u16 addr, -+ unsigned short flags, char read_write, -+ u8 command, int size, union i2c_smbus_data * data) -+{ -+ struct i2c_nct6775_adapdata *adapdata = i2c_get_adapdata(adap); -+ unsigned short nuvoton_nct6793d_smba = adapdata->smba; -+ int i, len, cnt; -+ union i2c_smbus_data tmp_data; -+ int timeout = 0; -+ -+ tmp_data.word = 0; -+ cnt = 0; -+ len = 0; -+ -+ outb_p(NCT6793D_SOFT_RESET, SMBHSTCTL); -+ -+ switch (size) { -+ case I2C_SMBUS_QUICK: -+ outb_p((addr << 1) | read_write, -+ SMBHSTADD); -+ break; -+ case I2C_SMBUS_BYTE_DATA: -+ tmp_data.byte = data->byte; -+ case I2C_SMBUS_BYTE: -+ outb_p((addr << 1) | read_write, -+ SMBHSTADD); -+ outb_p(command, SMBHSTIDX); -+ if (read_write == I2C_SMBUS_WRITE) { -+ outb_p(tmp_data.byte, SMBHSTDAT); -+ outb_p(NCT6793D_WRITE_BYTE, SMBHSTCMD); -+ } -+ else { -+ outb_p(NCT6793D_READ_BYTE, SMBHSTCMD); -+ } -+ break; -+ case I2C_SMBUS_WORD_DATA: -+ outb_p((addr << 1) | read_write, -+ SMBHSTADD); -+ outb_p(command, SMBHSTIDX); -+ if (read_write == I2C_SMBUS_WRITE) { -+ outb_p(data->word & 0xff, SMBHSTDAT); -+ outb_p((data->word & 0xff00) >> 8, SMBHSTDAT); -+ outb_p(NCT6793D_WRITE_WORD, SMBHSTCMD); -+ } -+ else { -+ outb_p(NCT6793D_READ_WORD, SMBHSTCMD); -+ } -+ break; -+ case I2C_SMBUS_BLOCK_DATA: -+ outb_p((addr << 1) | read_write, -+ SMBHSTADD); -+ outb_p(command, SMBHSTIDX); -+ if (read_write == I2C_SMBUS_WRITE) { -+ len = data->block[0]; -+ if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) -+ return -EINVAL; -+ outb_p(len, SMBBLKSZ); -+ -+ cnt = 1; -+ if (len >= 4) { -+ for (i = cnt; i <= 4; i++) { -+ outb_p(data->block[i], SMBHSTDAT); -+ } -+ -+ len -= 4; -+ cnt += 4; -+ } -+ else { -+ for (i = cnt; i <= len; i++ ) { -+ outb_p(data->block[i], SMBHSTDAT); -+ } -+ -+ len = 0; -+ } -+ -+ outb_p(NCT6793D_WRITE_BLOCK, SMBHSTCMD); -+ } -+ else { -+ return -ENOTSUPP; -+ } -+ break; -+ default: -+ dev_warn(&adap->dev, "Unsupported transaction %d\n", size); -+ return -EOPNOTSUPP; -+ } -+ -+ outb_p(NCT6793D_MANUAL_START, SMBHSTCTL); -+ -+ while ((size == I2C_SMBUS_BLOCK_DATA) && (len > 0)) { -+ if (read_write == I2C_SMBUS_WRITE) { -+ timeout = 0; -+ while ((inb_p(SMBHSTSTS) & NCT6793D_FIFO_EMPTY) == 0) -+ { -+ if(timeout > MAX_RETRIES) -+ { -+ return -ETIMEDOUT; -+ } -+ usleep_range(250, 500); -+ timeout++; -+ } -+ -+ //Load more bytes into FIFO -+ if (len >= 4) { -+ for (i = cnt; i <= (cnt + 4); i++) { -+ outb_p(data->block[i], SMBHSTDAT); -+ } -+ -+ len -= 4; -+ cnt += 4; -+ } -+ else { -+ for (i = cnt; i <= (cnt + len); i++) { -+ outb_p(data->block[i], SMBHSTDAT); -+ } -+ -+ len = 0; -+ } -+ } -+ else { -+ return -ENOTSUPP; -+ } -+ -+ } -+ -+ //wait for manual mode to complete -+ timeout = 0; -+ while ((inb_p(SMBHSTSTS) & NCT6793D_MANUAL_ACTIVE) != 0) -+ { -+ if(timeout > MAX_RETRIES) -+ { -+ return -ETIMEDOUT; -+ } -+ usleep_range(250, 500); -+ timeout++; -+ } -+ -+ if ((inb_p(SMBHSTERR) & NCT6793D_NO_ACK) != 0) { -+ return -ENXIO; -+ } -+ else if ((read_write == I2C_SMBUS_WRITE) || (size == I2C_SMBUS_QUICK)) { -+ return 0; -+ } -+ -+ switch (size) { -+ case I2C_SMBUS_QUICK: -+ case I2C_SMBUS_BYTE_DATA: -+ data->byte = inb_p(SMBHSTDAT); -+ break; -+ case I2C_SMBUS_WORD_DATA: -+ data->word = inb_p(SMBHSTDAT) + (inb_p(SMBHSTDAT) << 8); -+ break; -+ } -+ return 0; -+} -+ -+static u32 nct6775_func(struct i2c_adapter *adapter) -+{ -+ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | -+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | -+ I2C_FUNC_SMBUS_BLOCK_DATA; -+} -+ -+static const struct i2c_algorithm smbus_algorithm = { -+ .smbus_xfer = nct6775_access, -+ .functionality = nct6775_func, -+}; -+ -+static int nct6775_add_adapter(unsigned short smba, const char *name, struct i2c_adapter **padap) -+{ -+ struct i2c_adapter *adap; -+ struct i2c_nct6775_adapdata *adapdata; -+ int retval; -+ -+ adap = kzalloc(sizeof(*adap), GFP_KERNEL); -+ if (adap == NULL) { -+ return -ENOMEM; -+ } -+ -+ adap->owner = THIS_MODULE; -+ adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; -+ adap->algo = &smbus_algorithm; -+ -+ adapdata = kzalloc(sizeof(*adapdata), GFP_KERNEL); -+ if (adapdata == NULL) { -+ kfree(adap); -+ return -ENOMEM; -+ } -+ -+ adapdata->smba = smba; -+ -+ snprintf(adap->name, sizeof(adap->name), -+ "SMBus NCT67xx adapter%s at %04x", name, smba); -+ -+ i2c_set_adapdata(adap, adapdata); -+ -+ retval = i2c_add_adapter(adap); -+ if (retval) { -+ kfree(adapdata); -+ kfree(adap); -+ return retval; -+ } -+ -+ *padap = adap; -+ return 0; -+} -+ -+static void nct6775_remove_adapter(struct i2c_adapter *adap) -+{ -+ struct i2c_nct6775_adapdata *adapdata = i2c_get_adapdata(adap); -+ -+ if (adapdata->smba) { -+ i2c_del_adapter(adap); -+ kfree(adapdata); -+ kfree(adap); -+ } -+} -+ -+//static SIMPLE_DEV_PM_OPS(nct6775_dev_pm_ops, nct6775_suspend, nct6775_resume); -+ -+/* -+ * when Super-I/O functions move to a separate file, the Super-I/O -+ * bus will manage the lifetime of the device and this module will only keep -+ * track of the nct6775 driver. But since we use platform_device_alloc(), we -+ * must keep track of the device -+ */ -+static struct platform_device *pdev[2]; -+ -+static int nct6775_probe(struct platform_device *pdev) -+{ -+ struct device *dev = &pdev->dev; -+ struct nct6775_sio_data *sio_data = dev_get_platdata(dev); -+ struct resource *res; -+ -+ res = platform_get_resource(pdev, IORESOURCE_IO, 0); -+ if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH, -+ DRVNAME)) -+ return -EBUSY; -+ -+ switch (sio_data->kind) { -+ case nct6791: -+ case nct6792: -+ case nct6793: -+ case nct6795: -+ case nct6796: -+ case nct6798: -+ nct6775_add_adapter(res->start, "", &nct6775_adapter); -+ break; -+ default: -+ return -ENODEV; -+ } -+ -+ return 0; -+} -+/* -+static void nct6791_enable_io_mapping(int sioaddr) -+{ -+ int val; -+ -+ val = superio_inb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE); -+ if (val & 0x10) { -+ pr_info("Enabling hardware monitor logical device mappings.\n"); -+ superio_outb(sioaddr, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE, -+ val & ~0x10); -+ } -+}*/ -+ -+static struct platform_driver i2c_nct6775_driver = { -+ .driver = { -+ .name = DRVNAME, -+// .pm = &nct6775_dev_pm_ops, -+ }, -+ .probe = nct6775_probe, -+}; -+ -+static void __exit i2c_nct6775_exit(void) -+{ -+ int i; -+ -+ if(nct6775_adapter) -+ nct6775_remove_adapter(nct6775_adapter); -+ -+ for (i = 0; i < ARRAY_SIZE(pdev); i++) { -+ if (pdev[i]) -+ platform_device_unregister(pdev[i]); -+ } -+ platform_driver_unregister(&i2c_nct6775_driver); -+} -+ -+/* nct6775_find() looks for a '627 in the Super-I/O config space */ -+static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) -+{ -+ u16 val; -+ int err; -+ int addr; -+ -+ err = superio_enter(sioaddr); -+ if (err) -+ return err; -+ -+ val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8) | -+ superio_inb(sioaddr, SIO_REG_DEVID + 1); -+ -+ switch (val & SIO_ID_MASK) { -+ case SIO_NCT6106_ID: -+ sio_data->kind = nct6106; -+ break; -+ case SIO_NCT6775_ID: -+ sio_data->kind = nct6775; -+ break; -+ case SIO_NCT6776_ID: -+ sio_data->kind = nct6776; -+ break; -+ case SIO_NCT6779_ID: -+ sio_data->kind = nct6779; -+ break; -+ case SIO_NCT6791_ID: -+ sio_data->kind = nct6791; -+ break; -+ case SIO_NCT6792_ID: -+ sio_data->kind = nct6792; -+ break; -+ case SIO_NCT6793_ID: -+ sio_data->kind = nct6793; -+ break; -+ case SIO_NCT6795_ID: -+ sio_data->kind = nct6795; -+ break; -+ case SIO_NCT6796_ID: -+ sio_data->kind = nct6796; -+ break; -+ case SIO_NCT6798_ID: -+ sio_data->kind = nct6798; -+ break; -+ default: -+ if (val != 0xffff) -+ pr_debug("unsupported chip ID: 0x%04x\n", val); -+ superio_exit(sioaddr); -+ return -ENODEV; -+ } -+ -+ /* We have a known chip, find the SMBus I/O address */ -+ superio_select(sioaddr, NCT6775_LD_SMBUS); -+ val = (superio_inb(sioaddr, SIO_REG_SMBA) << 8) -+ | superio_inb(sioaddr, SIO_REG_SMBA + 1); -+ addr = val & IOREGION_ALIGNMENT; -+ if (addr == 0) { -+ pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n"); -+ superio_exit(sioaddr); -+ return -ENODEV; -+ } -+ -+ //if (sio_data->kind == nct6791 || sio_data->kind == nct6792 || -+ // sio_data->kind == nct6793 || sio_data->kind == nct6795 || -+ // sio_data->kind == nct6796) -+ // nct6791_enable_io_mapping(sioaddr); -+ -+ superio_exit(sioaddr); -+ pr_info("Found %s or compatible chip at %#x:%#x\n", -+ nct6775_sio_names[sio_data->kind], sioaddr, addr); -+ sio_data->sioreg = sioaddr; -+ -+ return addr; -+} -+ -+static int __init i2c_nct6775_init(void) -+{ -+ int i, err; -+ bool found = false; -+ int address; -+ struct resource res; -+ struct nct6775_sio_data sio_data; -+ int sioaddr[2] = { 0x2e, 0x4e }; -+ -+ err = platform_driver_register(&i2c_nct6775_driver); -+ if (err) -+ return err; -+ -+ /* -+ * initialize sio_data->kind and sio_data->sioreg. -+ * -+ * when Super-I/O functions move to a separate file, the Super-I/O -+ * driver will probe 0x2e and 0x4e and auto-detect the presence of a -+ * nct6775 hardware monitor, and call probe() -+ */ -+ for (i = 0; i < ARRAY_SIZE(pdev); i++) { -+ address = nct6775_find(sioaddr[i], &sio_data); -+ if (address <= 0) -+ continue; -+ -+ found = true; -+ -+ pdev[i] = platform_device_alloc(DRVNAME, address); -+ if (!pdev[i]) { -+ err = -ENOMEM; -+ goto exit_device_unregister; -+ } -+ -+ err = platform_device_add_data(pdev[i], &sio_data, -+ sizeof(struct nct6775_sio_data)); -+ if (err) -+ goto exit_device_put; -+ -+ memset(&res, 0, sizeof(res)); -+ res.name = DRVNAME; -+ res.start = address; -+ res.end = address + IOREGION_LENGTH - 1; -+ res.flags = IORESOURCE_IO; -+ -+ err = acpi_check_resource_conflict(&res); -+ if (err) { -+ platform_device_put(pdev[i]); -+ pdev[i] = NULL; -+ continue; -+ } -+ -+ err = platform_device_add_resources(pdev[i], &res, 1); -+ if (err) -+ goto exit_device_put; -+ -+ /* platform_device_add calls probe() */ -+ err = platform_device_add(pdev[i]); -+ if (err) -+ goto exit_device_put; -+ } -+ if (!found) { -+ err = -ENODEV; -+ goto exit_unregister; -+ } -+ -+ return 0; -+ -+exit_device_put: -+ platform_device_put(pdev[i]); -+exit_device_unregister: -+ while (--i >= 0) { -+ if (pdev[i]) -+ platform_device_unregister(pdev[i]); -+ } -+exit_unregister: -+ platform_driver_unregister(&i2c_nct6775_driver); -+ return err; -+} -+ -+MODULE_AUTHOR("Adam Honse "); -+MODULE_DESCRIPTION("SMBus driver for NCT6775F and compatible chips"); -+MODULE_LICENSE("GPL"); -+ -+module_init(i2c_nct6775_init); -+module_exit(i2c_nct6775_exit); -diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c -index 30ded6422e7b..e25ce84c26af 100644 ---- a/drivers/i2c/busses/i2c-piix4.c -+++ b/drivers/i2c/busses/i2c-piix4.c -@@ -467,11 +467,11 @@ static int piix4_transaction(struct i2c_adapter *piix4_adapter) - if (srvrworks_csb5_delay) /* Extra delay for SERVERWORKS_CSB5 */ - usleep_range(2000, 2100); - else -- usleep_range(250, 500); -+ usleep_range(25, 50); - - while ((++timeout < MAX_TIMEOUT) && - ((temp = inb_p(SMBHSTSTS)) & 0x01)) -- usleep_range(250, 500); -+ usleep_range(25, 50); - - /* If the SMBus is still busy, we give up */ - if (timeout == MAX_TIMEOUT) { -@@ -981,6 +981,11 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) - retval = piix4_setup_sb800(dev, id, 1); - } - -+ if (dev->vendor == PCI_VENDOR_ID_AMD && -+ dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) { -+ retval = piix4_setup_sb800(dev, id, 1); -+ } -+ - if (retval > 0) { - /* Try to add the aux adapter if it exists, - * piix4_add_adapter will clean up if this fails */ diff --git a/OpenRGB.pro b/OpenRGB.pro index 556be3bc..9a49651d 100644 --- a/OpenRGB.pro +++ b/OpenRGB.pro @@ -17,220 +17,161 @@ QT += CONFIG += c++17 \ lrelease \ embed_translations \ + silent \ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets -greaterThan(QT_MAJOR_VERSION, 5): DEFINES += _QT6 - -#-----------------------------------------------------------------------------------------------# -# pkg-config Configuration # -#-----------------------------------------------------------------------------------------------# -greaterThan(QT_MAJOR_VERSION, 4) { - PKG_CONFIG = $$pkgConfigExecutable() -} else { - PKG_CONFIG = "pkgconf" -} - #-----------------------------------------------------------------------------------------------# # Application Configuration # #-----------------------------------------------------------------------------------------------# MAJOR = 0 MINOR = 9 -REVISION = -VERSION = $$MAJOR"."$$MINOR$$REVISION +SUFFIX = git + +SHORTHASH = $$system("git rev-parse --short=7 HEAD") +LASTTAG = "release_"$$MAJOR"."$$MINOR +COMMAND = "git rev-list --count "$$LASTTAG"..HEAD" +COMMITS = $$system($$COMMAND) + +VERSION_NUM = $$MAJOR"."$$MINOR"."$$COMMITS +VERSION_STR = $$MAJOR"."$$MINOR + +VERSION_DEB = $$VERSION_NUM +VERSION_WIX = $$VERSION_NUM +VERSION_AUR = $$VERSION_NUM +VERSION_RPM = $$VERSION_NUM + +equals(SUFFIX, "git") { +VERSION_STR = $$VERSION_STR"+ ("$$SUFFIX$$COMMITS")" +VERSION_DEB = $$VERSION_DEB"~git"$$SHORTHASH +VERSION_AUR = $$VERSION_AUR".g"$$SHORTHASH +VERSION_RPM = $$VERSION_RPM"^git"$$SHORTHASH +} else { + !isEmpty(SUFFIX) { +VERSION_STR = $$VERSION_STR"+ ("$$SUFFIX")" +VERSION_DEB = $$VERSION_DEB"~"$$SUFFIX +VERSION_AUR = $$VERSION_AUR"."$$SUFFIX +VERSION_RPM = $$VERSION_RPM"^"$$SUFFIX + } +} + TARGET = OpenRGB TEMPLATE = app +message("VERSION_NUM: "$$VERSION_NUM) +message("VERSION_STR: "$$VERSION_STR) +message("VERSION_SFX: "$$SUFFIX) +message("VERSION_DEB: "$$VERSION_DEB) +message("VERSION_WIX: "$$VERSION_WIX) +message("VERSION_AUR: "$$VERSION_AUR) +message("VERSION_RPM: "$$VERSION_RPM) +message("QT_VERSION: "$$QT_VERSION) #-----------------------------------------------------------------------------------------------# # Automatically generated build information # #-----------------------------------------------------------------------------------------------# -win32:BUILDDATE = $$system(date /t) -unix:BUILDDATE = $$system(date -R -d "@${SOURCE_DATE_EPOCH:-$(date +%s)}") -GIT_COMMIT_ID = $$system(git log -n 1 --pretty=format:"%H") -GIT_COMMIT_DATE = $$system(git log -n 1 --pretty=format:"%ci") -GIT_BRANCH = $$system(git branch --show-current) +win32:BUILDDATE = $$system(date /t) +linux:BUILDDATE = $$system(date -R -d "@${SOURCE_DATE_EPOCH:-$(date +%s)}") +freebsd:BUILDDATE = $$system(date -j -R -r "${SOURCE_DATE_EPOCH:-$(date +%s)}") +macx:BUILDDATE = $$system(date -j -R -r "${SOURCE_DATE_EPOCH:-$(date +%s)}") +GIT_COMMIT_ID = $$system(git log -n 1 --pretty=format:"%H") +GIT_COMMIT_DATE = $$system(git log -n 1 --pretty=format:"%ci") +unix { + GIT_BRANCH = $$system(sh scripts/git-get-branch.sh) +} +else { + GIT_BRANCH = $$system(powershell -ExecutionPolicy Bypass -File scripts/git-get-branch.ps1) +} + +message("GIT_BRANCH: "$$GIT_BRANCH) DEFINES += \ - VERSION_STRING=\\"\"\"$$VERSION\\"\"\" \ + VERSION_STRING=\\"\"\"$$VERSION_STR\\"\"\" \ BUILDDATE_STRING=\\"\"\"$$BUILDDATE\\"\"\" \ GIT_COMMIT_ID=\\"\"\"$$GIT_COMMIT_ID\\"\"\" \ GIT_COMMIT_DATE=\\"\"\"$$GIT_COMMIT_DATE\\"\"\" \ GIT_BRANCH=\\"\"\"$$GIT_BRANCH\\"\"\" +#-----------------------------------------------------------------------------------------------# +# OpenRGB dynamically added sources # +#-----------------------------------------------------------------------------------------------# +FORMS += $$files("qt/*.ui", true) + +for(iter, FORMS) { + GUI_INCLUDES += $$dirname(iter) +} +GUI_INCLUDES = $$unique(GUI_INCLUDES) + +GUI_H = $$files("qt/*.h", true) +GUI_CPP = $$files("qt/*.cpp", true) + +CONTROLLER_H = $$files("Controllers/*.h", true) +CONTROLLER_CPP = $$files("Controllers/*.cpp", true) + +for(iter, $$list($$CONTROLLER_H)) { + CONTROLLER_INCLUDES += $$dirname(iter) +} +CONTROLLER_INCLUDES = $$unique(CONTROLLER_INCLUDES) + +#-----------------------------------------------------------------------------------------------# +# Remove OS-specific files from the overall controller headers and sources lists # +# The suffixes _Windows, _Linux, _FreeBSD, and _MacOS are usable to denote that a file only # +# applies to one or more OSes. The suffixes may be combined such as _Windows_Linux.cpp. # +#-----------------------------------------------------------------------------------------------# +CONTROLLER_H_WINDOWS = $$files("Controllers/*_Windows*.h", true) +CONTROLLER_CPP_WINDOWS = $$files("Controllers/*_Windows*.cpp", true) +CONTROLLER_H_LINUX = $$files("Controllers/*_Linux*.h", true) +CONTROLLER_CPP_LINUX = $$files("Controllers/*_Linux*.cpp", true) +CONTROLLER_H_FREEBSD = $$files("Controllers/*_FreeBSD*.h", true) +CONTROLLER_CPP_FREEBSD = $$files("Controllers/*_FreeBSD*.cpp", true) +CONTROLLER_H_MACOS = $$files("Controllers/*_MacOS*.h", true) +CONTROLLER_CPP_MACOS = $$files("Controllers/*_MacOS*.cpp", true) + +CONTROLLER_H -= $$CONTROLLER_H_WINDOWS +CONTROLLER_H -= $$CONTROLLER_H_LINUX +CONTROLLER_H -= $$CONTROLLER_H_FREEBSD +CONTROLLER_H -= $$CONTROLLER_H_MACOS + +CONTROLLER_CPP -= $$CONTROLLER_CPP_WINDOWS +CONTROLLER_CPP -= $$CONTROLLER_CPP_LINUX +CONTROLLER_CPP -= $$CONTROLLER_CPP_FREEBSD +CONTROLLER_CPP -= $$CONTROLLER_CPP_MACOS + #-----------------------------------------------------------------------------------------------# # OpenRGB Common # #-----------------------------------------------------------------------------------------------# INCLUDEPATH += \ + $$CONTROLLER_INCLUDES \ + $$GUI_INCLUDES \ dependencies/ColorWheel \ - dependencies/Swatches/ \ dependencies/CRCpp/ \ - dependencies/hueplusplus-1.0.0/include \ - dependencies/hueplusplus-1.0.0/include/hueplusplus \ + dependencies/hueplusplus-1.2.0/include \ + dependencies/hueplusplus-1.2.0/include/hueplusplus \ dependencies/httplib \ dependencies/json/ \ - dependencies/libe131/src/ \ - dependencies/libcmmk/include/ \ dependencies/mdns \ + dmiinfo/ \ hidapi_wrapper/ \ i2c_smbus/ \ i2c_tools/ \ + interop/ \ net_port/ \ pci_ids/ \ + scsiapi/ \ serial_port/ \ super_io/ \ AutoStart/ \ - qt/OpenRGBClientInfoPage/ \ - qt/OpenRGBConsolePage/ \ - qt/OpenRGBDeviceInfoPage/ \ - qt/OpenRGBDevicePage/ \ - qt/OpenRGBDialog2/ \ - qt/OpenRGBDMXSettingsPage/ \ - qt/OpenRGBE131SettingsPage/ \ - qt/OpenRGBElgatoKeyLightSettingsPage/ \ - qt/OpenRGBHardwareIDsDialog/ \ - qt/OpenRGBKasaSmartSettingsPage/ \ - qt/OpenRGBLIFXSettingsPage/ \ - qt/OpenRGBNanoleafSettingsPage/ \ - qt/OpenRGBPhilipsHueSettingsPage/ \ - qt/OpenRGBPhilipsWizSettingsPage/ \ - qt/OpenRGBPluginContainer/ \ - qt/OpenRGBProfileSaveDialog/ \ - qt/OpenRGBQMKORGBSettingsPage/ \ - qt/OpenRGBSerialSettingsPage/ \ - qt/OpenRGBServerInfoPage/ \ - qt/OpenRGBSettingsPage/ \ - qt/OpenRGBSoftwareInfoPage/ \ - qt/OpenRGBSupportedDevicesPage/ \ - qt/OpenRGBSystemInfoPage/ \ - qt/OpenRGBYeelightSettingsPage/ \ - qt/OpenRGBZoneResizeDialog/ \ - qt/OpenRGBZonesBulkResizer/ \ - Controllers/A4TechController/ \ - Controllers/AlienwareController/ \ - Controllers/AlienwareKeyboardController/ \ - Controllers/AMDWraithPrismController/ \ - Controllers/AOCKeyboardController/ \ - Controllers/AOCMouseController/ \ - Controllers/AOCMousematController/ \ - Controllers/ASRockPolychromeUSBController/ \ - Controllers/ASRockSMBusController/ \ - Controllers/AsusAuraCoreController/ \ - Controllers/AsusAuraGPUController/ \ - Controllers/AsusAuraUSBController/ \ - Controllers/CherryKeyboardController/ \ - Controllers/CoolerMasterController/ \ - Controllers/CorsairCommanderCoreController/ \ - Controllers/CorsairDominatorPlatinumController/ \ - Controllers/CorsairHydroController/ \ - Controllers/CorsairHydro2Controller/ \ - Controllers/CorsairHydroPlatinumController/ \ - Controllers/CorsairPeripheralController/ \ - Controllers/CorsairPeripheralV2Controller/ \ - Controllers/CorsairLightingNodeController/ \ - Controllers/CorsairVengeanceController/ \ - Controllers/CorsairVengeanceProController/ \ - Controllers/CorsairWirelessController/ \ - Controllers/CreativeController/ \ - Controllers/CrucialController/ \ - Controllers/CryorigH7QuadLumiController/ \ - Controllers/DasKeyboardController/ \ - Controllers/DebugController/ \ - Controllers/DMXController/ \ - Controllers/DuckyKeyboardController/ \ - Controllers/DygmaRaiseController/ \ - Controllers/E131Controller/ \ - Controllers/EKController/ \ - Controllers/ENESMBusController/ \ - Controllers/ENESMBusController/ENESMBusInterface \ - Controllers/EpomakerController/ \ - Controllers/EspurnaController/ \ - Controllers/EVGAGP102GPUController/ \ - Controllers/EVGAPascalGPUController/ \ - Controllers/EVGATuringGPUController/ \ - Controllers/EVGAAmpereGPUController/ \ - Controllers/EVisionKeyboardController/ \ - Controllers/FanBusController/ \ - Controllers/GainwardGPUController/ \ - Controllers/GaiZongGaiKeyboardController/ \ - Controllers/GalaxGPUController/ \ - Controllers/GigabyteAorusCPUCoolerController/ \ - Controllers/GigabyteAorusMouseController/ \ - Controllers/GigabyteRGBFusion2DRAMController/ \ - Controllers/GigabyteRGBFusion2SMBusController/ \ - Controllers/GigabyteRGBFusion2USBController/ \ - Controllers/GigabyteRGBFusionController/ \ - Controllers/GigabyteRGBFusionGPUController/ \ - Controllers/GigabyteRGBFusion2GPUController/ \ - Controllers/GigabyteSuperIORGBController/ \ - Controllers/HoltekController/ \ - Controllers/HPOmen30LController/ \ - Controllers/HyperXDRAMController/ \ - Controllers/HyperXKeyboardController/ \ - Controllers/HyperXMicrophoneController/ \ - Controllers/HyperXMouseController/ \ - Controllers/HyperXMousematController/ \ - Controllers/IntelArcA770LEController/ \ - Controllers/IonicoController/ \ - Controllers/LEDStripController/ \ - Controllers/LegoDimensionsToypadBaseController/ \ - Controllers/LenovoControllers/ \ - Controllers/LenovoMotherboardController/ \ - Controllers/LianLiController/ \ - Controllers/LIFXController/ \ - Controllers/LogitechController/ \ - Controllers/MSI3ZoneController/ \ - Controllers/MSIGPUController/ \ - Controllers/MSIMysticLightController/ \ - Controllers/MSIOptixController/ \ - Controllers/MSIRGBController/ \ - Controllers/MSIVigorController/ \ - Controllers/NanoleafController/ \ - Controllers/NollieController/ \ - Controllers/NZXTHue1Controller/ \ - Controllers/NZXTHue2Controller/ \ - Controllers/NZXTHuePlusController/ \ - Controllers/NZXTKrakenController/ \ - Controllers/OpenRazerController/ \ - Controllers/PatriotViperController/ \ - Controllers/PatriotViperSteelController/ \ - Controllers/PhilipsHueController/ \ - Controllers/PhilipsWizController/ \ - Controllers/PNYGPUController/ \ - Controllers/QMKOpenRGBController/ \ - Controllers/RazerController/ \ - Controllers/RedragonController/ \ - Controllers/RedSquareKeyroxController/ \ - Controllers/RoccatController/ \ - Controllers/SapphireGPUController/ \ - Controllers/SinowealthController/ \ - Controllers/SonyGamepadController/ \ - Controllers/SRGBmodsController/ \ - Controllers/SteelSeriesController/ \ - Controllers/TecknetController/ \ - Controllers/ThermaltakePoseidonZRGBController/ \ - Controllers/ThermaltakeRiingController/ \ - Controllers/ViewSonicController/ \ - Controllers/WootingKeyboardController/ \ - Controllers/WushiController/ \ - Controllers/YeelightController/ \ - Controllers/ZalmanZSyncController/ \ - Controllers/ZotacTuringGPUController/ \ - Controllers/ZotacV2GPUController/ \ KeyboardLayoutManager/ \ RGBController/ \ - qt/ - -contains(QMAKE_PLATFORM, freebsd) { - INCLUDEPATH -= \ - Controllers/GigabyteRGBFusion2GPUController/ -} + qt/ \ + SPDAccessor/ \ + SuspendResume/ HEADERS += \ + $$GUI_H \ + $$CONTROLLER_H \ Colors.h \ dependencies/ColorWheel/ColorWheel.h \ - dependencies/Swatches/swatches.h \ - dependencies/json/json.hpp \ - dependencies/libcmmk/include/libcmmk/libcmmk.h \ + dependencies/json/nlohmann/json.hpp \ LogManager.h \ NetworkClient.h \ NetworkProtocol.h \ @@ -239,1430 +180,179 @@ HEADERS += PluginManager.h \ ProfileManager.h \ ResourceManager.h \ + ResourceManagerInterface.h \ SettingsManager.h \ Detector.h \ DeviceDetector.h \ + dmiinfo/dmiinfo.h \ filesystem.h \ - qt/DetectorTableModel.h \ hidapi_wrapper/hidapi_wrapper.h \ i2c_smbus/i2c_smbus.h \ i2c_tools/i2c_tools.h \ + interop/DeviceGuard.h \ + interop/DeviceGuardLock.h \ + interop/DeviceGuardManager.h \ net_port/net_port.h \ pci_ids/pci_ids.h \ - qt/DeviceView.h \ - qt/OpenRGBFont.h \ - qt/OpenRGBThemeManager.h \ - qt/QTooltipedSlider.h \ - qt/TabLabel.h \ - qt/OpenRGBClientInfoPage/OpenRGBClientInfoPage.h \ - qt/OpenRGBConsolePage/OpenRGBConsolePage.h \ - qt/OpenRGBDeviceInfoPage/OpenRGBDeviceInfoPage.h \ - qt/OpenRGBDevicePage/OpenRGBDevicePage.h \ - qt/OpenRGBDialog2/OpenRGBDialog2.h \ - qt/OpenRGBDMXSettingsPage/OpenRGBDMXSettingsEntry.h \ - qt/OpenRGBDMXSettingsPage/OpenRGBDMXSettingsPage.h \ - qt/OpenRGBE131SettingsPage/OpenRGBE131SettingsEntry.h \ - qt/OpenRGBE131SettingsPage/OpenRGBE131SettingsPage.h \ - qt/OpenRGBElgatoKeyLightSettingsPage/OpenRGBElgatoKeyLightSettingsEntry.h \ - qt/OpenRGBElgatoKeyLightSettingsPage/OpenRGBElgatoKeyLightSettingsPage.h \ - qt/OpenRGBHardwareIDsDialog/OpenRGBHardwareIDsDialog.h \ - qt/OpenRGBKasaSmartSettingsPage/OpenRGBKasaSmartSettingsEntry.h \ - qt/OpenRGBKasaSmartSettingsPage/OpenRGBKasaSmartSettingsPage.h \ - qt/OpenRGBLIFXSettingsPage/OpenRGBLIFXSettingsEntry.h \ - qt/OpenRGBLIFXSettingsPage/OpenRGBLIFXSettingsPage.h \ - qt/OpenRGBNanoleafSettingsPage/OpenRGBNanoleafSettingsEntry.h \ - qt/OpenRGBNanoleafSettingsPage/OpenRGBNanoleafSettingsPage.h \ - qt/OpenRGBNanoleafSettingsPage/OpenRGBNanoleafScanningThread.h \ - qt/OpenRGBPhilipsHueSettingsPage/OpenRGBPhilipsHueSettingsEntry.h \ - qt/OpenRGBPhilipsHueSettingsPage/OpenRGBPhilipsHueSettingsPage.h \ - qt/OpenRGBPhilipsWizSettingsPage/OpenRGBPhilipsWizSettingsEntry.h \ - qt/OpenRGBPhilipsWizSettingsPage/OpenRGBPhilipsWizSettingsPage.h \ - qt/OpenRGBPluginContainer/OpenRGBPluginContainer.h \ - qt/OpenRGBPluginsPage/OpenRGBPluginsEntry.h \ - qt/OpenRGBPluginsPage/OpenRGBPluginsList.h \ - qt/OpenRGBPluginsPage/OpenRGBPluginsPage.h \ - qt/OpenRGBProfileSaveDialog/OpenRGBProfileSaveDialog.h \ - qt/OpenRGBQMKORGBSettingsPage/OpenRGBQMKORGBSettingsEntry.h \ - qt/OpenRGBQMKORGBSettingsPage/OpenRGBQMKORGBSettingsPage.h \ - qt/OpenRGBSerialSettingsPage/OpenRGBSerialSettingsEntry.h \ - qt/OpenRGBSerialSettingsPage/OpenRGBSerialSettingsPage.h \ - qt/OpenRGBServerInfoPage/OpenRGBServerInfoPage.h \ - qt/OpenRGBSettingsPage/OpenRGBSettingsPage.h \ - qt/OpenRGBSoftwareInfoPage/OpenRGBSoftwareInfoPage.h \ - qt/OpenRGBSupportedDevicesPage/OpenRGBSupportedDevicesPage.h \ - qt/OpenRGBSystemInfoPage/OpenRGBSystemInfoPage.h \ - qt/OpenRGBYeelightSettingsPage/OpenRGBYeelightSettingsEntry.h \ - qt/OpenRGBYeelightSettingsPage/OpenRGBYeelightSettingsPage.h \ - qt/OpenRGBZoneResizeDialog/OpenRGBZoneResizeDialog.h \ - qt/OpenRGBZonesBulkResizer/OpenRGBZonesBulkResizer.h \ + scsiapi/scsiapi.h \ serial_port/find_usb_serial_port.h \ serial_port/serial_port.h \ StringUtils.h \ super_io/super_io.h \ + SuspendResume/SuspendResume.h \ AutoStart/AutoStart.h \ - Controllers/A4TechController/BloodyMouseController.h \ - Controllers/A4TechController/RGBController_BloodyMouse.h \ - Controllers/AlienwareController/AlienwareController.h \ - Controllers/AlienwareController/RGBController_Alienware.h \ - Controllers/AlienwareKeyboardController/AlienwareAW510KController.h \ - Controllers/AlienwareKeyboardController/RGBController_AlienwareAW510K.h \ - Controllers/AMDWraithPrismController/AMDWraithPrismController.h \ - Controllers/AMDWraithPrismController/RGBController_AMDWraithPrism.h \ - Controllers/AnnePro2Controller/AnnePro2Controller.h \ - Controllers/AnnePro2Controller/RGBController_AnnePro2.h \ - Controllers/AOCKeyboardController/AOCKeyboardController.h \ - Controllers/AOCKeyboardController/RGBController_AOCKeyboard.h \ - Controllers/AOCMouseController/AOCMouseController.h \ - Controllers/AOCMouseController/RGBController_AOCMouse.h \ - Controllers/AOCMousematController/AOCMousematController.h \ - Controllers/AOCMousematController/RGBController_AOCMousemat.h \ - Controllers/ASRockPolychromeUSBController/ASRockPolychromeUSBController.h \ - Controllers/ASRockPolychromeUSBController/RGBController_ASRockPolychromeUSB.h \ - Controllers/ASRockSMBusController/ASRockASRRGBSMBusController.h \ - Controllers/ASRockSMBusController/RGBController_ASRockASRRGBSMBus.h \ - Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController.h \ - Controllers/ASRockSMBusController/RGBController_ASRockPolychromeV1SMBus.h \ - Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController.h \ - Controllers/ASRockSMBusController/RGBController_ASRockPolychromeV2SMBus.h \ - Controllers/AsusAuraCoreController/AsusAuraCoreController.h \ - Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController.h \ - Controllers/AsusAuraCoreController/RGBController_AsusAuraCore.h \ - Controllers/AsusAuraCoreController/RGBController_AsusAuraCoreLaptop.h \ - Controllers/AsusAuraGPUController/AsusAuraGPUController.h \ - Controllers/AsusAuraGPUController/RGBController_AsusAuraGPU.h \ - Controllers/AsusAuraUSBController/AsusAuraUSBController.h \ - Controllers/AsusAuraUSBController/AsusAuraAddressableController.h \ - Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController.h \ - Controllers/AsusAuraUSBController/AsusAuraKeyboardController.h \ - Controllers/AsusAuraUSBController/AsusAuraMainboardController.h \ - Controllers/AsusAuraUSBController/AsusAuraMonitorController.h \ - Controllers/AsusAuraUSBController/AsusAuraMouseController.h \ - Controllers/AsusAuraUSBController/AsusAuraMousematController.h \ - Controllers/AsusAuraUSBController/AsusAuraMouseDevices.h \ - Controllers/AsusAuraUSBController/AsusROGAllyController.h \ - Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController.h \ - Controllers/AsusAuraUSBController/AsusAuraStrixEvolveController.h \ - Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController.h \ - Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardLayouts.h \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraHeadsetStand.h \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraKeyboard.h \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraMonitor.h \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraMouse.h \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraMousemat.h \ - Controllers/AsusAuraUSBController/RGBController_AsusROGAlly.h \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraRyuoAIO.h \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraStrixEvolve.h \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraTUFKeyboard.h \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraUSB.h \ - Controllers/AsusAuraUSBController/RGBController_ROGStrixLC_Controller.h \ - Controllers/AsusAuraUSBController/ROGStrixLC_Controller.h \ - Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController.h \ - Controllers/AsusLegacyUSBController/AsusStrixClawController.h \ - Controllers/AsusLegacyUSBController/RGBController_AsusCerberusKeyboard.h \ - Controllers/AsusLegacyUSBController/RGBController_AsusStrixClaw.h \ - Controllers/BlinkyTapeController/BlinkyTapeController.h \ - Controllers/BlinkyTapeController/RGBController_BlinkyTape.h \ - Controllers/CherryKeyboardController/CherryKeyboardController.h \ - Controllers/CherryKeyboardController/RGBController_CherryKeyboard.h \ - Controllers/ColorfulGPUController/ColorfulGPUController.h \ - Controllers/ColorfulGPUController/RGBController_ColorfulGPU.h \ - Controllers/ColorfulTuringGPUController/ColorfulTuringGPUController.h \ - Controllers/ColorfulTuringGPUController/RGBController_ColorfulTuringGPU.h \ - Controllers/CoolerMasterController/CMARGBcontroller.h \ - Controllers/CoolerMasterController/CMARGBGen2A1controller.h \ - Controllers/CoolerMasterController/CMMKController.h \ - Controllers/CoolerMasterController/CMMMController.h \ - Controllers/CoolerMasterController/CMMM711Controller.h \ - Controllers/CoolerMasterController/CMMP750Controller.h \ - Controllers/CoolerMasterController/CMR6000Controller.h \ - Controllers/CoolerMasterController/CMRGBController.h \ - Controllers/CoolerMasterController/CMSmallARGBController.h \ - Controllers/CoolerMasterController/RGBController_CMARGBController.h \ - Controllers/CoolerMasterController/RGBController_CMARGBGen2A1Controller.h \ - Controllers/CoolerMasterController/RGBController_CMMKController.h \ - Controllers/CoolerMasterController/RGBController_CMMMController.h \ - Controllers/CoolerMasterController/RGBController_CMMM711Controller.h \ - Controllers/CoolerMasterController/RGBController_CMMP750Controller.h \ - Controllers/CoolerMasterController/RGBController_CMR6000Controller.h \ - Controllers/CoolerMasterController/RGBController_CMRGBController.h \ - Controllers/CoolerMasterController/RGBController_CMSmallARGBController.h \ - Controllers/CorsairCommanderCoreController/CorsairCommanderCoreController.h \ - Controllers/CorsairCommanderCoreController/RGBController_CorsairCommanderCore.h \ - Controllers/CorsairDominatorPlatinumController/CorsairDominatorPlatinumController.h \ - Controllers/CorsairDominatorPlatinumController/RGBController_CorsairDominatorPlatinum.h \ - Controllers/CorsairHydroController/CorsairHydroController.h \ - Controllers/CorsairHydroController/RGBController_CorsairHydro.h \ - Controllers/CorsairHydro2Controller/CorsairHydro2Controller.h \ - Controllers/CorsairHydro2Controller/RGBController_CorsairHydro2.h \ - Controllers/CorsairHydroPlatinumController/CorsairHydroPlatinumController.h \ - Controllers/CorsairHydroPlatinumController/RGBController_CorsairHydroPlatinum.h \ - Controllers/CorsairLightingNodeController/CorsairLightingNodeController.h \ - Controllers/CorsairLightingNodeController/RGBController_CorsairLightingNode.h \ - Controllers/CorsairPeripheralController/CorsairPeripheralController.h \ - Controllers/CorsairPeripheralController/CorsairK100Controller.h \ - Controllers/CorsairPeripheralController/CorsairK55RGBPROXTController.h \ - Controllers/CorsairPeripheralController/CorsairK65MiniController.h \ - Controllers/CorsairPeripheralController/CorsairK95PlatinumXTController.h \ - Controllers/CorsairPeripheralController/RGBController_CorsairPeripheral.h \ - Controllers/CorsairPeripheralController/RGBController_CorsairK100.h \ - Controllers/CorsairPeripheralController/RGBController_CorsairK55RGBPROXT.h \ - Controllers/CorsairPeripheralController/RGBController_CorsairK65Mini.h \ - Controllers/CorsairPeripheralController/RGBController_CorsairK95PlatinumXT.h \ - Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.h \ - Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.h \ - Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.h \ - Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2SoftwareController.h \ - Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.h \ - Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.h \ - Controllers/CorsairVengeanceController/CorsairVengeanceController.h \ - Controllers/CorsairVengeanceController/RGBController_CorsairVengeance.h \ - Controllers/CorsairVengeanceProController/CorsairVengeanceProController.h \ - Controllers/CorsairVengeanceProController/RGBController_CorsairVengeancePro.h \ - Controllers/CorsairWirelessController/CorsairWirelessController.h \ - Controllers/CorsairWirelessController/RGBController_CorsairWireless.h \ - Controllers/CougarController/CougarKeyboardController.h \ - Controllers/CougarController/CougarRevengerSTController.h \ - Controllers/CougarController/RGBController_CougarKeyboard.h \ - Controllers/CougarController/RGBController_CougarRevengerST.h \ - Controllers/CreativeController/CreativeSoundBlasterXG6Controller.h \ - Controllers/CreativeController/RGBController_CreativeSoundBlasterXG6.h \ - Controllers/CrucialController/CrucialController.h \ - Controllers/CrucialController/RGBController_Crucial.h \ - Controllers/CryorigH7QuadLumiController/CryorigH7QuadLumiController.h \ - Controllers/CryorigH7QuadLumiController/RGBController_CryorigH7QuadLumi.h \ - Controllers/DarkProject/DarkProjectKeyboardController.h \ - Controllers/DarkProject/RGBController_DarkProjectKeyboard.h \ - Controllers/DasKeyboardController/DasKeyboardController.h \ - Controllers/DasKeyboardController/RGBController_DasKeyboard.h \ - Controllers/DMXController/RGBController_DMX.h \ - Controllers/DuckyKeyboardController/DuckyKeyboardController.h \ - Controllers/DuckyKeyboardController/RGBController_DuckyKeyboard.h \ - Controllers/DygmaRaiseController/DygmaRaiseController.h \ - Controllers/DygmaRaiseController/RGBController_DygmaRaise.h \ - Controllers/DebugController/RGBController_Debug.h \ - Controllers/E131Controller/RGBController_E131.h \ - Controllers/EKController/EKController.h \ - Controllers/EKController/RGBController_EKController.h \ - Controllers/ElgatoKeyLightController/ElgatoKeyLightController.h \ - Controllers/ElgatoKeyLightController/RGBController_ElgatoKeyLight.h \ - Controllers/ENESMBusController/ENESMBusController.h \ - Controllers/ENESMBusController/RGBController_ENESMBus.h \ - Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface.h \ - Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_i2c_smbus.h \ - Controllers/EpomakerController/EpomakerController.h \ - Controllers/EpomakerController/RGBController_EpomakerController.h \ - Controllers/EspurnaController/EspurnaController.h \ - Controllers/EspurnaController/RGBController_Espurna.h \ - Controllers/EVGAGP102GPUController/EVGAGP102Controller.h \ - Controllers/EVGAGP102GPUController/RGBController_EVGAGP102.h \ - Controllers/EVGAPascalGPUController/EVGAGPUv1Controller.h \ - Controllers/EVGAPascalGPUController/RGBController_EVGAGPUv1.h \ - Controllers/EVGATuringGPUController/EVGAGPUv2Controller.h \ - Controllers/EVGATuringGPUController/RGBController_EVGAGPUv2.h \ - Controllers/EVGAAmpereGPUController/EVGAGPUv3Controller.h \ - Controllers/EVGAAmpereGPUController/RGBController_EVGAGPUv3.h \ - Controllers/EVGAUSBController/EVGAKeyboardController.h \ - Controllers/EVGAUSBController/EVGAMouseController.h \ - Controllers/EVGAUSBController/RGBController_EVGAKeyboard.h \ - Controllers/EVGAUSBController/RGBController_EVGAMouse.h \ - Controllers/EVisionKeyboardController/EVisionKeyboardController.h \ - Controllers/EVisionKeyboardController/RGBController_EVisionKeyboard.h \ - Controllers/FanBusController/FanBusController.h \ - Controllers/FanBusController/FanBusInterface.h \ - Controllers/FanBusController/RGBController_FanBus.h \ - Controllers/GainwardGPUController/GainwardGPUv1Controller.h \ - Controllers/GainwardGPUController/GainwardGPUv2Controller.h \ - Controllers/GainwardGPUController/RGBController_GainwardGPUv1.h \ - Controllers/GainwardGPUController/RGBController_GainwardGPUv2.h \ - Controllers/GaiZongGaiKeyboardController/GaiZhongGaiController.h \ - Controllers/GaiZongGaiKeyboardController/RGBController_GaiZhongGai.h \ - Controllers/GalaxGPUController/GalaxGPUController.h \ - Controllers/GalaxGPUController/RGBController_GalaxGPU.h \ - Controllers/GigabyteAorusCPUCoolerController/ATC800Controller.h \ - Controllers/GigabyteAorusCPUCoolerController/RGBController_AorusATC800.h \ - Controllers/GigabyteAorusMouseController/GigabyteAorusMouseController.h \ - Controllers/GigabyteAorusMouseController/RGBController_GigabyteAorusMouse.h \ - Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.h \ - Controllers/GigabyteRGBFusion2DRAMController/RGBController_GigabyteRGBFusion2DRAM.h \ - Controllers/GigabyteRGBFusion2SMBusController/GigabyteRGBFusion2SMBusController.h \ - Controllers/GigabyteRGBFusion2SMBusController/RGBController_GigabyteRGBFusion2SMBus.h \ - Controllers/GigabyteRGBFusion2USBController/GigabyteRGBFusion2USBController.h \ - Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USB.h \ - Controllers/GigabyteRGBFusionController/GigabyteRGBFusionController.h \ - Controllers/GigabyteRGBFusionController/RGBController_GigabyteRGBFusion.h \ - Controllers/GigabyteRGBFusionGPUController/GigabyteRGBFusionGPUController.h \ - Controllers/GigabyteRGBFusionGPUController/RGBController_GigabyteRGBFusionGPU.h \ - Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUController.h \ - Controllers/GigabyteRGBFusion2GPUController/RGBController_GigabyteRGBFusion2GPU.h \ - Controllers/GigabyteSuperIORGBController/GigabyteSuperIORGBController.h \ - Controllers/HoltekController/HoltekA070Controller.h \ - Controllers/HoltekController/HoltekA1FAController.h \ - Controllers/HoltekController/RGBController_HoltekA070.h \ - Controllers/HoltekController/RGBController_HoltekA1FA.h \ - Controllers/HPOmen30LController/HPOmen30LController.h \ - Controllers/HPOmen30LController/RGBController_HPOmen30L.h \ - Controllers/HyperXDRAMController/HyperXDRAMController.h \ - Controllers/HyperXDRAMController/RGBController_HyperXDRAM.h \ - Controllers/HyperXKeyboardController/HyperXAlloyEliteController.h \ - Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller.h \ - Controllers/HyperXKeyboardController/HyperXAlloyFPSController.h \ - Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller.h \ - Controllers/HyperXKeyboardController/HyperXAlloyOriginsController.h \ - Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.h \ - Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite.h \ - Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite2.h \ - Controllers/HyperXKeyboardController/RGBController_HyperXAlloyFPS.h \ - Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins.h \ - Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60and65.h \ - Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.h \ - Controllers/HyperXMicrophoneController/HyperXMicrophoneController.h \ - Controllers/HyperXMicrophoneController/RGBController_HyperXMicrophone.h \ - Controllers/HyperXMouseController/HyperXPulsefireFPSProController.h \ - Controllers/HyperXMouseController/HyperXPulsefireHasteController.h \ - Controllers/HyperXMouseController/HyperXPulsefireSurgeController.h \ - Controllers/HyperXMouseController/HyperXPulsefireDartController.h \ - Controllers/HyperXMouseController/HyperXPulsefireRaidController.h \ - Controllers/HyperXMouseController/RGBController_HyperXPulsefireFPSPro.h \ - Controllers/HyperXMouseController/RGBController_HyperXPulsefireHaste.h \ - Controllers/HyperXMouseController/RGBController_HyperXPulsefireSurge.h \ - Controllers/HyperXMouseController/RGBController_HyperXPulsefireDart.h \ - Controllers/HyperXMouseController/RGBController_HyperXPulsefireRaid.h \ - Controllers/HyperXMousematController/HyperXMousematController.h \ - Controllers/HyperXMousematController/RGBController_HyperXMousemat.h \ - Controllers/IntelArcA770LEController/IntelArcA770LEController.h \ - Controllers/IntelArcA770LEController/RGBController_IntelArcA770LE.h \ - Controllers/IonicoController/IonicoController.h \ - Controllers/IonicoController/RGBController_Ionico.h \ - Controllers/KasaSmartController/KasaSmartController.h \ - Controllers/KasaSmartController/RGBController_KasaSmart.h \ - Controllers/KeychronKeyboardController/KeychronKeyboardController.h \ - Controllers/KeychronKeyboardController/RGBController_KeychronKeyboard.h \ - Controllers/LEDStripController/LEDStripController.h \ - Controllers/LEDStripController/RGBController_LEDStrip.h \ - Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.h \ - Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.h \ - Controllers/LenovoControllers/LenovoDevices.h \ - Controllers/LenovoControllers/LenovoDevices4Zone.h \ - Controllers/LenovoControllers/LenovoUSBController.h \ - Controllers/LenovoControllers/Lenovo4ZoneUSBController.h \ - Controllers/LenovoControllers/RGBController_LenovoUSB.h \ - Controllers/LenovoControllers/RGBController_Lenovo4ZoneUSB.h \ - Controllers/LenovoMotherboardController/LenovoMotherboardController.h \ - Controllers/LenovoMotherboardController/RGBController_LenovoMotherboard.h \ - Controllers/LexipMouseController/LexipMouseController.h \ - Controllers/LexipMouseController/RGBController_LexipMouse.h \ - Controllers/LIFXController/LIFXController.h \ - Controllers/LIFXController/RGBController_LIFX.h \ - Controllers/LianLiController/LianLiUniHubController.h \ - Controllers/LianLiController/LianLiUniHub_AL10Controller.h \ - Controllers/LianLiController/RGBController_LianLiUniHub.h \ - Controllers/LianLiController/RGBController_StrimerLConnect.h \ - Controllers/LianLiController/StrimerLConnectController.h \ - Controllers/LianLiController/LianLiUniHubALController.h \ - Controllers/LianLiController/RGBController_LianLiUniHubAL.h \ - Controllers/LianLiController/RGBController_LianLiUniHub_AL10.h \ - Controllers/LianLiController/LianLiUniHubSLV2Controller.h \ - Controllers/LianLiController/RGBController_LianLiUniHubSLV2.h \ - Controllers/LogitechController/LogitechProtocolCommon.h \ - Controllers/LogitechController/LogitechG203LController.h \ - Controllers/LogitechController/LogitechG213Controller.h \ - Controllers/LogitechController/LogitechG560Controller.h \ - Controllers/LogitechController/LogitechG933Controller.h \ - Controllers/LogitechController/LogitechG810Controller.h \ - Controllers/LogitechController/LogitechGProKeyboardController.h \ - Controllers/LogitechController/LogitechG910Controller.h \ - Controllers/LogitechController/LogitechG815Controller.h \ - Controllers/LogitechController/LogitechG915Controller.h \ - Controllers/LogitechController/LogitechGLightsyncController.h \ - Controllers/LogitechController/LogitechLightspeedController.h \ - Controllers/LogitechController/LogitechX56Controller.h \ - Controllers/LogitechController/RGBController_LogitechG203L.h \ - Controllers/LogitechController/RGBController_LogitechG213.h \ - Controllers/LogitechController/RGBController_LogitechG560.h \ - Controllers/LogitechController/RGBController_LogitechG933.h \ - Controllers/LogitechController/RGBController_LogitechG810.h \ - Controllers/LogitechController/RGBController_LogitechGProKeyboard.h \ - Controllers/LogitechController/RGBController_LogitechG910.h \ - Controllers/LogitechController/RGBController_LogitechG815.h \ - Controllers/LogitechController/RGBController_LogitechG915.h \ - Controllers/LogitechController/RGBController_LogitechGLightsync.h \ - Controllers/LogitechController/RGBController_LogitechGLightsync1zone.h \ - Controllers/LogitechController/RGBController_LogitechGPowerPlay.h \ - Controllers/LogitechController/RGBController_LogitechLightspeed.h \ - Controllers/LogitechController/RGBController_LogitechX56.h \ - Controllers/MountainKeyboardController/MountainKeyboardController.h \ - Controllers/MountainKeyboardController/RGBController_MountainKeyboard.h \ - Controllers/MSI3ZoneController/MSI3ZoneController.h \ - Controllers/MSI3ZoneController/RGBController_MSI3Zone.h \ - Controllers/MSIGPUController/MSIGPUController.h \ - Controllers/MSIGPUController/MSIGPUv2Controller.h \ - Controllers/MSIGPUController/RGBController_MSIGPU.h \ - Controllers/MSIGPUController/RGBController_MSIGPUv2.h \ - Controllers/MSIMysticLightController/MSIMysticLightCommon.h \ - Controllers/MSIMysticLightController/MSIMysticLight64Controller.h \ - Controllers/MSIMysticLightController/MSIMysticLight112Controller.h \ - Controllers/MSIMysticLightController/MSIMysticLight162Controller.h \ - Controllers/MSIMysticLightController/MSIMysticLight185Controller.h \ - Controllers/MSIMysticLightController/RGBController_MSIMysticLight64.h \ - Controllers/MSIMysticLightController/RGBController_MSIMysticLight112.h \ - Controllers/MSIMysticLightController/RGBController_MSIMysticLight162.h \ - Controllers/MSIMysticLightController/RGBController_MSIMysticLight185.h \ - Controllers/MSIOptixController/MSIOptixController.h \ - Controllers/MSIOptixController/RGBController_MSIOptix.h \ - Controllers/MSIRGBController/MSIRGBController.h \ - Controllers/MSIVigorController/RGBController_MSIVigorGK30.h \ - Controllers/MSIVigorController/MSIVigorGK30Controller.h \ - Controllers/NanoleafController/NanoleafController.h \ - Controllers/MSIRGBController/RGBController_MSIRGB.h \ - Controllers/N5312AController/N5312AController.h \ - Controllers/N5312AController/RGBController_N5312A.h \ - Controllers/NvidiaESAController/NvidiaESAController.h \ - Controllers/NanoleafController/RGBController_Nanoleaf.h \ - Controllers/NollieController/NollieController.h \ - Controllers/NollieController/RGBController_Nollie.h \ - Controllers/NvidiaESAController/RGBController_NvidiaESA.h \ - Controllers/NZXTHue1Controller/NZXTHue1Controller.h \ - Controllers/NZXTHue1Controller/RGBController_NZXTHue1.h \ - Controllers/NZXTHue2Controller/NZXTHue2Controller.h \ - Controllers/NZXTHue2Controller/RGBController_NZXTHue2.h \ - Controllers/NZXTHuePlusController/NZXTHuePlusController.h \ - Controllers/NZXTHuePlusController/RGBController_NZXTHuePlus.h \ - Controllers/NZXTKrakenController/NZXTKrakenController.h \ - Controllers/NZXTKrakenController/RGBController_NZXTKraken.h \ - Controllers/OpenRazerController/OpenRazerDevices.h \ - Controllers/OKSController/OKSKeyboardController.h \ - Controllers/OKSController/RGBController_OKSKeyboard.h \ - Controllers/PalitGPUController/PalitGPUController.h \ - Controllers/PalitGPUController/RGBController_PalitGPU.h \ - Controllers/PatriotViperController/PatriotViperController.h \ - Controllers/PatriotViperController/RGBController_PatriotViper.h \ - Controllers/PatriotViperSteelController/PatriotViperSteelController.h \ - Controllers/PatriotViperSteelController/RGBController_PatriotViperSteel.h \ - Controllers/PhilipsHueController/PhilipsHueController.h \ - Controllers/PhilipsHueController/RGBController_PhilipsHue.h \ - Controllers/PhilipsWizController/PhilipsWizController.h \ - Controllers/PhilipsWizController/RGBController_PhilipsWiz.h \ - Controllers/PNYGPUController/PNYGPUController.h \ - Controllers/PNYGPUController/RGBController_PNYGPU.h \ - Controllers/QMKOpenRGBController/QMKOpenRGBController.h \ - Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller.h \ - Controllers/QMKOpenRGBController/QMKOpenRGBRevBController.h \ - Controllers/QMKOpenRGBController/QMKOpenRGBRevDController.h \ - Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRev9.h \ - Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevB.h \ - Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevD.h \ - Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevE.h \ - Controllers/RazerController/RazerController.h \ - Controllers/RazerController/RazerKrakenController.h \ - Controllers/RazerController/RazerDevices.h \ - Controllers/RazerController/RGBController_Razer.h \ - Controllers/RazerController/RGBController_RazerAddressable.h \ - Controllers/RazerController/RGBController_RazerKraken.h \ - Controllers/RedragonController/RGBController_RedragonMouse.h \ - Controllers/RedragonController/RedragonMouseController.h \ - Controllers/RedSquareKeyroxController/RedSquareKeyroxController.h \ - Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController.h \ - Controllers/RedSquareKeyroxController/RGBController_RedSquareKeyrox.h \ - Controllers/RedSquareKeyroxController/RGBController_RedSquareKeyroxTKLClassic.h \ - Controllers/RoccatController/RGBController_RoccatBurst.h \ - Controllers/RoccatController/RGBController_RoccatElo.h \ - Controllers/RoccatController/RGBController_RoccatHordeAimo.h \ - Controllers/RoccatController/RGBController_RoccatKoneAimo.h \ - Controllers/RoccatController/RGBController_RoccatKova.h \ - Controllers/RoccatController/RGBController_RoccatVulcanAimo.h \ - Controllers/RoccatController/RoccatBurstController.h \ - Controllers/RoccatController/RoccatEloController.h \ - Controllers/RoccatController/RoccatHordeAimoController.h \ - Controllers/RoccatController/RoccatKoneAimoController.h \ - Controllers/RoccatController/RoccatKovaController.h \ - Controllers/RoccatController/RoccatVulcanAimoController.h \ - Controllers/RoccatController/RoccatVulcanAimoLayouts.h \ - Controllers/SapphireGPUController/SapphireNitroGlowV1Controller.h \ - Controllers/SapphireGPUController/SapphireNitroGlowV3Controller.h \ - Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV1.h \ - Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV3.h \ - Controllers/SinowealthController/SinowealthController.h \ - Controllers/SinowealthController/SinowealthController1007.h \ - Controllers/SinowealthController/SinowealthGMOWController.h \ - Controllers/SinowealthController/SinowealthKeyboardController.h \ - Controllers/SinowealthController/SinowealthKeyboard16Controller.h \ - Controllers/SinowealthController/SinowealthKeyboard90Controller.h \ - Controllers/SinowealthController/RGBController_Sinowealth.h \ - Controllers/SinowealthController/RGBController_Sinowealth1007.h \ - Controllers/SinowealthController/RGBController_SinowealthGMOW.h \ - Controllers/SinowealthController/RGBController_SinowealthKeyboard.h \ - Controllers/SinowealthController/RGBController_SinowealthKeyboard16.h \ - Controllers/SinowealthController/RGBController_SinowealthKeyboard90.h \ - Controllers/SonyGamepadController/SonyDualSenseController.h \ - Controllers/SonyGamepadController/RGBController_SonyDualSense.h \ - Controllers/SonyGamepadController/SonyDS4Controller.h \ - Controllers/SonyGamepadController/RGBController_SonyDS4.h \ - Controllers/SRGBmodsController/SRGBmodsLEDControllerV1.h \ - Controllers/SRGBmodsController/RGBController_SRGBmodsLEDControllerV1.h \ - Controllers/SRGBmodsController/SRGBmodsPicoController.h \ - Controllers/SRGBmodsController/RGBController_SRGBmodsPico.h \ - Controllers/SteelSeriesController/color32.h \ - Controllers/SteelSeriesController/SteelSeriesAerox3Controller.h \ - Controllers/SteelSeriesController/SteelSeriesAerox9Controller.h \ - Controllers/SteelSeriesController/SteelSeriesApexBaseController.h \ - Controllers/SteelSeriesController/SteelSeriesApexController.h \ - Controllers/SteelSeriesController/SteelSeriesApex3Controller.h \ - Controllers/SteelSeriesController/SteelSeriesApex8ZoneController.h \ - Controllers/SteelSeriesController/SteelSeriesApexMController.h \ - Controllers/SteelSeriesController/SteelSeriesApexRegions.h \ - Controllers/SteelSeriesController/SteelSeriesApexTZoneController.h \ - Controllers/SteelSeriesController/SteelSeriesArctis5Controller.h \ - Controllers/SteelSeriesController/SteelSeriesGeneric.h \ - Controllers/SteelSeriesController/SteelSeriesMouseController.h \ - Controllers/SteelSeriesController/SteelSeriesOldApexController.h \ - Controllers/SteelSeriesController/SteelSeriesRivalController.h \ - Controllers/SteelSeriesController/SteelSeriesRival3Controller.h \ - Controllers/SteelSeriesController/SteelSeriesSenseiController.h \ - Controllers/SteelSeriesController/SteelSeriesSiberiaController.h \ - Controllers/SteelSeriesController/SteelSeriesQCKMatController.h \ - Controllers/SteelSeriesController/RGBController_SteelSeriesApex.h \ - Controllers/SteelSeriesController/RGBController_SteelSeriesApex3.h \ - Controllers/SteelSeriesController/RGBController_SteelSeriesArctis5.h \ - Controllers/SteelSeriesController/RGBController_SteelSeriesOldApex.h \ - Controllers/SteelSeriesController/RGBController_SteelSeriesRival.h \ - Controllers/SteelSeriesController/RGBController_SteelSeriesRival3.h \ - Controllers/SteelSeriesController/RGBController_SteelSeriesSiberia.h \ - Controllers/SteelSeriesController/RGBController_SteelSeriesQCKMat.h \ - Controllers/SteelSeriesController/RGBController_SteelSeriesSensei.h \ - Controllers/TecknetController/TecknetController.h \ - Controllers/TecknetController/RGBController_Tecknet.h \ - Controllers/ThermaltakePoseidonZRGBController/ThermaltakePoseidonZRGBController.h \ - Controllers/ThermaltakePoseidonZRGBController/RGBController_ThermaltakePoseidonZRGB.h \ - Controllers/ThermaltakeRiingController/ThermaltakeRiingController.h \ - Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController.h \ - Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiing.h \ - Controllers/ThingMController/BlinkController.h \ - Controllers/ThingMController/RGBController_BlinkController.h \ - Controllers/TrustController/RGBController_TrustGXT114.h \ - Controllers/TrustController/RGBController_TrustGXT180.h \ - Controllers/TrustController/TrustGXT114Controller.h \ - Controllers/TrustController/TrustGXT180Controller.h \ - Controllers/ViewSonicController/VS_XG270QG_Controller.h \ - Controllers/ViewSonicController/RGBController_XG270QG.h \ - Controllers/WootingKeyboardController/WootingKeyboardController.h \ - Controllers/WootingKeyboardController/WootingOneKeyboardController.h \ - Controllers/WootingKeyboardController/WootingTwoKeyboardController.h \ - Controllers/WootingKeyboardController/RGBController_WootingKeyboard.h \ - Controllers/WushiController/WushiL50USBController.h \ - Controllers/WushiController/RGBController_WushiL50USB.h \ - Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiingQuad.h \ - Controllers/YeelightController/YeelightController.h \ - Controllers/YeelightController/RGBController_Yeelight.h \ - Controllers/ZalmanZSyncController/ZalmanZSyncController.h \ - Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.h \ - Controllers/ZETEdgeAirProController/ZETEdgeAirProController.h \ - Controllers/ZETEdgeAirProController/RGBController_ZETEdgeAirPro.h \ - Controllers/ZETKeyboardController/ZETBladeOpticalController.h \ - Controllers/ZETKeyboardController/RGBController_ZETBladeOptical.h \ - Controllers/ZotacTuringGPUController/ZotacTuringGPUController.h \ - Controllers/ZotacTuringGPUController/RGBController_ZotacTuringGPU.h \ - Controllers/ZotacV2GPUController/ZotacV2GPUController.h \ - Controllers/ZotacV2GPUController/RGBController_ZotacV2GPU.h \ KeyboardLayoutManager/KeyboardLayoutManager.h \ RGBController/RGBController.h \ RGBController/RGBController_Dummy.h \ RGBController/RGBControllerKeyNames.h \ RGBController/RGBController_Network.h \ - -contains(QMAKE_PLATFORM, freebsd) { - HEADERS -= \ - Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUController.h \ - Controllers/GigabyteRGBFusion2GPUController/RGBController_GigabyteRGBFusion2GPU.h \ - Controllers/HoltekController/HoltekA070Controller.h \ - Controllers/HoltekController/HoltekA1FAController.h \ - Controllers/HoltekController/RGBController_HoltekA070.h \ - Controllers/HoltekController/RGBController_HoltekA1FA.h -} + startup/startup.h \ SOURCES += \ - dependencies/Swatches/swatches.cpp \ - dependencies/dmiinfo.cpp \ + $$GUI_CPP \ + $$CONTROLLER_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 \ + dependencies/hueplusplus-1.2.0/src/Action.cpp \ + dependencies/hueplusplus-1.2.0/src/APICache.cpp \ + dependencies/hueplusplus-1.2.0/src/BaseDevice.cpp \ + dependencies/hueplusplus-1.2.0/src/BaseHttpHandler.cpp \ + dependencies/hueplusplus-1.2.0/src/Bridge.cpp \ + dependencies/hueplusplus-1.2.0/src/BridgeConfig.cpp \ + dependencies/hueplusplus-1.2.0/src/CLIPSensors.cpp \ + dependencies/hueplusplus-1.2.0/src/ColorUnits.cpp \ + dependencies/hueplusplus-1.2.0/src/EntertainmentMode.cpp \ + dependencies/hueplusplus-1.2.0/src/ExtendedColorHueStrategy.cpp \ + dependencies/hueplusplus-1.2.0/src/ExtendedColorTemperatureStrategy.cpp \ + dependencies/hueplusplus-1.2.0/src/Group.cpp \ + dependencies/hueplusplus-1.2.0/src/HueCommandAPI.cpp \ + dependencies/hueplusplus-1.2.0/src/HueDeviceTypes.cpp \ + dependencies/hueplusplus-1.2.0/src/HueException.cpp \ + dependencies/hueplusplus-1.2.0/src/Light.cpp \ + dependencies/hueplusplus-1.2.0/src/ModelPictures.cpp \ + dependencies/hueplusplus-1.2.0/src/NewDeviceList.cpp \ + dependencies/hueplusplus-1.2.0/src/Scene.cpp \ + dependencies/hueplusplus-1.2.0/src/Schedule.cpp \ + dependencies/hueplusplus-1.2.0/src/Sensor.cpp \ + dependencies/hueplusplus-1.2.0/src/SimpleBrightnessStrategy.cpp \ + dependencies/hueplusplus-1.2.0/src/SimpleColorHueStrategy.cpp \ + dependencies/hueplusplus-1.2.0/src/SimpleColorTemperatureStrategy.cpp \ + dependencies/hueplusplus-1.2.0/src/StateTransaction.cpp \ + dependencies/hueplusplus-1.2.0/src/TimePattern.cpp \ + dependencies/hueplusplus-1.2.0/src/UPnP.cpp \ + dependencies/hueplusplus-1.2.0/src/Utils.cpp \ + dependencies/hueplusplus-1.2.0/src/ZLLSensors.cpp \ + startup/startup.cpp \ cli.cpp \ + dmiinfo/dmiinfo.cpp \ LogManager.cpp \ NetworkClient.cpp \ + NetworkProtocol.cpp \ NetworkServer.cpp \ PluginManager.cpp \ ProfileManager.cpp \ ResourceManager.cpp \ + SPDAccessor/DDR4DirectAccessor.cpp \ + SPDAccessor/DDR5DirectAccessor.cpp \ + SPDAccessor/SPDAccessor.cpp \ + SPDAccessor/SPDDetector.cpp \ + SPDAccessor/SPDWrapper.cpp \ SettingsManager.cpp \ - qt/DetectorTableModel.cpp \ i2c_smbus/i2c_smbus.cpp \ i2c_tools/i2c_tools.cpp \ + interop/DeviceGuard.cpp \ + interop/DeviceGuardLock.cpp \ + interop/DeviceGuardManager.cpp \ net_port/net_port.cpp \ - qt/DeviceView.cpp \ - qt/hsv.cpp \ - qt/OpenRGBFont.cpp \ - qt/OpenRGBThemeManager.cpp \ - qt/QTooltipedSlider.cpp \ - qt/TabLabel.cpp \ - qt/OpenRGBClientInfoPage/OpenRGBClientInfoPage.cpp \ - qt/OpenRGBConsolePage/OpenRGBConsolePage.cpp \ - qt/OpenRGBDeviceInfoPage/OpenRGBDeviceInfoPage.cpp \ - qt/OpenRGBDevicePage/OpenRGBDevicePage.cpp \ - qt/OpenRGBDialog2/OpenRGBDialog2.cpp \ - qt/OpenRGBDMXSettingsPage/OpenRGBDMXSettingsEntry.cpp \ - qt/OpenRGBDMXSettingsPage/OpenRGBDMXSettingsPage.cpp \ - qt/OpenRGBE131SettingsPage/OpenRGBE131SettingsEntry.cpp \ - qt/OpenRGBE131SettingsPage/OpenRGBE131SettingsPage.cpp \ - qt/OpenRGBElgatoKeyLightSettingsPage/OpenRGBElgatoKeyLightSettingsEntry.cpp \ - qt/OpenRGBElgatoKeyLightSettingsPage/OpenRGBElgatoKeyLightSettingsPage.cpp \ - qt/OpenRGBHardwareIDsDialog/OpenRGBHardwareIDsDialog.cpp \ - qt/OpenRGBKasaSmartSettingsPage/OpenRGBKasaSmartSettingsEntry.cpp \ - qt/OpenRGBKasaSmartSettingsPage/OpenRGBKasaSmartSettingsPage.cpp \ - qt/OpenRGBLIFXSettingsPage/OpenRGBLIFXSettingsEntry.cpp \ - qt/OpenRGBLIFXSettingsPage/OpenRGBLIFXSettingsPage.cpp \ - qt/OpenRGBNanoleafSettingsPage/OpenRGBNanoleafSettingsEntry.cpp \ - qt/OpenRGBNanoleafSettingsPage/OpenRGBNanoleafSettingsPage.cpp \ - qt/OpenRGBNanoleafSettingsPage/OpenRGBNanoleafScanningThread.cpp \ - qt/OpenRGBPhilipsHueSettingsPage/OpenRGBPhilipsHueSettingsEntry.cpp \ - qt/OpenRGBPhilipsHueSettingsPage/OpenRGBPhilipsHueSettingsPage.cpp \ - qt/OpenRGBPhilipsWizSettingsPage/OpenRGBPhilipsWizSettingsEntry.cpp \ - qt/OpenRGBPhilipsWizSettingsPage/OpenRGBPhilipsWizSettingsPage.cpp \ - qt/OpenRGBPluginContainer/OpenRGBPluginContainer.cpp \ - qt/OpenRGBPluginsPage/OpenRGBPluginsEntry.cpp \ - qt/OpenRGBPluginsPage/OpenRGBPluginsList.cpp \ - qt/OpenRGBPluginsPage/OpenRGBPluginsPage.cpp \ - qt/OpenRGBProfileSaveDialog/OpenRGBProfileSaveDialog.cpp \ - qt/OpenRGBQMKORGBSettingsPage/OpenRGBQMKORGBSettingsEntry.cpp \ - qt/OpenRGBQMKORGBSettingsPage/OpenRGBQMKORGBSettingsPage.cpp \ - qt/OpenRGBSerialSettingsPage/OpenRGBSerialSettingsEntry.cpp \ - qt/OpenRGBSerialSettingsPage/OpenRGBSerialSettingsPage.cpp \ - qt/OpenRGBServerInfoPage/OpenRGBServerInfoPage.cpp \ - qt/OpenRGBSettingsPage/OpenRGBSettingsPage.cpp \ - qt/OpenRGBSoftwareInfoPage/OpenRGBSoftwareInfoPage.cpp \ - qt/OpenRGBSupportedDevicesPage/OpenRGBSupportedDevicesPage.cpp \ - qt/OpenRGBSystemInfoPage/OpenRGBSystemInfoPage.cpp \ - qt/OpenRGBYeelightSettingsPage/OpenRGBYeelightSettingsEntry.cpp \ - qt/OpenRGBYeelightSettingsPage/OpenRGBYeelightSettingsPage.cpp \ - qt/OpenRGBZoneResizeDialog/OpenRGBZoneResizeDialog.cpp \ - qt/OpenRGBZonesBulkResizer/OpenRGBZonesBulkResizer.cpp \ serial_port/serial_port.cpp \ StringUtils.cpp \ super_io/super_io.cpp \ AutoStart/AutoStart.cpp \ - Controllers/A4TechController/A4Tech_Detector.cpp \ - Controllers/A4TechController/BloodyMouseController.cpp \ - Controllers/A4TechController/RGBController_BloodyMouse.cpp \ - Controllers/AlienwareController/AlienwareController.cpp \ - Controllers/AlienwareController/AlienwareControllerDetect.cpp \ - Controllers/AlienwareController/RGBController_Alienware.cpp \ - Controllers/AlienwareKeyboardController/AlienwareAW510KController.cpp \ - Controllers/AlienwareKeyboardController/AlienwareKeyboardControllerDetect.cpp \ - Controllers/AlienwareKeyboardController/RGBController_AlienwareAW510K.cpp \ - Controllers/AMDWraithPrismController/AMDWraithPrismController.cpp \ - Controllers/AMDWraithPrismController/AMDWraithPrismControllerDetect.cpp \ - Controllers/AMDWraithPrismController/RGBController_AMDWraithPrism.cpp \ - Controllers/AnnePro2Controller/AnnePro2Controller.cpp \ - Controllers/AnnePro2Controller/AnnePro2ControllerDetect.cpp \ - Controllers/AnnePro2Controller/RGBController_AnnePro2.cpp \ - Controllers/AOCKeyboardController/AOCKeyboardController.cpp \ - Controllers/AOCKeyboardController/AOCKeyboardControllerDetect.cpp \ - Controllers/AOCKeyboardController/RGBController_AOCKeyboard.cpp \ - Controllers/AOCMouseController/AOCMouseController.cpp \ - Controllers/AOCMouseController/AOCMouseControllerDetect.cpp \ - Controllers/AOCMouseController/RGBController_AOCMouse.cpp \ - Controllers/AOCMousematController/AOCMousematController.cpp \ - Controllers/AOCMousematController/AOCMousematControllerDetect.cpp \ - Controllers/AOCMousematController/RGBController_AOCMousemat.cpp \ - Controllers/ASRockPolychromeUSBController/ASRockPolychromeUSBController.cpp \ - Controllers/ASRockPolychromeUSBController/ASRockPolychromeUSBControllerDetect.cpp \ - Controllers/ASRockPolychromeUSBController/RGBController_ASRockPolychromeUSB.cpp \ - Controllers/ASRockSMBusController/ASRockASRRGBSMBusController.cpp \ - Controllers/ASRockSMBusController/ASRockPolychromeV1SMBusController.cpp \ - Controllers/ASRockSMBusController/ASRockPolychromeV2SMBusController.cpp \ - Controllers/ASRockSMBusController/ASRockSMBusControllerDetect.cpp \ - Controllers/ASRockSMBusController/RGBController_ASRockASRRGBSMBus.cpp \ - Controllers/ASRockSMBusController/RGBController_ASRockPolychromeV1SMBus.cpp \ - Controllers/ASRockSMBusController/RGBController_ASRockPolychromeV2SMBus.cpp \ - Controllers/AsusAuraCoreController/AsusAuraCoreController.cpp \ - Controllers/AsusAuraCoreController/AsusAuraCoreControllerDetect.cpp \ - Controllers/AsusAuraCoreController/AsusAuraCoreLaptopController.cpp \ - Controllers/AsusAuraCoreController/RGBController_AsusAuraCore.cpp \ - Controllers/AsusAuraCoreController/RGBController_AsusAuraCoreLaptop.cpp \ - Controllers/AsusAuraGPUController/AsusAuraGPUController.cpp \ - Controllers/AsusAuraGPUController/AsusAuraGPUControllerDetect.cpp \ - Controllers/AsusAuraGPUController/RGBController_AsusAuraGPU.cpp \ - Controllers/AsusAuraUSBController/AsusAuraUSBController.cpp \ - Controllers/AsusAuraUSBController/AsusAuraAddressableController.cpp \ - Controllers/AsusAuraUSBController/AsusAuraHeadsetStandController.cpp \ - Controllers/AsusAuraUSBController/AsusAuraKeyboardController.cpp \ - Controllers/AsusAuraUSBController/AsusAuraMainboardController.cpp \ - Controllers/AsusAuraUSBController/AsusAuraMonitorController.cpp \ - Controllers/AsusAuraUSBController/AsusAuraMouseController.cpp \ - Controllers/AsusAuraUSBController/AsusAuraMousematController.cpp \ - Controllers/AsusAuraUSBController/AsusROGAllyController.cpp \ - Controllers/AsusAuraUSBController/AsusAuraRyuoAIOController.cpp \ - Controllers/AsusAuraUSBController/AsusAuraStrixEvolveController.cpp \ - Controllers/AsusAuraUSBController/AsusAuraTUFKeyboardController.cpp \ - Controllers/AsusAuraUSBController/AsusAuraUSBControllerDetect.cpp \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraHeadsetStand.cpp \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraKeyboard.cpp \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraMonitor.cpp \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraMouse.cpp \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraMousemat.cpp \ - Controllers/AsusAuraUSBController/RGBController_AsusROGAlly.cpp \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraRyuoAIO.cpp \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraStrixEvolve.cpp \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraTUFKeyboard.cpp \ - Controllers/AsusAuraUSBController/RGBController_AsusAuraUSB.cpp \ - Controllers/AsusAuraUSBController/RGBController_ROGStrixLC_Controller.cpp \ - Controllers/AsusAuraUSBController/ROGStrixLC_Controller.cpp \ - Controllers/AsusLegacyUSBController/AsusCerberusKeyboardController.cpp \ - Controllers/AsusLegacyUSBController/AsusLegacyUSBControllerDetect.cpp \ - Controllers/AsusLegacyUSBController/AsusStrixClawController.cpp \ - Controllers/AsusLegacyUSBController/RGBController_AsusCerberusKeyboard.cpp \ - Controllers/AsusLegacyUSBController/RGBController_AsusStrixClaw.cpp \ - Controllers/BlinkyTapeController/BlinkyTapeController.cpp \ - Controllers/BlinkyTapeController/BlinkyTapeControllerDetect.cpp \ - Controllers/BlinkyTapeController/RGBController_BlinkyTape.cpp \ - Controllers/CherryKeyboardController/CherryKeyboardController.cpp \ - Controllers/CherryKeyboardController/CherryKeyboardControllerDetect.cpp \ - Controllers/CherryKeyboardController/RGBController_CherryKeyboard.cpp \ - Controllers/ColorfulGPUController/ColorfulGPUController.cpp \ - Controllers/ColorfulGPUController/ColorfulGPUControllerDetect.cpp \ - Controllers/ColorfulGPUController/RGBController_ColorfulGPU.cpp \ - Controllers/ColorfulTuringGPUController/ColorfulTuringGPUController.cpp \ - Controllers/ColorfulTuringGPUController/ColorfulTuringGPUControllerDetect.cpp \ - Controllers/ColorfulTuringGPUController/RGBController_ColorfulTuringGPU.cpp \ - Controllers/CoolerMasterController/CMARGBcontroller.cpp \ - Controllers/CoolerMasterController/CMARGBGen2A1controller.cpp \ - Controllers/CoolerMasterController/CMMKController.cpp \ - Controllers/CoolerMasterController/CMMMController.cpp \ - Controllers/CoolerMasterController/CMMM711Controller.cpp \ - Controllers/CoolerMasterController/CMMP750Controller.cpp \ - Controllers/CoolerMasterController/CMR6000Controller.cpp \ - Controllers/CoolerMasterController/CMRGBController.cpp \ - Controllers/CoolerMasterController/CMSmallARGBController.cpp \ - Controllers/CoolerMasterController/CoolerMasterControllerDetect.cpp \ - Controllers/CoolerMasterController/RGBController_CMARGBController.cpp \ - Controllers/CoolerMasterController/RGBController_CMARGBGen2A1Controller.cpp \ - Controllers/CoolerMasterController/RGBController_CMMKController.cpp \ - Controllers/CoolerMasterController/RGBController_CMMMController.cpp \ - Controllers/CoolerMasterController/RGBController_CMMM711Controller.cpp \ - Controllers/CoolerMasterController/RGBController_CMMP750Controller.cpp \ - Controllers/CoolerMasterController/RGBController_CMR6000Controller.cpp \ - Controllers/CoolerMasterController/RGBController_CMRGBController.cpp \ - Controllers/CoolerMasterController/RGBController_CMSmallARGBController.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 \ - Controllers/CorsairHydroController/CorsairHydroController.cpp \ - Controllers/CorsairHydroController/CorsairHydroControllerDetect.cpp \ - Controllers/CorsairHydroController/RGBController_CorsairHydro.cpp \ - Controllers/CorsairHydro2Controller/CorsairHydro2Controller.cpp \ - Controllers/CorsairHydro2Controller/CorsairHydro2ControllerDetect.cpp \ - Controllers/CorsairHydro2Controller/RGBController_CorsairHydro2.cpp \ - Controllers/CorsairHydroPlatinumController/CorsairHydroPlatinumController.cpp \ - Controllers/CorsairHydroPlatinumController/CorsairHydroPlatinumControllerDetect.cpp \ - Controllers/CorsairHydroPlatinumController/RGBController_CorsairHydroPlatinum.cpp \ - Controllers/CorsairLightingNodeController/CorsairLightingNodeController.cpp \ - Controllers/CorsairLightingNodeController/CorsairLightingNodeControllerDetect.cpp \ - Controllers/CorsairLightingNodeController/RGBController_CorsairLightingNode.cpp \ - Controllers/CorsairPeripheralController/CorsairPeripheralController.cpp \ - Controllers/CorsairPeripheralController/CorsairPeripheralControllerDetect.cpp \ - Controllers/CorsairPeripheralController/CorsairK100Controller.cpp \ - Controllers/CorsairPeripheralController/CorsairK55RGBPROXTController.cpp \ - Controllers/CorsairPeripheralController/CorsairK65MiniController.cpp \ - Controllers/CorsairPeripheralController/CorsairK95PlatinumXTController.cpp \ - Controllers/CorsairPeripheralController/RGBController_CorsairPeripheral.cpp \ - Controllers/CorsairPeripheralController/RGBController_CorsairK100.cpp \ - Controllers/CorsairPeripheralController/RGBController_CorsairK55RGBPROXT.cpp \ - Controllers/CorsairPeripheralController/RGBController_CorsairK65Mini.cpp \ - Controllers/CorsairPeripheralController/RGBController_CorsairK95PlatinumXT.cpp \ - Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Devices.cpp \ - Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2Controller.cpp \ - Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2ControllerDetect.cpp \ - Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2HardwareController.cpp \ - Controllers/CorsairPeripheralV2Controller/CorsairPeripheralV2SoftwareController.cpp \ - Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Hardware.cpp \ - Controllers/CorsairPeripheralV2Controller/RGBController_CorsairV2Software.cpp \ - Controllers/CorsairVengeanceController/CorsairVengeanceController.cpp \ - Controllers/CorsairVengeanceController/CorsairVengeanceControllerDetect.cpp \ - Controllers/CorsairVengeanceController/RGBController_CorsairVengeance.cpp \ - Controllers/CorsairVengeanceProController/CorsairVengeanceProController.cpp \ - Controllers/CorsairVengeanceProController/CorsairVengeanceProControllerDetect.cpp \ - Controllers/CorsairVengeanceProController/RGBController_CorsairVengeancePro.cpp \ - Controllers/CorsairWirelessController/CorsairWirelessController.cpp \ - Controllers/CorsairWirelessController/CorsairWirelessControllerDetect.cpp \ - Controllers/CorsairWirelessController/RGBController_CorsairWireless.cpp \ - Controllers/CougarController/CougarKeyboardController.cpp \ - Controllers/CougarController/CougarRevengerSTController.cpp \ - Controllers/CougarController/CougarControllerDetect.cpp \ - Controllers/CougarController/RGBController_CougarKeyboard.cpp \ - Controllers/CougarController/RGBController_CougarRevengerST.cpp \ - Controllers/CreativeController/CreativeSoundBlasterXG6Controller.cpp \ - Controllers/CreativeController/CreativeControllerDetect.cpp \ - Controllers/CreativeController/RGBController_CreativeSoundBlasterXG6.cpp \ - Controllers/CrucialController/CrucialController.cpp \ - Controllers/CrucialController/CrucialControllerDetect.cpp \ - Controllers/CrucialController/RGBController_Crucial.cpp \ - Controllers/CryorigH7QuadLumiController/CryorigH7QuadLumiController.cpp \ - Controllers/CryorigH7QuadLumiController/CryorigH7QuadLumiControllerDetect.cpp \ - Controllers/CryorigH7QuadLumiController/RGBController_CryorigH7QuadLumi.cpp \ - Controllers/DebugController/DebugControllerDetect.cpp \ - Controllers/DarkProject/DarkProjectControllerDetect.cpp \ - Controllers/DarkProject/DarkProjectKeyboardController.cpp \ - Controllers/DarkProject/RGBController_DarkProjectKeyboard.cpp \ - Controllers/DasKeyboardController/DasKeyboardController.cpp \ - Controllers/DasKeyboardController/DasKeyboardControllerDetect.cpp \ - Controllers/DasKeyboardController/RGBController_DasKeyboard.cpp \ - Controllers/DMXController/DMXControllerDetect.cpp \ - Controllers/DMXController/RGBController_DMX.cpp \ - Controllers/DuckyKeyboardController/DuckyKeyboardController.cpp \ - Controllers/DuckyKeyboardController/DuckyKeyboardControllerDetect.cpp \ - Controllers/DuckyKeyboardController/RGBController_DuckyKeyboard.cpp \ - Controllers/DebugController/RGBController_Debug.cpp \ - Controllers/DygmaRaiseController/DygmaRaiseController.cpp \ - Controllers/DygmaRaiseController/DygmaRaiseControllerDetect.cpp \ - Controllers/DygmaRaiseController/RGBController_DygmaRaise.cpp \ - Controllers/E131Controller/E131ControllerDetect.cpp \ - Controllers/E131Controller/RGBController_E131.cpp \ - Controllers/EKController/EKControllerDetect.cpp \ - Controllers/EKController/EKController.cpp \ - Controllers/EKController/RGBController_EKController.cpp \ - Controllers/ElgatoKeyLightController/ElgatoKeyLightController.cpp \ - Controllers/ElgatoKeyLightController/ElgatoKeyLightControllerDetect.cpp \ - Controllers/ElgatoKeyLightController/RGBController_ElgatoKeyLight.cpp \ - Controllers/ENESMBusController/ENESMBusController.cpp \ - Controllers/ENESMBusController/ENESMBusControllerDetect.cpp \ - Controllers/ENESMBusController/RGBController_ENESMBus.cpp \ - Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_i2c_smbus.cpp \ - Controllers/EpomakerController/EpomakerController.cpp \ - Controllers/EpomakerController/EpomakerControllerDetect.cpp \ - Controllers/EpomakerController/RGBController_EpomakerController.cpp \ - Controllers/EspurnaController/EspurnaController.cpp \ - Controllers/EspurnaController/EspurnaControllerDetect.cpp \ - Controllers/EspurnaController/RGBController_Espurna.cpp \ - Controllers/EVGAGP102GPUController/EVGAGP102Controller.cpp \ - Controllers/EVGAGP102GPUController/EVGAGP102GPUControllerDetect.cpp \ - Controllers/EVGAGP102GPUController/RGBController_EVGAGP102.cpp \ - Controllers/EVGAPascalGPUController/EVGAGPUv1Controller.cpp \ - Controllers/EVGAPascalGPUController/EVGAPascalGPUControllerDetect.cpp \ - Controllers/EVGAPascalGPUController/RGBController_EVGAGPUv1.cpp \ - Controllers/EVGATuringGPUController/EVGAGPUv2Controller.cpp \ - Controllers/EVGATuringGPUController/EVGATuringGPUControllerDetect.cpp \ - Controllers/EVGATuringGPUController/RGBController_EVGAGPUv2.cpp \ - Controllers/EVGAAmpereGPUController/EVGAGPUv3Controller.cpp \ - Controllers/EVGAAmpereGPUController/EVGAAmpereGPUControllerDetect.cpp \ - Controllers/EVGAAmpereGPUController/RGBController_EVGAGPUv3.cpp \ - Controllers/EVGAUSBController/EVGAKeyboardController.cpp \ - Controllers/EVGAUSBController/EVGAMouseController.cpp \ - Controllers/EVGAUSBController/EVGAUSBControllerDetect.cpp \ - Controllers/EVGAUSBController/RGBController_EVGAKeyboard.cpp \ - Controllers/EVGAUSBController/RGBController_EVGAMouse.cpp \ - Controllers/EVisionKeyboardController/EVisionKeyboardController.cpp \ - Controllers/EVisionKeyboardController/EVisionKeyboardControllerDetect.cpp \ - Controllers/EVisionKeyboardController/RGBController_EVisionKeyboard.cpp \ - Controllers/FanBusController/FanBusController.cpp \ - Controllers/FanBusController/FanBusControllerDetect.cpp \ - Controllers/FanBusController/FanBusInterface.cpp \ - Controllers/FanBusController/RGBController_FanBus.cpp \ - Controllers/GainwardGPUController/GainwardGPUControllerDetect.cpp \ - Controllers/GainwardGPUController/GainwardGPUv1Controller.cpp \ - Controllers/GainwardGPUController/GainwardGPUv2Controller.cpp \ - Controllers/GainwardGPUController/RGBController_GainwardGPUv1.cpp \ - Controllers/GainwardGPUController/RGBController_GainwardGPUv2.cpp \ - Controllers/GaiZongGaiKeyboardController/GaiZhongGaiController.cpp \ - Controllers/GaiZongGaiKeyboardController/GaiZhongGaiControllerDetect.cpp \ - Controllers/GaiZongGaiKeyboardController/RGBController_GaiZhongGai.cpp \ - Controllers/GalaxGPUController/GalaxGPUController.cpp \ - Controllers/GalaxGPUController/GalaxGPUControllerDetect.cpp \ - Controllers/GalaxGPUController/RGBController_GalaxGPU.cpp \ - Controllers/GigabyteAorusCPUCoolerController/ATC800Controller.cpp \ - Controllers/GigabyteAorusCPUCoolerController/GigabyteAorusCPUCoolerControllerDetect.cpp \ - Controllers/GigabyteAorusCPUCoolerController/RGBController_AorusATC800.cpp \ - Controllers/GigabyteAorusMouseController/GigabyteAorusMouseController.cpp \ - Controllers/GigabyteAorusMouseController/GigabyteAorusMouseControllerDetect.cpp \ - Controllers/GigabyteAorusMouseController/RGBController_GigabyteAorusMouse.cpp \ - Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMController.cpp \ - Controllers/GigabyteRGBFusion2DRAMController/GigabyteRGBFusion2DRAMControllerDetect.cpp \ - Controllers/GigabyteRGBFusion2DRAMController/RGBController_GigabyteRGBFusion2DRAM.cpp \ - Controllers/GigabyteRGBFusion2SMBusController/GigabyteRGBFusion2SMBusController.cpp \ - Controllers/GigabyteRGBFusion2SMBusController/GigabyteRGBFusion2SMBusControllerDetect.cpp \ - Controllers/GigabyteRGBFusion2SMBusController/RGBController_GigabyteRGBFusion2SMBus.cpp \ - Controllers/GigabyteRGBFusion2USBController/GigabyteRGBFusion2USBController.cpp \ - Controllers/GigabyteRGBFusion2USBController/GigabyteRGBFusion2USBControllerDetect.cpp \ - Controllers/GigabyteRGBFusion2USBController/RGBController_GigabyteRGBFusion2USB.cpp \ - Controllers/GigabyteRGBFusionController/GigabyteRGBFusionController.cpp \ - Controllers/GigabyteRGBFusionController/GigabyteRGBFusionControllerDetect.cpp \ - Controllers/GigabyteRGBFusionController/RGBController_GigabyteRGBFusion.cpp \ - Controllers/GigabyteRGBFusionGPUController/GigabyteRGBFusionGPUController.cpp \ - Controllers/GigabyteRGBFusionGPUController/GigabyteRGBFusionGPUControllerDetect.cpp \ - Controllers/GigabyteRGBFusionGPUController/RGBController_GigabyteRGBFusionGPU.cpp \ - Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUController.cpp \ - Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUControllerDetect.cpp \ - Controllers/GigabyteRGBFusion2GPUController/RGBController_GigabyteRGBFusion2GPU.cpp \ - Controllers/GigabyteSuperIORGBController/GigabyteSuperIORGBController.cpp \ - Controllers/GigabyteSuperIORGBController/GigabyteSuperIORGBControllerDetect.cpp \ - Controllers/GigabyteSuperIORGBController/RGBController_GigabyteSuperIORGB.cpp \ - Controllers/HoltekController/HoltekA070Controller.cpp \ - Controllers/HoltekController/HoltekA1FAController.cpp \ - Controllers/HoltekController/HoltekControllerDetect.cpp \ - Controllers/HoltekController/RGBController_HoltekA070.cpp \ - Controllers/HoltekController/RGBController_HoltekA1FA.cpp \ - Controllers/HPOmen30LController/HPOmen30LController.cpp \ - Controllers/HPOmen30LController/HPOmen30LControllerDetect.cpp \ - Controllers/HPOmen30LController/RGBController_HPOmen30L.cpp \ - Controllers/HyperXDRAMController/HyperXDRAMController.cpp \ - Controllers/HyperXDRAMController/HyperXDRAMControllerDetect.cpp \ - Controllers/HyperXDRAMController/RGBController_HyperXDRAM.cpp \ - Controllers/HyperXKeyboardController/HyperXAlloyEliteController.cpp \ - Controllers/HyperXKeyboardController/HyperXAlloyElite2Controller.cpp \ - Controllers/HyperXKeyboardController/HyperXAlloyFPSController.cpp \ - Controllers/HyperXKeyboardController/HyperXAlloyOrigins60and65Controller.cpp \ - Controllers/HyperXKeyboardController/HyperXAlloyOriginsController.cpp \ - Controllers/HyperXKeyboardController/HyperXAlloyOriginsCoreController.cpp \ - Controllers/HyperXKeyboardController/HyperXKeyboardControllerDetect.cpp \ - Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite.cpp \ - Controllers/HyperXKeyboardController/RGBController_HyperXAlloyElite2.cpp \ - Controllers/HyperXKeyboardController/RGBController_HyperXAlloyFPS.cpp \ - Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins.cpp \ - Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOrigins60and65.cpp \ - Controllers/HyperXKeyboardController/RGBController_HyperXAlloyOriginsCore.cpp \ - Controllers/HyperXMicrophoneController/HyperXMicrophoneController.cpp \ - Controllers/HyperXMicrophoneController/HyperXMicrophoneControllerDetect.cpp \ - Controllers/HyperXMicrophoneController/RGBController_HyperXMicrophone.cpp \ - Controllers/HyperXMouseController/HyperXMouseControllerDetect.cpp \ - Controllers/HyperXMouseController/HyperXPulsefireFPSProController.cpp \ - Controllers/HyperXMouseController/HyperXPulsefireHasteController.cpp \ - Controllers/HyperXMouseController/HyperXPulsefireSurgeController.cpp \ - Controllers/HyperXMouseController/HyperXPulsefireDartController.cpp \ - Controllers/HyperXMouseController/HyperXPulsefireRaidController.cpp \ - Controllers/HyperXMouseController/RGBController_HyperXPulsefireFPSPro.cpp \ - Controllers/HyperXMouseController/RGBController_HyperXPulsefireHaste.cpp \ - Controllers/HyperXMouseController/RGBController_HyperXPulsefireSurge.cpp \ - Controllers/HyperXMouseController/RGBController_HyperXPulsefireDart.cpp \ - Controllers/HyperXMouseController/RGBController_HyperXPulsefireRaid.cpp \ - Controllers/HyperXMousematController/HyperXMousematController.cpp \ - Controllers/HyperXMousematController/HyperXMousematControllerDetect.cpp \ - Controllers/HyperXMousematController/RGBController_HyperXMousemat.cpp \ - Controllers/IntelArcA770LEController/IntelArcA770LEController.cpp \ - Controllers/IntelArcA770LEController/IntelArcA770LEControllerDetect.cpp \ - Controllers/IonicoController/IonicoController.cpp \ - Controllers/IonicoController/IonicoControllerDetect.cpp \ - Controllers/IonicoController/RGBController_Ionico.cpp \ - Controllers/IntelArcA770LEController/RGBController_IntelArcA770LE.cpp \ - Controllers/KasaSmartController/KasaSmartController.cpp \ - Controllers/KasaSmartController/KasaSmartControllerDetect.cpp \ - Controllers/KasaSmartController/RGBController_KasaSmart.cpp \ - Controllers/KeychronKeyboardController/KeychronKeyboardController.cpp \ - Controllers/KeychronKeyboardController/KeychronKeyboardControllerDetect.cpp \ - Controllers/KeychronKeyboardController/RGBController_KeychronKeyboard.cpp \ - Controllers/LEDStripController/LEDStripController.cpp \ - Controllers/LEDStripController/LEDStripControllerDetect.cpp \ - Controllers/LEDStripController/RGBController_LEDStrip.cpp \ - Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseController.cpp \ - Controllers/LegoDimensionsToypadBaseController/LegoDimensionsToypadBaseControllerDetect.cpp \ - Controllers/LegoDimensionsToypadBaseController/RGBController_LegoDimensionsToypadBase.cpp \ - Controllers/LenovoControllers/LenovoUSBController.cpp \ - Controllers/LenovoControllers/Lenovo4ZoneUSBController.cpp \ - Controllers/LenovoControllers/LenovoUSBDetect.cpp \ - Controllers/LenovoControllers/Lenovo4ZoneUSBDetect.cpp \ - Controllers/LenovoControllers/RGBController_LenovoUSB.cpp \ - Controllers/LenovoControllers/RGBController_Lenovo4ZoneUSB.cpp \ - Controllers/LenovoMotherboardController/LenovoMotherboardController.cpp \ - Controllers/LenovoMotherboardController/LenovoMotherboardControllerDetect.cpp \ - Controllers/LenovoMotherboardController/RGBController_LenovoMotherboard.cpp \ - Controllers/LexipMouseController/LexipMouseController.cpp \ - Controllers/LexipMouseController/LexipMouseControllerDetect.cpp \ - Controllers/LexipMouseController/RGBController_LexipMouse.cpp \ - Controllers/LIFXController/LIFXController.cpp \ - Controllers/LIFXController/LIFXControllerDetect.cpp \ - Controllers/LIFXController/RGBController_LIFX.cpp \ - Controllers/LianLiController/LianLiControllerDetect.cpp \ - Controllers/LianLiController/LianLiUniHub_AL10Controller.cpp \ - Controllers/LianLiController/LianLiUniHubController.cpp \ - Controllers/LianLiController/RGBController_LianLiUniHub.cpp \ - Controllers/LianLiController/RGBController_LianLiUniHub_AL10.cpp \ - Controllers/LianLiController/RGBController_StrimerLConnect.cpp \ - Controllers/LianLiController/StrimerLConnectController.cpp \ - Controllers/LianLiController/LianLiUniHubALController.cpp \ - Controllers/LianLiController/RGBController_LianLiUniHubAL.cpp \ - Controllers/LianLiController/LianLiUniHubSLV2Controller.cpp \ - Controllers/LianLiController/RGBController_LianLiUniHubSLV2.cpp \ - Controllers/LogitechController/LogitechControllerDetect.cpp \ - Controllers/LogitechController/LogitechProtocolCommon.cpp \ - Controllers/LogitechController/LogitechG203LController.cpp \ - Controllers/LogitechController/LogitechG213Controller.cpp \ - Controllers/LogitechController/LogitechG560Controller.cpp \ - Controllers/LogitechController/LogitechG933Controller.cpp \ - Controllers/LogitechController/LogitechG810Controller.cpp \ - Controllers/LogitechController/LogitechGProKeyboardController.cpp \ - Controllers/LogitechController/LogitechG910Controller.cpp \ - Controllers/LogitechController/LogitechG815Controller.cpp \ - Controllers/LogitechController/LogitechG915Controller.cpp \ - Controllers/LogitechController/LogitechGLightsyncController.cpp \ - Controllers/LogitechController/LogitechLightspeedController.cpp \ - Controllers/LogitechController/LogitechX56Controller.cpp \ - Controllers/LogitechController/RGBController_LogitechG203L.cpp \ - Controllers/LogitechController/RGBController_LogitechG213.cpp \ - Controllers/LogitechController/RGBController_LogitechG560.cpp \ - Controllers/LogitechController/RGBController_LogitechG933.cpp \ - Controllers/LogitechController/RGBController_LogitechG810.cpp \ - Controllers/LogitechController/RGBController_LogitechGProKeyboard.cpp \ - Controllers/LogitechController/RGBController_LogitechG910.cpp \ - Controllers/LogitechController/RGBController_LogitechG815.cpp \ - Controllers/LogitechController/RGBController_LogitechG915.cpp \ - Controllers/LogitechController/RGBController_LogitechGLightsync.cpp \ - Controllers/LogitechController/RGBController_LogitechGLightsync1zone.cpp \ - Controllers/LogitechController/RGBController_LogitechGPowerPlay.cpp \ - Controllers/LogitechController/RGBController_LogitechLightspeed.cpp \ - Controllers/LogitechController/RGBController_LogitechX56.cpp \ - Controllers/MountainKeyboardController/MountainKeyboardController.cpp \ - Controllers/MountainKeyboardController/MountainKeyboardControllerDetect.cpp \ - Controllers/MountainKeyboardController/RGBController_MountainKeyboard.cpp \ - Controllers/MSI3ZoneController/MSI3ZoneController.cpp \ - Controllers/MSI3ZoneController/MSI3ZoneControllerDetect.cpp \ - Controllers/MSI3ZoneController/RGBController_MSI3Zone.cpp \ - Controllers/MSIGPUController/MSIGPUController.cpp \ - Controllers/MSIGPUController/MSIGPUControllerDetect.cpp \ - Controllers/MSIGPUController/MSIGPUv2Controller.cpp \ - Controllers/MSIGPUController/MSIGPUv2ControllerDetect.cpp \ - Controllers/MSIGPUController/RGBController_MSIGPU.cpp \ - Controllers/MSIGPUController/RGBController_MSIGPUv2.cpp \ - Controllers/MSIMysticLightController/MSIMysticLight64Controller.cpp \ - Controllers/MSIMysticLightController/MSIMysticLight162Controller.cpp \ - Controllers/MSIMysticLightController/MSIMysticLight112Controller.cpp \ - Controllers/MSIMysticLightController/MSIMysticLight185Controller.cpp \ - Controllers/MSIMysticLightController/MSIMysticLightControllerDetect.cpp \ - Controllers/MSIMysticLightController/RGBController_MSIMysticLight64.cpp \ - Controllers/MSIMysticLightController/RGBController_MSIMysticLight112.cpp \ - Controllers/MSIMysticLightController/RGBController_MSIMysticLight162.cpp \ - Controllers/MSIMysticLightController/RGBController_MSIMysticLight185.cpp \ - Controllers/MSIOptixController/MSIOptixController.cpp \ - Controllers/MSIOptixController/MSIOptixControllerDetect.cpp \ - Controllers/MSIOptixController/RGBController_MSIOptix.cpp \ - Controllers/MSIRGBController/MSIRGBController.cpp \ - Controllers/MSIRGBController/MSIRGBControllerDetect.cpp \ - Controllers/MSIRGBController/RGBController_MSIRGB.cpp \ - Controllers/MSIVigorController/RGBController_MSIVigorGK30.cpp \ - Controllers/MSIVigorController/MSIVigorControllerDetect.cpp \ - Controllers/MSIVigorController/MSIVigorGK30Controller.cpp \ - Controllers/NanoleafController/NanoleafController.cpp \ - Controllers/NanoleafController/NanoleafControllerDetect.cpp \ - Controllers/NanoleafController/RGBController_Nanoleaf.cpp \ - Controllers/N5312AController/N5312AController.cpp \ - Controllers/N5312AController/N5312AControllerDetect.cpp \ - Controllers/N5312AController/RGBController_N5312A.cpp \ - Controllers/NollieController/NollieController.cpp \ - Controllers/NollieController/NollieControllerDetect.cpp \ - Controllers/NollieController/RGBController_Nollie.cpp \ - Controllers/NvidiaESAController/NvidiaESAController.cpp \ - Controllers/NvidiaESAController/NvidiaESAControllerDetect.cpp \ - Controllers/NvidiaESAController/RGBController_NvidiaESA.cpp \ - Controllers/NZXTHue1Controller/NZXTHue1Controller.cpp \ - Controllers/NZXTHue1Controller/NZXTHue1ControllerDetect.cpp \ - Controllers/NZXTHue1Controller/RGBController_NZXTHue1.cpp \ - Controllers/NZXTHue2Controller/NZXTHue2Controller.cpp \ - Controllers/NZXTHue2Controller/NZXTHue2ControllerDetect.cpp \ - Controllers/NZXTHue2Controller/RGBController_NZXTHue2.cpp \ - Controllers/NZXTHuePlusController/NZXTHuePlusController.cpp \ - Controllers/NZXTHuePlusController/NZXTHuePlusControllerDetect.cpp \ - Controllers/NZXTHuePlusController/RGBController_NZXTHuePlus.cpp \ - Controllers/NZXTKrakenController/NZXTKrakenController.cpp \ - Controllers/NZXTKrakenController/NZXTKrakenControllerDetect.cpp \ - Controllers/NZXTKrakenController/RGBController_NZXTKraken.cpp \ - Controllers/OKSController/OKSKeyboardController.cpp \ - Controllers/OKSController/OKSKeyboardControllerDetect.cpp \ - Controllers/OKSController/RGBController_OKSKeyboard.cpp \ - Controllers/PalitGPUController/PalitGPUController.cpp \ - Controllers/PalitGPUController/PalitGPUControllerDetect.cpp \ - Controllers/PalitGPUController/RGBController_PalitGPU.cpp \ - Controllers/PatriotViperController/PatriotViperController.cpp \ - Controllers/PatriotViperController/PatriotViperControllerDetect.cpp \ - Controllers/PatriotViperController/RGBController_PatriotViper.cpp \ - Controllers/PatriotViperSteelController/PatriotViperSteelController.cpp \ - Controllers/PatriotViperSteelController/PatriotViperSteelControllerDetect.cpp \ - Controllers/PatriotViperSteelController/RGBController_PatriotViperSteel.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/PNYGPUController/PNYGPUController.cpp \ - Controllers/PNYGPUController/PNYGPUControllerDetect.cpp \ - Controllers/PNYGPUController/RGBController_PNYGPU.cpp \ - Controllers/QMKOpenRGBController/QMKOpenRGBControllerDetect.cpp \ - Controllers/QMKOpenRGBController/QMKOpenRGBRev9Controller.cpp \ - Controllers/QMKOpenRGBController/QMKOpenRGBRevBController.cpp \ - Controllers/QMKOpenRGBController/QMKOpenRGBRevDController.cpp \ - Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRev9.cpp \ - Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevB.cpp \ - Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevD.cpp \ - Controllers/QMKOpenRGBController/RGBController_QMKOpenRGBRevE.cpp \ - Controllers/RazerController/RazerDevices.cpp \ - Controllers/RazerController/RazerController.cpp \ - Controllers/RazerController/RazerKrakenController.cpp \ - Controllers/RazerController/RazerControllerDetect.cpp \ - Controllers/RazerController/RGBController_Razer.cpp \ - Controllers/RazerController/RGBController_RazerAddressable.cpp \ - Controllers/RazerController/RGBController_RazerKraken.cpp \ - Controllers/RedragonController/RGBController_RedragonMouse.cpp \ - Controllers/RedragonController/RedragonControllerDetect.cpp \ - Controllers/RedragonController/RedragonMouseController.cpp \ - Controllers/RedSquareKeyroxController/RedSquareKeyroxController.cpp \ - Controllers/RedSquareKeyroxController/RedSquareKeyroxControllerDetect.cpp \ - Controllers/RedSquareKeyroxController/RedSquareKeyroxTKLClassicController.cpp \ - Controllers/RedSquareKeyroxController/RGBController_RedSquareKeyrox.cpp \ - Controllers/RedSquareKeyroxController/RGBController_RedSquareKeyroxTKLClassic.cpp \ - Controllers/RoccatController/RGBController_RoccatBurst.cpp \ - Controllers/RoccatController/RGBController_RoccatElo.cpp \ - Controllers/RoccatController/RGBController_RoccatHordeAimo.cpp \ - Controllers/RoccatController/RGBController_RoccatKoneAimo.cpp \ - Controllers/RoccatController/RGBController_RoccatKova.cpp \ - Controllers/RoccatController/RGBController_RoccatVulcanAimo.cpp \ - Controllers/RoccatController/RoccatBurstController.cpp \ - Controllers/RoccatController/RoccatEloController.cpp \ - Controllers/RoccatController/RoccatHordeAimoController.cpp \ - Controllers/RoccatController/RoccatKoneAimoController.cpp \ - Controllers/RoccatController/RoccatKovaController.cpp \ - Controllers/RoccatController/RoccatVulcanAimoController.cpp \ - Controllers/RoccatController/RoccatControllerDetect.cpp \ - Controllers/SapphireGPUController/SapphireNitroGlowV1Controller.cpp \ - Controllers/SapphireGPUController/SapphireNitroGlowV3Controller.cpp \ - Controllers/SapphireGPUController/SapphireGPUControllerDetect.cpp \ - Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV1.cpp \ - Controllers/SapphireGPUController/RGBController_SapphireNitroGlowV3.cpp \ - Controllers/SinowealthController/SinowealthController.cpp \ - Controllers/SinowealthController/SinowealthController1007.cpp \ - Controllers/SinowealthController/SinowealthGMOWController.cpp \ - Controllers/SinowealthController/SinowealthKeyboardController.cpp \ - Controllers/SinowealthController/SinowealthKeyboard16Controller.cpp \ - Controllers/SinowealthController/SinowealthKeyboard90Controller.cpp \ - Controllers/SinowealthController/SinowealthControllerDetect.cpp \ - Controllers/SinowealthController/RGBController_Sinowealth.cpp \ - Controllers/SinowealthController/RGBController_Sinowealth1007.cpp \ - Controllers/SinowealthController/RGBController_SinowealthGMOW.cpp \ - Controllers/SinowealthController/RGBController_SinowealthKeyboard.cpp \ - Controllers/SinowealthController/RGBController_SinowealthKeyboard16.cpp \ - Controllers/SinowealthController/RGBController_SinowealthKeyboard90.cpp \ - Controllers/SonyGamepadController/SonyDualSenseController.cpp \ - Controllers/SonyGamepadController/RGBController_SonyDualSense.cpp \ - Controllers/SonyGamepadController/SonyDS4Controller.cpp \ - Controllers/SonyGamepadController/RGBController_SonyDS4.cpp \ - Controllers/SonyGamepadController/SonyGamepadControllerDetect.cpp \ - Controllers/SRGBmodsController/SRGBmodsLEDControllerV1.cpp \ - Controllers/SRGBmodsController/SRGBmodsPicoController.cpp \ - Controllers/SRGBmodsController/SRGBmodsControllerDetect.cpp \ - Controllers/SRGBmodsController/RGBController_SRGBmodsLEDControllerV1.cpp \ - Controllers/SRGBmodsController/RGBController_SRGBmodsPico.cpp \ - Controllers/SteelSeriesController/SteelSeriesAerox3Controller.cpp \ - Controllers/SteelSeriesController/SteelSeriesAerox9Controller.cpp \ - Controllers/SteelSeriesController/SteelSeriesApexController.cpp \ - Controllers/SteelSeriesController/SteelSeriesApex3Controller.cpp \ - Controllers/SteelSeriesController/SteelSeriesApex8ZoneController.cpp \ - Controllers/SteelSeriesController/SteelSeriesApexMController.cpp \ - Controllers/SteelSeriesController/SteelSeriesApexTZoneController.cpp \ - Controllers/SteelSeriesController/SteelSeriesArctis5Controller.cpp \ - Controllers/SteelSeriesController/SteelSeriesControllerDetect.cpp \ - Controllers/SteelSeriesController/SteelSeriesMouseController.cpp \ - Controllers/SteelSeriesController/SteelSeriesOldApexController.cpp \ - Controllers/SteelSeriesController/SteelSeriesRivalController.cpp \ - Controllers/SteelSeriesController/SteelSeriesRival3Controller.cpp \ - Controllers/SteelSeriesController/SteelSeriesSenseiController.cpp \ - Controllers/SteelSeriesController/SteelSeriesSiberiaController.cpp \ - Controllers/SteelSeriesController/SteelSeriesQCKMatController.cpp \ - Controllers/SteelSeriesController/RGBController_SteelSeriesApex.cpp \ - Controllers/SteelSeriesController/RGBController_SteelSeriesApex3.cpp \ - Controllers/SteelSeriesController/RGBController_SteelSeriesArctis5.cpp \ - Controllers/SteelSeriesController/RGBController_SteelSeriesOldApex.cpp \ - Controllers/SteelSeriesController/RGBController_SteelSeriesRival.cpp \ - Controllers/SteelSeriesController/RGBController_SteelSeriesRival3.cpp \ - Controllers/SteelSeriesController/RGBController_SteelSeriesSensei.cpp \ - Controllers/SteelSeriesController/RGBController_SteelSeriesSiberia.cpp \ - Controllers/SteelSeriesController/RGBController_SteelSeriesQCKMat.cpp \ - Controllers/TecknetController/TecknetController.cpp \ - Controllers/TecknetController/TecknetControllerDetect.cpp \ - Controllers/TecknetController/RGBController_Tecknet.cpp \ - Controllers/ThermaltakePoseidonZRGBController/ThermaltakePoseidonZRGBController.cpp \ - Controllers/ThermaltakePoseidonZRGBController/ThermaltakePoseidonZRGBControllerDetect.cpp \ - Controllers/ThermaltakePoseidonZRGBController/RGBController_ThermaltakePoseidonZRGB.cpp \ - Controllers/ThermaltakeRiingController/ThermaltakeRiingController.cpp \ - Controllers/ThermaltakeRiingController/ThermaltakeRiingQuadController.cpp \ - Controllers/ThermaltakeRiingController/ThermaltakeRiingControllerDetect.cpp \ - Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiing.cpp \ - Controllers/ThingMController/ThingMControllerDetect.cpp \ - Controllers/ThingMController/BlinkController.cpp \ - Controllers/ThingMController/RGBController_BlinkController.cpp \ - Controllers/TrustController/TrustGXT114Controller.cpp \ - Controllers/TrustController/TrustGXT180Controller.cpp \ - Controllers/TrustController/TrustControllerDetect.cpp \ - Controllers/TrustController/RGBController_TrustGXT114.cpp \ - Controllers/TrustController/RGBController_TrustGXT180.cpp \ - Controllers/ViewSonicController/ViewSonicControllerDetect.cpp \ - Controllers/ViewSonicController/RGBController_XG270QG.cpp \ - Controllers/ViewSonicController/VS_XG270QG_Controller.cpp \ - Controllers/WootingKeyboardController/WootingKeyboardController.cpp \ - Controllers/WootingKeyboardController/WootingKeyboardControllerDetect.cpp \ - Controllers/WootingKeyboardController/WootingOneKeyboardController.cpp \ - Controllers/WootingKeyboardController/WootingTwoKeyboardController.cpp \ - Controllers/WootingKeyboardController/RGBController_WootingKeyboard.cpp \ - Controllers/WushiController/WushiL50USBController.cpp \ - Controllers/WushiController/WushiL50USBDetect.cpp \ - Controllers/WushiController/RGBController_WushiL50USB.cpp \ - Controllers/ThermaltakeRiingController/RGBController_ThermaltakeRiingQuad.cpp \ - Controllers/YeelightController/YeelightController.cpp \ - Controllers/YeelightController/YeelightControllerDetect.cpp \ - Controllers/YeelightController/RGBController_Yeelight.cpp \ - Controllers/ZalmanZSyncController/ZalmanZSyncController.cpp \ - Controllers/ZalmanZSyncController/ZalmanZSyncControllerDetect.cpp \ - Controllers/ZalmanZSyncController/RGBController_ZalmanZSync.cpp \ - Controllers/ZETEdgeAirProController/ZETEdgeAirProController.cpp \ - Controllers/ZETEdgeAirProController/ZETEdgeAirProControllerDetect.cpp \ - Controllers/ZETEdgeAirProController/RGBController_ZETEdgeAirPro.cpp \ - Controllers/ZETKeyboardController/ZETBladeOpticalController.cpp \ - Controllers/ZETKeyboardController/ZETKeyboardControllerDetect.cpp \ - Controllers/ZETKeyboardController/RGBController_ZETBladeOptical.cpp \ - Controllers/ZotacTuringGPUController/ZotacTuringGPUController.cpp \ - Controllers/ZotacTuringGPUController/ZotacTuringGPUControllerDetect.cpp \ - Controllers/ZotacTuringGPUController/RGBController_ZotacTuringGPU.cpp \ - Controllers/ZotacV2GPUController/ZotacV2GPUController.cpp \ - Controllers/ZotacV2GPUController/ZotacV2GPUControllerDetect.cpp \ - Controllers/ZotacV2GPUController/RGBController_ZotacV2GPU.cpp \ KeyboardLayoutManager/KeyboardLayoutManager.cpp \ RGBController/RGBController.cpp \ RGBController/RGBController_Dummy.cpp \ RGBController/RGBControllerKeyNames.cpp \ RGBController/RGBController_Network.cpp \ -contains(QMAKE_PLATFORM, freebsd) { - SOURCES -= \ - Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUController.cpp \ - Controllers/GigabyteRGBFusion2GPUController/GigabyteRGBFusion2GPUControllerDetect.cpp \ - Controllers/GigabyteRGBFusion2GPUController/RGBController_GigabyteRGBFusion2GPU.cpp \ - Controllers/HoltekController/HoltekA070Controller.cpp \ - Controllers/HoltekController/HoltekA1FAController.cpp \ - Controllers/HoltekController/HoltekControllerDetect.cpp \ - Controllers/HoltekController/RGBController_HoltekA070.cpp \ - Controllers/HoltekController/RGBController_HoltekA1FA.cpp -} - RESOURCES += \ qt/resources.qrc \ +#-----------------------------------------------------------------------------------------------# +# General configuration to decide if in-tree dependencies are used or not +#-----------------------------------------------------------------------------------------------# + +!system_libe131:SOURCES += dependencies/libe131/src/e131.c +!system_libe131:INCLUDEPATH += dependencies/libe131/src/ + +#-----------------------------------------------------------------------------------------------# +# General configuration out-of-tree dependencies if in-tree are not used for systems +# who use pkg-config i.e. Unix-like. Also includes macOS as Homebrew uses pkg-config too. +#-----------------------------------------------------------------------------------------------# + +unix { + system_libe131 { + CONFIG += link_pkgconfig + PKGCONFIG += libe131 + } +} + +#-----------------------------------------------------------------------------------------------# +# Translations # +# NB: Translation files should not be added dynamically due to the process # +# to add new translations relies on entries here in OpenRGB.pro # +#-----------------------------------------------------------------------------------------------# TRANSLATIONS += \ - qt/i18n/OpenRGB_de.ts \ - qt/i18n/OpenRGB_en.ts \ + qt/i18n/OpenRGB_be_BY.ts \ + qt/i18n/OpenRGB_de_DE.ts \ + qt/i18n/OpenRGB_el_GR.ts \ + qt/i18n/OpenRGB_en_US.ts \ qt/i18n/OpenRGB_en_AU.ts \ qt/i18n/OpenRGB_en_GB.ts \ - qt/i18n/OpenRGB_es.ts \ - qt/i18n/OpenRGB_fr.ts \ - qt/i18n/OpenRGB_hr.ts \ + qt/i18n/OpenRGB_es_ES.ts \ + qt/i18n/OpenRGB_fr_FR.ts \ + qt/i18n/OpenRGB_hr_HR.ts \ + qt/i18n/OpenRGB_it_IT.ts \ + qt/i18n/OpenRGB_ja_JP.ts \ + qt/i18n/OpenRGB_ko_KR.ts \ qt/i18n/OpenRGB_ms_MY.ts \ - qt/i18n/OpenRGB_pl.ts \ + qt/i18n/OpenRGB_nb_NO.ts \ + qt/i18n/OpenRGB_pl_PL.ts \ qt/i18n/OpenRGB_pt_BR.ts \ - qt/i18n/OpenRGB_ru.ts \ - qt/i18n/OpenRGB_zh.ts \ + qt/i18n/OpenRGB_ru_RU.ts \ + qt/i18n/OpenRGB_uk_UA.ts \ + qt/i18n/OpenRGB_zh_CN.ts \ qt/i18n/OpenRGB_zh_TW.ts \ -FORMS += \ - qt/TabLabel.ui \ - qt/OpenRGBClientInfoPage/OpenRGBClientInfoPage.ui \ - qt/OpenRGBConsolePage/OpenRGBConsolePage.ui \ - qt/OpenRGBDeviceInfoPage/OpenRGBDeviceInfoPage.ui \ - qt/OpenRGBDevicePage/OpenRGBDevicePage.ui \ - qt/OpenRGBDialog2/OpenRGBDialog2.ui \ - qt/OpenRGBDMXSettingsPage/OpenRGBDMXSettingsEntry.ui \ - qt/OpenRGBDMXSettingsPage/OpenRGBDMXSettingsPage.ui \ - qt/OpenRGBE131SettingsPage/OpenRGBE131SettingsEntry.ui \ - qt/OpenRGBE131SettingsPage/OpenRGBE131SettingsPage.ui \ - qt/OpenRGBElgatoKeyLightSettingsPage/OpenRGBElgatoKeyLightSettingsEntry.ui \ - qt/OpenRGBElgatoKeyLightSettingsPage/OpenRGBElgatoKeyLightSettingsPage.ui \ - qt/OpenRGBHardwareIDsDialog/OpenRGBHardwareIDsDialog.ui \ - qt/OpenRGBKasaSmartSettingsPage/OpenRGBKasaSmartSettingsEntry.ui \ - qt/OpenRGBKasaSmartSettingsPage/OpenRGBKasaSmartSettingsPage.ui \ - qt/OpenRGBLIFXSettingsPage/OpenRGBLIFXSettingsEntry.ui \ - qt/OpenRGBLIFXSettingsPage/OpenRGBLIFXSettingsPage.ui \ - qt/OpenRGBNanoleafSettingsPage/OpenRGBNanoleafSettingsPage.ui \ - qt/OpenRGBNanoleafSettingsPage/OpenRGBNanoleafSettingsEntry.ui \ - qt/OpenRGBPhilipsHueSettingsPage/OpenRGBPhilipsHueSettingsEntry.ui \ - qt/OpenRGBPhilipsHueSettingsPage/OpenRGBPhilipsHueSettingsPage.ui \ - qt/OpenRGBPhilipsWizSettingsPage/OpenRGBPhilipsWizSettingsEntry.ui \ - qt/OpenRGBPhilipsWizSettingsPage/OpenRGBPhilipsWizSettingsPage.ui \ - qt/OpenRGBPluginContainer/OpenRGBPluginContainer.ui \ - qt/OpenRGBPluginsPage/OpenRGBPluginsEntry.ui \ - qt/OpenRGBPluginsPage/OpenRGBPluginsPage.ui \ - qt/OpenRGBProfileSaveDialog/OpenRGBProfileSaveDialog.ui \ - qt/OpenRGBQMKORGBSettingsPage/OpenRGBQMKORGBSettingsEntry.ui \ - qt/OpenRGBQMKORGBSettingsPage/OpenRGBQMKORGBSettingsPage.ui \ - qt/OpenRGBSerialSettingsPage/OpenRGBSerialSettingsEntry.ui \ - qt/OpenRGBSerialSettingsPage/OpenRGBSerialSettingsPage.ui \ - qt/OpenRGBServerInfoPage/OpenRGBServerInfoPage.ui \ - qt/OpenRGBSettingsPage/OpenRGBSettingsPage.ui \ - qt/OpenRGBSoftwareInfoPage/OpenRGBSoftwareInfoPage.ui \ - qt/OpenRGBSupportedDevicesPage/OpenRGBSupportedDevicesPage.ui \ - qt/OpenRGBSystemInfoPage/OpenRGBSystemInfoPage.ui \ - qt/OpenRGBYeelightSettingsPage/OpenRGBYeelightSettingsEntry.ui \ - qt/OpenRGBYeelightSettingsPage/OpenRGBYeelightSettingsPage.ui \ - qt/OpenRGBZoneResizeDialog/OpenRGBZoneResizeDialog.ui \ - qt/OpenRGBZonesBulkResizer/OpenRGBZonesBulkResizer.ui \ - #-----------------------------------------------------------------------------------------------# # Windows-specific Configuration # #-----------------------------------------------------------------------------------------------# +win32:QMAKE_CXXFLAGS += /utf-8 win32:INCLUDEPATH += \ dependencies/display-library/include \ - dependencies/hidapi \ + dependencies/hidapi-win/include \ dependencies/winring0/include \ - dependencies/libusb-1.0.22/include \ - dependencies/mbedtls-2.24.0/include \ + dependencies/libusb-1.0.27/include \ + dependencies/mbedtls-3.2.1/include \ dependencies/NVFC \ - dependencies/openrazer-win32 \ wmi/ \ - Controllers/AsusTUFLaptopController \ - Controllers/NVIDIAIlluminationController \ + +win32:SOURCES += $$CONTROLLER_CPP_WINDOWS 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/hueplusplus-1.2.0/src/WinHttpHandler.cpp \ dependencies/NVFC/nvapi.cpp \ i2c_smbus/i2c_smbus_amdadl.cpp \ i2c_smbus/i2c_smbus_i801.cpp \ i2c_smbus/i2c_smbus_nct6775.cpp \ i2c_smbus/i2c_smbus_nvapi.cpp \ i2c_smbus/i2c_smbus_piix4.cpp \ + scsiapi/scsiapi_windows.c \ serial_port/find_usb_serial_port_win.cpp \ + SuspendResume/SuspendResume_Windows.cpp \ wmi/wmi.cpp \ AutoStart/AutoStart-Windows.cpp \ - Controllers/AsusTUFLaptopController/AsusTUFLaptopController.cpp \ - Controllers/AsusTUFLaptopController/AsusTUFLaptopWMIDetect.cpp \ - Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.cpp \ - Controllers/ENESMBusController/XPGSpectrixS40GDetect_Windows.cpp \ - Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Windows.cpp \ - Controllers/NVIDIAIlluminationController/nvapi_accessor.cpp \ - Controllers/NVIDIAIlluminationController/NVIDIAIlluminationV1Controller.cpp \ - Controllers/NVIDIAIlluminationController/NVIDIAIlluminationControllerDetect.cpp \ - Controllers/NVIDIAIlluminationController/RGBController_NVIDIAIllumination.cpp \ - Controllers/OpenRazerController/OpenRazerWindowsDetect.cpp \ - Controllers/OpenRazerController/RGBController_OpenRazerWindows.cpp \ + startup/main_Windows.cpp \ + +win32:HEADERS += $$CONTROLLER_H_WINDOWS win32:HEADERS += \ dependencies/display-library/include/adl_defines.h \ @@ -1676,21 +366,16 @@ win32:HEADERS += i2c_smbus/i2c_smbus_piix4.h \ wmi/wmi.h \ AutoStart/AutoStart-Windows.h \ - Controllers/AsusTUFLaptopController/AsusTUFLaptopController.h \ - Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopWMI.h \ - Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G_Windows.h \ - Controllers/NVIDIAIlluminationController/nvapi_accessor.h \ - Controllers/NVIDIAIlluminationController/NVIDIAIlluminationV1Controller.h \ - Controllers/NVIDIAIlluminationController/RGBController_NVIDIAIllumination.h \ - Controllers/OpenRazerController/RGBController_OpenRazerWindows.h \ + SuspendResume/SuspendResume_Windows.h \ win32:contains(QMAKE_TARGET.arch, x86_64) { LIBS += \ -lws2_32 \ -liphlpapi \ -L"$$PWD/dependencies/winring0/x64/" -lWinRing0x64 \ - -L"$$PWD/dependencies/libusb-1.0.22/MS64/dll" -llibusb-1.0 \ + -L"$$PWD/dependencies/libusb-1.0.27/VS2019/MS64/dll" -llibusb-1.0 \ -L"$$PWD/dependencies/hidapi-win/x64/" -lhidapi \ + -L"$$PWD/dependencies/mbedtls-3.2.1/lib/x64/" -lmbedcrypto -lmbedtls -lmbedx509 \ } win32:contains(QMAKE_TARGET.arch, x86) { @@ -1698,8 +383,9 @@ win32:contains(QMAKE_TARGET.arch, x86) { -lws2_32 \ -liphlpapi \ -L"$$PWD/dependencies/winring0/Win32/" -lWinRing0 \ - -L"$$PWD/dependencies/libusb-1.0.22/MS32/dll" -llibusb-1.0 \ + -L"$$PWD/dependencies/libusb-1.0.27/VS2019/MS32/dll" -llibusb-1.0 \ -L"$$PWD/dependencies/hidapi-win/x86/" -lhidapi \ + -L"$$PWD/dependencies/mbedtls-3.2.1/lib/x86/" -lmbedcrypto -lmbedtls -lmbedx509 \ } win32:DEFINES -= \ @@ -1737,11 +423,10 @@ win32:UI_DIR = _intermediate_$$DESTDIR/.ui #-----------------------------------------------------------------------------------------------# win32:contains(QMAKE_TARGET.arch, x86_64) { - copydata.commands = $(COPY_FILE) \"$$shell_path($$PWD/dependencies/openrazer-win32/OpenRazer64.dll )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) - copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/winring0/x64/WinRing0x64.dll )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) - copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/winring0/x64/WinRing0x64.sys )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) - copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/libusb-1.0.22/MS64/dll/libusb-1.0.dll)\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) - copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/hidapi-win/x64/hidapi.dll )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) + copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/winring0/x64/WinRing0x64.dll )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) + copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/winring0/x64/WinRing0x64.sys )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) + copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/libusb-1.0.27/VS2019/MS64/dll/libusb-1.0.dll)\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) + copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/hidapi-win/x64/hidapi.dll )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) first.depends = $(first) copydata export(first.depends) export(copydata.commands) @@ -1749,12 +434,11 @@ win32:contains(QMAKE_TARGET.arch, x86_64) { } win32:contains(QMAKE_TARGET.arch, x86) { - copydata.commands = $(COPY_FILE) \"$$shell_path($$PWD/dependencies/openrazer-win32/OpenRazer.dll )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) - copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/winring0/Win32/WinRing0.dll )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) - copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/winring0/Win32/WinRing0.sys )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) - copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/winring0/x64/WinRing0x64.sys )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) - copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/libusb-1.0.22/MS32/dll/libusb-1.0.dll)\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) - copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/hidapi-win/x86/hidapi.dll )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) + copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/winring0/Win32/WinRing0.dll )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) + copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/winring0/Win32/WinRing0.sys )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) + copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/winring0/x64/WinRing0x64.sys )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) + copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/libusb-1.0.27/VS2019/MS32/dll/libusb-1.0.dll)\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) + copydata.commands += $(COPY_FILE) \"$$shell_path($$PWD/dependencies/hidapi-win/x86/hidapi.dll )\" \"$$shell_path($$DESTDIR)\" $$escape_expand(\n\t) first.depends = $(first) copydata export(first.depends) @@ -1766,25 +450,29 @@ win32:contains(QMAKE_TARGET.arch, x86) { # Linux-specific Configuration # #-----------------------------------------------------------------------------------------------# contains(QMAKE_PLATFORM, linux) { + CONFIG += link_pkgconfig + + PKGCONFIG += \ + libusb-1.0 + TARGET = $$lower($$TARGET) - INCLUDEPATH += \ - Controllers/FaustusController \ - Controllers/LinuxLEDController \ + HEADERS += $$CONTROLLER_H_LINUX HEADERS += \ + dependencies/NVFC/nvapi.h \ i2c_smbus/i2c_smbus_linux.h \ AutoStart/AutoStart-Linux.h \ - Controllers/AsusTUFLaptopController/AsusTUFLaptopLinuxController.h \ - Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopLinux.h \ - Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G.h \ - Controllers/FaustusController/RGBController_Faustus.h \ - Controllers/LinuxLEDController/LinuxLEDController.h \ - Controllers/LinuxLEDController/RGBController_LinuxLED.h \ - Controllers/OpenRazerController/RGBController_OpenRazer.h \ + SPDAccessor/EE1004Accessor_Linux.h \ + SPDAccessor/SPD5118Accessor_Linux.h \ + SuspendResume/SuspendResume_Linux_FreeBSD.h \ + + INCLUDEPATH += \ + dependencies/NVFC \ + /usr/include/mbedtls/ \ LIBS += \ - -lusb-1.0 \ + -L/usr/lib/mbedtls/ \ -lmbedx509 \ -lmbedtls \ -lmbedcrypto \ @@ -1795,14 +483,16 @@ contains(QMAKE_PLATFORM, linux) { LIBS += -lstdc++fs } - QMAKE_CXXFLAGS += -Wno-implicit-fallthrough + QT += dbus + + QMAKE_CXXFLAGS += -Wno-implicit-fallthrough -Wno-psabi #-------------------------------------------------------------------------------------------# # Determine which hidapi to use based on availability # # Prefer hidraw backend, then libusb # #-------------------------------------------------------------------------------------------# packagesExist(hidapi-hidraw) { - LIBS += -lhidapi-hidraw + PKGCONFIG += hidapi-hidraw #---------------------------------------------------------------------------------------# # hidapi-hidraw >= 0.10.1 supports USAGE/USAGE_PAGE # @@ -1814,28 +504,25 @@ contains(QMAKE_PLATFORM, linux) { } } else { packagesExist(hidapi-libusb) { - LIBS += -lhidapi-libusb + PKGCONFIG += hidapi-libusb } else { - LIBS += -lhidapi + PKGCONFIG += hidapi } } + SOURCES += $$CONTROLLER_CPP_LINUX + SOURCES += \ - dependencies/hueplusplus-1.0.0/src/LinHttpHandler.cpp \ + dependencies/hueplusplus-1.2.0/src/LinHttpHandler.cpp \ + dependencies/NVFC/nvapi.cpp \ i2c_smbus/i2c_smbus_linux.cpp \ + scsiapi/scsiapi_linux.c \ serial_port/find_usb_serial_port_linux.cpp \ AutoStart/AutoStart-Linux.cpp \ - Controllers/AsusTUFLaptopController/AsusTUFLaptopLinuxController.cpp \ - Controllers/AsusTUFLaptopController/AsusTUFLaptopLinuxDetect.cpp \ - Controllers/AsusTUFLaptopController/RGBController_AsusTUFLaptopLinux.cpp \ - Controllers/ENESMBusController/XPGSpectrixS40GDetect.cpp \ - Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G.cpp \ - Controllers/FaustusController/RGBController_Faustus.cpp \ - Controllers/LinuxLEDController/LinuxLEDController.cpp \ - Controllers/LinuxLEDController/LinuxLEDControllerDetect.cpp \ - Controllers/LinuxLEDController/RGBController_LinuxLED.cpp \ - Controllers/OpenRazerController/OpenRazerDetect.cpp \ - Controllers/OpenRazerController/RGBController_OpenRazer.cpp \ + SPDAccessor/EE1004Accessor_Linux.cpp \ + SPDAccessor/SPD5118Accessor_Linux.cpp \ + SuspendResume/SuspendResume_Linux_FreeBSD.cpp \ + startup/main_Linux_MacOS.cpp \ #-------------------------------------------------------------------------------------------# # Set up install paths # @@ -1845,6 +532,12 @@ contains(QMAKE_PLATFORM, linux) { PREFIX = /usr } + !defined(OPENRGB_SYSTEM_PLUGIN_DIRECTORY, var):OPENRGB_SYSTEM_PLUGIN_DIRECTORY = \ + "$$PREFIX/lib/openrgb/plugins" \ + + DEFINES += \ + OPENRGB_SYSTEM_PLUGIN_DIRECTORY=\\"\"\"$$OPENRGB_SYSTEM_PLUGIN_DIRECTORY\\"\"\" \ + #-------------------------------------------------------------------------------------------# # Custom target for dynamically created udev_rules # # Ordinarily you would add the 'udev_rules' target to both QMAKE_EXTRA_TARGETS to add a # @@ -1863,10 +556,10 @@ contains(QMAKE_PLATFORM, linux) { udev_rules.files = $$udev_rules.target } else { message($$udev_rules.target " - UDEV rules file missing. Adding script to build") - #-------------------------------------------------------------------------------------------# - # This is a compiler config flag to save the preproccessed .ii & .s # - # files so as to automatically process the UDEV rules and the Supported Devices # - #-------------------------------------------------------------------------------------------# + #-----------------------------------------------------------------------------------# + # This is a compiler config flag to save the preproccessed .ii & .s # + # files so as to automatically process the UDEV rules and the Supported Devices # + #-----------------------------------------------------------------------------------# QMAKE_CXXFLAGS+=-save-temps QMAKE_CXXFLAGS-=-pipe udev_rules.extra = $$PWD/scripts/build-udev-rules.sh $$PWD $$GIT_COMMIT_ID @@ -1875,38 +568,44 @@ contains(QMAKE_PLATFORM, linux) { } #-------------------------------------------------------------------------------------------# - # Add static files to installation # + # Add static files to installation # #-------------------------------------------------------------------------------------------# target.path=$$PREFIX/bin/ desktop.path=$$PREFIX/share/applications/ - desktop.files+=qt/OpenRGB.desktop + desktop.files+=qt/org.openrgb.OpenRGB.desktop icon.path=$$PREFIX/share/icons/hicolor/128x128/apps/ - icon.files+=qt/OpenRGB.png + icon.files+=qt/org.openrgb.OpenRGB.png metainfo.path=$$PREFIX/share/metainfo/ metainfo.files+=qt/org.openrgb.OpenRGB.metainfo.xml - INSTALLS += target desktop icon metainfo udev_rules + systemd_service.path=/etc/systemd/system + systemd_service.files+=qt/openrgb.service + INSTALLS += target desktop icon metainfo udev_rules systemd_service } #-----------------------------------------------------------------------------------------------# # FreeBSD-specific Configuration # #-----------------------------------------------------------------------------------------------# contains(QMAKE_PLATFORM, freebsd) { + CONFIG += link_pkgconfig + + PKGCONFIG += \ + libusb-1.0 + TARGET = $$lower($$TARGET) - INCLUDEPATH += \ - Controllers/FaustusController \ - Controllers/LinuxLEDController \ + HEADERS += $$CONTROLLER_H_FREEBSD HEADERS += \ AutoStart/AutoStart-FreeBSD.h \ - Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G.h \ - Controllers/FaustusController/RGBController_Faustus.h \ - Controllers/LinuxLEDController/LinuxLEDController.h \ - Controllers/LinuxLEDController/RGBController_LinuxLED.h \ - Controllers/OpenRazerController/RGBController_OpenRazer.h \ + SuspendResume/SuspendResume_Linux_FreeBSD.h \ + + HEADERS -= \ + Controllers/SeagateController/RGBController_Seagate.h \ + Controllers/SeagateController/SeagateController.h \ + Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_ROGArion.h \ + $$CONTROLLER_H_WINDOWS \ LIBS += \ - -lusb \ -lmbedx509 \ -lmbedtls \ -lmbedcrypto \ @@ -1916,41 +615,44 @@ contains(QMAKE_PLATFORM, freebsd) { LIBS += -lstdc++fs } + QT += dbus + #-------------------------------------------------------------------------------------------# # Determine which hidapi to use based on availability # # Prefer hidraw backend, then libusb # #-------------------------------------------------------------------------------------------# packagesExist(hidapi-hidraw) { - LIBS += -lhidapi-hidraw + PKGCONFIG += hidapi-hidraw #---------------------------------------------------------------------------------------# # hidapi-hidraw >= 0.10.1 supports USAGE/USAGE_PAGE # # Define USE_HID_USAGE if hidapi-hidraw supports it # #---------------------------------------------------------------------------------------# - HIDAPI_HIDRAW_VERSION = $$system($$PKG_CONFIG --modversion hidapi-hidraw) - if(versionAtLeast(HIDAPI_HIDRAW_VERSION, "0.10.1")) { + packagesExist(hidapi-hidraw>=0.10.1) { DEFINES += USE_HID_USAGE } } else { packagesExist(hidapi-libusb) { - LIBS += -lhidapi-libusb + PKGCONFIG += hidapi-libusb } else { - LIBS += -lhidapi + PKGCONFIG += hidapi } } + SOURCES += $$CONTROLLER_CPP_FREEBSD + SOURCES += \ - dependencies/hueplusplus-1.0.0/src/LinHttpHandler.cpp \ + dependencies/hueplusplus-1.2.0/src/LinHttpHandler.cpp \ serial_port/find_usb_serial_port_linux.cpp \ AutoStart/AutoStart-FreeBSD.cpp \ - Controllers/ENESMBusController/XPGSpectrixS40GDetect.cpp \ - Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_SpectrixS40G.cpp \ - Controllers/FaustusController/RGBController_Faustus.cpp \ - Controllers/LinuxLEDController/LinuxLEDController.cpp \ - Controllers/LinuxLEDController/LinuxLEDControllerDetect.cpp \ - Controllers/LinuxLEDController/RGBController_LinuxLED.cpp \ - Controllers/OpenRazerController/OpenRazerDetect.cpp \ - Controllers/OpenRazerController/RGBController_OpenRazer.cpp \ + SuspendResume/SuspendResume_Linux_FreeBSD.cpp \ + + SOURCES -= \ + Controllers/SeagateController/RGBController_Seagate.cpp \ + Controllers/SeagateController/SeagateController.cpp \ + Controllers/SeagateController/SeagateControllerDetect.cpp \ + Controllers/ENESMBusController/ROGArionDetect.cpp \ + Controllers/ENESMBusController/ENESMBusInterface/ENESMBusInterface_ROGArion.cpp \ #-------------------------------------------------------------------------------------------# # Set up install paths # @@ -1962,9 +664,9 @@ contains(QMAKE_PLATFORM, freebsd) { target.path=$$PREFIX/bin/ desktop.path=$$PREFIX/share/applications/ - desktop.files+=qt/OpenRGB.desktop + desktop.files+=qt/org.openrgb.OpenRGB.desktop icon.path=$$PREFIX/share/icons/hicolor/128x128/apps/ - icon.files+=qt/OpenRGB.png + icon.files+=qt/org.openrgb.OpenRGB.png metainfo.path=$$PREFIX/share/metainfo/ metainfo.files+=qt/org.openrgb.OpenRGB.metainfo.xml rules.path=$$PREFIX/lib/udev/rules.d/ @@ -1984,12 +686,16 @@ unix:!macx:CONFIG(asan) { #-----------------------------------------------------------------------------------------------# QMAKE_MACOSX_DEPLOYMENT_TARGET = 10.15 -macx:ICON = qt/OpenRGB.icns - -#-------------------------------------------------------------------------------------------# -# Common MacOS definitions # -#-------------------------------------------------------------------------------------------# +#-----------------------------------------------------------------------------------------------# +# Common MacOS definitions # +#-----------------------------------------------------------------------------------------------# macx { + CONFIG += link_pkgconfig + + PKGCONFIG += \ + libusb-1.0 \ + hidapi + DEFINES += \ USE_HID_USAGE \ @@ -1999,42 +705,57 @@ macx { HEADERS += \ AutoStart/AutoStart-MacOS.h \ qt/macutils.h \ + SuspendResume/SuspendResume_MacOS.h \ + + HEADERS += $$CONTROLLER_H_MACOS SOURCES += \ - dependencies/hueplusplus-1.0.0/src/LinHttpHandler.cpp \ - serial_port/find_usb_serial_port_linux.cpp \ + dependencies/hueplusplus-1.2.0/src/LinHttpHandler.cpp \ + serial_port/find_usb_serial_port_macos.cpp \ AutoStart/AutoStart-MacOS.cpp \ qt/macutils.mm \ + SuspendResume/SuspendResume_MacOS.cpp \ + startup/main_Linux_MacOS.cpp \ - # Use mbedtls v2 instead of latest - MBEDTLS_PREFIX = $$system(brew --prefix mbedtls@2) + SOURCES += $$CONTROLLER_CPP_MACOS + + # Use mbedtls + MBEDTLS_PREFIX = $$system(brew --prefix mbedtls) INCLUDEPATH += \ $$MBEDTLS_PREFIX/include \ LIBS += \ - -lusb-1.0 \ - -lhidapi \ -lmbedx509 \ -lmbedcrypto \ -lmbedtls \ - -L$$MBEDTLS_PREFIX/lib \ + -L$$MBEDTLS_PREFIX/lib + + ICON = qt/OpenRGB.icns + + info_plist.input = mac/Info.plist.in + info_plist.output = $$OUT_PWD/Info.plist + QMAKE_SUBSTITUTES += info_plist + QMAKE_INFO_PLIST = $$OUT_PWD/Info.plist } -#-------------------------------------------------------------------------------------------# -# Apple Silicon (arm64) Homebrew installs at /opt/homebrew # -#-------------------------------------------------------------------------------------------# +#-----------------------------------------------------------------------------------------------# +# Apple Silicon (arm64) Homebrew installs at /opt/homebrew # +#-----------------------------------------------------------------------------------------------# macx:contains(QMAKE_HOST.arch, arm64) { INCLUDEPATH += \ /opt/homebrew/include \ + SOURCES += \ + scsiapi/scsiapi_macos.c \ + LIBS += \ -L/opt/homebrew/lib \ } -#-------------------------------------------------------------------------------------------# -# Intel (x86_64) Homebrew installs at /usr/local/lib # -#-------------------------------------------------------------------------------------------# +#-----------------------------------------------------------------------------------------------# +# Intel (x86_64) Homebrew installs at /usr/local/lib # +#-----------------------------------------------------------------------------------------------# macx:contains(QMAKE_HOST.arch, x86_64) { INCLUDEPATH += \ dependencies/macUSPCIO \ @@ -2043,10 +764,15 @@ macx:contains(QMAKE_HOST.arch, x86_64) { SOURCES += \ i2c_smbus/i2c_smbus_i801.cpp \ + i2c_smbus/i2c_smbus_nct6775.cpp \ + i2c_smbus/i2c_smbus_piix4.cpp \ + scsiapi/scsiapi_macos.c \ HEADERS += \ dependencies/macUSPCIO/macUSPCIOAccess.h \ i2c_smbus/i2c_smbus_i801.h \ + i2c_smbus/i2c_smbus_nct6775.h \ + i2c_smbus/i2c_smbus_piix4.h \ LIBS += \ -L/usr/local/lib \ diff --git a/OpenRGBPluginInterface.h b/OpenRGBPluginInterface.h index 0b8dab0a..13d72d46 100644 --- a/OpenRGBPluginInterface.h +++ b/OpenRGBPluginInterface.h @@ -1,19 +1,21 @@ -/*-----------------------------------------*\ -| OpenRGBPluginInterface.h | -| | -| OpenRGB Plugin Interface Class | -| | -| herosilas12 (CoffeeIsLife) 12/11/2020 | -| Adam Honse (CalcProgrammer1) 1/5/2021 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| OpenRGBPluginInterface.h | +| | +| OpenRGB SDK network protocol | +| | +| herosilas12 (CoffeeIsLife) 11 Dec 2020 | +| Adam Honse (CalcProgrammer1) 05 Jan 2021 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include "ResourceManager.h" - #include #include #include +#include "ResourceManagerInterface.h" #define OpenRGBPluginInterface_IID "com.OpenRGBPluginInterface" @@ -23,8 +25,9 @@ | 1: OpenRGB 0.61 First versioned API, introduced with plugin settings changes | | 2: OpenRGB 0.7 First released versioned API, callback unregister functions in ResourceManager | | 3: OpenRGB 0.9 Use filesystem::path for paths, Added segments | +| 4: OpenRGB 1.0 Resizable effects-only zones, zone flags | \*-----------------------------------------------------------------------------------------------------*/ -#define OPENRGB_PLUGIN_API_VERSION 3 +#define OPENRGB_PLUGIN_API_VERSION 4 /*-----------------------------------------------------------------------------------------------------*\ | Plugin Tab Location Values | @@ -74,7 +77,7 @@ public: /*-------------------------------------------------------------------------------------------------*\ | Plugin Functionality | \*-------------------------------------------------------------------------------------------------*/ - virtual void Load(bool dark_theme, ResourceManager* resource_manager_ptr) = 0; + virtual void Load(ResourceManagerInterface* resource_manager_ptr) = 0; virtual QWidget* GetWidget() = 0; virtual QMenu* GetTrayMenu() = 0; virtual void Unload() = 0; diff --git a/PluginManager.cpp b/PluginManager.cpp index 74c331fa..157b6cd5 100644 --- a/PluginManager.cpp +++ b/PluginManager.cpp @@ -1,7 +1,22 @@ +/*---------------------------------------------------------*\ +| PluginManager.cpp | +| | +| OpenRGB plugin manager | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include "LogManager.h" #include "filesystem.h" #include "PluginManager.h" #include "OpenRGBThemeManager.h" +#include "SettingsManager.h" +#include "ResourceManager.h" + +#ifdef _WIN32 +#include +#endif PluginManager::PluginManager() { @@ -36,26 +51,54 @@ void PluginManager::RegisterRemovePluginCallback(RemovePluginCallback new_callba void PluginManager::ScanAndLoadPlugins() { /*---------------------------------------------------------*\ - | Get the plugins directory | + | Get the user plugins directory | | | - | The plugins directory is a directory named "plugins" in | - | the configuration directory | + | The user plugins directory is a directory named "plugins" | + | in the configuration directory | \*---------------------------------------------------------*/ filesystem::path plugins_dir = ResourceManager::get()->GetConfigurationDirectory() / plugins_path; - ScanAndLoadPluginsFrom(plugins_dir); + ScanAndLoadPluginsFrom(plugins_dir, false); -#ifdef OPENRGB_EXTRA_PLUGIN_DIRECTORY - /*-----------------------------------------------------------------*\ - | An additional plugin directory can be set during build time, e.g. | - | by the Linux distro to load plugins installed via package manager | - \*-----------------------------------------------------------------*/ - ScanAndLoadPluginsFrom(OPENRGB_EXTRA_PLUGIN_DIRECTORY); +#ifdef OPENRGB_SYSTEM_PLUGIN_DIRECTORY + /*---------------------------------------------------------*\ + | Get the system plugins directory | + | | + | The system plugin directory can be set during build time, | + | e.g. by the package maintainer to load plugins installed | + | via package manager | + \*---------------------------------------------------------*/ + ScanAndLoadPluginsFrom(OPENRGB_SYSTEM_PLUGIN_DIRECTORY, true); +#endif + +#ifdef _WIN32 + /*---------------------------------------------------------*\ + | Get the exe folder plugins directory (Windows) | + | | + | On Windows, system plugins are located in a folder called | + | "plugins" inside the folder where the OpenRGB.exe file is | + | installed. Typically, C:\Program Files\OpenRGB but other | + | install paths are allowed. | + \*---------------------------------------------------------*/ + char path[MAX_PATH]; + GetModuleFileName(NULL, path, MAX_PATH); + + filesystem::path exe_dir(path); + exe_dir = exe_dir.remove_filename() / plugins_path; + + ScanAndLoadPluginsFrom(exe_dir, true); #endif } -void PluginManager::ScanAndLoadPluginsFrom(const filesystem::path & plugins_dir) +void PluginManager::ScanAndLoadPluginsFrom(const filesystem::path & plugins_dir, bool is_system) { - LOG_TRACE("[PluginManager] Scanning plugin directory: %s", plugins_dir.generic_u8string().c_str()); + if(is_system) + { + LOG_TRACE("[PluginManager] Scanning system plugin directory: %s", plugins_dir.generic_u8string().c_str()); + } + else + { + LOG_TRACE("[PluginManager] Scanning user plugin directory: %s", plugins_dir.generic_u8string().c_str()); + } if(!filesystem::is_directory(plugins_dir)) { @@ -75,16 +118,48 @@ void PluginManager::ScanAndLoadPluginsFrom(const filesystem::path & plugins_dir) filesystem::path plugin_path = entry.path(); LOG_TRACE("[PluginManager] Found plugin file %s", plugin_path.filename().generic_u8string().c_str()); - AddPlugin(plugin_path); + AddPlugin(plugin_path, is_system); } } -void PluginManager::AddPlugin(const filesystem::path& path) +void PluginManager::AddPlugin(const filesystem::path& path, bool is_system) { OpenRGBPluginInterface* plugin = nullptr; unsigned int plugin_idx; + /*---------------------------------------------------------------------*\ + | Open plugin settings | + \*---------------------------------------------------------------------*/ + json plugin_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Plugins"); + + /*---------------------------------------------------------------------*\ + | Check if this plugin is on the remove list | + \*---------------------------------------------------------------------*/ + if(plugin_settings.contains("plugins_remove")) + { + for(unsigned int plugin_remove_idx = 0; plugin_remove_idx < plugin_settings["plugins_remove"].size(); plugin_remove_idx++) + { + LOG_WARNING("[PluginManager] Checking remove %d, %s", plugin_remove_idx, to_string(plugin_settings["plugins_remove"][plugin_remove_idx]).c_str()); + + if(plugin_settings["plugins_remove"][plugin_remove_idx] == path.generic_u8string()) + { + /*---------------------------------------------------------*\ + | Delete the plugin file | + \*---------------------------------------------------------*/ + filesystem::remove(path); + } + + /*-----------------------------------------------------------------*\ + | Erase the plugin from the remove list | + \*-----------------------------------------------------------------*/ + plugin_settings["plugins_remove"].erase(plugin_remove_idx); + + ResourceManager::get()->GetSettingsManager()->SetSettings("Plugins", plugin_settings); + ResourceManager::get()->GetSettingsManager()->SaveSettings(); + } + } + /*---------------------------------------------------------------------*\ | Search active plugins to see if this path already exists | \*---------------------------------------------------------------------*/ @@ -108,6 +183,11 @@ void PluginManager::AddPlugin(const filesystem::path& path) QPluginLoader* loader = new QPluginLoader(QString::fromStdString(path_string)); QObject* instance = loader->instance(); + if(!loader->isLoaded()) + { + LOG_WARNING("[PluginManager] Plugin %s cannot be loaded: %s", path.c_str(), loader->errorString().toStdString().c_str()); + } + /*-----------------------------------------------------------------*\ | Check that the plugin is valid, then check the API version | \*-----------------------------------------------------------------*/ @@ -135,30 +215,25 @@ void PluginManager::AddPlugin(const filesystem::path& path) bool found = false; unsigned int plugin_ct = 0; - /*-----------------------------------------------------*\ - | Open plugin list and check if plugin is in the list | - \*-----------------------------------------------------*/ - json plugin_settings = ResourceManager::get()->GetSettingsManager()->GetSettings("Plugins"); - if(plugin_settings.contains("plugins")) { - plugin_ct = plugin_settings["plugins"].size(); + plugin_ct = (unsigned int)plugin_settings["plugins"].size(); - for(unsigned int plugin_idx = 0; plugin_idx < plugin_settings["plugins"].size(); plugin_idx++) + for(unsigned int plugin_settings_idx = 0; plugin_settings_idx < plugin_settings["plugins"].size(); plugin_settings_idx++) { - if(plugin_settings["plugins"][plugin_idx].contains("name")) + if(plugin_settings["plugins"][plugin_settings_idx].contains("name")) { - name = plugin_settings["plugins"][plugin_idx]["name"]; + name = plugin_settings["plugins"][plugin_settings_idx]["name"]; } - if(plugin_settings["plugins"][plugin_idx].contains("description")) + if(plugin_settings["plugins"][plugin_settings_idx].contains("description")) { - description = plugin_settings["plugins"][plugin_idx]["description"]; + description = plugin_settings["plugins"][plugin_settings_idx]["description"]; } - if(plugin_settings["plugins"][plugin_idx].contains("enabled")) + if(plugin_settings["plugins"][plugin_settings_idx].contains("enabled")) { - enabled = plugin_settings["plugins"][plugin_idx]["enabled"]; + enabled = plugin_settings["plugins"][plugin_settings_idx]["enabled"]; } if((info.Name == name) @@ -184,36 +259,81 @@ void PluginManager::AddPlugin(const filesystem::path& path) ResourceManager::get()->GetSettingsManager()->SaveSettings(); } - LOG_VERBOSE("Loaded plugin %s", info.Name.c_str()); + LOG_VERBOSE("[PluginManager] Loaded plugin %s", info.Name.c_str()); /*-----------------------------------------------------*\ | Add the plugin to the PluginManager active plugins | \*-----------------------------------------------------*/ OpenRGBPluginEntry entry; - entry.info = info; - entry.plugin = plugin; - entry.loader = loader; - entry.loaded = false; - entry.path = path_string; - entry.enabled = enabled; - entry.widget = nullptr; + entry.info = info; + entry.plugin = plugin; + entry.loader = loader; + entry.path = path_string; + entry.enabled = enabled; + entry.widget = nullptr; + entry.incompatible = false; + entry.api_version = plugin->GetPluginAPIVersion(); + entry.is_system = is_system; + + loader->unload(); + + ActivePlugins.push_back(entry); + + if(entry.enabled) + { + LoadPlugin(&ActivePlugins.back()); + } + } + else + { + /*-----------------------------------------------------*\ + | Fill in a plugin information object with text showing | + | the plugin is incompatible | + \*-----------------------------------------------------*/ + OpenRGBPluginInfo info; + + info.Name = "Incompatible Plugin"; + info.Description = "This plugin is not compatible with this version of OpenRGB."; + + /*-----------------------------------------------------*\ + | Add the plugin to the PluginManager active plugins | + | but mark it as incompatible | + \*-----------------------------------------------------*/ + OpenRGBPluginEntry entry; + + entry.info = info; + entry.plugin = plugin; + entry.loader = loader; + entry.path = path_string; + entry.enabled = false; + entry.widget = nullptr; + entry.incompatible = true; + entry.api_version = plugin->GetPluginAPIVersion(); + entry.is_system = is_system; loader->unload(); PluginManager::ActivePlugins.push_back(entry); - if(entry.enabled) + bool unloaded = loader->unload(); + + LOG_WARNING("[PluginManager] Plugin %s has an incompatible API version", path.c_str()); + + if(!unloaded) { - LoadPlugin(path); + LOG_WARNING("[PluginManager] Plugin %s cannot be unloaded", path.c_str()); } } - else - { - loader->unload(); - LOG_WARNING("[PluginManager] Plugin %s has an incompatible API version", path.c_str()); - } } + else + { + LOG_WARNING("[PluginManager] Plugin %s cannot be casted to OpenRGBPluginInterface", path.c_str()); + } + } + else + { + LOG_WARNING("[PluginManager] Plugin %s cannot be instantiated.", path.c_str()); } } } @@ -247,10 +367,10 @@ void PluginManager::RemovePlugin(const filesystem::path& path) /*---------------------------------------------------------------------*\ | If the selected plugin is in the list and loaded, unload it | \*---------------------------------------------------------------------*/ - if(ActivePlugins[plugin_idx].loaded) + if(ActivePlugins[plugin_idx].loader->isLoaded()) { LOG_TRACE("[PluginManager] Plugin %s is active, unloading", path.c_str()); - UnloadPlugin(path); + UnloadPlugin(&ActivePlugins[plugin_idx]); } /*---------------------------------------------------------------------*\ @@ -259,7 +379,7 @@ void PluginManager::RemovePlugin(const filesystem::path& path) ActivePlugins.erase(ActivePlugins.begin() + plugin_idx); } -void PluginManager::LoadPlugin(const filesystem::path& path) +void PluginManager::EnablePlugin(const filesystem::path& path) { unsigned int plugin_idx; @@ -282,17 +402,28 @@ void PluginManager::LoadPlugin(const filesystem::path& path) return; } + ActivePlugins[plugin_idx].enabled = true; + LoadPlugin(&ActivePlugins[plugin_idx]); +} + +void PluginManager::LoadPlugin(OpenRGBPluginEntry* plugin_entry) +{ + /*---------------------------------------------------------------------*\ + | If the plugin is in the list but is incompatible, return | + \*---------------------------------------------------------------------*/ + if(plugin_entry->incompatible) + { + return; + } + /*---------------------------------------------------------------------*\ | If the selected plugin is in the list but not loaded, load it | \*---------------------------------------------------------------------*/ - if(!ActivePlugins[plugin_idx].loaded) + if(!plugin_entry->loader->isLoaded()) { - ActivePlugins[plugin_idx].loader->load(); - ActivePlugins[plugin_idx].loaded = true; + plugin_entry->loader->load(); - QObject* instance = ActivePlugins[plugin_idx].loader->instance(); - - bool dark_theme = OpenRGBThemeManager::IsDarkTheme(); + QObject* instance = plugin_entry->loader->instance(); if(instance) { @@ -302,16 +433,16 @@ void PluginManager::LoadPlugin(const filesystem::path& path) { if(plugin->GetPluginAPIVersion() == OPENRGB_PLUGIN_API_VERSION) { - ActivePlugins[plugin_idx].plugin = plugin; + plugin_entry->plugin = plugin; - plugin->Load(dark_theme, ResourceManager::get()); + plugin->Load(ResourceManager::get()); /*-------------------------------------------------*\ | Call the Add Plugin callback | \*-------------------------------------------------*/ if(AddPluginCallbackArg != nullptr) { - AddPluginCallbackVal(AddPluginCallbackArg, &ActivePlugins[plugin_idx]); + AddPluginCallbackVal(AddPluginCallbackArg, plugin_entry); } } } @@ -319,7 +450,7 @@ void PluginManager::LoadPlugin(const filesystem::path& path) } } -void PluginManager::UnloadPlugin(const filesystem::path& path) +void PluginManager::DisablePlugin(const filesystem::path& path) { unsigned int plugin_idx; @@ -342,33 +473,62 @@ void PluginManager::UnloadPlugin(const filesystem::path& path) return; } + ActivePlugins[plugin_idx].enabled = false; + UnloadPlugin(&ActivePlugins[plugin_idx]); +} + +void PluginManager::UnloadPlugin(OpenRGBPluginEntry* plugin_entry) +{ /*---------------------------------------------------------------------*\ | If the selected plugin is in the list and loaded, unload it | \*---------------------------------------------------------------------*/ - if(ActivePlugins[plugin_idx].loaded) + if(plugin_entry->loader->isLoaded()) { /*-------------------------------------------------*\ | Call plugin's Unload function before GUI removal | \*-------------------------------------------------*/ - ActivePlugins[plugin_idx].plugin->Unload(); + plugin_entry->plugin->Unload(); /*-------------------------------------------------*\ | Call the Remove Plugin callback | \*-------------------------------------------------*/ if(RemovePluginCallbackVal != nullptr) { - RemovePluginCallbackVal(RemovePluginCallbackArg, &ActivePlugins[plugin_idx]); + RemovePluginCallbackVal(RemovePluginCallbackArg, plugin_entry); } - ActivePlugins[plugin_idx].loader->unload(); - ActivePlugins[plugin_idx].loaded = false; + bool unloaded = plugin_entry->loader->unload(); + + if(!unloaded) + { + LOG_WARNING("[PluginManager] Plugin %s cannot be unloaded", plugin_entry->path.c_str()); + } + else + { + LOG_TRACE("[PluginManager] Plugin %s successfully unloaded", plugin_entry->path.c_str()); + } + } + else + { + LOG_TRACE("[PluginManager] Plugin %s was already unloaded", plugin_entry->path.c_str()); + } +} + +void PluginManager::LoadPlugins() +{ + for(OpenRGBPluginEntry& plugin_entry: ActivePlugins) + { + if(plugin_entry.enabled) + { + LoadPlugin(&plugin_entry); + } } } void PluginManager::UnloadPlugins() { - for(const OpenRGBPluginEntry& plugin_entry: ActivePlugins) + for(OpenRGBPluginEntry& plugin_entry: ActivePlugins) { - plugin_entry.plugin->Unload(); + UnloadPlugin(&plugin_entry); } } diff --git a/PluginManager.h b/PluginManager.h index 6c12990c..2451bb66 100644 --- a/PluginManager.h +++ b/PluginManager.h @@ -1,27 +1,35 @@ +/*---------------------------------------------------------*\ +| PluginManager.h | +| | +| OpenRGB plugin manager | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once -#include "OpenRGBPluginInterface.h" -#include "ResourceManager.h" - +#include +#include #include #include #include #include +#include "OpenRGBPluginInterface.h" -#include -#include - -typedef struct +struct OpenRGBPluginEntry { OpenRGBPluginInfo info; OpenRGBPluginInterface* plugin; QPluginLoader* loader; - bool loaded; QWidget* widget; QMenu* traymenu; std::string path; bool enabled; -} OpenRGBPluginEntry; + bool incompatible; + bool is_system; + int api_version; +}; typedef void (*AddPluginCallback)(void *, OpenRGBPluginEntry* plugin); typedef void (*RemovePluginCallback)(void *, OpenRGBPluginEntry* plugin); @@ -36,18 +44,22 @@ public: void ScanAndLoadPlugins(); - void AddPlugin(const filesystem::path& path); + void AddPlugin(const filesystem::path& path, bool is_system); void RemovePlugin(const filesystem::path& path); - void LoadPlugin(const filesystem::path& path); - void UnloadPlugin(const filesystem::path& path); + void EnablePlugin(const filesystem::path& path); + void DisablePlugin(const filesystem::path& path); + void LoadPlugins(); void UnloadPlugins(); std::vector ActivePlugins; private: - void ScanAndLoadPluginsFrom(const filesystem::path & plugins_dir); + void LoadPlugin(OpenRGBPluginEntry* plugin_entry); + void UnloadPlugin(OpenRGBPluginEntry* plugin_entry); + + void ScanAndLoadPluginsFrom(const filesystem::path & plugins_dir, bool is_system); AddPluginCallback AddPluginCallbackVal; void * AddPluginCallbackArg; diff --git a/ProfileManager.cpp b/ProfileManager.cpp index f866373c..8d80f141 100644 --- a/ProfileManager.cpp +++ b/ProfileManager.cpp @@ -1,12 +1,22 @@ +/*---------------------------------------------------------*\ +| ProfileManager.cpp | +| | +| OpenRGB profile manager | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include #include "ProfileManager.h" #include "ResourceManager.h" #include "RGBController_Dummy.h" #include "LogManager.h" +#include "NetworkProtocol.h" #include "filesystem.h" -#include -#include -#include - +#include "StringUtils.h" #define OPENRGB_PROFILE_HEADER "OPENRGB_PROFILE" #define OPENRGB_PROFILE_VERSION OPENRGB_SDK_PROTOCOL_VERSION @@ -24,6 +34,8 @@ ProfileManager::~ProfileManager() bool ProfileManager::SaveProfile(std::string profile_name, bool sizes) { + profile_name = StringUtils::remove_null_terminating_chars(profile_name); + /*---------------------------------------------------------*\ | Get the list of controllers from the resource manager | \*---------------------------------------------------------*/ @@ -71,6 +83,16 @@ bool ProfileManager::SaveProfile(std::string profile_name, bool sizes) \*---------------------------------------------------------*/ for(std::size_t controller_index = 0; controller_index < controllers.size(); controller_index++) { + /*-----------------------------------------------------*\ + | Ignore remote and virtual controllers when saving | + | sizes | + \*-----------------------------------------------------*/ + if(sizes && (controllers[controller_index]->flags & CONTROLLER_FLAG_REMOTE + || controllers[controller_index]->flags & CONTROLLER_FLAG_VIRTUAL)) + { + break; + } + unsigned char *controller_data = controllers[controller_index]->GetDeviceDescription(profile_version); unsigned int controller_size; @@ -107,11 +129,13 @@ void ProfileManager::SetConfigurationDirectory(const filesystem::path& directory bool ProfileManager::LoadProfile(std::string profile_name) { + profile_name = StringUtils::remove_null_terminating_chars(profile_name); return(LoadProfileWithOptions(profile_name, false, true)); } bool ProfileManager::LoadSizeFromProfile(std::string profile_name) { + profile_name = StringUtils::remove_null_terminating_chars(profile_name); return(LoadProfileWithOptions(profile_name, true, false)); } @@ -150,8 +174,8 @@ std::vector ProfileManager::LoadProfileToList /*---------------------------------------------------------*\ | Read and verify file header | \*---------------------------------------------------------*/ - char profile_string[16]; - unsigned int profile_version; + char profile_string[16] = ""; + unsigned int profile_version = 0; controller_file.read(profile_string, 16); controller_file.read((char *)&profile_version, sizeof(unsigned int)); @@ -225,38 +249,38 @@ bool ProfileManager::LoadDeviceFromListWithOptions \*---------------------------------------------------------*/ bool location_check; - if(load_controller->location.find("HID: ") == 0) + if(load_controller->GetLocation().find("HID: ") == 0) { location_check = true; } - else if(load_controller->location.find("I2C: ") == 0) + else if(load_controller->GetLocation().find("I2C: ") == 0) { - std::size_t loc = load_controller->location.rfind(", "); + std::size_t loc = load_controller->GetLocation().rfind(", "); if(loc == std::string::npos) { location_check = false; } else { - std::string i2c_address = load_controller->location.substr(loc + 2); - location_check = temp_controller->location.find(i2c_address) != std::string::npos; + std::string i2c_address = load_controller->GetLocation().substr(loc + 2); + location_check = temp_controller->GetLocation().find(i2c_address) != std::string::npos; } } else { - location_check = temp_controller->location == load_controller->location; + location_check = temp_controller->GetLocation() == load_controller->GetLocation(); } /*---------------------------------------------------------*\ | Test if saved controller data matches this controller | \*---------------------------------------------------------*/ - if((temp_controller_used[temp_index] == false ) - &&(temp_controller->type == load_controller->type ) - &&(temp_controller->name == load_controller->name ) - &&(temp_controller->description == load_controller->description) - &&(temp_controller->version == load_controller->version ) - &&(temp_controller->serial == load_controller->serial ) - &&(location_check == true )) + if((temp_controller_used[temp_index] == false ) + &&(temp_controller->type == load_controller->type ) + &&(temp_controller->GetName() == load_controller->GetName() ) + &&(temp_controller->GetDescription() == load_controller->GetDescription()) + &&(temp_controller->GetVersion() == load_controller->GetVersion() ) + &&(temp_controller->GetSerial() == load_controller->GetSerial() ) + &&(location_check == true )) { /*---------------------------------------------------------*\ | Set used flag for this temp device | @@ -277,14 +301,19 @@ bool ProfileManager::LoadDeviceFromListWithOptions &&(temp_controller->zones[zone_idx].leds_min == load_controller->zones[zone_idx].leds_min ) &&(temp_controller->zones[zone_idx].leds_max == load_controller->zones[zone_idx].leds_max )) { - if (temp_controller->zones[zone_idx].leds_count != load_controller->zones[zone_idx].leds_count) + if(temp_controller->zones[zone_idx].leds_count != load_controller->zones[zone_idx].leds_count) { - load_controller->ResizeZone(zone_idx, temp_controller->zones[zone_idx].leds_count); + load_controller->ResizeZone((int)zone_idx, temp_controller->zones[zone_idx].leds_count); } - for(std::size_t segment_idx = 0; segment_idx < temp_controller->zones[zone_idx].segments.size(); segment_idx++) + if(temp_controller->zones[zone_idx].segments.size() != load_controller->zones[zone_idx].segments.size()) { - load_controller->zones[zone_idx].segments.push_back(temp_controller->zones[zone_idx].segments[segment_idx]); + load_controller->zones[zone_idx].segments.clear(); + + for(std::size_t segment_idx = 0; segment_idx < temp_controller->zones[zone_idx].segments.size(); segment_idx++) + { + load_controller->zones[zone_idx].segments.push_back(temp_controller->zones[zone_idx].segments[segment_idx]); + } } } } @@ -388,8 +417,8 @@ bool ProfileManager::LoadProfileWithOptions for(std::size_t controller_index = 0; controller_index < controllers.size(); controller_index++) { bool temp_ret_val = LoadDeviceFromListWithOptions(temp_controllers, temp_controller_used, controllers[controller_index], load_size, load_settings); - std::string current_name = controllers[controller_index]->name + " @ " + controllers[controller_index]->location; - LOG_INFO("Profile loading: %s for %s", ( temp_ret_val ? "Succeeded" : "FAILED!" ), current_name.c_str()); + std::string current_name = controllers[controller_index]->GetName() + " @ " + controllers[controller_index]->GetLocation(); + LOG_INFO("[ProfileManager] Profile loading: %s for %s", ( temp_ret_val ? "Succeeded" : "FAILED!" ), current_name.c_str()); ret_val |= temp_ret_val; } @@ -406,6 +435,8 @@ bool ProfileManager::LoadProfileWithOptions void ProfileManager::DeleteProfile(std::string profile_name) { + profile_name = StringUtils::remove_null_terminating_chars(profile_name); + filesystem::path filename = configuration_directory / profile_name; filename.concat(".orp"); @@ -427,7 +458,7 @@ void ProfileManager::UpdateProfileList() if(filename.find(".orp") != std::string::npos) { - LOG_INFO("Found file: %s attempting to validate header", filename.c_str()); + LOG_INFO("[ProfileManager] Found file: %s attempting to validate header", filename.c_str()); /*---------------------------------------------------------*\ | Open input file in binary mode | @@ -455,16 +486,16 @@ void ProfileManager::UpdateProfileList() filename.erase(filename.length() - 4); profile_list.push_back(filename); - LOG_INFO("Valid v%i profile found for %s", profile_version, filename.c_str()); + LOG_INFO("[ProfileManager] Valid v%i profile found for %s", profile_version, filename.c_str()); } else { - LOG_WARNING("Profile %s isn't valid for current version (v%i, expected v%i at most)", filename.c_str(), profile_version, OPENRGB_PROFILE_VERSION); + LOG_WARNING("[ProfileManager] Profile %s isn't valid for current version (v%i, expected v%i at most)", filename.c_str(), profile_version, OPENRGB_PROFILE_VERSION); } } else { - LOG_WARNING("Profile %s isn't valid: header is missing", filename.c_str()); + LOG_WARNING("[ProfileManager] Profile %s isn't valid: header is missing", filename.c_str()); } profile_file.close(); @@ -480,7 +511,7 @@ unsigned char * ProfileManager::GetProfileListDescription() /*---------------------------------------------------------*\ | Calculate data size | \*---------------------------------------------------------*/ - unsigned short num_profiles = profile_list.size(); + unsigned short num_profiles = (unsigned short)profile_list.size(); data_size += sizeof(data_size); data_size += sizeof(num_profiles); @@ -488,7 +519,7 @@ unsigned char * ProfileManager::GetProfileListDescription() for(unsigned int i = 0; i < num_profiles; i++) { data_size += sizeof (unsigned short); - data_size += strlen(profile_list[i].c_str()) + 1; + data_size += (unsigned int)strlen(profile_list[i].c_str()) + 1; } /*---------------------------------------------------------*\ @@ -513,7 +544,7 @@ unsigned char * ProfileManager::GetProfileListDescription() \*---------------------------------------------------------*/ for(unsigned int i = 0; i < num_profiles; i++) { - unsigned short name_len = strlen(profile_list[i].c_str()) + 1; + unsigned short name_len = (unsigned short)strlen(profile_list[i].c_str()) + 1; memcpy(&data_buf[data_ptr], &name_len, sizeof(name_len)); data_ptr += sizeof(name_len); diff --git a/ProfileManager.h b/ProfileManager.h index 793d1d29..082d0566 100644 --- a/ProfileManager.h +++ b/ProfileManager.h @@ -1,7 +1,15 @@ +/*---------------------------------------------------------*\ +| ProfileManager.h | +| | +| OpenRGB profile manager | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #pragma once #include "RGBController.h" - #include "filesystem.h" class ProfileManagerInterface diff --git a/README.md b/README.md index 027b6a38..772c922c 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,8 @@ -## ![OpenRGB](https://gitlab.com/CalcProgrammer1/OpenRGB/-/wikis/uploads/5b7e633ac9f63b00c8a4c72686206c3f/OpenRGB.png "OpenRGB Logo") +## ![OpenRGB](Documentation/Images/OpenRGB.png "OpenRGB Logo") -![Visitors](https://visitor-badge.glitch.me/badge?page_id=org.openrgb.readme) ![Pipeline Status](https://gitlab.com/CalcProgrammer1/OpenRGB/badges/master/pipeline.svg) +![Pipeline Status](https://gitlab.com/CalcProgrammer1/OpenRGB/badges/master/pipeline.svg) -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. - -[[_TOC_]] +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 Windows, Linux, and MacOS, without any nonsense? That is what OpenRGB sets out to achieve. One app to rule them all. ## Features @@ -20,240 +16,58 @@ One of the biggest complaints about RGB is the software ecosystem surrounding it * No official/manufacturer software required * Graphical view of device LEDs makes creating custom patterns easy +![OpenRGB_Device_View](Documentation/Images/OpenRGB_Screenshot.png "OpenRGB Device View Screenshot") + +## Website + +* Check out our website at [openrgb.org](https://openrgb.org) + ## Supported Devices * See the [Supported Devices](https://openrgb.org/devices.html) page for the current list of supported devices. -## Configuration - -* See the [OpenRGB Settings](https://gitlab.com/OpenRGBDevelopers/OpenRGB-Wiki/-/blob/stable/OpenRGB-Settings.md) page for information about the configuration file. - ## WARNING! -This project interacts directly with hardware using reverse engineered protocols. While we do our best to make sure we're sending the right data, there is always some risk in sending data to hardware when we don't understand exactly how that hardware works. +This project interacts directly with hardware using reverse engineered protocols. While we do our best to make sure we're sending the right data, there is always some risk in sending data to hardware when we don't understand exactly how that hardware works. There have been issues in the past with certain hardware getting damaged/bricked and we have either disabled or fixed the offending code. That said, with OpenRGB always changing and the landscape of RGB devices being of widely varying quality, we can't guarantee it won't happen again. By installing and using OpenRGB you accept this risk. -There have been two instances of hardware damage in OpenRGB's development and we've taken precautions to prevent it from happening again. +## Download OpenRGB - * The Mystic Light motherboard code bricked the RGB controller of some MSI motherboards. The code was disabled and reworked. We have been re-adding these motherboards to the support list as we verify that the new code works with them. Affected boards can be unbricked with a Nuvoton Nu-Link adapter. - * There were reports of bricked Gigabyte Aorus Z390 motherboards caused by dumping SMBus address 0x68 in an attempt to reverse engineer the RGB. Due to this, the SMBus Tools page on OpenRGB is hidden by default now as it has no real use to non-developers. + * Pre-built binaries are available for the following platforms: + * Windows + * Linux (AppImage, .deb, and .rpm) + * MacOS + * Released versions are available to download on [OpenRGB.org](https://openrgb.org/releases.html) or under [Releases](https://gitlab.com/CalcProgrammer1/OpenRGB/-/releases/permalink/latest). + * Experimental (aka Pipeline) versions are available to download on [OpenRGB.org](https://openrgb.org/index.html#pl). + * On Windows, you will need the **Microsoft Visual 2019 C++ runtime** installed. You can get it [here](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads). + * An unofficial Flatpak release is [available on Flathub](https://flathub.org/apps/details/org.openrgb.OpenRGB) + * Note: If using the AppImage or Flatpak versions, ensure you [install the latest udev rules](Documentation/UdevRules.md). + * Released versions are officially packaged for various distributions including Alpine, Fedora, and Arch. + * Arch users can also install from the [Extra repository](https://archlinux.org/packages/extra/x86_64/openrgb/) or from the AUR for the [pipeline](https://aur.archlinux.org/packages/openrgb-git/) version. -![OpenRGB_Device_View](https://gitlab.com/CalcProgrammer1/OpenRGB/-/wikis/uploads/e1d8d4603ecdd04f1acbcf6b2314fc66/OpenRGB_0.31_Device_View.PNG "OpenRGB Device View Screenshot") +## Compile OpenRGB -## Windows + * Instructions for compiling from source are [available here](Documentation/Compiling.md). - * You will need the **Microsoft Visual 2019 C++ runtime** installed. You can get it [here](https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads) - * Pre-built Release binaries are available for Windows 10 / 11 64bit under the [Releases section](https://gitlab.com/CalcProgrammer1/OpenRGB/-/releases/permalink/latest#Windows-64-bit) on GitLab. - * If you want to test the latest (potentially unstable) code you can also get the Windows package from [the pipeline builds](https://gitlab.com/CalcProgrammer1/OpenRGB/-/jobs/artifacts/master/download?job=Windows+64). +## Setup Device Access -
-
Compiling
- - * To build the application yourself on Windows: - 1. Download the latest [Visual Studio Community Edition](https://visualstudio.microsoft.com/thank-you-for-downloading-visual-studio-for-cplusplus/?sku=Community) - and [Qt Creator](https://www.qt.io/download-thank-you). - 2. When [installing the QT toolset](https://gitlab.com/OpenRGBDevelopers/OpenRGB-Wiki/-/blob/stable/Downloading%20Qt%20and%20building%20OpenRGB.md) - select the latest revision of Qt 5.15.x as OpenRGB is not yet compatible with QT6 - 3. Optionally [install Git](https://git-scm.com/download) if you intend to - [contribute your changes](https://gitlab.com/CalcProgrammer1/OpenRGB/-/blob/master/CONTRIBUTING.md) - to the mainline codebase. - 4. Open the OpenRGB.pro project in Qt Creator. - 5. Use the MSVC compiler kit, either 32- or 64-bit, to build the application. - 6. Run the project from Qt Creator. If you want to use your custom build standalone, download the latest matching Release package and replace the OpenRGB.exe in it with your new build. - -
- - ---- - -### SMBus Access - * **You must run the application as Administrator the first time to allow WinRing0 to set up. It can be run as a normal user afterwards** - * Early versions of OpenRGB used InpOut32. This is no longer needed and should be removed to avoid warnings by some anti-cheat software. You can uninstall Inpout32 by following the instructions [here](https://gitlab.com/CalcProgrammer1/OpenRGB/-/issues/669#note_461054255). - -### USB Access - - * Early versions of OpenRGB used the WinUSB driver, installed using Zadig. This is no longer required, and you need to uninstall the WinUSB driver if you previously installed it. You can uninstall the WinUSB driver by following [this guide](https://gitlab.com/CalcProgrammer1/OpenRGB/-/wikis/Frequently-Asked-Questions#i-installed-the-winusb-driver-for-a-device-and-i-wish-to-uninstall-it). - -## Linux - - * Pre-built binaries in AppImage format are available under the [Releases](https://gitlab.com/CalcProgrammer1/OpenRGB/-/releases/permalink/latest#Linux-64-bit) section on GitLab. - * There is also a unofficial universal Flatpak build [available on Flathub](https://flathub.org/apps/details/org.openrgb.OpenRGB). Note: To ensure you have device permissions please [install the latest UDEV rules](#installing-udev-rules-manually). - -
-
Arch
- -##### Binaries - - * OpenRGB is available in the AUR for both the [release](https://aur.archlinux.org/packages/openrgb/) and [pipeline](https://aur.archlinux.org/packages/openrgb-git/) builds - -
-
-
Debian / Ubuntu
- -##### Binaries - - * OpenRGB builds an official Debian package for Bullseye and Ubuntu 21.04 onwards for both the 64bit [release](https://gitlab.com/CalcProgrammer1/OpenRGB/-/releases/permalink/latest#Debian-Bullseye-amd64) and [pipeline](https://gitlab.com/CalcProgrammer1/OpenRGB/-/jobs/artifacts/master/download?job=Linux+64+.deb+%28Debian+Bullseye%29) builds - * There is also a legacy package for Debian 64bit Buster and it's derivatives (Ubuntu prior to 21.04) with [release](https://gitlab.com/CalcProgrammer1/OpenRGB/-/releases/permalink/latest#Debian-Buster-amd64) and [pipeline](https://gitlab.com/CalcProgrammer1/OpenRGB/-/jobs/artifacts/master/download?job=Linux+64+.deb+%28Debian+Buster%29) builds - -##### Compiling - - 1. Install build dependencies - - `sudo apt install git build-essential qtcreator qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libusb-1.0-0-dev libhidapi-dev pkgconf libmbedtls-dev` - 2. git clone https://gitlab.com/CalcProgrammer1/OpenRGB - 3. cd OpenRGB - 4. qmake OpenRGB.pro - 5. make -j$(nproc) - 6. You can then run the application from the compile directory with `./openrgb` or install with `make install` - 7. You will also need to [install the latest UDEV rules](#installing-udev-rules-manually). - -##### Packaging - - * You can also build a Debian package (.deb) from this source code with `dpkg-buildpackage -us -B` - - Building a Debian package requires `debhelper` to be installed: `sudo apt install debhelper` - -
-
-
Fedora
- -##### Binaries - -* OpenRGB builds an official Fedora package for the latest [release](https://gitlab.com/CalcProgrammer1/OpenRGB/-/releases/permalink/latest#Linux-64-bit) of OpenRGB -* There are also pipeline builds for both [Fedora 35](https://gitlab.com/CalcProgrammer1/OpenRGB/-/jobs/artifacts/master/download?job=Linux+64+f35+rpm) and - [Fedora 36](https://gitlab.com/CalcProgrammer1/OpenRGB/-/jobs/artifacts/master/download?job=Linux+64+f36+rpm) available - -##### Compiling - - 1. Install build dependencies - - `sudo dnf install automake gcc-c++ qt5-qtbase-devel qt5-linguist hidapi-devel libusbx-devel mbedtls-devel` - 2. git clone https://gitlab.com/CalcProgrammer1/OpenRGB - 3. cd OpenRGB - 4. qmake-qt5 OpenRGB.pro - 5. make -j$(nproc) - 6. You can then run the application from the compile directory with `./openrgb` or install with `make install` - 7. You will also need to [install the latest UDEV rules](#installing-udev-rules-manually). - -
- - ---- - -### SMBus Access - - * SMBus access is necessary for controlling RGB RAM and certain motherboard on-board LEDs. - * If you are not trying to use OpenRGB to control RGB RAM or motherboard LEDs, you may skip this section. - * ASUS and ASRock motherboards have their RGB controller on a secondary SMBus interface and requires a Linux kernel > 5.7 [commit](https://github.com/torvalds/linux/commit/f27237c174fd9653033330e4e532cd9d153ce824) - * Allowing access to SMBus: - 1. Install the `i2c-tools` package. - 2. Load the i2c-dev module: `sudo modprobe i2c-dev` - 3. Create the i2c group if it does not already exist: `sudo groupadd --system i2c` - 4. Add yourself to the i2c group: `sudo usermod $USER -aG i2c` - 5. If you want you can load the i2c-dev module at boot: `sudo touch /etc/modules-load.d/i2c.conf && sudo sh -c 'echo "i2c-dev" >> /etc/modules-load.d/i2c.conf'` - 6. Load the i2c driver for your chipset: -
-
Intel
- - * `sudo modprobe i2c-i801` - * `sudo modprobe i2c-nct6775` - Secondary controller for motherboard LEDs (requires [kernel patch](https://gitlab.com/OpenRGBDevelopers/OpenRGB-Wiki/-/blob/stable/OpenRGB-Kernel-Patch.md)) - -
-
-
AMD
- - * `sudo modprobe i2c-piix4` - * Unmodified kernel will have one interface, patched kernel will have two. The first at 0x0B00 and the second at 0x0B20. The 0x0B20 interface is for motherboard LEDs. - -
- - * If RGB RAM or certain motherboard on-board LEDs are not loading the profile on startup, you need to add the loading entries to: `/etc/modules-load.d/` - - i2c-dev - - i2c-i801 or i2c-piix4 (according to your chipset) - - ---- - - * You'll have to enable user access to your SMBus if you don't run as root. - - List all SMBus controllers: `sudo i2cdetect -l` - - Note the number for PIIX4, I801, and NCT6775 controllers. - - Give user access to those controllers. If you have not installed OpenRGB from a package (e.g. deb, RPM or from the AUR) then most likely you need to [install the UDEV rules](#installing-udev-rules-manually). - * The i2c-nct6775 kernel module requires patching, please refer to [instructions here](https://gitlab.com/OpenRGBDevelopers/OpenRGB-Wiki/-/blob/stable/OpenRGB-Kernel-Patch.md) - * Some Gigabyte/Aorus motherboards have an ACPI conflict with the SMBus controller. Please [add a kernel parameter](#kernel-parameters) to resolve this conflict. - -### USB Access - - * USB devices require [udev rules](#installing-udev-rules-manually) to access as a normal user. - * Alternatively you can run OpenRGB as root to detect all USB devices. (Not recommended) - * USB based Gigabyte AORUS motherboards may also have an ACPI conflict. Please [add a kernel parameter](#kernel-parameters) to resolve this conflict. - -### Installing UDEV rules manually - - * If you have installed OpenRGB from a package then latest UDEV rules are installed locally at `/usr/lib/udev/rules.d/60-openrgb.rules` - * Flatpak and Appimage "packages" will need to install this file manually. - * Udev rules are built from the source at compile time. When building locally they are installed with the `make install` step to `/usr/lib/udev/rules.d/60-openrgb.rules` - * If you need to install the UDEV rules file manually you can also download the [latest compiled udev rules](https://gitlab.com/CalcProgrammer1/OpenRGB/-/jobs/artifacts/master/raw/60-openrgb.rules?job=Linux+64+AppImage&inline=false) from Gitlab. - - Copy this 60-openrgb.rules file to `/usr/lib/udev/rules.d/` - - Then reload rules with `sudo udevadm control --reload-rules && sudo udevadm trigger` - -### Kernel Parameters - - * To resolve an ACPI conflict add the `acpi_enforce_resources=lax` kernel parameter. - * If you want to check if the kernel was loaded with this option you can execute this command from the terminal once you've rebooted. - * `cat /proc/cmdline` - -
-
Arch
- - * Please see [the Arch wiki](https://wiki.archlinux.org/title/kernel_parameters) for details on how to update your bootloader. - -
-
-
Debian / Ubuntu
- - * Please see [the Ubuntu Documentation](https://wiki.ubuntu.com/Kernel/KernelBootParameters) for Kernel Parameters for more information on updating your boot parameters. - -
-
-
Fedora
- - * On Fedora, install `grubby` and then following command: - `grubby --update-kernel=ALL --args="acpi_enforce_resources=lax"` - * For more information please refer to the Fedora docs for [grubby](https://docs.fedoraproject.org/en-US/fedora/latest/system-administrators-guide/kernel-module-driver-configuration/Working_with_the_GRUB_2_Boot_Loader/#sec-Making_Persistent_Changes_to_a_GRUB_2_Menu_Using_the_grubby_Tool). - -
- - ---- - -## MacOS - - * Pre-built binaries in zipped application package 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 with Homebrew - - Install Homebrew by following the instructions at https://brew.sh/ - - brew install git qt5 hidapi libusb mbedtls@2 - - brew link qt5 - 2. [Create a local certificate](https://support.apple.com/guide/keychain-access/create-self-signed-certificates-kyca8916/mac) called OpenRGB with code signing capability - 3. git clone https://gitlab.com/CalcProgrammer1/OpenRGB - 4. cd OpenRGB - 5. qmake OpenRGB.pro - 6. make -j8 - 7. macdeployqt OpenRGB.app -codesign=OpenRGB - 8. Copy the OpenRGB.app application package to Applications - -### SMBus Access - - * For Intel devices using a controller in the I801 family you have to download and install the [macUSPCIO driver](https://github.com/ShadyNawara/macUSPCIO/releases) - -### USB Access - - * USB devices may require the Input Monitoring permission. You can add OpenRGB in System Preferences > Security & Privacy > Privacy. + * After installing OpenRGB, please see the [SMBus Access](Documentation/SMBusAccess.md) and [USB Access](Documentation/USBAccess.md) pages for instructions on setting up access to your RGB devices. ## Join Our Discord * https://discord.gg/AQwjJPY +## Follow Us On Mastodon + +* https://floss.social/@OpenRGB + ## Visit Our Lemmy Community * https://lemmy.ml/c/OpenRGB ## How-Tos and FAQs -* [Windows Setup and Usage](https://gitlab.com/OpenRGBDevelopers/OpenRGB-Wiki/-/blob/stable/OpenRGB-Windows-Setup-and-Usage.md) -* [Frequently Asked Questions](https://gitlab.com/OpenRGBDevelopers/OpenRGB-Wiki/-/blob/stable/Frequently-Asked-Questions.md) +* [Windows Setup and Usage](https://gitlab.com/OpenRGBDevelopers/OpenRGB-Wiki/-/blob/stable/User-Documentation/OpenRGB-Windows-Setup-and-Usage.md) +* [Frequently Asked Questions](https://gitlab.com/OpenRGBDevelopers/OpenRGB-Wiki/-/blob/stable/User-Documentation/Frequently-Asked-Questions.md) ## Support OpenRGB @@ -268,64 +82,64 @@ There have been two instances of hardware damage in OpenRGB's development and we ## Contributing -* Want to contribute support for a new device? Check out the [RGBController API](https://gitlab.com/OpenRGBDevelopers/OpenRGB-Wiki/-/blob/stable/The-RGBController-API.md) page for documentation of how OpenRGB implements device control. -* Want to create a new OpenRGB SDK client implementation? Check out the [OpenRGB SDK Documentation](Documentation) page for documentation of how the OpenRGB SDK network protocol functions. -* Please read the [Contributing Guidelines](https://gitlab.com/CalcProgrammer1/OpenRGB/-/blob/master/CONTRIBUTING.md) before starting work on your new changes. +* Want to contribute support for a new device? Check out the [RGBController API](Documentation/RGBControllerAPI.md) page for documentation of how OpenRGB implements device control. +* Want to create a new OpenRGB SDK client implementation? Check out the [OpenRGB SDK Documentation](Documentation/OpenRGBSDK.md) page for documentation of how the OpenRGB SDK network protocol functions. +* Please read the [Contributing Guidelines](CONTRIBUTING.md) before starting work on your new changes. ## OpenRGB SDK * OpenRGB provides a network interface for controlling supported RGB devices from other software. These projects implement the OpenRGB SDK and provide additional ways for you to control your lighting setup. - * OpenRGB Python Client (by bahorn): https://github.com/bahorn/OpenRGB-PyClient - * OpenRGB Python Client (by jath03): https://github.com/jath03/openrgb-python - * OpenRGB Node.js Client (by vlakreeh): https://github.com/vlakreeh/openrgb - * D-Bus Connector for OpenRGB (by Vinno97): https://github.com/Vinno97/OpenRGB-DBus-Connector - * OpenRGB.NET - C# OpenRGB Client (by diogotr7): https://github.com/diogotr7/OpenRGB.NET - * OpenRGB-Client - Java Client (by morg): https://gitlab.com/mguimard/openrgb-client - * OpenRGB-SDK - NodeJS client (by Mola19): https://www.npmjs.com/package/openrgb-sdk - * OpenRGB-cppSDK - C++ client (by Youda008): https://github.com/Youda008/OpenRGB-cppSDK - * openrgb-rs - Rust client (by nicoulaj): https://github.com/nicoulaj/openrgb-rs + * [OpenRGB Python Client](https://github.com/jath03/openrgb-python) (by jath03) + * [OpenRGB Python Client (deprecated)](https://github.com/bahorn/OpenRGB-PyClient) (by bahorn) + * [OpenRGB Node.js Client](https://github.com/vlakreeh/openrgb) (by vlakreeh) + * [D-Bus Connector for OpenRGB](https://github.com/Vinno97/OpenRGB-DBus-Connector) (by Vinno97) + * [OpenRGB.NET - C# OpenRGB Client](https://github.com/diogotr7/OpenRGB.NET) (by diogotr7) + * [OpenRGB-Client - Java Client](https://gitlab.com/mguimard/openrgb-client) (by morg) + * [OpenRGB-SDK - NodeJS client](https://www.npmjs.com/package/openrgb-sdk) (by Mola19) + * [OpenRGB-cppSDK - C++ client](https://github.com/Youda008/OpenRGB-cppSDK) (by Youda008) + * [openrgb-rs2 - Rust client](https://github.com/Achtuur/openrgb-rs2) (by nicoulaj & Achtuur) ## Applications Supporting OpenRGB SDK * While OpenRGB itself only provides control over the lighting effects built into hardware, several open source applications can use the OpenRGB SDK to provide synchronized lighting effects for your devices. - * Keyboard Visualizer (by me): https://gitlab.com/CalcProgrammer1/KeyboardVisualizer - * OpenRGB E1.31 Receiver (by me): https://gitlab.com/CalcProgrammer1/OpenRGBE131Receiver - * Project Aurora (support added by diogotr7): https://github.com/Aurora-RGB/Aurora - * Artemis 2 (support added by diogotr7 as a plugin): https://github.com/Artemis-RGB/Artemis - * RemoteLight (by Drumber, need OpenRGB plugin): https://github.com/Drumber/RemoteLight - * OpenRGB-python-FX (by herosilas12): https://github.com/herosilas12/OpenRGB-python-FX - * AllMyLights (by sparten11740): https://github.com/sparten11740/allmylights - * OpenRGBRemote (by morg): https://gitlab.com/mguimard/openrgbremote + * [Keyboard Visualizer](https://gitlab.com/CalcProgrammer1/KeyboardVisualizer) (by CalcProgrammer1) + * [OpenRGB E1.31 Receiver](https://gitlab.com/CalcProgrammer1/OpenRGBE131Receiver) (by me) + * [Aurora](https://github.com/Aurora-RGB/Aurora) (OpenRGB support added by diogotr7) + * [Artemis](https://github.com/Artemis-RGB/Artemis) (OpenRGB support added by diogotr7) + * [RemoteLight](https://github.com/Drumber/RemoteLight) (by Drumber, requires OpenRGB plugin) + * [OpenRGB-python-FX](https://github.com/herosilas12/OpenRGB-python-FX) (by herosilas12) + * [AllMyLights](https://github.com/sparten11740/allmylights) (by sparten11740) + * [OpenRGBRemote](https://gitlab.com/mguimard/openrgbremote) (by morg) + * [PiLED](https://github.com/PolisanTheEasyNick/PiLED) (by PolisanTheEasyNick) ## OpenRGB Plugins * OpenRGB provides a plugin interface for adding features to the OpenRGB application. The following projects provide additional functionality in the form of plugins. - * OpenRGB E1.31 Receiver Plugin (by me): https://gitlab.com/OpenRGBDevelopers/OpenRGBE131ReceiverPlugin - * Effects Engine Plugin (by herosilas12, morg): https://gitlab.com/OpenRGBDevelopers/OpenRGBEffectsPlugin - * OpenRGB Visual Map Plugin (by morg): https://gitlab.com/OpenRGBDevelopers/OpenRGBVisualMapPlugin - * Scheduler Plugin (by morg): https://gitlab.com/OpenRGBDevelopers/OpenRGBSchedulerPlugin - * Skin Plugin (by morg): https://gitlab.com/OpenRGBDevelopers/openrgbskinplugin - * Hardware Sync Plugin (by morg): https://gitlab.com/OpenRGBDevelopers/OpenRGBHardwareSyncPlugin - * Http Hook Plugin (by morg): https://gitlab.com/OpenRGBDevelopers/OpenRGBHttpHookPlugin - * Razer extras Plugin (by morg): https://gitlab.com/OpenRGBDevelopers/OpenRGBRazerExtrasPlugin - * Fan Hardware Sync Plugin (by Shady): https://gitlab.com/ShadyNawara/openrgbfansyncplugin - * OpenRGB Ambient Plugin (by krojew): https://github.com/krojew/OpenRGB-Ambient + * [OpenRGB Effects Plugin](https://gitlab.com/OpenRGBDevelopers/OpenRGBEffectsPlugin) (by herosilas12, morg) + * [OpenRGB Visual Map Plugin](https://gitlab.com/OpenRGBDevelopers/OpenRGBVisualMapPlugin) (by morg) + * [OpenRGB E1.31 Receiver Plugin](https://gitlab.com/OpenRGBDevelopers/OpenRGBE131ReceiverPlugin) (by CalcProgrammer1) + * [OpenRGB Scheduler Plugin](https://gitlab.com/OpenRGBDevelopers/OpenRGBSchedulerPlugin) (by morg) + * [OpenRGB Skin Plugin](https://gitlab.com/OpenRGBDevelopers/openrgbskinplugin) (by morg) + * [OpenRGB Hardware Sync Plugin](https://gitlab.com/OpenRGBDevelopers/OpenRGBHardwareSyncPlugin) (by morg) + * [OpenRGB Http Hook Plugin](https://gitlab.com/OpenRGBDevelopers/OpenRGBHttpHookPlugin) (by morg) + * [OpenRGB Razer Extras Plugin](https://gitlab.com/OpenRGBDevelopers/OpenRGBRazerExtrasPlugin) (by morg) + * [OpenRGB Fan Hardware Sync Plugin](https://gitlab.com/OpenRGBDevelopers/OpenRGBFanSyncPlugin) (by Shady) + * [OpenRGB Ambient Plugin](https://github.com/krojew/OpenRGB-Ambient) (by krojew) ## Projects Used +* OpenRGB directly relies upon these projects. + * WinRing0: https://openlibsys.org/ * libusb: https://github.com/libusb/libusb * hidapi: https://github.com/libusb/hidapi * libe131: https://github.com/hhromic/libe131 * NVFC: https://github.com/graphitemaster/NVFC - * OpenRazer: https://github.com/openrazer/openrazer - * OpenRazer-Win32: https://github.com/CalcProgrammer1/openrazer-win32 * 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 * httplib: https://github.com/yhirose/cpp-httplib * mdns: https://github.com/mjansson/mdns @@ -333,8 +147,10 @@ There have been two instances of hardware damage in OpenRGB's development and we ## Projects Researched -While no code from these projects directly made its way into OpenRGB, these projects have been invaluable resources for protocol information. +* While no code from these projects directly made its way into OpenRGB, these projects have been invaluable resources for protocol information. + * OpenRazer: https://github.com/openrazer/openrazer + * OpenRazer-Win32: https://github.com/CalcProgrammer1/openrazer-win32 * ckb-next: https://github.com/ckb-next/ckb-next * linux_thermaltake_riing: https://github.com/chestm007/linux_thermaltake_riing * Aura Addressable Header Controller: https://gitlab.com/cneil02/aura-addressable-header-controller @@ -351,3 +167,10 @@ While no code from these projects directly made its way into OpenRGB, these proj * g810-led: https://github.com/MatMoul/g810-led * liquidctl: https://github.com/jonasmalacofilho/liquidctl * Annemone: https://github.com/manualmanul/Annemone + * libcmmk: https://github.com/chmod222/libcmmk + * Signal RGB Plugins: https://gitlab.com/signalrgb/signal-plugins/-/tree/master/Plugins + * k550-macos: https://github.com/vookimedlo/ck550-macos/tree/master + * luxafor-python: https://github.com/vmitchell85/luxafor-python + * dreamcheekyusb: https://github.com/gbrayut/dreamcheekyusb + * omen-light: https://github.com/chiahsing/omen-light + diff --git a/RGBController/RGBController.cpp b/RGBController/RGBController.cpp index 88f1bd15..1e477549 100644 --- a/RGBController/RGBController.cpp +++ b/RGBController/RGBController.cpp @@ -1,5 +1,17 @@ -#include "RGBController.h" +/*---------------------------------------------------------*\ +| RGBController.cpp | +| | +| OpenRGB's RGB controller hardware abstration layer, | +| provides a generic representation of an RGB device | +| | +| Adam Honse (CalcProgrammer1) 02 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + #include +#include "RGBController.h" using namespace std::chrono_literals; @@ -25,8 +37,28 @@ mode::~mode() colors.clear(); } +zone::zone() +{ + name = ""; + type = 0; + leds = NULL; + colors = NULL; + start_idx = 0; + leds_count = 0; + leds_min = 0; + leds_max = 0; + matrix_map = NULL; + flags = 0; +} + +zone::~zone() +{ + +} + RGBController::RGBController() { + flags = 0; DeviceThreadRunning = true; DeviceCallThread = new std::thread(&RGBController::DeviceCallThreadFunction, this); } @@ -43,6 +75,59 @@ RGBController::~RGBController() modes.clear(); } +std::string RGBController::GetName() +{ + return(name); +} + +std::string RGBController::GetVendor() +{ + return(vendor); +} + +std::string RGBController::GetDescription() +{ + return(description); +} + +std::string RGBController::GetVersion() +{ + return(version); +} + +std::string RGBController::GetSerial() +{ + return(serial); +} + +std::string RGBController::GetLocation() +{ + return(location); +} + +std::string RGBController::GetModeName(unsigned int mode) +{ + return(modes[mode].name); +} + +std::string RGBController::GetZoneName(unsigned int zone) +{ + return(zones[zone].name); +} + +std::string RGBController::GetLEDName(unsigned int led) +{ + if(led < led_alt_names.size()) + { + if(led_alt_names[led] != "") + { + return(led_alt_names[led]); + } + } + + return(leds[led].name); +} + unsigned char * RGBController::GetDeviceDescription(unsigned int protocol_version) { unsigned int data_ptr = 0; @@ -51,16 +136,17 @@ unsigned char * RGBController::GetDeviceDescription(unsigned int protocol_versio /*---------------------------------------------------------*\ | Calculate data size | \*---------------------------------------------------------*/ - unsigned short name_len = strlen(name.c_str()) + 1; - unsigned short vendor_len = strlen(vendor.c_str()) + 1; - unsigned short description_len = strlen(description.c_str()) + 1; - unsigned short version_len = strlen(version.c_str()) + 1; - unsigned short serial_len = strlen(serial.c_str()) + 1; - unsigned short location_len = strlen(location.c_str()) + 1; - unsigned short num_modes = modes.size(); - unsigned short num_zones = zones.size(); - unsigned short num_leds = leds.size(); - unsigned short num_colors = colors.size(); + unsigned short name_len = (unsigned short)strlen(name.c_str()) + 1; + unsigned short vendor_len = (unsigned short)strlen(vendor.c_str()) + 1; + unsigned short description_len = (unsigned short)strlen(description.c_str()) + 1; + unsigned short version_len = (unsigned short)strlen(version.c_str()) + 1; + unsigned short serial_len = (unsigned short)strlen(serial.c_str()) + 1; + unsigned short location_len = (unsigned short)strlen(location.c_str()) + 1; + unsigned short num_modes = (unsigned short)modes.size(); + unsigned short num_zones = (unsigned short)zones.size(); + unsigned short num_leds = (unsigned short)leds.size(); + unsigned short num_colors = (unsigned short)colors.size(); + unsigned short num_led_alt_names= (unsigned short)led_alt_names.size(); unsigned short *mode_name_len = new unsigned short[num_modes]; unsigned short *zone_name_len = new unsigned short[num_zones]; @@ -88,8 +174,8 @@ unsigned char * RGBController::GetDeviceDescription(unsigned int protocol_versio for(int mode_index = 0; mode_index < num_modes; mode_index++) { - mode_name_len[mode_index] = strlen(modes[mode_index].name.c_str()) + 1; - mode_num_colors[mode_index] = modes[mode_index].colors.size(); + mode_name_len[mode_index] = (unsigned short)strlen(modes[mode_index].name.c_str()) + 1; + mode_num_colors[mode_index] = (unsigned short)modes[mode_index].colors.size(); data_size += mode_name_len[mode_index] + sizeof(mode_name_len[mode_index]); data_size += sizeof(modes[mode_index].value); @@ -118,7 +204,7 @@ unsigned char * RGBController::GetDeviceDescription(unsigned int protocol_versio for(int zone_index = 0; zone_index < num_zones; zone_index++) { - zone_name_len[zone_index] = strlen(zones[zone_index].name.c_str()) + 1; + zone_name_len[zone_index] = (unsigned short)strlen(zones[zone_index].name.c_str()) + 1; data_size += zone_name_len[zone_index] + sizeof(zone_name_len[zone_index]); data_size += sizeof(zones[zone_index].type); @@ -132,7 +218,7 @@ unsigned char * RGBController::GetDeviceDescription(unsigned int protocol_versio } else { - zone_matrix_len[zone_index] = (2 * sizeof(unsigned int)) + (zones[zone_index].matrix_map->height * zones[zone_index].matrix_map->width * sizeof(unsigned int)); + zone_matrix_len[zone_index] = (unsigned short)((2 * sizeof(unsigned int)) + (zones[zone_index].matrix_map->height * zones[zone_index].matrix_map->width * sizeof(unsigned int))); } data_size += sizeof(zone_matrix_len[zone_index]); @@ -155,26 +241,62 @@ unsigned char * RGBController::GetDeviceDescription(unsigned int protocol_versio /*---------------------------------------------------------*\ | Segment name string data | \*---------------------------------------------------------*/ - data_size += strlen(zones[zone_index].segments[segment_index].name.c_str()) + 1; + data_size += (unsigned int)strlen(zones[zone_index].segments[segment_index].name.c_str()) + 1; data_size += sizeof(zones[zone_index].segments[segment_index].type); data_size += sizeof(zones[zone_index].segments[segment_index].start_idx); data_size += sizeof(zones[zone_index].segments[segment_index].leds_count); } } + + /*---------------------------------------------------------*\ + | Zone flags | + \*---------------------------------------------------------*/ + if(protocol_version >= 5) + { + data_size += sizeof(unsigned int); + } } data_size += sizeof(num_leds); for(int led_index = 0; led_index < num_leds; led_index++) { - led_name_len[led_index] = strlen(leds[led_index].name.c_str()) + 1; + led_name_len[led_index] = (unsigned short)strlen(leds[led_index].name.c_str()) + 1; data_size += led_name_len[led_index] + sizeof(led_name_len[led_index]); data_size += sizeof(leds[led_index].value); } + /*---------------------------------------------------------*\ + | LED alternate names | + \*---------------------------------------------------------*/ + if(protocol_version >= 5) + { + /*-----------------------------------------------------*\ + | Number of LED alternate names | + \*-----------------------------------------------------*/ + data_size += sizeof(num_led_alt_names); + + /*-----------------------------------------------------*\ + | LED alternate name strings | + \*-----------------------------------------------------*/ + for(std::size_t led_idx = 0; led_idx < led_alt_names.size(); led_idx++) + { + data_size += sizeof(unsigned short); + data_size += (unsigned int)strlen(led_alt_names[led_idx].c_str()) + 1; + } + } + + /*---------------------------------------------------------*\ + | Controller flags | + \*---------------------------------------------------------*/ + if(protocol_version >= 5) + { + data_size += sizeof(flags); + } + data_size += sizeof(num_colors); data_size += num_colors * sizeof(RGBColor); @@ -400,22 +522,56 @@ unsigned char * RGBController::GetDeviceDescription(unsigned int protocol_versio data_ptr += sizeof(zones[zone_index].type); /*---------------------------------------------------------*\ - | Copy in zone minimum LED count (data) | + | Check for resizable effects-only zone. For protocol | + | versions that do not support this feature, we have to | + | overwrite the leds_min/max/count parameters to 1 so that | + | the zone appears a fixed size to older clients. | \*---------------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &zones[zone_index].leds_min, sizeof(zones[zone_index].leds_min)); - data_ptr += sizeof(zones[zone_index].leds_min); + if((zones[zone_index].flags & ZONE_FLAG_RESIZE_EFFECTS_ONLY) && (protocol_version < 5)) + { + /*---------------------------------------------------------*\ + | Create a temporary variable to hold the fixed value of 1 | + \*---------------------------------------------------------*/ + unsigned int tmp_size = 1; - /*---------------------------------------------------------*\ - | Copy in zone maximum LED count (data) | - \*---------------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &zones[zone_index].leds_max, sizeof(zones[zone_index].leds_max)); - data_ptr += sizeof(zones[zone_index].leds_max); + /*---------------------------------------------------------*\ + | Copy in temporary minimum LED count (data) | + \*---------------------------------------------------------*/ + memcpy(&data_buf[data_ptr], &tmp_size, sizeof(tmp_size)); + data_ptr += sizeof(tmp_size); - /*---------------------------------------------------------*\ - | Copy in zone LED count (data) | - \*---------------------------------------------------------*/ - memcpy(&data_buf[data_ptr], &zones[zone_index].leds_count, sizeof(zones[zone_index].leds_count)); - data_ptr += sizeof(zones[zone_index].leds_count); + /*---------------------------------------------------------*\ + | Copy in temporary maximum LED count (data) | + \*---------------------------------------------------------*/ + memcpy(&data_buf[data_ptr], &tmp_size, sizeof(tmp_size)); + data_ptr += sizeof(tmp_size); + + /*---------------------------------------------------------*\ + | Copy in temporary LED count (data) | + \*---------------------------------------------------------*/ + memcpy(&data_buf[data_ptr], &tmp_size, sizeof(tmp_size)); + data_ptr += sizeof(tmp_size); + } + else + { + /*---------------------------------------------------------*\ + | Copy in zone minimum LED count (data) | + \*---------------------------------------------------------*/ + memcpy(&data_buf[data_ptr], &zones[zone_index].leds_min, sizeof(zones[zone_index].leds_min)); + data_ptr += sizeof(zones[zone_index].leds_min); + + /*---------------------------------------------------------*\ + | Copy in zone maximum LED count (data) | + \*---------------------------------------------------------*/ + memcpy(&data_buf[data_ptr], &zones[zone_index].leds_max, sizeof(zones[zone_index].leds_max)); + data_ptr += sizeof(zones[zone_index].leds_max); + + /*---------------------------------------------------------*\ + | Copy in zone LED count (data) | + \*---------------------------------------------------------*/ + memcpy(&data_buf[data_ptr], &zones[zone_index].leds_count, sizeof(zones[zone_index].leds_count)); + data_ptr += sizeof(zones[zone_index].leds_count); + } /*---------------------------------------------------------*\ | Copy in size of zone matrix | @@ -455,7 +611,7 @@ unsigned char * RGBController::GetDeviceDescription(unsigned int protocol_versio \*---------------------------------------------------------*/ if(protocol_version >= 4) { - unsigned short num_segments = zones[zone_index].segments.size(); + unsigned short num_segments = (unsigned short)zones[zone_index].segments.size(); /*---------------------------------------------------------*\ | Number of segments in zone | @@ -468,7 +624,7 @@ unsigned char * RGBController::GetDeviceDescription(unsigned int protocol_versio /*---------------------------------------------------------*\ | Length of segment name string | \*---------------------------------------------------------*/ - unsigned short segment_name_length = strlen(zones[zone_index].segments[segment_index].name.c_str()) + 1; + unsigned short segment_name_length = (unsigned short)strlen(zones[zone_index].segments[segment_index].name.c_str()) + 1; memcpy(&data_buf[data_ptr], &segment_name_length, sizeof(segment_name_length)); data_ptr += sizeof(segment_name_length); @@ -492,12 +648,24 @@ unsigned char * RGBController::GetDeviceDescription(unsigned int protocol_versio data_ptr += sizeof(zones[zone_index].segments[segment_index].start_idx); /*---------------------------------------------------------*\ - | Segment LED count data | + | Segment LED count data | \*---------------------------------------------------------*/ memcpy(&data_buf[data_ptr], &zones[zone_index].segments[segment_index].leds_count, sizeof(zones[zone_index].segments[segment_index].leds_count)); data_ptr += sizeof(zones[zone_index].segments[segment_index].leds_count); } } + + /*---------------------------------------------------------*\ + | Copy in zone flags | + \*---------------------------------------------------------*/ + if(protocol_version >= 5) + { + /*---------------------------------------------------------*\ + | Zone flags | + \*---------------------------------------------------------*/ + memcpy(&data_buf[data_ptr], &zones[zone_index].flags, sizeof(zones[zone_index].flags)); + data_ptr += sizeof(zones[zone_index].flags); + } } /*---------------------------------------------------------*\ @@ -514,7 +682,7 @@ unsigned char * RGBController::GetDeviceDescription(unsigned int protocol_versio /*---------------------------------------------------------*\ | Copy in LED name (size+data) | \*---------------------------------------------------------*/ - unsigned short ledname_len = strlen(leds[led_index].name.c_str()) + 1; + unsigned short ledname_len = (unsigned short)strlen(leds[led_index].name.c_str()) + 1; memcpy(&data_buf[data_ptr], &ledname_len, sizeof(unsigned short)); data_ptr += sizeof(unsigned short); @@ -546,6 +714,41 @@ unsigned char * RGBController::GetDeviceDescription(unsigned int protocol_versio data_ptr += sizeof(colors[color_index]); } + /*---------------------------------------------------------*\ + | LED alternate names data | + \*---------------------------------------------------------*/ + if(protocol_version >= 5) + { + /*---------------------------------------------------------*\ + | Number of LED alternate name strings | + \*---------------------------------------------------------*/ + memcpy(&data_buf[data_ptr], &num_led_alt_names, sizeof(num_led_alt_names)); + data_ptr += sizeof(num_led_alt_names); + + for(std::size_t led_idx = 0; led_idx < led_alt_names.size(); led_idx++) + { + /*---------------------------------------------------------*\ + | Copy in LED alternate name (size+data) | + \*---------------------------------------------------------*/ + unsigned short string_length = (unsigned short)strlen(led_alt_names[led_idx].c_str()) + 1; + + memcpy(&data_buf[data_ptr], &string_length, sizeof(string_length)); + data_ptr += sizeof(string_length); + + strcpy((char *)&data_buf[data_ptr], led_alt_names[led_idx].c_str()); + data_ptr += string_length; + } + } + + /*---------------------------------------------------------*\ + | Controller flags data | + \*---------------------------------------------------------*/ + if(protocol_version >= 5) + { + memcpy(&data_buf[data_ptr], &flags, sizeof(flags)); + data_ptr += sizeof(flags); + } + delete[] mode_name_len; delete[] zone_name_len; delete[] led_name_len; @@ -906,6 +1109,16 @@ void RGBController::ReadDeviceDescription(unsigned char* data_buf, unsigned int new_zone.segments.push_back(new_segment); } } + + /*---------------------------------------------------------*\ + | Copy in zone flags | + \*---------------------------------------------------------*/ + if(protocol_version >= 5) + { + memcpy(&new_zone.flags, &data_buf[data_ptr], sizeof(new_zone.flags)); + data_ptr += sizeof(new_zone.flags); + } + zones.push_back(new_zone); } @@ -965,6 +1178,43 @@ void RGBController::ReadDeviceDescription(unsigned char* data_buf, unsigned int colors.push_back(new_color); } + /*---------------------------------------------------------*\ + | Copy in LED alternate names data | + \*---------------------------------------------------------*/ + if(protocol_version >= 5) + { + /*---------------------------------------------------------*\ + | Copy in number of LED alternate names | + \*---------------------------------------------------------*/ + unsigned short num_led_alt_names; + + memcpy(&num_led_alt_names, &data_buf[data_ptr], sizeof(num_led_alt_names)); + data_ptr += sizeof(num_led_alt_names); + + for(int led_idx = 0; led_idx < num_led_alt_names; led_idx++) + { + unsigned short string_length = 0; + + /*---------------------------------------------------------*\ + | Copy in LED alternate name string (size+data) | + \*---------------------------------------------------------*/ + memcpy(&string_length, &data_buf[data_ptr], sizeof(string_length)); + data_ptr += sizeof(string_length); + + led_alt_names.push_back((char *)&data_buf[data_ptr]); + data_ptr += string_length; + } + } + + /*---------------------------------------------------------*\ + | Copy in controller flags data | + \*---------------------------------------------------------*/ + if(protocol_version >= 5) + { + memcpy(&flags, &data_buf[data_ptr], sizeof(flags)); + data_ptr += sizeof(flags); + } + /*---------------------------------------------------------*\ | Setup colors | \*---------------------------------------------------------*/ @@ -982,8 +1232,8 @@ unsigned char * RGBController::GetModeDescription(int mode, unsigned int protoco /*---------------------------------------------------------*\ | Calculate data size | \*---------------------------------------------------------*/ - mode_name_len = strlen(modes[mode].name.c_str()) + 1; - mode_num_colors = modes[mode].colors.size(); + mode_name_len = (unsigned short)strlen(modes[mode].name.c_str()) + 1; + mode_num_colors = (unsigned short)modes[mode].colors.size(); data_size += sizeof(data_size); data_size += sizeof(mode); @@ -1277,7 +1527,7 @@ unsigned char * RGBController::GetColorDescription() unsigned int data_ptr = 0; unsigned int data_size = 0; - unsigned short num_colors = colors.size(); + unsigned short num_colors = (unsigned short)colors.size(); /*---------------------------------------------------------*\ | Calculate data size | @@ -1332,7 +1582,7 @@ void RGBController::SetColorDescription(unsigned char* data_buf) /*---------------------------------------------------------*\ | Check if we aren't reading beyond the list of colors. | \*---------------------------------------------------------*/ - if(((size_t) num_colors) > colors.size()) + if(((size_t)num_colors) > colors.size()) { return; } @@ -1421,7 +1671,7 @@ void RGBController::SetZoneColorDescription(unsigned char* data_buf) /*---------------------------------------------------------*\ | Check if we aren't reading beyond the list of zones. | \*---------------------------------------------------------*/ - if(((size_t) zone_idx) > zones.size()) + if(((size_t)zone_idx) > zones.size()) { return; } @@ -1489,7 +1739,7 @@ void RGBController::SetSingleLEDColorDescription(unsigned char* data_buf) /*---------------------------------------------------------*\ | Check if we aren't reading beyond the list of leds. | \*---------------------------------------------------------*/ - if(((size_t) led_idx) > leds.size()) + if(((size_t)led_idx) > leds.size()) { return; } @@ -1500,9 +1750,152 @@ void RGBController::SetSingleLEDColorDescription(unsigned char* data_buf) memcpy(&colors[led_idx], &data_buf[sizeof(led_idx)], sizeof(RGBColor)); } +unsigned char * RGBController::GetSegmentDescription(int zone, segment new_segment) +{ + unsigned int data_ptr = 0; + unsigned int data_size = 0; + + /*---------------------------------------------------------*\ + | Length of data size | + \*---------------------------------------------------------*/ + data_size += sizeof(data_size); + + /*---------------------------------------------------------*\ + | Length of zone index | + \*---------------------------------------------------------*/ + data_size += sizeof(zone); + + /*---------------------------------------------------------*\ + | Length of segment name string | + \*---------------------------------------------------------*/ + data_size += sizeof(unsigned short); + + /*---------------------------------------------------------*\ + | Segment name string data | + \*---------------------------------------------------------*/ + data_size += (unsigned int)strlen(new_segment.name.c_str()) + 1; + + data_size += sizeof(new_segment.type); + data_size += sizeof(new_segment.start_idx); + data_size += sizeof(new_segment.leds_count); + + /*---------------------------------------------------------*\ + | Create data buffer | + \*---------------------------------------------------------*/ + unsigned char *data_buf = new unsigned char[data_size]; + + /*---------------------------------------------------------*\ + | Copy in data size | + \*---------------------------------------------------------*/ + memcpy(&data_buf[data_ptr], &data_size, sizeof(data_size)); + data_ptr += sizeof(data_size); + + /*---------------------------------------------------------*\ + | Copy in zone index | + \*---------------------------------------------------------*/ + memcpy(&data_buf[data_ptr], &zone, sizeof(zone)); + data_ptr += sizeof(zone); + + /*---------------------------------------------------------*\ + | Length of segment name string | + \*---------------------------------------------------------*/ + unsigned short segment_name_length = (unsigned short)strlen(new_segment.name.c_str()) + 1; + + memcpy(&data_buf[data_ptr], &segment_name_length, sizeof(segment_name_length)); + data_ptr += sizeof(segment_name_length); + + /*---------------------------------------------------------*\ + | Segment name string data | + \*---------------------------------------------------------*/ + strcpy((char *)&data_buf[data_ptr], new_segment.name.c_str()); + data_ptr += segment_name_length; + + /*---------------------------------------------------------*\ + | Segment type data | + \*---------------------------------------------------------*/ + memcpy(&data_buf[data_ptr], &new_segment.type, sizeof(new_segment.type)); + data_ptr += sizeof(new_segment.type); + + /*---------------------------------------------------------*\ + | Segment start index data | + \*---------------------------------------------------------*/ + memcpy(&data_buf[data_ptr], &new_segment.start_idx, sizeof(new_segment.start_idx)); + data_ptr += sizeof(new_segment.start_idx); + + /*---------------------------------------------------------*\ + | Segment LED count data | + \*---------------------------------------------------------*/ + memcpy(&data_buf[data_ptr], &new_segment.leds_count, sizeof(new_segment.leds_count)); + data_ptr += sizeof(new_segment.leds_count); + + return(data_buf); +} + +void RGBController::SetSegmentDescription(unsigned char* data_buf) +{ + unsigned int data_ptr = sizeof(unsigned int); + + /*---------------------------------------------------------*\ + | Copy in zone index | + \*---------------------------------------------------------*/ + unsigned int zone_idx; + memcpy(&zone_idx, &data_buf[data_ptr], sizeof(zone_idx)); + data_ptr += sizeof(zone_idx); + + /*---------------------------------------------------------*\ + | Length of segment name string | + \*---------------------------------------------------------*/ + unsigned short segment_name_length; + memcpy(&segment_name_length, &data_buf[data_ptr], sizeof(segment_name_length)); + data_ptr += sizeof(segment_name_length); + + /*---------------------------------------------------------*\ + | Segment name string data | + \*---------------------------------------------------------*/ + char * segment_name = new char[segment_name_length]; + memcpy(segment_name, &data_buf[data_ptr], segment_name_length); + data_ptr += segment_name_length; + + /*---------------------------------------------------------*\ + | Segment type data | + \*---------------------------------------------------------*/ + zone_type segment_type; + memcpy(&segment_type, &data_buf[data_ptr], sizeof(segment_type)); + data_ptr += sizeof(segment_type); + + /*---------------------------------------------------------*\ + | Segment start index data | + \*---------------------------------------------------------*/ + unsigned int segment_start_idx; + memcpy(&segment_start_idx, &data_buf[data_ptr], sizeof(segment_start_idx)); + data_ptr += sizeof(segment_start_idx); + + /*---------------------------------------------------------*\ + | Segment LED count data | + \*---------------------------------------------------------*/ + unsigned int segment_leds_count; + memcpy(&segment_leds_count, &data_buf[data_ptr], sizeof(segment_leds_count)); + data_ptr += sizeof(segment_leds_count); + + /*---------------------------------------------------------*\ + | Add new segment | + \*---------------------------------------------------------*/ + segment new_segment; + + new_segment.name = segment_name; + new_segment.type = segment_type; + new_segment.start_idx = segment_start_idx; + new_segment.leds_count = segment_leds_count; + + AddSegment(zone_idx, new_segment); + + delete[] segment_name; +} + void RGBController::SetupColors() { unsigned int total_led_count; + unsigned int zone_led_count; /*---------------------------------------------------------*\ | Determine total number of LEDs on the device | @@ -1511,7 +1904,7 @@ void RGBController::SetupColors() for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) { - total_led_count += zones[zone_idx].leds_count; + total_led_count += GetLEDsInZone((unsigned int)zone_idx); } /*---------------------------------------------------------*\ @@ -1526,9 +1919,10 @@ void RGBController::SetupColors() for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) { - zones[zone_idx].start_idx=total_led_count; + zones[zone_idx].start_idx = total_led_count; + zone_led_count = GetLEDsInZone((unsigned int)zone_idx); - if((colors.size() > 0) && (zones[zone_idx].leds_count > 0)) + if((colors.size() > 0) && (zone_led_count > 0)) { zones[zone_idx].colors = &colors[total_led_count]; } @@ -1537,7 +1931,7 @@ void RGBController::SetupColors() zones[zone_idx].colors = NULL; } - if((leds.size() > 0) && (zones[zone_idx].leds_count > 0)) + if((leds.size() > 0) && (zone_led_count > 0)) { zones[zone_idx].leds = &leds[total_led_count]; } @@ -1547,10 +1941,25 @@ void RGBController::SetupColors() } - total_led_count += zones[zone_idx].leds_count; + total_led_count += zone_led_count; } } +unsigned int RGBController::GetLEDsInZone(unsigned int zone) +{ + unsigned int leds_count = zones[zone].leds_count; + + if(zones[zone].flags & ZONE_FLAG_RESIZE_EFFECTS_ONLY) + { + if(leds_count > 1) + { + leds_count = 1; + } + } + + return(leds_count); +} + RGBColor RGBController::GetLED(unsigned int led) { if(led < colors.size()) @@ -1575,13 +1984,13 @@ void RGBController::SetAllLEDs(RGBColor color) { for(std::size_t zone_idx = 0; zone_idx < zones.size(); zone_idx++) { - SetAllZoneLEDs(zone_idx, color); + SetAllZoneLEDs((int)zone_idx, color); } } void RGBController::SetAllZoneLEDs(int zone, RGBColor color) { - for (std::size_t color_idx = 0; color_idx < zones[zone].leds_count; color_idx++) + for (std::size_t color_idx = 0; color_idx < GetLEDsInZone(zone); color_idx++) { zones[zone].colors[color_idx] = color; } @@ -1708,13 +2117,29 @@ void RGBController::DeviceCallThreadFunction() { if(CallFlag_UpdateMode.load() == true) { - DeviceUpdateMode(); - CallFlag_UpdateMode = false; + if(flags & CONTROLLER_FLAG_RESET_BEFORE_UPDATE) + { + CallFlag_UpdateMode = false; + DeviceUpdateMode(); + } + else + { + DeviceUpdateMode(); + CallFlag_UpdateMode = false; + } } if(CallFlag_UpdateLEDs.load() == true) { - DeviceUpdateLEDs(); - CallFlag_UpdateLEDs = false; + if(flags & CONTROLLER_FLAG_RESET_BEFORE_UPDATE) + { + CallFlag_UpdateLEDs = false; + DeviceUpdateLEDs(); + } + else + { + DeviceUpdateLEDs(); + CallFlag_UpdateLEDs = false; + } } else { @@ -1730,6 +2155,16 @@ void RGBController::DeviceSaveMode() \*-------------------------------------------------*/ } +void RGBController::ClearSegments(int zone) +{ + zones[zone].segments.clear(); +} + +void RGBController::AddSegment(int zone, segment new_segment) +{ + zones[zone].segments.push_back(new_segment); +} + std::string device_type_to_str(device_type type) { switch(type) @@ -1760,16 +2195,22 @@ std::string device_type_to_str(device_type type) return "Light"; case DEVICE_TYPE_SPEAKER: return "Speaker"; - case DEVICE_TYPE_STORAGE: - return "Storage"; case DEVICE_TYPE_VIRTUAL: return "Virtual"; + case DEVICE_TYPE_STORAGE: + return "Storage"; case DEVICE_TYPE_CASE: return "Case"; + case DEVICE_TYPE_MICROPHONE: + return "Microphone"; case DEVICE_TYPE_ACCESSORY: return "Accessory"; case DEVICE_TYPE_KEYPAD: return "Keypad"; + case DEVICE_TYPE_LAPTOP: + return "Laptop"; + case DEVICE_TYPE_MONITOR: + return "Monitor"; default: return "Unknown"; } diff --git a/RGBController/RGBController.h b/RGBController/RGBController.h index ef6e9662..5c01a650 100644 --- a/RGBController/RGBController.h +++ b/RGBController/RGBController.h @@ -1,11 +1,14 @@ -/*-----------------------------------------*\ -| RGBController.h | -| | -| Definitions and types for generic RGB | -| lighting controller interface | -| | -| Adam Honse (CalcProgrammer1) 6/2/2019 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController.h | +| | +| OpenRGB's RGB controller hardware abstration layer, | +| provides a generic representation of an RGB device | +| | +| Adam Honse (CalcProgrammer1) 02 Jun 2019 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once @@ -27,6 +30,8 @@ typedef unsigned int RGBColor; #define ToRGBColor(r, g, b) ((RGBColor)((b << 16) | (g << 8) | (r))) +#define RGBToBGRColor(rgb) ((rgb & 0xFF) << 16 | (rgb & 0xFF00) | (rgb & 0xFF0000) >> 16) + /*------------------------------------------------------------------*\ | Mode Flags | \*------------------------------------------------------------------*/ @@ -113,6 +118,15 @@ typedef struct unsigned int value; /* Device-specific LED value */ } led; +/*------------------------------------------------------------------*\ +| Zone Flags | +\*------------------------------------------------------------------*/ +enum +{ + ZONE_FLAG_RESIZE_EFFECTS_ONLY = (1 << 0), /* Zone is resizable, but only for */ + /* effects - treat as single LED */ +}; + /*------------------------------------------------------------------*\ | Zone Types | \*------------------------------------------------------------------*/ @@ -147,10 +161,11 @@ typedef struct } segment; /*------------------------------------------------------------------*\ -| Zone Struct | +| Zone Class | \*------------------------------------------------------------------*/ -typedef struct +class zone { +public: std::string name; /* Zone name */ zone_type type; /* Zone type */ led * leds; /* List of LEDs in zone */ @@ -161,7 +176,14 @@ typedef struct unsigned int leds_max; /* Maximum number of LEDs */ matrix_map_type * matrix_map; /* Matrix map pointer */ std::vector segments; /* Segments in zone */ -} zone; + unsigned int flags; /* Zone flags bitfield */ + + /*--------------------------------------------------------------*\ + | Zone Constructor / Destructor | + \*--------------------------------------------------------------*/ + zone(); + ~zone(); +}; /*------------------------------------------------------------------*\ | Device Types | @@ -192,9 +214,24 @@ enum DEVICE_TYPE_MICROPHONE, DEVICE_TYPE_ACCESSORY, DEVICE_TYPE_KEYPAD, + DEVICE_TYPE_LAPTOP, + DEVICE_TYPE_MONITOR, DEVICE_TYPE_UNKNOWN, }; +/*------------------------------------------------------------------*\ +| Controller Flags | +\*------------------------------------------------------------------*/ +enum +{ + CONTROLLER_FLAG_LOCAL = (1 << 0), /* Device is local to this instance */ + CONTROLLER_FLAG_REMOTE = (1 << 1), /* Device is on a remote instance */ + CONTROLLER_FLAG_VIRTUAL = (1 << 2), /* Device is a virtual device */ + + CONTROLLER_FLAG_RESET_BEFORE_UPDATE = (1 << 8), /* Device resets update flag before */ + /* calling update function */ +}; + /*------------------------------------------------------------------*\ | RGBController Callback Types | \*------------------------------------------------------------------*/ @@ -207,6 +244,18 @@ class RGBControllerInterface public: virtual void SetupColors() = 0; + virtual unsigned int GetLEDsInZone(unsigned int zone) = 0; + virtual std::string GetName() = 0; + virtual std::string GetVendor() = 0; + virtual std::string GetDescription() = 0; + virtual std::string GetVersion() = 0; + virtual std::string GetSerial() = 0; + virtual std::string GetLocation() = 0; + + virtual std::string GetModeName(unsigned int mode) = 0; + virtual std::string GetZoneName(unsigned int zone) = 0; + virtual std::string GetLEDName(unsigned int led) = 0; + virtual RGBColor GetLED(unsigned int led) = 0; virtual void SetLED(unsigned int led, RGBColor color) = 0; virtual void SetAllLEDs(RGBColor color) = 0; @@ -244,6 +293,9 @@ public: virtual void DeviceCallThreadFunction() = 0; + virtual void ClearSegments(int zone) = 0; + virtual void AddSegment(int zone, segment new_segment) = 0; + /*---------------------------------------------------------*\ | Functions to be implemented in device implementation | \*---------------------------------------------------------*/ @@ -276,6 +328,9 @@ public: std::vector colors; /* Color buffer */ device_type type; /* device type */ int active_mode = 0;/* active mode */ + std::vector + led_alt_names; /* alternate LED names */ + unsigned int flags; /* controller flags */ /*---------------------------------------------------------*\ | RGBController base class constructor | @@ -288,6 +343,18 @@ public: \*---------------------------------------------------------*/ void SetupColors(); + unsigned int GetLEDsInZone(unsigned int zone); + std::string GetName(); + std::string GetVendor(); + std::string GetDescription(); + std::string GetVersion(); + std::string GetSerial(); + std::string GetLocation(); + + std::string GetModeName(unsigned int mode); + std::string GetZoneName(unsigned int zone); + std::string GetLEDName(unsigned int led); + RGBColor GetLED(unsigned int led); void SetLED(unsigned int led, RGBColor color); void SetAllLEDs(RGBColor color); @@ -311,6 +378,9 @@ public: unsigned char * GetSingleLEDColorDescription(int led); void SetSingleLEDColorDescription(unsigned char* data_buf); + unsigned char * GetSegmentDescription(int zone, segment new_segment); + void SetSegmentDescription(unsigned char* data_buf); + void RegisterUpdateCallback(RGBControllerCallback new_callback, void * new_callback_arg); void UnregisterUpdateCallback(void * callback_arg); void ClearCallbacks(); @@ -325,6 +395,9 @@ public: void DeviceCallThreadFunction(); + void ClearSegments(int zone); + void AddSegment(int zone, segment new_segment); + /*---------------------------------------------------------*\ | Functions to be implemented in device implementation | \*---------------------------------------------------------*/ diff --git a/RGBController/RGBControllerKeyNames.cpp b/RGBController/RGBControllerKeyNames.cpp index 43f92178..a09a22e1 100644 --- a/RGBController/RGBControllerKeyNames.cpp +++ b/RGBController/RGBControllerKeyNames.cpp @@ -1,187 +1,193 @@ -/*-------------------------------------------------------------------*\ -| RGBControllerKeyNames.cpp | -| | -| This is the canonical list of Key Names to be used in | -| keyboard and other device initialisations to avoid redundant | -| string literal declarations | -| | -| Chris M (Dr_No) 25 Jan 2022 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBControllerKeyNames.cpp | +| | +| List of standardized names to represent keyboard keys | +| when naming LEDs on keyboard devices | +| | +| Chris M (Dr_No) 25 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBControllerKeyNames.h" -const char* KEY_EN_UNUSED = ""; -const char* ZONE_EN_KEYBOARD = "Keyboard"; +const char* KEY_EN_UNUSED = ""; +const char* ZONE_EN_KEYBOARD = "Keyboard"; -const char* KEY_EN_ESCAPE = "Key: Escape"; -const char* KEY_EN_F1 = "Key: F1"; -const char* KEY_EN_F2 = "Key: F2"; -const char* KEY_EN_F3 = "Key: F3"; -const char* KEY_EN_F4 = "Key: F4"; -const char* KEY_EN_F5 = "Key: F5"; -const char* KEY_EN_F6 = "Key: F6"; -const char* KEY_EN_F7 = "Key: F7"; -const char* KEY_EN_F8 = "Key: F8"; -const char* KEY_EN_F9 = "Key: F9"; -const char* KEY_EN_F10 = "Key: F10"; -const char* KEY_EN_F11 = "Key: F11"; -const char* KEY_EN_F12 = "Key: F12"; -const char* KEY_EN_PRINT_SCREEN = "Key: Print Screen"; -const char* KEY_EN_SCROLL_LOCK = "Key: Scroll Lock"; -const char* KEY_EN_PAUSE_BREAK = "Key: Pause/Break"; -const char* KEY_EN_POWER = "Key: Power"; +const char* KEY_EN_ESCAPE = "Key: Escape"; +const char* KEY_EN_F1 = "Key: F1"; +const char* KEY_EN_F2 = "Key: F2"; +const char* KEY_EN_F3 = "Key: F3"; +const char* KEY_EN_F4 = "Key: F4"; +const char* KEY_EN_F5 = "Key: F5"; +const char* KEY_EN_F6 = "Key: F6"; +const char* KEY_EN_F7 = "Key: F7"; +const char* KEY_EN_F8 = "Key: F8"; +const char* KEY_EN_F9 = "Key: F9"; +const char* KEY_EN_F10 = "Key: F10"; +const char* KEY_EN_F11 = "Key: F11"; +const char* KEY_EN_F12 = "Key: F12"; +const char* KEY_EN_PRINT_SCREEN = "Key: Print Screen"; +const char* KEY_EN_SCROLL_LOCK = "Key: Scroll Lock"; +const char* KEY_EN_PAUSE_BREAK = "Key: Pause/Break"; +const char* KEY_EN_POWER = "Key: Power"; -const char* KEY_EN_BACK_TICK = "Key: `"; -const char* KEY_EN_1 = "Key: 1"; -const char* KEY_EN_2 = "Key: 2"; -const char* KEY_EN_3 = "Key: 3"; -const char* KEY_EN_4 = "Key: 4"; -const char* KEY_EN_5 = "Key: 5"; -const char* KEY_EN_6 = "Key: 6"; -const char* KEY_EN_7 = "Key: 7"; -const char* KEY_EN_8 = "Key: 8"; -const char* KEY_EN_9 = "Key: 9"; -const char* KEY_EN_0 = "Key: 0"; -const char* KEY_EN_MINUS = "Key: -"; -const char* KEY_EN_PLUS = "Key: +"; -const char* KEY_EN_EQUALS = "Key: ="; -const char* KEY_EN_BACKSPACE = "Key: Backspace"; -const char* KEY_EN_INSERT = "Key: Insert"; -const char* KEY_EN_HOME = "Key: Home"; -const char* KEY_EN_PAGE_UP = "Key: Page Up"; +const char* KEY_EN_BACK_TICK = "Key: `"; +const char* KEY_EN_1 = "Key: 1"; +const char* KEY_EN_2 = "Key: 2"; +const char* KEY_EN_3 = "Key: 3"; +const char* KEY_EN_4 = "Key: 4"; +const char* KEY_EN_5 = "Key: 5"; +const char* KEY_EN_6 = "Key: 6"; +const char* KEY_EN_7 = "Key: 7"; +const char* KEY_EN_8 = "Key: 8"; +const char* KEY_EN_9 = "Key: 9"; +const char* KEY_EN_0 = "Key: 0"; +const char* KEY_EN_MINUS = "Key: -"; +const char* KEY_EN_PLUS = "Key: +"; +const char* KEY_EN_EQUALS = "Key: ="; +const char* KEY_EN_BACKSPACE = "Key: Backspace"; +const char* KEY_EN_INSERT = "Key: Insert"; +const char* KEY_EN_HOME = "Key: Home"; +const char* KEY_EN_PAGE_UP = "Key: Page Up"; -const char* KEY_EN_TAB = "Key: Tab"; -const char* KEY_EN_Q = "Key: Q"; -const char* KEY_EN_W = "Key: W"; -const char* KEY_EN_E = "Key: E"; -const char* KEY_EN_R = "Key: R"; -const char* KEY_EN_T = "Key: T"; -const char* KEY_EN_Y = "Key: Y"; -const char* KEY_EN_U = "Key: U"; -const char* KEY_EN_I = "Key: I"; -const char* KEY_EN_O = "Key: O"; -const char* KEY_EN_P = "Key: P"; -const char* KEY_EN_LEFT_BRACKET = "Key: ["; -const char* KEY_EN_RIGHT_BRACKET = "Key: ]"; -const char* KEY_EN_BACK_SLASH = "Key: \\"; -const char* KEY_EN_ANSI_BACK_SLASH = "Key: \\ (ANSI)"; -const char* KEY_EN_DELETE = "Key: Delete"; -const char* KEY_EN_END = "Key: End"; -const char* KEY_EN_PAGE_DOWN = "Key: Page Down"; +const char* KEY_EN_TAB = "Key: Tab"; +const char* KEY_EN_Q = "Key: Q"; +const char* KEY_EN_W = "Key: W"; +const char* KEY_EN_E = "Key: E"; +const char* KEY_EN_R = "Key: R"; +const char* KEY_EN_T = "Key: T"; +const char* KEY_EN_Y = "Key: Y"; +const char* KEY_EN_U = "Key: U"; +const char* KEY_EN_I = "Key: I"; +const char* KEY_EN_O = "Key: O"; +const char* KEY_EN_P = "Key: P"; +const char* KEY_EN_LEFT_BRACKET = "Key: ["; +const char* KEY_EN_RIGHT_BRACKET = "Key: ]"; +const char* KEY_EN_BACK_SLASH = "Key: \\"; +const char* KEY_EN_ANSI_BACK_SLASH = "Key: \\ (ANSI)"; +const char* KEY_EN_DELETE = "Key: Delete"; +const char* KEY_EN_END = "Key: End"; +const char* KEY_EN_PAGE_DOWN = "Key: Page Down"; -const char* KEY_EN_CAPS_LOCK = "Key: Caps Lock"; -const char* KEY_EN_A = "Key: A"; -const char* KEY_EN_S = "Key: S"; -const char* KEY_EN_D = "Key: D"; -const char* KEY_EN_F = "Key: F"; -const char* KEY_EN_G = "Key: G"; -const char* KEY_EN_H = "Key: H"; -const char* KEY_EN_J = "Key: J"; -const char* KEY_EN_K = "Key: K"; -const char* KEY_EN_L = "Key: L"; -const char* KEY_EN_SEMICOLON = "Key: ;"; -const char* KEY_EN_QUOTE = "Key: '"; -const char* KEY_EN_POUND = "Key: #"; -const char* KEY_EN_ANSI_ENTER = "Key: Enter"; -const char* KEY_EN_ISO_ENTER = "Key: Enter (ISO)"; +const char* KEY_EN_CAPS_LOCK = "Key: Caps Lock"; +const char* KEY_EN_A = "Key: A"; +const char* KEY_EN_S = "Key: S"; +const char* KEY_EN_D = "Key: D"; +const char* KEY_EN_F = "Key: F"; +const char* KEY_EN_G = "Key: G"; +const char* KEY_EN_H = "Key: H"; +const char* KEY_EN_J = "Key: J"; +const char* KEY_EN_K = "Key: K"; +const char* KEY_EN_L = "Key: L"; +const char* KEY_EN_SEMICOLON = "Key: ;"; +const char* KEY_EN_QUOTE = "Key: '"; +const char* KEY_EN_POUND = "Key: #"; +const char* KEY_EN_ANSI_ENTER = "Key: Enter"; +const char* KEY_EN_ISO_ENTER = "Key: Enter (ISO)"; -const char* KEY_EN_LEFT_SHIFT = "Key: Left Shift"; -const char* KEY_EN_ISO_BACK_SLASH = "Key: \\ (ISO)"; -const char* KEY_EN_Z = "Key: Z"; -const char* KEY_EN_X = "Key: X"; -const char* KEY_EN_C = "Key: C"; -const char* KEY_EN_V = "Key: V"; -const char* KEY_EN_B = "Key: B"; -const char* KEY_EN_N = "Key: N"; -const char* KEY_EN_M = "Key: M"; -const char* KEY_EN_COMMA = "Key: ,"; -const char* KEY_EN_PERIOD = "Key: ."; -const char* KEY_EN_FORWARD_SLASH = "Key: /"; -const char* KEY_EN_RIGHT_SHIFT = "Key: Right Shift"; -const char* KEY_EN_UP_ARROW = "Key: Up Arrow"; +const char* KEY_EN_LEFT_SHIFT = "Key: Left Shift"; +const char* KEY_EN_ISO_BACK_SLASH = "Key: \\ (ISO)"; +const char* KEY_EN_Z = "Key: Z"; +const char* KEY_EN_X = "Key: X"; +const char* KEY_EN_C = "Key: C"; +const char* KEY_EN_V = "Key: V"; +const char* KEY_EN_B = "Key: B"; +const char* KEY_EN_N = "Key: N"; +const char* KEY_EN_M = "Key: M"; +const char* KEY_EN_COMMA = "Key: ,"; +const char* KEY_EN_PERIOD = "Key: ."; +const char* KEY_EN_FORWARD_SLASH = "Key: /"; +const char* KEY_EN_RIGHT_SHIFT = "Key: Right Shift"; +const char* KEY_EN_UP_ARROW = "Key: Up Arrow"; -const char* KEY_EN_LEFT_CONTROL = "Key: Left Control"; -const char* KEY_EN_LEFT_WINDOWS = "Key: Left Windows"; -const char* KEY_EN_LEFT_FUNCTION = "Key: Left Fn"; -const char* KEY_EN_LEFT_ALT = "Key: Left Alt"; -const char* KEY_EN_SPACE = "Key: Space"; -const char* KEY_EN_RIGHT_ALT = "Key: Right Alt"; -const char* KEY_EN_RIGHT_FUNCTION = "Key: Right Fn"; -const char* KEY_EN_RIGHT_WINDOWS = "Key: Right Windows"; -const char* KEY_EN_MENU = "Key: Menu"; -const char* KEY_EN_RIGHT_CONTROL = "Key: Right Control"; -const char* KEY_EN_LEFT_ARROW = "Key: Left Arrow"; -const char* KEY_EN_DOWN_ARROW = "Key: Down Arrow"; -const char* KEY_EN_RIGHT_ARROW = "Key: Right Arrow"; +const char* KEY_EN_LEFT_CONTROL = "Key: Left Control"; +const char* KEY_EN_LEFT_WINDOWS = "Key: Left Windows"; +const char* KEY_EN_LEFT_FUNCTION = "Key: Left Fn"; +const char* KEY_EN_LEFT_ALT = "Key: Left Alt"; +const char* KEY_EN_SPACE = "Key: Space"; +const char* KEY_EN_RIGHT_ALT = "Key: Right Alt"; +const char* KEY_EN_RIGHT_FUNCTION = "Key: Right Fn"; +const char* KEY_EN_RIGHT_WINDOWS = "Key: Right Windows"; +const char* KEY_EN_MENU = "Key: Menu"; +const char* KEY_EN_RIGHT_CONTROL = "Key: Right Control"; +const char* KEY_EN_LEFT_ARROW = "Key: Left Arrow"; +const char* KEY_EN_DOWN_ARROW = "Key: Down Arrow"; +const char* KEY_EN_RIGHT_ARROW = "Key: Right Arrow"; -const char* KEY_EN_NUMPAD_LOCK = "Key: Num Lock"; -const char* KEY_EN_NUMPAD_DIVIDE = "Key: Number Pad /"; -const char* KEY_EN_NUMPAD_TIMES = "Key: Number Pad *"; -const char* KEY_EN_NUMPAD_MINUS = "Key: Number Pad -"; -const char* KEY_EN_NUMPAD_PLUS = "Key: Number Pad +"; -const char* KEY_EN_NUMPAD_PERIOD = "Key: Number Pad ."; -const char* KEY_EN_NUMPAD_ENTER = "Key: Number Pad Enter"; -const char* KEY_EN_NUMPAD_0 = "Key: Number Pad 0"; -const char* KEY_EN_NUMPAD_1 = "Key: Number Pad 1"; -const char* KEY_EN_NUMPAD_2 = "Key: Number Pad 2"; -const char* KEY_EN_NUMPAD_3 = "Key: Number Pad 3"; -const char* KEY_EN_NUMPAD_4 = "Key: Number Pad 4"; -const char* KEY_EN_NUMPAD_5 = "Key: Number Pad 5"; -const char* KEY_EN_NUMPAD_6 = "Key: Number Pad 6"; -const char* KEY_EN_NUMPAD_7 = "Key: Number Pad 7"; -const char* KEY_EN_NUMPAD_8 = "Key: Number Pad 8"; -const char* KEY_EN_NUMPAD_9 = "Key: Number Pad 9"; +const char* KEY_EN_NUMPAD_LOCK = "Key: Num Lock"; +const char* KEY_EN_NUMPAD_DIVIDE = "Key: Number Pad /"; +const char* KEY_EN_NUMPAD_TIMES = "Key: Number Pad *"; +const char* KEY_EN_NUMPAD_MINUS = "Key: Number Pad -"; +const char* KEY_EN_NUMPAD_PLUS = "Key: Number Pad +"; +const char* KEY_EN_NUMPAD_PERIOD = "Key: Number Pad ."; +const char* KEY_EN_NUMPAD_ENTER = "Key: Number Pad Enter"; +const char* KEY_EN_NUMPAD_0 = "Key: Number Pad 0"; +const char* KEY_EN_NUMPAD_1 = "Key: Number Pad 1"; +const char* KEY_EN_NUMPAD_2 = "Key: Number Pad 2"; +const char* KEY_EN_NUMPAD_3 = "Key: Number Pad 3"; +const char* KEY_EN_NUMPAD_4 = "Key: Number Pad 4"; +const char* KEY_EN_NUMPAD_5 = "Key: Number Pad 5"; +const char* KEY_EN_NUMPAD_6 = "Key: Number Pad 6"; +const char* KEY_EN_NUMPAD_7 = "Key: Number Pad 7"; +const char* KEY_EN_NUMPAD_8 = "Key: Number Pad 8"; +const char* KEY_EN_NUMPAD_9 = "Key: Number Pad 9"; -const char* KEY_EN_MEDIA_PLAY_PAUSE = "Key: Media Play/Pause"; -const char* KEY_EN_MEDIA_PREVIOUS = "Key: Media Previous"; -const char* KEY_EN_MEDIA_NEXT = "Key: Media Next"; -const char* KEY_EN_MEDIA_STOP = "Key: Media Stop"; -const char* KEY_EN_MEDIA_MUTE = "Key: Media Mute"; -const char* KEY_EN_MEDIA_VOLUME_DOWN = "Key: Media Volume -"; -const char* KEY_EN_MEDIA_VOLUME_UP = "Key: Media Volume +"; +const char* KEY_EN_MEDIA_PLAY_PAUSE = "Key: Media Play/Pause"; +const char* KEY_EN_MEDIA_PREVIOUS = "Key: Media Previous"; +const char* KEY_EN_MEDIA_NEXT = "Key: Media Next"; +const char* KEY_EN_MEDIA_STOP = "Key: Media Stop"; +const char* KEY_EN_MEDIA_MUTE = "Key: Media Mute"; +const char* KEY_EN_MEDIA_VOLUME_DOWN = "Key: Media Volume -"; +const char* KEY_EN_MEDIA_VOLUME_UP = "Key: Media Volume +"; -const char* KEY_JP_RO = "Key: _"; -const char* KEY_JP_EJ = "Key: E/J"; -const char* KEY_JP_ZENKAKU = "Key: åŠè§’/全角"; -const char* KEY_JP_KANA = "Key: ã‹ãª"; -const char* KEY_JP_HENKAN = "Key: 変æ›"; -const char* KEY_JP_MUHENKAN = "Key: 無変æ›"; -const char* KEY_JP_YEN = "Key: Â¥"; -const char* KEY_JP_AT = "Key: @"; -const char* KEY_JP_CHEVRON = "Key: ^"; -const char* KEY_JP_COLON = "Key: :"; +const char* KEY_JP_RO = "Key: _"; +const char* KEY_JP_EJ = "Key: E/J"; +const char* KEY_JP_ZENKAKU = "Key: åŠè§’/全角"; +const char* KEY_JP_KANA = "Key: ã‹ãª"; +const char* KEY_JP_HENKAN = "Key: 変æ›"; +const char* KEY_JP_MUHENKAN = "Key: 無変æ›"; +const char* KEY_JP_YEN = "Key: Â¥"; +const char* KEY_JP_AT = "Key: @"; +const char* KEY_JP_CHEVRON = "Key: ^"; +const char* KEY_JP_COLON = "Key: :"; -const char* KEY_KR_HAN = "Key: 한/ì˜"; -const char* KEY_KR_HANJA = "Key: 한ìž"; +const char* KEY_KR_HAN = "Key: 한/ì˜"; +const char* KEY_KR_HANJA = "Key: 한ìž"; -const char* KEY_NORD_OE = "Key: Ø/Ä"; -const char* KEY_NORD_AE = "Key: Æ/Ö"; -const char* KEY_NORD_AAL = "Key: Ã…"; -const char* KEY_NORD_HALF = "Key: ½/§"; -const char* KEY_NORD_HYPHEN = "Key: -/_"; -const char* KEY_NORD_PLUS = "Key: +/?"; -const char* KEY_NORD_BACKSLASH = "Key: \\/`/´"; -const char* KEY_NORD_CHEVRON = "Key: ^/~"; -const char* KEY_NORD_QUOTE = "Key: '/*"; -const char* KEY_NORD_ANGLE_BRACKET = "Key: "; +const char* KEY_NORD_AAL = "Key: Ã…"; +const char* KEY_NORD_A_OE = "Key: Ä Ø"; +const char* KEY_NORD_O_AE = "Key: Ö Æ"; +const char* KEY_NORD_HALF = "Key: § ½"; +const char* KEY_NORD_HYPHEN = "Key: - _"; +const char* KEY_NORD_PLUS_QUESTION = "Key: + ?"; +const char* KEY_NORD_ACUTE_GRAVE = "Key: ´ `"; +const char* KEY_NORD_DOTS_CARET = "Key: ¨ ^"; +const char* KEY_NORD_QUOTE = "Key: ' *"; +const char* KEY_NORD_ANGLE_BRACKET = "Key: < >"; -const char* KEY_DE_ESZETT = "Key: ß"; -const char* KEY_DE_DIAERESIS_A = "Key: Ä"; -const char* KEY_DE_DIAERESIS_O = "Key: Ö"; -const char* KEY_DE_DIAERESIS_U = "Key: Ü"; +const char* KEY_DE_ESZETT = "Key: ß"; +const char* KEY_DE_DIAERESIS_A = "Key: Ä"; +const char* KEY_DE_DIAERESIS_O = "Key: Ö"; +const char* KEY_DE_DIAERESIS_U = "Key: Ü"; -const char* KEY_FR_SUPER_2 = "Key: ²"; -const char* KEY_FR_AMPERSAND = "Key: &"; -const char* KEY_FR_ACUTE_E = "Key: é"; -const char* KEY_FR_DOUBLEQUOTE = "Key: \""; -const char* KEY_FR_LEFT_PARENTHESIS = "Key: ("; -const char* KEY_FR_GRAVE_E = "Key: è"; -const char* KEY_FR_UNDERSCORE = "Key: _"; -const char* KEY_FR_CEDILLA_C = "Key: ç"; -const char* KEY_FR_GRAVE_A = "Key: à"; -const char* KEY_FR_RIGHT_PARENTHESIS = "Key: )"; -const char* KEY_FR_DOLLAR = "Key: $"; -const char* KEY_FR_GRAVE_U = "Key: ù"; -const char* KEY_FR_ASTERIX = "Key: *"; -const char* KEY_FR_EXCLAIMATION = "Key: !"; +const char* KEY_FR_SUPER_2 = "Key: ²"; +const char* KEY_FR_AMPERSAND = "Key: &"; +const char* KEY_FR_ACUTE_E = "Key: é"; +const char* KEY_FR_DOUBLEQUOTE = "Key: \""; +const char* KEY_FR_LEFT_PARENTHESIS = "Key: ("; +const char* KEY_FR_GRAVE_E = "Key: è"; +const char* KEY_FR_UNDERSCORE = "Key: _"; +const char* KEY_FR_CEDILLA_C = "Key: ç"; +const char* KEY_FR_GRAVE_A = "Key: à"; +const char* KEY_FR_RIGHT_PARENTHESIS = "Key: )"; +const char* KEY_FR_DOLLAR = "Key: $"; +const char* KEY_FR_GRAVE_U = "Key: ù"; +const char* KEY_FR_ASTERIX = "Key: *"; +const char* KEY_FR_EXCLAIMATION = "Key: !"; + +const char* KEY_ES_OPEN_QUESTION_MARK = "Key: ¿/¡"; +const char* KEY_ES_TILDE = "Key: ´/¨"; +const char* KEY_ES_ENIE = "Key: Ñ"; +const char* KEY_BR_TILDE = "Key: ~"; diff --git a/RGBController/RGBControllerKeyNames.h b/RGBController/RGBControllerKeyNames.h index 7cceba7d..99e61bdc 100644 --- a/RGBController/RGBControllerKeyNames.h +++ b/RGBController/RGBControllerKeyNames.h @@ -1,13 +1,14 @@ -/*-------------------------------------------------------------------*\ -| RGBControllerKeyNames.h | -| | -| This is the canonical list of Key Names to be used in | -| keyboard and other device initialisations to avoid redundant | -| string literal declarations | -| | -| Chris M (Dr_No) 25 Jan 2022 | -| | -\*-------------------------------------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBControllerKeyNames.h | +| | +| List of standardized names to represent keyboard keys | +| when naming LEDs on keyboard devices | +| | +| Chris M (Dr_No) 25 Jan 2022 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once @@ -155,14 +156,14 @@ extern const char* KEY_JP_COLON; extern const char* KEY_KR_HAN; extern const char* KEY_KR_HANJA; -extern const char* KEY_NORD_OE; -extern const char* KEY_NORD_AE; extern const char* KEY_NORD_AAL; +extern const char* KEY_NORD_A_OE; +extern const char* KEY_NORD_O_AE; extern const char* KEY_NORD_HALF; extern const char* KEY_NORD_HYPHEN; -extern const char* KEY_NORD_PLUS; -extern const char* KEY_NORD_BACKSLASH; -extern const char* KEY_NORD_CHEVRON; +extern const char* KEY_NORD_PLUS_QUESTION; +extern const char* KEY_NORD_ACUTE_GRAVE; +extern const char* KEY_NORD_DOTS_CARET; extern const char* KEY_NORD_QUOTE; extern const char* KEY_NORD_ANGLE_BRACKET; @@ -185,3 +186,8 @@ extern const char* KEY_FR_DOLLAR; extern const char* KEY_FR_GRAVE_U; extern const char* KEY_FR_ASTERIX; extern const char* KEY_FR_EXCLAIMATION; + +extern const char* KEY_ES_OPEN_QUESTION_MARK; +extern const char* KEY_ES_TILDE; +extern const char* KEY_ES_ENIE; +extern const char* KEY_BR_TILDE; diff --git a/RGBController/RGBController_Dummy.cpp b/RGBController/RGBController_Dummy.cpp index c3cbb323..1f25c620 100644 --- a/RGBController/RGBController_Dummy.cpp +++ b/RGBController/RGBController_Dummy.cpp @@ -1,10 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_Dummy.cpp | -| | -| Generic RGB Interface Dummy Class | -| | -| Adam Honse (CalcProgrammer1) 2/25/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Dummy.cpp | +| | +| Dummy RGBController that can mimic various devices for | +| development and test purposes | +| | +| Adam Honse (CalcProgrammer1) 25 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include "RGBController_Dummy.h" diff --git a/RGBController/RGBController_Dummy.h b/RGBController/RGBController_Dummy.h index 125a3262..cc766e13 100644 --- a/RGBController/RGBController_Dummy.h +++ b/RGBController/RGBController_Dummy.h @@ -1,10 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_Dummy.h | -| | -| Generic RGB Interface Dummy Class | -| | -| Adam Honse (CalcProgrammer1) 2/25/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Dummy.h | +| | +| Dummy RGBController that can mimic various devices for | +| development and test purposes | +| | +| Adam Honse (CalcProgrammer1) 25 Feb 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once diff --git a/RGBController/RGBController_Network.cpp b/RGBController/RGBController_Network.cpp index dab43ff5..a29fb231 100644 --- a/RGBController/RGBController_Network.cpp +++ b/RGBController/RGBController_Network.cpp @@ -1,10 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_Network.cpp | -| | -| Generic RGB Interface Network Class | -| | -| Adam Honse (CalcProgrammer1) 4/11/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Network.cpp | +| | +| RGBController implementation that represents a remote | +| RGBController instance from a connected OpenRGB server | +| | +| Adam Honse (CalcProgrammer1) 11 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include @@ -21,6 +25,29 @@ void RGBController_Network::SetupZones() //Don't send anything, this function should only process on host } +void RGBController_Network::ClearSegments(int zone) +{ + client->SendRequest_RGBController_ClearSegments(dev_idx, zone); + + client->SendRequest_ControllerData(dev_idx); + client->WaitOnControllerData(); +} + +void RGBController_Network::AddSegment(int zone, segment new_segment) +{ + unsigned char * data = GetSegmentDescription(zone, new_segment); + unsigned int size; + + memcpy(&size, &data[0], sizeof(unsigned int)); + + client->SendRequest_RGBController_AddSegment(dev_idx, data, size); + + delete[] data; + + client->SendRequest_ControllerData(dev_idx); + client->WaitOnControllerData(); +} + void RGBController_Network::ResizeZone(int zone, int new_size) { client->SendRequest_RGBController_ResizeZone(dev_idx, zone, new_size); diff --git a/RGBController/RGBController_Network.h b/RGBController/RGBController_Network.h index 47edff2d..d7948d52 100644 --- a/RGBController/RGBController_Network.h +++ b/RGBController/RGBController_Network.h @@ -1,10 +1,14 @@ -/*-----------------------------------------*\ -| RGBController_Network.h | -| | -| Generic RGB Interface Network Class | -| | -| Adam Honse (CalcProgrammer1) 4/11/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| RGBController_Network.h | +| | +| RGBController implementation that represents a remote | +| RGBController instance from a connected OpenRGB server | +| | +| Adam Honse (CalcProgrammer1) 11 Apr 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once @@ -18,6 +22,8 @@ public: void SetupZones(); + void ClearSegments(int zone); + void AddSegment(int zone, segment new_segment); void ResizeZone(int zone, int new_size); void DeviceUpdateLEDs(); diff --git a/ResourceManager.cpp b/ResourceManager.cpp index 6df9efa1..1238fd06 100644 --- a/ResourceManager.cpp +++ b/ResourceManager.cpp @@ -1,19 +1,15 @@ -/*-----------------------------------------*\ -| ResourceManager.cpp | -| | -| OpenRGB Resource Manager controls access | -| to application components including | -| RGBControllers, I2C interfaces, and | -| network SDK components | -| | -| Adam Honse (CalcProgrammer1) 9/27/2020 | -\*-----------------------------------------*/ - -#include "ResourceManager.h" -#include "ProfileManager.h" -#include "LogManager.h" -#include "filesystem.h" -#include "StringUtils.h" +/*---------------------------------------------------------*\ +| ResourceManager.cpp | +| | +| OpenRGB Resource Manager controls access to application | +| components including RGBControllers, I2C interfaces, | +| and network SDK components | +| | +| Adam Honse (CalcProgrammer1) 27 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #ifdef _WIN32 #include @@ -22,7 +18,53 @@ #include #include -#include +#include +#include "cli.h" +#include "pci_ids/pci_ids.h" +#include "ResourceManager.h" +#include "ProfileManager.h" +#include "LogManager.h" +#include "SettingsManager.h" +#include "NetworkClient.h" +#include "NetworkServer.h" +#include "filesystem.h" +#include "StringUtils.h" + +/*---------------------------------------------------------*\ +| Translation Strings | +\*---------------------------------------------------------*/ +const char* I2C_ERR_WIN = QT_TRANSLATE_NOOP("ResourceManager", + "

Some internal devices may not be detected:

" + "

One or more I2C or SMBus interfaces failed to initialize.

" + "

RGB DRAM modules, some motherboards' onboard RGB lighting, and RGB Graphics Cards, will not be available in OpenRGB without I2C or SMBus.

" + "

How to fix this:

" + "

On Windows, this is usually caused by a failure to load the WinRing0 driver.

" + "

You must run OpenRGB as administrator at least once to allow WinRing0 to set up.

" + "

See help.openrgb.org for additional troubleshooting steps if you keep seeing this message.

" + "

If you are not using internal RGB on a desktop this message is not important to you.

"); +const char* I2C_ERR_LINUX = QT_TRANSLATE_NOOP("ResourceManager", + "

Some internal devices may not be detected:

" + "

One or more I2C or SMBus interfaces failed to initialize.

" + "

RGB DRAM modules, some motherboards' onboard RGB lighting, and RGB Graphics Cards, will not be available in OpenRGB without I2C or SMBus.

" + "

How to fix this:

" + "

On Linux, this is usually because the i2c-dev module is not loaded.

" + "

You must load the i2c-dev module along with the correct i2c driver for your motherboard. " + "This is usually i2c-piix4 for AMD systems and i2c-i801 for Intel systems.

" + "

See help.openrgb.org for additional troubleshooting steps if you keep seeing this message.

" + "

If you are not using internal RGB on a desktop this message is not important to you.

"); + +const char* UDEV_MISSING = QT_TRANSLATE_NOOP("ResourceManager", + "

WARNING:

" + "

The OpenRGB udev rules are not installed.

" + "

Most devices will not be available unless running OpenRGB as root.

" + "

If using AppImage, Flatpak, or self-compiled versions of OpenRGB you must install the udev rules manually

" + "

See https://openrgb.org/udev to install the udev rules manually

"); +const char* UDEV_MUTLI = QT_TRANSLATE_NOOP("ResourceManager", + "

WARNING:

" + "

Multiple OpenRGB udev rules are installed.

" + "

The udev rules file 60-openrgb.rules is installed in both /etc/udev/rules.d and /usr/lib/udev/rules.d.

" + "

Multiple udev rules files can conflict, it is recommended to remove one of them.

"); + const hidapi_wrapper default_wrapper = { @@ -37,6 +79,24 @@ const hidapi_wrapper default_wrapper = (hidapi_wrapper_error) hid_error }; +bool BasicHIDBlock::compare(hid_device_info* info) +{ + return ( (vid == info->vendor_id) + && (pid == info->product_id) +#ifdef USE_HID_USAGE + && ( (usage_page == HID_USAGE_PAGE_ANY) + || (usage_page == info->usage_page) ) + && ( (usage == HID_USAGE_ANY) + || (usage == info->usage) ) + && ( (interface == HID_INTERFACE_ANY) + || (interface == info->interface_number ) ) +#else + && ( (interface == HID_INTERFACE_ANY) + || (interface == info->interface_number ) ) +#endif + ); +} + ResourceManager* ResourceManager::instance; using namespace std::chrono_literals; @@ -53,37 +113,48 @@ ResourceManager *ResourceManager::get() ResourceManager::ResourceManager() { - /*-------------------------------------------------------------------------*\ - | Initialize Detection Variables | - \*-------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Initialize Detection Variables | + \*-----------------------------------------------------*/ + auto_connection_client = NULL; + auto_connection_active = false; detection_enabled = true; detection_percent = 100; detection_string = ""; detection_is_required = false; - DetectDevicesThread = nullptr; dynamic_detectors_processed = false; + init_finished = false; + background_thread_running = true; + + /*-----------------------------------------------------*\ + | Start the background detection thread in advance; it | + | will be suspended until necessary | + \*-----------------------------------------------------*/ + DetectDevicesThread = new std::thread(&ResourceManager::BackgroundThreadFunction, this); SetupConfigurationDirectory(); - /*-------------------------------------------------------------------------*\ - | Load settings from file | - \*-------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Load settings from file | + \*-----------------------------------------------------*/ settings_manager = new SettingsManager(); settings_manager->LoadSettings(GetConfigurationDirectory() / "OpenRGB.json"); - /*-------------------------------------------------------------------------*\ - | Configure the log manager | - \*-------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Configure the log manager | + \*-----------------------------------------------------*/ LogManager::get()->configure(settings_manager->GetSettings("LogManager"), GetConfigurationDirectory()); - /*-------------------------------------------------------------------------*\ - | Initialize Server Instance | - | If configured, pass through full controller list including clients | - | Otherwise, pass only local hardware controllers | - \*-------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Initialize Server Instance | + | If configured, pass through full controller list | + | including clients. Otherwise, pass only local | + | hardware controllers | + \*-----------------------------------------------------*/ json server_settings = settings_manager->GetSettings("Server"); bool all_controllers = false; + bool legacy_workaround = false; if(server_settings.contains("all_controllers")) { @@ -99,45 +170,22 @@ ResourceManager::ResourceManager() server = new NetworkServer(rgb_controllers_hw); } - /*-------------------------------------------------------------------------*\ - | Initialize Saved Client Connections | - \*-------------------------------------------------------------------------*/ - json client_settings = settings_manager->GetSettings("Client"); - - if(client_settings.contains("clients")) + /*-----------------------------------------------------*\ + | Enable legacy SDK workaround in server if configured | + \*-----------------------------------------------------*/ + if(server_settings.contains("legacy_workaround")) { - for(unsigned int client_idx = 0; client_idx < client_settings["clients"].size(); client_idx++) - { - NetworkClient * client = new NetworkClient(rgb_controllers); - - std::string titleString = "OpenRGB "; - titleString.append(VERSION_STRING); - - std::string client_ip = client_settings["clients"][client_idx]["ip"]; - unsigned short client_port = client_settings["clients"][client_idx]["port"]; - - client->SetIP(client_ip.c_str()); - client->SetName(titleString.c_str()); - client->SetPort(client_port); - - client->StartClient(); - - for(int timeout = 0; timeout < 100; timeout++) - { - if(client->GetConnected()) - { - break; - } - std::this_thread::sleep_for(10ms); - } - - clients.push_back(client); - } + legacy_workaround = server_settings["legacy_workaround"]; } - /*-------------------------------------------------------------------------*\ - | Load sizes list from file | - \*-------------------------------------------------------------------------*/ + if(legacy_workaround) + { + server->SetLegacyWorkaroundEnable(true); + } + + /*-----------------------------------------------------*\ + | Load sizes list from file | + \*-----------------------------------------------------*/ profile_manager = new ProfileManager(GetConfigurationDirectory()); server->SetProfileManager(profile_manager); rgb_controllers_sizes = profile_manager->LoadProfileToList("sizes", true); @@ -146,11 +194,28 @@ ResourceManager::ResourceManager() ResourceManager::~ResourceManager() { Cleanup(); + + /*-----------------------------------------------------*\ + | Mark the background detection thread as not running | + | and then wake it up so it knows that it has to stop | + \*-----------------------------------------------------*/ + background_thread_running = false; + BackgroundFunctionStartTrigger.notify_one(); + + /*-----------------------------------------------------*\ + | Stop the background thread | + \*-----------------------------------------------------*/ + if(DetectDevicesThread) + { + DetectDevicesThread->join(); + delete DetectDevicesThread; + DetectDevicesThread = nullptr; + } } void ResourceManager::RegisterI2CBus(i2c_smbus_interface *bus) { - LOG_INFO("Registering I2C interface: %s Device %04X:%04X Subsystem: %04X:%04X", bus->device_name, bus->pci_vendor, bus->pci_device,bus->pci_subsystem_vendor,bus->pci_subsystem_device); + LOG_INFO("[ResourceManager] Registering I2C interface: %s Device %04X:%04X Subsystem: %04X:%04X", bus->device_name, bus->pci_vendor, bus->pci_device,bus->pci_subsystem_vendor,bus->pci_subsystem_device); busses.push_back(bus); } @@ -161,18 +226,24 @@ std::vector & ResourceManager::GetI2CBusses() void ResourceManager::RegisterRGBController(RGBController *rgb_controller) { - LOG_INFO("[%s] Registering RGB controller", rgb_controller->name.c_str()); + /*-----------------------------------------------------*\ + | Mark this controller as locally owned | + \*-----------------------------------------------------*/ + rgb_controller->flags &= ~CONTROLLER_FLAG_REMOTE; + rgb_controller->flags |= CONTROLLER_FLAG_LOCAL; + + LOG_INFO("[%s] Registering RGB controller", rgb_controller->GetName().c_str()); rgb_controllers_hw.push_back(rgb_controller); - /*-------------------------------------------------*\ - | If the device list size has changed, call the | - | device list changed callbacks | - | | - | TODO: If all detection is reworked to use | - | RegisterRGBController, tracking of previous list | - | size can be removed and profile can be loaded per | - | controller before adding to list | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | If the device list size has changed, call the device | + | list changed callbacks | + | | + | TODO: If all detection is reworked to use | + | RegisterRGBController, tracking of previous list size | + | can be removed and profile can be loaded per | + | controller before adding to list | + \*-----------------------------------------------------*/ if(rgb_controllers_hw.size() != detection_prev_size) { /*-------------------------------------------------*\ @@ -185,23 +256,25 @@ void ResourceManager::RegisterRGBController(RGBController *rgb_controller) UpdateDeviceList(); } - detection_prev_size = rgb_controllers_hw.size(); + + detection_prev_size = (unsigned int)rgb_controllers_hw.size(); UpdateDeviceList(); } void ResourceManager::UnregisterRGBController(RGBController* rgb_controller) { - LOG_INFO("[%s] Unregistering RGB controller", rgb_controller->name.c_str()); + LOG_INFO("[%s] Unregistering RGB controller", rgb_controller->GetName().c_str()); - /*-------------------------------------------------------------------------*\ - | Clear callbacks from the controller before removal | - \*-------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Clear callbacks from the controller before removal | + \*-----------------------------------------------------*/ rgb_controller->ClearCallbacks(); - /*-------------------------------------------------------------------------*\ - | Find the controller to remove and remove it from the hardware list | - \*-------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Find the controller to remove and remove it from the | + | hardware list | + \*-----------------------------------------------------*/ std::vector::iterator hw_it = std::find(rgb_controllers_hw.begin(), rgb_controllers_hw.end(), rgb_controller); if (hw_it != rgb_controllers_hw.end()) @@ -209,9 +282,10 @@ void ResourceManager::UnregisterRGBController(RGBController* rgb_controller) rgb_controllers_hw.erase(hw_it); } - /*-------------------------------------------------------------------------*\ - | Find the controller to remove and remove it from the master list | - \*-------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Find the controller to remove and remove it from the | + | master list | + \*-----------------------------------------------------*/ std::vector::iterator rgb_it = std::find(rgb_controllers.begin(), rgb_controllers.end(), rgb_controller); if (rgb_it != rgb_controllers.end()) @@ -238,6 +312,18 @@ void ResourceManager::RegisterI2CDeviceDetector(std::string name, I2CDeviceDetec i2c_device_detectors.push_back(detector); } +void ResourceManager::RegisterI2CDIMMDeviceDetector(std::string name, I2CDIMMDeviceDetectorFunction detector, uint16_t jedec_id, uint8_t dimm_type) +{ + I2CDIMMDeviceDetectorBlock block; + + block.name = name; + block.function = detector; + block.jedec_id = jedec_id; + block.dimm_type = dimm_type; + + i2c_dimm_device_detectors.push_back(block); +} + void ResourceManager::RegisterI2CPCIDeviceDetector(std::string name, I2CPCIDeviceDetectorFunction detector, uint16_t ven_id, uint16_t dev_id, uint16_t subven_id, uint16_t subdev_id, uint8_t i2c_addr) { I2CPCIDeviceDetectorBlock block; @@ -270,7 +356,8 @@ void ResourceManager::RegisterHIDDeviceDetector(std::string name, HIDDeviceDetectorBlock block; block.name = name; - block.address = (vid << 16) | pid; + block.vid = vid; + block.pid = pid; block.function = detector; block.interface = interface; block.usage_page = usage_page; @@ -290,7 +377,8 @@ void ResourceManager::RegisterHIDWrappedDeviceDetector(std::string name, HIDWrappedDeviceDetectorBlock block; block.name = name; - block.address = (vid << 16) | pid; + block.vid = vid; + block.pid = pid; block.function = detector; block.interface = interface; block.usage_page = usage_page; @@ -310,6 +398,28 @@ void ResourceManager::RegisterPreDetectionHook(PreDetectionHookFunction hook) pre_detection_hooks.push_back(hook); } +void ResourceManager::RegisterClientInfoChangeCallback(ClientInfoChangeCallback new_callback, void * new_callback_arg) +{ + ClientInfoChangeCallbacks.push_back(new_callback); + ClientInfoChangeCallbackArgs.push_back(new_callback_arg); + + LOG_TRACE("[ResourceManager] Registered client info change callback. Total callbacks registered: %d", ClientInfoChangeCallbacks.size()); +} + +void ResourceManager::UnregisterClientInfoChangeCallback(ClientInfoChangeCallback callback, void * callback_arg) +{ + for(size_t idx = 0; idx < ClientInfoChangeCallbacks.size(); idx++) + { + if(ClientInfoChangeCallbacks[idx] == callback && ClientInfoChangeCallbackArgs[idx] == callback_arg) + { + ClientInfoChangeCallbacks.erase(ClientInfoChangeCallbacks.begin() + idx); + ClientInfoChangeCallbackArgs.erase(ClientInfoChangeCallbackArgs.begin() + idx); + } + } + + LOG_TRACE("[ResourceManager] Unregistered client info change callback. Total callbacks registered: %d", ClientInfoChangeCallbacks.size()); +} + void ResourceManager::RegisterDeviceListChangeCallback(DeviceListChangeCallback new_callback, void * new_callback_arg) { DeviceListChangeCallbacks.push_back(new_callback); @@ -412,9 +522,9 @@ void ResourceManager::UpdateDeviceList() { DeviceListChangeMutex.lock(); - /*-------------------------------------------------*\ - | Insert hardware controllers into controller list | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Insert hardware controllers into controller list | + \*-----------------------------------------------------*/ for(unsigned int hw_controller_idx = 0; hw_controller_idx < rgb_controllers_hw.size(); hw_controller_idx++) { /*-------------------------------------------------*\ @@ -449,28 +559,41 @@ void ResourceManager::UpdateDeviceList() rgb_controllers.insert(rgb_controllers.begin() + hw_controller_idx, rgb_controllers_hw[hw_controller_idx]); } - /*-------------------------------------------------*\ - | Device list has changed, call the callbacks | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Device list has changed, call the callbacks | + \*-----------------------------------------------------*/ DeviceListChanged(); - /*-------------------------------------------------*\ - | Device list has changed, inform all clients | - | connected to this server | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Device list has changed, inform all clients connected | + | to this server | + \*-----------------------------------------------------*/ server->DeviceListChanged(); DeviceListChangeMutex.unlock(); } +void ResourceManager::ClientInfoChanged() +{ + /*-----------------------------------------------------*\ + | Client info has changed, call the callbacks | + \*-----------------------------------------------------*/ + LOG_TRACE("[ResourceManager] Calling client info change callbacks."); + + for(std::size_t callback_idx = 0; callback_idx < ClientInfoChangeCallbacks.size(); callback_idx++) + { + ResourceManager::ClientInfoChangeCallbacks[callback_idx](ClientInfoChangeCallbackArgs[callback_idx]); + } +} + void ResourceManager::DeviceListChanged() { - /*-------------------------------------------------*\ - | Device list has changed, call the callbacks | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Device list has changed, call the callbacks | + \*-----------------------------------------------------*/ LOG_TRACE("[ResourceManager] Calling device list change callbacks."); - for(unsigned int callback_idx = 0; callback_idx < DeviceListChangeCallbacks.size(); callback_idx++) + for(std::size_t callback_idx = 0; callback_idx < DeviceListChangeCallbacks.size(); callback_idx++) { ResourceManager::DeviceListChangeCallbacks[callback_idx](DeviceListChangeCallbackArgs[callback_idx]); } @@ -480,12 +603,12 @@ void ResourceManager::DetectionProgressChanged() { DetectionProgressMutex.lock(); - /*-------------------------------------------------*\ - | Detection progress has changed, call the callbacks| - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Detection progress has changed, call the callbacks | + \*-----------------------------------------------------*/ LOG_TRACE("[ResourceManager] Calling detection progress callbacks."); - for(unsigned int callback_idx = 0; callback_idx < DetectionProgressCallbacks.size(); callback_idx++) + for(std::size_t callback_idx = 0; callback_idx < (unsigned int)DetectionProgressCallbacks.size(); callback_idx++) { DetectionProgressCallbacks[callback_idx](DetectionProgressCallbackArgs[callback_idx]); } @@ -497,10 +620,10 @@ void ResourceManager::I2CBusListChanged() { I2CBusListChangeMutex.lock(); - /*-------------------------------------------------*\ - | Detection progress has changed, call the callbacks| - \*-------------------------------------------------*/ - for(unsigned int callback_idx = 0; callback_idx < I2CBusListChangeCallbacks.size(); callback_idx++) + /*-----------------------------------------------------*\ + | Detection progress has changed, call the callbacks | + \*-----------------------------------------------------*/ + for(std::size_t callback_idx = 0; callback_idx < (unsigned int)I2CBusListChangeCallbacks.size(); callback_idx++) { I2CBusListChangeCallbacks[callback_idx](I2CBusListChangeCallbackArgs[callback_idx]); } @@ -543,9 +666,10 @@ void ResourceManager::SetupConfigurationDirectory() { config_dir.append("OpenRGB"); - /*-------------------------------------------------------------------------*\ - | Create OpenRGB configuration directory if it doesn't exist | - \*-------------------------------------------------------------------------*/ + /*-------------------------------------------------*\ + | Create OpenRGB configuration directory if it | + | doesn't exist | + \*-------------------------------------------------*/ filesystem::create_directories(config_dir); } else @@ -578,6 +702,7 @@ static void NetworkClientInfoChangeCallback(void* this_ptr) { ResourceManager* this_obj = (ResourceManager*)this_ptr; + this_obj->ClientInfoChanged(); this_obj->DeviceListChanged(); } @@ -590,19 +715,20 @@ void ResourceManager::RegisterNetworkClient(NetworkClient* new_client) void ResourceManager::UnregisterNetworkClient(NetworkClient* network_client) { - /*-------------------------------------------------------------------------*\ - | Stop the disconnecting client | - \*-------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Stop the disconnecting client | + \*-----------------------------------------------------*/ network_client->StopClient(); - /*-------------------------------------------------------------------------*\ - | Clear callbacks from the client before removal | - \*-------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Clear callbacks from the client before removal | + \*-----------------------------------------------------*/ network_client->ClearCallbacks(); - /*-------------------------------------------------------------------------*\ - | Find the client to remove and remove it from the clients list | - \*-------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Find the client to remove and remove it from the | + | clients list | + \*-----------------------------------------------------*/ std::vector::iterator client_it = std::find(clients.begin(), clients.end(), network_client); if(client_it != clients.end()) @@ -610,14 +736,84 @@ void ResourceManager::UnregisterNetworkClient(NetworkClient* network_client) clients.erase(client_it); } - /*-------------------------------------------------------------------------*\ - | Delete the client | - \*-------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Delete the client | + \*-----------------------------------------------------*/ delete network_client; UpdateDeviceList(); } + +/******************************************************************************************\ +* * +* AttemptLocalConnection * +* * +* Attempts an SDK connection to the local server. Returns true if success * +* * +\******************************************************************************************/ + +bool ResourceManager::AttemptLocalConnection() +{ + detection_percent = 0; + detection_string = "Attempting local server connection..."; + DetectionProgressChanged(); + + LOG_DEBUG("[ResourceManager] Attempting local server connection..."); + + bool success = false; + + auto_connection_client = new NetworkClient(ResourceManager::get()->GetRGBControllers()); + + std::string titleString = "OpenRGB "; + titleString.append(VERSION_STRING); + + auto_connection_client->SetName(titleString.c_str()); + auto_connection_client->StartClient(); + + for(int timeout = 0; timeout < 10; timeout++) + { + if(auto_connection_client->GetConnected()) + { + break; + } + std::this_thread::sleep_for(5ms); + } + + if(!auto_connection_client->GetConnected()) + { + LOG_TRACE("[ResourceManager] Client failed to connect"); + auto_connection_client->StopClient(); + LOG_TRACE("[ResourceManager] Client stopped"); + + delete auto_connection_client; + + auto_connection_client = NULL; + } + else + { + ResourceManager::get()->RegisterNetworkClient(auto_connection_client); + LOG_TRACE("[ResourceManager] Registered network client"); + + success = true; + + /*-------------------------------------------------*\ + | Wait up to 5 seconds for the client connection to | + | retrieve all controllers | + \*-------------------------------------------------*/ + for(int timeout = 0; timeout < 1000; timeout++) + { + if(auto_connection_client->GetOnline()) + { + break; + } + std::this_thread::sleep_for(5ms); + } + } + + return success; +} + std::vector& ResourceManager::GetClients() { return(clients); @@ -654,9 +850,9 @@ void ResourceManager::Cleanup() std::vector rgb_controllers_hw_copy = rgb_controllers_hw; - for(unsigned int hw_controller_idx = 0; hw_controller_idx < rgb_controllers_hw.size(); hw_controller_idx++) + for(std::size_t hw_controller_idx = 0; hw_controller_idx < rgb_controllers_hw.size(); hw_controller_idx++) { - for(unsigned int controller_idx = 0; controller_idx < rgb_controllers.size(); controller_idx++) + for(std::size_t controller_idx = 0; controller_idx < rgb_controllers.size(); controller_idx++) { if(rgb_controllers[controller_idx] == rgb_controllers_hw[hw_controller_idx]) { @@ -666,10 +862,10 @@ void ResourceManager::Cleanup() } } - /*-------------------------------------------------*\ - | Clear the hardware controllers list and set the | - | previous hardware controllers list size to zero | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Clear the hardware controllers list and set the | + | previous hardware controllers list size to zero | + \*-----------------------------------------------------*/ rgb_controllers_hw.clear(); detection_prev_size = 0; @@ -687,24 +883,12 @@ void ResourceManager::Cleanup() delete bus; } - /*-------------------------------------------------*\ - | Cleanup HID interface | - \*-------------------------------------------------*/ - int hid_status = hid_exit(); - - LOG_DEBUG("Closing HID interfaces: %s", ((hid_status == 0) ? "Success" : "Failed")); - - if(DetectDevicesThread) - { - DetectDevicesThread->join(); - delete DetectDevicesThread; - DetectDevicesThread = nullptr; - } + RunInBackgroundThread(std::bind(&ResourceManager::HidExitCoroutine, this)); } void ResourceManager::ProcessPreDetectionHooks() { - for(unsigned int hook_idx = 0; hook_idx < pre_detection_hooks.size(); hook_idx++) + for(std::size_t hook_idx = 0; hook_idx < pre_detection_hooks.size(); hook_idx++) { pre_detection_hooks[hook_idx](); } @@ -712,7 +896,7 @@ void ResourceManager::ProcessPreDetectionHooks() void ResourceManager::ProcessDynamicDetectors() { - for(unsigned int detector_idx = 0; detector_idx < dynamic_detectors.size(); detector_idx++) + for(std::size_t detector_idx = 0; detector_idx < dynamic_detectors.size(); detector_idx++) { dynamic_detectors[detector_idx](); } @@ -720,7 +904,12 @@ void ResourceManager::ProcessDynamicDetectors() dynamic_detectors_processed = true; } -void ResourceManager::DetectDevices() +/*---------------------------------------------------------*\ +| Handle ALL pre-detection routines | +| The system should be ready to start a detection thread | +| (returns false if detection can not proceed) | +\*---------------------------------------------------------*/ +bool ResourceManager::ProcessPreDetection() { /*-----------------------------------------------------*\ | Process pre-detection hooks | @@ -740,7 +929,7 @@ void ResourceManager::DetectDevices() \*-----------------------------------------------------*/ LOG_TRACE("[ResourceManager] Calling detection start callbacks."); - for(unsigned int callback_idx = 0; callback_idx < DetectionStartCallbacks.size(); callback_idx++) + for(std::size_t callback_idx = 0; callback_idx < DetectionStartCallbacks.size(); callback_idx++) { DetectionStartCallbacks[callback_idx](DetectionStartCallbackArgs[callback_idx]); } @@ -749,7 +938,6 @@ void ResourceManager::DetectDevices() | Update the detector settings | \*-----------------------------------------------------*/ UpdateDetectorSettings(); - if(detection_enabled) { /*-------------------------------------------------*\ @@ -757,7 +945,7 @@ void ResourceManager::DetectDevices() \*-------------------------------------------------*/ if(detection_is_required.load()) { - return; + return false; } /*-------------------------------------------------*\ @@ -774,33 +962,88 @@ void ResourceManager::DetectDevices() UpdateDeviceList(); /*-------------------------------------------------*\ - | Start the device detection thread | + | Initialize HID interface for detection | + \*-------------------------------------------------*/ + int hid_status = hid_init(); + + LOG_INFO("[ResourceManager] Initializing HID interfaces: %s", ((hid_status == 0) ? "Success" : "Failed")); + + /*-------------------------------------------------*\ + | Mark the detection as ongoing | + | So the detection thread may proceed | \*-------------------------------------------------*/ detection_is_required = true; - DetectDevicesThread = new std::thread(&ResourceManager::DetectDevicesThreadFunction, this); - /*-------------------------------------------------*\ - | Release the current thread to allow detection | - | thread to start | - \*-------------------------------------------------*/ - std::this_thread::sleep_for(1ms); + return true; } - else + return false; +} + +void ResourceManager::DetectDevices() +{ + if(ProcessPreDetection()) { - /*-------------------------------------------------*\ - | Signal that detection is complete | - \*-------------------------------------------------*/ - detection_percent = 100; - DetectionProgressChanged(); - - /*-----------------------------------------------------*\ - | Call detection end callbacks | - \*-----------------------------------------------------*/ - for(unsigned int callback_idx = 0; callback_idx < DetectionEndCallbacks.size(); callback_idx++) - { - DetectionEndCallbacks[callback_idx](DetectionEndCallbackArgs[callback_idx]); - } + // Run the detection coroutine + RunInBackgroundThread(std::bind(&ResourceManager::DetectDevicesCoroutine, this)); } + + if(!detection_enabled) + { + ProcessPostDetection(); + } +} + +void ResourceManager::RescanDevices() +{ + /*-----------------------------------------------------*\ + | If automatic local connection is active, the primary | + | instance is the local server, so send rescan requests | + | to the automatic local connection client | + \*-----------------------------------------------------*/ + if(auto_connection_active && auto_connection_client != NULL) + { + auto_connection_client->SendRequest_RescanDevices(); + } + + /*-----------------------------------------------------*\ + | If detection is disabled and there is exactly one | + | client, the primary instance is the connected server, | + | so send rescan requests to the first (and only) | + | client | + \*-----------------------------------------------------*/ + else if(!detection_enabled && clients.size() == 1) + { + clients[0]->SendRequest_RescanDevices(); + } + + /*-----------------------------------------------------*\ + | Perform local rescan | + \*-----------------------------------------------------*/ + DetectDevices(); +} + +void ResourceManager::ProcessPostDetection() +{ + /*-----------------------------------------------------*\ + | Signal that detection is complete | + \*-----------------------------------------------------*/ + detection_percent = 100; + DetectionProgressChanged(); + + LOG_INFO("[ResourceManager] Calling Post-detection callbacks"); + /*-----------------------------------------------------*\ + | Call detection end callbacks | + \*-----------------------------------------------------*/ + for(std::size_t callback_idx = 0; callback_idx < DetectionEndCallbacks.size(); callback_idx++) + { + DetectionEndCallbacks[callback_idx](DetectionEndCallbackArgs[callback_idx]); + } + + detection_is_required = false; + + LOG_INFO("------------------------------------------------------"); + LOG_INFO("| Detection completed |"); + LOG_INFO("------------------------------------------------------"); } void ResourceManager::DisableDetection() @@ -808,7 +1051,7 @@ void ResourceManager::DisableDetection() detection_enabled = false; } -void ResourceManager::DetectDevicesThreadFunction() +void ResourceManager::DetectDevicesCoroutine() { DetectDeviceMutex.lock(); @@ -824,45 +1067,38 @@ void ResourceManager::DetectDevicesThreadFunction() LOG_INFO("| Start device detection |"); LOG_INFO("------------------------------------------------------"); - /*-------------------------------------------------*\ - | Reset the size entry used flags vector | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Reset the size entry used flags vector | + \*-----------------------------------------------------*/ detection_size_entry_used.resize(rgb_controllers_sizes.size()); - for(unsigned int size_idx = 0; size_idx < detection_size_entry_used.size(); size_idx++) + for(std::size_t size_idx = 0; size_idx < (unsigned int)detection_size_entry_used.size(); size_idx++) { detection_size_entry_used[size_idx] = false; } - /*-------------------------------------------------*\ - | Open device disable list and read in disabled | - | device strings | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Open device disable list and read in disabled | + | device strings | + \*-----------------------------------------------------*/ detector_settings = settings_manager->GetSettings("Detectors"); - /*-------------------------------------------------*\ - | Initialize HID interface for detection | - \*-------------------------------------------------*/ - int hid_status = hid_init(); - - LOG_INFO("Initializing HID interfaces: %s", ((hid_status == 0) ? "Success" : "Failed")); - - /*-------------------------------------------------*\ - | Check HID safe mode setting | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check HID safe mode setting | + \*-----------------------------------------------------*/ if(detector_settings.contains("hid_safe_mode")) { hid_safe_mode = detector_settings["hid_safe_mode"]; } - /*-------------------------------------------------*\ - | Calculate the percentage denominator by adding | - | the number of I2C and miscellaneous detectors and | - | the number of enumerated HID devices | - | | - | Start by iterating through all HID devices in | - | list to get a total count | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Calculate the percentage denominator by adding the | + | number of I2C and miscellaneous detectors and the | + | number of enumerated HID devices | + | | + | Start by iterating through all HID devices in list to | + | get a total count | + \*-----------------------------------------------------*/ if(!hid_safe_mode) { hid_devices = hid_enumerate(0, 0); @@ -877,17 +1113,17 @@ void ResourceManager::DetectDevicesThreadFunction() current_hid_device = current_hid_device->next; } - percent_denominator = i2c_device_detectors.size() + i2c_pci_device_detectors.size() + device_detectors.size() + hid_device_count; + percent_denominator = (float)(i2c_device_detectors.size() + i2c_dimm_device_detectors.size() + i2c_pci_device_detectors.size() + device_detectors.size()) + (float)hid_device_count; - /*-------------------------------------------------*\ - | Start at 0% detection progress | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Start at 0% detection progress | + \*-----------------------------------------------------*/ detection_percent = 0; #ifdef __linux__ - /*-------------------------------------------------*\ - | Check if the udev rules exist | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check if the udev rules exist | + \*-----------------------------------------------------*/ bool udev_not_exist = false; bool udev_multiple = false; @@ -907,16 +1143,16 @@ void ResourceManager::DetectDevicesThreadFunction() } #endif - /*-------------------------------------------------*\ - | Detect i2c interfaces | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Detect i2c interfaces | + \*-----------------------------------------------------*/ LOG_INFO("------------------------------------------------------"); LOG_INFO("| Detecting I2C interfaces |"); LOG_INFO("------------------------------------------------------"); bool i2c_interface_fail = false; - for(unsigned int i2c_bus_detector_idx = 0; i2c_bus_detector_idx < i2c_bus_detectors.size() && detection_is_required.load(); i2c_bus_detector_idx++) + for(unsigned int i2c_bus_detector_idx = 0; i2c_bus_detector_idx < (unsigned int)i2c_bus_detectors.size() && detection_is_required.load(); i2c_bus_detector_idx++) { if(i2c_bus_detectors[i2c_bus_detector_idx]() == false) { @@ -926,14 +1162,15 @@ void ResourceManager::DetectDevicesThreadFunction() I2CBusListChanged(); } - /*-------------------------------------------------*\ - | Detect i2c devices | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Detect i2c devices | + \*-----------------------------------------------------*/ LOG_INFO("------------------------------------------------------"); LOG_INFO("| Detecting I2C devices |"); LOG_INFO("------------------------------------------------------"); - for(unsigned int i2c_detector_idx = 0; i2c_detector_idx < i2c_device_detectors.size() && detection_is_required.load(); i2c_detector_idx++) + for(unsigned int i2c_detector_idx = 0; i2c_detector_idx < (unsigned int)i2c_device_detectors.size() && detection_is_required.load(); i2c_detector_idx++) { + std::size_t controller_size = rgb_controllers_hw.size(); detection_string = i2c_device_detector_strings[i2c_detector_idx].c_str(); /*-------------------------------------------------*\ @@ -957,41 +1194,95 @@ void ResourceManager::DetectDevicesThreadFunction() | If the device list size has changed, call the | | device list changed callbacks | \*-------------------------------------------------*/ - if(rgb_controllers_hw.size() != detection_prev_size) - { - /*-------------------------------------------------*\ - | First, load sizes for the new controllers | - \*-------------------------------------------------*/ - for(unsigned int controller_size_idx = detection_prev_size; controller_size_idx < rgb_controllers_hw.size(); controller_size_idx++) - { - profile_manager->LoadDeviceFromListWithOptions(rgb_controllers_sizes, detection_size_entry_used, rgb_controllers_hw[controller_size_idx], true, false); - } - - UpdateDeviceList(); - } - else + if(rgb_controllers_hw.size() == controller_size) { LOG_DEBUG("[%s] no devices found", detection_string); } - detection_prev_size = rgb_controllers_hw.size(); LOG_TRACE("[%s] detection end", detection_string); /*-------------------------------------------------*\ | Update detection percent | \*-------------------------------------------------*/ - percent = (i2c_detector_idx + 1.0f) / percent_denominator; + percent = ((float)i2c_detector_idx + 1.0f) / percent_denominator; - detection_percent = percent * 100.0f; + detection_percent = (unsigned int)(percent * 100.0f); } - /*-------------------------------------------------*\ - | Detect i2c PCI devices | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Detect i2c DIMM modules | + \*-----------------------------------------------------*/ + LOG_INFO("------------------------------------------------------"); + LOG_INFO("| Detecting I2C DIMM modules |"); + LOG_INFO("------------------------------------------------------"); + + detection_string = "Reading DRAM SPD Information"; + DetectionProgressChanged(); + + for(unsigned int bus = 0; bus < busses.size() && IsAnyDimmDetectorEnabled(detector_settings); bus++) + { + IF_DRAM_SMBUS(busses[bus]->pci_vendor, busses[bus]->pci_device) + { + std::vector slots; + SPDMemoryType dimm_type = SPD_RESERVED; + + for(uint8_t spd_addr = 0x50; spd_addr < 0x58; spd_addr++) + { + SPDDetector spd(busses[bus], spd_addr, dimm_type); + if(spd.is_valid()) + { + SPDWrapper accessor(spd); + dimm_type = spd.memory_type(); + LOG_INFO("[ResourceManager] Detected occupied slot %d, bus %d, type %s", spd_addr - 0x50 + 1, bus, spd_memory_type_name[dimm_type]); + LOG_DEBUG("[ResourceManager] Jedec ID: 0x%04x", accessor.jedec_id()); + slots.push_back(accessor); + } + } + + for(unsigned int i2c_detector_idx = 0; i2c_detector_idx < i2c_dimm_device_detectors.size() && detection_is_required.load(); i2c_detector_idx++) + { + if((i2c_dimm_device_detectors[i2c_detector_idx].dimm_type == dimm_type) && is_jedec_in_slots(slots, i2c_dimm_device_detectors[i2c_detector_idx].jedec_id)) + { + detection_string = i2c_dimm_device_detectors[i2c_detector_idx].name.c_str(); + + /*-------------------------------------*\ + | Check if this detector is enabled | + \*-------------------------------------*/ + bool this_device_enabled = true; + if(detector_settings.contains("detectors") && detector_settings["detectors"].contains(detection_string)) + { + this_device_enabled = detector_settings["detectors"][detection_string]; + } + + LOG_DEBUG("[%s] is %s", detection_string, ((this_device_enabled == true) ? "enabled" : "disabled")); + if(this_device_enabled) + { + DetectionProgressChanged(); + + std::vector matching_slots = slots_with_jedec(slots, i2c_dimm_device_detectors[i2c_detector_idx].jedec_id); + i2c_dimm_device_detectors[i2c_detector_idx].function(busses[bus], matching_slots, i2c_dimm_device_detectors[i2c_detector_idx].name); + } + + LOG_TRACE("[%s] detection end", detection_string); + } + + /*-----------------------------------------*\ + | Update detection percent | + \*-----------------------------------------*/ + percent = (i2c_device_detectors.size() + i2c_detector_idx + 1.0f) / percent_denominator; + + detection_percent = (unsigned int)(percent * 100.0f); + } + } + } + + /*-----------------------------------------------------*\ + | Detect i2c PCI devices | + \*-----------------------------------------------------*/ LOG_INFO("------------------------------------------------------"); LOG_INFO("| Detecting I2C PCI devices |"); LOG_INFO("------------------------------------------------------"); - for(unsigned int i2c_detector_idx = 0; i2c_detector_idx < i2c_pci_device_detectors.size() && detection_is_required.load(); i2c_detector_idx++) + for(unsigned int i2c_detector_idx = 0; i2c_detector_idx < (unsigned int)i2c_pci_device_detectors.size() && detection_is_required.load(); i2c_detector_idx++) { detection_string = i2c_pci_device_detectors[i2c_detector_idx].name.c_str(); @@ -1026,16 +1317,16 @@ void ResourceManager::DetectDevicesThreadFunction() /*-------------------------------------------------*\ | Update detection percent | \*-------------------------------------------------*/ - percent = (i2c_device_detectors.size() + i2c_detector_idx + 1.0f) / percent_denominator; + percent = (i2c_device_detectors.size() + i2c_dimm_device_detectors.size() + i2c_detector_idx + 1.0f) / percent_denominator; - detection_percent = percent * 100.0f; + detection_percent = (unsigned int)(percent * 100.0f); } - /*-------------------------------------------------*\ - | Detect HID devices | - | | - | Reset current device pointer to first device | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Detect HID devices | + | | + | Reset current device pointer to first device | + \*-----------------------------------------------------*/ LOG_INFO("------------------------------------------------------"); LOG_INFO("| Detecting HID devices |"); if (hid_safe_mode) @@ -1045,42 +1336,30 @@ void ResourceManager::DetectDevicesThreadFunction() if(hid_safe_mode) { - /*-----------------------------------------------------------------------------*\ - | Loop through all available detectors. If all required information matches, | - | run the detector | - \*-----------------------------------------------------------------------------*/ - for(unsigned int hid_detector_idx = 0; hid_detector_idx < hid_device_detectors.size() && detection_is_required.load(); hid_detector_idx++) + /*-------------------------------------------------*\ + | Loop through all available detectors. If all | + | required information matches, run the detector | + \*-------------------------------------------------*/ + for(unsigned int hid_detector_idx = 0; hid_detector_idx < (unsigned int)hid_device_detectors.size() && detection_is_required.load(); hid_detector_idx++) { - hid_devices = hid_enumerate(hid_device_detectors[hid_detector_idx].address >> 16, hid_device_detectors[hid_detector_idx].address & 0x0000FFFF); + HIDDeviceDetectorBlock & detector = hid_device_detectors[hid_detector_idx]; + hid_devices = hid_enumerate(detector.vid, detector.pid); - LOG_VERBOSE("Trying to run detector for [%s] (for 0x%08hx)", hid_device_detectors[hid_detector_idx].name.c_str(), hid_device_detectors[hid_detector_idx].address); + LOG_VERBOSE("[ResourceManager] Trying to run detector for [%s] (for %04x:%04x)", detector.name.c_str(), detector.vid, detector.pid); current_hid_device = hid_devices; while(current_hid_device) { - unsigned int addr = (current_hid_device->vendor_id << 16) | current_hid_device->product_id; - if(( ( hid_device_detectors[hid_detector_idx].address == addr ) ) -#ifdef USE_HID_USAGE - && ( ( hid_device_detectors[hid_detector_idx].usage_page == HID_USAGE_PAGE_ANY ) - || ( hid_device_detectors[hid_detector_idx].usage_page == current_hid_device->usage_page ) ) - && ( ( hid_device_detectors[hid_detector_idx].usage == HID_USAGE_ANY ) - || ( hid_device_detectors[hid_detector_idx].usage == current_hid_device->usage ) ) - && ( ( hid_device_detectors[hid_detector_idx].interface == HID_INTERFACE_ANY ) - || ( hid_device_detectors[hid_detector_idx].interface == current_hid_device->interface_number ) ) -#else - && ( ( hid_device_detectors[hid_detector_idx].interface == HID_INTERFACE_ANY ) - || ( hid_device_detectors[hid_detector_idx].interface == current_hid_device->interface_number ) ) -#endif - ) + if(detector.compare(current_hid_device)) { - detection_string = hid_device_detectors[hid_detector_idx].name.c_str(); + detection_string = detector.name.c_str(); - /*-------------------------------------------------*\ - | Check if this detector is enabled or needs to be | - | added to the settings list | - \*-------------------------------------------------*/ + /*-------------------------------------*\ + | Check if this detector is enabled or | + | needs to be added to the settings list| + \*-------------------------------------*/ bool this_device_enabled = true; if(detector_settings.contains("detectors") && detector_settings["detectors"].contains(detection_string)) { @@ -1093,7 +1372,7 @@ void ResourceManager::DetectDevicesThreadFunction() { DetectionProgressChanged(); - hid_device_detectors[hid_detector_idx].function(current_hid_device, hid_device_detectors[hid_detector_idx].name); + detector.function(current_hid_device, hid_device_detectors[hid_detector_idx].name); LOG_TRACE("[%s] detection end", detection_string); } @@ -1124,34 +1403,21 @@ void ResourceManager::DetectDevicesThreadFunction() detection_string = ""; DetectionProgressChanged(); - unsigned int addr = (current_hid_device->vendor_id << 16) | current_hid_device->product_id; - - /*-----------------------------------------------------------------------------*\ - | Loop through all available detectors. If all required information matches, | - | run the detector | - \*-----------------------------------------------------------------------------*/ - for(unsigned int hid_detector_idx = 0; hid_detector_idx < hid_device_detectors.size() && detection_is_required.load(); hid_detector_idx++) + /*---------------------------------------------*\ + | Loop through all available detectors. If all | + | required information matches, run the detector| + \*---------------------------------------------*/ + for(unsigned int hid_detector_idx = 0; hid_detector_idx < (unsigned int)hid_device_detectors.size() && detection_is_required.load(); hid_detector_idx++) { - if(( ( hid_device_detectors[hid_detector_idx].address == addr ) ) -#ifdef USE_HID_USAGE - && ( ( hid_device_detectors[hid_detector_idx].usage_page == HID_USAGE_PAGE_ANY ) - || ( hid_device_detectors[hid_detector_idx].usage_page == current_hid_device->usage_page ) ) - && ( ( hid_device_detectors[hid_detector_idx].usage == HID_USAGE_ANY ) - || ( hid_device_detectors[hid_detector_idx].usage == current_hid_device->usage ) ) - && ( ( hid_device_detectors[hid_detector_idx].interface == HID_INTERFACE_ANY ) - || ( hid_device_detectors[hid_detector_idx].interface == current_hid_device->interface_number ) ) -#else - && ( ( hid_device_detectors[hid_detector_idx].interface == HID_INTERFACE_ANY ) - || ( hid_device_detectors[hid_detector_idx].interface == current_hid_device->interface_number ) ) -#endif - ) + HIDDeviceDetectorBlock & detector = hid_device_detectors[hid_detector_idx]; + if(detector.compare(current_hid_device)) { - detection_string = hid_device_detectors[hid_detector_idx].name.c_str(); + detection_string = detector.name.c_str(); - /*-------------------------------------------------*\ - | Check if this detector is enabled or needs to be | - | added to the settings list | - \*-------------------------------------------------*/ + /*-------------------------------------*\ + | Check if this detector is enabled or | + | needs to be added to the settings list| + \*-------------------------------------*/ bool this_device_enabled = true; if(detector_settings.contains("detectors") && detector_settings["detectors"].contains(detection_string)) { @@ -1164,37 +1430,27 @@ void ResourceManager::DetectDevicesThreadFunction() { DetectionProgressChanged(); - hid_device_detectors[hid_detector_idx].function(current_hid_device, hid_device_detectors[hid_detector_idx].name); + detector.function(current_hid_device, hid_device_detectors[hid_detector_idx].name); } } } - /*-----------------------------------------------------------------------------*\ - | Loop through all available wrapped HID detectors. If all required | - | information matches, run the detector | - \*-----------------------------------------------------------------------------*/ - for(unsigned int hid_detector_idx = 0; hid_detector_idx < hid_wrapped_device_detectors.size() && detection_is_required.load(); hid_detector_idx++) + /*---------------------------------------------*\ + | Loop through all available wrapped HID | + | detectors. If all required information | + | matches, run the detector | + \*---------------------------------------------*/ + for(unsigned int hid_detector_idx = 0; hid_detector_idx < (unsigned int)hid_wrapped_device_detectors.size() && detection_is_required.load(); hid_detector_idx++) { - if(( ( hid_wrapped_device_detectors[hid_detector_idx].address == addr ) ) -#ifdef USE_HID_USAGE - && ( ( hid_wrapped_device_detectors[hid_detector_idx].usage_page == HID_USAGE_PAGE_ANY ) - || ( hid_wrapped_device_detectors[hid_detector_idx].usage_page == current_hid_device->usage_page ) ) - && ( ( hid_wrapped_device_detectors[hid_detector_idx].usage == HID_USAGE_ANY ) - || ( hid_wrapped_device_detectors[hid_detector_idx].usage == current_hid_device->usage ) ) - && ( ( hid_wrapped_device_detectors[hid_detector_idx].interface == HID_INTERFACE_ANY ) - || ( hid_wrapped_device_detectors[hid_detector_idx].interface == current_hid_device->interface_number ) ) -#else - && ( ( hid_wrapped_device_detectors[hid_detector_idx].interface == HID_INTERFACE_ANY ) - || ( hid_wrapped_device_detectors[hid_detector_idx].interface == current_hid_device->interface_number ) ) -#endif - ) + HIDWrappedDeviceDetectorBlock & detector = hid_wrapped_device_detectors[hid_detector_idx]; + if(detector.compare(current_hid_device)) { - detection_string = hid_wrapped_device_detectors[hid_detector_idx].name.c_str(); + detection_string = detector.name.c_str(); - /*-------------------------------------------------*\ - | Check if this detector is enabled or needs to be | - | added to the settings list | - \*-------------------------------------------------*/ + /*-------------------------------------*\ + | Check if this detector is enabled or | + | needs to be added to the settings list| + \*-------------------------------------*/ bool this_device_enabled = true; if(detector_settings.contains("detectors") && detector_settings["detectors"].contains(detection_string)) { @@ -1207,23 +1463,23 @@ void ResourceManager::DetectDevicesThreadFunction() { DetectionProgressChanged(); - hid_wrapped_device_detectors[hid_detector_idx].function(default_wrapper, current_hid_device, hid_wrapped_device_detectors[hid_detector_idx].name); + detector.function(default_wrapper, current_hid_device, hid_wrapped_device_detectors[hid_detector_idx].name); } } } - /*-------------------------------------------------*\ - | Update detection percent | - \*-------------------------------------------------*/ + /*---------------------------------------------*\ + | Update detection percent | + \*---------------------------------------------*/ hid_device_count++; - percent = (i2c_device_detectors.size() + i2c_pci_device_detectors.size() + hid_device_count) / percent_denominator; + percent = (i2c_device_detectors.size() + i2c_dimm_device_detectors.size() + i2c_pci_device_detectors.size() + hid_device_count) / percent_denominator; - detection_percent = percent * 100.0f; + detection_percent = (unsigned int)(percent * 100.0f); - /*-------------------------------------------------*\ - | Move on to the next HID device | - \*-------------------------------------------------*/ + /*---------------------------------------------*\ + | Move on to the next HID device | + \*---------------------------------------------*/ current_hid_device = current_hid_device->next; } @@ -1233,11 +1489,11 @@ void ResourceManager::DetectDevicesThreadFunction() hid_free_enumeration(hid_devices); } - /*-------------------------------------------------*\ - | Detect HID devices | - | | - | Reset current device pointer to first device | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Detect HID devices | + | | + | Reset current device pointer to first device | + \*-----------------------------------------------------*/ #ifdef __linux__ #ifdef __GLIBC__ LOG_INFO("------------------------------------------------------"); @@ -1247,9 +1503,9 @@ void ResourceManager::DetectDevicesThreadFunction() void * dyn_handle = NULL; hidapi_wrapper wrapper; - /*-------------------------------------------------*\ - | Load the libhidapi-libusb library | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Load the libhidapi-libusb library | + \*-----------------------------------------------------*/ #ifdef __GLIBC__ if((dyn_handle = dlopen("libhidapi-libusb.so", RTLD_NOW | RTLD_NODELETE | RTLD_DEEPBIND))) #else @@ -1293,29 +1549,22 @@ void ResourceManager::DetectDevicesThreadFunction() detection_string = ""; DetectionProgressChanged(); - unsigned int addr = (current_hid_device->vendor_id << 16) | current_hid_device->product_id; - - /*-----------------------------------------------------------------------------*\ - | Loop through all available wrapped HID detectors. If all required | - | information matches, run the detector | - \*-----------------------------------------------------------------------------*/ - for(unsigned int hid_detector_idx = 0; hid_detector_idx < hid_wrapped_device_detectors.size() && detection_is_required.load(); hid_detector_idx++) + /*---------------------------------------------*\ + | Loop through all available wrapped HID | + | detectors. If all required information | + | matches, run the detector | + \*---------------------------------------------*/ + for(unsigned int hid_detector_idx = 0; hid_detector_idx < (unsigned int)hid_wrapped_device_detectors.size() && detection_is_required.load(); hid_detector_idx++) { - if(( ( hid_wrapped_device_detectors[hid_detector_idx].address == addr ) ) - && ( ( hid_wrapped_device_detectors[hid_detector_idx].usage_page == HID_USAGE_PAGE_ANY ) - || ( hid_wrapped_device_detectors[hid_detector_idx].usage_page == current_hid_device->usage_page ) ) - && ( ( hid_wrapped_device_detectors[hid_detector_idx].usage == HID_USAGE_ANY ) - || ( hid_wrapped_device_detectors[hid_detector_idx].usage == current_hid_device->usage ) ) - && ( ( hid_wrapped_device_detectors[hid_detector_idx].interface == HID_INTERFACE_ANY ) - || ( hid_wrapped_device_detectors[hid_detector_idx].interface == current_hid_device->interface_number ) ) - ) + HIDWrappedDeviceDetectorBlock & detector = hid_wrapped_device_detectors[hid_detector_idx]; + if(detector.compare(current_hid_device)) { - detection_string = hid_wrapped_device_detectors[hid_detector_idx].name.c_str(); + detection_string = detector.name.c_str(); - /*-------------------------------------------------*\ - | Check if this detector is enabled or needs to be | - | added to the settings list | - \*-------------------------------------------------*/ + /*-------------------------------------*\ + | Check if this detector is enabled or | + | needs to be added to the settings list| + \*-------------------------------------*/ bool this_device_enabled = true; if(detector_settings.contains("detectors") && detector_settings["detectors"].contains(detection_string)) { @@ -1328,23 +1577,23 @@ void ResourceManager::DetectDevicesThreadFunction() { DetectionProgressChanged(); - hid_wrapped_device_detectors[hid_detector_idx].function(wrapper, current_hid_device, hid_wrapped_device_detectors[hid_detector_idx].name); + detector.function(wrapper, current_hid_device, detector.name); } } } - /*-------------------------------------------------*\ - | Update detection percent | - \*-------------------------------------------------*/ + /*---------------------------------------------*\ + | Update detection percent | + \*---------------------------------------------*/ hid_device_count++; - percent = (i2c_device_detectors.size() + i2c_pci_device_detectors.size() + hid_device_count) / percent_denominator; + percent = (i2c_device_detectors.size() + i2c_dimm_device_detectors.size() + i2c_pci_device_detectors.size() + hid_device_count) / percent_denominator; detection_percent = percent * 100.0f; - /*-------------------------------------------------*\ - | Move on to the next HID device | - \*-------------------------------------------------*/ + /*---------------------------------------------*\ + | Move on to the next HID device | + \*---------------------------------------------*/ current_hid_device = current_hid_device->next; } @@ -1356,14 +1605,14 @@ void ResourceManager::DetectDevicesThreadFunction() #endif #endif - /*-------------------------------------------------*\ - | Detect other devices | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Detect other devices | + \*-----------------------------------------------------*/ LOG_INFO("------------------------------------------------------"); LOG_INFO("| Detecting other devices |"); LOG_INFO("------------------------------------------------------"); - for(unsigned int detector_idx = 0; detector_idx < device_detectors.size() && detection_is_required.load(); detector_idx++) + for(unsigned int detector_idx = 0; detector_idx < (unsigned int)device_detectors.size() && detection_is_required.load(); detector_idx++) { detection_string = device_detector_strings[detector_idx].c_str(); @@ -1392,118 +1641,294 @@ void ResourceManager::DetectDevicesThreadFunction() \*-------------------------------------------------*/ percent = (i2c_device_detectors.size() + hid_device_count + detector_idx + 1.0f) / percent_denominator; - detection_percent = percent * 100.0f; + detection_percent = (unsigned int)(percent * 100.0f); } - /*-------------------------------------------------*\ - | Make sure that when the detection is done, | - | progress bar is set to 100% | - \*-------------------------------------------------*/ - detection_is_required = false; - detection_percent = 100; - detection_string = ""; - - DetectionProgressChanged(); + /*-----------------------------------------------------*\ + | Make sure that when the detection is done, progress | + | bar is set to 100% | + \*-----------------------------------------------------*/ + ProcessPostDetection(); DetectDeviceMutex.unlock(); - /*-----------------------------------------------------*\ - | Call detection end callbacks | - \*-----------------------------------------------------*/ - for(unsigned int callback_idx = 0; callback_idx < DetectionEndCallbacks.size(); callback_idx++) - { - DetectionEndCallbacks[callback_idx](DetectionEndCallbackArgs[callback_idx]); - } - - LOG_INFO("------------------------------------------------------"); - LOG_INFO("| Detection completed |"); - LOG_INFO("------------------------------------------------------"); - #ifdef __linux__ - /*-------------------------------------------------*\ - | If the udev rules file is not installed, show a | - | dialog | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | If the udev rules file is not installed, show a dialog| + \*-----------------------------------------------------*/ if(udev_not_exist) { - const char* message = "

WARNING:

" - "

The OpenRGB udev rules are not installed.

" - "

Most devices will not be available unless running OpenRGB as root.

" - "

If using AppImage, Flatpak, or self-compiled versions of OpenRGB you must install the udev rules manually

" - "

See https://openrgb.org/udev to install the udev rules manually

"; - - LOG_DIALOG("%s", message); + LOG_DIALOG("%s", UDEV_MISSING); udev_multiple = false; i2c_interface_fail = false; } - /*-------------------------------------------------*\ - | If multiple udev rules files are installed, show | - | a dialog | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | If multiple udev rules files are installed, show a | + | dialog | + \*-----------------------------------------------------*/ if(udev_multiple) { - const char* message = "

WARNING:

" - "

Multiple OpenRGB udev rules are installed.

" - "

The udev rules file 60-openrgb.rules is installed in both /etc/udev/rules.d and /usr/lib/udev/rules.d.

" - "

Multiple udev rules files can conflict, it is recommended to remove one of them.

"; - - LOG_DIALOG("%s", message); + LOG_DIALOG("%s", UDEV_MUTLI); i2c_interface_fail = false; } #endif - /*-------------------------------------------------*\ - | If any i2c interfaces failed to detect due to an | - | error condition, show a dialog | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | If any i2c interfaces failed to detect due to an | + | error condition, show a dialog | + \*-----------------------------------------------------*/ if(i2c_interface_fail) { - const char* message = "

WARNING:

" - "

One or more I2C/SMBus interfaces failed to initialize.

" - "

RGB DRAM modules and some motherboards' onboard RGB lighting will not be available without I2C/SMBus.

" #ifdef _WIN32 - "

On Windows, this is usually caused by a failure to load the WinRing0 driver. " - "You must run OpenRGB as administrator at least once to allow WinRing0 to set up.

" + LOG_DIALOG("%s", I2C_ERR_WIN); #endif #ifdef __linux__ - "

On Linux, this is usually because the i2c-dev module is not loaded. " - "You must load the i2c-dev module along with the correct i2c driver for your motherboard. " - "This is usually i2c-piix4 for AMD systems and i2c-i801 for Intel systems.

" + LOG_DIALOG("%s", I2C_ERR_LINUX); #endif - "

See help.openrgb.org for additional troubleshooting steps if you keep seeing this message.

"; - - LOG_DIALOG("%s", message); } } void ResourceManager::StopDeviceDetection() { - LOG_INFO("Detection abort requested"); + LOG_INFO("[ResourceManager] Detection abort requested"); detection_is_required = false; detection_percent = 100; detection_string = "Stopping"; } +void ResourceManager::Initialize(bool tryConnect, bool detectDevices, bool startServer, bool applyPostOptions) +{ + /*-----------------------------------------------------*\ + | Cache the parameters | + | TODO: Possibly cache them in the CLI file somewhere | + \*-----------------------------------------------------*/ + tryAutoConnect = tryConnect; + detection_enabled = detectDevices; + start_server = startServer; + apply_post_options = applyPostOptions; + + RunInBackgroundThread(std::bind(&ResourceManager::InitCoroutine, this)); +} + +void ResourceManager::InitCoroutine() +{ + /*-----------------------------------------------------*\ + | If enabled, try connecting to local server instead of | + | detecting devices from this instance of OpenRGB | + \*-----------------------------------------------------*/ + if(tryAutoConnect) + { + detection_percent = 0; + detection_string = "Attempting server connection..."; + DetectionProgressChanged(); + + /*-------------------------------------------------*\ + | Attempt connection to local server | + \*-------------------------------------------------*/ + if(AttemptLocalConnection()) + { + LOG_DEBUG("[ResourceManager] Local OpenRGB server connected, running in client mode"); + + /*---------------------------------------------*\ + | Set auto connection active flag and disable | + | detection if the local server was connected | + \*---------------------------------------------*/ + auto_connection_active = true; + DisableDetection(); + } + + tryAutoConnect = false; + } + + /*-----------------------------------------------------*\ + | Initialize Saved Client Connections | + \*-----------------------------------------------------*/ + json client_settings = settings_manager->GetSettings("Client"); + + if(client_settings.contains("clients")) + { + for(unsigned int client_idx = 0; client_idx < client_settings["clients"].size(); client_idx++) + { + NetworkClient * client = new NetworkClient(rgb_controllers); + + std::string titleString = "OpenRGB "; + titleString.append(VERSION_STRING); + + std::string client_ip = client_settings["clients"][client_idx]["ip"]; + unsigned short client_port = client_settings["clients"][client_idx]["port"]; + + client->SetIP(client_ip.c_str()); + client->SetName(titleString.c_str()); + client->SetPort(client_port); + + client->StartClient(); + + for(int timeout = 0; timeout < 100; timeout++) + { + if(client->GetConnected()) + { + break; + } + std::this_thread::sleep_for(10ms); + } + + RegisterNetworkClient(client); + } + } + + /*-----------------------------------------------------*\ + | Perform actual detection if enabled | + | Done in the same thread (InitThread), as we need to | + | wait for completion anyway | + \*-----------------------------------------------------*/ + if(detection_enabled) + { + LOG_DEBUG("[ResourceManager] Running standalone"); + if(ProcessPreDetection()) + { + /*---------------------------------------------*\ + | We are currently in a coroutine, so run | + | detection directly with no scheduling | + \*---------------------------------------------*/ + DetectDevicesCoroutine(); + } + } + else + { + ProcessPostDetection(); + } + + /*-----------------------------------------------------*\ + | Start server if requested | + \*-----------------------------------------------------*/ + if(start_server) + { + detection_percent = 100; + detection_string = "Starting server"; + DetectionProgressChanged(); + + GetServer()->StartServer(); + if(!GetServer()->GetOnline()) + { + LOG_DEBUG("[ResourceManager] Server failed to start"); + } + } + + /*-----------------------------------------------------*\ + | Process command line arguments after detection only | + | if the pre-detection parsing indicated it should be | + | run | + \*-----------------------------------------------------*/ + if(apply_post_options) + { + cli_post_detection(); + } + + init_finished = true; +} + +void ResourceManager::HidExitCoroutine() +{ + /*-----------------------------------------------------*\ + | Cleanup HID interface | + | WARNING: may not be ran from any other thread!!! | + \*-----------------------------------------------------*/ + int hid_status = hid_exit(); + + LOG_DEBUG("[ResourceManager] Closing HID interfaces: %s", ((hid_status == 0) ? "Success" : "Failed")); +} + +void ResourceManager::RunInBackgroundThread(std::function coroutine) +{ + if(std::this_thread::get_id() == DetectDevicesThread->get_id()) + { + /*-------------------------------------------------*\ + | We are already in the background thread - don't | + | schedule the call, run it immediately | + \*-------------------------------------------------*/ + coroutine(); + } + else + { + BackgroundThreadStateMutex.lock(); + if(ScheduledBackgroundFunction != nullptr) + { + LOG_WARNING("[ResourceManager] Detection coroutine: assigned a new coroutine when one was already scheduled - probably two rescan events sent at once"); + } + ScheduledBackgroundFunction = coroutine; + BackgroundThreadStateMutex.unlock(); + BackgroundFunctionStartTrigger.notify_one(); + } +} + +void ResourceManager::BackgroundThreadFunction() +{ + /*-----------------------------------------------------*\ + | The background thread that runs scheduled coroutines | + | when applicable | + | Stays asleep if nothing is scheduled | + | NOTE: this thread owns the HIDAPI library internal | + | objects on MacOS | + | hid_init and hid_exit may not be called outside of | + | this thread. Calling hid_exit outside of this thread | + | WILL cause an immediate CRASH on MacOS. | + | BackgroundThreadStateMutex will be UNLOCKED as long | + | as the thread is suspended. It locks automatically | + | when any coroutine is running. However, it seems to | + | be necessary to be separate from the | + | DeviceDetectionMutex, even though their states are | + | nearly identical. | + \------------------------------------------------------*/ + + std::unique_lock lock(BackgroundThreadStateMutex); + while(background_thread_running) + { + if(ScheduledBackgroundFunction) + { + std::function coroutine = nullptr; + std::swap(ScheduledBackgroundFunction, coroutine); + try + { + coroutine(); + } + catch(std::exception& e) + { + LOG_ERROR("[ResourceManager] Unhandled exception in coroutine; e.what(): %s", e.what()); + } + catch(...) + { + LOG_ERROR("[ResourceManager] Unhandled exception in coroutine"); + } + } + /*-------------------------------------------------*\ + | This line will cause the thread to suspend until | + | the condition variable is triggered | + | NOTE: it may be subject to "spurious wakeups" | + \*-------------------------------------------------*/ + BackgroundFunctionStartTrigger.wait(lock); + } +} + void ResourceManager::UpdateDetectorSettings() { json detector_settings; bool save_settings = false; - /*-------------------------------------------------*\ - | Open device disable list and read in disabled | - | device strings | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Open device disable list and read in disabled device | + | strings | + \*-----------------------------------------------------*/ detector_settings = settings_manager->GetSettings("Detectors"); - /*-------------------------------------------------*\ - | Loop through all I2C detectors and see if any | - | need to be saved to the settings | - \*-------------------------------------------------*/ - for(unsigned int i2c_detector_idx = 0; i2c_detector_idx < i2c_device_detectors.size(); i2c_detector_idx++) + /*-----------------------------------------------------*\ + | Loop through all I2C detectors and see if any need to | + | be saved to the settings | + \*-----------------------------------------------------*/ + for(unsigned int i2c_detector_idx = 0; i2c_detector_idx < (unsigned int)i2c_device_detectors.size(); i2c_detector_idx++) { detection_string = i2c_device_detector_strings[i2c_detector_idx].c_str(); @@ -1514,11 +1939,26 @@ void ResourceManager::UpdateDetectorSettings() } } - /*-------------------------------------------------*\ - | Loop through all I2C PCI detectors and see if any | - | need to be saved to the settings | - \*-------------------------------------------------*/ - for(unsigned int i2c_pci_detector_idx = 0; i2c_pci_detector_idx < i2c_pci_device_detectors.size(); i2c_pci_detector_idx++) + /*-----------------------------------------------------*\ + | Loop through all I2C DIMM detectors and see if any | + | need to be saved to the settings | + \*-----------------------------------------------------*/ + for(unsigned int i2c_detector_idx = 0; i2c_detector_idx < (unsigned int)i2c_dimm_device_detectors.size(); i2c_detector_idx++) + { + detection_string = i2c_dimm_device_detectors[i2c_detector_idx].name.c_str(); + + if(!(detector_settings.contains("detectors") && detector_settings["detectors"].contains(detection_string))) + { + detector_settings["detectors"][detection_string] = true; + save_settings = true; + } + } + + /*-----------------------------------------------------*\ + | Loop through all I2C PCI detectors and see if any | + | need to be saved to the settings | + \*-----------------------------------------------------*/ + for(unsigned int i2c_pci_detector_idx = 0; i2c_pci_detector_idx < (unsigned int)i2c_pci_device_detectors.size(); i2c_pci_detector_idx++) { detection_string = i2c_pci_device_detectors[i2c_pci_detector_idx].name.c_str(); @@ -1529,11 +1969,11 @@ void ResourceManager::UpdateDetectorSettings() } } - /*-------------------------------------------------*\ - | Loop through all HID detectors and see if any | - | need to be saved to the settings | - \*-------------------------------------------------*/ - for(unsigned int hid_detector_idx = 0; hid_detector_idx < hid_device_detectors.size(); hid_detector_idx++) + /*-----------------------------------------------------*\ + | Loop through all HID detectors and see if any need to | + | be saved to the settings | + \*-----------------------------------------------------*/ + for(unsigned int hid_detector_idx = 0; hid_detector_idx < (unsigned int)hid_device_detectors.size(); hid_detector_idx++) { detection_string = hid_device_detectors[hid_detector_idx].name.c_str(); @@ -1544,11 +1984,11 @@ void ResourceManager::UpdateDetectorSettings() } } - /*-------------------------------------------------*\ - | Loop through all HID wrapped detectors and see if | - | any need to be saved to the settings | - \*-------------------------------------------------*/ - for(unsigned int hid_wrapped_detector_idx = 0; hid_wrapped_detector_idx < hid_wrapped_device_detectors.size(); hid_wrapped_detector_idx++) + /*-----------------------------------------------------*\ + | Loop through all HID wrapped detectors and see if any | + | need to be saved to the settings | + \*-----------------------------------------------------*/ + for(unsigned int hid_wrapped_detector_idx = 0; hid_wrapped_detector_idx < (unsigned int)hid_wrapped_device_detectors.size(); hid_wrapped_detector_idx++) { detection_string = hid_wrapped_device_detectors[hid_wrapped_detector_idx].name.c_str(); @@ -1559,40 +1999,29 @@ void ResourceManager::UpdateDetectorSettings() } } - /*-------------------------------------------------*\ - | Loop through remaining detectors and see if any | - | need to be saved to the settings | - \*-------------------------------------------------*/ - for(unsigned int detector_idx = 0; detector_idx < device_detectors.size(); detector_idx++) + /*-----------------------------------------------------*\ + | Loop through remaining detectors and see if any need | + | to be saved to the settings | + \*-----------------------------------------------------*/ + for(unsigned int detector_idx = 0; detector_idx < (unsigned int)device_detectors.size(); detector_idx++) { detection_string = device_detector_strings[detector_idx].c_str(); if(!(detector_settings.contains("detectors") && detector_settings["detectors"].contains(detection_string))) { - /*-------------------------------------------------*\ - | Default the OpenRazer detector to disabled, as it | - | overrides RazerController when enabled | - \*-------------------------------------------------*/ - if(strcmp(detection_string, "OpenRazer") == 0 || strcmp(detection_string, "OpenRazer-Win32") == 0) - { - detector_settings["detectors"][detection_string] = false; - } - else - { - detector_settings["detectors"][detection_string] = true; - } + detector_settings["detectors"][detection_string] = true; save_settings = true; } } - /*-------------------------------------------------*\ - | If there were any setting changes that need to be | - | saved, set the settings in the settings manager | - | and save them. | - \*-------------------------------------------------*/ + /*-----------------------------------------------------*\ + | If there were any setting changes that need to be | + | saved, set the settings in the settings manager and | + | save them. | + \*-----------------------------------------------------*/ if(save_settings) { - LOG_INFO("Saving detector settings"); + LOG_INFO("[ResourceManager] Saving detector settings"); settings_manager->SetSettings("Detectors", detector_settings); @@ -1600,8 +2029,38 @@ void ResourceManager::UpdateDetectorSettings() } } +void ResourceManager::WaitForInitialization() +{ + /*-----------------------------------------------------*\ + | A reliable sychronization of this kind is impossible | + | without the use of a `barrier` implementation, which | + | is only introduced in C++20 | + \*-----------------------------------------------------*/ + while(!init_finished) + { + std::this_thread::sleep_for(1ms); + }; +} + void ResourceManager::WaitForDeviceDetection() { DetectDeviceMutex.lock(); DetectDeviceMutex.unlock(); } + +bool ResourceManager::IsAnyDimmDetectorEnabled(json &detector_settings) +{ + for(unsigned int i2c_detector_idx = 0; i2c_detector_idx < i2c_dimm_device_detectors.size() && detection_is_required.load(); i2c_detector_idx++) + { + std::string detector_name_string = i2c_dimm_device_detectors[i2c_detector_idx].name.c_str(); + /*-------------------------------------------------*\ + | Check if this detector is enabled | + \*-------------------------------------------------*/ + if(detector_settings.contains("detectors") && detector_settings["detectors"].contains(detector_name_string) && + detector_settings["detectors"][detector_name_string] == true) + { + return true; + } + } + return false; +} diff --git a/ResourceManager.h b/ResourceManager.h index 6939ba30..6a3e42dc 100644 --- a/ResourceManager.h +++ b/ResourceManager.h @@ -1,13 +1,15 @@ -/*-----------------------------------------*\ -| ResourceManager.h | -| | -| OpenRGB Resource Manager controls access | -| to application components including | -| RGBControllers, I2C interfaces, and | -| network SDK components | -| | -| Adam Honse (CalcProgrammer1) 9/27/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| ResourceManager.h | +| | +| OpenRGB Resource Manager controls access to application | +| components including RGBControllers, I2C interfaces, | +| and network SDK components | +| | +| Adam Honse (CalcProgrammer1) 27 Sep 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once @@ -16,52 +18,61 @@ #include #include #include - +#include +#include "SPDWrapper.h" #include "hidapi_wrapper.h" #include "i2c_smbus.h" -#include "NetworkClient.h" -#include "NetworkServer.h" -#include "ProfileManager.h" -#include "RGBController.h" -#include "SettingsManager.h" +#include "ResourceManagerInterface.h" #include "filesystem.h" +#include + +using json = nlohmann::json; #define HID_INTERFACE_ANY -1 #define HID_USAGE_ANY -1 -#define HID_USAGE_PAGE_ANY -1L - -#define CONTROLLER_LIST_HID 0 +#define HID_USAGE_PAGE_ANY -1 struct hid_device_info; +class NetworkClient; +class NetworkServer; +class ProfileManager; +class RGBController; +class SettingsManager; -typedef std::function I2CBusDetectorFunction; -typedef std::function DeviceDetectorFunction; -typedef std::function&)> I2CDeviceDetectorFunction; -typedef std::function I2CPCIDeviceDetectorFunction; -typedef std::function HIDDeviceDetectorFunction; -typedef std::function HIDWrappedDeviceDetectorFunction; -typedef std::function DynamicDetectorFunction; -typedef std::function PreDetectionHookFunction; +typedef std::function I2CBusDetectorFunction; +typedef std::function DeviceDetectorFunction; +typedef std::function&)> I2CDeviceDetectorFunction; +typedef std::function&, const std::string&)> I2CDIMMDeviceDetectorFunction; +typedef std::function I2CPCIDeviceDetectorFunction; +typedef std::function HIDDeviceDetectorFunction; +typedef std::function HIDWrappedDeviceDetectorFunction; +typedef std::function DynamicDetectorFunction; +typedef std::function PreDetectionHookFunction; -typedef struct +class BasicHIDBlock { - std::string name; +public: + std::string name; + uint16_t vid; + uint16_t pid; + int interface; + int usage_page; + int usage; + + bool compare(hid_device_info* info); +}; + +class HIDDeviceDetectorBlock : public BasicHIDBlock +{ +public: HIDDeviceDetectorFunction function; - unsigned int address; - int interface; - int usage_page; - int usage; -} HIDDeviceDetectorBlock; +}; -typedef struct +class HIDWrappedDeviceDetectorBlock : public BasicHIDBlock { - std::string name; +public: HIDWrappedDeviceDetectorFunction function; - unsigned int address; - int interface; - int usage_page; - int usage; -} HIDWrappedDeviceDetectorBlock; +}; typedef struct { @@ -74,50 +85,23 @@ typedef struct uint8_t i2c_addr; } I2CPCIDeviceDetectorBlock; -typedef void (*DeviceListChangeCallback)(void *); -typedef void (*DetectionProgressCallback)(void *); -typedef void (*DetectionStartCallback)(void *); -typedef void (*DetectionEndCallback)(void *); -typedef void (*I2CBusListChangeCallback)(void *); - -class ResourceManagerInterface +typedef struct { -public: - virtual std::vector & GetI2CBusses() = 0; + std::string name; + I2CDIMMDeviceDetectorFunction function; + uint16_t jedec_id; + uint8_t dimm_type; +} I2CDIMMDeviceDetectorBlock; - virtual void RegisterRGBController(RGBController *rgb_controller) = 0; - virtual void UnregisterRGBController(RGBController *rgb_controller) = 0; +/*---------------------------------------------------------*\ +| Define a macro for QT lupdate to parse | +\*---------------------------------------------------------*/ +#define QT_TRANSLATE_NOOP(scope, x) x - virtual void RegisterDeviceListChangeCallback(DeviceListChangeCallback new_callback, void * new_callback_arg) = 0; - virtual void RegisterDetectionProgressCallback(DetectionProgressCallback new_callback, void * new_callback_arg) = 0; - virtual void RegisterDetectionStartCallback(DetectionStartCallback new_callback, void * new_callback_arg) = 0; - virtual void RegisterDetectionEndCallback(DetectionEndCallback new_callback, void * new_callback_arg) = 0; - virtual void RegisterI2CBusListChangeCallback(I2CBusListChangeCallback new_callback, void * new_callback_arg) = 0; - - virtual void UnregisterDeviceListChangeCallback(DeviceListChangeCallback callback, void * callback_arg) = 0; - virtual void UnregisterDetectionProgressCallback(DetectionProgressCallback callback, void *callback_arg) = 0; - virtual void UnregisterDetectionStartCallback(DetectionStartCallback callback, void *callback_arg) = 0; - virtual void UnregisterDetectionEndCallback(DetectionEndCallback callback, void *callback_arg) = 0; - virtual void UnregisterI2CBusListChangeCallback(I2CBusListChangeCallback callback, void * callback_arg) = 0; - - virtual std::vector & GetRGBControllers() = 0; - - virtual unsigned int GetDetectionPercent() = 0; - - virtual filesystem::path GetConfigurationDirectory() = 0; - - virtual std::vector& GetClients() = 0; - virtual NetworkServer* GetServer() = 0; - - virtual ProfileManager* GetProfileManager() = 0; - virtual SettingsManager* GetSettingsManager() = 0; - - virtual void UpdateDeviceList() = 0; - virtual void WaitForDeviceDetection() = 0; - -protected: - virtual ~ResourceManagerInterface() {}; -}; +extern const char* I2C_ERR_WIN; +extern const char* I2C_ERR_LINUX; +extern const char* UDEV_MISSING; +extern const char* UDEV_MULTI; class ResourceManager: public ResourceManagerInterface { @@ -138,6 +122,7 @@ public: void RegisterI2CBusDetector (I2CBusDetectorFunction detector); void RegisterDeviceDetector (std::string name, DeviceDetectorFunction detector); void RegisterI2CDeviceDetector (std::string name, I2CDeviceDetectorFunction detector); + void RegisterI2CDIMMDeviceDetector (std::string name, I2CDIMMDeviceDetectorFunction detector, uint16_t jedec_id, uint8_t dimm_type); void RegisterI2CPCIDeviceDetector (std::string name, I2CPCIDeviceDetectorFunction detector, uint16_t ven_id, uint16_t dev_id, uint16_t subven_id, uint16_t subdev_id, uint8_t i2c_addr); void RegisterHIDDeviceDetector (std::string name, HIDDeviceDetectorFunction detector, @@ -156,12 +141,14 @@ public: void RegisterDynamicDetector (std::string name, DynamicDetectorFunction detector); void RegisterPreDetectionHook (PreDetectionHookFunction hook); + void RegisterClientInfoChangeCallback(ClientInfoChangeCallback new_callback, void * new_callback_arg); void RegisterDeviceListChangeCallback(DeviceListChangeCallback new_callback, void * new_callback_arg); void RegisterDetectionProgressCallback(DetectionProgressCallback new_callback, void * new_callback_arg); void RegisterDetectionStartCallback(DetectionStartCallback new_callback, void * new_callback_arg); void RegisterDetectionEndCallback(DetectionEndCallback new_callback, void * new_callback_arg); void RegisterI2CBusListChangeCallback(I2CBusListChangeCallback new_callback, void * new_callback_arg); + void UnregisterClientInfoChangeCallback(ClientInfoChangeCallback new_callback, void * new_callback_arg); void UnregisterDeviceListChangeCallback(DeviceListChangeCallback callback, void * callback_arg); void UnregisterDetectionProgressCallback(DetectionProgressCallback callback, void *callback_arg); void UnregisterDetectionStartCallback(DetectionStartCallback callback, void *callback_arg); @@ -185,78 +172,129 @@ public: void SetConfigurationDirectory(const filesystem::path &directory); - void ProcessPreDetectionHooks(); - void ProcessDynamicDetectors(); + void ProcessPreDetectionHooks(); // Consider making private + void ProcessDynamicDetectors(); // Consider making private void UpdateDeviceList(); + void ClientInfoChanged(); void DeviceListChanged(); void DetectionProgressChanged(); void I2CBusListChanged(); + void Initialize(bool tryConnect, bool detectDevices, bool startServer, bool applyPostOptions); + void Cleanup(); void DetectDevices(); void DisableDetection(); + void RescanDevices(); + void StopDeviceDetection(); + void WaitForInitialization(); void WaitForDeviceDetection(); private: - void DetectDevicesThreadFunction(); void UpdateDetectorSettings(); void SetupConfigurationDirectory(); + bool AttemptLocalConnection(); + bool ProcessPreDetection(); + void ProcessPostDetection(); + bool IsAnyDimmDetectorEnabled(json &detector_settings); + void RunInBackgroundThread(std::function); + void BackgroundThreadFunction(); - /*-------------------------------------------------------------------------------------*\ - | Static pointer to shared instance of ResourceManager | - \*-------------------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Functions that must be run in the background thread | + | These are not related to STL coroutines, yet this | + | name is the most convenient | + \*-----------------------------------------------------*/ + void InitCoroutine(); + void DetectDevicesCoroutine(); + void HidExitCoroutine(); + + /*-----------------------------------------------------*\ + | Static pointer to shared instance of ResourceManager | + \*-----------------------------------------------------*/ static ResourceManager* instance; - /*-------------------------------------------------------------------------------------*\ - | Detection enabled flag | - \*-------------------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Auto connection permitting flag | + \*-----------------------------------------------------*/ + bool tryAutoConnect; + + /*-----------------------------------------------------*\ + | Detection enabled flag | + \*-----------------------------------------------------*/ bool detection_enabled; - /*-------------------------------------------------------------------------------------*\ - | Profile Manager | - \*-------------------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Auto connection active flag | + \*-----------------------------------------------------*/ + bool auto_connection_active; + + /*-----------------------------------------------------*\ + | Auto connection client pointer | + \*-----------------------------------------------------*/ + NetworkClient * auto_connection_client; + + /*-----------------------------------------------------*\ + | Auto connection permitting flag | + \*-----------------------------------------------------*/ + bool start_server; + + /*-----------------------------------------------------*\ + | Auto connection permitting flag | + \*-----------------------------------------------------*/ + bool apply_post_options; + + /*-----------------------------------------------------*\ + | Initialization completion flag | + \*-----------------------------------------------------*/ + std::atomic init_finished; + + /*-----------------------------------------------------*\ + | Profile Manager | + \*-----------------------------------------------------*/ ProfileManager* profile_manager; - /*-------------------------------------------------------------------------------------*\ - | Settings Manager | - \*-------------------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Settings Manager | + \*-----------------------------------------------------*/ SettingsManager* settings_manager; - /*-------------------------------------------------------------------------------------*\ - | I2C/SMBus Interfaces | - \*-------------------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | I2C/SMBus Interfaces | + \*-----------------------------------------------------*/ std::vector busses; - /*-------------------------------------------------------------------------------------*\ - | RGBControllers | - \*-------------------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | RGBControllers | + \*-----------------------------------------------------*/ std::vector rgb_controllers_sizes; std::vector rgb_controllers_hw; std::vector rgb_controllers; - /*-------------------------------------------------------------------------------------*\ - | Network Server | - \*-------------------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Network Server | + \*-----------------------------------------------------*/ NetworkServer* server; - /*-------------------------------------------------------------------------------------*\ - | Network Clients | - \*-------------------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Network Clients | + \*-----------------------------------------------------*/ std::vector clients; - /*-------------------------------------------------------------------------------------*\ - | Detectors | - \*-------------------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Detectors | + \*-----------------------------------------------------*/ std::vector device_detectors; std::vector device_detector_strings; std::vector i2c_bus_detectors; std::vector i2c_device_detectors; std::vector i2c_device_detector_strings; + std::vector i2c_dimm_device_detectors; std::vector i2c_pci_device_detectors; std::vector hid_device_detectors; std::vector hid_wrapped_device_detectors; @@ -266,29 +304,42 @@ private: bool dynamic_detectors_processed; - /*-------------------------------------------------------------------------------------*\ - | Detection Thread and Detection State | - \*-------------------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Detection Thread and Detection State | + \*-----------------------------------------------------*/ std::thread * DetectDevicesThread; std::mutex DetectDeviceMutex; + std::function ScheduledBackgroundFunction; + std::mutex BackgroundThreadStateMutex; + /*-----------------------------------------------------*\ + | NOTE: wakes up the background detection thread | + \*-----------------------------------------------------*/ + std::condition_variable BackgroundFunctionStartTrigger; + + std::atomic background_thread_running; std::atomic detection_is_required; std::atomic detection_percent; std::atomic detection_prev_size; std::vector detection_size_entry_used; const char* detection_string; + /*-----------------------------------------------------*\ + | Client Info Changed Callback | + \*-----------------------------------------------------*/ + std::vector ClientInfoChangeCallbacks; + std::vector ClientInfoChangeCallbackArgs; - /*-------------------------------------------------------------------------------------*\ - | Device List Changed Callback | - \*-------------------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Device List Changed Callback | + \*-----------------------------------------------------*/ std::mutex DeviceListChangeMutex; std::vector DeviceListChangeCallbacks; std::vector DeviceListChangeCallbackArgs; - /*-------------------------------------------------------------------------------------*\ - | Detection Progress, Start, and End Callbacks | - \*-------------------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Detection Progress, Start, and End Callbacks | + \*-----------------------------------------------------*/ std::mutex DetectionProgressMutex; std::vector DetectionProgressCallbacks; std::vector DetectionProgressCallbackArgs; @@ -299,12 +350,15 @@ private: std::vector DetectionEndCallbacks; std::vector DetectionEndCallbackArgs; - /*-------------------------------------------------------------------------------------*\ - | I2C/SMBus Adapter List Changed Callback | - \*-------------------------------------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | I2C/SMBus Adapter List Changed Callback | + \*-----------------------------------------------------*/ std::mutex I2CBusListChangeMutex; std::vector I2CBusListChangeCallbacks; std::vector I2CBusListChangeCallbackArgs; - filesystem::path config_dir; + /*-----------------------------------------------------*\ + | OpenRGB configuration directory path | + \*-----------------------------------------------------*/ + filesystem::path config_dir; }; diff --git a/ResourceManagerInterface.h b/ResourceManagerInterface.h new file mode 100644 index 00000000..b858b26a --- /dev/null +++ b/ResourceManagerInterface.h @@ -0,0 +1,68 @@ +/*---------------------------------------------------------*\ +| ResourceManagerInterface.h | +| | +| Provides a virtual interface to ResourceManager for | +| exposing ResourceManager to plugins. Changes to this | +| class structure require a new plugin API version. | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "i2c_smbus.h" +#include "filesystem.h" + +class NetworkClient; +class NetworkServer; +class ProfileManager; +class RGBController; +class SettingsManager; + +typedef void (*ClientInfoChangeCallback)(void *); +typedef void (*DeviceListChangeCallback)(void *); +typedef void (*DetectionProgressCallback)(void *); +typedef void (*DetectionStartCallback)(void *); +typedef void (*DetectionEndCallback)(void *); +typedef void (*I2CBusListChangeCallback)(void *); + +class ResourceManagerInterface +{ +public: + virtual std::vector & GetI2CBusses() = 0; + + virtual void RegisterRGBController(RGBController *rgb_controller) = 0; + virtual void UnregisterRGBController(RGBController *rgb_controller) = 0; + + virtual void RegisterDeviceListChangeCallback(DeviceListChangeCallback new_callback, void * new_callback_arg) = 0; + virtual void RegisterDetectionProgressCallback(DetectionProgressCallback new_callback, void * new_callback_arg) = 0; + virtual void RegisterDetectionStartCallback(DetectionStartCallback new_callback, void * new_callback_arg) = 0; + virtual void RegisterDetectionEndCallback(DetectionEndCallback new_callback, void * new_callback_arg) = 0; + virtual void RegisterI2CBusListChangeCallback(I2CBusListChangeCallback new_callback, void * new_callback_arg) = 0; + + virtual void UnregisterDeviceListChangeCallback(DeviceListChangeCallback callback, void * callback_arg) = 0; + virtual void UnregisterDetectionProgressCallback(DetectionProgressCallback callback, void *callback_arg) = 0; + virtual void UnregisterDetectionStartCallback(DetectionStartCallback callback, void *callback_arg) = 0; + virtual void UnregisterDetectionEndCallback(DetectionEndCallback callback, void *callback_arg) = 0; + virtual void UnregisterI2CBusListChangeCallback(I2CBusListChangeCallback callback, void * callback_arg) = 0; + + virtual std::vector & GetRGBControllers() = 0; + + virtual unsigned int GetDetectionPercent() = 0; + + virtual filesystem::path GetConfigurationDirectory() = 0; + + virtual std::vector& GetClients() = 0; + virtual NetworkServer* GetServer() = 0; + + virtual ProfileManager* GetProfileManager() = 0; + virtual SettingsManager* GetSettingsManager() = 0; + + virtual void UpdateDeviceList() = 0; + virtual void WaitForDeviceDetection() = 0; + +protected: + virtual ~ResourceManagerInterface() {}; +}; diff --git a/SPDAccessor/DDR4DirectAccessor.cpp b/SPDAccessor/DDR4DirectAccessor.cpp new file mode 100644 index 00000000..7579e073 --- /dev/null +++ b/SPDAccessor/DDR4DirectAccessor.cpp @@ -0,0 +1,104 @@ +/*---------------------------------------------------------*\ +| DDR4DirectAccessor.cpp | +| | +| DDR4 SPD accessor implementation using direct i2c | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "DDR4DirectAccessor.h" + +using namespace std::chrono_literals; + +DDR4DirectAccessor::DDR4DirectAccessor(i2c_smbus_interface *bus, uint8_t spd_addr) + : DDR4Accessor(bus, spd_addr) +{ +} + +DDR4DirectAccessor::~DDR4DirectAccessor() +{ +} + +bool DDR4DirectAccessor::isAvailable(i2c_smbus_interface *bus, uint8_t spd_addr) +{ + /*-----------------------------------------------------*\ + | Perform i2c quick transfer to test if i2c address | + | responds | + \*-----------------------------------------------------*/ + int value = bus->i2c_smbus_write_quick(0x36, 0x00); + if(value < 0) + { + return false; + } + + /*-----------------------------------------------------*\ + | Select low page | + \*-----------------------------------------------------*/ + bus->i2c_smbus_write_byte_data(0x36, 0x00, 0xFF); + + std::this_thread::sleep_for(SPD_IO_DELAY); + + /*-----------------------------------------------------*\ + | Read value at address 0 in SPD device | + \*-----------------------------------------------------*/ + value = bus->i2c_smbus_read_byte_data(spd_addr, 0x00); + + /*-----------------------------------------------------*\ + | DDR4 is available if value is 0x23 | + \*-----------------------------------------------------*/ + return(value == 0x23); +} + +SPDAccessor *DDR4DirectAccessor::copy() +{ + return new DDR4DirectAccessor(bus, address); +} + +uint8_t DDR4DirectAccessor::at(uint16_t addr) +{ + /*-----------------------------------------------------*\ + | Ensure address is valid | + \*-----------------------------------------------------*/ + if(addr >= SPD_DDR4_EEPROM_LENGTH) + { + return 0xFF; + } + + /*-----------------------------------------------------*\ + | Switch to the page containing address | + \*-----------------------------------------------------*/ + set_page(addr >> SPD_DDR4_EEPROM_PAGE_SHIFT); + + /*-----------------------------------------------------*\ + | Calculate offset | + \*-----------------------------------------------------*/ + uint8_t offset = (uint8_t)(addr & SPD_DDR4_EEPROM_PAGE_MASK); + + /*-----------------------------------------------------*\ + | Read value at address | + \*-----------------------------------------------------*/ + uint32_t value = bus->i2c_smbus_read_byte_data(address, offset); + + std::this_thread::sleep_for(SPD_IO_DELAY); + + /*-----------------------------------------------------*\ + | Return value | + \*-----------------------------------------------------*/ + return((uint8_t)value); +} + +void DDR4DirectAccessor::set_page(uint8_t page) +{ + /*-----------------------------------------------------*\ + | Switch page if not already active | + \*-----------------------------------------------------*/ + if(current_page != page) + { + bus->i2c_smbus_write_byte_data(0x36 + page, 0x00, 0xFF); + current_page = page; + + std::this_thread::sleep_for(SPD_IO_DELAY); + } +} diff --git a/SPDAccessor/DDR4DirectAccessor.h b/SPDAccessor/DDR4DirectAccessor.h new file mode 100644 index 00000000..f429ceff --- /dev/null +++ b/SPDAccessor/DDR4DirectAccessor.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------*\ +| DDR4DirectAccessor.h | +| | +| DDR4 SPD accessor implementation using direct i2c | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "SPDAccessor.h" + +class DDR4DirectAccessor : public DDR4Accessor +{ + public: + DDR4DirectAccessor(i2c_smbus_interface *bus, uint8_t address); + virtual ~DDR4DirectAccessor(); + + static bool isAvailable(i2c_smbus_interface *bus, uint8_t address); + + virtual SPDAccessor * copy(); + virtual uint8_t at(uint16_t addr); + + private: + uint8_t current_page = 0xFF; + static const uint16_t SPD_DDR4_EEPROM_LENGTH = 512; + static const uint8_t SPD_DDR4_EEPROM_PAGE_SHIFT = 8; + static const uint8_t SPD_DDR4_EEPROM_PAGE_MASK = 0xFF; + + void set_page(uint8_t page); +}; diff --git a/SPDAccessor/DDR5DirectAccessor.cpp b/SPDAccessor/DDR5DirectAccessor.cpp new file mode 100644 index 00000000..43459102 --- /dev/null +++ b/SPDAccessor/DDR5DirectAccessor.cpp @@ -0,0 +1,122 @@ +/*---------------------------------------------------------*\ +| DDR5DirectAccessor.cpp | +| | +| DDR5 SPD accessor implementation using direct i2c | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "DDR5DirectAccessor.h" +#include "LogManager.h" + +using namespace std::chrono_literals; + +DDR5DirectAccessor::DDR5DirectAccessor(i2c_smbus_interface *bus, uint8_t spd_addr) + : DDR5Accessor(bus, spd_addr) +{ +} + +DDR5DirectAccessor::~DDR5DirectAccessor() +{ +} + +bool DDR5DirectAccessor::isAvailable(i2c_smbus_interface *bus, uint8_t spd_addr) +{ + bool retry = true; + + while(true) + { + std::this_thread::sleep_for(SPD_IO_DELAY); + int ddr5Magic = bus->i2c_smbus_read_byte_data(spd_addr, 0x00); + std::this_thread::sleep_for(SPD_IO_DELAY); + int ddr5Sensor = bus->i2c_smbus_read_byte_data(spd_addr, 0x01); + std::this_thread::sleep_for(SPD_IO_DELAY); + + if(ddr5Magic < 0 || ddr5Sensor < 0) + { + break; + } + + LOG_TRACE("[DDR5DirectAccessor] SPD Hub Magic: 0x%02x 0x%02x", ddr5Magic, ddr5Sensor); + + if(ddr5Magic == 0x51 && (ddr5Sensor & 0xEF) == 0x08) + { + return true; + } + + int page = bus->i2c_smbus_read_byte_data(spd_addr, SPD_DDR5_MREG_VIRTUAL_PAGE); + std::this_thread::sleep_for(SPD_IO_DELAY); + + LOG_TRACE("[DDR5DirectAccessor] SPD Page: 0x%02x", page); + if(page < 0) + { + break; + } + else if(retry && page > 0 && page < (SPD_DDR5_EEPROM_LENGTH >> SPD_DDR5_EEPROM_PAGE_SHIFT)) + { + // This still might be a DDR5 module, just the page is off + bus->i2c_smbus_write_byte_data(spd_addr, SPD_DDR5_MREG_VIRTUAL_PAGE, 0); + std::this_thread::sleep_for(SPD_IO_DELAY); + retry = false; + } + else + { + break; + } + } + return false; +} + +SPDAccessor *DDR5DirectAccessor::copy() +{ + DDR5DirectAccessor *access = new DDR5DirectAccessor(bus, address); + access->current_page = this->current_page; + return access; +} + +uint8_t DDR5DirectAccessor::at(uint16_t addr) +{ + /*-----------------------------------------------------*\ + | Ensure address is valid | + \*-----------------------------------------------------*/ + if(addr >= SPD_DDR5_EEPROM_LENGTH) + { + return 0xFF; + } + + /*-----------------------------------------------------*\ + | Switch to the page containing address | + \*-----------------------------------------------------*/ + set_page(addr >> SPD_DDR5_EEPROM_PAGE_SHIFT); + + /*-----------------------------------------------------*\ + | Calculate offset | + \*-----------------------------------------------------*/ + uint8_t offset = (uint8_t)(addr & SPD_DDR5_EEPROM_PAGE_MASK) | 0x80; + + /*-----------------------------------------------------*\ + | Read value at address | + \*-----------------------------------------------------*/ + uint32_t value = bus->i2c_smbus_read_byte_data(address, offset); + + std::this_thread::sleep_for(SPD_IO_DELAY); + + /*-----------------------------------------------------*\ + | Return value | + \*-----------------------------------------------------*/ + return((uint8_t)value); +} + +void DDR5DirectAccessor::set_page(uint8_t page) +{ + /*-----------------------------------------------------*\ + | Switch page if not already active | + \*-----------------------------------------------------*/ + if(current_page != page) + { + bus->i2c_smbus_write_byte_data(address, SPD_DDR5_MREG_VIRTUAL_PAGE, page); + current_page = page; + std::this_thread::sleep_for(SPD_IO_DELAY); + } +} diff --git a/SPDAccessor/DDR5DirectAccessor.h b/SPDAccessor/DDR5DirectAccessor.h new file mode 100644 index 00000000..0f3e4732 --- /dev/null +++ b/SPDAccessor/DDR5DirectAccessor.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------*\ +| DDR5DirectAccessor.h | +| | +| DDR5 SPD accessor implementation using direct i2c | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "SPDAccessor.h" + +class DDR5DirectAccessor : public DDR5Accessor +{ + public: + DDR5DirectAccessor(i2c_smbus_interface *bus, uint8_t address); + virtual ~DDR5DirectAccessor(); + + static bool isAvailable(i2c_smbus_interface *bus, uint8_t address); + + virtual SPDAccessor * copy(); + virtual uint8_t at(uint16_t addr); + + private: + uint8_t current_page = 0xFF; + static const uint16_t SPD_DDR5_EEPROM_LENGTH = 2048; + static const uint8_t SPD_DDR5_EEPROM_PAGE_SHIFT = 7; + static const uint8_t SPD_DDR5_EEPROM_PAGE_MASK = 0x7F; + static const uint8_t SPD_DDR5_MREG_VIRTUAL_PAGE = 0x0B; + + void set_page(uint8_t page); +}; diff --git a/SPDAccessor/EE1004Accessor_Linux.cpp b/SPDAccessor/EE1004Accessor_Linux.cpp new file mode 100644 index 00000000..fcfdf084 --- /dev/null +++ b/SPDAccessor/EE1004Accessor_Linux.cpp @@ -0,0 +1,66 @@ +/*---------------------------------------------------------*\ +| EE1004Accessor_Linux.cpp | +| | +| SPD accessor implementation using e1004 driver on Linux | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "EE1004Accessor_Linux.h" +#include "filesystem.h" + +const char *EE1004Accessor::SPD_EE1004_PATH = "/sys/bus/i2c/drivers/ee1004/%u-%04x/eeprom"; + +EE1004Accessor::EE1004Accessor(i2c_smbus_interface *bus, uint8_t spd_addr) + : DDR4Accessor(bus, spd_addr), valid(false) +{ +} + +EE1004Accessor::~EE1004Accessor() +{ +} + +bool EE1004Accessor::isAvailable(i2c_smbus_interface *bus, uint8_t spd_addr) +{ + int size = snprintf(nullptr, 0, SPD_EE1004_PATH, bus->bus_id, spd_addr); + char *path = new char[size+1]; + snprintf(path, size+1, SPD_EE1004_PATH, bus->bus_id, spd_addr); + bool result = std::filesystem::exists(path); + delete[] path; + return result; +} + +SPDAccessor *EE1004Accessor::copy() +{ + EE1004Accessor *access = new EE1004Accessor(bus, address); + memcpy(access->dump, this->dump, sizeof(this->dump)); + access->valid = this->valid; + return access; +} + +uint8_t EE1004Accessor::at(uint16_t addr) +{ + if(!valid) + { + readEEPROM(); + } + return dump[addr]; +} + +void EE1004Accessor::readEEPROM() +{ + int size = snprintf(nullptr, 0, SPD_EE1004_PATH, bus->bus_id, address); + char *filename = new char[size+1]; + snprintf(filename, size+1, SPD_EE1004_PATH, bus->bus_id, address); + + std::ifstream eeprom_file(filename, std::ios::in | std::ios::binary); + if(eeprom_file) + { + eeprom_file.read((char*)dump, sizeof(dump)); + eeprom_file.close(); + } + delete[] filename; +} diff --git a/SPDAccessor/EE1004Accessor_Linux.h b/SPDAccessor/EE1004Accessor_Linux.h new file mode 100644 index 00000000..7347cc2f --- /dev/null +++ b/SPDAccessor/EE1004Accessor_Linux.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------*\ +| EE1004Accessor_Linux.h | +| | +| SPD accessor implementation using e1004 driver on Linux | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "SPDAccessor.h" + +class EE1004Accessor : public DDR4Accessor +{ + public: + EE1004Accessor(i2c_smbus_interface *bus, uint8_t address); + virtual ~EE1004Accessor(); + + static bool isAvailable(i2c_smbus_interface *bus, uint8_t address); + + virtual SPDAccessor *copy(); + virtual uint8_t at(uint16_t addr); + + private: + static const char *SPD_EE1004_PATH; + + uint8_t dump[512]; + bool valid; + + void readEEPROM(); +}; diff --git a/SPDAccessor/SPD5118Accessor_Linux.cpp b/SPDAccessor/SPD5118Accessor_Linux.cpp new file mode 100644 index 00000000..4d40aa3e --- /dev/null +++ b/SPDAccessor/SPD5118Accessor_Linux.cpp @@ -0,0 +1,67 @@ +/*---------------------------------------------------------*\ +| SPD5118Accessor_Linux.cpp | +| | +| DDR5 SPD accessor implementation using spd5118 driver | +| on Linux | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "SPD5118Accessor_Linux.h" +#include "filesystem.h" + +const char *SPD5118Accessor::SPD_SPD5118_PATH = "/sys/bus/i2c/drivers/spd5118/%u-%04x/eeprom"; + +SPD5118Accessor::SPD5118Accessor(i2c_smbus_interface *bus, uint8_t spd_addr) + : DDR5Accessor(bus, spd_addr), valid(false) +{ +} + +SPD5118Accessor::~SPD5118Accessor() +{ +} + +bool SPD5118Accessor::isAvailable(i2c_smbus_interface *bus, uint8_t spd_addr) +{ + int size = snprintf(nullptr, 0, SPD_SPD5118_PATH, bus->bus_id, spd_addr); + char *path = new char[size+1]; + snprintf(path, size+1, SPD_SPD5118_PATH, bus->bus_id, spd_addr); + bool result = std::filesystem::exists(path); + delete[] path; + return result; +} + +SPDAccessor *SPD5118Accessor::copy() +{ + SPD5118Accessor *access = new SPD5118Accessor(bus, address); + memcpy(access->dump, this->dump, sizeof(this->dump)); + access->valid = this->valid; + return access; +} + +uint8_t SPD5118Accessor::at(uint16_t addr) +{ + if(!valid) + { + readEEPROM(); + } + return dump[addr]; +} + +void SPD5118Accessor::readEEPROM() +{ + int size = snprintf(nullptr, 0, SPD_SPD5118_PATH, bus->bus_id, address); + char *filename = new char[size+1]; + snprintf(filename, size+1, SPD_SPD5118_PATH, bus->bus_id, address); + + std::ifstream eeprom_file(filename, std::ios::in | std::ios::binary); + if(eeprom_file) + { + eeprom_file.read((char*)dump, sizeof(dump)); + eeprom_file.close(); + } + delete[] filename; +} diff --git a/SPDAccessor/SPD5118Accessor_Linux.h b/SPDAccessor/SPD5118Accessor_Linux.h new file mode 100644 index 00000000..93fca3a4 --- /dev/null +++ b/SPDAccessor/SPD5118Accessor_Linux.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------*\ +| SPD5118Accessor_Linux.h | +| | +| DDR5 SPD accessor implementation using spd5118 driver | +| on Linux | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "SPDAccessor.h" + +class SPD5118Accessor : public DDR5Accessor +{ + public: + SPD5118Accessor(i2c_smbus_interface *bus, uint8_t address); + virtual ~SPD5118Accessor(); + + static bool isAvailable(i2c_smbus_interface *bus, uint8_t address); + + virtual SPDAccessor *copy(); + virtual uint8_t at(uint16_t addr); + + private: + static const char *SPD_SPD5118_PATH; + + uint8_t dump[2048]; + bool valid; + + void readEEPROM(); +}; diff --git a/SPDAccessor/SPDAccessor.cpp b/SPDAccessor/SPDAccessor.cpp new file mode 100644 index 00000000..837b9e88 --- /dev/null +++ b/SPDAccessor/SPDAccessor.cpp @@ -0,0 +1,149 @@ +/*---------------------------------------------------------*\ +| SPDAccessor.cpp | +| | +| Access to SPD information on various DIMMs | +| | +| Milan Cermak (krysmanta) 09 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "DDR4DirectAccessor.h" +#include "DDR5DirectAccessor.h" +#include "LogManager.h" +#include "SPDAccessor.h" + +#ifdef __linux__ +#include "EE1004Accessor_Linux.h" +#include "SPD5118Accessor_Linux.h" +#endif + +using namespace std::chrono_literals; + +const char *spd_memory_type_name[] = +{ + "Reserved", + "FPM", + "EDO", + "Nibble", + "SDR", + "Multiplex ROM", + "DDR", + "DDR", + "DDR2", + "FB", + "FB Probe", + "DDR3", + "DDR4", + "Reserved", + "DDR4e", + "LPDDR3", + "LPDDR4", + "LPDDR4X", + "DDR5", + "LPDDR5" +}; + +SPDAccessor::SPDAccessor(i2c_smbus_interface *bus, uint8_t spd_addr) +{ + this->bus = bus; + this->address = spd_addr; +} + +SPDAccessor::~SPDAccessor() +{ +} + +SPDAccessor *SPDAccessor::for_memory_type(SPDMemoryType type, i2c_smbus_interface *bus, uint8_t spd_addr) +{ + /*-----------------------------------------------------*\ + | DDR4 can use DDR4DirectAccessor or EE1004Accessor | + \*-----------------------------------------------------*/ + if(type == SPD_DDR4_SDRAM) + { +#ifdef __linux__ + if(EE1004Accessor::isAvailable(bus, spd_addr)) + { + return(new EE1004Accessor(bus, spd_addr)); + } +#endif + return(new DDR4DirectAccessor(bus, spd_addr)); + } + + /*-----------------------------------------------------*\ + | DDR5 can use DDR5DirectAccessor or SPD5118Accessor | + \*-----------------------------------------------------*/ + if(type == SPD_DDR5_SDRAM) + { +#ifdef __linux__ + if(SPD5118Accessor::isAvailable(bus, spd_addr)) + { + return(new SPD5118Accessor(bus, spd_addr)); + } +#endif + return(new DDR5DirectAccessor(bus, spd_addr)); + } + + return(nullptr); +}; + +/*---------------------------------------------------------*\ +| Internal implementation for specific memory type. | +\*---------------------------------------------------------*/ + +DDR4Accessor::DDR4Accessor(i2c_smbus_interface *bus, uint8_t spd_addr) + : SPDAccessor(bus, spd_addr) +{ +} + +DDR4Accessor::~DDR4Accessor() +{ +} + +SPDMemoryType DDR4Accessor::memory_type() +{ + return((SPDMemoryType)(this->at(0x02))); +} + +uint16_t DDR4Accessor::jedec_id() +{ + return((this->at(0x140) << 8) + (this->at(0x141) & 0x7f) - 1); +} + +uint8_t DDR4Accessor::manufacturer_data(uint16_t index) +{ + if(index > 28) + { + return 0; + } + return this->at(0x161 + index); +} + +DDR5Accessor::DDR5Accessor(i2c_smbus_interface *bus, uint8_t spd_addr) + : SPDAccessor(bus, spd_addr) +{ +} + +DDR5Accessor::~DDR5Accessor() +{ +} + +SPDMemoryType DDR5Accessor::memory_type() +{ + return((SPDMemoryType)(this->at(0x02))); +} + +uint16_t DDR5Accessor::jedec_id() +{ + return((this->at(0x200) << 8) + (this->at(0x201) & 0x7f) - 1); +} + +uint8_t DDR5Accessor::manufacturer_data(uint16_t index) +{ + if(index > 84) + { + return 0; + } + return this->at(0x22B + index); +} diff --git a/SPDAccessor/SPDAccessor.h b/SPDAccessor/SPDAccessor.h new file mode 100644 index 00000000..256b922d --- /dev/null +++ b/SPDAccessor/SPDAccessor.h @@ -0,0 +1,57 @@ +/*---------------------------------------------------------*\ +| SPDAccessor.h | +| | +| Access to SPD information on various DIMMs | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "SPDCommon.h" + +class SPDAccessor +{ + public: + SPDAccessor(i2c_smbus_interface *bus, uint8_t address); + virtual ~SPDAccessor(); + + static SPDAccessor *for_memory_type(SPDMemoryType type, i2c_smbus_interface *bus, uint8_t address); + + virtual SPDMemoryType memory_type() = 0; + virtual uint16_t jedec_id() = 0; + virtual uint8_t manufacturer_data(uint16_t index) = 0; + + virtual SPDAccessor *copy() = 0; + + virtual uint8_t at(uint16_t addr) = 0; + + protected: + i2c_smbus_interface *bus; + uint8_t address; +}; + +/*---------------------------------------------------------*\ +| Internal implementation for specific memory type. | +\*---------------------------------------------------------*/ + +class DDR4Accessor : public SPDAccessor +{ + public: + DDR4Accessor(i2c_smbus_interface *bus, uint8_t address); + virtual ~DDR4Accessor(); + virtual SPDMemoryType memory_type(); + virtual uint16_t jedec_id(); + virtual uint8_t manufacturer_data(uint16_t index); +}; + +class DDR5Accessor : public SPDAccessor +{ + public: + DDR5Accessor(i2c_smbus_interface *bus, uint8_t address); + virtual ~DDR5Accessor(); + virtual SPDMemoryType memory_type(); + virtual uint16_t jedec_id(); + virtual uint8_t manufacturer_data(uint16_t index); +}; diff --git a/SPDAccessor/SPDCommon.h b/SPDAccessor/SPDCommon.h new file mode 100644 index 00000000..302b8e39 --- /dev/null +++ b/SPDAccessor/SPDCommon.h @@ -0,0 +1,56 @@ +/*---------------------------------------------------------*\ +| SPDCommon.h | +| | +| Common definitions for SPD | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "i2c_smbus.h" + +typedef enum +{ + JEDEC_KINGSTON = 0x0117, + JEDEC_CORSAIR = 0x021D, + JEDEC_ADATA = 0x044A, + JEDEC_GSKILL = 0x044C, + JEDEC_TEAMGROUP = 0x046E, + JEDEC_KINGSTON_2 = 0x300F, + JEDEC_KINGSTON_3 = 0x3011, + JEDEC_MUSHKIN = 0x8313, + JEDEC_GIGABYTE = 0x8971, + JEDEC_THERMALTAKE = 0x8A41, + JEDEC_PATRIOT = 0x8501 +} JedecIdentifier; + +typedef enum +{ + SPD_RESERVED = 0, + SPD_FPM_DRAM = 1, + SPD_EDO = 2, + SPD_NIBBLE = 3, + SPD_SDR_SDRAM = 4, + SPD_MUX_ROM = 5, + SPD_DDR_SGRAM = 6, + SPD_DDR_SDRAM = 7, + SPD_DDR2_SDRAM = 8, + SPD_FB_DIMM = 9, + SPD_FB_PROBE = 10, + SPD_DDR3_SDRAM = 11, + SPD_DDR4_SDRAM = 12, + SPD_RESERVED2 = 13, + SPD_DDR4E_SDRAM = 14, + SPD_LPDDR3_SDRAM = 15, + SPD_LPDDR4_SDRAM = 16, + SPD_LPDDR4X_SDRAM = 17, + SPD_DDR5_SDRAM = 18, + SPD_LPDDR5_SDRAM = 19 +} SPDMemoryType; + +#define SPD_IO_DELAY 1ms + +extern const char *spd_memory_type_name[]; diff --git a/SPDAccessor/SPDDetector.cpp b/SPDAccessor/SPDDetector.cpp new file mode 100644 index 00000000..f3a850a1 --- /dev/null +++ b/SPDAccessor/SPDDetector.cpp @@ -0,0 +1,140 @@ +/*---------------------------------------------------------*\ +| SPDDetector.cpp | +| | +| Detector for DRAM modules using SPD information | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "DDR4DirectAccessor.h" +#include "DDR5DirectAccessor.h" +#include "LogManager.h" +#include "SPDDetector.h" + +#ifdef __linux__ +#include "EE1004Accessor_Linux.h" +#include "SPD5118Accessor_Linux.h" +#endif + +SPDDetector::SPDDetector(i2c_smbus_interface *bus, uint8_t address, SPDMemoryType mem_type = SPD_RESERVED) + : bus(bus), address(address), mem_type(mem_type), valid(false) +{ + detect_memory_type(); +} + +bool SPDDetector::is_valid() const +{ + return(valid); +} + +SPDMemoryType SPDDetector::memory_type() const +{ + return(mem_type); +} + +void SPDDetector::detect_memory_type() +{ + SPDAccessor *accessor; + + /*---------------------------------------------------------*\ + | On Linux, attempt to use the ee1004 or spd5118 drivers to | + | access SPD on DDR4 and DDR5, respectively | + \*---------------------------------------------------------*/ +#ifdef __linux__ + if(EE1004Accessor::isAvailable(bus, address)) + { + LOG_DEBUG("[SPDDetector] Probing DRAM using EE1004 Accessor on bus %d, address 0x%02x", bus->bus_id, address); + accessor = new EE1004Accessor(bus, address); + } + else if(SPD5118Accessor::isAvailable(bus, address)) + { + LOG_DEBUG("[SPDDetector] Probing DRAM using SPD5118 Accessor on bus %d, address 0x%02x", bus->bus_id, address); + accessor = new SPD5118Accessor(bus, address); + } + else +#endif + /*---------------------------------------------------------*\ + | Otherwise, access the SPD using a direct accessor using | + | i2c for DDR4 and DDR5 | + \*---------------------------------------------------------*/ + if((mem_type == SPD_RESERVED + || mem_type == SPD_DDR4_SDRAM + || mem_type == SPD_DDR4E_SDRAM + || mem_type == SPD_LPDDR4_SDRAM + || mem_type == SPD_LPDDR4X_SDRAM) + && DDR4DirectAccessor::isAvailable(bus, address)) + { + LOG_DEBUG("[SPDDetector] Probing DRAM using DDR4 Direct Accessor on bus %d, address 0x%02x", bus->bus_id, address); + accessor = new DDR4DirectAccessor(bus, address); + } + else if((mem_type == SPD_RESERVED + || mem_type == SPD_DDR5_SDRAM + || mem_type == SPD_LPDDR5_SDRAM) + && DDR5DirectAccessor::isAvailable(bus, address)) + { + LOG_DEBUG("[SPDDetector] Probing DRAM using DDR5 Direct Accessor on bus %d, address 0x%02x", bus->bus_id, address); + accessor = new DDR5DirectAccessor(bus, address); + } + /*---------------------------------------------------------*\ + | Otherwise, probe the SPD directly using i2c, probably an | + | older system than DDR4 | + \*---------------------------------------------------------*/ + else if(mem_type == SPD_RESERVED) + { + LOG_DEBUG("[SPDDetector] Probing DRAM older than DDR4 on bus %d, address 0x%02x", bus->bus_id, address); + + int value = bus->i2c_smbus_read_byte_data(address, 0x02); + + if(value < 0) + { + valid = false; + } + else + { + mem_type = (SPDMemoryType)value; + + /*-------------------------------------------------*\ + | We are only interested in DDR4 and DDR5 systems | + \*-------------------------------------------------*/ + valid = (mem_type == SPD_DDR4_SDRAM + || mem_type == SPD_DDR4E_SDRAM + || mem_type == SPD_LPDDR4_SDRAM + || mem_type == SPD_LPDDR4X_SDRAM + || mem_type == SPD_DDR5_SDRAM + || mem_type == SPD_LPDDR5_SDRAM); + } + + return; + } + /*---------------------------------------------------------*\ + | If memory type could not be determined, detection failed | + \*---------------------------------------------------------*/ + else + { + LOG_DEBUG("[SPDDetector] Memory type could not be determined for bus %d, address 0x%02x", bus->bus_id, address); + valid = false; + return; + } + + /*---------------------------------------------------------*\ + | If an accessor was created, save the memory type | + \*---------------------------------------------------------*/ + valid = true; + mem_type = accessor->memory_type(); + + /*---------------------------------------------------------*\ + | Delete the accessor | + \*---------------------------------------------------------*/ + delete accessor; +} + +uint8_t SPDDetector::spd_address() const +{ + return(this->address); +} + +i2c_smbus_interface *SPDDetector::smbus() const +{ + return(this->bus); +} diff --git a/SPDAccessor/SPDDetector.h b/SPDAccessor/SPDDetector.h new file mode 100644 index 00000000..f3cebbbd --- /dev/null +++ b/SPDAccessor/SPDDetector.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------*\ +| SPDDetector.h | +| | +| Detector for DRAM modules using SPD information | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "SPDAccessor.h" +#include "SPDCommon.h" + +class SPDDetector +{ + public: + SPDDetector(i2c_smbus_interface *bus, uint8_t address, SPDMemoryType mem_type); + + bool is_valid() const; + SPDMemoryType memory_type() const; + uint8_t spd_address() const; + i2c_smbus_interface *smbus() const; + + private: + i2c_smbus_interface *bus; + uint8_t address; + SPDMemoryType mem_type; + bool valid; + + void detect_memory_type(); +}; diff --git a/SPDAccessor/SPDWrapper.cpp b/SPDAccessor/SPDWrapper.cpp new file mode 100644 index 00000000..9d3c99f4 --- /dev/null +++ b/SPDAccessor/SPDWrapper.cpp @@ -0,0 +1,132 @@ +/*---------------------------------------------------------*\ +| SPDWrapper.cpp | +| | +| Wrapper for DRAM modules using SPD information | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include "SPDWrapper.h" + +SPDWrapper::SPDWrapper(const SPDWrapper &wrapper) +{ + if(wrapper.accessor != nullptr) + { + this->accessor = wrapper.accessor->copy(); + } + this->addr = wrapper.addr; + this->mem_type = wrapper.mem_type; + + /*-----------------------------------------------------*\ + | Read the JEDEC ID and cache its value | + | This saves a significant amount of time over reading | + | the JEDEC ID each time it is accessed | + \*-----------------------------------------------------*/ + if(accessor == nullptr) + { + jedec_id_val = 0x0000; + } + else + { + jedec_id_val = accessor->jedec_id(); + } +} + +SPDWrapper::SPDWrapper(const SPDDetector &detector) +{ + this->addr = detector.spd_address(); + this->mem_type = detector.memory_type(); + + /*-----------------------------------------------------*\ + | Allocate a new accessor | + \*-----------------------------------------------------*/ + this->accessor = SPDAccessor::for_memory_type(this->mem_type, detector.smbus(), this->addr); + + /*-----------------------------------------------------*\ + | Read the JEDEC ID and cache its value | + | This saves a significant amount of time over reading | + | the JEDEC ID each time it is accessed | + \*-----------------------------------------------------*/ + if(accessor == nullptr) + { + jedec_id_val = 0x0000; + } + else + { + jedec_id_val = accessor->jedec_id(); + } +} + +SPDWrapper::~SPDWrapper() +{ + delete accessor; +} + +SPDMemoryType SPDWrapper::memory_type() +{ + return mem_type; +} + +uint8_t SPDWrapper::address() +{ + return this->addr; +} + +int SPDWrapper::index() +{ + return this->addr - 0x50; +} + +uint16_t SPDWrapper::jedec_id() +{ + return jedec_id_val; +} + +uint8_t SPDWrapper::manufacturer_data(uint16_t index) +{ + if(accessor == nullptr) + { + return 0x00; + } + return accessor->manufacturer_data(index); +} + +/*---------------------------------------------------------*\ +| Helper functions for easier collection handling. | +\*---------------------------------------------------------*/ + +bool is_jedec_in_slots(std::vector &slots, uint16_t jedec_id) +{ + /*-----------------------------------------------------*\ + | Search through all SPD slots to see if any have the | + | desired JEDEC ID | + \*-----------------------------------------------------*/ + for(SPDWrapper &slot : slots) + { + if(slot.jedec_id() == jedec_id) + { + return true; + } + } + return false; +} + +std::vector slots_with_jedec(std::vector &slots, uint16_t jedec_id) +{ + std::vector matching_slots; + + /*-----------------------------------------------------*\ + | Search through all SPD slots and build a list of all | + | slots matching the desired JEDEC ID | + \*-----------------------------------------------------*/ + for(SPDWrapper &slot : slots) + { + if(slot.jedec_id() == jedec_id) + { + matching_slots.push_back(&slot); + } + } + + return matching_slots; +} diff --git a/SPDAccessor/SPDWrapper.h b/SPDAccessor/SPDWrapper.h new file mode 100644 index 00000000..68b44f15 --- /dev/null +++ b/SPDAccessor/SPDWrapper.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------*\ +| SPDWrapper.h | +| | +| Wrapper for DRAM modules using SPD information | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include "SPDAccessor.h" +#include "SPDCommon.h" +#include "SPDDetector.h" + +class SPDWrapper +{ + public: + SPDWrapper(const SPDWrapper &wrapper); + SPDWrapper(const SPDDetector &detector); + ~SPDWrapper(); + + uint8_t address(); + SPDMemoryType memory_type(); + int index(); + uint16_t jedec_id(); + uint8_t manufacturer_data(uint16_t index); + + private: + SPDAccessor *accessor = nullptr; + uint8_t addr; + uint16_t jedec_id_val; + SPDMemoryType mem_type; +}; + +/*-------------------------------------------------------------------------*\ +| Helper functions for easier collection handling. | +\*-------------------------------------------------------------------------*/ + +bool is_jedec_in_slots(std::vector &slots, uint16_t jedec_id); +std::vector slots_with_jedec(std::vector &slots, uint16_t jedec_id); diff --git a/SettingsManager.cpp b/SettingsManager.cpp index 93a80410..6dc5a80a 100644 --- a/SettingsManager.cpp +++ b/SettingsManager.cpp @@ -1,23 +1,24 @@ -/*-----------------------------------------*\ -| SettingsManager.cpp | -| | -| OpenRGB Settings Manager maintains a list| -| of application settings in JSON format. | -| Other components may register settings | -| with this class and store/load values. | -| | -| Adam Honse (CalcProgrammer1) 11/4/2020 | -\*-----------------------------------------*/ - -#include "SettingsManager.h" -#include "LogManager.h" +/*---------------------------------------------------------*\ +| SettingsManager.cpp | +| | +| OpenRGB Settings Manager maintains a list of application| +| settings in JSON format. Other components may register | +| settings with this class and store/load values. | +| | +| Adam Honse (CalcProgrammer1) 04 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #include #include +#include "SettingsManager.h" +#include "LogManager.h" SettingsManager::SettingsManager() { - + config_found = false; } SettingsManager::~SettingsManager() @@ -27,73 +28,88 @@ SettingsManager::~SettingsManager() json SettingsManager::GetSettings(std::string settings_key) { - /*---------------------------------------------------------*\ - | Check to see if the key exists in the settings store and | - | return the settings associated with the key if it exists | - \*---------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Check to see if the key exists in the settings store | + | and return the settings associated with the key if it | + | exists. We lock the mutex to protect the value from | + | changing while data is being read and copy before | + | unlocking. | + \*-----------------------------------------------------*/ + json result; + + mutex.lock(); if(settings_data.contains(settings_key)) { - return(settings_data[settings_key]); + result = settings_data[settings_key]; } - /*---------------------------------------------------------*\ - | If the settings store doesn't contain the key, create an | - | empty json and return it | - \*---------------------------------------------------------*/ - json empty; + mutex.unlock(); - return(empty); + return result; } void SettingsManager::SetSettings(std::string settings_key, json new_settings) { + mutex.lock(); settings_data[settings_key] = new_settings; + mutex.unlock(); } void SettingsManager::LoadSettings(const filesystem::path& filename) { - /*---------------------------------------------------------*\ - | Clear any stored settings before loading | - \*---------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Clear any stored settings before loading | + \*-----------------------------------------------------*/ + mutex.lock(); + settings_data.clear(); - /*---------------------------------------------------------*\ - | Store settings filename, so we can save to it later | - \*---------------------------------------------------------*/ + /*-----------------------------------------------------*\ + | Store settings filename, so we can save to it later | + \*-----------------------------------------------------*/ settings_filename = filename; - /*---------------------------------------------------------*\ - | Open input file in binary mode | - \*---------------------------------------------------------*/ - std::ifstream settings_file(settings_filename, std::ios::in | std::ios::binary); - - /*---------------------------------------------------------*\ - | Read settings into JSON store | - \*---------------------------------------------------------*/ - if(settings_file) + /*-----------------------------------------------------*\ + | Open input file in binary mode | + \*-----------------------------------------------------*/ + config_found = filesystem::exists(filename); + if(config_found) { - try - { - settings_file >> settings_data; - } - catch(const std::exception& e) - { - /*-------------------------------------------------*\ - | If an exception was caught, that means the JSON | - | parsing failed. Clear out any data in the store | - | as it is corrupt. | - \*-------------------------------------------------*/ - LOG_ERROR("[SettingsManager] JSON parsing failed: %s", e.what()); + std::ifstream settings_file(settings_filename, std::ios::in | std::ios::binary); - settings_data.clear(); + /*-------------------------------------------------*\ + | Read settings into JSON store | + \*-------------------------------------------------*/ + if(settings_file) + { + try + { + settings_file >> settings_data; + } + catch(const std::exception& e) + { + /*-----------------------------------------*\ + | If an exception was caught, that means | + | the JSON parsing failed. Clear out any | + | data in the store as it is corrupt. We | + | could attempt a reload for backup | + | location | + \*-----------------------------------------*/ + LOG_ERROR("[SettingsManager] JSON parsing failed: %s", e.what()); + + settings_data.clear(); + } } + + settings_file.close(); } - settings_file.close(); + mutex.unlock(); } void SettingsManager::SaveSettings() { + mutex.lock(); std::ofstream settings_file(settings_filename, std::ios::out | std::ios::binary); if(settings_file) @@ -109,4 +125,5 @@ void SettingsManager::SaveSettings() settings_file.close(); } + mutex.unlock(); } diff --git a/SettingsManager.h b/SettingsManager.h index 3e1e3e84..2251fadc 100644 --- a/SettingsManager.h +++ b/SettingsManager.h @@ -1,17 +1,20 @@ -/*-----------------------------------------*\ -| SettingsManager.h | -| | -| OpenRGB Settings Manager maintains a list| -| of application settings in JSON format. | -| Other components may register settings | -| with this class and store/load values. | -| | -| Adam Honse (CalcProgrammer1) 11/4/2020 | -\*-----------------------------------------*/ +/*---------------------------------------------------------*\ +| SettingsManager.h | +| | +| OpenRGB Settings Manager maintains a list of application| +| settings in JSON format. Other components may register | +| settings with this class and store/load values. | +| | +| Adam Honse (CalcProgrammer1) 04 Nov 2020 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ #pragma once -#include "json.hpp" +#include +#include #include "filesystem.h" using json = nlohmann::json; @@ -45,4 +48,6 @@ private: json settings_data; json settings_prototype; filesystem::path settings_filename; + std::mutex mutex; + bool config_found; }; diff --git a/StringUtils.cpp b/StringUtils.cpp index 614679c1..58ece3c5 100644 --- a/StringUtils.cpp +++ b/StringUtils.cpp @@ -1,40 +1,84 @@ -#include "StringUtils.h" +/*---------------------------------------------------------*\ +| StringUtils.cpp | +| | +| String utility functions | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include #include +#include "StringUtils.h" const char* StringUtils::wchar_to_char(const wchar_t* pwchar) { - if (pwchar == nullptr) + if(pwchar == nullptr) { return ""; } - // get the number of characters in the string. - int currentCharIndex = 0; - char currentChar = pwchar[currentCharIndex]; - while (currentChar != '\0') + /*-----------------------------------------------------*\ + | Get the number of characters in the string. | + \*-----------------------------------------------------*/ + int currentCharIndex = 0; + char currentChar = (char)pwchar[currentCharIndex]; + + while(currentChar != '\0') { currentCharIndex++; - currentChar = pwchar[currentCharIndex]; + currentChar = (char)pwchar[currentCharIndex]; } const int charCount = currentCharIndex + 1; - // allocate a new block of memory size char (1 byte) instead of wide char (2 bytes) + /*-----------------------------------------------------*\ + | Allocate a new block of memory size char (1 byte) | + | instead of wide char (2 bytes) | + \*-----------------------------------------------------*/ char* filePathC = (char*)malloc(sizeof(char) * charCount); - for (int i = 0; i < charCount; i++) + for(int i = 0; i < charCount; i++) { - // convert to char (1 byte) - char character = pwchar[i]; + /*-------------------------------------------------*\ + | Convert to char (1 byte) | + \*-------------------------------------------------*/ + char character = (char)pwchar[i]; *filePathC = character; filePathC += sizeof(char); } + filePathC += '\0'; filePathC -= (sizeof(char) * charCount); - return filePathC; + return(filePathC); +} + +std::string StringUtils::wstring_to_string(const std::wstring wstring) +{ + std::wstring_convert, wchar_t> converter; + + return(converter.to_bytes(wstring)); +} + +std::string StringUtils::u16string_to_string(const std::u16string wstring) +{ + std::wstring_convert,char16_t> converter; + + return(converter.to_bytes(wstring)); +} + +const std::string StringUtils::remove_null_terminating_chars(std::string input) +{ + while(!input.empty() && input.back() == 0) + { + input.pop_back(); + } + + return(input); } diff --git a/StringUtils.h b/StringUtils.h index 7b52f46b..f69bb65d 100644 --- a/StringUtils.h +++ b/StringUtils.h @@ -1,10 +1,21 @@ -#ifndef STRING_UTILS_H -#define STRING_UTILS_H +/*---------------------------------------------------------*\ +| StringUtils.h | +| | +| String utility functions | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include class StringUtils { public: static const char* wchar_to_char(const wchar_t* pwchar); + static std::string wstring_to_string(const std::wstring wstring); + static std::string u16string_to_string(const std::u16string wstring); + static const std::string remove_null_terminating_chars(std::string input); }; - -#endif // STRING_UTILS_H diff --git a/SuspendResume/SuspendResume.h b/SuspendResume/SuspendResume.h new file mode 100644 index 00000000..48b614c2 --- /dev/null +++ b/SuspendResume/SuspendResume.h @@ -0,0 +1,31 @@ +/*---------------------------------------------------------*\ +| SuspendResume.h | +| | +| Suspend/resume common implementation | +| | +| Zach Deibert (zachdeibert) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +class SuspendResumeListenerBase +{ +protected: + virtual void OnSuspend() = 0; + virtual void OnResume() = 0; +}; + +#ifdef _WIN32 +#include "SuspendResume_Windows.h" +#endif + +#ifdef __APPLE__ +#include "SuspendResume_MacOS.h" +#endif + +#if defined(__linux__) || defined(__FreeBSD__) +#include "SuspendResume_Linux_FreeBSD.h" +#endif diff --git a/SuspendResume/SuspendResume_Linux_FreeBSD.cpp b/SuspendResume/SuspendResume_Linux_FreeBSD.cpp new file mode 100644 index 00000000..a9ceb0c7 --- /dev/null +++ b/SuspendResume/SuspendResume_Linux_FreeBSD.cpp @@ -0,0 +1,39 @@ +/*---------------------------------------------------------*\ +| SuspendResume_Linux_FreeBSD.cpp | +| | +| Suspend/resume Linux/FreeBSD implementation | +| | +| Zach Deibert (zachdeibert) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "SuspendResume.h" + +SuspendResumeLoginManager::SuspendResumeLoginManager(SuspendResumeListener *srl) : srl(srl), bus(QDBusConnection::systemBus()) +{ + bus.connect("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "PrepareForSleep", this, SLOT(PrepareForSleep(bool))); +} + +SuspendResumeLoginManager::~SuspendResumeLoginManager() +{ + bus.disconnect("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "PrepareForSleep", this, SLOT(PrepareForSleep(bool))); +} + +void SuspendResumeLoginManager::PrepareForSleep(bool mode) +{ + if(mode) + { + srl->OnSuspend(); + } + else + { + srl->OnResume(); + } +} + +SuspendResumeListener::SuspendResumeListener() : login_manager(this) +{ +} diff --git a/SuspendResume/SuspendResume_Linux_FreeBSD.h b/SuspendResume/SuspendResume_Linux_FreeBSD.h new file mode 100644 index 00000000..f6248bdd --- /dev/null +++ b/SuspendResume/SuspendResume_Linux_FreeBSD.h @@ -0,0 +1,45 @@ +/*---------------------------------------------------------*\ +| SuspendResume_Linux_FreeBSD.h | +| | +| Suspend/resume Linux/FreeBSD implementation | +| | +| Zach Deibert (zachdeibert) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "SuspendResume.h" + +class SuspendResumeListener; + +class SuspendResumeLoginManager : public QObject +{ + Q_OBJECT + +public: + SuspendResumeLoginManager(SuspendResumeListener *srl); + ~SuspendResumeLoginManager(); + +public slots: + void PrepareForSleep(bool mode); + +private: + SuspendResumeListener *srl; + QDBusConnection bus; +}; + +class SuspendResumeListener : public SuspendResumeListenerBase +{ + friend class SuspendResumeLoginManager; + +protected: + SuspendResumeListener(); + +private: + SuspendResumeLoginManager login_manager; +}; diff --git a/SuspendResume/SuspendResume_MacOS.cpp b/SuspendResume/SuspendResume_MacOS.cpp new file mode 100644 index 00000000..f38505e6 --- /dev/null +++ b/SuspendResume/SuspendResume_MacOS.cpp @@ -0,0 +1,45 @@ +/*---------------------------------------------------------*\ +| SuspendResume_MacOS.cpp | +| | +| Suspend/resume MacOS implementation | +| | +| Zach Deibert (zachdeibert) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include "SuspendResume.h" +#include "IOKit/pwr_mgt/IOPMLib.h" +#include "IOKit/IOMessage.h" + +SuspendResumeListener::SuspendResumeListener() +{ + root_port = IORegisterForSystemPower(this, &port_ref, &SuspendResumeListener::SystemPowerCallback, ¬ifier); + CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(port_ref), kCFRunLoopCommonModes); +} + +SuspendResumeListener::~SuspendResumeListener() +{ + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(port_ref), kCFRunLoopCommonModes); + IODeregisterForSystemPower(¬ifier); + IOServiceClose(root_port); + IONotificationPortDestroy(port_ref); +} + +void SuspendResumeListener::SystemPowerCallback(void *refcon, io_service_t service, uint32_t message_type, void *message_argument) +{ + (void)service; + SuspendResumeListener *spl = (SuspendResumeListener *)refcon; + switch(message_type) + { + case kIOMessageSystemWillSleep: + spl->OnSuspend(); + IOAllowPowerChange(spl->root_port, (intptr_t)message_argument); + break; + case kIOMessageSystemHasPoweredOn: + spl->OnResume(); + break; + } +} diff --git a/SuspendResume/SuspendResume_MacOS.h b/SuspendResume/SuspendResume_MacOS.h new file mode 100644 index 00000000..ef5638a1 --- /dev/null +++ b/SuspendResume/SuspendResume_MacOS.h @@ -0,0 +1,31 @@ +/*---------------------------------------------------------*\ +| SuspendResume_MacOS.h | +| | +| Suspend/resume MacOS implementation | +| | +| Zach Deibert (zachdeibert) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include "SuspendResume.h" +#include "IOKit/pwr_mgt/IOPMLib.h" +#include "IOKit/IOMessage.h" + +class SuspendResumeListener : public SuspendResumeListenerBase +{ +protected: + SuspendResumeListener(); + virtual ~SuspendResumeListener(); + +private: + static void SystemPowerCallback(void *refcon, io_service_t service, uint32_t message_type, void *message_argument); + + io_connect_t root_port; + IONotificationPortRef port_ref; + io_object_t notifier; +}; diff --git a/SuspendResume/SuspendResume_Windows.cpp b/SuspendResume/SuspendResume_Windows.cpp new file mode 100644 index 00000000..8d0784b8 --- /dev/null +++ b/SuspendResume/SuspendResume_Windows.cpp @@ -0,0 +1,48 @@ +/*---------------------------------------------------------*\ +| SuspendResume_Windows.cpp | +| | +| Suspend/resume Windows implementation | +| | +| Zach Deibert (zachdeibert) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include "SuspendResume.h" +#include "windows.h" + +SuspendResumeListener::SuspendResumeListener() +{ + QCoreApplication::instance()->installNativeEventFilter(this); +} + +SuspendResumeListener::~SuspendResumeListener() +{ + QCoreApplication::instance()->removeNativeEventFilter(this); +} + +bool SuspendResumeListener::nativeEventFilter(const QByteArray &event_type, void *message, NEFResultType *result) +{ + (void)result; + if(event_type == "windows_generic_MSG") + { + switch(((MSG *)message)->message) + { + case WM_POWERBROADCAST: + switch(((MSG *)message)->wParam) + { + case PBT_APMSUSPEND: + OnSuspend(); + break; + case PBT_APMRESUMEAUTOMATIC: + OnResume(); + break; + } + break; + } + } + return false; +} diff --git a/SuspendResume/SuspendResume_Windows.h b/SuspendResume/SuspendResume_Windows.h new file mode 100644 index 00000000..fd490773 --- /dev/null +++ b/SuspendResume/SuspendResume_Windows.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------*\ +| SuspendResume_Windows.h | +| | +| Suspend/resume Windows implementation | +| | +| Zach Deibert (zachdeibert) 12 Nov 2024 | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#pragma once + +#include +#include +#include "SuspendResume.h" + +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#define NEFResultType long +#else +#define NEFResultType qintptr +#endif + +class SuspendResumeListener : public SuspendResumeListenerBase, private QAbstractNativeEventFilter +{ +protected: + SuspendResumeListener(); + virtual ~SuspendResumeListener(); + +private: + bool nativeEventFilter(const QByteArray &event_type, void *message, NEFResultType *result); +}; diff --git a/cli.cpp b/cli.cpp index 96d7c3ed..8d851835 100644 --- a/cli.cpp +++ b/cli.cpp @@ -1,3 +1,17 @@ +/*---------------------------------------------------------*\ +| cli.cpp | +| | +| OpenRGB command line interface | +| | +| This file is part of the OpenRGB project | +| SPDX-License-Identifier: GPL-2.0-only | +\*---------------------------------------------------------*/ + +#include +#include +#include +#include +#include #include "AutoStart.h" #include "filesystem.h" #include "ProfileManager.h" @@ -9,25 +23,23 @@ #include "LogManager.h" #include "Colors.h" -#include -#include -#include -#include -#include - /*-------------------------------------------------------------*\ | Quirk for MSVC; which doesn't support this case-insensitive | | function | \*-------------------------------------------------------------*/ #ifdef _WIN32 #include - #define strcasecmp strcmpi + #define strcasecmp _strcmpi #endif using namespace std::chrono_literals; static std::string profile_save_filename = ""; const unsigned int brightness_percentage = 100; +const unsigned int speed_percentage = 100; + +static int preserve_argc = 0; +static char** preserve_argv = nullptr; enum { @@ -47,7 +59,8 @@ struct DeviceOptions int zone = -1; std::vector> colors; std::string mode; - unsigned int brightness; + unsigned int speed = 100; + unsigned int brightness = 100; unsigned int size; bool random_colors = false; bool hasSize = false; @@ -332,7 +345,7 @@ unsigned int ParseMode(DeviceOptions& options, std::vector &rgb } } - std::cout << "Error: Mode '" + options.mode + "' not available for device '" + rgb_controllers[options.device]->name + "'" << std::endl; + std::cout << "Error: Mode '" + options.mode + "' not available for device '" + rgb_controllers[options.device]->GetName() + "'" << std::endl; return false; } @@ -385,6 +398,7 @@ void OptionHelp() help_text += "--startminimized Starts the GUI minimized to tray. Implies --gui, even if not specified\n"; help_text += "--client [IP]:[Port] Starts an SDK client on the given IP:Port (assumes port 6742 if not specified)\n"; help_text += "--server Starts the SDK's server\n"; + help_text += "--server-host Sets the SDK's server host. Default: 0.0.0.0 (all network interfaces)\n"; help_text += "--server-port Sets the SDK's server port. Default: 6742 (1024-65535)\n"; help_text += "-l, --list-devices Lists every compatible device with their number\n"; help_text += "-d, --device [0-9 | \"name\"] Selects device to apply colors and/or effect to, or applies to all devices if omitted\n"; @@ -396,7 +410,8 @@ void OptionHelp() help_text += " If there are more LEDs than colors given, the last color will be applied to the remaining LEDs\n"; help_text += "-m, --mode [breathing | static | ...] Sets the mode to be applied, check --list-devices to see which modes are supported on your device\n"; help_text += "-b, --brightness [0-100] Sets the brightness as a percentage if the mode supports brightness\n"; - help_text += "-s, --size [0-N] Sets the new size of the specified device zone.\n"; + help_text += "-s, --speed [0-100] Sets the speed as a percentage if the mode supports speed\n"; + help_text += "-sz, --size [0-N] Sets the new size of the specified device zone.\n"; help_text += " Must be specified after specifying a zone.\n"; help_text += " If the specified size is out of range, or the zone does not offer resizing capability, the size will not be changed\n"; help_text += "-V, --version Display version and software build information\n"; @@ -452,7 +467,7 @@ void OptionListDevices(std::vector& rgb_controllers) /*---------------------------------------------------------*\ | Print device name | \*---------------------------------------------------------*/ - std::cout << controller_idx << ": " << controller->name << std::endl; + std::cout << controller_idx << ": " << controller->GetName() << std::endl; /*---------------------------------------------------------*\ | Print device type | @@ -462,33 +477,33 @@ void OptionListDevices(std::vector& rgb_controllers) /*---------------------------------------------------------*\ | Print device description | \*---------------------------------------------------------*/ - if(!controller->description.empty()) + if(!controller->GetDescription().empty()) { - std::cout << " Description: " << controller->description << std::endl; + std::cout << " Description: " << controller->GetDescription() << std::endl; } /*---------------------------------------------------------*\ | Print device version | \*---------------------------------------------------------*/ - if(!controller->version.empty()) + if(!controller->GetVersion().empty()) { - std::cout << " Version: " << controller->version << std::endl; + std::cout << " Version: " << controller->GetLocation() << std::endl; } /*---------------------------------------------------------*\ | Print device location | \*---------------------------------------------------------*/ - if(!controller->location.empty()) + if(!controller->GetLocation().empty()) { - std::cout << " Location: " << controller->location << std::endl; + std::cout << " Location: " << controller->GetLocation() << std::endl; } /*---------------------------------------------------------*\ | Print device serial | \*---------------------------------------------------------*/ - if(!controller->serial.empty()) + if(!controller->GetSerial().empty()) { - std::cout << " Serial: " << controller->serial << std::endl; + std::cout << " Serial: " << controller->GetSerial() << std::endl; } /*---------------------------------------------------------*\ @@ -553,6 +568,8 @@ bool OptionDevice(std::vector* current_devices, std::string argum { int current_device = std::stoi(argument); + LOG_TRACE("[CLI] using device number %d for argument %s", current_device, argument.c_str()); + if((current_device >= static_cast(rgb_controllers.size())) || (current_device < 0)) { throw nullptr; @@ -574,17 +591,22 @@ bool OptionDevice(std::vector* current_devices, std::string argum { if(argument.length() > 1) { + std::string argument_lower = argument; + std::transform(argument_lower.begin(), argument_lower.end(), argument_lower.begin(), ::tolower); + + LOG_TRACE("[CLI] Searching for %s", argument_lower.c_str()); + for(unsigned int i = 0; i < rgb_controllers.size(); i++) { /*---------------------------------------------------------*\ | If the argument is not a number then check all the | | controllers names for a match | \*---------------------------------------------------------*/ - std::string name = rgb_controllers[i]->name; + std::string name = rgb_controllers[i]->GetName(); std::transform(name.begin(), name.end(), name.begin(), ::tolower); - std::transform(argument.begin(), argument.end(), argument.begin(), ::tolower); + LOG_TRACE("[CLI] Comparing to %s", name.c_str()); - if(name.find(argument) != std::string::npos) + if(name.find(argument_lower) != std::string::npos) { found = true; @@ -602,11 +624,16 @@ bool OptionDevice(std::vector* current_devices, std::string argum } else { - std::cout << "Error: Invalid device ID: " + argument << std::endl; + std::cout << "Error: Empty device ID" << std::endl; return false; } } + if(!found) + { + std::cout << "Error: Cannot find device \"" << argument << "\"" << std::endl; + } + return found; } @@ -714,6 +741,50 @@ bool OptionMode(std::vector* current_devices, std::string argumen } } + if(!found) + { + std::cout << "Error: No devices for mode \"" << argument << "\"" << std::endl; + } + return found; +} + +bool OptionSpeed(std::vector* current_devices, std::string argument, Options* options) +{ + if(argument.size() == 0) + { + std::cout << "Error: --speed passed with no argument" << std::endl; + return false; + } + + /*---------------------------------------------------------*\ + | If a device is not selected i.e. size() == 0 | + | then add speed to allDeviceOptions | + \*---------------------------------------------------------*/ + bool found = false; + DeviceOptions* currentDevOpts = &options->allDeviceOptions; + + if(current_devices->size() == 0) + { + currentDevOpts->speed = std::min(std::max(std::stoi(argument), 0),(int)speed_percentage); + currentDevOpts->hasOption = true; + found = true; + } + else + { + for(size_t i = 0; i < current_devices->size(); i++) + { + DeviceOptions* currentDevOpts = ¤t_devices->at(i); + + currentDevOpts->speed = std::min(std::max(std::stoi(argument), 0),(int)speed_percentage); + currentDevOpts->hasOption = true; + found = true; + } + } + + if(!found) + { + std::cout << "Error: No devices for speed \"" << argument << "\"" << std::endl; + } return found; } @@ -750,6 +821,10 @@ bool OptionBrightness(std::vector* current_devices, std::string a } } + if(!found) + { + std::cout << "Error: No devices for brightness \"" << argument << "\"" << std::endl; + } return found; } @@ -813,12 +888,12 @@ bool OptionProfile(std::string argument, std::vector& rgb_contr RGBController* device = rgb_controllers[controller_idx]; device->DeviceUpdateMode(); - LOG_DEBUG("Updating mode for %s to %i", device->name.c_str(), device->active_mode); + LOG_DEBUG("[CLI] Updating mode for %s to %i", device->GetName().c_str(), device->active_mode); if(device->modes[device->active_mode].color_mode == MODE_COLORS_PER_LED) { device->DeviceUpdateLEDs(); - LOG_DEBUG("Mode uses per-LED color, also updating LEDs"); + LOG_DEBUG("[CLI] Mode uses per-LED color, also updating LEDs"); } } @@ -841,7 +916,7 @@ bool OptionSaveProfile(std::string argument) return(true); } -int ProcessOptions(int argc, char* argv[], Options* options, std::vector& rgb_controllers) +int ProcessOptions(Options* options, std::vector& rgb_controllers) { unsigned int ret_flags = 0; int arg_index = 1; @@ -855,18 +930,18 @@ int ProcessOptions(int argc, char* argv[], Options* options, std::vector& rgb_cont device->modes[mode].brightness = device->modes[mode].brightness_min + new_brightness; } + if((device->modes[mode].flags & MODE_FLAG_HAS_SPEED)) + { + unsigned int new_speed = device->modes[mode].speed_max - device->modes[mode].speed_min; + new_speed *= options.speed; + new_speed /= speed_percentage; + + device->modes[mode].speed = device->modes[mode].speed_min + new_speed; + } + /*---------------------------------------------------------*\ | Determine which color mode this mode uses and update | | colors accordingly | @@ -1122,7 +1220,7 @@ void ApplyOptions(DeviceOptions& options, std::vector& rgb_cont if(options.zone < 0) { start_from = &device->colors[0]; - led_count = device->leds.size(); + led_count = (unsigned int)device->leds.size(); } else { @@ -1158,7 +1256,8 @@ void ApplyOptions(DeviceOptions& options, std::vector& rgb_cont } else { - std::cout << "Wrong number of colors specified for mode" << std::endl; + std::cout << "Wrong number of colors specified for mode " + device->modes[mode].name << std::endl; + std::cout << "Please provide between " + std::to_string(device->modes[mode].colors_min) + " and " + std::to_string(device->modes[mode].colors_min) + " colors" << std::endl; exit(0); } break; @@ -1194,6 +1293,9 @@ unsigned int cli_pre_detection(int argc, char* argv[]) bool server_start = false; bool print_help = false; + preserve_argc = argc; + preserve_argv = argv; + #ifdef _WIN32 int fake_argc; wchar_t** argvw = CommandLineToArgvW(GetCommandLineW(), &fake_argc); @@ -1204,7 +1306,7 @@ unsigned int cli_pre_detection(int argc, char* argv[]) std::string option = argv[arg_index]; std::string argument = ""; - LOG_DEBUG("Parsing CLI option: %s", option.c_str()); + LOG_DEBUG("[CLI] Parsing CLI option: %s", option.c_str()); /*---------------------------------------------------------*\ | Handle options that take an argument | @@ -1239,11 +1341,11 @@ unsigned int cli_pre_detection(int argc, char* argv[]) if(filesystem::is_directory(config_path)) { ResourceManager::get()->SetConfigurationDirectory(config_path); - LOG_INFO("Setting config directory to %s",argument.c_str()); // TODO: Use config_path in logs somehow + LOG_INFO("[CLI] Setting config directory to %s",argument.c_str()); // TODO: Use config_path in logs somehow } else { - LOG_ERROR("'%s' is not a valid directory",argument.c_str()); // TODO: Use config_path in logs somehow + LOG_ERROR("[CLI] '%s' is not a valid directory",argument.c_str()); // TODO: Use config_path in logs somehow print_help = true; break; } @@ -1306,8 +1408,9 @@ unsigned int cli_pre_detection(int argc, char* argv[]) std::this_thread::sleep_for(10ms); } - ResourceManager::get()->GetClients().push_back(client); + ResourceManager::get()->RegisterNetworkClient(client); + cfg_args++; arg_index++; } @@ -1395,7 +1498,7 @@ unsigned int cli_pre_detection(int argc, char* argv[]) } else { - LOG_ERROR("Loglevel out of range: %d (0-6)", level); + LOG_ERROR("[CLI] Loglevel out of range: %d (0-6)", level); print_help = true; break; } @@ -1432,7 +1535,7 @@ unsigned int cli_pre_detection(int argc, char* argv[]) } else { - LOG_ERROR("Invalid loglevel"); + LOG_ERROR("[CLI] Invalid loglevel"); print_help = true; break; } @@ -1440,7 +1543,7 @@ unsigned int cli_pre_detection(int argc, char* argv[]) } else { - LOG_ERROR("Missing argument for --loglevel"); + LOG_ERROR("[CLI] Missing argument for --loglevel"); print_help = true; break; } @@ -1624,7 +1727,7 @@ unsigned int cli_pre_detection(int argc, char* argv[]) return(ret_flags); } -unsigned int cli_post_detection(int argc, char *argv[]) +unsigned int cli_post_detection() { /*---------------------------------------------------------*\ | Wait for device detection | @@ -1640,7 +1743,7 @@ unsigned int cli_post_detection(int argc, char *argv[]) | Process the argument options | \*---------------------------------------------------------*/ Options options; - unsigned int ret_flags = ProcessOptions(argc, argv, &options, rgb_controllers); + unsigned int ret_flags = ProcessOptions(&options, rgb_controllers); /*---------------------------------------------------------*\ | If the return flags are set, exit CLI mode without | @@ -1652,7 +1755,7 @@ unsigned int cli_post_detection(int argc, char *argv[]) break; case RET_FLAG_PRINT_HELP: - OptionHelp(); + std::cout << "Run `OpenRGB --help` for syntax" << std::endl; exit(-1); break; @@ -1689,11 +1792,11 @@ unsigned int cli_post_detection(int argc, char *argv[]) { if(ResourceManager::get()->GetProfileManager()->SaveProfile(profile_save_filename)) { - LOG_INFO("Profile saved successfully"); + LOG_INFO("[CLI] Profile saved successfully"); } else { - LOG_ERROR("Profile saving failed"); + LOG_ERROR("[CLI] Profile saving failed"); } } diff --git a/cli.h b/cli.h new file mode 100644 index 00000000..45e15b37 --- /dev/null +++ b/cli.h @@ -0,0 +1,19 @@ +#ifndef CLI_H +#define CLI_H + +unsigned int cli_pre_detection(int argc, char* argv[]); +unsigned int cli_post_detection(); + +enum +{ + RET_FLAG_PRINT_HELP = 1, + RET_FLAG_START_GUI = 2, + RET_FLAG_I2C_TOOLS = 4, + RET_FLAG_START_MINIMIZED = 8, + RET_FLAG_NO_DETECT = 16, + RET_FLAG_CLI_POST_DETECTION = 32, + RET_FLAG_START_SERVER = 64, + RET_FLAG_NO_AUTO_CONNECT = 128, +}; + +#endif diff --git a/debian/control b/debian/control index 010af1c6..68b9038d 100644 --- a/debian/control +++ b/debian/control @@ -22,7 +22,6 @@ Depends: ${misc:Depends}, udev, Recommends: - openrazer-driver-dkms, openrgb-dkms-drivers, Conflicts: openrgb-udev, diff --git a/debian/openrgb.postinst b/debian/openrgb.postinst index 9b59441f..20ad8034 100644 --- a/debian/openrgb.postinst +++ b/debian/openrgb.postinst @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # -e is not set should this step fail for whatever reason the installation is still valid set -u -o pipefail @@ -6,7 +6,7 @@ set -u -o pipefail # Reload rules if [ -f /bin/udevadm ]; then udevadm control --reload-rules || echo "done" - udevadm trigger; + udevadm trigger || : else echo echo "\/-------------------------------------------------------\\" diff --git a/dependencies/CRCpp/CRC.h b/dependencies/CRCpp/CRC.h index 8bab176a..f737cc45 100644 --- a/dependencies/CRCpp/CRC.h +++ b/dependencies/CRCpp/CRC.h @@ -1,11 +1,11 @@ /** @file CRC.h @author Daniel Bahr - @version 1.0.1.0 + @version 1.2.0.0 @copyright @parblock CRC++ - Copyright (c) 2020, Daniel Bahr + Copyright (c) 2022, Daniel Bahr All rights reserved. Redistribution and use in source and binary forms, with or without @@ -47,19 +47,20 @@ #define crcpp_uint64 - Specifies the type used to store CRCs that have a width between 33 and 64 bits (inclusive). This type is not used in CRC calculations. Defaults to ::std::uint64_t. #define crcpp_size - This type is used for loop iteration and function signatures only. Defaults to ::std::size_t. - */ #define CRCPP_USE_NAMESPACE - Define to place all CRC++ code within the ::CRCPP namespace. - /* #define CRCPP_BRANCHLESS - Define to enable a branchless CRC implementation. The branchless implementation uses a single integer multiplication in the bit-by-bit calculation instead of a small conditional. The branchless implementation may be faster on processor architectures which support single-instruction integer multiplication. #define CRCPP_USE_CPP11 - Define to enables C++11 features (move semantics, constexpr, static_assert, etc.). - #define CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS - Define to include definitions for little-used CRCs. + #define CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS - Define to include definitions for little-used CRCs. */ #ifndef CRCPP_CRC_H_ #define CRCPP_CRC_H_ +/* OpenRGB: We define our configuration macros here. */ +#define CRCPP_USE_NAMESPACE + #include // Includes CHAR_BIT #ifdef CRCPP_USE_CPP11 #include // Includes ::std::size_t @@ -204,6 +205,18 @@ public: template static CRCType Calculate(const void * data, crcpp_size size, const Table & lookupTable, CRCType crc); + template + static CRCType CalculateBits(const void * data, crcpp_size size, const Parameters & parameters); + + template + static CRCType CalculateBits(const void * data, crcpp_size size, const Parameters & parameters, CRCType crc); + + template + static CRCType CalculateBits(const void * data, crcpp_size size, const Table & lookupTable); + + template + static CRCType CalculateBits(const void * data, crcpp_size size, const Table & lookupTable, CRCType crc); + // Common CRCs up to 64 bits. // Note: Check values are the computed CRCs when given an ASCII input of "123456789" (without null terminator) #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS @@ -214,6 +227,7 @@ public: static const Parameters< crcpp_uint8, 6> & CRC_6_CDMA2000A(); static const Parameters< crcpp_uint8, 6> & CRC_6_CDMA2000B(); static const Parameters< crcpp_uint8, 6> & CRC_6_ITU(); + static const Parameters< crcpp_uint8, 6> & CRC_6_NR(); static const Parameters< crcpp_uint8, 7> & CRC_7(); #endif static const Parameters< crcpp_uint8, 8> & CRC_8(); @@ -221,9 +235,11 @@ public: static const Parameters< crcpp_uint8, 8> & CRC_8_EBU(); static const Parameters< crcpp_uint8, 8> & CRC_8_MAXIM(); static const Parameters< crcpp_uint8, 8> & CRC_8_WCDMA(); + static const Parameters< crcpp_uint8, 8> & CRC_8_LTE(); static const Parameters & CRC_10(); static const Parameters & CRC_10_CDMA2000(); static const Parameters & CRC_11(); + static const Parameters & CRC_11_NR(); static const Parameters & CRC_12_CDMA2000(); static const Parameters & CRC_12_DECT(); static const Parameters & CRC_12_UMTS(); @@ -234,6 +250,7 @@ public: static const Parameters & CRC_16_ARC(); static const Parameters & CRC_16_BUYPASS(); static const Parameters & CRC_16_CCITTFALSE(); + static const Parameters & CRC_16_MCRF4XX(); #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS static const Parameters & CRC_16_CDMA2000(); static const Parameters & CRC_16_CMS(); @@ -257,6 +274,9 @@ public: static const Parameters & CRC_24(); static const Parameters & CRC_24_FLEXRAYA(); static const Parameters & CRC_24_FLEXRAYB(); + static const Parameters & CRC_24_LTEA(); + static const Parameters & CRC_24_LTEB(); + static const Parameters & CRC_24_NRC(); static const Parameters & CRC_30(); #endif static const Parameters & CRC_32(); @@ -301,6 +321,9 @@ private: template static CRCType CalculateRemainder(const void * data, crcpp_size size, const Table & lookupTable, CRCType remainder); + + template + static CRCType CalculateRemainderBits(unsigned char byte, crcpp_size numBits, const Parameters & parameters, CRCType remainder); }; /** @@ -426,7 +449,7 @@ inline void CRC::Table::InitTable() /** @brief Computes a CRC. @param[in] data Data over which CRC will be computed - @param[in] size Size of the data + @param[in] size Size of the data, in bytes @param[in] parameters CRC parameters @tparam CRCType Integer type for storing the CRC result @tparam CRCWidth Number of bits in the CRC @@ -445,7 +468,7 @@ inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Paramete @brief Appends additional data to a previous CRC calculation. @note This function can be used to compute multi-part CRCs. @param[in] data Data over which CRC will be computed - @param[in] size Size of the data + @param[in] size Size of the data, in bytes @param[in] parameters CRC parameters @param[in] crc CRC from a previous calculation @tparam CRCType Integer type for storing the CRC result @@ -467,7 +490,7 @@ inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Paramete /** @brief Computes a CRC via a lookup table. @param[in] data Data over which CRC will be computed - @param[in] size Size of the data + @param[in] size Size of the data, in bytes @param[in] lookupTable CRC lookup table @tparam CRCType Integer type for storing the CRC result @tparam CRCWidth Number of bits in the CRC @@ -489,7 +512,7 @@ inline CRCType CRC::Calculate(const void * data, crcpp_size size, const Table(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); } +/** + @brief Computes a CRC. + @param[in] data Data over which CRC will be computed + @param[in] size Size of the data, in bits + @param[in] parameters CRC parameters + @tparam CRCType Integer type for storing the CRC result + @tparam CRCWidth Number of bits in the CRC + @return CRC +*/ +template +inline CRCType CRC::CalculateBits(const void * data, crcpp_size size, const Parameters & parameters) +{ + CRCType remainder = parameters.initialValue; + + // Calculate the remainder on a whole number of bytes first, then call + // a special-case function for the remaining bits. + crcpp_size wholeNumberOfBytes = size / CHAR_BIT; + if (wholeNumberOfBytes > 0) + { + remainder = CalculateRemainder(data, wholeNumberOfBytes, parameters, remainder); + } + + crcpp_size remainingNumberOfBits = size % CHAR_BIT; + if (remainingNumberOfBits != 0) + { + unsigned char lastByte = *(reinterpret_cast(data) + wholeNumberOfBytes); + remainder = CalculateRemainderBits(lastByte, remainingNumberOfBits, parameters, remainder); + } + + // No need to mask the remainder here; the mask will be applied in the Finalize() function. + + return Finalize(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); +} +/** + @brief Appends additional data to a previous CRC calculation. + @note This function can be used to compute multi-part CRCs. + @param[in] data Data over which CRC will be computed + @param[in] size Size of the data, in bits + @param[in] parameters CRC parameters + @param[in] crc CRC from a previous calculation + @tparam CRCType Integer type for storing the CRC result + @tparam CRCWidth Number of bits in the CRC + @return CRC +*/ +template +inline CRCType CRC::CalculateBits(const void * data, crcpp_size size, const Parameters & parameters, CRCType crc) +{ + CRCType remainder = UndoFinalize(crc, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); + + // Calculate the remainder on a whole number of bytes first, then call + // a special-case function for the remaining bits. + crcpp_size wholeNumberOfBytes = size / CHAR_BIT; + if (wholeNumberOfBytes > 0) + { + remainder = CalculateRemainder(data, wholeNumberOfBytes, parameters, parameters.initialValue); + } + + crcpp_size remainingNumberOfBits = size % CHAR_BIT; + if (remainingNumberOfBits != 0) + { + unsigned char lastByte = *(reinterpret_cast(data) + wholeNumberOfBytes); + remainder = CalculateRemainderBits(lastByte, remainingNumberOfBits, parameters, remainder); + } + + // No need to mask the remainder here; the mask will be applied in the Finalize() function. + + return Finalize(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); +} + +/** + @brief Computes a CRC via a lookup table. + @param[in] data Data over which CRC will be computed + @param[in] size Size of the data, in bits + @param[in] lookupTable CRC lookup table + @tparam CRCType Integer type for storing the CRC result + @tparam CRCWidth Number of bits in the CRC + @return CRC +*/ +template +inline CRCType CRC::CalculateBits(const void * data, crcpp_size size, const Table & lookupTable) +{ + const Parameters & parameters = lookupTable.GetParameters(); + + CRCType remainder = parameters.initialValue; + + // Calculate the remainder on a whole number of bytes first, then call + // a special-case function for the remaining bits. + crcpp_size wholeNumberOfBytes = size / CHAR_BIT; + if (wholeNumberOfBytes > 0) + { + remainder = CalculateRemainder(data, wholeNumberOfBytes, lookupTable, remainder); + } + + crcpp_size remainingNumberOfBits = size % CHAR_BIT; + if (remainingNumberOfBits != 0) + { + unsigned char lastByte = *(reinterpret_cast(data) + wholeNumberOfBytes); + remainder = CalculateRemainderBits(lastByte, remainingNumberOfBits, parameters, remainder); + } + + // No need to mask the remainder here; the mask will be applied in the Finalize() function. + + return Finalize(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); +} + +/** + @brief Appends additional data to a previous CRC calculation using a lookup table. + @note This function can be used to compute multi-part CRCs. + @param[in] data Data over which CRC will be computed + @param[in] size Size of the data, in bits + @param[in] lookupTable CRC lookup table + @param[in] crc CRC from a previous calculation + @tparam CRCType Integer type for storing the CRC result + @tparam CRCWidth Number of bits in the CRC + @return CRC +*/ +template +inline CRCType CRC::CalculateBits(const void * data, crcpp_size size, const Table & lookupTable, CRCType crc) +{ + const Parameters & parameters = lookupTable.GetParameters(); + + CRCType remainder = UndoFinalize(crc, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); + + // Calculate the remainder on a whole number of bytes first, then call + // a special-case function for the remaining bits. + crcpp_size wholeNumberOfBytes = size / CHAR_BIT; + if (wholeNumberOfBytes > 0) + { + remainder = CalculateRemainder(data, wholeNumberOfBytes, lookupTable, parameters.initialValue); + } + + crcpp_size remainingNumberOfBits = size % CHAR_BIT; + if (remainingNumberOfBits > 0) + { + unsigned char lastByte = *(reinterpret_cast(data) + wholeNumberOfBytes); + remainder = CalculateRemainderBits(lastByte, remainingNumberOfBits, parameters, remainder); + } + + // No need to mask the remainder here; the mask will be applied in the Finalize() function. + + return Finalize(remainder, parameters.finalXOR, parameters.reflectInput != parameters.reflectOutput); +} + /** @brief Reflects (i.e. reverses the bits within) an integer value. @param[in] value Value to reflect @@ -592,7 +758,7 @@ inline CRCType CRC::UndoFinalize(CRCType crc, CRCType finalXOR, bool reflectOutp /** @brief Computes a CRC remainder. @param[in] data Data over which the remainder will be computed - @param[in] size Size of the data + @param[in] size Size of the data, in bytes @param[in] parameters CRC parameters @param[in] remainder Running CRC remainder. Can be an initial value or the result of a previous CRC remainder calculation. @tparam CRCType Integer type for storing the CRC result @@ -709,7 +875,7 @@ inline CRCType CRC::CalculateRemainder(const void * data, crcpp_size size, const /** @brief Computes a CRC remainder using lookup table. @param[in] data Data over which the remainder will be computed - @param[in] size Size of the data + @param[in] size Size of the data, in bytes @param[in] lookupTable CRC lookup table @param[in] remainder Running CRC remainder. Can be an initial value or the result of a previous CRC remainder calculation. @tparam CRCType Integer type for storing the CRC result @@ -767,6 +933,90 @@ inline CRCType CRC::CalculateRemainder(const void * data, crcpp_size size, const return remainder; } +template +inline CRCType CRC::CalculateRemainderBits(unsigned char byte, crcpp_size numBits, const Parameters & parameters, CRCType remainder) +{ + // Slightly different implementations based on the parameters. The current implementations try to eliminate as much + // computation from the inner loop (looping over each bit) as possible. + if (parameters.reflectInput) + { + CRCType polynomial = CRC::Reflect(parameters.polynomial, CRCWidth); + remainder = static_cast(remainder ^ byte); + + // An optimizing compiler might choose to unroll this loop. + for (crcpp_size i = 0; i < numBits; ++i) + { +#ifdef CRCPP_BRANCHLESS + // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following: + // if (remainder & 1) + // remainder = (remainder >> 1) ^ polynomial; + // else + // remainder >>= 1; + remainder = static_cast((remainder >> 1) ^ ((remainder & 1) * polynomial)); +#else + remainder = static_cast((remainder & 1) ? ((remainder >> 1) ^ polynomial) : (remainder >> 1)); +#endif + } + } + else if (CRCWidth >= CHAR_BIT) + { + static crcpp_constexpr CRCType CRC_WIDTH_MINUS_ONE(CRCWidth - CRCType(1)); +#ifndef CRCPP_BRANCHLESS + static crcpp_constexpr CRCType CRC_HIGHEST_BIT_MASK(CRCType(1) << CRC_WIDTH_MINUS_ONE); +#endif + // The conditional expression is used to avoid a -Wshift-count-overflow warning. + static crcpp_constexpr CRCType SHIFT((CRCWidth >= CHAR_BIT) ? static_cast(CRCWidth - CHAR_BIT) : 0); + + remainder = static_cast(remainder ^ (static_cast(byte) << SHIFT)); + + // An optimizing compiler might choose to unroll this loop. + for (crcpp_size i = 0; i < numBits; ++i) + { +#ifdef CRCPP_BRANCHLESS + // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following: + // if (remainder & CRC_HIGHEST_BIT_MASK) + // remainder = (remainder << 1) ^ parameters.polynomial; + // else + // remainder <<= 1; + remainder = static_cast((remainder << 1) ^ (((remainder >> CRC_WIDTH_MINUS_ONE) & 1) * parameters.polynomial)); +#else + remainder = static_cast((remainder & CRC_HIGHEST_BIT_MASK) ? ((remainder << 1) ^ parameters.polynomial) : (remainder << 1)); +#endif + } + } + else + { + static crcpp_constexpr CRCType CHAR_BIT_MINUS_ONE(CHAR_BIT - 1); +#ifndef CRCPP_BRANCHLESS + static crcpp_constexpr CRCType CHAR_BIT_HIGHEST_BIT_MASK(CRCType(1) << CHAR_BIT_MINUS_ONE); +#endif + // The conditional expression is used to avoid a -Wshift-count-overflow warning. + static crcpp_constexpr CRCType SHIFT((CHAR_BIT >= CRCWidth) ? static_cast(CHAR_BIT - CRCWidth) : 0); + + CRCType polynomial = static_cast(parameters.polynomial << SHIFT); + remainder = static_cast((remainder << SHIFT) ^ byte); + + // An optimizing compiler might choose to unroll this loop. + for (crcpp_size i = 0; i < numBits; ++i) + { +#ifdef CRCPP_BRANCHLESS + // Clever way to avoid a branch at the expense of a multiplication. This code is equivalent to the following: + // if (remainder & CHAR_BIT_HIGHEST_BIT_MASK) + // remainder = (remainder << 1) ^ polynomial; + // else + // remainder <<= 1; + remainder = static_cast((remainder << 1) ^ (((remainder >> CHAR_BIT_MINUS_ONE) & 1) * polynomial)); +#else + remainder = static_cast((remainder & CHAR_BIT_HIGHEST_BIT_MASK) ? ((remainder << 1) ^ polynomial) : (remainder << 1)); +#endif + } + + remainder = static_cast(remainder >> SHIFT); + } + + return remainder; +} + #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS /** @brief Returns a set of parameters for CRC-4 ITU. @@ -894,6 +1144,25 @@ inline const CRC::Parameters & CRC::CRC_6_ITU() return parameters; } +/** + @brief Returns a set of parameters for CRC-6 NR. + @note The parameters are static and are delayed-constructed to reduce memory + footprint. + @note CRC-6 NR has the following parameters and check value: + - polynomial = 0x21 + - initial value = 0x00 + - final XOR = 0x00 + - reflect input = false + - reflect output = false + - check value = 0x15 + @return CRC-6 NR parameters +*/ +inline const CRC::Parameters & CRC::CRC_6_NR() +{ + static const Parameters parameters = { 0x21, 0x00, 0x00, false, false }; + return parameters; +} + /** @brief Returns a set of parameters for CRC-7 JEDEC. @note The parameters are static and are delayed-constructed to reduce memory footprint. @@ -986,6 +1255,24 @@ inline const CRC::Parameters & CRC::CRC_8_WCDMA() return parameters; } +/** + @brief Returns a set of parameters for CRC-8 LTE. + @note The parameters are static and are delayed-constructed to reduce memory footprint. + @note CRC-8 LTE has the following parameters and check value: + - polynomial = 0x9B + - initial value = 0x00 + - final XOR = 0x00 + - reflect input = false + - reflect output = false + - check value = 0xEA + @return CRC-8 LTE parameters +*/ +inline const CRC::Parameters & CRC::CRC_8_LTE() +{ + static const Parameters parameters = { 0x9B, 0x00, 0x00, false, false }; + return parameters; +} + /** @brief Returns a set of parameters for CRC-10 ITU. @note The parameters are static and are delayed-constructed to reduce memory footprint. @@ -1040,6 +1327,25 @@ inline const CRC::Parameters & CRC::CRC_11() return parameters; } +/** + @brief Returns a set of parameters for CRC-11 NR. + @note The parameters are static and are delayed-constructed to reduce memory + footprint. + @note CRC-11 NR has the following parameters and check value: + - polynomial = 0x621 + - initial value = 0x000 + - final XOR = 0x000 + - reflect input = false + - reflect output = false + - check value = 0x5CA + @return CRC-11 NR parameters +*/ +inline const CRC::Parameters & CRC::CRC_11_NR() +{ + static const Parameters parameters = { 0x621, 0x000, 0x000, false, false }; + return parameters; +} + /** @brief Returns a set of parameters for CRC-12 CDMA2000. @note The parameters are static and are delayed-constructed to reduce memory footprint. @@ -1203,6 +1509,24 @@ inline const CRC::Parameters & CRC::CRC_16_CCITTFALSE() return parameters; } +/** + @brief Returns a set of parameters for CRC-16 MCRF4XX. + @note The parameters are static and are delayed-constructed to reduce memory footprint. + @note CRC-16 MCRF4XX has the following parameters and check value: + - polynomial = 0x1021 + - initial value = 0xFFFF + - final XOR = 0x0000 + - reflect input = true + - reflect output = true + - check value = 0x6F91 + @return CRC-16 MCRF4XX parameters +*/ +inline const CRC::Parameters & CRC::CRC_16_MCRF4XX() +{ + static const Parameters parameters = { 0x1021, 0xFFFF, 0x0000, true, true}; + return parameters; +} + #ifdef CRCPP_INCLUDE_ESOTERIC_CRC_DEFINITIONS /** @brief Returns a set of parameters for CRC-16 CDMA2000. @@ -1533,6 +1857,63 @@ inline const CRC::Parameters & CRC::CRC_24_FLEXRAYB() return parameters; } +/** + @brief Returns a set of parameters for CRC-24 LTE-A/NR-A. + @note The parameters are static and are delayed-constructed to reduce memory + footprint. + @note CRC-24 LTE-A has the following parameters and check value: + - polynomial = 0x864CFB + - initial value = 0x000000 + - final XOR = 0x000000 + - reflect input = false + - reflect output = false + - check value = 0xCDE703 + @return CRC-24 LTE-A parameters +*/ +inline const CRC::Parameters & CRC::CRC_24_LTEA() +{ + static const Parameters parameters = { 0x864CFB, 0x000000, 0x000000, false, false }; + return parameters; +} + +/** + @brief Returns a set of parameters for CRC-24 LTE-B/NR-B. + @note The parameters are static and are delayed-constructed to reduce memory + footprint. + @note CRC-24 LTE-B has the following parameters and check value: + - polynomial = 0x800063 + - initial value = 0x000000 + - final XOR = 0x000000 + - reflect input = false + - reflect output = false + - check value = 0x23EF52 + @return CRC-24 LTE-B parameters +*/ +inline const CRC::Parameters & CRC::CRC_24_LTEB() +{ + static const Parameters parameters = { 0x800063, 0x000000, 0x000000, false, false }; + return parameters; +} + +/** + @brief Returns a set of parameters for CRC-24 NR-C. + @note The parameters are static and are delayed-constructed to reduce memory + footprint. + @note CRC-24 NR-C has the following parameters and check value: + - polynomial = 0xB2B117 + - initial value = 0x000000 + - final XOR = 0x000000 + - reflect input = false + - reflect output = false + - check value = 0xF48279 + @return CRC-24 NR-C parameters +*/ +inline const CRC::Parameters & CRC::CRC_24_NRC() +{ + static const Parameters parameters = { 0xB2B117, 0x000000, 0x000000, false, false }; + return parameters; +} + /** @brief Returns a set of parameters for CRC-30 CDMA. @note The parameters are static and are delayed-constructed to reduce memory footprint. diff --git a/dependencies/NVFC/nvapi.cpp b/dependencies/NVFC/nvapi.cpp index 36862dd0..632b2e08 100644 --- a/dependencies/NVFC/nvapi.cpp +++ b/dependencies/NVFC/nvapi.cpp @@ -1,7 +1,14 @@ -#define _WIN32_LEAN_AND_MEAN -#include +#ifdef _WIN32 + #define _WIN32_LEAN_AND_MEAN + #include +#elif __linux__ + #include +#endif #include "nvapi.h" +#include + +typedef void * (*nvapi_QueryInterface_t)(int); // Constructors for NvAPI structures that just zero the memory and set the right version NV_DELTA_ENTRY::NV_DELTA_ENTRY() @@ -240,15 +247,15 @@ static NV_STATUS(*pNvAPI_I2CReadEx)( // Interface: 3DBF5764 static NV_STATUS(*pNvAPI_GPU_ClientIllumZonesGetControl)( - NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS* pIllumZonesControl); // Interface: 197D065E static NV_STATUS(*pNvAPI_GPU_ClientIllumZonesSetControl)( - NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS* pIllumZonesControl); -static bool QueryInterfaceOpaque(FARPROC query_interface, NV_U32 id, void **result) +static bool QueryInterfaceOpaque(nvapi_QueryInterface_t query_interface, NV_U32 id, void **result) { void *address = ((void *(*)(NV_U32))query_interface)(id); if (address) { @@ -259,7 +266,7 @@ static bool QueryInterfaceOpaque(FARPROC query_interface, NV_U32 id, void **resu } template -static void QueryInterfaceCast(FARPROC query_interface, NV_U32 id, const char *function_name, F &function_pointer) +static void QueryInterfaceCast(nvapi_QueryInterface_t query_interface, NV_U32 id, const char */*function_name*/, F &function_pointer) { const bool result = QueryInterfaceOpaque(query_interface, id, (void **)&function_pointer); ////Log::write("%s querying interface '0x%08x' '%s'", result ? "success" : "failure", id, function_name); @@ -268,7 +275,7 @@ static void QueryInterfaceCast(FARPROC query_interface, NV_U32 id, const char *f #define QueryInterface(query_interface, id, function) \ QueryInterfaceCast((query_interface), (id), #function, p ## function) -static void QueryInterfaces(FARPROC query_interface) +static void QueryInterfaces(nvapi_QueryInterface_t query_interface) { //Log::write("querying interfaces with '0x%p'", query_interface); @@ -284,8 +291,8 @@ static void QueryInterfaces(FARPROC query_interface) QueryInterface(query_interface, 0x0CEEE8E9F, NvAPI_GPU_GetFullName); QueryInterface(query_interface, 0x6FF81213, NvAPI_GPU_GetPStates20); QueryInterface(query_interface, 0x0F4DAE6B, NvAPI_GPU_SetPStates20); - QueryInterface(query_interface, 0xDCB616C3, NvAPI_GPU_GetAllClockFrequencies); - QueryInterface(query_interface, 0x60DED2ED, NvAPI_GPU_GetDynamicPStates); + QueryInterface(query_interface, 0xDCB616C3, NvAPI_GPU_GetAllClockFrequencies); + QueryInterface(query_interface, 0x60DED2ED, NvAPI_GPU_GetDynamicPStates); QueryInterface(query_interface, 0x34206D86, NvAPI_GPU_GetPowerPoliciesInfo); QueryInterface(query_interface, 0x70916171, NvAPI_GPU_GetPowerPoliciesStatus); QueryInterface(query_interface, 0x0C16C7E2C, NvAPI_GPU_GetVoltageDomainStatus); @@ -296,7 +303,7 @@ static void QueryInterfaces(FARPROC query_interface) QueryInterface(query_interface, 0x0E9C425A1, NvAPI_GPU_GetThermalPoliciesStatus); QueryInterface(query_interface, 0x034C0B13D, NvAPI_GPU_SetThermalPoliciesStatus); QueryInterface(query_interface, 0xDA141340, NvAPI_GPU_GetCoolerSettings); - QueryInterface(query_interface, 0x891FA0AE, NvAPI_GPU_SetCoolerLevels); + QueryInterface(query_interface, 0x891FA0AE, NvAPI_GPU_SetCoolerLevels); QueryInterface(query_interface, 0x2DDFB66E, NvAPI_GPU_GetPCIIdentifiers); QueryInterface(query_interface, 0x283AC65A, NvAPI_I2CWriteEx); @@ -308,20 +315,35 @@ static void QueryInterfaces(FARPROC query_interface) NV_STATUS NvAPI_Initialize() { if (!pNvAPI_Initialize) { +#ifdef _WIN32 const char *name = sizeof(void*) == 4 ? "nvapi.dll" : "nvapi64.dll"; HMODULE nvapi = LoadLibraryA(name); if (!nvapi) { //Log::write("failed to load '%s'", name); return -1; } - //Log::write("loaded '%s' '0x%p'", name, nvapi); - - FARPROC query_interface = GetProcAddress(nvapi, "nvapi_QueryInterface"); + nvapi_QueryInterface_t query_interface = (nvapi_QueryInterface_t) GetProcAddress(nvapi, "nvapi_QueryInterface"); if (!query_interface) { //Log::write("failed to find 'nvapi_QueryInterface'"); return -1; } +#elif __linux__ + void* nvapi = nullptr; + if (!nvapi) nvapi = dlopen("libnvidia-api.so.1", RTLD_LAZY); + if (!nvapi) nvapi = dlopen("libnvidia-api.so", RTLD_LAZY); + if (!nvapi) { + // NVIDIA Driver is not installed + //Log::write("failed to load libnvidia-api.so, NVIDIA Driver is not installed"); + return -1; + } + nvapi_QueryInterface_t query_interface = (nvapi_QueryInterface_t) dlsym(nvapi, "nvapi_QueryInterface"); + if (!query_interface) { + // NVIDIA Driver is probably not up to date, requires at least driver version 525 + //Log::write("failed to load QueryInterface from libnvidia-api.so, NVIDIA Driver is not up to date"); + return -1; + } +#endif QueryInterfaces(query_interface); } @@ -572,7 +594,7 @@ NV_STATUS NvAPI_I2CReadEx( } NV_STATUS NvAPI_GPU_ClientIllumZonesGetControl( - NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS* pIllumZonesControl) { return pNvAPI_GPU_ClientIllumZonesGetControl @@ -581,10 +603,10 @@ NV_STATUS NvAPI_GPU_ClientIllumZonesGetControl( } NV_STATUS NvAPI_GPU_ClientIllumZonesSetControl( - NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS* pIllumZonesControl) { return pNvAPI_GPU_ClientIllumZonesSetControl ? (*pNvAPI_GPU_ClientIllumZonesSetControl)(physical_gpu_handle, pIllumZonesControl) : -1; -} \ No newline at end of file +} diff --git a/dependencies/NVFC/nvapi.h b/dependencies/NVFC/nvapi.h index 73668b03..50823ff6 100644 --- a/dependencies/NVFC/nvapi.h +++ b/dependencies/NVFC/nvapi.h @@ -1024,12 +1024,12 @@ NV_STATUS NvAPI_I2CReadEx( // Interface: 73C01D58 NV_STATUS NvAPI_GPU_ClientIllumZonesGetControl( - __in NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, - __inout NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS* pIllumZonesControl); + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS* pIllumZonesControl); // Interface: 57024C62 NV_STATUS NvAPI_GPU_ClientIllumZonesSetControl( - __in NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, - __inout NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS* pIllumZonesControl); + NV_PHYSICAL_GPU_HANDLE physical_gpu_handle, + NV_GPU_CLIENT_ILLUM_ZONE_CONTROL_PARAMS* pIllumZonesControl); #endif diff --git a/dependencies/Swatches/swatches.h b/dependencies/Swatches/swatches.h deleted file mode 100644 index dfe745e1..00000000 --- a/dependencies/Swatches/swatches.h +++ /dev/null @@ -1,71 +0,0 @@ -/*-------------------------------------------------------------------*\ -| Swatches.cpp | -| | -| Custom Colour Swatch widget that allows for adding user colours | -| | -| Chris M (Dr_No) 23rd April 2021 | -| | -\*-------------------------------------------------------------------*/ - -#ifndef SWATCHES_H -#define SWATCHES_H - -#include -#include -#include - -class Swatches : public QWidget -{ - Q_OBJECT -public: - explicit Swatches(QWidget *parent = nullptr); - - virtual QSize sizeHint () const; - virtual QSize minimumSizeHint () const; - QColor color(); - -signals: - void swatchChanged(const QColor color); - //void customSwatches(const QVector swatch); - -public slots: - void addCustomSwatch(const QColor &color); - //void addCustomSwatches(const QVector &swatch); - void setCurrentColor(const QColor &color); - -protected: - void mousePressEvent(QMouseEvent *event); - void mouseReleaseEvent(QMouseEvent *); - void resizeEvent(QResizeEvent *event); - void paintEvent(QPaintEvent *); - -private: - const int minSize = 20; - const int minRows = 1; - const int minColumns = 8; - const int margin = 2; - const float corner_radius = 0.0f; - bool mouseDown = false; - int selected = 0; - int width_inc_margin = minSize + (margin * 2); - int height_inc_margin = minSize + (margin * 2); - int min_swatches; - - struct swatch - { - QColor color = QColor(0, 0, 0); - QRect region = QRect(0, 0, 25, 25); - }; - - swatch add_swatch; - QPen border_pen = QColor(128,128,128); //Grey50 - QVector swatch_list; - QColor picker_color; - QSize initSize; - QPixmap swatch_pixmap; - QImage swatch_image; - - void drawSwatches(const QSize &newSize); -}; - -#endif // SWATCHES_H diff --git a/dependencies/display-library/include/adl_defines.h b/dependencies/display-library/include/adl_defines.h index 0c5031f5..849dbcab 100644 --- a/dependencies/display-library/include/adl_defines.h +++ b/dependencies/display-library/include/adl_defines.h @@ -20,85 +20,180 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +/// \file adl_defines.h +/// \brief Contains all definitions exposed by ADL for \ALL platforms.\n Included in ADL SDK +/// +/// This file contains all definitions used by ADL. +/// The ADL definitions include the following: +/// \li ADL error codes +/// \li Enumerations for the ADLDisplayInfo structure +/// \li Maximum limits +/// #ifndef ADL_DEFINES_H_ #define ADL_DEFINES_H_ +/// \defgroup DEFINES Constants and Definitions +/// @{ +/// \defgroup define_misc Miscellaneous Constant Definitions +/// @{ +/// \name General Definitions +/// @{ +/// Defines ADL_TRUE #define ADL_TRUE 1 +/// Defines ADL_FALSE #define ADL_FALSE 0 +/// Defines the maximum string length #define ADL_MAX_CHAR 4096 +/// Defines the maximum string length #define ADL_MAX_PATH 256 +/// Defines the maximum number of supported adapters #define ADL_MAX_ADAPTERS 250 +/// Defines the maxumum number of supported displays #define ADL_MAX_DISPLAYS 150 +/// Defines the maxumum string length for device name #define ADL_MAX_DEVICENAME 32 +/// Defines for all adapters #define ADL_ADAPTER_INDEX_ALL -1 +/// Defines APIs with iOption none #define ADL_MAIN_API_OPTION_NONE 0 +/// @} +/// \name Definitions for iOption parameter used by +/// ADL_Display_DDCBlockAccess_Get() +/// @{ +/// Switch to DDC line 2 before sending the command to the display. #define ADL_DDC_OPTION_SWITCHDDC2 0x00000001 +/// Save command in the registry under a unique key, corresponding to parameter \b iCommandIndex #define ADL_DDC_OPTION_RESTORECOMMAND 0x00000002 +/// Combine write-read DDC block access command. #define ADL_DDC_OPTION_COMBOWRITEREAD 0x00000010 +/// Direct DDC access to the immediate device connected to graphics card. +/// MST with this option set: DDC command is sent to first branch. +/// MST with this option not set: DDC command is sent to the end node sink device. #define ADL_DDC_OPTION_SENDTOIMMEDIATEDEVICE 0x00000020 +/// @} + +/// \name Values for +/// ADLI2C.iAction used with ADL_Display_WriteAndReadI2C() +/// @{ + +#define ADL_DL_I2C_ACTIONREAD 0x00000001 +#define ADL_DL_I2C_ACTIONWRITE 0x00000002 +#define ADL_DL_I2C_ACTIONREAD_REPEATEDSTART 0x00000003 +#define ADL_DL_I2C_ACTIONIS_PRESENT 0x00000004 +/// @} -#define ADL_DL_I2C_ACTIONREAD 0x00000001 -#define ADL_DL_I2C_ACTIONWRITE 0x00000002 -#define ADL_DL_I2C_ACTIONREAD_REPEATEDSTART 0x00000003 -#define ADL_DL_I2C_ACTIONIS_PRESENT 0x00000004 - - +/// @} //Misc +/// \defgroup define_adl_results Result Codes +/// This group of definitions are the various results returned by all ADL functions \n +/// @{ +/// All OK, but need to wait #define ADL_OK_WAIT 4 +/// All OK, but need restart #define ADL_OK_RESTART 3 +/// All OK but need mode change #define ADL_OK_MODE_CHANGE 2 +/// All OK, but with warning #define ADL_OK_WARNING 1 +/// ADL function completed successfully #define ADL_OK 0 +/// Generic Error. Most likely one or more of the Escape calls to the driver failed! #define ADL_ERR -1 +/// ADL not initialized #define ADL_ERR_NOT_INIT -2 +/// One of the parameter passed is invalid #define ADL_ERR_INVALID_PARAM -3 +/// One of the parameter size is invalid #define ADL_ERR_INVALID_PARAM_SIZE -4 +/// Invalid ADL index passed #define ADL_ERR_INVALID_ADL_IDX -5 +/// Invalid controller index passed #define ADL_ERR_INVALID_CONTROLLER_IDX -6 +/// Invalid display index passed #define ADL_ERR_INVALID_DIPLAY_IDX -7 +/// Function not supported by the driver #define ADL_ERR_NOT_SUPPORTED -8 +/// Null Pointer error #define ADL_ERR_NULL_POINTER -9 +/// Call can't be made due to disabled adapter #define ADL_ERR_DISABLED_ADAPTER -10 +/// Invalid Callback #define ADL_ERR_INVALID_CALLBACK -11 +/// Display Resource conflict #define ADL_ERR_RESOURCE_CONFLICT -12 //Failed to update some of the values. Can be returned by set request that include multiple values if not all values were successfully committed. #define ADL_ERR_SET_INCOMPLETE -20 +/// There's no Linux XDisplay in Linux Console environment #define ADL_ERR_NO_XDISPLAY -21 +/// escape call failed becuse of incompatiable driver found in driver store #define ADL_ERR_CALL_TO_INCOMPATIABLE_DRIVER -22 +/// not running as administrator #define ADL_ERR_NO_ADMINISTRATOR_PRIVILEGES -23 +/// Feature Sync Start api is not called yet #define ADL_ERR_FEATURESYNC_NOT_STARTED -24 +/// Adapter is in an invalid power state +#define ADL_ERR_INVALID_POWER_STATE -25 +/// @} +/// +/// \defgroup define_display_type Display Type +/// Define Monitor/CRT display type +/// @{ +/// Define Monitor display type #define ADL_DT_MONITOR 0 +/// Define TV display type #define ADL_DT_TELEVISION 1 +/// Define LCD display type #define ADL_DT_LCD_PANEL 2 +/// Define DFP display type #define ADL_DT_DIGITAL_FLAT_PANEL 3 +/// Define Componment Video display type #define ADL_DT_COMPONENT_VIDEO 4 +/// Define Projector display type #define ADL_DT_PROJECTOR 5 +/// @} +/// \defgroup define_display_connection_type Display Connection Type +/// @{ +/// Define unknown display output type #define ADL_DOT_UNKNOWN 0 +/// Define composite display output type #define ADL_DOT_COMPOSITE 1 +/// Define SVideo display output type #define ADL_DOT_SVIDEO 2 +/// Define analog display output type #define ADL_DOT_ANALOG 3 +/// Define digital display output type #define ADL_DOT_DIGITAL 4 +/// @} +/// \defgroup define_color_type Display Color Type and Source +/// Define Display Color Type and Source +/// @{ #define ADL_DISPLAY_COLOR_BRIGHTNESS (1 << 0) #define ADL_DISPLAY_COLOR_CONTRAST (1 << 1) #define ADL_DISPLAY_COLOR_SATURATION (1 << 2) #define ADL_DISPLAY_COLOR_HUE (1 << 3) #define ADL_DISPLAY_COLOR_TEMPERATURE (1 << 4) +/// Color Temperature Source is EDID #define ADL_DISPLAY_COLOR_TEMPERATURE_SOURCE_EDID (1 << 5) +/// Color Temperature Source is User #define ADL_DISPLAY_COLOR_TEMPERATURE_SOURCE_USER (1 << 6) +/// @} +/// \defgroup define_adjustment_capabilities Display Adjustment Capabilities +/// Display adjustment capabilities values. Returned by ADL_Display_AdjustCaps_Get +/// @{ #define ADL_DISPLAY_ADJUST_OVERSCAN (1 << 0) #define ADL_DISPLAY_ADJUST_VERT_POS (1 << 1) #define ADL_DISPLAY_ADJUST_HOR_POS (1 << 2) @@ -107,11 +202,18 @@ #define ADL_DISPLAY_ADJUST_SIZEPOS (ADL_DISPLAY_ADJUST_VERT_POS | ADL_DISPLAY_ADJUST_HOR_POS | ADL_DISPLAY_ADJUST_VERT_SIZE | ADL_DISPLAY_ADJUST_HOR_SIZE) #define ADL_DISPLAY_CUSTOMMODES (1<<5) #define ADL_DISPLAY_ADJUST_UNDERSCAN (1<<6) +/// @} +///Down-scale support #define ADL_DISPLAY_CAPS_DOWNSCALE (1 << 0) +/// Sharpness support #define ADL_DISPLAY_CAPS_SHARPNESS (1 << 0) +/// \defgroup define_desktop_config Desktop Configuration Flags +/// These flags are used by ADL_DesktopConfig_xxx +/// \deprecated This API has been deprecated because it was only used for RandR 1.1 (Red Hat 5.x) distributions which is now not supported. +/// @{ #define ADL_DESKTOPCONFIG_UNKNOWN 0 /* UNKNOWN desktop config */ #define ADL_DESKTOPCONFIG_SINGLE (1 << 0) /* Single */ #define ADL_DESKTOPCONFIG_CLONE (1 << 2) /* Clone */ @@ -120,9 +222,14 @@ #define ADL_DESKTOPCONFIG_BIGDESK_HR (1 << 6) /* Big Desktop Reverse Horz */ #define ADL_DESKTOPCONFIG_BIGDESK_VR (1 << 7) /* Big Desktop Reverse Vert */ #define ADL_DESKTOPCONFIG_RANDR12 (1 << 8) /* RandR 1.2 Multi-display */ +/// @} +/// needed for ADLDDCInfo structure #define ADL_MAX_DISPLAY_NAME 256 +/// \defgroup define_edid_flags Values for ulDDCInfoFlag +/// defines for ulDDCInfoFlag EDID flag +/// @{ #define ADL_DISPLAYDDCINFOEX_FLAG_PROJECTORDEVICE (1 << 0) #define ADL_DISPLAYDDCINFOEX_FLAG_EDIDEXTENSION (1 << 1) #define ADL_DISPLAYDDCINFOEX_FLAG_DIGITALDEVICE (1 << 2) @@ -130,7 +237,11 @@ #define ADL_DISPLAYDDCINFOEX_FLAG_SUPPORTS_AI (1 << 4) #define ADL_DISPLAYDDCINFOEX_FLAG_SUPPORT_xvYCC601 (1 << 5) #define ADL_DISPLAYDDCINFOEX_FLAG_SUPPORT_xvYCC709 (1 << 6) +/// @} +/// \defgroup define_displayinfo_connector Display Connector Type +/// defines for ADLDisplayInfo.iDisplayConnector +/// @{ #define ADL_DISPLAY_CONTYPE_UNKNOWN 0 #define ADL_DISPLAY_CONTYPE_VGA 1 #define ADL_DISPLAY_CONTYPE_DVI_D 2 @@ -149,10 +260,16 @@ #define ADL_DISPLAY_CONTYPE_EDP 16 #define ADL_DISPLAY_CONTYPE_WIRELESSDISPLAY 17 #define ADL_DISPLAY_CONTYPE_USB_TYPE_C 18 +/// @} +/// TV Capabilities and Standards +/// \defgroup define_tv_caps TV Capabilities and Standards +/// \deprecated Dropping support for TV displays +/// @{ #define ADL_TV_STANDARDS (1 << 0) #define ADL_TV_SCART (1 << 1) +/// TV Standards Definitions #define ADL_STANDARD_NTSC_M (1 << 0) #define ADL_STANDARD_NTSC_JPN (1 << 1) #define ADL_STANDARD_NTSC_N (1 << 2) @@ -171,14 +288,22 @@ #define ADL_STANDARD_PAL_SECAM_K (1 << 15) #define ADL_STANDARD_PAL_SECAM_K1 (1 << 16) #define ADL_STANDARD_PAL_SECAM_L (1 << 17) +/// @} +/// \defgroup define_video_custom_mode Video Custom Mode flags +/// Component Video Custom Mode flags. This is used by the iFlags parameter in ADLCustomMode +/// @{ #define ADL_CUSTOMIZEDMODEFLAG_MODESUPPORTED (1 << 0) #define ADL_CUSTOMIZEDMODEFLAG_NOTDELETETABLE (1 << 1) #define ADL_CUSTOMIZEDMODEFLAG_INSERTBYDRIVER (1 << 2) #define ADL_CUSTOMIZEDMODEFLAG_INTERLACED (1 << 3) #define ADL_CUSTOMIZEDMODEFLAG_BASEMODE (1 << 4) +/// @} +/// \defgroup define_ddcinfoflag Values used for DDCInfoFlag +/// ulDDCInfoFlag field values used by the ADLDDCInfo structure +/// @{ #define ADL_DISPLAYDDCINFOEX_FLAG_PROJECTORDEVICE (1 << 0) #define ADL_DISPLAYDDCINFOEX_FLAG_EDIDEXTENSION (1 << 1) #define ADL_DISPLAYDDCINFOEX_FLAG_DIGITALDEVICE (1 << 2) @@ -186,13 +311,19 @@ #define ADL_DISPLAYDDCINFOEX_FLAG_SUPPORTS_AI (1 << 4) #define ADL_DISPLAYDDCINFOEX_FLAG_SUPPORT_xvYCC601 (1 << 5) #define ADL_DISPLAYDDCINFOEX_FLAG_SUPPORT_xvYCC709 (1 << 6) +/// @} +/// \defgroup define_cv_dongle Values used by ADL_CV_DongleSettings_xxx +/// The following is applicable to ADL_DISPLAY_CONTYPE_ATICVDONGLE_JP and ADL_DISPLAY_CONTYPE_ATICVDONGLE_NONI2C_D only +/// \deprecated Dropping support for Component Video displays +/// @{ #define ADL_DISPLAY_CV_DONGLE_D1 (1 << 0) #define ADL_DISPLAY_CV_DONGLE_D2 (1 << 1) #define ADL_DISPLAY_CV_DONGLE_D3 (1 << 2) #define ADL_DISPLAY_CV_DONGLE_D4 (1 << 3) #define ADL_DISPLAY_CV_DONGLE_D5 (1 << 4) +/// The following is applicable to ADL_DISPLAY_CONTYPE_ATICVDONGLE_NA and ADL_DISPLAY_CONTYPE_ATICVDONGLE_NONI2C only #define ADL_DISPLAY_CV_DONGLE_480I (1 << 0) #define ADL_DISPLAY_CV_DONGLE_480P (1 << 1) @@ -209,7 +340,12 @@ #define ADL_DISPLAY_CV_DONGLE_1080P25 (1 << 12) #define ADL_DISPLAY_CV_DONGLE_1080P30 (1 << 13) #define ADL_DISPLAY_CV_DONGLE_1080P50 (1 << 14) +/// @} +/// \defgroup define_formats_ovr Formats Override Settings +/// Display force modes flags +/// @{ +/// #define ADL_DISPLAY_FORMAT_FORCE_720P 0x00000001 #define ADL_DISPLAY_FORMAT_FORCE_1080I 0x00000002 #define ADL_DISPLAY_FORMAT_FORCE_1080P 0x00000004 @@ -222,6 +358,7 @@ #define ADL_DISPLAY_FORMAT_FORCE_1080P30 0x00000200 #define ADL_DISPLAY_FORMAT_FORCE_1080P50 0x00000400 +///< Below are \b EXTENDED display mode flags #define ADL_DISPLAY_FORMAT_CVDONGLEOVERIDE 0x00000001 #define ADL_DISPLAY_FORMAT_CVMODEUNDERSCAN 0x00000002 @@ -230,68 +367,115 @@ #define ADL_DISPLAY_FORMAT_SETASPECRATIO 0x00000010 #define ADL_DISPLAY_FORMAT_FORCEMODES 0x00000020 #define ADL_DISPLAY_FORMAT_LCDRTCCOEFF 0x00000040 +/// @} +/// Defines used by OD5 #define ADL_PM_PARAM_DONT_CHANGE 0 +/// The following defines Bus types +/// @{ #define ADL_BUSTYPE_PCI 0 /* PCI bus */ #define ADL_BUSTYPE_AGP 1 /* AGP bus */ #define ADL_BUSTYPE_PCIE 2 /* PCI Express bus */ #define ADL_BUSTYPE_PCIE_GEN2 3 /* PCI Express 2nd generation bus */ #define ADL_BUSTYPE_PCIE_GEN3 4 /* PCI Express 3rd generation bus */ #define ADL_BUSTYPE_PCIE_GEN4 5 /* PCI Express 4th generation bus */ +/// @} +/// \defgroup define_ws_caps Workstation Capabilities +/// Workstation values +/// @{ +/// This value indicates that the workstation card supports active stereo though stereo output connector #define ADL_STEREO_SUPPORTED (1 << 2) +/// This value indicates that the workstation card supports active stereo via "blue-line" #define ADL_STEREO_BLUE_LINE (1 << 3) +/// This value is used to turn off stereo mode. #define ADL_STEREO_OFF 0 +/// This value indicates that the workstation card supports active stereo. This is also used to set the stereo mode to active though the stereo output connector #define ADL_STEREO_ACTIVE (1 << 1) +/// This value indicates that the workstation card supports auto-stereo monitors with horizontal interleave. This is also used to set the stereo mode to use the auto-stereo monitor with horizontal interleave #define ADL_STEREO_AUTO_HORIZONTAL (1 << 30) +/// This value indicates that the workstation card supports auto-stereo monitors with vertical interleave. This is also used to set the stereo mode to use the auto-stereo monitor with vertical interleave #define ADL_STEREO_AUTO_VERTICAL (1 << 31) +/// This value indicates that the workstation card supports passive stereo, ie. non stereo sync #define ADL_STEREO_PASSIVE (1 << 6) +/// This value indicates that the workstation card supports auto-stereo monitors with vertical interleave. This is also used to set the stereo mode to use the auto-stereo monitor with vertical interleave #define ADL_STEREO_PASSIVE_HORIZ (1 << 7) +/// This value indicates that the workstation card supports auto-stereo monitors with vertical interleave. This is also used to set the stereo mode to use the auto-stereo monitor with vertical interleave #define ADL_STEREO_PASSIVE_VERT (1 << 8) +/// This value indicates that the workstation card supports auto-stereo monitors with Samsung. #define ADL_STEREO_AUTO_SAMSUNG (1 << 11) +/// This value indicates that the workstation card supports auto-stereo monitors with Tridility. #define ADL_STEREO_AUTO_TSL (1 << 12) +/// This value indicates that the workstation card supports DeepBitDepth (10 bpp) #define ADL_DEEPBITDEPTH_10BPP_SUPPORTED (1 << 5) +/// This value indicates that the workstation supports 8-Bit Grayscale #define ADL_8BIT_GREYSCALE_SUPPORTED (1 << 9) +/// This value indicates that the workstation supports CUSTOM TIMING #define ADL_CUSTOM_TIMING_SUPPORTED (1 << 10) +/// Load balancing is supported. #define ADL_WORKSTATION_LOADBALANCING_SUPPORTED 0x00000001 +/// Load balancing is available. #define ADL_WORKSTATION_LOADBALANCING_AVAILABLE 0x00000002 +/// Load balancing is disabled. #define ADL_WORKSTATION_LOADBALANCING_DISABLED 0x00000000 +/// Load balancing is Enabled. #define ADL_WORKSTATION_LOADBALANCING_ENABLED 0x00000001 +/// @} +/// \defgroup define_adapterspeed speed setting from the adapter +/// @{ #define ADL_CONTEXT_SPEED_UNFORCED 0 /* default asic running speed */ #define ADL_CONTEXT_SPEED_FORCEHIGH 1 /* asic running speed is forced to high */ #define ADL_CONTEXT_SPEED_FORCELOW 2 /* asic running speed is forced to low */ #define ADL_ADAPTER_SPEEDCAPS_SUPPORTED (1 << 0) /* change asic running speed setting is supported */ +/// @} +/// \defgroup define_glsync Genlock related values +/// GL-Sync port types (unique values) +/// @{ +/// Unknown port of GL-Sync module #define ADL_GLSYNC_PORT_UNKNOWN 0 +/// BNC port of of GL-Sync module #define ADL_GLSYNC_PORT_BNC 1 +/// RJ45(1) port of of GL-Sync module #define ADL_GLSYNC_PORT_RJ45PORT1 2 +/// RJ45(2) port of of GL-Sync module #define ADL_GLSYNC_PORT_RJ45PORT2 3 // GL-Sync Genlock settings mask (bit-vector) +/// None of the ADLGLSyncGenlockConfig members are valid #define ADL_GLSYNC_CONFIGMASK_NONE 0 +/// The ADLGLSyncGenlockConfig.lSignalSource member is valid #define ADL_GLSYNC_CONFIGMASK_SIGNALSOURCE (1 << 0) +/// The ADLGLSyncGenlockConfig.iSyncField member is valid #define ADL_GLSYNC_CONFIGMASK_SYNCFIELD (1 << 1) +/// The ADLGLSyncGenlockConfig.iSampleRate member is valid #define ADL_GLSYNC_CONFIGMASK_SAMPLERATE (1 << 2) +/// The ADLGLSyncGenlockConfig.lSyncDelay member is valid #define ADL_GLSYNC_CONFIGMASK_SYNCDELAY (1 << 3) +/// The ADLGLSyncGenlockConfig.iTriggerEdge member is valid #define ADL_GLSYNC_CONFIGMASK_TRIGGEREDGE (1 << 4) +/// The ADLGLSyncGenlockConfig.iScanRateCoeff member is valid #define ADL_GLSYNC_CONFIGMASK_SCANRATECOEFF (1 << 5) +/// The ADLGLSyncGenlockConfig.lFramelockCntlVector member is valid #define ADL_GLSYNC_CONFIGMASK_FRAMELOCKCNTL (1 << 6) // GL-Sync Framelock control mask (bit-vector) +/// Framelock is disabled #define ADL_GLSYNC_FRAMELOCKCNTL_NONE 0 +/// Framelock is enabled #define ADL_GLSYNC_FRAMELOCKCNTL_ENABLE ( 1 << 0) #define ADL_GLSYNC_FRAMELOCKCNTL_DISABLE ( 1 << 1) @@ -307,110 +491,175 @@ // GL-Sync Signal Sources (unique values) +/// GL-Sync signal source is undefined #define ADL_GLSYNC_SIGNALSOURCE_UNDEFINED 0x00000100 +/// GL-Sync signal source is Free Run #define ADL_GLSYNC_SIGNALSOURCE_FREERUN 0x00000101 +/// GL-Sync signal source is the BNC GL-Sync port #define ADL_GLSYNC_SIGNALSOURCE_BNCPORT 0x00000102 +/// GL-Sync signal source is the RJ45(1) GL-Sync port #define ADL_GLSYNC_SIGNALSOURCE_RJ45PORT1 0x00000103 +/// GL-Sync signal source is the RJ45(2) GL-Sync port #define ADL_GLSYNC_SIGNALSOURCE_RJ45PORT2 0x00000104 // GL-Sync Signal Types (unique values) +/// GL-Sync signal type is unknown #define ADL_GLSYNC_SIGNALTYPE_UNDEFINED 0 +/// GL-Sync signal type is 480I #define ADL_GLSYNC_SIGNALTYPE_480I 1 +/// GL-Sync signal type is 576I #define ADL_GLSYNC_SIGNALTYPE_576I 2 +/// GL-Sync signal type is 480P #define ADL_GLSYNC_SIGNALTYPE_480P 3 +/// GL-Sync signal type is 576P #define ADL_GLSYNC_SIGNALTYPE_576P 4 +/// GL-Sync signal type is 720P #define ADL_GLSYNC_SIGNALTYPE_720P 5 +/// GL-Sync signal type is 1080P #define ADL_GLSYNC_SIGNALTYPE_1080P 6 +/// GL-Sync signal type is 1080I #define ADL_GLSYNC_SIGNALTYPE_1080I 7 +/// GL-Sync signal type is SDI #define ADL_GLSYNC_SIGNALTYPE_SDI 8 +/// GL-Sync signal type is TTL #define ADL_GLSYNC_SIGNALTYPE_TTL 9 +/// GL_Sync signal type is Analog #define ADL_GLSYNC_SIGNALTYPE_ANALOG 10 // GL-Sync Sync Field options (unique values) +///GL-Sync sync field option is undefined #define ADL_GLSYNC_SYNCFIELD_UNDEFINED 0 +///GL-Sync sync field option is Sync to Field 1 (used for Interlaced signal types) #define ADL_GLSYNC_SYNCFIELD_BOTH 1 +///GL-Sync sync field option is Sync to Both fields (used for Interlaced signal types) #define ADL_GLSYNC_SYNCFIELD_1 2 // GL-Sync trigger edge options (unique values) +/// GL-Sync trigger edge is undefined #define ADL_GLSYNC_TRIGGEREDGE_UNDEFINED 0 +/// GL-Sync trigger edge is the rising edge #define ADL_GLSYNC_TRIGGEREDGE_RISING 1 +/// GL-Sync trigger edge is the falling edge #define ADL_GLSYNC_TRIGGEREDGE_FALLING 2 +/// GL-Sync trigger edge is both the rising and the falling edge #define ADL_GLSYNC_TRIGGEREDGE_BOTH 3 // GL-Sync scan rate coefficient/multiplier options (unique values) +/// GL-Sync scan rate coefficient/multiplier is undefined #define ADL_GLSYNC_SCANRATECOEFF_UNDEFINED 0 +/// GL-Sync scan rate coefficient/multiplier is 5 #define ADL_GLSYNC_SCANRATECOEFF_x5 1 +/// GL-Sync scan rate coefficient/multiplier is 4 #define ADL_GLSYNC_SCANRATECOEFF_x4 2 +/// GL-Sync scan rate coefficient/multiplier is 3 #define ADL_GLSYNC_SCANRATECOEFF_x3 3 +/// GL-Sync scan rate coefficient/multiplier is 5:2 (SMPTE) #define ADL_GLSYNC_SCANRATECOEFF_x5_DIV_2 4 +/// GL-Sync scan rate coefficient/multiplier is 2 #define ADL_GLSYNC_SCANRATECOEFF_x2 5 +/// GL-Sync scan rate coefficient/multiplier is 3 : 2 #define ADL_GLSYNC_SCANRATECOEFF_x3_DIV_2 6 +/// GL-Sync scan rate coefficient/multiplier is 5 : 4 #define ADL_GLSYNC_SCANRATECOEFF_x5_DIV_4 7 +/// GL-Sync scan rate coefficient/multiplier is 1 (default) #define ADL_GLSYNC_SCANRATECOEFF_x1 8 +/// GL-Sync scan rate coefficient/multiplier is 4 : 5 #define ADL_GLSYNC_SCANRATECOEFF_x4_DIV_5 9 +/// GL-Sync scan rate coefficient/multiplier is 2 : 3 #define ADL_GLSYNC_SCANRATECOEFF_x2_DIV_3 10 +/// GL-Sync scan rate coefficient/multiplier is 1 : 2 #define ADL_GLSYNC_SCANRATECOEFF_x1_DIV_2 11 +/// GL-Sync scan rate coefficient/multiplier is 2 : 5 (SMPTE) #define ADL_GLSYNC_SCANRATECOEFF_x2_DIV_5 12 +/// GL-Sync scan rate coefficient/multiplier is 1 : 3 #define ADL_GLSYNC_SCANRATECOEFF_x1_DIV_3 13 +/// GL-Sync scan rate coefficient/multiplier is 1 : 4 #define ADL_GLSYNC_SCANRATECOEFF_x1_DIV_4 14 +/// GL-Sync scan rate coefficient/multiplier is 1 : 5 #define ADL_GLSYNC_SCANRATECOEFF_x1_DIV_5 15 // GL-Sync port (signal presence) states (unique values) +/// GL-Sync port state is undefined #define ADL_GLSYNC_PORTSTATE_UNDEFINED 0 +/// GL-Sync port is not connected #define ADL_GLSYNC_PORTSTATE_NOCABLE 1 +/// GL-Sync port is Idle #define ADL_GLSYNC_PORTSTATE_IDLE 2 +/// GL-Sync port has an Input signal #define ADL_GLSYNC_PORTSTATE_INPUT 3 +/// GL-Sync port is Output #define ADL_GLSYNC_PORTSTATE_OUTPUT 4 // GL-Sync LED types (used index within ADL_Workstation_GLSyncPortState_Get returned ppGlSyncLEDs array) (unique values) +/// Index into the ADL_Workstation_GLSyncPortState_Get returned ppGlSyncLEDs array for the one LED of the BNC port #define ADL_GLSYNC_LEDTYPE_BNC 0 +/// Index into the ADL_Workstation_GLSyncPortState_Get returned ppGlSyncLEDs array for the Left LED of the RJ45(1) or RJ45(2) port #define ADL_GLSYNC_LEDTYPE_RJ45_LEFT 0 +/// Index into the ADL_Workstation_GLSyncPortState_Get returned ppGlSyncLEDs array for the Right LED of the RJ45(1) or RJ45(2) port #define ADL_GLSYNC_LEDTYPE_RJ45_RIGHT 1 // GL-Sync LED colors (unique values) +/// GL-Sync LED undefined color #define ADL_GLSYNC_LEDCOLOR_UNDEFINED 0 +/// GL-Sync LED is unlit #define ADL_GLSYNC_LEDCOLOR_NOLIGHT 1 +/// GL-Sync LED is yellow #define ADL_GLSYNC_LEDCOLOR_YELLOW 2 +/// GL-Sync LED is red #define ADL_GLSYNC_LEDCOLOR_RED 3 +/// GL-Sync LED is green #define ADL_GLSYNC_LEDCOLOR_GREEN 4 +/// GL-Sync LED is flashing green #define ADL_GLSYNC_LEDCOLOR_FLASH_GREEN 5 // GL-Sync Port Control (refers one GL-Sync Port) (unique values) +/// Used to configure the RJ54(1) or RJ42(2) port of GL-Sync is as Idle #define ADL_GLSYNC_PORTCNTL_NONE 0x00000000 +/// Used to configure the RJ54(1) or RJ42(2) port of GL-Sync is as Output #define ADL_GLSYNC_PORTCNTL_OUTPUT 0x00000001 // GL-Sync Mode Control (refers one Display/Controller) (bitfields) +/// Used to configure the display to use internal timing (not genlocked) #define ADL_GLSYNC_MODECNTL_NONE 0x00000000 +/// Bitfield used to configure the display as genlocked (either as Timing Client or as Timing Server) #define ADL_GLSYNC_MODECNTL_GENLOCK 0x00000001 +/// Bitfield used to configure the display as Timing Server #define ADL_GLSYNC_MODECNTL_TIMINGSERVER 0x00000002 // GL-Sync Mode Status +/// Display is currently not genlocked #define ADL_GLSYNC_MODECNTL_STATUS_NONE 0x00000000 +/// Display is currently genlocked #define ADL_GLSYNC_MODECNTL_STATUS_GENLOCK 0x00000001 +/// Display requires a mode switch #define ADL_GLSYNC_MODECNTL_STATUS_SETMODE_REQUIRED 0x00000002 +/// Display is capable of being genlocked #define ADL_GLSYNC_MODECNTL_STATUS_GENLOCK_ALLOWED 0x00000004 #define ADL_MAX_GLSYNC_PORTS 8 #define ADL_MAX_GLSYNC_PORT_LEDS 8 +/// @} +/// \defgroup define_crossfirestate CrossfireX state of a particular adapter CrossfireX combination +/// @{ #define ADL_XFIREX_STATE_NOINTERCONNECT ( 1 << 0 ) /* Dongle / cable is missing */ #define ADL_XFIREX_STATE_DOWNGRADEPIPES ( 1 << 1 ) /* CrossfireX can be enabled if pipes are downgraded */ #define ADL_XFIREX_STATE_DOWNGRADEMEM ( 1 << 2 ) /* CrossfireX cannot be enabled unless mem downgraded */ @@ -440,9 +689,16 @@ #define ADL_XFIREX_STATE_DRV_HANDLE_DOWNGRADE_KEY ( 1 << 29 ) /* Indicate base driver handles the downgrade key updating */ #define ADL_XFIREX_STATE_CF_RECONFIG_REQUIRED ( 1 << 30 ) /* CrossfireX need to be reconfigured by CCC because of a LDA chain broken */ #define ADL_XFIREX_STATE_ERRORGETTINGSTATUS ( 1 << 31 ) /* Could not obtain current status */ +/// @} +/////////////////////////////////////////////////////////////////////////// // ADL_DISPLAY_ADJUSTMENT_PIXELFORMAT adjustment values // (bit-vector) +/////////////////////////////////////////////////////////////////////////// +/// \defgroup define_pixel_formats Pixel Formats values +/// This group defines the various Pixel Formats that a particular digital display can support. \n +/// Since a display can support multiple formats, these values can be bit-or'ed to indicate the various formats \n +/// @{ #define ADL_DISPLAY_PIXELFORMAT_UNKNOWN 0 #define ADL_DISPLAY_PIXELFORMAT_RGB (1 << 0) #define ADL_DISPLAY_PIXELFORMAT_YCRCB444 (1 << 1) //Limited range @@ -450,7 +706,11 @@ #define ADL_DISPLAY_PIXELFORMAT_RGB_LIMITED_RANGE (1 << 3) #define ADL_DISPLAY_PIXELFORMAT_RGB_FULL_RANGE ADL_DISPLAY_PIXELFORMAT_RGB //Full range #define ADL_DISPLAY_PIXELFORMAT_YCRCB420 (1 << 4) +/// @} +/// \defgroup define_contype Connector Type Values +/// ADLDisplayConfig.ulConnectorType defines +/// @{ #define ADL_DL_DISPLAYCONFIG_CONTYPE_UNKNOWN 0 #define ADL_DL_DISPLAYCONFIG_CONTYPE_CV_NONI2C_JP 1 #define ADL_DL_DISPLAYCONFIG_CONTYPE_CV_JPN 2 @@ -462,10 +722,15 @@ #define ADL_DL_DISPLAYCONFIG_CONTYPE_HDMI_TYPE_A 8 #define ADL_DL_DISPLAYCONFIG_CONTYPE_HDMI_TYPE_B 9 #define ADL_DL_DISPLAYCONFIG_CONTYPE_DISPLAYPORT 10 +/// @} +/////////////////////////////////////////////////////////////////////////// // ADL_DISPLAY_DISPLAYINFO_ Definitions // for ADLDisplayInfo.iDisplayInfoMask and ADLDisplayInfo.iDisplayInfoValue // (bit-vector) +/////////////////////////////////////////////////////////////////////////// +/// \defgroup define_displayinfomask Display Info Mask Values +/// @{ #define ADL_DISPLAY_DISPLAYINFO_DISPLAYCONNECTED 0x00000001 #define ADL_DISPLAY_DISPLAYINFO_DISPLAYMAPPED 0x00000002 #define ADL_DISPLAY_DISPLAYINFO_NONLOCAL 0x00000004 @@ -478,28 +743,37 @@ #define ADL_DISPLAY_DISPLAYINFO_MANNER_SUPPORTED_SINGLE 0x00000100 #define ADL_DISPLAY_DISPLAYINFO_MANNER_SUPPORTED_CLONE 0x00000200 +/// Legacy support for XP #define ADL_DISPLAY_DISPLAYINFO_MANNER_SUPPORTED_2VSTRETCH 0x00000400 #define ADL_DISPLAY_DISPLAYINFO_MANNER_SUPPORTED_2HSTRETCH 0x00000800 #define ADL_DISPLAY_DISPLAYINFO_MANNER_SUPPORTED_EXTENDED 0x00001000 +/// More support manners #define ADL_DISPLAY_DISPLAYINFO_MANNER_SUPPORTED_NSTRETCH1GPU 0x00010000 #define ADL_DISPLAY_DISPLAYINFO_MANNER_SUPPORTED_NSTRETCHNGPU 0x00020000 #define ADL_DISPLAY_DISPLAYINFO_MANNER_SUPPORTED_RESERVED2 0x00040000 #define ADL_DISPLAY_DISPLAYINFO_MANNER_SUPPORTED_RESERVED3 0x00080000 +/// Projector display type #define ADL_DISPLAY_DISPLAYINFO_SHOWTYPE_PROJECTOR 0x00100000 +/// @} +/////////////////////////////////////////////////////////////////////////// // ADL_ADAPTER_DISPLAY_MANNER_SUPPORTED_ Definitions // for ADLAdapterDisplayCap of ADL_Adapter_Display_Cap() // (bit-vector) +/////////////////////////////////////////////////////////////////////////// +/// \defgroup define_adaptermanner Adapter Manner Support Values +/// @{ #define ADL_ADAPTER_DISPLAYCAP_MANNER_SUPPORTED_NOTACTIVE 0x00000001 #define ADL_ADAPTER_DISPLAYCAP_MANNER_SUPPORTED_SINGLE 0x00000002 #define ADL_ADAPTER_DISPLAYCAP_MANNER_SUPPORTED_CLONE 0x00000004 #define ADL_ADAPTER_DISPLAYCAP_MANNER_SUPPORTED_NSTRETCH1GPU 0x00000008 #define ADL_ADAPTER_DISPLAYCAP_MANNER_SUPPORTED_NSTRETCHNGPU 0x00000010 +/// Legacy support for XP #define ADL_ADAPTER_DISPLAYCAP_MANNER_SUPPORTED_2VSTRETCH 0x00000020 #define ADL_ADAPTER_DISPLAYCAP_MANNER_SUPPORTED_2HSTRETCH 0x00000040 #define ADL_ADAPTER_DISPLAYCAP_MANNER_SUPPORTED_EXTENDED 0x00000080 @@ -508,9 +782,11 @@ #define ADL_ADAPTER_DISPLAYCAP_BEZEL_SUPPORTED 0x00000200 +/////////////////////////////////////////////////////////////////////////// // ADL_DISPLAY_DISPLAYMAP_MANNER_ Definitions // for ADLDisplayMap.iDisplayMapMask and ADLDisplayMap.iDisplayMapValue // (bit-vector) +/////////////////////////////////////////////////////////////////////////// #define ADL_DISPLAY_DISPLAYMAP_MANNER_RESERVED 0x00000001 #define ADL_DISPLAY_DISPLAYMAP_MANNER_NOTACTIVE 0x00000002 #define ADL_DISPLAY_DISPLAYMAP_MANNER_SINGLE 0x00000004 @@ -520,27 +796,38 @@ #define ADL_DISPLAY_DISPLAYMAP_MANNER_VSTRETCH 0x00000040 #define ADL_DISPLAY_DISPLAYMAP_MANNER_VLD 0x00000080 +/// @} +/////////////////////////////////////////////////////////////////////////// // ADL_DISPLAY_DISPLAYMAP_OPTION_ Definitions // for iOption in function ADL_Display_DisplayMapConfig_Get // (bit-vector) +/////////////////////////////////////////////////////////////////////////// #define ADL_DISPLAY_DISPLAYMAP_OPTION_GPUINFO 0x00000001 +/////////////////////////////////////////////////////////////////////////// // ADL_DISPLAY_DISPLAYTARGET_ Definitions // for ADLDisplayTarget.iDisplayTargetMask and ADLDisplayTarget.iDisplayTargetValue // (bit-vector) +/////////////////////////////////////////////////////////////////////////// #define ADL_DISPLAY_DISPLAYTARGET_PREFERRED 0x00000001 +/////////////////////////////////////////////////////////////////////////// // ADL_DISPLAY_POSSIBLEMAPRESULT_VALID Definitions // for ADLPossibleMapResult.iPossibleMapResultMask and ADLPossibleMapResult.iPossibleMapResultValue // (bit-vector) +/////////////////////////////////////////////////////////////////////////// #define ADL_DISPLAY_POSSIBLEMAPRESULT_VALID 0x00000001 #define ADL_DISPLAY_POSSIBLEMAPRESULT_BEZELSUPPORTED 0x00000002 #define ADL_DISPLAY_POSSIBLEMAPRESULT_OVERLAPSUPPORTED 0x00000004 +/////////////////////////////////////////////////////////////////////////// // ADL_DISPLAY_MODE_ Definitions // for ADLMode.iModeMask, ADLMode.iModeValue, and ADLMode.iModeFlag // (bit-vector) +/////////////////////////////////////////////////////////////////////////// +/// \defgroup define_displaymode Display Mode Values +/// @{ #define ADL_DISPLAY_MODE_COLOURFORMAT_565 0x00000001 #define ADL_DISPLAY_MODE_COLOURFORMAT_8888 0x00000002 #define ADL_DISPLAY_MODE_ORIENTATION_SUPPORTED_000 0x00000004 @@ -552,8 +839,13 @@ #define ADL_DISPLAY_MODE_PROGRESSIVE_FLAG 0 #define ADL_DISPLAY_MODE_INTERLACED_FLAG 2 +/// @} +/////////////////////////////////////////////////////////////////////////// // ADL_OSMODEINFO Definitions +/////////////////////////////////////////////////////////////////////////// +/// \defgroup define_osmode OS Mode Values +/// @{ #define ADL_OSMODEINFOXPOS_DEFAULT -640 #define ADL_OSMODEINFOYPOS_DEFAULT 0 #define ADL_OSMODEINFOXRES_DEFAULT 640 @@ -568,15 +860,25 @@ #define ADL_OSMODEINFOORIENTATION_DEFAULT 0 #define ADL_OSMODEINFOORIENTATION_DEFAULT_WIN7 DISPLAYCONFIG_ROTATION_FORCE_UINT32 #define ADL_OSMODEFLAG_DEFAULT 0 +/// @} +/////////////////////////////////////////////////////////////////////////// // ADLThreadingModel Enumeration +/////////////////////////////////////////////////////////////////////////// +/// \defgroup thread_model +/// Used with \ref ADL_Main_ControlX2_Create and \ref ADL2_Main_ControlX2_Create to specify how ADL handles API calls when executed by multiple threads concurrently. +/// \brief Declares ADL threading behavior. +/// @{ typedef enum ADLThreadingModel { - ADL_THREADING_UNLOCKED = 0, - ADL_THREADING_LOCKED + ADL_THREADING_UNLOCKED = 0, /*!< Default behavior. ADL will not enforce serialization of ADL API executions by multiple threads. Multiple threads will be allowed to enter to ADL at the same time. Note that ADL library is not guaranteed to be thread-safe. Client that calls ADL_Main_Control_Create have to provide its own mechanism for ADL calls serialization. */ + ADL_THREADING_LOCKED /*!< ADL will enforce serialization of ADL API when called by multiple threads. Only single thread will be allowed to enter ADL API at the time. This option makes ADL calls thread-safe. You shouldn't use this option if ADL calls will be executed on Linux on x-server rendering thread. It can cause the application to hung. */ }ADLThreadingModel; +/// @} +/////////////////////////////////////////////////////////////////////////// // ADLPurposeCode Enumeration +/////////////////////////////////////////////////////////////////////////// enum ADLPurposeCode { ADL_PURPOSECODE_NORMAL = 0, @@ -588,7 +890,9 @@ enum ADLPurposeCode ADL_PURPOSECODE_GDI_ROTATION, ADL_PURPOSECODE_ATI_ROTATION }; +/////////////////////////////////////////////////////////////////////////// // ADLAngle Enumeration +/////////////////////////////////////////////////////////////////////////// enum ADLAngle { ADL_ANGLE_LANDSCAPE = 0, @@ -597,14 +901,18 @@ enum ADLAngle ADL_ANGLE_ROTATELEFT = 270, }; +/////////////////////////////////////////////////////////////////////////// // ADLOrientationDataType Enumeration +/////////////////////////////////////////////////////////////////////////// enum ADLOrientationDataType { ADL_ORIENTATIONTYPE_OSDATATYPE, ADL_ORIENTATIONTYPE_NONOSDATATYPE }; +/////////////////////////////////////////////////////////////////////////// // ADLPanningMode Enumeration +/////////////////////////////////////////////////////////////////////////// enum ADLPanningMode { ADL_PANNINGMODE_NO_PANNING = 0, @@ -612,7 +920,9 @@ enum ADLPanningMode ADL_PANNINGMODE_ALLOW_PANNING = 2, }; +/////////////////////////////////////////////////////////////////////////// // ADLLARGEDESKTOPTYPE Enumeration +/////////////////////////////////////////////////////////////////////////// enum ADLLARGEDESKTOPTYPE { ADL_LARGEDESKTOPTYPE_NORMALDESKTOP = 0, @@ -620,14 +930,18 @@ enum ADLLARGEDESKTOPTYPE ADL_LARGEDESKTOPTYPE_VERYLARGEDESKTOP = 2 }; +/////////////////////////////////////////////////////////////////////////// // ADLPlatform Enumeration +/////////////////////////////////////////////////////////////////////////// enum ADLPlatForm { GRAPHICS_PLATFORM_DESKTOP = 0, GRAPHICS_PLATFORM_MOBILE = 1 }; +/////////////////////////////////////////////////////////////////////////// // ADLGraphicCoreGeneration Enumeration +/////////////////////////////////////////////////////////////////////////// enum ADLGraphicCoreGeneration { ADL_GRAPHIC_CORE_GENERATION_UNDEFINED = 0, @@ -652,22 +966,34 @@ enum ADLGraphicCoreGeneration #define ADL_DL_I2C_LINE_OEM4 0x00000005 #define ADL_DL_I2C_LINE_OEM5 0x00000006 #define ADL_DL_I2C_LINE_OEM6 0x00000007 +#define ADL_DL_I2C_LINE_GPIO 0x00000008 // Max size of I2C data buffer -#define ADL_DL_I2C_MAXDATASIZE 0x00000040 +#define ADL_DL_I2C_MAXDATASIZE 0x00000018 #define ADL_DL_I2C_MAXWRITEDATASIZE 0x0000000C #define ADL_DL_I2C_MAXADDRESSLENGTH 0x00000006 #define ADL_DL_I2C_MAXOFFSETLENGTH 0x00000004 +// I2C clock speed in KHz +#define ADL_DL_I2C_SPEED_50K 50 +#define ADL_DL_I2C_SPEED_100K 100 +#define ALD_DL_I2C_SPEED_400K 400 +#define ADL_DL_I2C_SPEED_1M 1000 +#define ADL_DL_I2C_SPEED_2M 2300 +/// Values for ADLDisplayProperty.iPropertyType #define ADL_DL_DISPLAYPROPERTY_TYPE_UNKNOWN 0 #define ADL_DL_DISPLAYPROPERTY_TYPE_EXPANSIONMODE 1 #define ADL_DL_DISPLAYPROPERTY_TYPE_USEUNDERSCANSCALING 2 +/// Enables ITC processing for HDMI panels that are capable of the feature #define ADL_DL_DISPLAYPROPERTY_TYPE_ITCFLAGENABLE 9 #define ADL_DL_DISPLAYPROPERTY_TYPE_DOWNSCALE 11 #define ADL_DL_DISPLAYPROPERTY_TYPE_INTEGER_SCALING 12 +/// Values for ADLDisplayContent.iContentType +/// Certain HDMI panels that support ITC have support for a feature such that, the display on the panel +/// can be adjusted to optimize the view of the content being displayed, depending on the type of content. #define ADL_DL_DISPLAYCONTENT_TYPE_GRAPHICS 1 #define ADL_DL_DISPLAYCONTENT_TYPE_PHOTO 2 #define ADL_DL_DISPLAYCONTENT_TYPE_CINEMA 4 @@ -681,33 +1007,61 @@ enum ADLGraphicCoreGeneration #define ADL_DL_DISPLAYPROPERTY_EXPANSIONMODE_ASPECTRATIO 2 +///\defgroup define_dither_states Dithering options +/// @{ +/// Dithering disabled. #define ADL_DL_DISPLAY_DITHER_DISABLED 0 +/// Use default driver settings for dithering. Note that the default setting could be dithering disabled. #define ADL_DL_DISPLAY_DITHER_DRIVER_DEFAULT 1 +/// Temporal dithering to 6 bpc. Note that if the input is 12 bits, the two least significant bits will be truncated. #define ADL_DL_DISPLAY_DITHER_FM6 2 +/// Temporal dithering to 8 bpc. #define ADL_DL_DISPLAY_DITHER_FM8 3 +/// Temporal dithering to 10 bpc. #define ADL_DL_DISPLAY_DITHER_FM10 4 +/// Spatial dithering to 6 bpc. Note that if the input is 12 bits, the two least significant bits will be truncated. #define ADL_DL_DISPLAY_DITHER_DITH6 5 +/// Spatial dithering to 8 bpc. #define ADL_DL_DISPLAY_DITHER_DITH8 6 +/// Spatial dithering to 10 bpc. #define ADL_DL_DISPLAY_DITHER_DITH10 7 +/// Spatial dithering to 6 bpc. Random number generators are reset every frame, so the same input value of a certain pixel will always be dithered to the same output value. Note that if the input is 12 bits, the two least significant bits will be truncated. #define ADL_DL_DISPLAY_DITHER_DITH6_NO_FRAME_RAND 8 +/// Spatial dithering to 8 bpc. Random number generators are reset every frame, so the same input value of a certain pixel will always be dithered to the same output value. #define ADL_DL_DISPLAY_DITHER_DITH8_NO_FRAME_RAND 9 +/// Spatial dithering to 10 bpc. Random number generators are reset every frame, so the same input value of a certain pixel will always be dithered to the same output value. #define ADL_DL_DISPLAY_DITHER_DITH10_NO_FRAME_RAND 10 +/// Truncation to 6 bpc. #define ADL_DL_DISPLAY_DITHER_TRUN6 11 +/// Truncation to 8 bpc. #define ADL_DL_DISPLAY_DITHER_TRUN8 12 +/// Truncation to 10 bpc. #define ADL_DL_DISPLAY_DITHER_TRUN10 13 +/// Truncation to 10 bpc followed by spatial dithering to 8 bpc. #define ADL_DL_DISPLAY_DITHER_TRUN10_DITH8 14 +/// Truncation to 10 bpc followed by spatial dithering to 6 bpc. #define ADL_DL_DISPLAY_DITHER_TRUN10_DITH6 15 +/// Truncation to 10 bpc followed by temporal dithering to 8 bpc. #define ADL_DL_DISPLAY_DITHER_TRUN10_FM8 16 +/// Truncation to 10 bpc followed by temporal dithering to 6 bpc. #define ADL_DL_DISPLAY_DITHER_TRUN10_FM6 17 +/// Truncation to 10 bpc followed by spatial dithering to 8 bpc and temporal dithering to 6 bpc. #define ADL_DL_DISPLAY_DITHER_TRUN10_DITH8_FM6 18 +/// Spatial dithering to 10 bpc followed by temporal dithering to 8 bpc. #define ADL_DL_DISPLAY_DITHER_DITH10_FM8 19 +/// Spatial dithering to 10 bpc followed by temporal dithering to 6 bpc. #define ADL_DL_DISPLAY_DITHER_DITH10_FM6 20 +/// Truncation to 8 bpc followed by spatial dithering to 6 bpc. #define ADL_DL_DISPLAY_DITHER_TRUN8_DITH6 21 +/// Truncation to 8 bpc followed by temporal dithering to 6 bpc. #define ADL_DL_DISPLAY_DITHER_TRUN8_FM6 22 +/// Spatial dithering to 8 bpc followed by temporal dithering to 6 bpc. #define ADL_DL_DISPLAY_DITHER_DITH8_FM6 23 #define ADL_DL_DISPLAY_DITHER_LAST ADL_DL_DISPLAY_DITHER_DITH8_FM6 +/// @} +/// Display Get Cached EDID flag #define ADL_MAX_EDIDDATA_SIZE 256 // number of UCHAR #define ADL_MAX_OVERRIDEEDID_SIZE 512 // number of UCHAR #define ADL_MAX_EDID_EXTENSION_BLOCKS 3 @@ -719,20 +1073,27 @@ enum ADLGraphicCoreGeneration #define ADL_DL_DISPLAY_DATA_PACKET__INFO_PACKET_SET 0x00000001 #define ADL_DL_DISPLAY_DATA_PACKET__INFO_PACKET_SCAN 0x00000002 +///\defgroup define_display_packet Display Data Packet Types +/// @{ #define ADL_DL_DISPLAY_DATA_PACKET__TYPE__AVI 0x00000001 #define ADL_DL_DISPLAY_DATA_PACKET__TYPE__GAMMUT 0x00000002 #define ADL_DL_DISPLAY_DATA_PACKET__TYPE__VENDORINFO 0x00000004 #define ADL_DL_DISPLAY_DATA_PACKET__TYPE__HDR 0x00000008 #define ADL_DL_DISPLAY_DATA_PACKET__TYPE__SPD 0x00000010 +/// @} // matrix types #define ADL_GAMUT_MATRIX_SD 1 // SD matrix i.e. BT601 #define ADL_GAMUT_MATRIX_HD 2 // HD matrix i.e. BT709 +///\defgroup define_clockinfo_flags Clock flags +/// Used by ADLAdapterODClockInfo.iFlag +/// @{ #define ADL_DL_CLOCKINFO_FLAG_FULLSCREEN3DONLY 0x00000001 #define ADL_DL_CLOCKINFO_FLAG_ALWAYSFULLSCREEN3D 0x00000002 #define ADL_DL_CLOCKINFO_FLAG_VPURECOVERYREDUCED 0x00000004 #define ADL_DL_CLOCKINFO_FLAG_THERMALPROTECTION 0x00000008 +/// @} // Supported GPUs // ADL_Display_PowerXpressActiveGPU_Get() @@ -761,10 +1122,14 @@ enum ADLGraphicCoreGeneration #define ADL_DL_THERMAL_FLAG_INTERRUPT 1 #define ADL_DL_THERMAL_FLAG_FANCONTROL 2 +///\defgroup define_fanctrl Fan speed cotrol +/// Values for ADLFanSpeedInfo.iFlags +/// @{ #define ADL_DL_FANCTRL_SUPPORTS_PERCENT_READ 1 #define ADL_DL_FANCTRL_SUPPORTS_PERCENT_WRITE 2 #define ADL_DL_FANCTRL_SUPPORTS_RPM_READ 4 #define ADL_DL_FANCTRL_SUPPORTS_RPM_WRITE 8 +/// @} //values for ADLFanSpeedValue.iSpeedType #define ADL_DL_FANCTRL_SPEED_TYPE_PERCENT 1 @@ -786,6 +1151,9 @@ enum ADLGraphicCoreGeneration #define ADL_DL_MVPU_STATUS_ON 1 // values for ASIC family +///\defgroup define_Asic_type Detailed asic types +/// Defines for Adapter ASIC family type +/// @{ #define ADL_ASIC_UNDEFINED 0 #define ADL_ASIC_DISCRETE (1 << 0) #define ADL_ASIC_INTEGRATED (1 << 1) @@ -797,7 +1165,11 @@ enum ADLGraphicCoreGeneration #define ADL_ASIC_EMBEDDED (1 << 7) // Backward compatibility #define ADL_ASIC_FIREGL ADL_ASIC_WORKSTATION +/// @} +///\defgroup define_detailed_timing_flags Detailed Timimg Flags +/// Defines for ADLDetailedTiming.sTimingFlags field +/// @{ #define ADL_DL_TIMINGFLAG_DOUBLE_SCAN 0x0001 //sTimingFlags is set when the mode is INTERLACED, if not PROGRESSIVE #define ADL_DL_TIMINGFLAG_INTERLACED 0x0002 @@ -805,23 +1177,35 @@ enum ADLGraphicCoreGeneration #define ADL_DL_TIMINGFLAG_H_SYNC_POLARITY 0x0004 //sTimingFlags is set when the Vertical Sync is POSITIVE, if not NEGATIVE #define ADL_DL_TIMINGFLAG_V_SYNC_POLARITY 0x0008 +/// @} +///\defgroup define_modetiming_standard Timing Standards +/// Defines for ADLDisplayModeInfo.iTimingStandard field +/// @{ #define ADL_DL_MODETIMING_STANDARD_CVT 0x00000001 // CVT Standard #define ADL_DL_MODETIMING_STANDARD_GTF 0x00000002 // GFT Standard #define ADL_DL_MODETIMING_STANDARD_DMT 0x00000004 // DMT Standard #define ADL_DL_MODETIMING_STANDARD_CUSTOM 0x00000008 // User-defined standard #define ADL_DL_MODETIMING_STANDARD_DRIVER_DEFAULT 0x00000010 // Remove Mode from overriden list #define ADL_DL_MODETIMING_STANDARD_CVT_RB 0x00000020 // CVT-RB Standard +/// @} // \defgroup define_xserverinfo driver x-server info +/// These flags are used by ADL_XServerInfo_Get() // @ +/// Xinerama is active in the x-server, Xinerama extension may report it to be active but it +/// may not be active in x-server #define ADL_XSERVERINFO_XINERAMAACTIVE (1<<0) +/// RandR 1.2 is supported by driver, RandR extension may report version 1.2 +/// but driver may not support it #define ADL_XSERVERINFO_RANDR12SUPPORTED (1<<1) // @ +///\defgroup define_eyefinity_constants Eyefinity Definitions +/// @{ #define ADL_CONTROLLERVECTOR_0 1 // ADL_CONTROLLERINDEX_0 = 0, (1 << ADL_CONTROLLERINDEX_0) #define ADL_CONTROLLERVECTOR_1 2 // ADL_CONTROLLERINDEX_1 = 1, (1 << ADL_CONTROLLERINDEX_1) @@ -875,12 +1259,17 @@ enum ADLGraphicCoreGeneration #define ADL_DISPLAY_SLSGRID_RELATIVETO_CURRENTANGLE 0x00000020 +/// The bit mask identifies displays is currently in bezel mode. #define ADL_DISPLAY_SLSMAP_BEZELMODE 0x00000010 +/// The bit mask identifies displays from this map is arranged. #define ADL_DISPLAY_SLSMAP_DISPLAYARRANGED 0x00000002 +/// The bit mask identifies this map is currently in used for the current adapter. #define ADL_DISPLAY_SLSMAP_CURRENTCONFIG 0x00000004 +///For onlay active SLS map info #define ADL_DISPLAY_SLSMAPINDEXLIST_OPTION_ACTIVE 0x00000001 +///For Bezel #define ADL_DISPLAY_BEZELOFFSET_STEPBYSTEPSET 0x00000004 #define ADL_DISPLAY_BEZELOFFSET_COMMIT 0x00000008 @@ -901,20 +1290,24 @@ typedef enum DceSettingsType { typedef enum DpLinkRate { DPLinkRate_Unknown, DPLinkRate_RBR, - DPLinkRate_2_16Gbps, - DPLinkRate_2_43Gbps, + DPLinkRate_2_16Gbps, + DPLinkRate_2_43Gbps, DPLinkRate_HBR, - DPLinkRate_4_32Gbps, + DPLinkRate_4_32Gbps, DPLinkRate_HBR2, DPLinkRate_HBR3, - DPLinkRate_UHBR10, - DPLinkRate_UHBR13D5, - DPLinkRate_UHBR20 + DPLinkRate_UHBR10, + DPLinkRate_UHBR13D5, + DPLinkRate_UHBR20 } DpLinkRate; +/// @} +///\defgroup define_powerxpress_constants PowerXpress Definitions +/// @{ +/// The bit mask identifies PX caps for ADLPXConfigCaps.iPXConfigCapMask and ADLPXConfigCaps.iPXConfigCapValue #define ADL_PX_CONFIGCAPS_SPLASHSCREEN_SUPPORT 0x0001 #define ADL_PX_CONFIGCAPS_CF_SUPPORT 0x0002 #define ADL_PX_CONFIGCAPS_MUXLESS 0x0004 @@ -924,9 +1317,11 @@ typedef enum DpLinkRate { #define ADL_PX_CONFIGCAPS_DYNAMIC_SUPPORT 0x0040 #define ADL_PX_CONFIGCAPS_HIDE_AUTO_SWITCH 0x0080 +/// The bit mask identifies PX schemes for ADLPXSchemeRange #define ADL_PX_SCHEMEMASK_FIXED 0x0001 #define ADL_PX_SCHEMEMASK_DYNAMIC 0x0002 +/// PX Schemes typedef enum ADLPXScheme { ADL_PX_SCHEME_INVALID = 0, @@ -934,6 +1329,7 @@ typedef enum ADLPXScheme ADL_PX_SCHEME_DYNAMIC = ADL_PX_SCHEMEMASK_DYNAMIC }ADLPXScheme; +/// Just keep the old definitions for compatibility, need to be removed later typedef enum PXScheme { PX_SCHEME_INVALID = 0, @@ -942,7 +1338,10 @@ typedef enum PXScheme } PXScheme; +/// @} +///\defgroup define_appprofiles For Application Profiles +/// @{ #define ADL_APP_PROFILE_FILENAME_LENGTH 256 #define ADL_APP_PROFILE_TIMESTAMP_LENGTH 32 @@ -973,25 +1372,36 @@ typedef enum ADLProfilePropertyType //Virtual display type returning virtual display type and for request for creating a dummy target ID (xInput or remote play) typedef enum ADL_VIRTUALDISPLAY_TYPE { - ADL_VIRTUALDISPLAY_NONE = 0, - ADL_VIRTUALDISPLAY_XINPUT = 1, //Requested for xInput - ADL_VIRTUALDISPLAY_REMOTEPLAY = 2, //Requested for emulated display during remote play - ADL_VIRTUALDISPLAY_GENERIC = 10 //Generic virtual display, af a type different than any of the above special ones + ADL_VIRTUALDISPLAY_NONE = 0, + ADL_VIRTUALDISPLAY_XINPUT = 1, //Requested for xInput + ADL_VIRTUALDISPLAY_REMOTEPLAY = 2, //Requested for emulated display during remote play + ADL_VIRTUALDISPLAY_GENERIC = 10 //Generic virtual display, af a type different than any of the above special ones }ADL_VIRTUALDISPLAY_TYPE; +/// @} +///\defgroup define_dp12 For Display Port 1.2 +/// @{ +/// Maximum Relative Address Link #define ADL_MAX_RAD_LINK_COUNT 15 +/// @} +///\defgroup defines_gamutspace Driver Supported Gamut Space +/// @{ +/// The flags desribes that gamut is related to source or to destination and to overlay or to graphics #define ADL_GAMUT_REFERENCE_SOURCE (1 << 0) #define ADL_GAMUT_GAMUT_VIDEO_CONTENT (1 << 1) +/// The flags are used to describe the source of gamut and how read information from struct ADLGamutData #define ADL_CUSTOM_WHITE_POINT (1 << 0) #define ADL_CUSTOM_GAMUT (1 << 1) #define ADL_GAMUT_REMAP_ONLY (1 << 2) +/// The define means the predefined gamut values . +///Driver uses to find entry in the table and apply appropriate gamut space. #define ADL_GAMUT_SPACE_CCIR_709 (1 << 0) #define ADL_GAMUT_SPACE_CCIR_601 (1 << 1) #define ADL_GAMUT_SPACE_ADOBE_RGB (1 << 2) @@ -1000,28 +1410,46 @@ typedef enum ADL_VIRTUALDISPLAY_TYPE #define ADL_GAMUT_SPACE_CCIR_2020 (1 << 5) #define ADL_GAMUT_SPACE_APPCTRL (1 << 6) +/// Predefine white point values are structed similar to gamut . #define ADL_WHITE_POINT_5000K (1 << 0) #define ADL_WHITE_POINT_6500K (1 << 1) #define ADL_WHITE_POINT_7500K (1 << 2) #define ADL_WHITE_POINT_9300K (1 << 3) #define ADL_WHITE_POINT_CUSTOM (1 << 4) +///gamut and white point coordinates are from 0.0 -1.0 and divider is used to find the real value . +/// X float = X int /divider #define ADL_GAMUT_WHITEPOINT_DIVIDER 10000 +///gamma a0 coefficient uses the following divider: #define ADL_REGAMMA_COEFFICIENT_A0_DIVIDER 10000000 +///gamma a1 ,a2,a3 coefficients use the following divider: #define ADL_REGAMMA_COEFFICIENT_A1A2A3_DIVIDER 1000 +///describes whether the coefficients are from EDID or custom user values. #define ADL_EDID_REGAMMA_COEFFICIENTS (1 << 0) +///Used for struct ADLRegamma. Feature if set use gamma ramp, if missing use regamma coefficents #define ADL_USE_GAMMA_RAMP (1 << 4) +///Used for struct ADLRegamma. If the gamma ramp flag is used then the driver could apply de gamma corretion to the supplied curve and this depends on this flag #define ADL_APPLY_DEGAMMA (1 << 5) +///specifies that standard SRGB gamma should be applied #define ADL_EDID_REGAMMA_PREDEFINED_SRGB (1 << 1) +///specifies that PQ gamma curve should be applied #define ADL_EDID_REGAMMA_PREDEFINED_PQ (1 << 2) +///specifies that PQ gamma curve should be applied, lower max nits #define ADL_EDID_REGAMMA_PREDEFINED_PQ_2084_INTERIM (1 << 3) +///specifies that 3.6 gamma should be applied #define ADL_EDID_REGAMMA_PREDEFINED_36 (1 << 6) +///specifies that BT709 gama should be applied #define ADL_EDID_REGAMMA_PREDEFINED_BT709 (1 << 7) +///specifies that regamma should be disabled, and application controls regamma content (of the whole screen) #define ADL_EDID_REGAMMA_PREDEFINED_APPCTRL (1 << 8) +/// @} +/// \defgroup define_ddcinfo_pixelformats DDCInfo Pixel Formats +/// @{ +/// defines for iPanelPixelFormat in struct ADLDDCInfo2 #define ADL_DISPLAY_DDCINFO_PIXEL_FORMAT_RGB656 0x00000001L #define ADL_DISPLAY_DDCINFO_PIXEL_FORMAT_RGB666 0x00000002L #define ADL_DISPLAY_DDCINFO_PIXEL_FORMAT_RGB888 0x00000004L @@ -1040,79 +1468,170 @@ typedef enum ADL_VIRTUALDISPLAY_TYPE #define ADL_DISPLAY_DDCINFO_PIXEL_FORMAT_YCBCR420_8BPCC 0x00008000L #define ADL_DISPLAY_DDCINFO_PIXEL_FORMAT_YCBCR420_10BPCC 0x00010000L #define ADL_DISPLAY_DDCINFO_PIXEL_FORMAT_YCBCR420_12BPCC 0x00020000L +/// @} -#define ADL_TF_sRGB 0x0001 -#define ADL_TF_BT709 0x0002 -#define ADL_TF_PQ2084 0x0004 -#define ADL_TF_PQ2084_INTERIM 0x0008 -#define ADL_TF_LINEAR_0_1 0x0010 -#define ADL_TF_LINEAR_0_125 0x0020 -#define ADL_TF_DOLBYVISION 0x0040 -#define ADL_TF_GAMMA_22 0x0080 +/// \defgroup define_source_content_TF ADLSourceContentAttributes transfer functions (gamma) +/// @{ +/// defines for iTransferFunction in ADLSourceContentAttributes +#define ADL_TF_sRGB 0x0001 ///< sRGB +#define ADL_TF_BT709 0x0002 ///< BT.709 +#define ADL_TF_PQ2084 0x0004 ///< PQ2084 +#define ADL_TF_PQ2084_INTERIM 0x0008 ///< PQ2084-Interim +#define ADL_TF_LINEAR_0_1 0x0010 ///< Linear 0 - 1 +#define ADL_TF_LINEAR_0_125 0x0020 ///< Linear 0 - 125 +#define ADL_TF_DOLBYVISION 0x0040 ///< DolbyVision +#define ADL_TF_GAMMA_22 0x0080 ///< Plain 2.2 gamma curve +/// @} -#define ADL_CS_sRGB 0x0001 -#define ADL_CS_BT601 0x0002 -#define ADL_CS_BT709 0x0004 -#define ADL_CS_BT2020 0x0008 -#define ADL_CS_ADOBE 0x0010 -#define ADL_CS_P3 0x0020 -#define ADL_CS_scRGB_MS_REF 0x0040 -#define ADL_CS_DISPLAY_NATIVE 0x0080 -#define ADL_CS_APP_CONTROL 0x0100 -#define ADL_CS_DOLBYVISION 0x0200 +/// \defgroup define_source_content_CS ADLSourceContentAttributes color spaces +/// @{ +/// defines for iColorSpace in ADLSourceContentAttributes +#define ADL_CS_sRGB 0x0001 ///< sRGB +#define ADL_CS_BT601 0x0002 ///< BT.601 +#define ADL_CS_BT709 0x0004 ///< BT.709 +#define ADL_CS_BT2020 0x0008 ///< BT.2020 +#define ADL_CS_ADOBE 0x0010 ///< Adobe RGB +#define ADL_CS_P3 0x0020 ///< DCI-P3 +#define ADL_CS_scRGB_MS_REF 0x0040 ///< scRGB (MS Reference) +#define ADL_CS_DISPLAY_NATIVE 0x0080 ///< Display Native +#define ADL_CS_APP_CONTROL 0x0100 ///< Application Controlled +#define ADL_CS_DOLBYVISION 0x0200 ///< DolbyVision +/// @} -#define ADL_HDR_CEA861_3 0x0001 -#define ADL_HDR_DOLBYVISION 0x0002 -#define ADL_HDR_FREESYNC_HDR 0x0004 +/// \defgroup define_HDR_support ADLDDCInfo2 HDR support options +/// @{ +/// defines for iSupportedHDR in ADLDDCInfo2 +#define ADL_HDR_CEA861_3 0x0001 ///< HDR10/CEA861.3 HDR supported +#define ADL_HDR_DOLBYVISION 0x0002 ///< \deprecated DolbyVision HDR supported +#define ADL_HDR_FREESYNC_HDR 0x0004 ///< FreeSync HDR supported +/// @} -#define ADL_HDR_FREESYNC_BACKLIGHT_SUPPORT 0x0001 -#define ADL_HDR_FREESYNC_LOCAL_DIMMING 0x0002 +/// \defgroup define_FreesyncFlags ADLDDCInfo2 Freesync HDR flags +/// @{ +/// defines for iFreesyncFlags in ADLDDCInfo2 +#define ADL_HDR_FREESYNC_BACKLIGHT_SUPPORT 0x0001 ///< Global backlight control supported +#define ADL_HDR_FREESYNC_LOCAL_DIMMING 0x0002 ///< Local dimming supported +/// @} -#define ADL_SCA_LOCAL_DIMMING_DISABLE 0x0001 +/// \defgroup define_source_content_flags ADLSourceContentAttributes flags +/// @{ +/// defines for iFlags in ADLSourceContentAttributes +#define ADL_SCA_LOCAL_DIMMING_DISABLE 0x0001 ///< Disable local dimming +/// @} +/// \defgroup define_dbd_state Deep Bit Depth +/// @{ +/// defines for ADL_Workstation_DeepBitDepth_Get and ADL_Workstation_DeepBitDepth_Set functions // This value indicates that the deep bit depth state is forced off #define ADL_DEEPBITDEPTH_FORCEOFF 0 +/// This value indicates that the deep bit depth state is set to auto, the driver will automatically enable the +/// appropriate deep bit depth state depending on what connected display supports. #define ADL_DEEPBITDEPTH_10BPP_AUTO 1 +/// This value indicates that the deep bit depth state is forced on to 10 bits per pixel, this is regardless if the display +/// supports 10 bpp. #define ADL_DEEPBITDEPTH_10BPP_FORCEON 2 +/// defines for ADLAdapterConfigMemory of ADL_Adapter_ConfigMemory_Get +/// If this bit is set, it indicates that the Deep Bit Depth pixel is set on the display #define ADL_ADAPTER_CONFIGMEMORY_DBD (1 << 0) +/// If this bit is set, it indicates that the display is rotated (90, 180 or 270) #define ADL_ADAPTER_CONFIGMEMORY_ROTATE (1 << 1) +/// If this bit is set, it indicates that passive stereo is set on the display #define ADL_ADAPTER_CONFIGMEMORY_STEREO_PASSIVE (1 << 2) +/// If this bit is set, it indicates that the active stereo is set on the display #define ADL_ADAPTER_CONFIGMEMORY_STEREO_ACTIVE (1 << 3) +/// If this bit is set, it indicates that the tear free vsync is set on the display #define ADL_ADAPTER_CONFIGMEMORY_ENHANCEDVSYNC (1 << 4) #define ADL_ADAPTER_CONFIGMEMORY_TEARFREEVSYNC (1 << 4) +/// @} +/// \defgroup define_adl_validmemoryrequiredfields Memory Type +/// @{ +/// This group defines memory types in ADLMemoryRequired struct \n +/// Indicates that this is the visible memory #define ADL_MEMORYREQTYPE_VISIBLE (1 << 0) +/// Indicates that this is the invisible memory. #define ADL_MEMORYREQTYPE_INVISIBLE (1 << 1) +/// Indicates that this is amount of visible memory per GPU that should be reserved for all other allocations. #define ADL_MEMORYREQTYPE_GPURESERVEDVISIBLE (1 << 2) +/// @} +/// \defgroup define_adapter_tear_free_status +/// Used in ADL_Adapter_TEAR_FREE_Set and ADL_Adapter_TFD_Get functions to indicate the tear free +/// desktop status. +/// @{ +/// Tear free desktop is enabled. #define ADL_ADAPTER_TEAR_FREE_ON 1 +/// Tear free desktop can't be enabled due to a lack of graphic adapter memory. #define ADL_ADAPTER_TEAR_FREE_NOTENOUGHMEM -1 +/// Tear free desktop can't be enabled due to quad buffer stereo being enabled. #define ADL_ADAPTER_TEAR_FREE_OFF_ERR_QUADBUFFERSTEREO -2 +/// Tear free desktop can't be enabled due to MGPU-SLS being enabled. #define ADL_ADAPTER_TEAR_FREE_OFF_ERR_MGPUSLD -3 +/// Tear free desktop is disabled. #define ADL_ADAPTER_TEAR_FREE_OFF 0 +/// @} +/// \defgroup define_adapter_crossdisplay_platforminfo +/// Used in ADL_Adapter_CrossDisplayPlatformInfo_Get function to indicate the Crossdisplay platform info. +/// @{ +/// CROSSDISPLAY platform. #define ADL_CROSSDISPLAY_PLATFORM (1 << 0) +/// CROSSDISPLAY platform for Lasso station. #define ADL_CROSSDISPLAY_PLATFORM_LASSO (1 << 1) +/// CROSSDISPLAY platform for docking station. #define ADL_CROSSDISPLAY_PLATFORM_DOCKSTATION (1 << 2) +/// @} +/// \defgroup define_adapter_crossdisplay_option +/// Used in ADL_Adapter_CrossdisplayInfoX2_Set function to indicate cross display options. +/// @{ +/// Checking if 3D application is runnning. If yes, not to do switch, return ADL_OK_WAIT; otherwise do switch. #define ADL_CROSSDISPLAY_OPTION_NONE 0 +/// Force switching without checking for running 3D applications #define ADL_CROSSDISPLAY_OPTION_FORCESWITCH (1 << 0) +/// @} +/// \defgroup define_adapter_states Adapter Capabilities +/// These defines the capabilities supported by an adapter. It is used by \ref ADL_Adapter_ConfigureState_Get +/// @{ +/// Indicates that the adapter is headless (i.e. no displays can be connected to it) #define ADL_ADAPTERCONFIGSTATE_HEADLESS ( 1 << 2 ) +/// Indicates that the adapter is configured to define the main rendering capabilities. For example, adapters +/// in Crossfire(TM) configuration, this bit would only be set on the adapter driving the display(s). #define ADL_ADAPTERCONFIGSTATE_REQUISITE_RENDER ( 1 << 0 ) +/// Indicates that the adapter is configured to be used to unload some of the rendering work for a particular +/// requisite rendering adapter. For eample, for adapters in a Crossfire configuration, this bit would be set +/// on all adapters that are currently not driving the display(s) #define ADL_ADAPTERCONFIGSTATE_ANCILLARY_RENDER ( 1 << 1 ) +/// Indicates that scatter gather feature enabled on the adapter #define ADL_ADAPTERCONFIGSTATE_SCATTERGATHER ( 1 << 4 ) +/// @} +/// \defgroup define_controllermode_ulModifiers +/// These defines the detailed actions supported by set viewport. It is used by \ref ADL_Display_ViewPort_Set +/// @{ +/// Indicate that the viewport set will change the view position #define ADL_CONTROLLERMODE_CM_MODIFIER_VIEW_POSITION 0x00000001 +/// Indicate that the viewport set will change the view PanLock #define ADL_CONTROLLERMODE_CM_MODIFIER_VIEW_PANLOCK 0x00000002 +/// Indicate that the viewport set will change the view size #define ADL_CONTROLLERMODE_CM_MODIFIER_VIEW_SIZE 0x00000008 +/// @} +/// \defgroup defines for Mirabilis +/// These defines are used for the Mirabilis feature +/// @{ +/// +/// Indicates the maximum number of audio sample rates #define ADL_MAX_AUDIO_SAMPLE_RATE_COUNT 16 +/// @} +/////////////////////////////////////////////////////////////////////////// // ADLMultiChannelSplitStateFlag Enumeration +/////////////////////////////////////////////////////////////////////////// enum ADLMultiChannelSplitStateFlag { ADLMultiChannelSplit_Unitialized = 0, @@ -1121,7 +1640,9 @@ enum ADLMultiChannelSplitStateFlag ADLMultiChannelSplit_SaveProfile = 3 }; +/////////////////////////////////////////////////////////////////////////// // ADLSampleRate Enumeration +/////////////////////////////////////////////////////////////////////////// enum ADLSampleRate { ADLSampleRate_32KHz =0, @@ -1136,44 +1657,107 @@ enum ADLSampleRate ADLSampleRate_Undefined }; +/// \defgroup define_overdrive6_capabilities +/// These defines the capabilities supported by Overdrive 6. It is used by \ref ADL_Overdrive6_Capabilities_Get +/// @{ +/// Indicate that core (engine) clock can be changed. #define ADL_OD6_CAPABILITY_SCLK_CUSTOMIZATION 0x00000001 +/// Indicate that memory clock can be changed. #define ADL_OD6_CAPABILITY_MCLK_CUSTOMIZATION 0x00000002 +/// Indicate that graphics activity reporting is supported. #define ADL_OD6_CAPABILITY_GPU_ACTIVITY_MONITOR 0x00000004 +/// Indicate that power limit can be customized. #define ADL_OD6_CAPABILITY_POWER_CONTROL 0x00000008 +/// Indicate that SVI2 Voltage Control is supported. #define ADL_OD6_CAPABILITY_VOLTAGE_CONTROL 0x00000010 +/// Indicate that OD6+ percentage adjustment is supported. #define ADL_OD6_CAPABILITY_PERCENT_ADJUSTMENT 0x00000020 +/// Indicate that Thermal Limit Unlock is supported. #define ADL_OD6_CAPABILITY_THERMAL_LIMIT_UNLOCK 0x00000040 +///Indicate that Fan speed needs to be displayed in RPM #define ADL_OD6_CAPABILITY_FANSPEED_IN_RPM 0x00000080 +/// @} +/// \defgroup define_overdrive6_supported_states +/// These defines the power states supported by Overdrive 6. It is used by \ref ADL_Overdrive6_Capabilities_Get +/// @{ +/// Indicate that overdrive is supported in the performance state. This is currently the only state supported. #define ADL_OD6_SUPPORTEDSTATE_PERFORMANCE 0x00000001 +/// Do not use. Reserved for future use. #define ADL_OD6_SUPPORTEDSTATE_POWER_SAVING 0x00000002 +/// @} +/// \defgroup define_overdrive6_getstateinfo +/// These defines the power states to get information about. It is used by \ref ADL_Overdrive6_StateInfo_Get +/// @{ +/// Get default clocks for the performance state. #define ADL_OD6_GETSTATEINFO_DEFAULT_PERFORMANCE 0x00000001 +/// Do not use. Reserved for future use. #define ADL_OD6_GETSTATEINFO_DEFAULT_POWER_SAVING 0x00000002 +/// Get clocks for current state. Currently this is the same as \ref ADL_OD6_GETSTATEINFO_CUSTOM_PERFORMANCE +/// since only performance state is supported. #define ADL_OD6_GETSTATEINFO_CURRENT 0x00000003 +/// Get the modified clocks (if any) for the performance state. If clocks were not modified +/// through Overdrive 6, then this will return the same clocks as \ref ADL_OD6_GETSTATEINFO_DEFAULT_PERFORMANCE. #define ADL_OD6_GETSTATEINFO_CUSTOM_PERFORMANCE 0x00000004 +/// Do not use. Reserved for future use. #define ADL_OD6_GETSTATEINFO_CUSTOM_POWER_SAVING 0x00000005 +/// @} +/// \defgroup define_overdrive6_getstate and define_overdrive6_getmaxclockadjust +/// These defines the power states to get information about. It is used by \ref ADL_Overdrive6_StateEx_Get and \ref ADL_Overdrive6_MaxClockAdjust_Get +/// @{ +/// Get default clocks for the performance state. Only performance state is currently supported. #define ADL_OD6_STATE_PERFORMANCE 0x00000001 +/// @} +/// \defgroup define_overdrive6_setstate +/// These define which power state to set customized clocks on. It is used by \ref ADL_Overdrive6_State_Set +/// @{ +/// Set customized clocks for the performance state. #define ADL_OD6_SETSTATE_PERFORMANCE 0x00000001 +/// Do not use. Reserved for future use. #define ADL_OD6_SETSTATE_POWER_SAVING 0x00000002 +/// @} +/// \defgroup define_overdrive6_thermalcontroller_caps +/// These defines the capabilities of the GPU thermal controller. It is used by \ref ADL_Overdrive6_ThermalController_Caps +/// @{ +/// GPU thermal controller is supported. #define ADL_OD6_TCCAPS_THERMAL_CONTROLLER 0x00000001 +/// GPU fan speed control is supported. #define ADL_OD6_TCCAPS_FANSPEED_CONTROL 0x00000002 +/// Fan speed percentage can be read. #define ADL_OD6_TCCAPS_FANSPEED_PERCENT_READ 0x00000100 +/// Fan speed can be set by specifying a percentage value. #define ADL_OD6_TCCAPS_FANSPEED_PERCENT_WRITE 0x00000200 +/// Fan speed RPM (revolutions-per-minute) can be read. #define ADL_OD6_TCCAPS_FANSPEED_RPM_READ 0x00000400 +/// Fan speed can be set by specifying an RPM value. #define ADL_OD6_TCCAPS_FANSPEED_RPM_WRITE 0x00000800 +/// @} +/// \defgroup define_overdrive6_fanspeed_type +/// These defines the fan speed type being reported. It is used by \ref ADL_Overdrive6_FanSpeed_Get +/// @{ +/// Fan speed reported in percentage. #define ADL_OD6_FANSPEED_TYPE_PERCENT 0x00000001 +/// Fan speed reported in RPM. #define ADL_OD6_FANSPEED_TYPE_RPM 0x00000002 +/// Fan speed has been customized by the user, and fan is not running in automatic mode. #define ADL_OD6_FANSPEED_USER_DEFINED 0x00000100 +/// @} +/// \defgroup define_overdrive_EventCounter_type +/// These defines the EventCounter type being reported. It is used by \ref ADL2_OverdriveN_CountOfEvents_Get ,can be used on older OD version supported ASICs also. +/// @{ #define ADL_ODN_EVENTCOUNTER_THERMAL 0 #define ADL_ODN_EVENTCOUNTER_VPURECOVERY 1 +/// @} +/////////////////////////////////////////////////////////////////////////// // ADLODNControlType Enumeration +/////////////////////////////////////////////////////////////////////////// enum ADLODNControlType { ODNControlType_Current = 0, @@ -1184,67 +1768,67 @@ enum ADLODNControlType enum ADLODNDPMMaskType { - ADL_ODN_DPM_CLOCK = 1 << 0, - ADL_ODN_DPM_VDDC = 1 << 1, - ADL_ODN_DPM_MASK = 1 << 2, + ADL_ODN_DPM_CLOCK = 1 << 0, + ADL_ODN_DPM_VDDC = 1 << 1, + ADL_ODN_DPM_MASK = 1 << 2, }; //ODN features Bits for ADLODNCapabilitiesX2 enum ADLODNFeatureControl { - ADL_ODN_SCLK_DPM = 1 << 0, - ADL_ODN_MCLK_DPM = 1 << 1, - ADL_ODN_SCLK_VDD = 1 << 2, - ADL_ODN_MCLK_VDD = 1 << 3, - ADL_ODN_FAN_SPEED_MIN = 1 << 4, - ADL_ODN_FAN_SPEED_TARGET = 1 << 5, - ADL_ODN_ACOUSTIC_LIMIT_SCLK = 1 << 6, - ADL_ODN_TEMPERATURE_FAN_MAX = 1 << 7, - ADL_ODN_TEMPERATURE_SYSTEM = 1 << 8, - ADL_ODN_POWER_LIMIT = 1 << 9, - ADL_ODN_SCLK_AUTO_LIMIT = 1 << 10, - ADL_ODN_MCLK_AUTO_LIMIT = 1 << 11, - ADL_ODN_SCLK_DPM_MASK_ENABLE = 1 << 12, - ADL_ODN_MCLK_DPM_MASK_ENABLE = 1 << 13, - ADL_ODN_MCLK_UNDERCLOCK_ENABLE = 1 << 14, - ADL_ODN_SCLK_DPM_THROTTLE_NOTIFY = 1 << 15, - ADL_ODN_POWER_UTILIZATION = 1 << 16, - ADL_ODN_PERF_TUNING_SLIDER = 1 << 17, - ADL_ODN_REMOVE_WATTMAN_PAGE = 1 << 31 // Internal Only + ADL_ODN_SCLK_DPM = 1 << 0, + ADL_ODN_MCLK_DPM = 1 << 1, + ADL_ODN_SCLK_VDD = 1 << 2, + ADL_ODN_MCLK_VDD = 1 << 3, + ADL_ODN_FAN_SPEED_MIN = 1 << 4, + ADL_ODN_FAN_SPEED_TARGET = 1 << 5, + ADL_ODN_ACOUSTIC_LIMIT_SCLK = 1 << 6, + ADL_ODN_TEMPERATURE_FAN_MAX = 1 << 7, + ADL_ODN_TEMPERATURE_SYSTEM = 1 << 8, + ADL_ODN_POWER_LIMIT = 1 << 9, + ADL_ODN_SCLK_AUTO_LIMIT = 1 << 10, + ADL_ODN_MCLK_AUTO_LIMIT = 1 << 11, + ADL_ODN_SCLK_DPM_MASK_ENABLE = 1 << 12, + ADL_ODN_MCLK_DPM_MASK_ENABLE = 1 << 13, + ADL_ODN_MCLK_UNDERCLOCK_ENABLE = 1 << 14, + ADL_ODN_SCLK_DPM_THROTTLE_NOTIFY = 1 << 15, + ADL_ODN_POWER_UTILIZATION = 1 << 16, + ADL_ODN_PERF_TUNING_SLIDER = 1 << 17, + ADL_ODN_REMOVE_WATTMAN_PAGE = 1 << 31 // Internal Only }; //If any new feature is added, PPLIB only needs to add ext feature ID and Item ID(Seeting ID). These IDs should match the drive defined in CWDDEPM.h enum ADLODNExtFeatureControl { - ADL_ODN_EXT_FEATURE_MEMORY_TIMING_TUNE = 1 << 0, - ADL_ODN_EXT_FEATURE_FAN_ZERO_RPM_CONTROL = 1 << 1, - ADL_ODN_EXT_FEATURE_AUTO_UV_ENGINE = 1 << 2, //Auto under voltage - ADL_ODN_EXT_FEATURE_AUTO_OC_ENGINE = 1 << 3, //Auto OC Enine - ADL_ODN_EXT_FEATURE_AUTO_OC_MEMORY = 1 << 4, //Auto OC memory - ADL_ODN_EXT_FEATURE_FAN_CURVE = 1 << 5 //Fan curve + ADL_ODN_EXT_FEATURE_MEMORY_TIMING_TUNE = 1 << 0, + ADL_ODN_EXT_FEATURE_FAN_ZERO_RPM_CONTROL = 1 << 1, + ADL_ODN_EXT_FEATURE_AUTO_UV_ENGINE = 1 << 2, //Auto under voltage + ADL_ODN_EXT_FEATURE_AUTO_OC_ENGINE = 1 << 3, //Auto OC Enine + ADL_ODN_EXT_FEATURE_AUTO_OC_MEMORY = 1 << 4, //Auto OC memory + ADL_ODN_EXT_FEATURE_FAN_CURVE = 1 << 5 //Fan curve }; //If any new feature is added, PPLIB only needs to add ext feature ID and Item ID(Seeting ID).These IDs should match the drive defined in CWDDEPM.h enum ADLODNExtSettingId { - ADL_ODN_PARAMETER_AC_TIMING = 0, - ADL_ODN_PARAMETER_FAN_ZERO_RPM_CONTROL, - ADL_ODN_PARAMETER_AUTO_UV_ENGINE, - ADL_ODN_PARAMETER_AUTO_OC_ENGINE, - ADL_ODN_PARAMETER_AUTO_OC_MEMORY, - ADL_ODN_PARAMETER_FAN_CURVE_TEMPERATURE_1, - ADL_ODN_PARAMETER_FAN_CURVE_SPEED_1, - ADL_ODN_PARAMETER_FAN_CURVE_TEMPERATURE_2, - ADL_ODN_PARAMETER_FAN_CURVE_SPEED_2, - ADL_ODN_PARAMETER_FAN_CURVE_TEMPERATURE_3, - ADL_ODN_PARAMETER_FAN_CURVE_SPEED_3, - ADL_ODN_PARAMETER_FAN_CURVE_TEMPERATURE_4, - ADL_ODN_PARAMETER_FAN_CURVE_SPEED_4, - ADL_ODN_PARAMETER_FAN_CURVE_TEMPERATURE_5, - ADL_ODN_PARAMETER_FAN_CURVE_SPEED_5, + ADL_ODN_PARAMETER_AC_TIMING = 0, + ADL_ODN_PARAMETER_FAN_ZERO_RPM_CONTROL, + ADL_ODN_PARAMETER_AUTO_UV_ENGINE, + ADL_ODN_PARAMETER_AUTO_OC_ENGINE, + ADL_ODN_PARAMETER_AUTO_OC_MEMORY, + ADL_ODN_PARAMETER_FAN_CURVE_TEMPERATURE_1, + ADL_ODN_PARAMETER_FAN_CURVE_SPEED_1, + ADL_ODN_PARAMETER_FAN_CURVE_TEMPERATURE_2, + ADL_ODN_PARAMETER_FAN_CURVE_SPEED_2, + ADL_ODN_PARAMETER_FAN_CURVE_TEMPERATURE_3, + ADL_ODN_PARAMETER_FAN_CURVE_SPEED_3, + ADL_ODN_PARAMETER_FAN_CURVE_TEMPERATURE_4, + ADL_ODN_PARAMETER_FAN_CURVE_SPEED_4, + ADL_ODN_PARAMETER_FAN_CURVE_TEMPERATURE_5, + ADL_ODN_PARAMETER_FAN_CURVE_SPEED_5, ADL_ODN_POWERGAUGE, - ODN_COUNT + ODN_COUNT } ; @@ -1261,59 +1845,79 @@ enum ADLOD8FeatureControl ADL_OD8_TEMPERATURE_SYSTEM = 1 << 7, //MaxOpTemp ADL_OD8_MEMORY_TIMING_TUNE = 1 << 8, ADL_OD8_FAN_ZERO_RPM_CONTROL = 1 << 9 , - ADL_OD8_AUTO_UV_ENGINE = 1 << 10, //Auto under voltage - ADL_OD8_AUTO_OC_ENGINE = 1 << 11, //Auto overclock engine - ADL_OD8_AUTO_OC_MEMORY = 1 << 12, //Auto overclock memory - ADL_OD8_FAN_CURVE = 1 << 13, //Fan curve - ADL_OD8_WS_AUTO_FAN_ACOUSTIC_LIMIT = 1 << 14, //Workstation Manual Fan controller + ADL_OD8_AUTO_UV_ENGINE = 1 << 10, //Auto under voltage + ADL_OD8_AUTO_OC_ENGINE = 1 << 11, //Auto overclock engine + ADL_OD8_AUTO_OC_MEMORY = 1 << 12, //Auto overclock memory + ADL_OD8_FAN_CURVE = 1 << 13, //Fan curve + ADL_OD8_WS_AUTO_FAN_ACOUSTIC_LIMIT = 1 << 14, //Workstation Manual Fan controller ADL_OD8_GFXCLK_QUADRATIC_CURVE = 1 << 15, ADL_OD8_OPTIMIZED_GPU_POWER_MODE = 1 << 16, ADL_OD8_ODVOLTAGE_LIMIT = 1 << 17, - ADL_OD8_POWER_GAUGE = 1 << 18 //Power Gauge + ADL_OD8_ADV_OC_LIMITS = 1 << 18, //Advanced OC limits. + ADL_OD8_PER_ZONE_GFX_VOLTAGE_OFFSET = 1 << 19, //Per Zone gfx voltage offset feature + ADL_OD8_AUTO_CURVE_OPTIMIZER = 1 << 20, //Auto per zone tuning. + ADL_OD8_GFX_VOLTAGE_LIMIT = 1 << 21, //Voltage limit slider + ADL_OD8_TDC_LIMIT = 1 << 22, //TDC slider + ADL_OD8_FULL_CONTROL_MODE = 1 << 23, //Full control + ADL_OD8_POWER_SAVING_FEATURE_CONTROL = 1 << 24, //Power saving feature control + ADL_OD8_POWER_GAUGE = 1 << 25 //Power Gauge }; typedef enum ADLOD8SettingId { - OD8_GFXCLK_FMAX = 0, - OD8_GFXCLK_FMIN, - OD8_GFXCLK_FREQ1, - OD8_GFXCLK_VOLTAGE1, - OD8_GFXCLK_FREQ2, - OD8_GFXCLK_VOLTAGE2, - OD8_GFXCLK_FREQ3, - OD8_GFXCLK_VOLTAGE3, - OD8_UCLK_FMAX, - OD8_POWER_PERCENTAGE, - OD8_FAN_MIN_SPEED, - OD8_FAN_ACOUSTIC_LIMIT, - OD8_FAN_TARGET_TEMP, - OD8_OPERATING_TEMP_MAX, - OD8_AC_TIMING, - OD8_FAN_ZERORPM_CONTROL, - OD8_AUTO_UV_ENGINE_CONTROL, - OD8_AUTO_OC_ENGINE_CONTROL, - OD8_AUTO_OC_MEMORY_CONTROL, - OD8_FAN_CURVE_TEMPERATURE_1, - OD8_FAN_CURVE_SPEED_1, - OD8_FAN_CURVE_TEMPERATURE_2, - OD8_FAN_CURVE_SPEED_2, - OD8_FAN_CURVE_TEMPERATURE_3, - OD8_FAN_CURVE_SPEED_3, - OD8_FAN_CURVE_TEMPERATURE_4, - OD8_FAN_CURVE_SPEED_4, - OD8_FAN_CURVE_TEMPERATURE_5, - OD8_FAN_CURVE_SPEED_5, - OD8_WS_FAN_AUTO_FAN_ACOUSTIC_LIMIT, - RESERVED_1, - RESERVED_2, - RESERVED_3, - RESERVED_4, + OD8_GFXCLK_FMAX = 0, + OD8_GFXCLK_FMIN, + OD8_GFXCLK_FREQ1, + OD8_GFXCLK_VOLTAGE1, + OD8_GFXCLK_FREQ2, + OD8_GFXCLK_VOLTAGE2, + OD8_GFXCLK_FREQ3, + OD8_GFXCLK_VOLTAGE3, + OD8_UCLK_FMAX, + OD8_POWER_PERCENTAGE, + OD8_FAN_MIN_SPEED, + OD8_FAN_ACOUSTIC_LIMIT, + OD8_FAN_TARGET_TEMP, + OD8_OPERATING_TEMP_MAX, + OD8_AC_TIMING, + OD8_FAN_ZERORPM_CONTROL, + OD8_AUTO_UV_ENGINE_CONTROL, + OD8_AUTO_OC_ENGINE_CONTROL, + OD8_AUTO_OC_MEMORY_CONTROL, + OD8_FAN_CURVE_TEMPERATURE_1, + OD8_FAN_CURVE_SPEED_1, + OD8_FAN_CURVE_TEMPERATURE_2, + OD8_FAN_CURVE_SPEED_2, + OD8_FAN_CURVE_TEMPERATURE_3, + OD8_FAN_CURVE_SPEED_3, + OD8_FAN_CURVE_TEMPERATURE_4, + OD8_FAN_CURVE_SPEED_4, + OD8_FAN_CURVE_TEMPERATURE_5, + OD8_FAN_CURVE_SPEED_5, + OD8_WS_FAN_AUTO_FAN_ACOUSTIC_LIMIT, + OD8_GFXCLK_CURVE_COEFFICIENT_A, // As part of the agreement with UI team, the min/max voltage limits for the + OD8_GFXCLK_CURVE_COEFFICIENT_B, // quadratic curve graph will be stored in the min and max limits of + OD8_GFXCLK_CURVE_COEFFICIENT_C, // coefficient a, b and c. A, b and c themselves do not have limits. + OD8_GFXCLK_CURVE_VFT_FMIN, OD8_UCLK_FMIN, OD8_FAN_ZERO_RPM_STOP_TEMPERATURE, OD8_OPTIMZED_POWER_MODE, - OD8_OD_VOLTAGE, - OD8_POWER_GAUGE, //Starting from this is new features with new capabilities and new interface for limits. + OD8_OD_VOLTAGE,// RSX - voltage offset feature + OD8_ADV_OC_LIMITS_SETTING, + OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_1, + OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_2, + OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_3, + OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_4, + OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_5, + OD8_PER_ZONE_GFX_VOLTAGE_OFFSET_POINT_6, + OD8_AUTO_CURVE_OPTIMIZER_SETTING, + OD8_GFX_VOLTAGE_LIMIT_SETTING, + OD8_TDC_PERCENTAGE, + OD8_FULL_CONTROL_MODE_SETTING, + OD8_IDLE_POWER_SAVING_FEATURE_CONTROL, + OD8_RUNTIME_POWER_SAVING_FEATURE_CONTROL, + OD8_POWER_GAUGE, OD8_COUNT } ADLOD8SettingId; @@ -1321,6 +1925,7 @@ typedef enum ADLOD8SettingId //Define Performance Metrics Log max sensors number #define ADL_PMLOG_MAX_SENSORS 256 +/// \deprecated Replaced with ADL_PMLOG_SENSORS typedef enum ADLSensorType { SENSOR_MAXTYPES = 0, @@ -1369,6 +1974,34 @@ typedef enum ADLSensorType PMLOG_TEMPERATURE_LIQUID1 = 43, PMLOG_CLK_FCLK = 44, PMLOG_THROTTLER_STATUS_CPU = 45, + PMLOG_SSPAIRED_ASICPOWER = 46, // apuPower + PMLOG_SSTOTAL_POWERLIMIT = 47, // Total Power limit + PMLOG_SSAPU_POWERLIMIT = 48, // APU Power limit + PMLOG_SSDGPU_POWERLIMIT = 49, // DGPU Power limit + PMLOG_TEMPERATURE_HOTSPOT_GCD = 50, + PMLOG_TEMPERATURE_HOTSPOT_MCD = 51, + PMLOG_THROTTLER_TEMP_EDGE_PERCENTAGE = 52, + PMLOG_THROTTLER_TEMP_HOTSPOT_PERCENTAGE = 53, + PMLOG_THROTTLER_TEMP_HOTSPOT_GCD_PERCENTAGE = 54, + PMLOG_THROTTLER_TEMP_HOTSPOT_MCD_PERCENTAGE = 55, + PMLOG_THROTTLER_TEMP_MEM_PERCENTAGE = 56, + PMLOG_THROTTLER_TEMP_VR_GFX_PERCENTAGE = 57, + PMLOG_THROTTLER_TEMP_VR_MEM0_PERCENTAGE = 58, + PMLOG_THROTTLER_TEMP_VR_MEM1_PERCENTAGE = 59, + PMLOG_THROTTLER_TEMP_VR_SOC_PERCENTAGE = 60, + PMLOG_THROTTLER_TEMP_LIQUID0_PERCENTAGE = 61, + PMLOG_THROTTLER_TEMP_LIQUID1_PERCENTAGE = 62, + PMLOG_THROTTLER_TEMP_PLX_PERCENTAGE = 63, + PMLOG_THROTTLER_TDC_GFX_PERCENTAGE = 64, + PMLOG_THROTTLER_TDC_SOC_PERCENTAGE = 65, + PMLOG_THROTTLER_TDC_USR_PERCENTAGE = 66, + PMLOG_THROTTLER_PPT0_PERCENTAGE = 67, + PMLOG_THROTTLER_PPT1_PERCENTAGE = 68, + PMLOG_THROTTLER_PPT2_PERCENTAGE = 69, + PMLOG_THROTTLER_PPT3_PERCENTAGE = 70, + PMLOG_THROTTLER_FIT_PERCENTAGE = 71, + PMLOG_THROTTLER_GFX_APCC_PLUS_PERCENTAGE = 72, + PMLOG_BOARD_POWER = 73, PMLOG_MAX_SENSORS_REAL } ADLSensorType; @@ -1376,9 +2009,9 @@ typedef enum ADLSensorType //Throttle Status typedef enum ADL_THROTTLE_NOTIFICATION { - ADL_PMLOG_THROTTLE_POWER = 1 << 0, - ADL_PMLOG_THROTTLE_THERMAL = 1 << 1, - ADL_PMLOG_THROTTLE_CURRENT = 1 << 2, + ADL_PMLOG_THROTTLE_POWER = 1 << 0, + ADL_PMLOG_THROTTLE_THERMAL = 1 << 1, + ADL_PMLOG_THROTTLE_CURRENT = 1 << 2, } ADL_THROTTLE_NOTIFICATION; typedef enum ADL_PMLOG_SENSORS @@ -1429,112 +2062,293 @@ typedef enum ADL_PMLOG_SENSORS ADL_PMLOG_TEMPERATURE_LIQUID1 = 43, ADL_PMLOG_CLK_FCLK = 44, ADL_PMLOG_THROTTLER_STATUS_CPU = 45, + ADL_PMLOG_SSPAIRED_ASICPOWER = 46, // apuPower + ADL_PMLOG_SSTOTAL_POWERLIMIT = 47, // Total Power limit + ADL_PMLOG_SSAPU_POWERLIMIT = 48, // APU Power limit + ADL_PMLOG_SSDGPU_POWERLIMIT = 49, // DGPU Power limit + ADL_PMLOG_TEMPERATURE_HOTSPOT_GCD = 50, + ADL_PMLOG_TEMPERATURE_HOTSPOT_MCD = 51, + ADL_PMLOG_THROTTLER_TEMP_EDGE_PERCENTAGE = 52, + ADL_PMLOG_THROTTLER_TEMP_HOTSPOT_PERCENTAGE = 53, + ADL_PMLOG_THROTTLER_TEMP_HOTSPOT_GCD_PERCENTAGE = 54, + ADL_PMLOG_THROTTLER_TEMP_HOTSPOT_MCD_PERCENTAGE = 55, + ADL_PMLOG_THROTTLER_TEMP_MEM_PERCENTAGE = 56, + ADL_PMLOG_THROTTLER_TEMP_VR_GFX_PERCENTAGE = 57, + ADL_PMLOG_THROTTLER_TEMP_VR_MEM0_PERCENTAGE = 58, + ADL_PMLOG_THROTTLER_TEMP_VR_MEM1_PERCENTAGE = 59, + ADL_PMLOG_THROTTLER_TEMP_VR_SOC_PERCENTAGE = 60, + ADL_PMLOG_THROTTLER_TEMP_LIQUID0_PERCENTAGE = 61, + ADL_PMLOG_THROTTLER_TEMP_LIQUID1_PERCENTAGE = 62, + ADL_PMLOG_THROTTLER_TEMP_PLX_PERCENTAGE = 63, + ADL_PMLOG_THROTTLER_TDC_GFX_PERCENTAGE = 64, + ADL_PMLOG_THROTTLER_TDC_SOC_PERCENTAGE = 65, + ADL_PMLOG_THROTTLER_TDC_USR_PERCENTAGE = 66, + ADL_PMLOG_THROTTLER_PPT0_PERCENTAGE = 67, + ADL_PMLOG_THROTTLER_PPT1_PERCENTAGE = 68, + ADL_PMLOG_THROTTLER_PPT2_PERCENTAGE = 69, + ADL_PMLOG_THROTTLER_PPT3_PERCENTAGE = 70, + ADL_PMLOG_THROTTLER_FIT_PERCENTAGE = 71, + ADL_PMLOG_THROTTLER_GFX_APCC_PLUS_PERCENTAGE = 72, + ADL_PMLOG_BOARD_POWER = 73, + ADL_PMLOG_MAX_SENSORS_REAL } ADL_PMLOG_SENSORS; +/// \defgroup define_ecc_mode_states +/// These defines the ECC(Error Correction Code) state. It is used by \ref ADL_Workstation_ECC_Get,ADL_Workstation_ECC_Set +/// @{ +/// Error Correction is OFF. #define ECC_MODE_OFF 0 +/// Error Correction is ECCV2. #define ECC_MODE_ON 2 +/// Error Correction is HBM. #define ECC_MODE_HBM 3 +/// @} +/// \defgroup define_board_layout_flags +/// These defines are the board layout flags state which indicates what are the valid properties of \ref ADLBoardLayoutInfo . It is used by \ref ADL_Adapter_BoardLayout_Get +/// @{ +/// Indicates the number of slots is valid. #define ADL_BLAYOUT_VALID_NUMBER_OF_SLOTS 0x1 +/// Indicates the slot sizes are valid. Size of the slot consists of the length and width. #define ADL_BLAYOUT_VALID_SLOT_SIZES 0x2 +/// Indicates the connector offsets are valid. #define ADL_BLAYOUT_VALID_CONNECTOR_OFFSETS 0x4 +/// Indicates the connector lengths is valid. #define ADL_BLAYOUT_VALID_CONNECTOR_LENGTHS 0x8 +/// @} +/// \defgroup define_max_constants +/// These defines are the maximum value constants. +/// @{ +/// Indicates the Maximum supported slots on board. #define ADL_ADAPTER_MAX_SLOTS 4 +/// Indicates the Maximum supported connectors on slot. #define ADL_ADAPTER_MAX_CONNECTORS 10 +/// Indicates the Maximum supported properties of connection #define ADL_MAX_CONNECTION_TYPES 32 +/// Indicates the Maximum relative address link count. #define ADL_MAX_RELATIVE_ADDRESS_LINK_COUNT 15 +/// Indicates the Maximum size of EDID data block size #define ADL_MAX_DISPLAY_EDID_DATA_SIZE 1024 +/// Indicates the Maximum count of Error Records. #define ADL_MAX_ERROR_RECORDS_COUNT 256 +/// Indicates the maximum number of power states supported #define ADL_MAX_POWER_POLICY 6 +/// @} +/// \defgroup define_connection_types +/// These defines are the connection types constants which indicates what are the valid connection type of given connector. It is used by \ref ADL_Adapter_SupportedConnections_Get +/// @{ +/// Indicates the VGA connection type is valid. #define ADL_CONNECTION_TYPE_VGA 0 +/// Indicates the DVI_I connection type is valid. #define ADL_CONNECTION_TYPE_DVI 1 +/// Indicates the DVI_SL connection type is valid. #define ADL_CONNECTION_TYPE_DVI_SL 2 +/// Indicates the HDMI connection type is valid. #define ADL_CONNECTION_TYPE_HDMI 3 +/// Indicates the DISPLAY PORT connection type is valid. #define ADL_CONNECTION_TYPE_DISPLAY_PORT 4 +/// Indicates the Active dongle DP->DVI(single link) connection type is valid. #define ADL_CONNECTION_TYPE_ACTIVE_DONGLE_DP_DVI_SL 5 +/// Indicates the Active dongle DP->DVI(double link) connection type is valid. #define ADL_CONNECTION_TYPE_ACTIVE_DONGLE_DP_DVI_DL 6 +/// Indicates the Active dongle DP->HDMI connection type is valid. #define ADL_CONNECTION_TYPE_ACTIVE_DONGLE_DP_HDMI 7 +/// Indicates the Active dongle DP->VGA connection type is valid. #define ADL_CONNECTION_TYPE_ACTIVE_DONGLE_DP_VGA 8 +/// Indicates the Passive dongle DP->HDMI connection type is valid. #define ADL_CONNECTION_TYPE_PASSIVE_DONGLE_DP_HDMI 9 +/// Indicates the Active dongle DP->VGA connection type is valid. #define ADL_CONNECTION_TYPE_PASSIVE_DONGLE_DP_DVI 10 +/// Indicates the MST type is valid. #define ADL_CONNECTION_TYPE_MST 11 +/// Indicates the active dongle, all types. #define ADL_CONNECTION_TYPE_ACTIVE_DONGLE 12 +/// Indicates the Virtual Connection Type. #define ADL_CONNECTION_TYPE_VIRTUAL 13 +/// Macros for generating bitmask from index. #define ADL_CONNECTION_BITMAST_FROM_INDEX(index) (1 << index) +/// @} +/// \defgroup define_connection_properties +/// These defines are the connection properties which indicates what are the valid properties of given connection type. It is used by \ref ADL_Adapter_SupportedConnections_Get +/// @{ +/// Indicates the property Bitrate is valid. #define ADL_CONNECTION_PROPERTY_BITRATE 0x1 +/// Indicates the property number of lanes is valid. #define ADL_CONNECTION_PROPERTY_NUMBER_OF_LANES 0x2 +/// Indicates the property 3D caps is valid. #define ADL_CONNECTION_PROPERTY_3DCAPS 0x4 +/// Indicates the property output bandwidth is valid. #define ADL_CONNECTION_PROPERTY_OUTPUT_BANDWIDTH 0x8 +/// Indicates the property colordepth is valid. #define ADL_CONNECTION_PROPERTY_COLORDEPTH 0x10 +/// @} +/// \defgroup define_lanecount_constants +/// These defines are the Lane count constants which will be used in DP & etc. +/// @{ +/// Indicates if lane count is unknown #define ADL_LANECOUNT_UNKNOWN 0 +/// Indicates if lane count is 1 #define ADL_LANECOUNT_ONE 1 +/// Indicates if lane count is 2 #define ADL_LANECOUNT_TWO 2 +/// Indicates if lane count is 4 #define ADL_LANECOUNT_FOUR 4 +/// Indicates if lane count is 8 #define ADL_LANECOUNT_EIGHT 8 +/// Indicates default value of lane count #define ADL_LANECOUNT_DEF ADL_LANECOUNT_FOUR +/// @} +/// \defgroup define_linkrate_constants +/// These defines are the link rate constants which will be used in DP & etc. +/// @{ +/// Indicates if link rate is unknown #define ADL_LINK_BITRATE_UNKNOWN 0 +/// Indicates if link rate is 1.62Ghz #define ADL_LINK_BITRATE_1_62_GHZ 0x06 +/// Indicates if link rate is 2.7Ghz #define ADL_LINK_BITRATE_2_7_GHZ 0x0A +/// Indicates if link rate is 5.4Ghz #define ADL_LINK_BITRATE_5_4_GHZ 0x14 +/// Indicates if link rate is 8.1Ghz #define ADL_LINK_BITRATE_8_1_GHZ 0x1E +/// Indicates default value of link rate #define ADL_LINK_BITRATE_DEF ADL_LINK_BITRATE_2_7_GHZ +/// @} +/// \defgroup define_colordepth_constants +/// These defines are the color depth constants which will be used in DP & etc. +/// @{ #define ADL_CONNPROP_S3D_ALTERNATE_TO_FRAME_PACK 0x00000001 +/// @} +/// \defgroup define_colordepth_constants +/// These defines are the color depth constants which will be used in DP & etc. +/// @{ +/// Indicates if color depth is unknown #define ADL_COLORDEPTH_UNKNOWN 0 +/// Indicates if color depth is 666 #define ADL_COLORDEPTH_666 1 +/// Indicates if color depth is 888 #define ADL_COLORDEPTH_888 2 +/// Indicates if color depth is 101010 #define ADL_COLORDEPTH_101010 3 +/// Indicates if color depth is 121212 #define ADL_COLORDEPTH_121212 4 +/// Indicates if color depth is 141414 #define ADL_COLORDEPTH_141414 5 +/// Indicates if color depth is 161616 #define ADL_COLORDEPTH_161616 6 +/// Indicates default value of color depth #define ADL_COLOR_DEPTH_DEF ADL_COLORDEPTH_888 +/// @} +/// \defgroup define_emulation_status +/// These defines are the status of emulation +/// @{ +/// Indicates if real device is connected. #define ADL_EMUL_STATUS_REAL_DEVICE_CONNECTED 0x1 +/// Indicates if emulated device is presented. #define ADL_EMUL_STATUS_EMULATED_DEVICE_PRESENT 0x2 +/// Indicates if emulated device is used. #define ADL_EMUL_STATUS_EMULATED_DEVICE_USED 0x4 +/// In case when last active real/emulated device used (when persistence is enabled but no emulation enforced then persistence will use last connected/emulated device). #define ADL_EMUL_STATUS_LAST_ACTIVE_DEVICE_USED 0x8 +/// @} +/// \defgroup define_emulation_mode +/// These defines are the modes of emulation +/// @{ +/// Indicates if no emulation is used #define ADL_EMUL_MODE_OFF 0 +/// Indicates if emulation is used when display connected #define ADL_EMUL_MODE_ON_CONNECTED 1 +/// Indicates if emulation is used when display dis connected #define ADL_EMUL_MODE_ON_DISCONNECTED 2 +/// Indicates if emulation is used always #define ADL_EMUL_MODE_ALWAYS 3 +/// @} +/// \defgroup define_emulation_query +/// These defines are the modes of emulation +/// @{ +/// Indicates Data from real device #define ADL_QUERY_REAL_DATA 0 +/// Indicates Emulated data #define ADL_QUERY_EMULATED_DATA 1 +/// Indicates Data currently in use #define ADL_QUERY_CURRENT_DATA 2 +/// @} +/// \defgroup define_persistence_state +/// These defines are the states of persistence +/// @{ +/// Indicates persistence is disabled #define ADL_EDID_PERSISTANCE_DISABLED 0 +/// Indicates persistence is enabled #define ADL_EDID_PERSISTANCE_ENABLED 1 +/// @} +/// \defgroup define_connector_types Connector Type +/// defines for ADLConnectorInfo.iType +/// @{ +/// Indicates unknown Connector type #define ADL_CONNECTOR_TYPE_UNKNOWN 0 +/// Indicates VGA Connector type #define ADL_CONNECTOR_TYPE_VGA 1 +/// Indicates DVI-D Connector type #define ADL_CONNECTOR_TYPE_DVI_D 2 +/// Indicates DVI-I Connector type #define ADL_CONNECTOR_TYPE_DVI_I 3 +/// Indicates Active Dongle-NA Connector type #define ADL_CONNECTOR_TYPE_ATICVDONGLE_NA 4 +/// Indicates Active Dongle-JP Connector type #define ADL_CONNECTOR_TYPE_ATICVDONGLE_JP 5 +/// Indicates Active Dongle-NONI2C Connector type #define ADL_CONNECTOR_TYPE_ATICVDONGLE_NONI2C 6 +/// Indicates Active Dongle-NONI2C-D Connector type #define ADL_CONNECTOR_TYPE_ATICVDONGLE_NONI2C_D 7 +/// Indicates HDMI-Type A Connector type #define ADL_CONNECTOR_TYPE_HDMI_TYPE_A 8 +/// Indicates HDMI-Type B Connector type #define ADL_CONNECTOR_TYPE_HDMI_TYPE_B 9 +/// Indicates Display port Connector type #define ADL_CONNECTOR_TYPE_DISPLAYPORT 10 +/// Indicates EDP Connector type #define ADL_CONNECTOR_TYPE_EDP 11 +/// Indicates MiniDP Connector type #define ADL_CONNECTOR_TYPE_MINI_DISPLAYPORT 12 +/// Indicates Virtual Connector type #define ADL_CONNECTOR_TYPE_VIRTUAL 13 +/// Indicates USB type C Connector type #define ADL_CONNECTOR_TYPE_USB_TYPE_C 14 +/// @} +/// \defgroup define_freesync_usecase +/// These defines are to specify use cases in which FreeSync should be enabled +/// They are a bit mask. To specify FreeSync for more than one use case, the input value +/// should be set to include multiple bits set +/// @{ +/// Indicates FreeSync is enabled for Static Screen case #define ADL_FREESYNC_USECASE_STATIC 0x1 +/// Indicates FreeSync is enabled for Video use case #define ADL_FREESYNC_USECASE_VIDEO 0x2 +/// Indicates FreeSync is enabled for Gaming use case #define ADL_FREESYNC_USECASE_GAMING 0x4 +/// @} +/// \defgroup define_freesync_caps +/// These defines are used to retrieve FreeSync display capabilities. +/// GPU support flag also indicates whether the display is +/// connected to a GPU that actually supports FreeSync +/// @{ #define ADL_FREESYNC_CAP_SUPPORTED (1 << 0) #define ADL_FREESYNC_CAP_GPUSUPPORTED (1 << 1) #define ADL_FREESYNC_CAP_DISPLAYSUPPORTED (1 << 2) @@ -1542,98 +2356,121 @@ typedef enum ADL_PMLOG_SENSORS #define ADL_FREESYNC_CAP_NOCFXORCFXSUPPORTED (1 << 4) #define ADL_FREESYNC_CAP_NOGENLOCKORGENLOCKSUPPORTED (1 << 5) #define ADL_FREESYNC_CAP_BORDERLESSWINDOWSUPPORTED (1 << 6) +/// @} +/// \defgroup define_freesync_labelIndex +/// These defines are used to retrieve which FreeSync label to use +/// @{ #define ADL_FREESYNC_LABEL_UNSUPPORTED 0 #define ADL_FREESYNC_LABEL_FREESYNC 1 #define ADL_FREESYNC_LABEL_ADAPTIVE_SYNC 2 #define ADL_FREESYNC_LABEL_VRR 3 #define ADL_FREESYNC_LABEL_FREESYNC_PREMIUM 4 #define ADL_FREESYNC_LABEL_FREESYNC_PREMIUM_PRO 5 +/// @} -#define ADL_FREESYNC_POWEROPTIMIZATION_SUPPORTED_MASK (1 << 0) -#define ADL_FREESYNC_POWEROPTIMIZATION_ENABLED_MASK (1 << 1) -#define ADL_FREESYNC_POWEROPTIMIZATION_DEFAULT_VALUE_MASK (1 << 2) +/// Freesync Power optimization masks +/// @{ +#define ADL_FREESYNC_POWEROPTIMIZATION_SUPPORTED_MASK (1 << 0) +#define ADL_FREESYNC_POWEROPTIMIZATION_ENABLED_MASK (1 << 1) +#define ADL_FREESYNC_POWEROPTIMIZATION_DEFAULT_VALUE_MASK (1 << 2) +/// @} +/// \defgroup define_MST_CommandLine_execute +/// @{ +/// Indicates the MST command line for branch message if the bit is set. Otherwise, it is display message #define ADL_MST_COMMANDLINE_PATH_MSG 0x1 +/// Indicates the MST command line to send message in broadcast way it the bit is set #define ADL_MST_COMMANDLINE_BROADCAST 0x2 +/// @} +/// \defgroup define_Adapter_CloneTypes_Get +/// @{ +/// Indicates there is crossGPU clone with non-AMD dispalys #define ADL_CROSSGPUDISPLAYCLONE_AMD_WITH_NONAMD 0x1 +/// Indicates there is crossGPU clone #define ADL_CROSSGPUDISPLAYCLONE 0x2 +/// @} +/// \defgroup define_D3DKMT_HANDLE +/// @{ +/// Handle can be used to create Device Handle when using CreateDevice() typedef unsigned int ADL_D3DKMT_HANDLE; +/// @} // End Bracket for Constants and Definitions. Add new groups ABOVE this line! +/// @} typedef enum ADL_RAS_ERROR_INJECTION_MODE { - ADL_RAS_ERROR_INJECTION_MODE_SINGLE = 1, - ADL_RAS_ERROR_INJECTION_MODE_MULTIPLE = 2 + ADL_RAS_ERROR_INJECTION_MODE_SINGLE = 1, + ADL_RAS_ERROR_INJECTION_MODE_MULTIPLE = 2 }ADL_RAS_ERROR_INJECTION_MODE; typedef enum ADL_RAS_BLOCK_ID { - ADL_RAS_BLOCK_ID_UMC = 0, - ADL_RAS_BLOCK_ID_SDMA, - ADL_RAS_BLOCK_ID_GFX_HUB, - ADL_RAS_BLOCK_ID_MMHUB, - ADL_RAS_BLOCK_ID_ATHUB, - ADL_RAS_BLOCK_ID_PCIE_BIF, - ADL_RAS_BLOCK_ID_HDP, - ADL_RAS_BLOCK_ID_XGMI_WAFL, - ADL_RAS_BLOCK_ID_DF, - ADL_RAS_BLOCK_ID_SMN, - ADL_RAS_BLOCK_ID_SEM, - ADL_RAS_BLOCK_ID_MP0, - ADL_RAS_BLOCK_ID_MP1, - ADL_RAS_BLOCK_ID_FUSE + ADL_RAS_BLOCK_ID_UMC = 0, + ADL_RAS_BLOCK_ID_SDMA, + ADL_RAS_BLOCK_ID_GFX_HUB, + ADL_RAS_BLOCK_ID_MMHUB, + ADL_RAS_BLOCK_ID_ATHUB, + ADL_RAS_BLOCK_ID_PCIE_BIF, + ADL_RAS_BLOCK_ID_HDP, + ADL_RAS_BLOCK_ID_XGMI_WAFL, + ADL_RAS_BLOCK_ID_DF, + ADL_RAS_BLOCK_ID_SMN, + ADL_RAS_BLOCK_ID_SEM, + ADL_RAS_BLOCK_ID_MP0, + ADL_RAS_BLOCK_ID_MP1, + ADL_RAS_BLOCK_ID_FUSE }ADL_RAS_BLOCK_ID; typedef enum ADL_MEM_SUB_BLOCK_ID { - ADL_RAS__UMC_HBM = 0, - ADL_RAS__UMC_SRAM = 1 + ADL_RAS__UMC_HBM = 0, + ADL_RAS__UMC_SRAM = 1 }ADL_MEM_SUB_BLOCK_ID; typedef enum _ADL_RAS_ERROR_TYPE { - ADL_RAS_ERROR__NONE = 0, - ADL_RAS_ERROR__PARITY = 1, - ADL_RAS_ERROR__SINGLE_CORRECTABLE = 2, - ADL_RAS_ERROR__PARITY_SINGLE_CORRECTABLE = 3, - ADL_RAS_ERROR__MULTI_UNCORRECTABLE = 4, - ADL_RAS_ERROR__PARITY_MULTI_UNCORRECTABLE = 5, - ADL_RAS_ERROR__SINGLE_CORRECTABLE_MULTI_UNCORRECTABLE = 6, - ADL_RAS_ERROR__PARITY_SINGLE_CORRECTABLE_MULTI_UNCORRECTABLE = 7, - ADL_RAS_ERROR__POISON = 8, - ADL_RAS_ERROR__PARITY_POISON = 9, - ADL_RAS_ERROR__SINGLE_CORRECTABLE_POISON = 10, - ADL_RAS_ERROR__PARITY_SINGLE_CORRECTABLE_POISON = 11, - ADL_RAS_ERROR__MULTI_UNCORRECTABLE_POISON = 12, - ADL_RAS_ERROR__PARITY_MULTI_UNCORRECTABLE_POISON = 13, - ADL_RAS_ERROR__SINGLE_CORRECTABLE_MULTI_UNCORRECTABLE_POISON = 14, - ADL_RAS_ERROR__PARITY_SINGLE_CORRECTABLE_MULTI_UNCORRECTABLE_POISON = 15 + ADL_RAS_ERROR__NONE = 0, + ADL_RAS_ERROR__PARITY = 1, + ADL_RAS_ERROR__SINGLE_CORRECTABLE = 2, + ADL_RAS_ERROR__PARITY_SINGLE_CORRECTABLE = 3, + ADL_RAS_ERROR__MULTI_UNCORRECTABLE = 4, + ADL_RAS_ERROR__PARITY_MULTI_UNCORRECTABLE = 5, + ADL_RAS_ERROR__SINGLE_CORRECTABLE_MULTI_UNCORRECTABLE = 6, + ADL_RAS_ERROR__PARITY_SINGLE_CORRECTABLE_MULTI_UNCORRECTABLE = 7, + ADL_RAS_ERROR__POISON = 8, + ADL_RAS_ERROR__PARITY_POISON = 9, + ADL_RAS_ERROR__SINGLE_CORRECTABLE_POISON = 10, + ADL_RAS_ERROR__PARITY_SINGLE_CORRECTABLE_POISON = 11, + ADL_RAS_ERROR__MULTI_UNCORRECTABLE_POISON = 12, + ADL_RAS_ERROR__PARITY_MULTI_UNCORRECTABLE_POISON = 13, + ADL_RAS_ERROR__SINGLE_CORRECTABLE_MULTI_UNCORRECTABLE_POISON = 14, + ADL_RAS_ERROR__PARITY_SINGLE_CORRECTABLE_MULTI_UNCORRECTABLE_POISON = 15 }ADL_RAS_ERROR_TYPE; typedef enum ADL_RAS_INJECTION_METHOD { - ADL_RAS_ERROR__UMC_METH_COHERENT = 0, - ADL_RAS_ERROR__UMC_METH_SINGLE_SHOT = 1, - ADL_RAS_ERROR__UMC_METH_PERSISTENT = 2, - ADL_RAS_ERROR__UMC_METH_PERSISTENT_DISABLE = 3 + ADL_RAS_ERROR__UMC_METH_COHERENT = 0, + ADL_RAS_ERROR__UMC_METH_SINGLE_SHOT = 1, + ADL_RAS_ERROR__UMC_METH_PERSISTENT = 2, + ADL_RAS_ERROR__UMC_METH_PERSISTENT_DISABLE = 3 }ADL_RAS_INJECTION_METHOD; // Driver event types typedef enum ADL_DRIVER_EVENT_TYPE { - ADL_EVENT_ID_AUTO_FEATURE_COMPLETED = 30, - ADL_EVENT_ID_FEATURE_AVAILABILITY = 31, + ADL_EVENT_ID_AUTO_FEATURE_COMPLETED = 30, + ADL_EVENT_ID_FEATURE_AVAILABILITY = 31, } ADL_DRIVER_EVENT_TYPE; @@ -1641,19 +2478,19 @@ typedef enum ADL_DRIVER_EVENT_TYPE //UIFeature Ids typedef enum ADL_UIFEATURES_GROUP { - ADL_UIFEATURES_GROUP_DVR = 0, - ADL_UIFEATURES_GROUP_TURBOSYNC = 1, - ADL_UIFEATURES_GROUP_FRAMEMETRICSMONITOR = 2, - ADL_UIFEATURES_GROUP_FRTC = 3, - ADL_UIFEATURES_GROUP_XVISION = 4, - ADL_UIFEATURES_GROUP_BLOCKCHAIN = 5, - ADL_UIFEATURES_GROUP_GAMEINTELLIGENCE = 6, - ADL_UIFEATURES_GROUP_CHILL = 7, - ADL_UIFEATURES_GROUP_DELAG = 8, - ADL_UIFEATURES_GROUP_BOOST = 9, - ADL_UIFEATURES_GROUP_USU = 10, - ADL_UIFEATURES_GROUP_XGMI = 11, - ADL_UIFEATURES_GROUP_PROVSR = 12, + ADL_UIFEATURES_GROUP_DVR = 0, + ADL_UIFEATURES_GROUP_TURBOSYNC = 1, + ADL_UIFEATURES_GROUP_FRAMEMETRICSMONITOR = 2, + ADL_UIFEATURES_GROUP_FRTC = 3, + ADL_UIFEATURES_GROUP_XVISION = 4, + ADL_UIFEATURES_GROUP_BLOCKCHAIN = 5, + ADL_UIFEATURES_GROUP_GAMEINTELLIGENCE = 6, + ADL_UIFEATURES_GROUP_CHILL = 7, + ADL_UIFEATURES_GROUP_DELAG = 8, + ADL_UIFEATURES_GROUP_BOOST = 9, + ADL_UIFEATURES_GROUP_USU = 10, + ADL_UIFEATURES_GROUP_XGMI = 11, + ADL_UIFEATURES_GROUP_PROVSR = 12, ADL_UIFEATURES_GROUP_SMA = 13, ADL_UIFEATURES_GROUP_CAMERA = 14, ADL_UIFEATURES_GROUP_FRTCPRO = 15 @@ -1661,45 +2498,83 @@ typedef enum ADL_UIFEATURES_GROUP -#define ADL_RADEON_LED_MAX_BRIGHTNESS 2 +/// Maximum brightness supported by Radeon LED interface +#define ADL_RADEON_LED_MAX_BRIGHTNESS 2 -#define ADL_RADEON_LED_MAX_SPEED 4 +/// Maximum speed supported by Radeon LED interface +#define ADL_RADEON_LED_MAX_SPEED 4 -#define ADL_RADEON_LED_MAX_RGB 255 +/// Maximum RGB supported by Radeon LED interface +#define ADL_RADEON_LED_MAX_RGB 255 +/// Maximum MORSE code supported string #define ADL_RADEON_LED_MAX_MORSE_CODE 260 +/// Maximum LED ROW ON GRID #define ADL_RADEON_LED_MAX_LED_ROW_ON_GRID 7 +/// Maximum LED COLUMN ON GRID #define ADL_RADEON_LED_MAX_LED_COLUMN_ON_GRID 24 +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief +/// +/// +/// +/// +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef enum ADL_RADEON_USB_LED_BAR_CONTROLS { - RadeonLEDBarControl_OFF = 0, - RadeonLEDBarControl_Static, - RadeonLEDBarControl_Rainbow, - RadeonLEDBarControl_Swirl, - RadeonLEDBarControl_Chase, - RadeonLEDBarControl_Bounce, - RadeonLEDBarControl_MorseCode, - RadeonLEDBarControl_ColorCycle, - RadeonLEDBarControl_Breathing, - RadeonLEDBarControl_CustomPattern, - RadeonLEDBarControl_MAX + RadeonLEDBarControl_OFF = 0, + RadeonLEDBarControl_Static, + RadeonLEDBarControl_Rainbow, + RadeonLEDBarControl_Swirl, + RadeonLEDBarControl_Chase, + RadeonLEDBarControl_Bounce, + RadeonLEDBarControl_MorseCode, + RadeonLEDBarControl_ColorCycle, + RadeonLEDBarControl_Breathing, + RadeonLEDBarControl_CustomPattern, + RadeonLEDBarControl_MAX }ADL_RADEON_USB_LED_BAR_CONTROLS; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief +/// +/// +/// +/// +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef unsigned int RadeonLEDBARSupportedControl; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief +/// +/// +/// +/// +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef enum ADL_RADEON_USB_LED_CONTROL_CONFIGS { - RadeonLEDPattern_Speed = 0, - RadeonLEDPattern_Brightness, - RadeonLEDPattern_Direction, - RadeonLEDPattern_Color, - RadeonLEDPattern_MAX + RadeonLEDPattern_Speed = 0, + RadeonLEDPattern_Brightness, + RadeonLEDPattern_Direction, + RadeonLEDPattern_Color, + RadeonLEDPattern_MAX }ADL_RADEON_USB_LED_CONTROL_CONFIGS; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief +/// +/// +/// +/// +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef unsigned int RadeonLEDBARSupportedConfig; //User blob feature settings @@ -1708,12 +2583,12 @@ typedef enum ADL_USER_SETTINGS ADL_USER_SETTINGS_ENHANCEDSYNC = 1 << 0, //notify Enhanced Sync settings change ADL_USER_SETTINGS_CHILL_PROFILE = 1 << 1, //notify Chill settings change ADL_USER_SETTINGS_DELAG_PROFILE = 1 << 2, //notify Delag settings change - ADL_USER_SETTINGS_BOOST_PROFILE = 1 << 3, //notify Boost settings change - ADL_USER_SETTINGS_USU_PROFILE = 1 << 4, //notify USU settings change - ADL_USER_SETTINGS_CVDC_PROFILE = 1 << 5, //notify Color Vision Deficiency Corretion settings change + ADL_USER_SETTINGS_BOOST_PROFILE = 1 << 3, //notify Boost settings change + ADL_USER_SETTINGS_USU_PROFILE = 1 << 4, //notify USU settings change + ADL_USER_SETTINGS_CVDC_PROFILE = 1 << 5, //notify Color Vision Deficiency Corretion settings change ADL_USER_SETTINGS_SCE_PROFILE = 1 << 6, ADL_USER_SETTINGS_PROVSR = 1 << 7 -} ADL_USER_SETTINGS; + } ADL_USER_SETTINGS; #define ADL_REG_DEVICE_FUNCTION_1 0x00000001 #endif /* ADL_DEFINES_H_ */ diff --git a/dependencies/display-library/include/adl_sdk.h b/dependencies/display-library/include/adl_sdk.h index 220f452b..2079b7ca 100644 --- a/dependencies/display-library/include/adl_sdk.h +++ b/dependencies/display-library/include/adl_sdk.h @@ -20,6 +20,13 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +/// \file adl_sdk.h +/// \brief Contains the definition of the Memory Allocation Callback.\n Included in ADL SDK +/// +/// \n\n +/// This file contains the definition of the Memory Allocation Callback.\n +/// It also includes definitions of the respective structures and constants.\n +/// This is the only header file to be included in a C/C++ project using ADL #ifndef ADL_SDK_H_ #define ADL_SDK_H_ @@ -30,9 +37,10 @@ #define __stdcall #endif /* (LINUX) */ +/// Memory Allocation Call back typedef void* ( __stdcall *ADL_MAIN_MALLOC_CALLBACK )( int ); #define ADL_SDK_MAJOR_VERSION 17 -#define ADL_SDK_MINOR_VERSION 0 +#define ADL_SDK_MINOR_VERSION 1 #endif /* ADL_SDK_H_ */ diff --git a/dependencies/display-library/include/adl_structures.h b/dependencies/display-library/include/adl_structures.h index 9fa0d703..bab4032d 100644 --- a/dependencies/display-library/include/adl_structures.h +++ b/dependencies/display-library/include/adl_structures.h @@ -20,103 +20,206 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. +/// \file adl_structures.h +///\brief This file contains the structure declarations that are used by the public ADL interfaces for \ALL platforms.\n Included in ADL SDK +/// +/// All data structures used in AMD Display Library (ADL) public interfaces should be defined in this header file. +/// #ifndef ADL_STRUCTURES_H_ #define ADL_STRUCTURES_H_ #include "adl_defines.h" #include +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the graphics adapter. +/// +/// This structure is used to store various information about the graphics adapter. This +/// information can be returned to the user. Alternatively, it can be used to access various driver calls to set +/// or fetch various settings upon the user's request. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct AdapterInfo { +/// \ALL_STRUCT_MEM +/// Size of the structure. int iSize; +/// The ADL index handle. One GPU may be associated with one or two index handles int iAdapterIndex; +/// The unique device ID associated with this adapter. char strUDID[ADL_MAX_PATH]; +/// The BUS number associated with this adapter. int iBusNumber; +/// The driver number associated with this adapter. int iDeviceNumber; +/// The function number. int iFunctionNumber; +/// The vendor ID associated with this adapter. int iVendorID; +/// Adapter name. char strAdapterName[ADL_MAX_PATH]; +/// Display name. For example, "\\\\Display0" for Windows or ":0:0" for Linux. char strDisplayName[ADL_MAX_PATH]; +/// Present or not; 1 if present and 0 if not present.It the logical adapter is present, the display name such as \\\\.\\Display1 can be found from OS int iPresent; #if defined (_WIN32) || defined (_WIN64) +/// \WIN_STRUCT_MEM +/// Exist or not; 1 is exist and 0 is not present. int iExist; +/// Driver registry path. char strDriverPath[ADL_MAX_PATH]; +/// Driver registry path Ext for. char strDriverPathExt[ADL_MAX_PATH]; +/// PNP string from Windows. char strPNPString[ADL_MAX_PATH]; +/// It is generated from EnumDisplayDevices. int iOSDisplayIndex; #endif /* (_WIN32) || (_WIN64) */ #if defined (LINUX) +/// \LNX_STRUCT_MEM +/// Internal X screen number from GPUMapInfo (DEPRICATED use XScreenInfo) int iXScreenNum; +/// Internal driver index from GPUMapInfo int iDrvIndex; +/// \deprecated Internal x config file screen identifier name. Use XScreenInfo instead. char strXScreenConfigName[ADL_MAX_PATH]; #endif /* (LINUX) */ } AdapterInfo, *LPAdapterInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the Linux X screen information. +/// +/// This structure is used to store the current screen number and xorg.conf ID name assoicated with an adapter index. +/// This structure is updated during ADL_Main_Control_Refresh or ADL_ScreenInfo_Update. +/// Note: This structure should be used in place of iXScreenNum and strXScreenConfigName in AdapterInfo as they will be +/// deprecated. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// #if defined (LINUX) typedef struct XScreenInfo { +/// Internal X screen number from GPUMapInfo. int iXScreenNum; +/// Internal x config file screen identifier name. char strXScreenConfigName[ADL_MAX_PATH]; } XScreenInfo, *LPXScreenInfo; #endif /* (LINUX) */ +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about an controller mode +/// +/// This structure is used to store information of an controller mode +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLAdapterCaps { - int iAdapterID; - int iNumControllers; - int iNumDisplays; - int iNumOverlays; - int iNumOfGLSyncConnectors; - int iCapsMask; - int iCapsValue; + /// AdapterID for this adapter + int iAdapterID; + /// Number of controllers for this adapter + int iNumControllers; + /// Number of displays for this adapter + int iNumDisplays; + /// Number of overlays for this adapter + int iNumOverlays; + /// Number of GLSyncConnectors + int iNumOfGLSyncConnectors; + /// The bit mask identifies the adapter caps + int iCapsMask; + /// The bit identifies the adapter caps \ref define_adapter_caps + int iCapsValue; }ADLAdapterCaps; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing additional information about the ASIC memory +/// +/// This structure is used to store additional information about the ASIC memory. This +/// information can be returned to the user. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLMemoryInfo2 { - long long iMemorySize; - char strMemoryType[ADL_MAX_PATH]; - long long iMemoryBandwidth; - long long iHyperMemorySize; + /// Memory size in bytes. + long long iMemorySize; + /// Memory type in string. + char strMemoryType[ADL_MAX_PATH]; + /// Highest default performance level Memory bandwidth in Mbytes/s + long long iMemoryBandwidth; + /// HyperMemory size in bytes. + long long iHyperMemorySize; - long long iInvisibleMemorySize; - long long iVisibleMemorySize; + /// Invisible Memory size in bytes. + long long iInvisibleMemorySize; + /// Visible Memory size in bytes. + long long iVisibleMemorySize; } ADLMemoryInfo2, *LPADLMemoryInfo2; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing additional information about the ASIC memory +/// +/// This structure is used to store additional information about the ASIC memory. This +/// information can be returned to the user. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLMemoryInfo3 { + /// Memory size in bytes. long long iMemorySize; + /// Memory type in string. char strMemoryType[ADL_MAX_PATH]; + /// Highest default performance level Memory bandwidth in Mbytes/s long long iMemoryBandwidth; + /// HyperMemory size in bytes. long long iHyperMemorySize; + /// Invisible Memory size in bytes. long long iInvisibleMemorySize; + /// Visible Memory size in bytes. long long iVisibleMemorySize; + /// Vram vendor ID long long iVramVendorRevId; } ADLMemoryInfo3, *LPADLMemoryInfo3; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing additional information about the ASIC memory +/// +/// This structure is used to store additional information about the ASIC memory. This +/// information can be returned to the user. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLMemoryInfoX4 { + /// Memory size in bytes. long long iMemorySize; + /// Memory type in string. char strMemoryType[ADL_MAX_PATH]; + /// Highest default performance level Memory bandwidth in Mbytes/s long long iMemoryBandwidth; + /// HyperMemory size in bytes. long long iHyperMemorySize; + /// Invisible Memory size in bytes. long long iInvisibleMemorySize; + /// Visible Memory size in bytes. long long iVisibleMemorySize; + /// Vram vendor ID long long iVramVendorRevId; + /// Memory Bandiwidth that is calculated and finalized on the driver side, grab and go. long long iMemoryBandwidthX2; + /// Memory Bit Rate that is calculated and finalized on the driver side, grab and go. long long iMemoryBitRateX2; } ADLMemoryInfoX4, *LPADLMemoryInfoX4; +/////////////////////////////////////////////////////////////////////////// // ADLvRamVendor Enumeration +/////////////////////////////////////////////////////////////////////////// enum ADLvRamVendors { ADLvRamVendor_Unsupported = 0x0, @@ -133,113 +236,216 @@ enum ADLvRamVendors ADLvRamVendor_Undefined }; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about components of ASIC GCN architecture +/// +/// Elements of GCN info are compute units, number of Tex (Texture filtering units) , number of ROPs (render back-ends). +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLGcnInfo { - int CuCount; //Number of compute units on the ASIC. - int TexCount; //Number of texture mapping units. - int RopCount; //Number of Render backend Units. - int ASICFamilyId; //Such SI, VI. See /inc/asic_reg/atiid.h for family ids - int ASICRevisionId; //Such as Ellesmere, Fiji. For example - VI family revision ids are stored in /inc/asic_reg/vi_id.h + int CuCount; //Number of compute units on the ASIC. + int TexCount; //Number of texture mapping units. + int RopCount; //Number of Render backend Units. + int ASICFamilyId; //Such SI, VI. See /inc/asic_reg/atiid.h for family ids + int ASICRevisionId; //Such as Ellesmere, Fiji. For example - VI family revision ids are stored in /inc/asic_reg/vi_id.h }ADLGcnInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information related virtual segment config information. +/// +/// This structure is used to store information related virtual segment config +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLVirtualSegmentSettingsOutput { - int virtualSegmentSupported; // 1 - subsequent values are valid - int virtualSegmentDefault; //virtual segment default, 1: enable, 0: disable - int virtualSegmentCurrent; //virtual segment current, 1: enable, 0: disable - int iMinSizeInMB; //minimum value - int iMaxSizeInMB; //maximum value - int icurrentSizeInMB; //last configured otherwise same as factory default - int idefaultSizeInMB; //factory default - int iMask; //fileds for extension in the future - int iValue; //fileds for extension in the future + int virtualSegmentSupported; // 1 - subsequent values are valid + int virtualSegmentDefault; //virtual segment default, 1: enable, 0: disable + int virtualSegmentCurrent; //virtual segment current, 1: enable, 0: disable + int iMinSizeInMB; //minimum value + int iMaxSizeInMB; //maximum value + int icurrentSizeInMB; //last configured otherwise same as factory default + int idefaultSizeInMB; //factory default + int iMask; //fileds for extension in the future + int iValue; //fileds for extension in the future } ADLVirtualSegmentSettingsOutput; +///////////////////////////////////////////////////////////////////////////////////////////// +/// \brief Structure containing information about the Chipset. +/// +/// This structure is used to store various information about the Chipset. This +/// information can be returned to the user. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLChipSetInfo { - int iBusType; - int iBusSpeedType; - int iMaxPCIELaneWidth; - int iCurrentPCIELaneWidth; - int iSupportedAGPSpeeds; - int iCurrentAGPSpeed; + int iBusType; ///< Bus type. + int iBusSpeedType; ///Maximum Bus Speed of the current platform + int iMaxPCIELaneWidth; ///< Number of PCIE lanes. + int iCurrentPCIELaneWidth; ///< Current PCIE Lane Width + int iSupportedAGPSpeeds; ///< Bit mask or AGP transfer speed. + int iCurrentAGPSpeed; ///< Current AGP speed } ADLChipSetInfo, *LPADLChipSetInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the ASIC memory. +/// +/// This structure is used to store various information about the ASIC memory. This +/// information can be returned to the user. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLMemoryInfo { +/// Memory size in bytes. long long iMemorySize; +/// Memory type in string. char strMemoryType[ADL_MAX_PATH]; +/// Memory bandwidth in Mbytes/s. long long iMemoryBandwidth; } ADLMemoryInfo, *LPADLMemoryInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about memory required by type +/// +/// This structure is returned by ADL_Adapter_ConfigMemory_Get, which given a desktop and display configuration +/// will return the Memory used. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLMemoryRequired { - long long iMemoryReq; - int iType; - int iDisplayFeatureValue; + long long iMemoryReq; /// Memory in bytes required + int iType; /// Type of Memory \ref define_adl_validmemoryrequiredfields + int iDisplayFeatureValue; /// Display features \ref define_adl_visiblememoryfeatures that are using this type of memory } ADLMemoryRequired, *LPADLMemoryRequired; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the features associated with a display +/// +/// This structure is a parameter to ADL_Adapter_ConfigMemory_Get, which given a desktop and display configuration +/// will return the Memory used. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLMemoryDisplayFeatures { - int iDisplayIndex; - int iDisplayFeatureValue; + int iDisplayIndex; /// ADL Display index + int iDisplayFeatureValue; /// features that the display is using \ref define_adl_visiblememoryfeatures } ADLMemoryDisplayFeatures, *LPADLMemoryDisplayFeatures; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing DDC information. +/// +/// This structure is used to store various DDC information that can be returned to the user. +/// Note that all fields of type int are actually defined as unsigned int types within the driver. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDDCInfo { +/// Size of the structure int ulSize; +/// Indicates whether the attached display supports DDC. If this field is zero on return, no other DDC information fields will be used. int ulSupportsDDC; +/// Returns the manufacturer ID of the display device. Should be zeroed if this information is not available. int ulManufacturerID; +/// Returns the product ID of the display device. Should be zeroed if this information is not available. int ulProductID; +/// Returns the name of the display device. Should be zeroed if this information is not available. char cDisplayName[ADL_MAX_DISPLAY_NAME]; +/// Returns the maximum Horizontal supported resolution. Should be zeroed if this information is not available. int ulMaxHResolution; +/// Returns the maximum Vertical supported resolution. Should be zeroed if this information is not available. int ulMaxVResolution; +/// Returns the maximum supported refresh rate. Should be zeroed if this information is not available. int ulMaxRefresh; +/// Returns the display device preferred timing mode's horizontal resolution. int ulPTMCx; +/// Returns the display device preferred timing mode's vertical resolution. int ulPTMCy; +/// Returns the display device preferred timing mode's refresh rate. int ulPTMRefreshRate; +/// Return EDID flags. int ulDDCInfoFlag; } ADLDDCInfo, *LPADLDDCInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing DDC information. +/// +/// This structure is used to store various DDC information that can be returned to the user. +/// Note that all fields of type int are actually defined as unsigned int types within the driver. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDDCInfo2 { +/// Size of the structure int ulSize; +/// Indicates whether the attached display supports DDC. If this field is zero on return, no other DDC +/// information fields will be used. int ulSupportsDDC; +/// Returns the manufacturer ID of the display device. Should be zeroed if this information is not available. int ulManufacturerID; +/// Returns the product ID of the display device. Should be zeroed if this information is not available. int ulProductID; +/// Returns the name of the display device. Should be zeroed if this information is not available. char cDisplayName[ADL_MAX_DISPLAY_NAME]; +/// Returns the maximum Horizontal supported resolution. Should be zeroed if this information is not available. int ulMaxHResolution; +/// Returns the maximum Vertical supported resolution. Should be zeroed if this information is not available. int ulMaxVResolution; +/// Returns the maximum supported refresh rate. Should be zeroed if this information is not available. int ulMaxRefresh; +/// Returns the display device preferred timing mode's horizontal resolution. int ulPTMCx; +/// Returns the display device preferred timing mode's vertical resolution. int ulPTMCy; +/// Returns the display device preferred timing mode's refresh rate. int ulPTMRefreshRate; +/// Return EDID flags. int ulDDCInfoFlag; +/// Returns 1 if the display supported packed pixel, 0 otherwise int bPackedPixelSupported; +/// Returns the Pixel formats the display supports \ref define_ddcinfo_pixelformats int iPanelPixelFormat; +/// Return EDID serial ID. int ulSerialID; +/// Return minimum monitor luminance data int ulMinLuminanceData; +/// Return average monitor luminance data int ulAvgLuminanceData; +/// Return maximum monitor luminance data int ulMaxLuminanceData; +/// Bit vector of supported transfer functions \ref define_source_content_TF int iSupportedTransferFunction; +/// Bit vector of supported color spaces \ref define_source_content_CS int iSupportedColorSpace; +/// Display Red Chromaticity X coordinate multiplied by 10000 int iNativeDisplayChromaticityRedX; +/// Display Red Chromaticity Y coordinate multiplied by 10000 int iNativeDisplayChromaticityRedY; +/// Display Green Chromaticity X coordinate multiplied by 10000 int iNativeDisplayChromaticityGreenX; +/// Display Green Chromaticity Y coordinate multiplied by 10000 int iNativeDisplayChromaticityGreenY; +/// Display Blue Chromaticity X coordinate multiplied by 10000 int iNativeDisplayChromaticityBlueX; +/// Display Blue Chromaticity Y coordinate multiplied by 10000 int iNativeDisplayChromaticityBlueY; +/// Display White Point X coordinate multiplied by 10000 int iNativeDisplayChromaticityWhitePointX; +/// Display White Point Y coordinate multiplied by 10000 int iNativeDisplayChromaticityWhitePointY; +/// Display diffuse screen reflectance 0-1 (100%) in units of 0.01 int iDiffuseScreenReflectance; +/// Display specular screen reflectance 0-1 (100%) in units of 0.01 int iSpecularScreenReflectance; +/// Bit vector of supported color spaces \ref define_HDR_support int iSupportedHDR; +/// Bit vector for freesync flags int iFreesyncFlags; +/// Return minimum monitor luminance without dimming data int ulMinLuminanceNoDimmingData; int ulMaxBacklightMaxLuminanceData; @@ -251,23 +457,52 @@ typedef struct ADLDDCInfo2 int iReserved[4]; } ADLDDCInfo2, *LPADLDDCInfo2; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information controller Gamma settings. +/// +/// This structure is used to store the red, green and blue color channel information for the. +/// controller gamma setting. This information is returned by ADL, and it can also be used to +/// set the controller gamma setting. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLGamma { +/// Red color channel gamma value. float fRed; +/// Green color channel gamma value. float fGreen; +/// Blue color channel gamma value. float fBlue; } ADLGamma, *LPADLGamma; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about component video custom modes. +/// +/// This structure is used to store the component video custom mode. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLCustomMode { +/// Custom mode flags. They are returned by the ADL driver. int iFlags; +/// Custom mode width. int iModeWidth; +/// Custom mode height. int iModeHeight; +/// Custom mode base width. int iBaseModeWidth; +/// Custom mode base height. int iBaseModeHeight; +/// Custom mode refresh rate. int iRefreshRate; } ADLCustomMode, *LPADLCustomMode; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing Clock information for OD5 calls. +/// +/// This structure is used to retrieve clock information for OD5 calls. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLGetClocksOUT { long ulHighCoreClock; @@ -283,847 +518,1807 @@ typedef struct ADLGetClocksOUT long ulReserved; } ADLGetClocksOUT; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing HDTV information for display calls. +/// +/// This structure is used to retrieve HDTV information information for display calls. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDisplayConfig { - long ulSize; - long ulConnectorType; - long ulDeviceData; - long ulOverridedDeviceData; - long ulReserved; +/// Size of the structure + long ulSize; +/// HDTV connector type. + long ulConnectorType; +/// HDTV capabilities. + long ulDeviceData; +/// Overridden HDTV capabilities. + long ulOverridedDeviceData; +/// Reserved field + long ulReserved; } ADLDisplayConfig; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the display device. +/// +/// This structure is used to store display device information +/// such as display index, type, name, connection status, mapped adapter and controller indexes, +/// whether or not multiple VPUs are supported, local display connections or not (through Lasso), etc. +/// This information can be returned to the user. Alternatively, it can be used to access various driver calls to set +/// or fetch various display device related settings upon the user's request. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDisplayID { +/// The logical display index belonging to this adapter. int iDisplayLogicalIndex; +///\brief The physical display index. +/// For example, display index 2 from adapter 2 can be used by current adapter 1.\n +/// So current adapter may enumerate this adapter as logical display 7 but the physical display +/// index is still 2. int iDisplayPhysicalIndex; +/// The persistent logical adapter index for the display. int iDisplayLogicalAdapterIndex; +///\brief The persistent physical adapter index for the display. +/// It can be the current adapter or a non-local adapter. \n +/// If this adapter index is different than the current adapter, +/// the Display Non Local flag is set inside DisplayInfoValue. int iDisplayPhysicalAdapterIndex; } ADLDisplayID, *LPADLDisplayID; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the display device. +/// +/// This structure is used to store various information about the display device. This +/// information can be returned to the user, or used to access various driver calls to set +/// or fetch various display-device-related settings upon the user's request +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDisplayInfo { +/// The DisplayID structure ADLDisplayID displayID; +///\deprecated The controller index to which the display is mapped.\n Will not be used in the future\n int iDisplayControllerIndex; +/// The display's EDID name. char strDisplayName[ADL_MAX_PATH]; +/// The display's manufacturer name. char strDisplayManufacturerName[ADL_MAX_PATH]; +/// The Display type. For example: CRT, TV, CV, DFP. int iDisplayType; +/// The display output type. For example: HDMI, SVIDEO, COMPONMNET VIDEO. int iDisplayOutputType; +/// The connector type for the device. int iDisplayConnector; +///\brief The bit mask identifies the number of bits ADLDisplayInfo is currently using. \n +/// It will be the sum all the bit definitions in ADL_DISPLAY_DISPLAYINFO_xxx. int iDisplayInfoMask; +/// The bit mask identifies the display status. \ref define_displayinfomask int iDisplayInfoValue; } ADLDisplayInfo, *LPADLDisplayInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the display port MST device. +/// +/// This structure is used to store various MST information about the display port device. This +/// information can be returned to the user, or used to access various driver calls to +/// fetch various display-device-related settings upon the user's request +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDisplayDPMSTInfo { + /// The ADLDisplayID structure ADLDisplayID displayID; + /// total bandwidth available on the DP connector int iTotalAvailableBandwidthInMpbs; + /// bandwidth allocated to this display int iAllocatedBandwidthInMbps; // info from DAL DpMstSinkInfo + /// string identifier for the display char strGlobalUniqueIdentifier[ADL_MAX_PATH]; + /// The link count of relative address, rad[0] upto rad[linkCount] are valid int radLinkCount; + /// The physical connector ID, used to identify the physical DP port int iPhysicalConnectorID; + /// Relative address, address scheme starts from source side char rad[ADL_MAX_RAD_LINK_COUNT]; } ADLDisplayDPMSTInfo, *LPADLDisplayDPMSTInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing the display mode definition used per controller. +/// +/// This structure is used to store the display mode definition used per controller. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDisplayMode { - int iPelsHeight; - int iPelsWidth; - int iBitsPerPel; - int iDisplayFrequency; +/// Vertical resolution (in pixels). + int iPelsHeight; +/// Horizontal resolution (in pixels). + int iPelsWidth; +/// Color depth. + int iBitsPerPel; +/// Refresh rate. + int iDisplayFrequency; } ADLDisplayMode; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing detailed timing parameters. +/// +/// This structure is used to store the detailed timing parameters. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDetailedTiming { - int iSize; - short sTimingFlags; - short sHTotal; - short sHDisplay; - short sHSyncStart; - short sHSyncWidth; - short sVTotal; - short sVDisplay; - short sVSyncStart; - short sVSyncWidth; - short sPixelClock; - short sHOverscanRight; - short sHOverscanLeft; - short sVOverscanBottom; - short sVOverscanTop; - short sOverscan8B; - short sOverscanGR; +/// Size of the structure. + int iSize; +/// Timing flags. \ref define_detailed_timing_flags + short sTimingFlags; +/// Total width (columns). + short sHTotal; +/// Displayed width. + short sHDisplay; +/// Horizontal sync signal offset. + short sHSyncStart; +/// Horizontal sync signal width. + short sHSyncWidth; +/// Total height (rows). + short sVTotal; +/// Displayed height. + short sVDisplay; +/// Vertical sync signal offset. + short sVSyncStart; +/// Vertical sync signal width. + short sVSyncWidth; +/// Pixel clock value. + short sPixelClock; +/// Overscan right. + short sHOverscanRight; +/// Overscan left. + short sHOverscanLeft; +/// Overscan bottom. + short sVOverscanBottom; +/// Overscan top. + short sVOverscanTop; + short sOverscan8B; + short sOverscanGR; } ADLDetailedTiming; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing display mode information. +/// +/// This structure is used to store the display mode information. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDisplayModeInfo { - int iTimingStandard; - int iPossibleStandard; - int iRefreshRate; - int iPelsWidth; - int iPelsHeight; - ADLDetailedTiming sDetailedTiming; +/// Timing standard of the current mode. \ref define_modetiming_standard + int iTimingStandard; +/// Applicable timing standards for the current mode. + int iPossibleStandard; +/// Refresh rate factor. + int iRefreshRate; +/// Num of pixels in a row. + int iPelsWidth; +/// Num of pixels in a column. + int iPelsHeight; +/// Detailed timing parameters. + ADLDetailedTiming sDetailedTiming; } ADLDisplayModeInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +/// \brief Structure containing information about display property. +/// +/// This structure is used to store the display property for the current adapter. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDisplayProperty { - int iSize; - int iPropertyType; - int iExpansionMode; - int iSupport; - int iCurrent; - int iDefault; +/// Must be set to sizeof the structure + int iSize; +/// Must be set to \ref ADL_DL_DISPLAYPROPERTY_TYPE_EXPANSIONMODE or \ref ADL_DL_DISPLAYPROPERTY_TYPE_USEUNDERSCANSCALING + int iPropertyType; +/// Get or Set \ref ADL_DL_DISPLAYPROPERTY_EXPANSIONMODE_CENTER or \ref ADL_DL_DISPLAYPROPERTY_EXPANSIONMODE_FULLSCREEN or \ref ADL_DL_DISPLAYPROPERTY_EXPANSIONMODE_ASPECTRATIO or \ref ADL_DL_DISPLAYPROPERTY_TYPE_ITCFLAGENABLE + int iExpansionMode; +/// Display Property supported? 1: Supported, 0: Not supported + int iSupport; +/// Display Property current value + int iCurrent; +/// Display Property Default value + int iDefault; } ADLDisplayProperty; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Clock. +/// +/// This structure is used to store the clock information for the current adapter +/// such as core clock and memory clock info. +///\nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLClockInfo { +/// Core clock in 10 KHz. int iCoreClock; +/// Memory clock in 10 KHz. int iMemoryClock; } ADLClockInfo, *LPADLClockInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about I2C. +/// +/// This structure is used to store the I2C information for the current adapter. +/// This structure is used by the ADL_Display_WriteAndReadI2C() function. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLI2C { +/// Size of the structure int iSize; +/// Numerical value representing hardware I2C. int iLine; +/// The 7-bit I2C slave device address, shifted one bit to the left. int iAddress; +/// The offset of the data from the address. int iOffset; +/// Read from or write to slave device. \ref ADL_DL_I2C_ACTIONREAD or \ref ADL_DL_I2C_ACTIONWRITE or \ref ADL_DL_I2C_ACTIONREAD_REPEATEDSTART int iAction; +/// I2C clock speed in KHz. int iSpeed; +/// A numerical value representing the number of bytes to be sent or received on the I2C bus. int iDataSize; +/// Address of the characters which are to be sent or received on the I2C bus. char *pcData; } ADLI2C; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about EDID data. +/// +/// This structure is used to store the information about EDID data for the adapter. +/// This structure is used by the ADL_Display_EdidData_Get() and ADL_Display_EdidData_Set() functions. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDisplayEDIDData { - int iSize; - int iFlag; - int iEDIDSize; - int iBlockIndex; - char cEDIDData[ADL_MAX_EDIDDATA_SIZE]; - int iReserved[4]; +/// Size of the structure + int iSize; +/// Set to 0 + int iFlag; + /// Size of cEDIDData. Set by ADL_Display_EdidData_Get() upon return + int iEDIDSize; +/// 0, 1 or 2. If set to 3 or above an error ADL_ERR_INVALID_PARAM is generated + int iBlockIndex; +/// EDID data + char cEDIDData[ADL_MAX_EDIDDATA_SIZE]; +/// Reserved + int iReserved[4]; }ADLDisplayEDIDData; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about input of controller overlay adjustment. +/// +/// This structure is used to store the information about input of controller overlay adjustment for the adapter. +/// This structure is used by the ADL_Display_ControllerOverlayAdjustmentCaps_Get, ADL_Display_ControllerOverlayAdjustmentData_Get, and +/// ADL_Display_ControllerOverlayAdjustmentData_Set() functions. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLControllerOverlayInput { - int iSize; - int iOverlayAdjust; - int iValue; - int iReserved; +/// Should be set to the sizeof the structure + int iSize; +///\ref ADL_DL_CONTROLLER_OVERLAY_ALPHA or \ref ADL_DL_CONTROLLER_OVERLAY_ALPHAPERPIX + int iOverlayAdjust; +/// Data. + int iValue; +/// Should be 0. + int iReserved; } ADLControllerOverlayInput; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about overlay adjustment. +/// +/// This structure is used to store the information about overlay adjustment for the adapter. +/// This structure is used by the ADLControllerOverlayInfo() function. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLAdjustmentinfo { - int iDefault; - int iMin; - int iMax; - int iStep; +/// Default value + int iDefault; +/// Minimum value + int iMin; +/// Maximum Value + int iMax; +/// Step value + int iStep; } ADLAdjustmentinfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about controller overlay information. +/// +/// This structure is used to store information about controller overlay info for the adapter. +/// This structure is used by the ADL_Display_ControllerOverlayAdjustmentCaps_Get() function. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLControllerOverlayInfo { - int iSize; - ADLAdjustmentinfo sOverlayInfo; - int iReserved[3]; +/// Should be set to the sizeof the structure + int iSize; +/// Data. + ADLAdjustmentinfo sOverlayInfo; +/// Should be 0. + int iReserved[3]; } ADLControllerOverlayInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing GL-Sync module information. +/// +/// This structure is used to retrieve GL-Sync module information for +/// Workstation Framelock/Genlock. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLGLSyncModuleID { +/// Unique GL-Sync module ID. int iModuleID; +/// GL-Sync GPU port index (to be passed into ADLGLSyncGenlockConfig.lSignalSource and ADLGlSyncPortControl.lSignalSource). int iGlSyncGPUPort; +/// GL-Sync module firmware version of Boot Sector. int iFWBootSectorVersion; +/// GL-Sync module firmware version of User Sector. int iFWUserSectorVersion; } ADLGLSyncModuleID , *LPADLGLSyncModuleID; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing GL-Sync ports capabilities. +/// +/// This structure is used to retrieve hardware capabilities for the ports of the GL-Sync module +/// for Workstation Framelock/Genlock (such as port type and number of associated LEDs). +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLGLSyncPortCaps { +/// Port type. Bitfield of ADL_GLSYNC_PORTTYPE_* \ref define_glsync int iPortType; +/// Number of LEDs associated for this port. int iNumOfLEDs; }ADLGLSyncPortCaps, *LPADLGLSyncPortCaps; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing GL-Sync Genlock settings. +/// +/// This structure is used to get and set genlock settings for the GPU ports of the GL-Sync module +/// for Workstation Framelock/Genlock.\n +/// \see define_glsync +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLGLSyncGenlockConfig { +/// Specifies what fields in this structure are valid \ref define_glsync int iValidMask; +/// Delay (ms) generating a sync signal. int iSyncDelay; +/// Vector of framelock control bits. Bitfield of ADL_GLSYNC_FRAMELOCKCNTL_* \ref define_glsync int iFramelockCntlVector; +/// Source of the sync signal. Either GL_Sync GPU Port index or ADL_GLSYNC_SIGNALSOURCE_* \ref define_glsync int iSignalSource; +/// Use sampled sync signal. A value of 0 specifies no sampling. int iSampleRate; +/// For interlaced sync signals, the value can be ADL_GLSYNC_SYNCFIELD_1 or *_BOTH \ref define_glsync int iSyncField; +/// The signal edge that should trigger synchronization. ADL_GLSYNC_TRIGGEREDGE_* \ref define_glsync int iTriggerEdge; +/// Scan rate multiplier applied to the sync signal. ADL_GLSYNC_SCANRATECOEFF_* \ref define_glsync int iScanRateCoeff; }ADLGLSyncGenlockConfig, *LPADLGLSyncGenlockConfig; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing GL-Sync port information. +/// +/// This structure is used to get status of the GL-Sync ports (BNC or RJ45s) +/// for Workstation Framelock/Genlock. +/// \see define_glsync +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLGlSyncPortInfo { +/// Type of GL-Sync port (ADL_GLSYNC_PORT_*). int iPortType; +/// The number of LEDs for this port. It's also filled within ADLGLSyncPortCaps. int iNumOfLEDs; +/// Port state ADL_GLSYNC_PORTSTATE_* \ref define_glsync int iPortState; +/// Scanned frequency for this port (vertical refresh rate in milliHz; 60000 means 60 Hz). int iFrequency; +/// Used for ADL_GLSYNC_PORT_BNC. It is ADL_GLSYNC_SIGNALTYPE_* \ref define_glsync int iSignalType; +/// Used for ADL_GLSYNC_PORT_RJ45PORT*. It is GL_Sync GPU Port index or ADL_GLSYNC_SIGNALSOURCE_*. \ref define_glsync int iSignalSource; } ADLGlSyncPortInfo, *LPADLGlSyncPortInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing GL-Sync port control settings. +/// +/// This structure is used to configure the GL-Sync ports (RJ45s only) +/// for Workstation Framelock/Genlock. +/// \see define_glsync +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLGlSyncPortControl { +/// Port to control ADL_GLSYNC_PORT_RJ45PORT1 or ADL_GLSYNC_PORT_RJ45PORT2 \ref define_glsync int iPortType; +/// Port control data ADL_GLSYNC_PORTCNTL_* \ref define_glsync int iControlVector; +/// Source of the sync signal. Either GL_Sync GPU Port index or ADL_GLSYNC_SIGNALSOURCE_* \ref define_glsync int iSignalSource; } ADLGlSyncPortControl; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing GL-Sync mode of a display. +/// +/// This structure is used to get and set GL-Sync mode settings for a display connected to +/// an adapter attached to a GL-Sync module for Workstation Framelock/Genlock. +/// \see define_glsync +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLGlSyncMode { +/// Mode control vector. Bitfield of ADL_GLSYNC_MODECNTL_* \ref define_glsync int iControlVector; +/// Mode status vector. Bitfield of ADL_GLSYNC_MODECNTL_STATUS_* \ref define_glsync int iStatusVector; +/// Index of GL-Sync connector used to genlock the display/controller. int iGLSyncConnectorIndex; } ADLGlSyncMode, *LPADLGlSyncMode; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing GL-Sync mode of a display. +/// +/// This structure is used to get and set GL-Sync mode settings for a display connected to +/// an adapter attached to a GL-Sync module for Workstation Framelock/Genlock. +/// \see define_glsync +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLGlSyncMode2 { +/// Mode control vector. Bitfield of ADL_GLSYNC_MODECNTL_* \ref define_glsync int iControlVector; +/// Mode status vector. Bitfield of ADL_GLSYNC_MODECNTL_STATUS_* \ref define_glsync int iStatusVector; +/// Index of GL-Sync connector used to genlock the display/controller. int iGLSyncConnectorIndex; +/// Index of the display to which this GLSync applies to. int iDisplayIndex; } ADLGlSyncMode2, *LPADLGlSyncMode2; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing the packet info of a display. +/// +/// This structure is used to get and set the packet information of a display. +/// This structure is used by ADLDisplayDataPacket. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLInfoPacket { char hb0; char hb1; char hb2; +/// sb0~sb27 char sb[28]; }ADLInfoPacket; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing the AVI packet info of a display. +/// +/// This structure is used to get and set AVI the packet info of a display. +/// This structure is used by ADLDisplayDataPacket. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLAVIInfoPacket //Valid user defined data/ { - char bPB3_ITC; - char bPB5; +/// byte 3, bit 7 + char bPB3_ITC; +/// byte 5, bit [7:4]. + char bPB5; }ADLAVIInfoPacket; // Overdrive clock setting structure definition. +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing the Overdrive clock setting. +/// +/// This structure is used to get the Overdrive clock setting. +/// This structure is used by ADLAdapterODClockInfo. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLODClockSetting { +/// Deafult clock int iDefaultClock; +/// Current clock int iCurrentClock; +/// Maximum clcok int iMaxClock; +/// Minimum clock int iMinClock; +/// Requested clcock int iRequestedClock; +/// Step int iStepClock; } ADLODClockSetting; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing the Overdrive clock information. +/// +/// This structure is used to get the Overdrive clock information. +/// This structure is used by the ADL_Display_ODClockInfo_Get() function. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLAdapterODClockInfo { +/// Size of the structure int iSize; +/// Flag \ref define_clockinfo_flags int iFlags; +/// Memory Clock ADLODClockSetting sMemoryClock; +/// Engine Clock ADLODClockSetting sEngineClock; } ADLAdapterODClockInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing the Overdrive clock configuration. +/// +/// This structure is used to set the Overdrive clock configuration. +/// This structure is used by the ADL_Display_ODClockConfig_Set() function. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLAdapterODClockConfig { - int iSize; - int iFlags; - int iMemoryClock; - int iEngineClock; +/// Size of the structure + int iSize; +/// Flag \ref define_clockinfo_flags + int iFlags; +/// Memory Clock + int iMemoryClock; +/// Engine Clock + int iEngineClock; } ADLAdapterODClockConfig; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about current power management related activity. +/// +/// This structure is used to store information about current power management related activity. +/// This structure (Overdrive 5 interfaces) is used by the ADL_PM_CurrentActivity_Get() function. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLPMActivity { +/// Must be set to the size of the structure int iSize; +/// Current engine clock. int iEngineClock; +/// Current memory clock. int iMemoryClock; +/// Current core voltage. int iVddc; +/// GPU utilization. int iActivityPercent; +/// Performance level index. int iCurrentPerformanceLevel; +/// Current PCIE bus speed. int iCurrentBusSpeed; +/// Number of PCIE bus lanes. int iCurrentBusLanes; +/// Maximum number of PCIE bus lanes. int iMaximumBusLanes; +/// Reserved for future purposes. int iReserved; } ADLPMActivity; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about thermal controller. +/// +/// This structure is used to store information about thermal controller. +/// This structure is used by ADL_PM_ThermalDevices_Enum. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLThermalControllerInfo { - int iSize; - int iThermalDomain; - int iDomainIndex; - int iFlags; +/// Must be set to the size of the structure + int iSize; +/// Possible valies: \ref ADL_DL_THERMAL_DOMAIN_OTHER or \ref ADL_DL_THERMAL_DOMAIN_GPU. + int iThermalDomain; +/// GPU 0, 1, etc. + int iDomainIndex; +/// Possible valies: \ref ADL_DL_THERMAL_FLAG_INTERRUPT or \ref ADL_DL_THERMAL_FLAG_FANCONTROL + int iFlags; } ADLThermalControllerInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about thermal controller temperature. +/// +/// This structure is used to store information about thermal controller temperature. +/// This structure is used by the ADL_PM_Temperature_Get() function. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLTemperature { - int iSize; - int iTemperature; +/// Must be set to the size of the structure + int iSize; +/// Temperature in millidegrees Celsius. + int iTemperature; } ADLTemperature; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about thermal controller fan speed. +/// +/// This structure is used to store information about thermal controller fan speed. +/// This structure is used by the ADL_PM_FanSpeedInfo_Get() function. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLFanSpeedInfo { - int iSize; - int iFlags; - int iMinPercent; - int iMaxPercent; - int iMinRPM; - int iMaxRPM; +/// Must be set to the size of the structure + int iSize; +/// \ref define_fanctrl + int iFlags; +/// Minimum possible fan speed value in percents. + int iMinPercent; +/// Maximum possible fan speed value in percents. + int iMaxPercent; +/// Minimum possible fan speed value in RPM. + int iMinRPM; +/// Maximum possible fan speed value in RPM. + int iMaxRPM; } ADLFanSpeedInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about fan speed reported by thermal controller. +/// +/// This structure is used to store information about fan speed reported by thermal controller. +/// This structure is used by the ADL_Overdrive5_FanSpeed_Get() and ADL_Overdrive5_FanSpeed_Set() functions. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLFanSpeedValue { - int iSize; - int iSpeedType; - int iFanSpeed; - int iFlags; +/// Must be set to the size of the structure + int iSize; +/// Possible valies: \ref ADL_DL_FANCTRL_SPEED_TYPE_PERCENT or \ref ADL_DL_FANCTRL_SPEED_TYPE_RPM + int iSpeedType; +/// Fan speed value + int iFanSpeed; +/// The only flag for now is: \ref ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED + int iFlags; } ADLFanSpeedValue; +//////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing the range of Overdrive parameter. +/// +/// This structure is used to store information about the range of Overdrive parameter. +/// This structure is used by ADLODParameters. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLODParameterRange { - int iMin; - int iMax; - int iStep; +/// Minimum parameter value. + int iMin; +/// Maximum parameter value. + int iMax; +/// Parameter step value. + int iStep; } ADLODParameterRange; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive parameters. +/// +/// This structure is used to store information about Overdrive parameters. +/// This structure is used by the ADL_Overdrive5_ODParameters_Get() function. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLODParameters { - int iSize; - int iNumberOfPerformanceLevels; - int iActivityReportingSupported; - int iDiscretePerformanceLevels; - int iReserved; - ADLODParameterRange sEngineClock; - ADLODParameterRange sMemoryClock; - ADLODParameterRange sVddc; +/// Must be set to the size of the structure + int iSize; +/// Number of standard performance states. + int iNumberOfPerformanceLevels; +/// Indicates whether the GPU is capable to measure its activity. + int iActivityReportingSupported; +/// Indicates whether the GPU supports discrete performance levels or performance range. + int iDiscretePerformanceLevels; +/// Reserved for future use. + int iReserved; +/// Engine clock range. + ADLODParameterRange sEngineClock; +/// Memory clock range. + ADLODParameterRange sMemoryClock; +/// Core voltage range. + ADLODParameterRange sVddc; } ADLODParameters; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive level. +/// +/// This structure is used to store information about Overdrive level. +/// This structure is used by ADLODPerformanceLevels. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLODPerformanceLevel { - int iEngineClock; - int iMemoryClock; - int iVddc; +/// Engine clock. + int iEngineClock; +/// Memory clock. + int iMemoryClock; +/// Core voltage. + int iVddc; } ADLODPerformanceLevel; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive performance levels. +/// +/// This structure is used to store information about Overdrive performance levels. +/// This structure is used by the ADL_Overdrive5_ODPerformanceLevels_Get() and ADL_Overdrive5_ODPerformanceLevels_Set() functions. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLODPerformanceLevels { - int iSize; - int iReserved; - ADLODPerformanceLevel aLevels [1]; +/// Must be set to sizeof( \ref ADLODPerformanceLevels ) + sizeof( \ref ADLODPerformanceLevel ) * (ADLODParameters.iNumberOfPerformanceLevels - 1) + int iSize; + int iReserved; +/// Array of performance state descriptors. Must have ADLODParameters.iNumberOfPerformanceLevels elements. + ADLODPerformanceLevel aLevels [1]; } ADLODPerformanceLevels; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the proper CrossfireX chains combinations. +/// +/// This structure is used to store information about the CrossfireX chains combination for a particular adapter. +/// This structure is used by the ADL_Adapter_Crossfire_Caps(), ADL_Adapter_Crossfire_Get(), and ADL_Adapter_Crossfire_Set() functions. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLCrossfireComb { - int iNumLinkAdapter; - int iAdaptLink[3]; +/// Number of adapters in this combination. + int iNumLinkAdapter; +/// A list of ADL indexes of the linked adapters in this combination. + int iAdaptLink[3]; } ADLCrossfireComb; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing CrossfireX state and error information. +/// +/// This structure is used to store state and error information about a particular adapter CrossfireX combination. +/// This structure is used by the ADL_Adapter_Crossfire_Get() function. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLCrossfireInfo { - int iErrorCode; - int iState; - int iSupported; +/// Current error code of this CrossfireX combination. + int iErrorCode; +/// Current \ref define_crossfirestate + int iState; +/// If CrossfireX is supported by this combination. The value is either \ref ADL_TRUE or \ref ADL_FALSE. + int iSupported; } ADLCrossfireInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +/// \brief Structure containing information about the BIOS. +/// +/// This structure is used to store various information about the Chipset. This +/// information can be returned to the user. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLBiosInfo { - char strPartNumber[ADL_MAX_PATH]; - char strVersion[ADL_MAX_PATH]; - char strDate[ADL_MAX_PATH]; + char strPartNumber[ADL_MAX_PATH]; ///< Part number. + char strVersion[ADL_MAX_PATH]; ///< Version number. + char strDate[ADL_MAX_PATH]; ///< BIOS date in yyyy/mm/dd hh:mm format. } ADLBiosInfo, *LPADLBiosInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +/// \brief Structure containing information about adapter location. +/// +/// This structure is used to store information about adapter location. +/// This structure is used by ADLMVPUStatus. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLAdapterLocation { +/// PCI Bus number : 8 bits int iBus; +/// Device number : 5 bits int iDevice; +/// Function number : 3 bits int iFunction; } ADLAdapterLocation,ADLBdf; +///////////////////////////////////////////////////////////////////////////////////////////// +/// \brief Structure containing version information +/// +/// This structure is used to store software version information, description of the display device and a web link to the latest installed Catalyst drivers. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLVersionsInfo { + /// Driver Release (Packaging) Version (e.g. 8.71-100128n-094835E-ATI) char strDriverVer[ADL_MAX_PATH]; + /// Catalyst Version(e.g. "10.1"). char strCatalystVersion[ADL_MAX_PATH]; + /// Web link to an XML file with information about the latest AMD drivers and locations (e.g. "http://www.amd.com/us/driverxml" ) char strCatalystWebLink[ADL_MAX_PATH]; } ADLVersionsInfo, *LPADLVersionsInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +/// \brief Structure containing version information +/// +/// This structure is used to store software version information, description of the display device and a web link to the latest installed Catalyst drivers. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLVersionsInfoX2 { + /// Driver Release (Packaging) Version (e.g. "16.20.1035-160621a-303814C") char strDriverVer[ADL_MAX_PATH]; + /// Catalyst Version(e.g. "15.8"). char strCatalystVersion[ADL_MAX_PATH]; + /// Crimson Version(e.g. "16.6.2"). char strCrimsonVersion[ADL_MAX_PATH]; + /// Web link to an XML file with information about the latest AMD drivers and locations (e.g. "http://support.amd.com/drivers/xml/driver_09_us.xml" ) char strCatalystWebLink[ADL_MAX_PATH]; } ADLVersionsInfoX2, *LPADLVersionsInfoX2; +///////////////////////////////////////////////////////////////////////////////////////////// +/// \brief Structure containing information about MultiVPU capabilities. +/// +/// This structure is used to store information about MultiVPU capabilities. +/// This structure is used by the ADL_Display_MVPUCaps_Get() function. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLMVPUCaps { - int iSize; - int iAdapterCount; - int iPossibleMVPUMasters; - int iPossibleMVPUSlaves; - char cAdapterPath[ADL_DL_MAX_MVPU_ADAPTERS][ADL_DL_MAX_REGISTRY_PATH]; +/// Must be set to sizeof( ADLMVPUCaps ). + int iSize; +/// Number of adapters. + int iAdapterCount; +/// Bits set for all possible MVPU masters. \ref MVPU_ADAPTER_0 .. \ref MVPU_ADAPTER_3 + int iPossibleMVPUMasters; +/// Bits set for all possible MVPU slaves. \ref MVPU_ADAPTER_0 .. \ref MVPU_ADAPTER_3 + int iPossibleMVPUSlaves; +/// Registry path for each adapter. + char cAdapterPath[ADL_DL_MAX_MVPU_ADAPTERS][ADL_DL_MAX_REGISTRY_PATH]; } ADLMVPUCaps; +///////////////////////////////////////////////////////////////////////////////////////////// +/// \brief Structure containing information about MultiVPU status. +/// +/// This structure is used to store information about MultiVPU status. +/// Ths structure is used by the ADL_Display_MVPUStatus_Get() function. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLMVPUStatus { - int iSize; - int iActiveAdapterCount; - int iStatus; - ADLAdapterLocation aAdapterLocation[ADL_DL_MAX_MVPU_ADAPTERS]; +/// Must be set to sizeof( ADLMVPUStatus ). + int iSize; +/// Number of active adapters. + int iActiveAdapterCount; +/// MVPU status. + int iStatus; +/// PCI Bus/Device/Function for each active adapter participating in MVPU. + ADLAdapterLocation aAdapterLocation[ADL_DL_MAX_MVPU_ADAPTERS]; } ADLMVPUStatus; // Displays Manager structures +/////////////////////////////////////////////////////////////////////////// +/// \brief Structure containing information about the activatable source. +/// +/// This structure is used to store activatable source information +/// This information can be returned to the user. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLActivatableSource { + /// The Persistent logical Adapter Index. int iAdapterIndex; + /// The number of Activatable Sources. int iNumActivatableSources; + /// The bit mask identifies the number of bits ActivatableSourceValue is using. (Not currnetly used) int iActivatableSourceMask; + /// The bit mask identifies the status. (Not currnetly used) int iActivatableSourceValue; } ADLActivatableSource, *LPADLActivatableSource; +///////////////////////////////////////////////////////////////////////////////////////////// +/// \brief Structure containing information about display mode. +/// +/// This structure is used to store the display mode for the current adapter +/// such as X, Y positions, screen resolutions, orientation, +/// color depth, refresh rate, progressive or interlace mode, etc. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLMode { +/// Adapter index. int iAdapterIndex; +/// Display IDs. ADLDisplayID displayID; +/// Screen position X coordinate. int iXPos; +/// Screen position Y coordinate. int iYPos; +/// Screen resolution Width. int iXRes; +/// Screen resolution Height. int iYRes; +/// Screen Color Depth. E.g., 16, 32. int iColourDepth; +/// Screen refresh rate. Could be fractional E.g. 59.97 float fRefreshRate; +/// Screen orientation. E.g., 0, 90, 180, 270. int iOrientation; +/// Vista mode flag indicating Progressive or Interlaced mode. int iModeFlag; +/// The bit mask identifying the number of bits this Mode is currently using. It is the sum of all the bit definitions defined in \ref define_displaymode int iModeMask; +/// The bit mask identifying the display status. The detailed definition is in \ref define_displaymode int iModeValue; } ADLMode, *LPADLMode; +///////////////////////////////////////////////////////////////////////////////////////////// +/// \brief Structure containing information about display target information. +/// +/// This structure is used to store the display target information. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDisplayTarget { + /// The Display ID. ADLDisplayID displayID; + /// The display map index identify this manner and the desktop surface. int iDisplayMapIndex; + /// The bit mask identifies the number of bits DisplayTarget is currently using. It is the sum of all the bit definitions defined in \ref ADL_DISPLAY_DISPLAYTARGET_PREFERRED. int iDisplayTargetMask; + /// The bit mask identifies the display status. The detailed definition is in \ref ADL_DISPLAY_DISPLAYTARGET_PREFERRED. int iDisplayTargetValue; } ADLDisplayTarget, *LPADLDisplayTarget; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the display SLS bezel Mode information. +/// +/// This structure is used to store the display SLS bezel Mode information. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct tagADLBezelTransientMode { + /// Adapter Index int iAdapterIndex; + /// SLS Map Index int iSLSMapIndex; + /// The mode index int iSLSModeIndex; + /// The mode ADLMode displayMode; + /// The number of bezel offsets belongs to this map int iNumBezelOffset; + /// The first bezel offset array index in the native mode array int iFirstBezelOffsetArrayIndex; + /// The bit mask identifies the bits this structure is currently using. It will be the total OR of all the bit definitions. int iSLSBezelTransientModeMask; + /// The bit mask identifies the display status. The detail definition is defined below. int iSLSBezelTransientModeValue; } ADLBezelTransientMode, *LPADLBezelTransientMode; +///////////////////////////////////////////////////////////////////////////////////////////// +/// \brief Structure containing information about the adapter display manner. +/// +/// This structure is used to store adapter display manner information +/// This information can be returned to the user. Alternatively, it can be used to access various driver calls to +/// fetch various display device related display manner settings upon the user's request. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLAdapterDisplayCap { + /// The Persistent logical Adapter Index. int iAdapterIndex; + /// The bit mask identifies the number of bits AdapterDisplayCap is currently using. Sum all the bits defined in ADL_ADAPTER_DISPLAYCAP_XXX int iAdapterDisplayCapMask; + /// The bit mask identifies the status. Refer to ADL_ADAPTER_DISPLAYCAP_XXX int iAdapterDisplayCapValue; } ADLAdapterDisplayCap, *LPADLAdapterDisplayCap; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about display mapping. +/// +/// This structure is used to store the display mapping data such as display manner. +/// For displays with horizontal or vertical stretch manner, +/// this structure also stores the display order, display row, and column data. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDisplayMap { +/// The current display map index. It is the OS desktop index. For example, if the OS index 1 is showing clone mode, the display map will be 1. int iDisplayMapIndex; +/// The Display Mode for the current map ADLMode displayMode; +/// The number of display targets belongs to this map\n int iNumDisplayTarget; +/// The first target array index in the Target array\n int iFirstDisplayTargetArrayIndex; - int iDisplayMapMask; +/// The bit mask identifies the number of bits DisplayMap is currently using. It is the sum of all the bit definitions defined in ADL_DISPLAY_DISPLAYMAP_MANNER_xxx. + int iDisplayMapMask; +///The bit mask identifies the display status. The detailed definition is in ADL_DISPLAY_DISPLAYMAP_MANNER_xxx. int iDisplayMapValue; } ADLDisplayMap, *LPADLDisplayMap; +///////////////////////////////////////////////////////////////////////////////////////////// +/// \brief Structure containing information about the display device possible map for one GPU +/// +/// This structure is used to store the display device possible map +/// This information can be returned to the user. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLPossibleMap { + /// The current PossibleMap index. Each PossibleMap is assigned an index int iIndex; + /// The adapter index identifying the GPU for which to validate these Maps & Targets int iAdapterIndex; + /// Number of display Maps for this GPU to be validated int iNumDisplayMap; + /// The display Maps list to validate ADLDisplayMap* displayMap; + /// the number of display Targets for these display Maps int iNumDisplayTarget; + /// The display Targets list for these display Maps to be validated. ADLDisplayTarget* displayTarget; } ADLPossibleMap, *LPADLPossibleMap; +///////////////////////////////////////////////////////////////////////////////////////////// +/// \brief Structure containing information about display possible mapping. +/// +/// This structure is used to store the display possible mapping's controller index for the current display. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLPossibleMapping { - int iDisplayIndex; - int iDisplayControllerIndex; - int iDisplayMannerSupported; + int iDisplayIndex; ///< The display index. Each display is assigned an index. + int iDisplayControllerIndex; ///< The controller index to which display is mapped. + int iDisplayMannerSupported; ///< The supported display manner. } ADLPossibleMapping, *LPADLPossibleMapping; +///////////////////////////////////////////////////////////////////////////////////////////// +/// \brief Structure containing information about the validated display device possible map result. +/// +/// This structure is used to store the validated display device possible map result +/// This information can be returned to the user. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLPossibleMapResult { + /// The current display map index. It is the OS Desktop index. For example, OS Index 1 showing clone mode. The Display Map will be 1. int iIndex; // The bit mask identifies the number of bits PossibleMapResult is currently using. It will be the sum all the bit definitions defined in ADL_DISPLAY_POSSIBLEMAPRESULT_VALID. int iPossibleMapResultMask; + /// The bit mask identifies the possible map result. The detail definition is defined in ADL_DISPLAY_POSSIBLEMAPRESULT_XXX. int iPossibleMapResultValue; } ADLPossibleMapResult, *LPADLPossibleMapResult; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the display SLS Grid information. +/// +/// This structure is used to store the display SLS Grid information. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLSLSGrid { +/// The Adapter index. int iAdapterIndex; +/// The grid index. int iSLSGridIndex; +/// The grid row. int iSLSGridRow; +/// The grid column. int iSLSGridColumn; +/// The grid bit mask identifies the number of bits DisplayMap is currently using. Sum of all bits defined in ADL_DISPLAY_SLSGRID_ORIENTATION_XXX int iSLSGridMask; +/// The grid bit value identifies the display status. Refer to ADL_DISPLAY_SLSGRID_ORIENTATION_XXX int iSLSGridValue; } ADLSLSGrid, *LPADLSLSGrid; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the display SLS Map information. +/// +/// This structure is used to store the display SLS Map information. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLSLSMap { + /// The Adapter Index int iAdapterIndex; + /// The current display map index. It is the OS Desktop index. For example, OS Index 1 showing clone mode. The Display Map will be 1. int iSLSMapIndex; + /// Indicate the current grid ADLSLSGrid grid; + /// OS surface index int iSurfaceMapIndex; - int iOrientation; + /// Screen orientation. E.g., 0, 90, 180, 270 + int iOrientation; + /// The number of display targets belongs to this map int iNumSLSTarget; + /// The first target array index in the Target array int iFirstSLSTargetArrayIndex; + /// The number of native modes belongs to this map int iNumNativeMode; + /// The first native mode array index in the native mode array int iFirstNativeModeArrayIndex; + /// The number of bezel modes belongs to this map int iNumBezelMode; + /// The first bezel mode array index in the native mode array int iFirstBezelModeArrayIndex; + /// The number of bezel offsets belongs to this map int iNumBezelOffset; + /// The first bezel offset array index in the int iFirstBezelOffsetArrayIndex; + /// The bit mask identifies the number of bits DisplayMap is currently using. Sum all the bit definitions defined in ADL_DISPLAY_SLSMAP_XXX. int iSLSMapMask; + /// The bit mask identifies the display map status. Refer to ADL_DISPLAY_SLSMAP_XXX int iSLSMapValue; } ADLSLSMap, *LPADLSLSMap; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the display SLS Offset information. +/// +/// This structure is used to store the display SLS Offset information. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLSLSOffset { + /// The Adapter Index int iAdapterIndex; + /// The current display map index. It is the OS Desktop index. For example, OS Index 1 showing clone mode. The Display Map will be 1. int iSLSMapIndex; + /// The Display ID. ADLDisplayID displayID; + /// SLS Bezel Mode Index int iBezelModeIndex; + /// SLS Bezel Offset X int iBezelOffsetX; + /// SLS Bezel Offset Y int iBezelOffsetY; + /// SLS Display Width int iDisplayWidth; + /// SLS Display Height int iDisplayHeight; + /// The bit mask identifies the number of bits Offset is currently using. int iBezelOffsetMask; + /// The bit mask identifies the display status. int iBezelffsetValue; } ADLSLSOffset, *LPADLSLSOffset; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the display SLS Mode information. +/// +/// This structure is used to store the display SLS Mode information. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLSLSMode { + /// The Adapter Index int iAdapterIndex; + /// The current display map index. It is the OS Desktop index. For example, OS Index 1 showing clone mode. The Display Map will be 1. int iSLSMapIndex; + /// The mode index int iSLSModeIndex; + /// The mode for this map. ADLMode displayMode; + /// The bit mask identifies the number of bits Mode is currently using. int iSLSNativeModeMask; + /// The bit mask identifies the display status. int iSLSNativeModeValue; } ADLSLSMode, *LPADLSLSMode; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the display Possible SLS Map information. +/// +/// This structure is used to store the display Possible SLS Map information. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLPossibleSLSMap { + /// The current display map index. It is the OS Desktop index. + /// For example, OS Index 1 showing clone mode. The Display Map will be 1. int iSLSMapIndex; + /// Number of display map to be validated. int iNumSLSMap; + /// The display map list for validation ADLSLSMap* lpSLSMap; + /// the number of display map config to be validated. int iNumSLSTarget; + /// The display target list for validation. ADLDisplayTarget* lpDisplayTarget; } ADLPossibleSLSMap, *LPADLPossibleSLSMap; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the SLS targets. +/// +/// This structure is used to store the SLS targets information. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLSLSTarget { + /// the logic adapter index int iAdapterIndex; + /// The SLS map index int iSLSMapIndex; + /// The target ID ADLDisplayTarget displayTarget; + /// Target postion X in SLS grid int iSLSGridPositionX; + /// Target postion Y in SLS grid int iSLSGridPositionY; + /// The view size width, height and rotation angle per SLS Target ADLMode viewSize; + /// The bit mask identifies the bits in iSLSTargetValue are currently used int iSLSTargetMask; + /// The bit mask identifies status info. It is for function extension purpose int iSLSTargetValue; } ADLSLSTarget, *LPADLSLSTarget; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the Adapter offset stepping size. +/// +/// This structure is used to store the Adapter offset stepping size information. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLBezelOffsetSteppingSize { + /// the logic adapter index int iAdapterIndex; + /// The SLS map index int iSLSMapIndex; + /// Bezel X stepping size offset int iBezelOffsetSteppingSizeX; + /// Bezel Y stepping size offset int iBezelOffsetSteppingSizeY; + /// Identifies the bits this structure is currently using. It will be the total OR of all the bit definitions. int iBezelOffsetSteppingSizeMask; + /// Bit mask identifies the display status. int iBezelOffsetSteppingSizeValue; } ADLBezelOffsetSteppingSize, *LPADLBezelOffsetSteppingSize; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the overlap offset info for all the displays for each SLS mode. +/// +/// This structure is used to store the no. of overlapped modes for each SLS Mode once user finishes the configuration from Overlap Widget +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLSLSOverlappedMode { + /// the SLS mode for which the overlap is configured ADLMode SLSMode; + /// the number of target displays in SLS. int iNumSLSTarget; + /// the first target array index in the target array int iFirstTargetArrayIndex; }ADLSLSTargetOverlap, *LPADLSLSTargetOverlap; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about driver supported PowerExpress Config Caps +/// +/// This structure is used to store the driver supported PowerExpress Config Caps +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLPXConfigCaps { + /// The Persistent logical Adapter Index. int iAdapterIndex; + /// The bit mask identifies the number of bits PowerExpress Config Caps is currently using. It is the sum of all the bit definitions defined in ADL_PX_CONFIGCAPS_XXXX /ref define_powerxpress_constants. int iPXConfigCapMask; + /// The bit mask identifies the PowerExpress Config Caps value. The detailed definition is in ADL_PX_CONFIGCAPS_XXXX /ref define_powerxpress_constants. int iPXConfigCapValue; } ADLPXConfigCaps, *LPADLPXConfigCaps; +///////////////////////////////////////////////////////////////////////////////////////// +///\brief Enum containing PX or HG type +/// +/// This enum is used to get PX or hG type +/// +/// \nosubgrouping +////////////////////////////////////////////////////////////////////////////////////////// typedef enum ADLPxType { - //Not AMD related PX/HG or not PX or HG at all - ADL_PX_NONE = 0, - //A+A PX - ADL_SWITCHABLE_AMDAMD = 1, - // A+A HG - ADL_HG_AMDAMD = 2, - //A+I PX - ADL_SWITCHABLE_AMDOTHER = 3, - //A+I HG - ADL_HG_AMDOTHER = 4, + //Not AMD related PX/HG or not PX or HG at all + ADL_PX_NONE = 0, + //A+A PX + ADL_SWITCHABLE_AMDAMD = 1, + // A+A HG + ADL_HG_AMDAMD = 2, + //A+I PX + ADL_SWITCHABLE_AMDOTHER = 3, + //A+I HG + ADL_HG_AMDOTHER = 4, }ADLPxType; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about an application +/// +/// This structure is used to store basic information of an application +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLApplicationData { + /// Path Name char strPathName[ADL_MAX_PATH]; + /// File Name char strFileName[ADL_APP_PROFILE_FILENAME_LENGTH]; + /// Creation timestamp char strTimeStamp[ADL_APP_PROFILE_TIMESTAMP_LENGTH]; + /// Version char strVersion[ADL_APP_PROFILE_VERSION_LENGTH]; }ADLApplicationData; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about an application +/// +/// This structure is used to store basic information of an application +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLApplicationDataX2 { + /// Path Name wchar_t strPathName[ADL_MAX_PATH]; + /// File Name wchar_t strFileName[ADL_APP_PROFILE_FILENAME_LENGTH]; + /// Creation timestamp wchar_t strTimeStamp[ADL_APP_PROFILE_TIMESTAMP_LENGTH]; + /// Version wchar_t strVersion[ADL_APP_PROFILE_VERSION_LENGTH]; }ADLApplicationDataX2; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about an application +/// +/// This structure is used to store basic information of an application including process id +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLApplicationDataX3 { + /// Path Name wchar_t strPathName[ADL_MAX_PATH]; + /// File Name wchar_t strFileName[ADL_APP_PROFILE_FILENAME_LENGTH]; + /// Creation timestamp wchar_t strTimeStamp[ADL_APP_PROFILE_TIMESTAMP_LENGTH]; + /// Version wchar_t strVersion[ADL_APP_PROFILE_VERSION_LENGTH]; //Application Process id unsigned int iProcessId; }ADLApplicationDataX3; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information of a property of an application profile +/// +/// This structure is used to store property information of an application profile +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct PropertyRecord { + /// Property Name char strName [ADL_APP_PROFILE_PROPERTY_LENGTH]; + /// Property Type ADLProfilePropertyType eType; + /// Data Size in bytes int iDataSize; + /// Property Value, can be any data type unsigned char uData[1]; }PropertyRecord; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about an application profile +/// +/// This structure is used to store information of an application profile +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLApplicationProfile { + /// Number of properties int iCount; + /// Buffer to store all property records PropertyRecord record[1]; }ADLApplicationProfile; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about an OD5 Power Control feature +/// +/// This structure is used to store information of an Power Control feature +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLPowerControlInfo { - int iMinValue; - int iMaxValue; - int iStepValue; -} ADLPowerControlInfo; +/// Minimum value. +int iMinValue; +/// Maximum value. +int iMaxValue; +/// The minimum change in between minValue and maxValue. +int iStepValue; + } ADLPowerControlInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about an controller mode +/// +/// This structure is used to store information of an controller mode +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLControllerMode { + /// This falg indicates actions that will be applied by set viewport + /// The value can be a combination of ADL_CONTROLLERMODE_CM_MODIFIER_VIEW_POSITION, + /// ADL_CONTROLLERMODE_CM_MODIFIER_VIEW_PANLOCK and ADL_CONTROLLERMODE_CM_MODIFIER_VIEW_SIZE int iModifiers; + /// Horizontal view starting position int iViewPositionCx; + /// Vertical view starting position int iViewPositionCy; + /// Horizontal left panlock position int iViewPanLockLeft; + /// Horizontal right panlock position int iViewPanLockRight; + /// Vertical top panlock position int iViewPanLockTop; + /// Vertical bottom panlock position int iViewPanLockBottom; + /// View resolution in pixels (width) int iViewResolutionCx; + /// View resolution in pixels (hight) int iViewResolutionCy; }ADLControllerMode; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about a display +/// +/// This structure is used to store information about a display +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDisplayIdentifier { + /// ADL display index long ulDisplayIndex; + /// manufacturer ID of the display long ulManufacturerId; + /// product ID of the display long ulProductId; + /// serial number of the display long ulSerialNo; } ADLDisplayIdentifier; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive 6 clock range +/// +/// This structure is used to store information about Overdrive 6 clock range +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLOD6ParameterRange { + /// The starting value of the clock range int iMin; + /// The ending value of the clock range int iMax; + /// The minimum increment between clock values int iStep; } ADLOD6ParameterRange; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive 6 capabilities +/// +/// This structure is used to store information about Overdrive 6 capabilities +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLOD6Capabilities { + /// Contains a bitmap of the OD6 capability flags. Possible values: \ref ADL_OD6_CAPABILITY_SCLK_CUSTOMIZATION, + /// \ref ADL_OD6_CAPABILITY_MCLK_CUSTOMIZATION, \ref ADL_OD6_CAPABILITY_GPU_ACTIVITY_MONITOR int iCapabilities; + /// Contains a bitmap indicating the power states + /// supported by OD6. Currently only the performance state + /// is supported. Possible Values: \ref ADL_OD6_SUPPORTEDSTATE_PERFORMANCE int iSupportedStates; + /// Number of levels. OD6 will always use 2 levels, which describe + /// the minimum to maximum clock ranges. + /// The 1st level indicates the minimum clocks, and the 2nd level + /// indicates the maximum clocks. int iNumberOfPerformanceLevels; + /// Contains the hard limits of the sclk range. Overdrive + /// clocks cannot be set outside this range. ADLOD6ParameterRange sEngineClockRange; + /// Contains the hard limits of the mclk range. Overdrive + /// clocks cannot be set outside this range. ADLOD6ParameterRange sMemoryClockRange; + /// Value for future extension int iExtValue; + /// Mask for future extension int iExtMask; } ADLOD6Capabilities; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive 6 clock values. +/// +/// This structure is used to store information about Overdrive 6 clock values. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLOD6PerformanceLevel { + /// Engine (core) clock. int iEngineClock; + /// Memory clock. int iMemoryClock; } ADLOD6PerformanceLevel; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive 6 clocks. +/// +/// This structure is used to store information about Overdrive 6 clocks. This is a +/// variable-sized structure. iNumberOfPerformanceLevels indicate how many elements +/// are contained in the aLevels array. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLOD6StateInfo { + /// Number of levels. OD6 uses clock ranges instead of discrete performance levels. + /// iNumberOfPerformanceLevels is always 2. The 1st level indicates the minimum clocks + /// in the range. The 2nd level indicates the maximum clocks in the range. int iNumberOfPerformanceLevels; + /// Value for future extension int iExtValue; + /// Mask for future extension int iExtMask; + /// Variable-sized array of levels. + /// The number of elements in the array is specified by iNumberofPerformanceLevels. ADLOD6PerformanceLevel aLevels [1]; } ADLOD6StateInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about current Overdrive 6 performance status. +/// +/// This structure is used to store information about current Overdrive 6 performance status. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLOD6CurrentStatus { + /// Current engine clock in 10 KHz. int iEngineClock; + /// Current memory clock in 10 KHz. int iMemoryClock; + /// Current GPU activity in percent. This + /// indicates how "busy" the GPU is. int iActivityPercent; + /// Not used. Reserved for future use. int iCurrentPerformanceLevel; + /// Current PCI-E bus speed int iCurrentBusSpeed; + /// Current PCI-E bus # of lanes int iCurrentBusLanes; + /// Maximum possible PCI-E bus # of lanes int iMaximumBusLanes; + /// Value for future extension int iExtValue; + /// Mask for future extension int iExtMask; } ADLOD6CurrentStatus; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive 6 thermal contoller capabilities +/// +/// This structure is used to store information about Overdrive 6 thermal controller capabilities +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLOD6ThermalControllerCaps { + /// Contains a bitmap of thermal controller capability flags. Possible values: \ref ADL_OD6_TCCAPS_THERMAL_CONTROLLER, \ref ADL_OD6_TCCAPS_FANSPEED_CONTROL, + /// \ref ADL_OD6_TCCAPS_FANSPEED_PERCENT_READ, \ref ADL_OD6_TCCAPS_FANSPEED_PERCENT_WRITE, \ref ADL_OD6_TCCAPS_FANSPEED_RPM_READ, \ref ADL_OD6_TCCAPS_FANSPEED_RPM_WRITE int iCapabilities; + /// Minimum fan speed expressed as a percentage int iFanMinPercent; + /// Maximum fan speed expressed as a percentage int iFanMaxPercent; + /// Minimum fan speed expressed in revolutions-per-minute int iFanMinRPM; + /// Maximum fan speed expressed in revolutions-per-minute int iFanMaxRPM; + /// Value for future extension int iExtValue; + /// Mask for future extension int iExtMask; } ADLOD6ThermalControllerCaps; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive 6 fan speed information +/// +/// This structure is used to store information about Overdrive 6 fan speed information +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLOD6FanSpeedInfo { + /// Contains a bitmap of the valid fan speed type flags. Possible values: \ref ADL_OD6_FANSPEED_TYPE_PERCENT, \ref ADL_OD6_FANSPEED_TYPE_RPM, \ref ADL_OD6_FANSPEED_USER_DEFINED int iSpeedType; + /// Contains current fan speed in percent (if valid flag exists in iSpeedType) int iFanSpeedPercent; + /// Contains current fan speed in RPM (if valid flag exists in iSpeedType) int iFanSpeedRPM; + /// Value for future extension int iExtValue; + /// Mask for future extension int iExtMask; } ADLOD6FanSpeedInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive 6 fan speed value +/// +/// This structure is used to store information about Overdrive 6 fan speed value +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLOD6FanSpeedValue { + /// Indicates the units of the fan speed. Possible values: \ref ADL_OD6_FANSPEED_TYPE_PERCENT, \ref ADL_OD6_FANSPEED_TYPE_RPM int iSpeedType; + /// Fan speed value (units as indicated above) int iFanSpeed; + /// Value for future extension int iExtValue; + /// Mask for future extension int iExtMask; } ADLOD6FanSpeedValue; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive 6 PowerControl settings. +/// +/// This structure is used to store information about Overdrive 6 PowerControl settings. +/// PowerControl is the feature which allows the performance characteristics of the GPU +/// to be adjusted by changing the PowerTune power limits. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLOD6PowerControlInfo { + /// The minimum PowerControl adjustment value int iMinValue; + /// The maximum PowerControl adjustment value int iMaxValue; + /// The minimum difference between PowerControl adjustment values int iStepValue; + /// Value for future extension int iExtValue; + /// Mask for future extension int iExtMask; } ADLOD6PowerControlInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive 6 PowerControl settings. +/// +/// This structure is used to store information about Overdrive 6 PowerControl settings. +/// PowerControl is the feature which allows the performance characteristics of the GPU +/// to be adjusted by changing the PowerTune power limits. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLOD6VoltageControlInfo { + /// The minimum VoltageControl adjustment value int iMinValue; + /// The maximum VoltageControl adjustment value int iMaxValue; + /// The minimum difference between VoltageControl adjustment values int iStepValue; + /// Value for future extension int iExtValue; + /// Mask for future extension int iExtMask; } ADLOD6VoltageControlInfo; +//////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing ECC statistics namely SEC counts and DED counts +/// Single error count - count of errors that can be corrected +/// Doubt Error Detect - count of errors that cannot be corrected +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLECCData { // Single error count - count of errors that can be corrected @@ -1132,60 +2327,83 @@ typedef struct ADLECCData int iDed; } ADLECCData; +/// \brief Handle to ADL client context. +/// +/// ADL clients obtain context handle from initial call to \ref ADL2_Main_Control_Create. +/// Clients have to pass the handle to each subsequent ADL call and finally destroy +/// the context with call to \ref ADL2_Main_Control_Destroy +/// \nosubgrouping typedef void *ADL_CONTEXT_HANDLE; +/// \brief Handle to ADL Frame Monitor Token. +/// +/// Frame Monitor clients obtain handle from initial call to \ref ADL2_Adapter_FrameMetrics_FrameDuration_Enable +/// Clients have to pass the handle to each subsequent ADL call to \ref ADL2_Adapter_FrameMetrics_FrameDuration_Get +/// and finally destroy the token with call to \ref ADL2_Adapter_FrameMetrics_FrameDuration_Disable +/// \nosubgrouping typedef void *ADL_FRAME_DURATION_HANDLE; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing the display mode definition used per controller. +/// +/// This structure is used to store the display mode definition used per controller. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDisplayModeX2 { - int iWidth; - int iHeight; - int iScanType; - int iRefreshRate; - int iTimingStandard; +/// Horizontal resolution (in pixels). + int iWidth; +/// Vertical resolution (in lines). + int iHeight; +/// Interlaced/Progressive. The value will be set for Interlaced as ADL_DL_TIMINGFLAG_INTERLACED. If not set it is progressive. Refer define_detailed_timing_flags. + int iScanType; +/// Refresh rate. + int iRefreshRate; +/// Timing Standard. Refer define_modetiming_standard. + int iTimingStandard; } ADLDisplayModeX2; typedef enum ADLAppProcessState { - APP_PROC_INVALID = 0, // Invalid Application - APP_PROC_PREMPTION = 1, // The Application is being set up for Process Creation - APP_PROC_CREATION = 2, // The Application's Main Process is created by the OS - APP_PROC_READ = 3, // The Application's Data is ready to be read - APP_PROC_WAIT = 4, // The Application is waiting for Timeout or Notification to Resume - APP_PROC_RUNNING = 5, // The Application is running - APP_PROC_TERMINATE = 6 // The Application is about to terminate + APP_PROC_INVALID = 0, // Invalid Application + APP_PROC_PREMPTION = 1, // The Application is being set up for Process Creation + APP_PROC_CREATION = 2, // The Application's Main Process is created by the OS + APP_PROC_READ = 3, // The Application's Data is ready to be read + APP_PROC_WAIT = 4, // The Application is waiting for Timeout or Notification to Resume + APP_PROC_RUNNING = 5, // The Application is running + APP_PROC_TERMINATE = 6 // The Application is about to terminate }ADLAppProcessState; typedef enum ADLAppInterceptionListType { - ADL_INVALID_FORMAT = 0, - ADL_IMAGEFILEFORMAT = 1, - ADL_ENVVAR = 2 + ADL_INVALID_FORMAT = 0, + ADL_IMAGEFILEFORMAT = 1, + ADL_ENVVAR = 2 }ADLAppInterceptionListType; typedef struct ADLAppInterceptionInfo { - wchar_t AppName[ADL_MAX_PATH]; // the file name of the application or env var - unsigned int ProcessId; - ADLAppInterceptionListType AppFormat; - ADLAppProcessState AppState; + wchar_t AppName[ADL_MAX_PATH]; // the file name of the application or env var + unsigned int ProcessId; + ADLAppInterceptionListType AppFormat; + ADLAppProcessState AppState; } ADLAppInterceptionInfo; typedef enum ADL_AP_DATABASE // same as _SHARED_AP_DATABASE in "inc/shared/shared_escape.h" { - ADL_AP_DATABASE__SYSTEM, - ADL_AP_DATABASE__USER, - ADL_AP_DATABASE__OEM + ADL_AP_DATABASE__SYSTEM, + ADL_AP_DATABASE__USER, + ADL_AP_DATABASE__OEM } ADL_AP_DATABASE; typedef struct ADLAppInterceptionInfoX2 { - wchar_t AppName[ADL_MAX_PATH]; // the file name of the application or env var - unsigned int ProcessId; - unsigned int WaitForResumeNeeded; - wchar_t CommandLine[ADL_MAX_PATH]; // The command line on app start/stop event - ADLAppInterceptionListType AppFormat; - ADLAppProcessState AppState; + wchar_t AppName[ADL_MAX_PATH]; // the file name of the application or env var + unsigned int ProcessId; + unsigned int WaitForResumeNeeded; + wchar_t CommandLine[ADL_MAX_PATH]; // The command line on app start/stop event + ADLAppInterceptionListType AppFormat; + ADLAppProcessState AppState; } ADLAppInterceptionInfoX2; typedef struct ADLAppInterceptionInfoX3 @@ -1199,97 +2417,219 @@ typedef struct ADLAppInterceptionInfoX3 ADLAppProcessState AppState; } ADLAppInterceptionInfoX3; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information info for a property record in a profile +/// +/// This structure is used to store info for a property record in a profile +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLPropertyRecordCreate { - wchar_t * strPropertyName; - ADLProfilePropertyType eType; - // Value of the property - wchar_t * strPropertyValue; + /// Name of the property + wchar_t * strPropertyName; + /// Data type of the property + ADLProfilePropertyType eType; + // Value of the property + wchar_t * strPropertyValue; } ADLPropertyRecordCreate; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information info for an application record +/// +/// This structure is used to store info for an application record +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLApplicationRecord { + /// Title of the application wchar_t * strTitle; + /// File path of the application wchar_t * strPathName; + /// File name of the application wchar_t * strFileName; + /// File versin the application wchar_t * strVersion; + /// Nostes on the application wchar_t * strNotes; + /// Driver area which the application uses wchar_t * strArea; + /// Name of profile assigned to the application wchar_t * strProfileName; // Source where this application record come from ADL_AP_DATABASE recordSource; } ADLApplicationRecord; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive 6 extension capabilities +/// +/// This structure is used to store information about Overdrive 6 extension capabilities +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLOD6CapabilitiesEx { + /// Contains a bitmap of the OD6 extension capability flags. Possible values: \ref ADL_OD6_CAPABILITY_SCLK_CUSTOMIZATION, + /// \ref ADL_OD6_CAPABILITY_MCLK_CUSTOMIZATION, \ref ADL_OD6_CAPABILITY_GPU_ACTIVITY_MONITOR, + /// \ref ADL_OD6_CAPABILITY_POWER_CONTROL, \ref ADL_OD6_CAPABILITY_VOLTAGE_CONTROL, \ref ADL_OD6_CAPABILITY_PERCENT_ADJUSTMENT, + //// \ref ADL_OD6_CAPABILITY_THERMAL_LIMIT_UNLOCK int iCapabilities; + /// The Power states that support clock and power customization. Only performance state is currently supported. + /// Possible Values: \ref ADL_OD6_SUPPORTEDSTATE_PERFORMANCE int iSupportedStates; + /// Returns the hard limits of the SCLK overdrive adjustment range. Overdrive clocks should not be adjusted outside of this range. The values are specified as +/- percentages. ADLOD6ParameterRange sEngineClockPercent; + /// Returns the hard limits of the MCLK overdrive adjustment range. Overdrive clocks should not be adjusted outside of this range. The values are specified as +/- percentages. ADLOD6ParameterRange sMemoryClockPercent; + /// Returns the hard limits of the Power Limit adjustment range. Power limit should not be adjusted outside this range. The values are specified as +/- percentages. ADLOD6ParameterRange sPowerControlPercent; + /// Reserved for future expansion of the structure. int iExtValue; + /// Reserved for future expansion of the structure. int iExtMask; } ADLOD6CapabilitiesEx; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive 6 extension state information +/// +/// This structure is used to store information about Overdrive 6 extension state information +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLOD6StateEx { + /// The current engine clock adjustment value, specified as a +/- percent. int iEngineClockPercent; + /// The current memory clock adjustment value, specified as a +/- percent. int iMemoryClockPercent; + /// The current power control adjustment value, specified as a +/- percent. int iPowerControlPercent; + /// Reserved for future expansion of the structure. int iExtValue; + /// Reserved for future expansion of the structure. int iExtMask; } ADLOD6StateEx; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive 6 extension recommended maximum clock adjustment values +/// +/// This structure is used to store information about Overdrive 6 extension recommended maximum clock adjustment values +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLOD6MaxClockAdjust { + /// The recommended maximum engine clock adjustment in percent, for the specified power limit value. int iEngineClockMax; + /// The recommended maximum memory clock adjustment in percent, for the specified power limit value. + /// Currently the memory is independent of the Power Limit setting, so iMemoryClockMax will always return the maximum + /// possible adjustment value. This field is here for future enhancement in case we add a dependency between Memory Clock + /// adjustment and Power Limit setting. int iMemoryClockMax; + /// Reserved for future expansion of the structure. int iExtValue; + /// Reserved for future expansion of the structure. int iExtMask; } ADLOD6MaxClockAdjust; +//////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing the Connector information +/// +/// this structure is used to get the connector information like length, positions & etc. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLConnectorInfo { + ///index of the connector(0-based) int iConnectorIndex; + ///used for disply identification/ordering int iConnectorId; + ///index of the slot, 0-based index. int iSlotIndex; + ///Type of the connector. \ref define_connector_types int iType; + ///Position of the connector(in millimeters), from the right side of the slot. int iOffset; + ///Length of the connector(in millimeters). int iLength; } ADLConnectorInfo; +//////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing the slot information +/// +/// this structure is used to get the slot information like length of the slot, no of connectors on the slot & etc. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLBracketSlotInfo { + ///index of the slot, 0-based index. int iSlotIndex; + ///length of the slot(in millimeters). int iLength; + ///width of the slot(in millimeters). int iWidth; } ADLBracketSlotInfo; +//////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing MST branch information +/// +/// this structure is used to store the MST branch information +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLMSTRad { + ///depth of the link. int iLinkNumber; + /// Relative address, address scheme starts from source side char rad[ADL_MAX_RAD_LINK_COUNT]; } ADLMSTRad; +//////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing port information +/// +/// this structure is used to get the display or MST branch information +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDevicePort { + ///index of the connector. int iConnectorIndex; + ///Relative MST address. If MST RAD contains 0 it means DP or Root of the MST topology. For non DP connectors MST RAD is ignored. ADLMSTRad aMSTRad; } ADLDevicePort; +//////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing supported connection types and properties +/// +/// this structure is used to get the supported connection types and supported properties of given connector +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLSupportedConnections { + ///Bit vector of supported connections. Bitmask is defined in constants section. \ref define_connection_types int iSupportedConnections; + ///Array of bitvectors. Each bit vector represents supported properties for one connection type. Index of this array is connection type (bit number in mask). int iSupportedProperties[ADL_MAX_CONNECTION_TYPES]; } ADLSupportedConnections; +//////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing connection state of the connector +/// +/// this structure is used to get the current Emulation status and mode of the given connector +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLConnectionState { + ///The value is bit vector. Each bit represents status. See masks constants for details. \ref define_emulation_status int iEmulationStatus; + ///It contains information about current emulation mode. See constants for details. \ref define_emulation_mode int iEmulationMode; + ///If connection is active it will contain display id, otherwise CWDDEDI_INVALID_DISPLAY_INDEX int iDisplayIndex; } ADLConnectionState; +//////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing connection properties information +/// +/// this structure is used to retrieve the properties of connection type +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLConnectionProperties { //Bit vector. Represents actual properties. Supported properties for specific connection type. \ref define_connection_properties @@ -1302,28 +2642,55 @@ typedef struct ADLConnectionProperties int iColorDepth; //3D capabilities. It could be used for some dongles. For instance: alternate framepack. Value of this property is bit vector. int iStereo3DCaps; + ///Output Bandwidth. Could be used for MST branch, DP or DP Active dongle. \ref define_linkrate_constants int iOutputBandwidth; } ADLConnectionProperties; +//////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing connection information +/// +/// this structure is used to retrieve the data from driver which includes +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLConnectionData { + ///Connection type. based on the connection type either iNumberofPorts or IDataSize,EDIDdata is valid, \ref define_connection_types int iConnectionType; + ///Specifies the connection properties. ADLConnectionProperties aConnectionProperties; + ///Number of ports int iNumberofPorts; + ///Number of Active Connections int iActiveConnections; + ///actual size of EDID data block size. int iDataSize; + ///EDID Data char EdidData[ADL_MAX_DISPLAY_EDID_DATA_SIZE]; } ADLConnectionData; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about an controller mode including Number of Connectors +/// +/// This structure is used to store information of an controller mode +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLAdapterCapsX2 { + /// AdapterID for this adapter int iAdapterID; + /// Number of controllers for this adapter int iNumControllers; + /// Number of displays for this adapter int iNumDisplays; + /// Number of overlays for this adapter int iNumOverlays; + /// Number of GLSyncConnectors int iNumOfGLSyncConnectors; + /// The bit mask identifies the adapter caps int iCapsMask; + /// The bit identifies the adapter caps \ref define_adapter_caps int iCapsValue; + /// Number of Connectors for this adapter int iNumConnectors; }ADLAdapterCapsX2; @@ -1345,6 +2712,12 @@ typedef union _ADL_ECC_EDC_FLAG unsigned int u32All; }ADL_ECC_EDC_FLAG; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about EDC Error Record +/// +/// This structure is used to store EDC Error Record +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLErrorRecord { // Severity of error @@ -1407,6 +2780,12 @@ typedef struct ADL_ERROR_INJECTION_DATA ADL_ERROR_PATTERN errorPattern; }ADL_ERROR_INJECTION_DATA; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about EDC Error Injection +/// +/// This structure is used to store EDC Error Injection +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLErrorInjection { ADL_EDC_BLOCK_ID blockId; @@ -1420,16 +2799,35 @@ typedef struct ADLErrorInjectionX2 ADL_ERROR_INJECTION_DATA errorInjectionData; }ADLErrorInjectionX2; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing per display FreeSync capability information. +/// +/// This structure is used to store the FreeSync capability of both the display and +/// the GPU the display is connected to. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLFreeSyncCap { + /// FreeSync capability flags. \ref define_freesync_caps int iCaps; + /// Reports minimum FreeSync refresh rate supported by the display in micro hertz int iMinRefreshRateInMicroHz; + /// Reports maximum FreeSync refresh rate supported by the display in micro hertz int iMaxRefreshRateInMicroHz; + /// Index of FreeSync Label to use: ADL_FREESYNC_LABEL_* unsigned char ucLabelIndex; + /// Reserved char cReserved[3]; int iReserved[4]; } ADLFreeSyncCap; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing per display Display Connectivty Experience Settings +/// +/// This structure is used to store the Display Connectivity Experience settings of a +/// display +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDceSettings { DceSettingsType type; // Defines which structure is in the union below @@ -1456,83 +2854,188 @@ typedef struct ADLDceSettings int iReserved[15]; } ADLDceSettings; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Graphic Core +/// +/// This structure is used to get Graphic Core Info +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLGraphicCoreInfo { + /// indicate the graphic core generation int iGCGen; union { + /// Total number of CUs. Valid for GCN (iGCGen == GCN) int iNumCUs; + /// Total number of WGPs. Valid for RDNA (iGCGen == RDNA) int iNumWGPs; }; union { + /// Number of processing elements per CU. Valid for GCN (iGCGen == GCN) int iNumPEsPerCU; + /// Number of processing elements per WGP. Valid for RDNA (iGCGen == RDNA) int iNumPEsPerWGP; }; + /// Total number of SIMDs. Valid for Pre GCN (iGCGen == Pre-GCN) int iNumSIMDs; + /// Total number of ROPs. Valid for both GCN and Pre GCN int iNumROPs; + /// reserved for future use int iReserved[11]; }ADLGraphicCoreInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive N clock range +/// +/// This structure is used to store information about Overdrive N clock range +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLODNParameterRange { + /// The starting value of the clock range int iMode; + /// The starting value of the clock range int iMin; + /// The ending value of the clock range int iMax; + /// The minimum increment between clock values int iStep; + /// The default clock values int iDefault; } ADLODNParameterRange; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive N capabilities +/// +/// This structure is used to store information about Overdrive N capabilities +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLODNCapabilities { + /// Number of levels which describe the minimum to maximum clock ranges. + /// The 1st level indicates the minimum clocks, and the 2nd level + /// indicates the maximum clocks. int iMaximumNumberOfPerformanceLevels; + /// Contains the hard limits of the sclk range. Overdrive + /// clocks cannot be set outside this range. ADLODNParameterRange sEngineClockRange; + /// Contains the hard limits of the mclk range. Overdrive + /// clocks cannot be set outside this range. ADLODNParameterRange sMemoryClockRange; + /// Contains the hard limits of the vddc range. Overdrive + /// clocks cannot be set outside this range. ADLODNParameterRange svddcRange; + /// Contains the hard limits of the power range. Overdrive + /// clocks cannot be set outside this range. ADLODNParameterRange power; + /// Contains the hard limits of the power range. Overdrive + /// clocks cannot be set outside this range. ADLODNParameterRange powerTuneTemperature; + /// Contains the hard limits of the Temperature range. Overdrive + /// clocks cannot be set outside this range. ADLODNParameterRange fanTemperature; + /// Contains the hard limits of the Fan range. Overdrive + /// clocks cannot be set outside this range. ADLODNParameterRange fanSpeed; + /// Contains the hard limits of the Fan range. Overdrive + /// clocks cannot be set outside this range. ADLODNParameterRange minimumPerformanceClock; } ADLODNCapabilities; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive N capabilities +/// +/// This structure is used to store information about Overdrive N capabilities +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLODNCapabilitiesX2 { + /// Number of levels which describe the minimum to maximum clock ranges. + /// The 1st level indicates the minimum clocks, and the 2nd level + /// indicates the maximum clocks. int iMaximumNumberOfPerformanceLevels; + /// bit vector, which tells what are the features are supported. + /// \ref: ADLODNFEATURECONTROL int iFlags; + /// Contains the hard limits of the sclk range. Overdrive + /// clocks cannot be set outside this range. ADLODNParameterRange sEngineClockRange; + /// Contains the hard limits of the mclk range. Overdrive + /// clocks cannot be set outside this range. ADLODNParameterRange sMemoryClockRange; + /// Contains the hard limits of the vddc range. Overdrive + /// clocks cannot be set outside this range. ADLODNParameterRange svddcRange; + /// Contains the hard limits of the power range. Overdrive + /// clocks cannot be set outside this range. ADLODNParameterRange power; + /// Contains the hard limits of the power range. Overdrive + /// clocks cannot be set outside this range. ADLODNParameterRange powerTuneTemperature; + /// Contains the hard limits of the Temperature range. Overdrive + /// clocks cannot be set outside this range. ADLODNParameterRange fanTemperature; + /// Contains the hard limits of the Fan range. Overdrive + /// clocks cannot be set outside this range. ADLODNParameterRange fanSpeed; + /// Contains the hard limits of the Fan range. Overdrive + /// clocks cannot be set outside this range. ADLODNParameterRange minimumPerformanceClock; + /// Contains the hard limits of the throttleNotification ADLODNParameterRange throttleNotificaion; + /// Contains the hard limits of the Auto Systemclock ADLODNParameterRange autoSystemClock; } ADLODNCapabilitiesX2; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive level. +/// +/// This structure is used to store information about Overdrive level. +/// This structure is used by ADLODPerformanceLevels. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLODNPerformanceLevel { + /// clock. int iClock; + /// VDCC. int iVddc; + /// enabled int iEnabled; } ADLODNPerformanceLevel; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive N performance levels. +/// +/// This structure is used to store information about Overdrive performance levels. +/// This structure is used by the ADL_OverdriveN_ODPerformanceLevels_Get() and ADL_OverdriveN_ODPerformanceLevels_Set() functions. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLODNPerformanceLevels { int iSize; //Automatic/manual int iMode; + /// Must be set to sizeof( \ref ADLODPerformanceLevels ) + sizeof( \ref ADLODPerformanceLevel ) * (ADLODParameters.iNumberOfPerformanceLevels - 1) int iNumberOfPerformanceLevels; + /// Array of performance state descriptors. Must have ADLODParameters.iNumberOfPerformanceLevels elements. ADLODNPerformanceLevel aLevels[1]; } ADLODNPerformanceLevels; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive N Fan Speed. +/// +/// This structure is used to store information about Overdrive Fan control . +/// This structure is used by the ADL_OverdriveN_ODPerformanceLevels_Get() and ADL_OverdriveN_ODPerformanceLevels_Set() functions. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLODNFanControl { int iMode; @@ -1545,6 +3048,13 @@ typedef struct ADLODNFanControl int iMinFanLimit; } ADLODNFanControl; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive N power limit. +/// +/// This structure is used to store information about Overdrive power limit. +/// This structure is used by the ADL_OverdriveN_ODPerformanceLevels_Get() and ADL_OverdriveN_ODPerformanceLevels_Set() functions. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLODNPowerLimitSetting { int iMode; @@ -1574,20 +3084,39 @@ typedef struct ADLODNPerformanceStatus int iVDDCI; } ADLODNPerformanceStatus; +///\brief Structure containing information about Overdrive level. +/// +/// This structure is used to store information about Overdrive level. +/// This structure is used by ADLODPerformanceLevels. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLODNPerformanceLevelX2 { + /// clock. int iClock; + /// VDCC. int iVddc; + /// enabled int iEnabled; + /// MASK int iControl; } ADLODNPerformanceLevelX2; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive N performance levels. +/// +/// This structure is used to store information about Overdrive performance levels. +/// This structure is used by the ADL_OverdriveN_ODPerformanceLevels_Get() and ADL_OverdriveN_ODPerformanceLevels_Set() functions. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLODNPerformanceLevelsX2 { int iSize; //Automatic/manual int iMode; + /// Must be set to sizeof( \ref ADLODPerformanceLevels ) + sizeof( \ref ADLODPerformanceLevel ) * (ADLODParameters.iNumberOfPerformanceLevels - 1) int iNumberOfPerformanceLevels; + /// Array of performance state descriptors. Must have ADLODParameters.iNumberOfPerformanceLevels elements. ADLODNPerformanceLevelX2 aLevels[1]; } ADLODNPerformanceLevelsX2; @@ -1610,11 +3139,11 @@ typedef struct ADLODNCurrentPowerParameters //ODN Ext range data structure typedef struct ADLODNExtSingleInitSetting { - int mode; - int minValue; - int maxValue; - int step; - int defaultValue; + int mode; + int minValue; + int maxValue; + int step; + int defaultValue; } ADLODNExtSingleInitSetting; //OD8 Ext range data structure @@ -1626,6 +3155,12 @@ typedef struct ADLOD8SingleInitSetting int defaultValue; } ADLOD8SingleInitSetting; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive8 initial setting +/// +/// This structure is used to store information about Overdrive8 initial setting +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLOD8InitSetting { int count; @@ -1633,12 +3168,24 @@ typedef struct ADLOD8InitSetting ADLOD8SingleInitSetting od8SettingTable[OD8_COUNT]; } ADLOD8InitSetting; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive8 current setting +/// +/// This structure is used to store information about Overdrive8 current setting +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLOD8CurrentSetting { int count; int Od8SettingTable[OD8_COUNT]; } ADLOD8CurrentSetting; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Overdrive8 set setting +/// +/// This structure is used to store information about Overdrive8 set setting +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLOD8SingleSetSetting { @@ -1653,6 +3200,12 @@ typedef struct ADLOD8SetSetting ADLOD8SingleSetSetting od8SettingTable[OD8_COUNT]; } ADLOD8SetSetting; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Performance Metrics data +/// +/// This structure is used to store information about Performance Metrics data output +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLSingleSensorData { int supported; @@ -1665,6 +3218,13 @@ typedef struct ADLPMLogDataOutput ADLSingleSensorData sensors[ADL_PMLOG_MAX_SENSORS]; }ADLPMLogDataOutput; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about PPLog settings. +/// +/// This structure is used to store information about PPLog settings. +/// This structure is used by the ADL2_PPLogSettings_Set() and ADL2_PPLogSettings_Get() functions. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLPPLogSettings { int BreakOnAssert; @@ -1678,73 +3238,147 @@ typedef struct ADLPPLogSettings int PowerProfilingTimeInterval; }ADLPPLogSettings; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information related Frames Per Second for AC and DC. +/// +/// This structure is used to store information related AC and DC Frames Per Second settings +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLFPSSettingsOutput { + /// size int ulSize; + /// FPS Monitor is enabled in the AC state if 1 int bACFPSEnabled; + /// FPS Monitor is enabled in the DC state if 1 int bDCFPSEnabled; + /// Current Value of FPS Monitor in AC state int ulACFPSCurrent; + /// Current Value of FPS Monitor in DC state int ulDCFPSCurrent; + /// Maximum FPS Threshold allowed in PPLib for AC int ulACFPSMaximum; + /// Minimum FPS Threshold allowed in PPLib for AC int ulACFPSMinimum; + /// Maximum FPS Threshold allowed in PPLib for DC int ulDCFPSMaximum; + /// Minimum FPS Threshold allowed in PPLib for DC int ulDCFPSMinimum; } ADLFPSSettingsOutput; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information related Frames Per Second for AC and DC. +/// +/// This structure is used to store information related AC and DC Frames Per Second settings +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLFPSSettingsInput { + /// size int ulSize; + /// Settings are for Global FPS (used by CCC) int bGlobalSettings; + /// Current Value of FPS Monitor in AC state int ulACFPSCurrent; + /// Current Value of FPS Monitor in DC state int ulDCFPSCurrent; + /// Reserved int ulReserved[6]; } ADLFPSSettingsInput; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information related power management logging. +/// +/// This structure is used to store support information for power management logging. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// enum { ADL_PMLOG_MAX_SUPPORTED_SENSORS = 256 }; typedef struct ADLPMLogSupportInfo { + /// list of sensors defined by ADL_PMLOG_SENSORS unsigned short usSensors[ADL_PMLOG_MAX_SUPPORTED_SENSORS]; + /// Reserved int ulReserved[16]; } ADLPMLogSupportInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information to start power management logging. +/// +/// This structure is used as input to ADL2_Adapter_PMLog_Start +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLPMLogStartInput { + /// list of sensors defined by ADL_PMLOG_SENSORS unsigned short usSensors[ADL_PMLOG_MAX_SUPPORTED_SENSORS]; + /// Sample rate in milliseconds unsigned long ulSampleRate; + /// Reserved int ulReserved[15]; } ADLPMLogStartInput; typedef struct ADLPMLogData { + /// Structure version unsigned int ulVersion; + /// Current driver sample rate unsigned int ulActiveSampleRate; + /// Timestamp of last update unsigned long long ulLastUpdated; + /// 2D array of senesor and values unsigned int ulValues[ADL_PMLOG_MAX_SUPPORTED_SENSORS][2]; + /// Reserved unsigned int ulReserved[256]; } ADLPMLogData; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information to start power management logging. +/// +/// This structure is returned as output from ADL2_Adapter_PMLog_Start +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLPMLogStartOutput { + /// Pointer to memory address containing logging data union { void* pLoggingAddress; unsigned long long ptr_LoggingAddress; }; + /// Reserved int ulReserved[14]; } ADLPMLogStartOutput; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information to query limts of power management logging. +/// +/// This structure is returned as output from ADL2_Adapter_PMLog_SensorLimits_Get +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLPMLogSensorLimits { int SensorLimits[ADL_PMLOG_MAX_SENSORS][2]; //index 0: min, 1: max } ADLPMLogSensorLimits; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information related RAS Get Error Counts Information +/// +/// This structure is used to store RAS Error Counts Get Input Information +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLRASGetErrorCountsInput { unsigned int Reserved[16]; } ADLRASGetErrorCountsInput; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information related RAS Get Error Counts Information +/// +/// This structure is used to store RAS Error Counts Get Output Information +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLRASGetErrorCountsOutput { @@ -1753,6 +3387,12 @@ typedef struct ADLRASGetErrorCountsOutput unsigned int Reserved[14]; } ADLRASGetErrorCountsOutput; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information related RAS Get Error Counts Information +/// +/// This structure is used to store RAS Error Counts Get Information +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLRASGetErrorCounts { @@ -1762,18 +3402,36 @@ typedef struct ADLRASGetErrorCounts ADLRASGetErrorCountsOutput Output; } ADLRASGetErrorCounts; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information related RAS Error Counts Reset Information +/// +/// This structure is used to store RAS Error Counts Reset Input Information +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLRASResetErrorCountsInput { unsigned int Reserved[8]; } ADLRASResetErrorCountsInput; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information related RAS Error Counts Reset Information +/// +/// This structure is used to store RAS Error Counts Reset Output Information +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLRASResetErrorCountsOutput { unsigned int Reserved[8]; } ADLRASResetErrorCountsOutput; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information related RAS Error Counts Reset Information +/// +/// This structure is used to store RAS Error Counts Reset Information +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLRASResetErrorCounts { @@ -1783,6 +3441,12 @@ typedef struct ADLRASResetErrorCounts ADLRASResetErrorCountsOutput Output; } ADLRASResetErrorCounts; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information related RAS Error Injection information +/// +/// This structure is used to store RAS Error Injection input information +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLRASErrorInjectonInput { @@ -1794,6 +3458,12 @@ typedef struct ADLRASErrorInjectonInput unsigned int padding[9]; } ADLRASErrorInjectonInput; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information related RAS Error Injection information +/// +/// This structure is used to store RAS Error Injection output information +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLRASErrorInjectionOutput { @@ -1801,6 +3471,12 @@ typedef struct ADLRASErrorInjectionOutput unsigned int padding[15]; } ADLRASErrorInjectionOutput; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information related RAS Error Injection information +/// +/// This structure is used to store RAS Error Injection information +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLRASErrorInjection { @@ -1810,17 +3486,36 @@ typedef struct ADLRASErrorInjection ADLRASErrorInjectionOutput Output; } ADLRASErrorInjection; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about an application +/// +/// This structure is used to store basic information of a recently ran or currently running application +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLSGApplicationInfo { + /// Application file name wchar_t strFileName[ADL_MAX_PATH]; + /// Application file path wchar_t strFilePath[ADL_MAX_PATH]; + /// Application version wchar_t strVersion[ADL_MAX_PATH]; + /// Timestamp at which application has run long long int timeStamp; + /// Holds whether the applicaition profile exists or not unsigned int iProfileExists; + /// The GPU on which application runs unsigned int iGPUAffinity; + /// The BDF of the GPU on which application runs ADLBdf GPUBdf; } ADLSGApplicationInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information related Frames Per Second for AC and DC. +/// +/// This structure is used to store information related AC and DC Frames Per Second settings +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// enum { ADLPreFlipPostProcessingInfoInvalidLUTIndex = 0xFFFFFFFF }; enum ADLPreFlipPostProcessingLUTAlgorithm @@ -1832,10 +3527,15 @@ enum ADLPreFlipPostProcessingLUTAlgorithm typedef struct ADLPreFlipPostProcessingInfo { + /// size int ulSize; + /// Current active state int bEnabled; + /// Current selected LUT index. 0xFFFFFFF returned if nothing selected. int ulSelectedLUTIndex; + /// Current selected LUT Algorithm int ulSelectedLUTAlgorithm; + /// Reserved int ulReserved[12]; } ADLPreFlipPostProcessingInfo; @@ -1847,355 +3547,675 @@ typedef struct ADL_ERROR_REASON int proVsr; //ON, when proVsr is Enabled }ADL_ERROR_REASON; +typedef struct ADL_ERROR_REASON2 +{ + int boost; //ON, when boost is Enabled + int delag; //ON, when delag is Enabled + int chill; //ON, when chill is Enabled + int proVsr; //ON, when proVsr is Enabled + int upscale; //ON, when RSR is Enabled +}ADL_ERROR_REASON2; + +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about DELAG Settings change reason +/// +/// Elements of DELAG settings changed reason. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_DELAG_NOTFICATION_REASON { - int HotkeyChanged; //Set when Hotkey value is changed - int GlobalEnableChanged; //Set when Global enable value is changed - int GlobalLimitFPSChanged; //Set when Global enable value is changed + int HotkeyChanged; //Set when Hotkey value is changed + int GlobalEnableChanged; //Set when Global enable value is changed + int GlobalLimitFPSChanged; //Set when Global enable value is changed }ADL_DELAG_NOTFICATION_REASON; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about DELAG Settings +/// +/// Elements of DELAG settings. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_DELAG_SETTINGS { - int Hotkey; // Hotkey value - int GlobalEnable; //Global enable value - int GlobalLimitFPS; //Global Limit FPS - int GlobalLimitFPS_MinLimit; //Gloabl Limit FPS slider min limit value - int GlobalLimitFPS_MaxLimit; //Gloabl Limit FPS slider max limit value - int GlobalLimitFPS_Step; //Gloabl Limit FPS step value + int Hotkey; // Hotkey value + int GlobalEnable; //Global enable value + int GlobalLimitFPS; //Global Limit FPS + int GlobalLimitFPS_MinLimit; //Gloabl Limit FPS slider min limit value + int GlobalLimitFPS_MaxLimit; //Gloabl Limit FPS slider max limit value + int GlobalLimitFPS_Step; //Gloabl Limit FPS step value }ADL_DELAG_SETTINGS; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about BOOST Settings change reason +/// +/// Elements of BOOST settings changed reason. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_BOOST_NOTFICATION_REASON { - int HotkeyChanged; //Set when Hotkey value is changed - int GlobalEnableChanged; //Set when Global enable value is changed - int GlobalMinResChanged; //Set when Global min resolution value is changed + int HotkeyChanged; //Set when Hotkey value is changed + int GlobalEnableChanged; //Set when Global enable value is changed + int GlobalMinResChanged; //Set when Global min resolution value is changed }ADL_BOOST_NOTFICATION_REASON; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about BOOST Settings +/// +/// Elements of BOOST settings. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_BOOST_SETTINGS { - int Hotkey; // Hotkey value - int GlobalEnable; //Global enable value - int GlobalMinRes; //Gloabl Min Resolution value - int GlobalMinRes_MinLimit; //Gloabl Min Resolution slider min limit value - int GlobalMinRes_MaxLimit; //Gloabl Min Resolution slider max limit value - int GlobalMinRes_Step; //Gloabl Min Resolution step value + int Hotkey; // Hotkey value + int GlobalEnable; //Global enable value + int GlobalMinRes; //Gloabl Min Resolution value + int GlobalMinRes_MinLimit; //Gloabl Min Resolution slider min limit value + int GlobalMinRes_MaxLimit; //Gloabl Min Resolution slider max limit value + int GlobalMinRes_Step; //Gloabl Min Resolution step value }ADL_BOOST_SETTINGS; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about ProVSR Settings change reason +/// +/// Elements of ProVSR settings changed reason. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_PROVSR_NOTFICATION_REASON { - int HotkeyChanged; //Set when Hotkey value is changed - int GlobalEnableChanged; //Set when Global enable value is changed + int HotkeyChanged; //Set when Hotkey value is changed + int GlobalEnableChanged; //Set when Global enable value is changed }ADL_PROVSR_NOTFICATION_REASON; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Pro VSR Settings +/// +/// Elements of ProVSR settings. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_PROVSR_SETTINGS { - int Hotkey; // Hotkey value - int GlobalEnable; //Global enable value + int Hotkey; // Hotkey value + int GlobalEnable; //Global enable value }ADL_PROVSR_SETTINGS; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about Image Boost(OGL) Settings change reason +/// +/// Elements of Image Boost settings changed reason. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_IMAGE_BOOST_NOTFICATION_REASON { int HotkeyChanged; //Set when Hotkey value is changed int GlobalEnableChanged; //Set when Global enable value is changed }ADL_IMAGE_BOOST_NOTFICATION_REASON; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about OGL IMAGE BOOST Settings +/// +/// Elements of OGL IMAGE BOOST settings. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_IMAGE_BOOST_SETTINGS { int Hotkey; // Hotkey value int GlobalEnable; //Global enable value }ADL_IMAGE_BOOST_SETTINGS; +///////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about RIS Settings change reason +/// +/// Elements of RIS settings changed reason. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_RIS_NOTFICATION_REASON { - unsigned int GlobalEnableChanged; //Set when Global enable value is changed - unsigned int GlobalSharpeningDegreeChanged; //Set when Global sharpening Degree value is changed + unsigned int GlobalEnableChanged; //Set when Global enable value is changed + unsigned int GlobalSharpeningDegreeChanged; //Set when Global sharpening Degree value is changed }ADL_RIS_NOTFICATION_REASON; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about RIS Settings +/// +/// Elements of RIS settings. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_RIS_SETTINGS { - int GlobalEnable; //Global enable value - int GlobalSharpeningDegree; //Global sharpening value - int GlobalSharpeningDegree_MinLimit; //Gloabl sharpening slider min limit value - int GlobalSharpeningDegree_MaxLimit; //Gloabl sharpening slider max limit value - int GlobalSharpeningDegree_Step; //Gloabl sharpening step value + int GlobalEnable; //Global enable value + int GlobalSharpeningDegree; //Global sharpening value + int GlobalSharpeningDegree_MinLimit; //Gloabl sharpening slider min limit value + int GlobalSharpeningDegree_MaxLimit; //Gloabl sharpening slider max limit value + int GlobalSharpeningDegree_Step; //Gloabl sharpening step value }ADL_RIS_SETTINGS; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about CHILL Settings change reason +/// +/// Elements of Chiil settings changed reason. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_CHILL_NOTFICATION_REASON { - int HotkeyChanged; //Set when Hotkey value is changed - int GlobalEnableChanged; //Set when Global enable value is changed - int GlobalMinFPSChanged; //Set when Global min FPS value is changed - int GlobalMaxFPSChanged; //Set when Global max FPS value is changed + int HotkeyChanged; //Set when Hotkey value is changed + int GlobalEnableChanged; //Set when Global enable value is changed + int GlobalMinFPSChanged; //Set when Global min FPS value is changed + int GlobalMaxFPSChanged; //Set when Global max FPS value is changed }ADL_CHILL_NOTFICATION_REASON; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about CHILL Settings +/// +/// Elements of Chill settings. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_CHILL_SETTINGS { - int Hotkey; // Hotkey value - int GlobalEnable; //Global enable value - int GlobalMinFPS; //Global Min FPS value - int GlobalMaxFPS; //Global Max FPS value - int GlobalFPS_MinLimit; //Gloabl FPS slider min limit value - int GlobalFPS_MaxLimit; //Gloabl FPS slider max limit value - int GlobalFPS_Step; //Gloabl FPS Slider step value + int Hotkey; // Hotkey value + int GlobalEnable; //Global enable value + int GlobalMinFPS; //Global Min FPS value + int GlobalMaxFPS; //Global Max FPS value + int GlobalFPS_MinLimit; //Gloabl FPS slider min limit value + int GlobalFPS_MaxLimit; //Gloabl FPS slider max limit value + int GlobalFPS_Step; //Gloabl FPS Slider step value }ADL_CHILL_SETTINGS; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about DRIVERUPSCALE Settings change reason +/// +/// Elements of DRIVERUPSCALE settings changed reason. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_DRIVERUPSCALE_NOTFICATION_REASON { int ModeOverrideEnabledChanged; //Set when Global min resolution value is changed int GlobalEnabledChanged; //Set when Global enable value is changed }ADL_DRIVERUPSCALE_NOTFICATION_REASON; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about DRIVERUPSCALE Settings +/// +/// Elements of DRIVERUPSCALE settings. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_DRIVERUPSCALE_SETTINGS { int ModeOverrideEnabled; int GlobalEnabled; }ADL_DRIVERUPSCALE_SETTINGS; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure Containing R G B values for Radeon USB LED Bar +/// +/// Elements of RGB Values. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_RADEON_LED_COLOR_CONFIG { - unsigned short R : 8; // Red Value - unsigned short G : 8; // Green Value - unsigned short B : 8; // Blue Value + unsigned short R : 8; // Red Value + unsigned short G : 8; // Green Value + unsigned short B : 8; // Blue Value }ADL_RADEON_LED_COLOR_CONFIG; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure Containing All Generic LED configuration for user requested LED pattern. The driver will apply the confgiuration as requested +/// +/// Elements of Radeon USB LED configuration. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_RADEON_LED_PATTERN_CONFIG_GENERIC { - short brightness : 8; // Brightness of LED - short speed : 8; // Speed of LED pattern - bool directionCounterClockWise; //Direction of LED Pattern - ADL_RADEON_LED_COLOR_CONFIG colorConfig; // RGB value of LED pattern - char morseCodeText[ADL_RADEON_LED_MAX_MORSE_CODE]; // Morse Code user input for Morse Code LED pattern - char morseCodeTextOutPut[ADL_RADEON_LED_MAX_MORSE_CODE]; // Driver set output representation of Morse Code - int morseCodeTextOutPutLen; // Length of Morse Code output + short brightness : 8; // Brightness of LED + short speed : 8; // Speed of LED pattern + bool directionCounterClockWise; //Direction of LED Pattern + ADL_RADEON_LED_COLOR_CONFIG colorConfig; // RGB value of LED pattern + char morseCodeText[ADL_RADEON_LED_MAX_MORSE_CODE]; // Morse Code user input for Morse Code LED pattern + char morseCodeTextOutPut[ADL_RADEON_LED_MAX_MORSE_CODE]; // Driver set output representation of Morse Code + int morseCodeTextOutPutLen; // Length of Morse Code output }ADL_RADEON_LED_PATTERN_CONFIG_GENERIC; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure Containing All custom grid pattern LED configuration for user requested LED grid pattern. The driver will apply the confgiuration as requested +/// +/// Elements of Radeon USB LED custom grid configuration. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_RADEON_LED_CUSTOM_LED_CONFIG { - short brightness : 8; // Brightness of LED - ADL_RADEON_LED_COLOR_CONFIG colorConfig[ADL_RADEON_LED_MAX_LED_ROW_ON_GRID][ADL_RADEON_LED_MAX_LED_COLUMN_ON_GRID]; // Full grid array representation of Radeon LED to be populated by user + short brightness : 8; // Brightness of LED + ADL_RADEON_LED_COLOR_CONFIG colorConfig[ADL_RADEON_LED_MAX_LED_ROW_ON_GRID][ADL_RADEON_LED_MAX_LED_COLUMN_ON_GRID]; // Full grid array representation of Radeon LED to be populated by user }ADL_RADEON_LED_CUSTOM_GRID_LED_CONFIG; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure Containing All Radeon USB LED requests and controls. +/// +/// Elements of Radeon USB LED Controls. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_RADEON_LED_PATTERN_CONFIG { - ADL_RADEON_USB_LED_BAR_CONTROLS control; //Requested LED pattern + ADL_RADEON_USB_LED_BAR_CONTROLS control; //Requested LED pattern union { - ADL_RADEON_LED_PATTERN_CONFIG_GENERIC genericPararmeters; //Requested pattern configuration settings - ADL_RADEON_LED_CUSTOM_GRID_LED_CONFIG customGridConfig; //Requested custom grid configuration settings + ADL_RADEON_LED_PATTERN_CONFIG_GENERIC genericPararmeters; //Requested pattern configuration settings + ADL_RADEON_LED_CUSTOM_GRID_LED_CONFIG customGridConfig; //Requested custom grid configuration settings }; }ADL_RADEON_LED_PATTERN_CONFIG; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about the graphics adapter with extended caps +/// +/// This structure is used to store various information about the graphics adapter. This +/// information can be returned to the user. Alternatively, it can be used to access various driver calls to set +/// or fetch various settings upon the user's request. +/// This AdapterInfoX2 struct extends the AdapterInfo struct in adl_structures.h +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct AdapterInfoX2 { + /// \ALL_STRUCT_MEM + /// Size of the structure. int iSize; + /// The ADL index handle. One GPU may be associated with one or two index handles int iAdapterIndex; + /// The unique device ID associated with this adapter. char strUDID[ADL_MAX_PATH]; + /// The BUS number associated with this adapter. int iBusNumber; + /// The driver number associated with this adapter. int iDeviceNumber; + /// The function number. int iFunctionNumber; + /// The vendor ID associated with this adapter. int iVendorID; + /// Adapter name. char strAdapterName[ADL_MAX_PATH]; + /// Display name. For example, "\\\\Display0" char strDisplayName[ADL_MAX_PATH]; + /// Present or not; 1 if present and 0 if not present.It the logical adapter is present, the display name such as \\\\.\\Display1 can be found from OS int iPresent; + /// Exist or not; 1 is exist and 0 is not present. int iExist; + /// Driver registry path. char strDriverPath[ADL_MAX_PATH]; + /// Driver registry path Ext for. char strDriverPathExt[ADL_MAX_PATH]; + /// PNP string from Windows. char strPNPString[ADL_MAX_PATH]; + /// It is generated from EnumDisplayDevices. int iOSDisplayIndex; + /// The bit mask identifies the adapter info int iInfoMask; + /// The bit identifies the adapter info \ref define_adapter_info int iInfoValue; } AdapterInfoX2, *LPAdapterInfoX2; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about driver gamut space , whether it is related to source or to destination, overlay or graphics +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLGamutReference { + /// mask whether it is related to source or to destination, overlay or graphics int iGamutRef; }ADLGamutReference; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about driver supported gamut spaces , capability method +/// +/// This structure is used to get driver all supported gamut spaces +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLGamutInfo { + ///Any combination of following ADL_GAMUT_SPACE_CCIR_709 - ADL_GAMUT_SPACE_CUSTOM int SupportedGamutSpace; + ///Any combination of following ADL_WHITE_POINT_5000K - ADL_WHITE_POINT_CUSTOM int SupportedWhitePoint; } ADLGamutInfo; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about driver point coordinates +/// +/// This structure is used to store the driver point coodinates for gamut and white point +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLPoint { + /// x coordinate int iX; + /// y coordinate int iY; } ADLPoint; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about driver supported gamut coordinates +/// +/// This structure is used to store the driver supported supported gamut coordinates +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLGamutCoordinates { + /// red channel chromasity coordinate ADLPoint Red; + /// green channel chromasity coordinate ADLPoint Green; + /// blue channel chromasity coordinate ADLPoint Blue; } ADLGamutCoordinates; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about driver current gamut space , parent struct for ADLGamutCoordinates and ADLWhitePoint +/// This structure is used to get/set driver supported gamut space +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLGamutData { + ///used as mask and could be 4 options + ///BIT_0 If flag ADL_GAMUT_REFERENCE_SOURCE is asserted set operation is related to gamut source , + ///if not gamut destination + ///BIT_1 If flag ADL_GAMUT_GAMUT_VIDEO_CONTENT is asserted + ///BIT_2,BIT_3 used as mask and could be 4 options custom (2) + predefined (2) + ///0. Gamut predefined, white point predefined -> 0 | 0 + ///1. Gamut predefined, white point custom -> 0 | ADL_CUSTOM_WHITE_POINT + ///2. White point predefined, gamut custom -> 0 | ADL_CUSTOM_GAMUT + ///3. White point custom, gamut custom -> ADL_CUSTOM_GAMUT | ADL_CUSTOM_WHITE_POINT int iFeature; + ///one of ADL_GAMUT_SPACE_CCIR_709 - ADL_GAMUT_SPACE_CIE_RGB int iPredefinedGamut; + ///one of ADL_WHITE_POINT_5000K - ADL_WHITE_POINT_9300K int iPredefinedWhitePoint; + ///valid when in mask avails ADL_CUSTOM_WHITE_POINT ADLPoint CustomWhitePoint; + ///valid when in mask avails ADL_CUSTOM_GAMUT ADLGamutCoordinates CustomGamut; } ADLGamutData; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing detailed timing parameters. +/// +/// This structure is used to store the detailed timing parameters. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDetailedTimingX2 { + /// Size of the structure. int iSize; + /// Timing flags. \ref define_detailed_timing_flags int sTimingFlags; + /// Total width (columns). int sHTotal; + /// Displayed width. int sHDisplay; + /// Horizontal sync signal offset. int sHSyncStart; + /// Horizontal sync signal width. int sHSyncWidth; + /// Total height (rows). int sVTotal; + /// Displayed height. int sVDisplay; + /// Vertical sync signal offset. int sVSyncStart; + /// Vertical sync signal width. int sVSyncWidth; + /// Pixel clock value. int sPixelClock; + /// Overscan right. short sHOverscanRight; + /// Overscan left. short sHOverscanLeft; + /// Overscan bottom. short sVOverscanBottom; + /// Overscan top. short sVOverscanTop; short sOverscan8B; short sOverscanGR; } ADLDetailedTimingX2; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing display mode information. +/// +/// This structure is used to store the display mode information. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLDisplayModeInfoX2 { + /// Timing standard of the current mode. \ref define_modetiming_standard int iTimingStandard; + /// Applicable timing standards for the current mode. int iPossibleStandard; + /// Refresh rate factor. int iRefreshRate; + /// Num of pixels in a row. int iPelsWidth; + /// Num of pixels in a column. int iPelsHeight; + /// Detailed timing parameters. ADLDetailedTimingX2 sDetailedTiming; } ADLDisplayModeInfoX2; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about I2C. +/// +/// This structure is used to store the I2C information for the current adapter. +/// This structure is used by \ref ADL_Display_WriteAndReadI2CLargePayload +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLI2CLargePayload { + /// Size of the structure int iSize; + /// Numerical value representing hardware I2C. int iLine; + /// The 7-bit I2C slave device address. int iAddress; + /// The offset of the data from the address. int iOffset; + /// Read from or write to slave device. \ref ADL_DL_I2C_ACTIONREAD or \ref ADL_DL_I2C_ACTIONWRITE int iAction; + /// I2C clock speed in KHz. int iSpeed; + /// I2C option flags. \ref define_ADLI2CLargePayload int iFlags; + /// A numerical value representing the number of bytes to be sent or received on the I2C bus. int iDataSize; + /// Address of the characters which are to be sent or received on the I2C bus. char *pcData; } ADLI2CLargePayload; -#define ADL_FEATURE_NAME_LENGTH 16 +/// Size in bytes of the Feature Name +#define ADL_FEATURE_NAME_LENGTH 16 +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing the Multimedia Feature Name +/// +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLFeatureName { + /// The Feature Name char FeatureName[ADL_FEATURE_NAME_LENGTH]; -} ADLFeatureName, *LPADLFeatureName; +} ADLFeatureName, *LPADLFeatureName; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about MM Feature Capabilities. +/// +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLFeatureCaps { - ADLFeatureName Name; - // char strFeatureName[ADL_FEATURE_NAME_LENGTH]; + /// The Feature Name + ADLFeatureName Name; + // char strFeatureName[ADL_FEATURE_NAME_LENGTH]; + /// Group ID. All Features in the same group are shown sequentially in the same UI Page. int iGroupID; + /// Visual ID. Places one or more features in a Group Box. If zero, no Group Box is added. int iVisualID; + /// Page ID. All Features with the same Page ID value are shown together on the same UI page. int iPageID; + /// Feature Property Mask. Indicates which are the valid bits for iFeatureProperties. int iFeatureMask; + /// Feature Property Values. See definitions for ADL_FEATURE_PROPERTIES_XXX int iFeatureProperties; + /// Apperance of the User-Controlled Boolean. int iControlType; + /// Style of the User-Controlled Boolean. int iControlStyle; + /// Apperance of the Adjustment Controls. int iAdjustmentType; + /// Style of the Adjustment Controls. int iAdjustmentStyle; + /// Default user-controlled boolean value. Valid only if ADLFeatureCaps supports user-controlled boolean. int bDefault; + /// Minimum integer value. Valid only if ADLFeatureCaps indicates support for integers. int iMin; + /// Maximum integer value. Valid only if ADLFeatureCaps indicates support for integers. int iMax; + /// Step integer value. Valid only if ADLFeatureCaps indicates support for integers. int iStep; + /// Default integer value. Valid only if ADLFeatureCaps indicates support for integers. int iDefault; + /// Minimum float value. Valid only if ADLFeatureCaps indicates support for floats. float fMin; + /// Maximum float value. Valid only if ADLFeatureCaps indicates support for floats. float fMax; + /// Step float value. Valid only if ADLFeatureCaps indicates support for floats. float fStep; + /// Default float value. Valid only if ADLFeatureCaps indicates support for floats. float fDefault; + /// The Mask for available bits for enumerated values.(If ADLFeatureCaps supports ENUM values) int EnumMask; } ADLFeatureCaps, *LPADLFeatureCaps; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about MM Feature Values. +/// +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLFeatureValues { - ADLFeatureName Name; - // char strFeatureName[ADL_FEATURE_NAME_LENGTH]; + /// The Feature Name + ADLFeatureName Name; + // char strFeatureName[ADL_FEATURE_NAME_LENGTH]; + /// User controlled Boolean current value. Valid only if ADLFeatureCaps supports Boolean. int bCurrent; + /// Current integer value. Valid only if ADLFeatureCaps indicates support for integers. int iCurrent; + /// Current float value. Valid only if ADLFeatureCaps indicates support for floats. float fCurrent; + /// The States for the available bits for enumerated values. int EnumStates; } ADLFeatureValues, *LPADLFeatureValues; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing HDCP Settings info +/// +/// This structure is used to store the HDCP settings of a +/// display +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLHDCPSettings { - int iHDCPProtectionVersion; // Version, starting from 1 - int iHDCPCaps; //Caps used to ensure at least one protection scheme is supported, 1 is HDCP1X and 2 is HDCP22 - int iAllowAll; //Allow all is true, disable all is false - int iHDCPVale; - int iHDCPMask; + int iHDCPProtectionVersion; // Version, starting from 1 + int iHDCPCaps; //Caps used to ensure at least one protection scheme is supported, 1 is HDCP1X and 2 is HDCP22 + int iAllowAll; //Allow all is true, disable all is false + int iHDCPVale; + int iHDCPMask; } ADLHDCPSettings; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing Mantle App info +/// +/// This structure is used to store the Mantle Driver information +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLMantleAppInfo { - int apiVersion; - long driverVersion; - long vendorId; - long deviceId; - int gpuType; - char gpuName[256]; - int maxMemRefsPerSubmission; - long long virtualMemPageSize; - long long maxInlineMemoryUpdateSize; - long maxBoundDescriptorSets; - long maxThreadGroupSize; - long long timestampFrequency; - long multiColorTargetClears; + /// mantle api version + int apiVersion; + /// mantle driver version + long driverVersion; + /// mantle vendroe id + long vendorId; + /// mantle device id + long deviceId; + /// mantle gpu type; + int gpuType; + /// gpu name + char gpuName[256]; + /// mem size + int maxMemRefsPerSubmission; + /// virtual mem size + long long virtualMemPageSize; + /// mem update + long long maxInlineMemoryUpdateSize; + /// bound descriptot + long maxBoundDescriptorSets; + /// thread group size + long maxThreadGroupSize; + /// time stamp frequency + long long timestampFrequency; + /// color target + long multiColorTargetClears; }ADLMantleAppInfo, *LPADLMantleAppInfo; +//////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about SDIData +///This structure is used to store information about the state of the SDI whether it is on +///or off and the current size of the segment or aperture size. +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLSDIData { - int iSDIState; - int iSizeofSDISegment; + /// The SDI state, ADL_SDI_ON or ADL_SDI_OFF, for the current SDI mode + int iSDIState; + /// Size of the memory segment for SDI (in MB). + int iSizeofSDISegment; } ADLSDIData, *LPADLSDIData; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about FRTCPRO Settings +/// +/// Elements of FRTCPRO settings. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_FRTCPRO_Settings { int DefaultState; //The default status for FRTC pro @@ -2206,12 +4226,24 @@ typedef struct ADL_FRTCPRO_Settings unsigned int minSupportedFps; //The min value for FRTC pro. }ADL_FRTCPRO_Settings, *LPADLFRTCProSettings; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information about FRTCPRO Settings changed reason +/// +/// Reason of FRTCPRO changed. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_FRTCPRO_CHANGED_REASON { int StateChanged; // FRTCPro state changed int ValueChanged; // FRTCPro value changed }ADL_FRTCPRO_CHANGED_REASON; +///////////////////////////////////////////////////////////////////////////////////////////// +/// \brief Structure containing the display mode definition used per controller. +/// +/// This structure is used to store the display mode definition used per controller. +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADL_DL_DISPLAY_MODE { int iPelsHeight; // Vertical resolution (in pixels). @@ -2220,6 +4252,13 @@ typedef struct ADL_DL_DISPLAY_MODE int iDisplayFrequency; // Refresh rate. } ADL_DL_DISPLAY_MODE; +///////////////////////////////////////////////////////////////////////////////////////////// +///\brief Structure containing information related DCE support +/// +/// This structure is used to store a bit vector of possible DCE support +/// +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef union _ADLDCESupport { struct @@ -2231,14 +4270,20 @@ typedef union _ADLDCESupport unsigned int u32All; }ADLDCESupport; +///////////////////////////////////////////////////////////////////////////////////////////// +/// \brief Structure for Smart shift 2.0 settings +/// +/// This structure is used to return the smart shift settings +/// \nosubgrouping +//////////////////////////////////////////////////////////////////////////////////////////// typedef struct ADLSmartShiftSettings { - int iMinRange; - int iMaxRange; - int iDefaultMode; //Refer to CWDDEPM_ODN_CONTROL_TYPE - int iDefaultValue; - int iCurrentMode; - int iCurrentValue; + int iMinRange; + int iMaxRange; + int iDefaultMode; //Refer to CWDDEPM_ODN_CONTROL_TYPE + int iDefaultValue; + int iCurrentMode; + int iCurrentValue; int iFlags; //refer to define_smartshift_bits }ADLSmartShiftSettings, *LPADLSmartShiftSettings; #endif /* ADL_STRUCTURES_H_ */ diff --git a/dependencies/dmiinfo.cpp b/dependencies/dmiinfo.cpp deleted file mode 100644 index 6476640f..00000000 --- a/dependencies/dmiinfo.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/*-------------------------------------------------------------------*\ -| dmiinfo.cpp | -| | -| Read DMI information for motherboard vendor and name | -| | -| Chris M (Dr_No) 30th Jun 2020 | -| | -\*-------------------------------------------------------------------*/ - -#include "dmiinfo.h" -#include "LogManager.h" - -#ifdef WIN32 -#include "wmi.h" - -/******************************************************************************************\ -* * -* DMIInfo (Windows) * -* * -* Implementing way to read motherboard vendor and name based on * -* the win32_baseboard WMI query * -* https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-baseboard * -* * -\******************************************************************************************/ -DMIInfo::DMIInfo() -{ - mainboard = ""; - manufacturer = ""; - HRESULT hres; - Wmi wmi; - - // Query WMI for Win32_PnPSignedDriver entries with names matching "SMBUS" or "SM BUS" - // These devices may be browsed under Device Manager -> System Devices - std::vector q_res_BaseBoard; - hres = wmi.query("SELECT * FROM Win32_BaseBoard", q_res_BaseBoard); - - if (hres) - { - LOG_DEBUG("[DMI Info] Unable to read from %s", WMI); - return; - } - - for (QueryObj &i : q_res_BaseBoard) - { - manufacturer = i["Manufacturer"].c_str(); - mainboard = i["Product"].c_str(); - } -} -#else /* WIN32 */ - - -/******************************************************************************************\ -* * -* DMIInfo (Linux) * -* * -* Implementing way to read motherboard vendor and name based on * -* the Linux DMIDecode which is read only for users in the sysfs @ * -* /sys/devices/virtual/dmi/id/ * -* * -\******************************************************************************************/ -DMIInfo::DMIInfo() -{ - mainboard = ""; - manufacturer = ""; - - if ((access(SYSFSDMI "/board_vendor", R_OK)!=0) && (access(SYSFSDMI "/board_name", R_OK)!=0)) - { - LOG_DEBUG("[DMI Info] Unable to read from %s", SYSFSDMI); - return; - } - - std::ifstream mftr(SYSFSDMI "/board_vendor", std::ifstream::in); - getline(mftr, manufacturer); - mftr.close(); - - std::ifstream prdt(SYSFSDMI "/board_name", std::ifstream::in); - getline(prdt, mainboard); - prdt.close(); -} -#endif /* WIN32 */ - -DMIInfo::~DMIInfo() -{ - -} - -std::string DMIInfo::getMainboard() -{ - return mainboard; -} - -std::string DMIInfo::getManufacturer() -{ - return manufacturer; -} diff --git a/dependencies/dmiinfo.h b/dependencies/dmiinfo.h deleted file mode 100644 index 60d0ac6f..00000000 --- a/dependencies/dmiinfo.h +++ /dev/null @@ -1,39 +0,0 @@ -/*-------------------------------------------------------------------*\ -| dmiinfo.h | -| | -| Read DMI information for motherboard vendor and name | -| | -| Chris M (Dr_No) 30th Jun 2020 | -| | -\*-------------------------------------------------------------------*/ - -#ifndef DMIINFO_H -#define DMIINFO_H - -#include - -#ifdef WIN32 -#include "wmi.h" - -#define WMI "WMI" -#else -#include //Linux specific filesystem operation -#include - -#define SYSFSDMI "/sys/devices/virtual/dmi/id/" //Linux specific file path -#endif - -class DMIInfo -{ -public: - DMIInfo(); - ~DMIInfo(); - - std::string getMainboard(); - std::string getManufacturer(); -private: - std::string mainboard; - std::string manufacturer; -}; - -#endif // DMIINFO_H diff --git a/dependencies/hidapi/hidapi/hidapi.h b/dependencies/hidapi-win/include/hidapi.h similarity index 85% rename from dependencies/hidapi/hidapi/hidapi.h rename to dependencies/hidapi-win/include/hidapi.h index 3cee21db..2da647f3 100644 --- a/dependencies/hidapi/hidapi/hidapi.h +++ b/dependencies/hidapi-win/include/hidapi.h @@ -1,559 +1,624 @@ -/******************************************************* - HIDAPI - Multi-Platform library for - communication with HID devices. - - Alan Ott - Signal 11 Software - - libusb/hidapi Team - - Copyright 2022, All Rights Reserved. - - At the discretion of the user of this library, - this software may be licensed under the terms of the - GNU General Public License v3, a BSD-Style license, or the - original HIDAPI license as outlined in the LICENSE.txt, - LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt - files located at the root of the source distribution. - These files may also be found in the public source - code repository located at: - https://github.com/libusb/hidapi . -********************************************************/ - -/** @file - * @defgroup API hidapi API - */ - -#ifndef HIDAPI_H__ -#define HIDAPI_H__ - -#include - -#ifdef _WIN32 - #define HID_API_EXPORT __declspec(dllexport) - #define HID_API_CALL -#else - #define HID_API_EXPORT /**< API export macro */ - #define HID_API_CALL /**< API call macro */ -#endif - -#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/ - -/** @brief Static/compile-time major version of the library. - - @ingroup API -*/ -#define HID_API_VERSION_MAJOR 0 -/** @brief Static/compile-time minor version of the library. - - @ingroup API -*/ -#define HID_API_VERSION_MINOR 13 -/** @brief Static/compile-time patch version of the library. - - @ingroup API -*/ -#define HID_API_VERSION_PATCH 0 - -/* Helper macros */ -#define HID_API_AS_STR_IMPL(x) #x -#define HID_API_AS_STR(x) HID_API_AS_STR_IMPL(x) -#define HID_API_TO_VERSION_STR(v1, v2, v3) HID_API_AS_STR(v1.v2.v3) - -/** @brief Coverts a version as Major/Minor/Patch into a number: - <8 bit major><16 bit minor><8 bit patch>. - - This macro was added in version 0.12.0. - - Convenient function to be used for compile-time checks, like: - #if HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0) - - @ingroup API -*/ -#define HID_API_MAKE_VERSION(mj, mn, p) (((mj) << 24) | ((mn) << 8) | (p)) - -/** @brief Static/compile-time version of the library. - - This macro was added in version 0.12.0. - - @see @ref HID_API_MAKE_VERSION. - - @ingroup API -*/ -#define HID_API_VERSION HID_API_MAKE_VERSION(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH) - -/** @brief Static/compile-time string version of the library. - - @ingroup API -*/ -#define HID_API_VERSION_STR HID_API_TO_VERSION_STR(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH) - -#ifdef __cplusplus -extern "C" { -#endif - struct hid_api_version { - int major; - int minor; - int patch; - }; - - struct hid_device_; - typedef struct hid_device_ hid_device; /**< opaque hidapi structure */ - - /** hidapi info structure */ - struct hid_device_info { - /** Platform-specific device path */ - char *path; - /** Device Vendor ID */ - unsigned short vendor_id; - /** Device Product ID */ - unsigned short product_id; - /** Serial Number */ - wchar_t *serial_number; - /** Device Release Number in binary-coded decimal, - also known as Device Version Number */ - unsigned short release_number; - /** Manufacturer String */ - wchar_t *manufacturer_string; - /** Product string */ - wchar_t *product_string; - /** Usage Page for this Device/Interface - (Windows/Mac/hidraw only) */ - unsigned short usage_page; - /** Usage for this Device/Interface - (Windows/Mac/hidraw only) */ - unsigned short usage; - /** The USB interface which this logical device - represents. - - * Valid on both Linux implementations in all cases. - * Valid on the Windows implementation only if the device - contains more than one interface. - * Valid on the Mac implementation if and only if the device - is a USB HID device. */ - int interface_number; - - /** Pointer to the next device */ - struct hid_device_info *next; - }; - - - /** @brief Initialize the HIDAPI library. - - This function initializes the HIDAPI library. Calling it is not - strictly necessary, as it will be called automatically by - hid_enumerate() and any of the hid_open_*() functions if it is - needed. This function should be called at the beginning of - execution however, if there is a chance of HIDAPI handles - being opened by different threads simultaneously. - - @ingroup API - - @returns - This function returns 0 on success and -1 on error. - Call hid_error(NULL) to get the failure reason. - */ - int HID_API_EXPORT HID_API_CALL hid_init(void); - - /** @brief Finalize the HIDAPI library. - - This function frees all of the static data associated with - HIDAPI. It should be called at the end of execution to avoid - memory leaks. - - @ingroup API - - @returns - This function returns 0 on success and -1 on error. - */ - int HID_API_EXPORT HID_API_CALL hid_exit(void); - - /** @brief Enumerate the HID Devices. - - This function returns a linked list of all the HID devices - attached to the system which match vendor_id and product_id. - If @p vendor_id is set to 0 then any vendor matches. - If @p product_id is set to 0 then any product matches. - If @p vendor_id and @p product_id are both set to 0, then - all HID devices will be returned. - - @ingroup API - @param vendor_id The Vendor ID (VID) of the types of device - to open. - @param product_id The Product ID (PID) of the types of - device to open. - - @returns - This function returns a pointer to a linked list of type - struct #hid_device_info, containing information about the HID devices - attached to the system, - or NULL in the case of failure or if no HID devices present in the system. - Call hid_error(NULL) to get the failure reason. - - @note The returned value by this function must to be freed by calling hid_free_enumeration(), - when not needed anymore. - */ - struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); - - /** @brief Free an enumeration Linked List - - This function frees a linked list created by hid_enumerate(). - - @ingroup API - @param devs Pointer to a list of struct_device returned from - hid_enumerate(). - */ - void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs); - - /** @brief Open a HID device using a Vendor ID (VID), Product ID - (PID) and optionally a serial number. - - If @p serial_number is NULL, the first device with the - specified VID and PID is opened. - - @ingroup API - @param vendor_id The Vendor ID (VID) of the device to open. - @param product_id The Product ID (PID) of the device to open. - @param serial_number The Serial Number of the device to open - (Optionally NULL). - - @returns - This function returns a pointer to a #hid_device object on - success or NULL on failure. - Call hid_error(NULL) to get the failure reason. - - @note The returned object must be freed by calling hid_close(), - when not needed anymore. - */ - HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); - - /** @brief Open a HID device by its path name. - - The path name be determined by calling hid_enumerate(), or a - platform-specific path name can be used (eg: /dev/hidraw0 on - Linux). - - @ingroup API - @param path The path name of the device to open - - @returns - This function returns a pointer to a #hid_device object on - success or NULL on failure. - Call hid_error(NULL) to get the failure reason. - - @note The returned object must be freed by calling hid_close(), - when not needed anymore. - */ - HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path); - - /** @brief Write an Output report to a HID device. - - The first byte of @p data[] must contain the Report ID. For - devices which only support a single report, this must be set - to 0x0. The remaining bytes contain the report data. Since - the Report ID is mandatory, calls to hid_write() will always - contain one more byte than the report contains. For example, - if a hid report is 16 bytes long, 17 bytes must be passed to - hid_write(), the Report ID (or 0x0, for devices with a - single report), followed by the report data (16 bytes). In - this example, the length passed in would be 17. - - hid_write() will send the data on the first OUT endpoint, if - one exists. If it does not, it will send the data through - the Control Endpoint (Endpoint 0). - - @ingroup API - @param dev A device handle returned from hid_open(). - @param data The data to send, including the report number as - the first byte. - @param length The length in bytes of the data to send. - - @returns - This function returns the actual number of bytes written and - -1 on error. - Call hid_error(dev) to get the failure reason. - */ - int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length); - - /** @brief Read an Input report from a HID device with timeout. - - Input reports are returned - to the host through the INTERRUPT IN endpoint. The first byte will - contain the Report number if the device uses numbered reports. - - @ingroup API - @param dev A device handle returned from hid_open(). - @param data A buffer to put the read data into. - @param length The number of bytes to read. For devices with - multiple reports, make sure to read an extra byte for - the report number. - @param milliseconds timeout in milliseconds or -1 for blocking wait. - - @returns - This function returns the actual number of bytes read and - -1 on error. - Call hid_error(dev) to get the failure reason. - If no packet was available to be read within - the timeout period, this function returns 0. - */ - int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); - - /** @brief Read an Input report from a HID device. - - Input reports are returned - to the host through the INTERRUPT IN endpoint. The first byte will - contain the Report number if the device uses numbered reports. - - @ingroup API - @param dev A device handle returned from hid_open(). - @param data A buffer to put the read data into. - @param length The number of bytes to read. For devices with - multiple reports, make sure to read an extra byte for - the report number. - - @returns - This function returns the actual number of bytes read and - -1 on error. - Call hid_error(dev) to get the failure reason. - If no packet was available to be read and - the handle is in non-blocking mode, this function returns 0. - */ - int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length); - - /** @brief Set the device handle to be non-blocking. - - In non-blocking mode calls to hid_read() will return - immediately with a value of 0 if there is no data to be - read. In blocking mode, hid_read() will wait (block) until - there is data to read before returning. - - Nonblocking can be turned on and off at any time. - - @ingroup API - @param dev A device handle returned from hid_open(). - @param nonblock enable or not the nonblocking reads - - 1 to enable nonblocking - - 0 to disable nonblocking. - - @returns - This function returns 0 on success and -1 on error. - Call hid_error(dev) to get the failure reason. - */ - int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock); - - /** @brief Send a Feature report to the device. - - Feature reports are sent over the Control endpoint as a - Set_Report transfer. The first byte of @p data[] must - contain the Report ID. For devices which only support a - single report, this must be set to 0x0. The remaining bytes - contain the report data. Since the Report ID is mandatory, - calls to hid_send_feature_report() will always contain one - more byte than the report contains. For example, if a hid - report is 16 bytes long, 17 bytes must be passed to - hid_send_feature_report(): the Report ID (or 0x0, for - devices which do not use numbered reports), followed by the - report data (16 bytes). In this example, the length passed - in would be 17. - - @ingroup API - @param dev A device handle returned from hid_open(). - @param data The data to send, including the report number as - the first byte. - @param length The length in bytes of the data to send, including - the report number. - - @returns - This function returns the actual number of bytes written and - -1 on error. - Call hid_error(dev) to get the failure reason. - */ - int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length); - - /** @brief Get a feature report from a HID device. - - Set the first byte of @p data[] to the Report ID of the - report to be read. Make sure to allow space for this - extra byte in @p data[]. Upon return, the first byte will - still contain the Report ID, and the report data will - start in data[1]. - - @ingroup API - @param dev A device handle returned from hid_open(). - @param data A buffer to put the read data into, including - the Report ID. Set the first byte of @p data[] to the - Report ID of the report to be read, or set it to zero - if your device does not use numbered reports. - @param length The number of bytes to read, including an - extra byte for the report ID. The buffer can be longer - than the actual report. - - @returns - This function returns the number of bytes read plus - one for the report ID (which is still in the first - byte), or -1 on error. - Call hid_error(dev) to get the failure reason. - */ - int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length); - - /** @brief Get a input report from a HID device. - - Since version 0.10.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 10, 0) - - Set the first byte of @p data[] to the Report ID of the - report to be read. Make sure to allow space for this - extra byte in @p data[]. Upon return, the first byte will - still contain the Report ID, and the report data will - start in data[1]. - - @ingroup API - @param device A device handle returned from hid_open(). - @param data A buffer to put the read data into, including - the Report ID. Set the first byte of @p data[] to the - Report ID of the report to be read, or set it to zero - if your device does not use numbered reports. - @param length The number of bytes to read, including an - extra byte for the report ID. The buffer can be longer - than the actual report. - - @returns - This function returns the number of bytes read plus - one for the report ID (which is still in the first - byte), or -1 on error. - Call hid_error(dev) to get the failure reason. - */ - int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length); - - /** @brief Close a HID device. - - @ingroup API - @param dev A device handle returned from hid_open(). - */ - void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev); - - /** @brief Get The Manufacturer String from a HID device. - - @ingroup API - @param dev A device handle returned from hid_open(). - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - Call hid_error(dev) to get the failure reason. - */ - int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen); - - /** @brief Get The Product String from a HID device. - - @ingroup API - @param dev A device handle returned from hid_open(). - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - Call hid_error(dev) to get the failure reason. - */ - int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen); - - /** @brief Get The Serial Number String from a HID device. - - @ingroup API - @param dev A device handle returned from hid_open(). - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - Call hid_error(dev) to get the failure reason. - */ - int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen); - - /** @brief Get The struct #hid_device_info from a HID device. - - Since version 0.13.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 13, 0) - - @ingroup API - @param dev A device handle returned from hid_open(). - - @returns - This function returns a pointer to the struct #hid_device_info - for this hid_device, or NULL in the case of failure. - Call hid_error(dev) to get the failure reason. - This struct is valid until the device is closed with hid_close(). - - @note The returned object is owned by the @p dev, and SHOULD NOT be freed by the user. - */ - struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_get_device_info(hid_device *dev); - - /** @brief Get a string from a HID device, based on its string index. - - @ingroup API - @param dev A device handle returned from hid_open(). - @param string_index The index of the string to get. - @param string A wide string buffer to put the data into. - @param maxlen The length of the buffer in multiples of wchar_t. - - @returns - This function returns 0 on success and -1 on error. - Call hid_error(dev) to get the failure reason. - */ - int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen); - - /** @brief Get a string describing the last error which occurred. - - This function is intended for logging/debugging purposes. - - This function guarantees to never return NULL. - If there was no error in the last function call - - the returned string clearly indicates that. - - Any HIDAPI function that can explicitly indicate an execution failure - (e.g. by an error code, or by returning NULL) - may set the error string, - to be returned by this function. - - Strings returned from hid_error() must not be freed by the user, - i.e. owned by HIDAPI library. - Device-specific error string may remain allocated at most until hid_close() is called. - Global error string may remain allocated at most until hid_exit() is called. - - @ingroup API - @param dev A device handle returned from hid_open(), - or NULL to get the last non-device-specific error - (e.g. for errors in hid_open() or hid_enumerate()). - - @returns - A string describing the last error (if any). - */ - HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *dev); - - /** @brief Get a runtime version of the library. - - This function is thread-safe. - - @ingroup API - - @returns - Pointer to statically allocated struct, that contains version. - */ - HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version(void); - - - /** @brief Get a runtime version string of the library. - - This function is thread-safe. - - @ingroup API - - @returns - Pointer to statically allocated string, that contains version string. - */ - HID_API_EXPORT const char* HID_API_CALL hid_version_str(void); - -#ifdef __cplusplus -} -#endif - -#endif - +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + Alan Ott + Signal 11 Software + + libusb/hidapi Team + + Copyright 2023, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + https://github.com/libusb/hidapi . +********************************************************/ + +/** @file + * @defgroup API hidapi API + */ + +#ifndef HIDAPI_H__ +#define HIDAPI_H__ + +#include + +/* #480: this is to be refactored properly for v1.0 */ +#ifdef _WIN32 + #ifndef HID_API_NO_EXPORT_DEFINE + #define HID_API_EXPORT __declspec(dllexport) + #endif +#endif +#ifndef HID_API_EXPORT + #define HID_API_EXPORT /**< API export macro */ +#endif +/* To be removed in v1.0 */ +#define HID_API_CALL /**< API call macro */ + +#define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/ + +/** @brief Static/compile-time major version of the library. + + @ingroup API +*/ +#define HID_API_VERSION_MAJOR 0 +/** @brief Static/compile-time minor version of the library. + + @ingroup API +*/ +#define HID_API_VERSION_MINOR 14 +/** @brief Static/compile-time patch version of the library. + + @ingroup API +*/ +#define HID_API_VERSION_PATCH 0 + +/* Helper macros */ +#define HID_API_AS_STR_IMPL(x) #x +#define HID_API_AS_STR(x) HID_API_AS_STR_IMPL(x) +#define HID_API_TO_VERSION_STR(v1, v2, v3) HID_API_AS_STR(v1.v2.v3) + +/** @brief Coverts a version as Major/Minor/Patch into a number: + <8 bit major><16 bit minor><8 bit patch>. + + This macro was added in version 0.12.0. + + Convenient function to be used for compile-time checks, like: + @code{.c} + #if HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0) + @endcode + + @ingroup API +*/ +#define HID_API_MAKE_VERSION(mj, mn, p) (((mj) << 24) | ((mn) << 8) | (p)) + +/** @brief Static/compile-time version of the library. + + This macro was added in version 0.12.0. + + @see @ref HID_API_MAKE_VERSION. + + @ingroup API +*/ +#define HID_API_VERSION HID_API_MAKE_VERSION(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH) + +/** @brief Static/compile-time string version of the library. + + @ingroup API +*/ +#define HID_API_VERSION_STR HID_API_TO_VERSION_STR(HID_API_VERSION_MAJOR, HID_API_VERSION_MINOR, HID_API_VERSION_PATCH) + +/** @brief Maximum expected HID Report descriptor size in bytes. + + Since version 0.13.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 13, 0) + + @ingroup API +*/ +#define HID_API_MAX_REPORT_DESCRIPTOR_SIZE 4096 + +#ifdef __cplusplus +extern "C" { +#endif + /** A structure to hold the version numbers. */ + struct hid_api_version { + int major; /**< major version number */ + int minor; /**< minor version number */ + int patch; /**< patch version number */ + }; + + struct hid_device_; + typedef struct hid_device_ hid_device; /**< opaque hidapi structure */ + + /** @brief HID underlying bus types. + + @ingroup API + */ + typedef enum { + /** Unknown bus type */ + HID_API_BUS_UNKNOWN = 0x00, + + /** USB bus + Specifications: + https://usb.org/hid */ + HID_API_BUS_USB = 0x01, + + /** Bluetooth or Bluetooth LE bus + Specifications: + https://www.bluetooth.com/specifications/specs/human-interface-device-profile-1-1-1/ + https://www.bluetooth.com/specifications/specs/hid-service-1-0/ + https://www.bluetooth.com/specifications/specs/hid-over-gatt-profile-1-0/ */ + HID_API_BUS_BLUETOOTH = 0x02, + + /** I2C bus + Specifications: + https://docs.microsoft.com/previous-versions/windows/hardware/design/dn642101(v=vs.85) */ + HID_API_BUS_I2C = 0x03, + + /** SPI bus + Specifications: + https://www.microsoft.com/download/details.aspx?id=103325 */ + HID_API_BUS_SPI = 0x04, + } hid_bus_type; + + /** hidapi info structure */ + struct hid_device_info { + /** Platform-specific device path */ + char *path; + /** Device Vendor ID */ + unsigned short vendor_id; + /** Device Product ID */ + unsigned short product_id; + /** Serial Number */ + wchar_t *serial_number; + /** Device Release Number in binary-coded decimal, + also known as Device Version Number */ + unsigned short release_number; + /** Manufacturer String */ + wchar_t *manufacturer_string; + /** Product string */ + wchar_t *product_string; + /** Usage Page for this Device/Interface + (Windows/Mac/hidraw only) */ + unsigned short usage_page; + /** Usage for this Device/Interface + (Windows/Mac/hidraw only) */ + unsigned short usage; + /** The USB interface which this logical device + represents. + + Valid only if the device is a USB HID device. + Set to -1 in all other cases. + */ + int interface_number; + + /** Pointer to the next device */ + struct hid_device_info *next; + + /** Underlying bus type + Since version 0.13.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 13, 0) + */ + hid_bus_type bus_type; + }; + + + /** @brief Initialize the HIDAPI library. + + This function initializes the HIDAPI library. Calling it is not + strictly necessary, as it will be called automatically by + hid_enumerate() and any of the hid_open_*() functions if it is + needed. This function should be called at the beginning of + execution however, if there is a chance of HIDAPI handles + being opened by different threads simultaneously. + + @ingroup API + + @returns + This function returns 0 on success and -1 on error. + Call hid_error(NULL) to get the failure reason. + */ + int HID_API_EXPORT HID_API_CALL hid_init(void); + + /** @brief Finalize the HIDAPI library. + + This function frees all of the static data associated with + HIDAPI. It should be called at the end of execution to avoid + memory leaks. + + @ingroup API + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT HID_API_CALL hid_exit(void); + + /** @brief Enumerate the HID Devices. + + This function returns a linked list of all the HID devices + attached to the system which match vendor_id and product_id. + If @p vendor_id is set to 0 then any vendor matches. + If @p product_id is set to 0 then any product matches. + If @p vendor_id and @p product_id are both set to 0, then + all HID devices will be returned. + + @ingroup API + @param vendor_id The Vendor ID (VID) of the types of device + to open. + @param product_id The Product ID (PID) of the types of + device to open. + + @returns + This function returns a pointer to a linked list of type + struct #hid_device_info, containing information about the HID devices + attached to the system, + or NULL in the case of failure or if no HID devices present in the system. + Call hid_error(NULL) to get the failure reason. + + @note The returned value by this function must to be freed by calling hid_free_enumeration(), + when not needed anymore. + */ + struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); + + /** @brief Free an enumeration Linked List + + This function frees a linked list created by hid_enumerate(). + + @ingroup API + @param devs Pointer to a list of struct_device returned from + hid_enumerate(). + */ + void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs); + + /** @brief Open a HID device using a Vendor ID (VID), Product ID + (PID) and optionally a serial number. + + If @p serial_number is NULL, the first device with the + specified VID and PID is opened. + + @ingroup API + @param vendor_id The Vendor ID (VID) of the device to open. + @param product_id The Product ID (PID) of the device to open. + @param serial_number The Serial Number of the device to open + (Optionally NULL). + + @returns + This function returns a pointer to a #hid_device object on + success or NULL on failure. + Call hid_error(NULL) to get the failure reason. + + @note The returned object must be freed by calling hid_close(), + when not needed anymore. + */ + HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); + + /** @brief Open a HID device by its path name. + + The path name be determined by calling hid_enumerate(), or a + platform-specific path name can be used (eg: /dev/hidraw0 on + Linux). + + @ingroup API + @param path The path name of the device to open + + @returns + This function returns a pointer to a #hid_device object on + success or NULL on failure. + Call hid_error(NULL) to get the failure reason. + + @note The returned object must be freed by calling hid_close(), + when not needed anymore. + */ + HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path); + + /** @brief Write an Output report to a HID device. + + The first byte of @p data[] must contain the Report ID. For + devices which only support a single report, this must be set + to 0x0. The remaining bytes contain the report data. Since + the Report ID is mandatory, calls to hid_write() will always + contain one more byte than the report contains. For example, + if a hid report is 16 bytes long, 17 bytes must be passed to + hid_write(), the Report ID (or 0x0, for devices with a + single report), followed by the report data (16 bytes). In + this example, the length passed in would be 17. + + hid_write() will send the data on the first OUT endpoint, if + one exists. If it does not, it will send the data through + the Control Endpoint (Endpoint 0). + + @ingroup API + @param dev A device handle returned from hid_open(). + @param data The data to send, including the report number as + the first byte. + @param length The length in bytes of the data to send. + + @returns + This function returns the actual number of bytes written and + -1 on error. + Call hid_error(dev) to get the failure reason. + */ + int HID_API_EXPORT HID_API_CALL hid_write(hid_device *dev, const unsigned char *data, size_t length); + + /** @brief Read an Input report from a HID device with timeout. + + Input reports are returned + to the host through the INTERRUPT IN endpoint. The first byte will + contain the Report number if the device uses numbered reports. + + @ingroup API + @param dev A device handle returned from hid_open(). + @param data A buffer to put the read data into. + @param length The number of bytes to read. For devices with + multiple reports, make sure to read an extra byte for + the report number. + @param milliseconds timeout in milliseconds or -1 for blocking wait. + + @returns + This function returns the actual number of bytes read and + -1 on error. + Call hid_error(dev) to get the failure reason. + If no packet was available to be read within + the timeout period, this function returns 0. + */ + int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); + + /** @brief Read an Input report from a HID device. + + Input reports are returned + to the host through the INTERRUPT IN endpoint. The first byte will + contain the Report number if the device uses numbered reports. + + @ingroup API + @param dev A device handle returned from hid_open(). + @param data A buffer to put the read data into. + @param length The number of bytes to read. For devices with + multiple reports, make sure to read an extra byte for + the report number. + + @returns + This function returns the actual number of bytes read and + -1 on error. + Call hid_error(dev) to get the failure reason. + If no packet was available to be read and + the handle is in non-blocking mode, this function returns 0. + */ + int HID_API_EXPORT HID_API_CALL hid_read(hid_device *dev, unsigned char *data, size_t length); + + /** @brief Set the device handle to be non-blocking. + + In non-blocking mode calls to hid_read() will return + immediately with a value of 0 if there is no data to be + read. In blocking mode, hid_read() will wait (block) until + there is data to read before returning. + + Nonblocking can be turned on and off at any time. + + @ingroup API + @param dev A device handle returned from hid_open(). + @param nonblock enable or not the nonblocking reads + - 1 to enable nonblocking + - 0 to disable nonblocking. + + @returns + This function returns 0 on success and -1 on error. + Call hid_error(dev) to get the failure reason. + */ + int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *dev, int nonblock); + + /** @brief Send a Feature report to the device. + + Feature reports are sent over the Control endpoint as a + Set_Report transfer. The first byte of @p data[] must + contain the Report ID. For devices which only support a + single report, this must be set to 0x0. The remaining bytes + contain the report data. Since the Report ID is mandatory, + calls to hid_send_feature_report() will always contain one + more byte than the report contains. For example, if a hid + report is 16 bytes long, 17 bytes must be passed to + hid_send_feature_report(): the Report ID (or 0x0, for + devices which do not use numbered reports), followed by the + report data (16 bytes). In this example, the length passed + in would be 17. + + @ingroup API + @param dev A device handle returned from hid_open(). + @param data The data to send, including the report number as + the first byte. + @param length The length in bytes of the data to send, including + the report number. + + @returns + This function returns the actual number of bytes written and + -1 on error. + Call hid_error(dev) to get the failure reason. + */ + int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length); + + /** @brief Get a feature report from a HID device. + + Set the first byte of @p data[] to the Report ID of the + report to be read. Make sure to allow space for this + extra byte in @p data[]. Upon return, the first byte will + still contain the Report ID, and the report data will + start in data[1]. + + @ingroup API + @param dev A device handle returned from hid_open(). + @param data A buffer to put the read data into, including + the Report ID. Set the first byte of @p data[] to the + Report ID of the report to be read, or set it to zero + if your device does not use numbered reports. + @param length The number of bytes to read, including an + extra byte for the report ID. The buffer can be longer + than the actual report. + + @returns + This function returns the number of bytes read plus + one for the report ID (which is still in the first + byte), or -1 on error. + Call hid_error(dev) to get the failure reason. + */ + int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length); + + /** @brief Get a input report from a HID device. + + Since version 0.10.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 10, 0) + + Set the first byte of @p data[] to the Report ID of the + report to be read. Make sure to allow space for this + extra byte in @p data[]. Upon return, the first byte will + still contain the Report ID, and the report data will + start in data[1]. + + @ingroup API + @param dev A device handle returned from hid_open(). + @param data A buffer to put the read data into, including + the Report ID. Set the first byte of @p data[] to the + Report ID of the report to be read, or set it to zero + if your device does not use numbered reports. + @param length The number of bytes to read, including an + extra byte for the report ID. The buffer can be longer + than the actual report. + + @returns + This function returns the number of bytes read plus + one for the report ID (which is still in the first + byte), or -1 on error. + Call hid_error(dev) to get the failure reason. + */ + int HID_API_EXPORT HID_API_CALL hid_get_input_report(hid_device *dev, unsigned char *data, size_t length); + + /** @brief Close a HID device. + + @ingroup API + @param dev A device handle returned from hid_open(). + */ + void HID_API_EXPORT HID_API_CALL hid_close(hid_device *dev); + + /** @brief Get The Manufacturer String from a HID device. + + @ingroup API + @param dev A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + Call hid_error(dev) to get the failure reason. + */ + int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen); + + /** @brief Get The Product String from a HID device. + + @ingroup API + @param dev A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + Call hid_error(dev) to get the failure reason. + */ + int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen); + + /** @brief Get The Serial Number String from a HID device. + + @ingroup API + @param dev A device handle returned from hid_open(). + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + Call hid_error(dev) to get the failure reason. + */ + int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen); + + /** @brief Get The struct #hid_device_info from a HID device. + + Since version 0.13.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 13, 0) + + @ingroup API + @param dev A device handle returned from hid_open(). + + @returns + This function returns a pointer to the struct #hid_device_info + for this hid_device, or NULL in the case of failure. + Call hid_error(dev) to get the failure reason. + This struct is valid until the device is closed with hid_close(). + + @note The returned object is owned by the @p dev, and SHOULD NOT be freed by the user. + */ + struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_get_device_info(hid_device *dev); + + /** @brief Get a string from a HID device, based on its string index. + + @ingroup API + @param dev A device handle returned from hid_open(). + @param string_index The index of the string to get. + @param string A wide string buffer to put the data into. + @param maxlen The length of the buffer in multiples of wchar_t. + + @returns + This function returns 0 on success and -1 on error. + Call hid_error(dev) to get the failure reason. + */ + int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen); + + /** @brief Get a report descriptor from a HID device. + + Since version 0.14.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 14, 0) + + User has to provide a preallocated buffer where descriptor will be copied to. + The recommended size for preallocated buffer is @ref HID_API_MAX_REPORT_DESCRIPTOR_SIZE bytes. + + @ingroup API + @param dev A device handle returned from hid_open(). + @param buf The buffer to copy descriptor into. + @param buf_size The size of the buffer in bytes. + + @returns + This function returns non-negative number of bytes actually copied, or -1 on error. + */ + int HID_API_EXPORT_CALL hid_get_report_descriptor(hid_device *dev, unsigned char *buf, size_t buf_size); + + /** @brief Get a string describing the last error which occurred. + + This function is intended for logging/debugging purposes. + + This function guarantees to never return NULL. + If there was no error in the last function call - + the returned string clearly indicates that. + + Any HIDAPI function that can explicitly indicate an execution failure + (e.g. by an error code, or by returning NULL) - may set the error string, + to be returned by this function. + + Strings returned from hid_error() must not be freed by the user, + i.e. owned by HIDAPI library. + Device-specific error string may remain allocated at most until hid_close() is called. + Global error string may remain allocated at most until hid_exit() is called. + + @ingroup API + @param dev A device handle returned from hid_open(), + or NULL to get the last non-device-specific error + (e.g. for errors in hid_open() or hid_enumerate()). + + @returns + A string describing the last error (if any). + */ + HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *dev); + + /** @brief Get a runtime version of the library. + + This function is thread-safe. + + @ingroup API + + @returns + Pointer to statically allocated struct, that contains version. + */ + HID_API_EXPORT const struct hid_api_version* HID_API_CALL hid_version(void); + + + /** @brief Get a runtime version string of the library. + + This function is thread-safe. + + @ingroup API + + @returns + Pointer to statically allocated string, that contains version string. + */ + HID_API_EXPORT const char* HID_API_CALL hid_version_str(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dependencies/hidapi-win/include/hidapi_winapi.h b/dependencies/hidapi-win/include/hidapi_winapi.h new file mode 100644 index 00000000..da576846 --- /dev/null +++ b/dependencies/hidapi-win/include/hidapi_winapi.h @@ -0,0 +1,74 @@ +/******************************************************* + HIDAPI - Multi-Platform library for + communication with HID devices. + + libusb/hidapi Team + + Copyright 2022, All Rights Reserved. + + At the discretion of the user of this library, + this software may be licensed under the terms of the + GNU General Public License v3, a BSD-Style license, or the + original HIDAPI license as outlined in the LICENSE.txt, + LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt + files located at the root of the source distribution. + These files may also be found in the public source + code repository located at: + https://github.com/libusb/hidapi . +********************************************************/ + +/** @file + * @defgroup API hidapi API + * + * Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0) + */ + +#ifndef HIDAPI_WINAPI_H__ +#define HIDAPI_WINAPI_H__ + +#include + +#include + +#include "hidapi.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /** @brief Get the container ID for a HID device. + + Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0) + + This function returns the `DEVPKEY_Device_ContainerId` property of + the given device. This can be used to correlate different + interfaces/ports on the same hardware device. + + @ingroup API + @param dev A device handle returned from hid_open(). + @param guid The device's container ID on return. + + @returns + This function returns 0 on success and -1 on error. + */ + int HID_API_EXPORT_CALL hid_winapi_get_container_id(hid_device *dev, GUID *container_id); + + /** + * @brief Reconstructs a HID Report Descriptor from a Win32 HIDP_PREPARSED_DATA structure. + * This reconstructed report descriptor is logical identical to the real report descriptor, + * but not byte wise identical. + * + * @param[in] hidp_preparsed_data Pointer to the HIDP_PREPARSED_DATA to read, i.e.: the value of PHIDP_PREPARSED_DATA, + * as returned by HidD_GetPreparsedData WinAPI function. + * @param buf Pointer to the buffer where the report descriptor should be stored. + * @param[in] buf_size Size of the buffer. The recommended size for the buffer is @ref HID_API_MAX_REPORT_DESCRIPTOR_SIZE bytes. + * + * @return Returns size of reconstructed report descriptor if successful, -1 for error. + */ + int HID_API_EXPORT_CALL hid_winapi_descriptor_reconstruct_pp_data(void *hidp_preparsed_data, unsigned char *buf, size_t buf_size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/dependencies/hidapi-win/x64/hidapi.dll b/dependencies/hidapi-win/x64/hidapi.dll index 68d7a898..4eded6ee 100644 Binary files a/dependencies/hidapi-win/x64/hidapi.dll and b/dependencies/hidapi-win/x64/hidapi.dll differ diff --git a/dependencies/hidapi-win/x64/hidapi.lib b/dependencies/hidapi-win/x64/hidapi.lib index 041bdf96..76560045 100644 Binary files a/dependencies/hidapi-win/x64/hidapi.lib and b/dependencies/hidapi-win/x64/hidapi.lib differ diff --git a/dependencies/hidapi-win/x86/hidapi.dll b/dependencies/hidapi-win/x86/hidapi.dll index 21674b5c..c137c4ea 100644 Binary files a/dependencies/hidapi-win/x86/hidapi.dll and b/dependencies/hidapi-win/x86/hidapi.dll differ diff --git a/dependencies/hidapi-win/x86/hidapi.lib b/dependencies/hidapi-win/x86/hidapi.lib index a1c38297..85d906cb 100644 Binary files a/dependencies/hidapi-win/x86/hidapi.lib and b/dependencies/hidapi-win/x86/hidapi.lib differ diff --git a/dependencies/hidapi/hidapi.c b/dependencies/hidapi/hidapi.c deleted file mode 100644 index 44d986ad..00000000 --- a/dependencies/hidapi/hidapi.c +++ /dev/null @@ -1,1383 +0,0 @@ -/******************************************************* - HIDAPI - Multi-Platform library for - communication with HID devices. - - Alan Ott - Signal 11 Software - - 8/22/2009 - Linux Version - 6/2/2010 - Libusb Version - 8/13/2010 - FreeBSD Version - 11/1/2011 - - Copyright 2009, All Rights Reserved. - - At the discretion of the user of this library, - this software may be licensed under the terms of the - GNU General Public License v3, a BSD-Style license, or the - original HIDAPI license as outlined in the LICENSE.txt, - LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt - files located at the root of the source distribution. - These files may also be found in the public source - code repository located at: - http://github.com/signal11/hidapi . -********************************************************/ - -#define _GNU_SOURCE /* needed for wcsdup() before glibc 2.10 */ - -/* C */ -#include -#include -#include -#include -#include -#include -#include - -/* Unix */ -#include -#include -#include -#include - -/* GNU / LibUSB */ -#include - -#include "hidapi/hidapi.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef DEBUG_PRINTF -#define LOG(...) fprintf(stderr, __VA_ARGS__) -#else -#define LOG(...) do {} while (0) -#endif - -#ifndef __FreeBSD__ -#define DETACH_KERNEL_DRIVER -#endif - -/* Uncomment to enable the retrieval of Usage and Usage Page in -hid_enumerate(). Warning, on platforms different from FreeBSD -this is very invasive as it requires the detach -and re-attach of the kernel driver. See comments inside hid_enumerate(). -libusb HIDAPI programs are encouraged to use the interface number -instead to differentiate between interfaces on a composite HID device. */ -/*#define INVASIVE_GET_USAGE*/ - -/* Linked List of input reports received from the device. */ -struct input_report { - uint8_t *data; - size_t len; - struct input_report *next; -}; - - -struct hid_device_ { - /* Handle to the actual device. */ - libusb_device_handle *device_handle; - - /* Endpoint information */ - int input_endpoint; - int output_endpoint; - int input_ep_max_packet_size; - - /* The interface number of the HID */ - int interface; - - /* Indexes of Strings */ - int manufacturer_index; - int product_index; - int serial_index; - - /* Whether blocking reads are used */ - int blocking; /* boolean */ - - /* Read thread objects */ - //HANDLE thread; - //pthread_mutex_t mutex; /* Protects input_reports */ - //pthread_cond_t condition; - //pthread_barrier_t barrier; /* Ensures correct startup sequence */ - int shutdown_thread; - int cancelled; - struct libusb_transfer *transfer; - - /* List of received input reports. */ - struct input_report *input_reports; -}; - -static libusb_context *usb_context = NULL; - -uint16_t get_usb_code_for_current_locale(void); -static int return_data(hid_device *dev, unsigned char *data, size_t length); - -static hid_device *new_hid_device(void) -{ - hid_device *dev = calloc(1, sizeof(hid_device)); - dev->blocking = 1; - - //pthread_mutex_init(&dev->mutex, NULL); - //pthread_cond_init(&dev->condition, NULL); - //pthread_barrier_init(&dev->barrier, NULL, 2); - - return dev; -} - -static void free_hid_device(hid_device *dev) -{ - /* Clean up the thread objects */ - //pthread_barrier_destroy(&dev->barrier); - //pthread_cond_destroy(&dev->condition); - //pthread_mutex_destroy(&dev->mutex); - - /* Free the device itself */ - free(dev); -} - -#ifdef WIN32 -#define CLOCK_REALTIME 0 - static int clock_gettime(int x, struct timespec *spec) //C-file part - { - __int64 wintime; GetSystemTimeAsFileTime((FILETIME*)&wintime); - wintime -= 116444736000000000i64; //1jan1601 to 1jan1970 - spec->tv_sec = wintime / 10000000i64; //seconds - spec->tv_nsec = wintime % 10000000i64 * 100; //nano-seconds - return 0; - } -#endif - -#if 0 -/*TODO: Implement this funciton on hidapi/libusb.. */ -static void register_error(hid_device *device, const char *op) -{ - -} -#endif - -#ifdef INVASIVE_GET_USAGE -/* Get bytes from a HID Report Descriptor. - Only call with a num_bytes of 0, 1, 2, or 4. */ -static uint32_t get_bytes(uint8_t *rpt, size_t len, size_t num_bytes, size_t cur) -{ - /* Return if there aren't enough bytes. */ - if (cur + num_bytes >= len) - return 0; - - if (num_bytes == 0) - return 0; - else if (num_bytes == 1) { - return rpt[cur+1]; - } - else if (num_bytes == 2) { - return (rpt[cur+2] * 256 + rpt[cur+1]); - } - else if (num_bytes == 4) { - return (rpt[cur+4] * 0x01000000 + - rpt[cur+3] * 0x00010000 + - rpt[cur+2] * 0x00000100 + - rpt[cur+1] * 0x00000001); - } - else - return 0; -} - -/* Retrieves the device's Usage Page and Usage from the report - descriptor. The algorithm is simple, as it just returns the first - Usage and Usage Page that it finds in the descriptor. - The return value is 0 on success and -1 on failure. */ -static int get_usage(uint8_t *report_descriptor, size_t size, - unsigned short *usage_page, unsigned short *usage) -{ - unsigned int i = 0; - int size_code; - int data_len, key_size; - int usage_found = 0, usage_page_found = 0; - - while (i < size) { - int key = report_descriptor[i]; - int key_cmd = key & 0xfc; - - //printf("key: %02hhx\n", key); - - if ((key & 0xf0) == 0xf0) { - /* This is a Long Item. The next byte contains the - length of the data section (value) for this key. - See the HID specification, version 1.11, section - 6.2.2.3, titled "Long Items." */ - if (i+1 < size) - data_len = report_descriptor[i+1]; - else - data_len = 0; /* malformed report */ - key_size = 3; - } - else { - /* This is a Short Item. The bottom two bits of the - key contain the size code for the data section - (value) for this key. Refer to the HID - specification, version 1.11, section 6.2.2.2, - titled "Short Items." */ - size_code = key & 0x3; - switch (size_code) { - case 0: - case 1: - case 2: - data_len = size_code; - break; - case 3: - data_len = 4; - break; - default: - /* Can't ever happen since size_code is & 0x3 */ - data_len = 0; - break; - }; - key_size = 1; - } - - if (key_cmd == 0x4) { - *usage_page = get_bytes(report_descriptor, size, data_len, i); - usage_page_found = 1; - //printf("Usage Page: %x\n", (uint32_t)*usage_page); - } - if (key_cmd == 0x8) { - *usage = get_bytes(report_descriptor, size, data_len, i); - usage_found = 1; - //printf("Usage: %x\n", (uint32_t)*usage); - } - - if (usage_page_found && usage_found) - return 0; /* success */ - - /* Skip over this key and it's associated data */ - i += data_len + key_size; - } - - return -1; /* failure */ -} -#endif /* INVASIVE_GET_USAGE */ - -/* Get the first language the device says it reports. This comes from - USB string #0. */ -static uint16_t get_first_language(libusb_device_handle *dev) -{ - uint16_t buf[32]; - int len; - - /* Get the string from libusb. */ - len = libusb_get_string_descriptor(dev, - 0x0, /* String ID */ - 0x0, /* Language */ - (unsigned char*)buf, - sizeof(buf)); - if (len < 4) - return 0x0; - - return buf[1]; /* First two bytes are len and descriptor type. */ -} - -static int is_language_supported(libusb_device_handle *dev, uint16_t lang) -{ - uint16_t buf[32]; - int len; - int i; - - /* Get the string from libusb. */ - len = libusb_get_string_descriptor(dev, - 0x0, /* String ID */ - 0x0, /* Language */ - (unsigned char*)buf, - sizeof(buf)); - if (len < 4) - return 0x0; - - - len /= 2; /* language IDs are two-bytes each. */ - /* Start at index 1 because there are two bytes of protocol data. */ - for (i = 1; i < len; i++) { - if (buf[i] == lang) - return 1; - } - - return 0; -} - - -/* This function returns a newly allocated wide string containing the USB - device string numbered by the index. The returned string must be freed - by using free(). */ -static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx) -{ - char buf[512]; - int len; - wchar_t *str = NULL; - - /* Determine which language to use. */ - uint16_t lang; - lang = get_usb_code_for_current_locale(); - if (!is_language_supported(dev, lang)) - lang = get_first_language(dev); - - /* Get the string from libusb. */ - len = libusb_get_string_descriptor(dev, - idx, - lang, - (unsigned char*)buf, - sizeof(buf)); - if (len < 0) - return NULL; - - /* Bionic does not have iconv support nor wcsdup() function, so it - has to be done manually. The following code will only work for - code points that can be represented as a single UTF-16 character, - and will incorrectly convert any code points which require more - than one UTF-16 character. - - Skip over the first character (2-bytes). */ - len -= 2; - str = malloc((len / 2 + 1) * sizeof(wchar_t)); - int i; - for (i = 0; i < len / 2; i++) { - str[i] = buf[i * 2 + 2] | (buf[i * 2 + 3] << 8); - } - str[len / 2] = 0x00000000; - - return str; -} - -static char *make_path(libusb_device *dev, int interface_number) -{ - char str[64]; - snprintf(str, sizeof(str), "%04x:%04x:%02x", - libusb_get_bus_number(dev), - libusb_get_device_address(dev), - interface_number); - str[sizeof(str)-1] = '\0'; - - return strdup(str); -} - - -int HID_API_EXPORT hid_init(void) -{ - if (!usb_context) { - const char *locale; - - /* Init Libusb */ - if (libusb_init(&usb_context)) - return -1; - - /* Set the locale if it's not set. */ - locale = setlocale(LC_CTYPE, NULL); - if (!locale) - setlocale(LC_CTYPE, ""); - } - - return 0; -} - -int HID_API_EXPORT hid_exit(void) -{ - if (usb_context) { - libusb_exit(usb_context); - usb_context = NULL; - } - - return 0; -} - -struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) -{ - libusb_device **devs; - libusb_device *dev; - libusb_device_handle *handle; - ssize_t num_devs; - int i = 0; - - struct hid_device_info *root = NULL; /* return object */ - struct hid_device_info *cur_dev = NULL; - - if(hid_init() < 0) - return NULL; - - num_devs = libusb_get_device_list(usb_context, &devs); - if (num_devs < 0) - return NULL; - while ((dev = devs[i++]) != NULL) { - struct libusb_device_descriptor desc; - struct libusb_config_descriptor *conf_desc = NULL; - int j, k; - int interface_num = 0; - - int res = libusb_get_device_descriptor(dev, &desc); - unsigned short dev_vid = desc.idVendor; - unsigned short dev_pid = desc.idProduct; - - res = libusb_get_active_config_descriptor(dev, &conf_desc); - if (res < 0) - libusb_get_config_descriptor(dev, 0, &conf_desc); - if (conf_desc) { - for (j = 0; j < conf_desc->bNumInterfaces; j++) { - const struct libusb_interface *intf = &conf_desc->interface[j]; - for (k = 0; k < intf->num_altsetting; k++) { - const struct libusb_interface_descriptor *intf_desc; - intf_desc = &intf->altsetting[k]; - if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) { - interface_num = intf_desc->bInterfaceNumber; - - /* Check the VID/PID against the arguments */ - if ((vendor_id == 0x0 || vendor_id == dev_vid) && - (product_id == 0x0 || product_id == dev_pid)) { - struct hid_device_info *tmp; - - /* VID/PID match. Create the record. */ - tmp = calloc(1, sizeof(struct hid_device_info)); - if (cur_dev) { - cur_dev->next = tmp; - } - else { - root = tmp; - } - cur_dev = tmp; - - /* Fill out the record */ - cur_dev->next = NULL; - cur_dev->path = make_path(dev, interface_num); - - res = libusb_open(dev, &handle); - - if (res >= 0) { - /* Serial Number */ - if (desc.iSerialNumber > 0) - cur_dev->serial_number = - get_usb_string(handle, desc.iSerialNumber); - - /* Manufacturer and Product strings */ - if (desc.iManufacturer > 0) - cur_dev->manufacturer_string = - get_usb_string(handle, desc.iManufacturer); - if (desc.iProduct > 0) - cur_dev->product_string = - get_usb_string(handle, desc.iProduct); - -#ifdef INVASIVE_GET_USAGE -{ - /* - This section is removed because it is too - invasive on the system. Getting a Usage Page - and Usage requires parsing the HID Report - descriptor. Getting a HID Report descriptor - involves claiming the interface. Claiming the - interface involves detaching the kernel driver. - Detaching the kernel driver is hard on the system - because it will unclaim interfaces (if another - app has them claimed) and the re-attachment of - the driver will sometimes change /dev entry names. - It is for these reasons that this section is - #if 0. For composite devices, use the interface - field in the hid_device_info struct to distinguish - between interfaces. */ - unsigned char data[256]; -#ifdef DETACH_KERNEL_DRIVER - int detached = 0; - /* Usage Page and Usage */ - res = libusb_kernel_driver_active(handle, interface_num); - if (res == 1) { - res = libusb_detach_kernel_driver(handle, interface_num); - if (res < 0) - LOG("Couldn't detach kernel driver, even though a kernel driver was attached."); - else - detached = 1; - } -#endif - res = libusb_claim_interface(handle, interface_num); - if (res >= 0) { - /* Get the HID Report Descriptor. */ - res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8)|interface_num, 0, data, sizeof(data), 5000); - if (res >= 0) { - unsigned short page=0, usage=0; - /* Parse the usage and usage page - out of the report descriptor. */ - get_usage(data, res, &page, &usage); - cur_dev->usage_page = page; - cur_dev->usage = usage; - } - else - LOG("libusb_control_transfer() for getting the HID report failed with %d\n", res); - - /* Release the interface */ - res = libusb_release_interface(handle, interface_num); - if (res < 0) - LOG("Can't release the interface.\n"); - } - else - LOG("Can't claim interface %d\n", res); -#ifdef DETACH_KERNEL_DRIVER - /* Re-attach kernel driver if necessary. */ - if (detached) { - res = libusb_attach_kernel_driver(handle, interface_num); - if (res < 0) - LOG("Couldn't re-attach kernel driver.\n"); - } -#endif -} -#endif /* INVASIVE_GET_USAGE */ - - libusb_close(handle); - } - /* VID/PID */ - cur_dev->vendor_id = dev_vid; - cur_dev->product_id = dev_pid; - - /* Release Number */ - cur_dev->release_number = desc.bcdDevice; - - /* Interface Number */ - cur_dev->interface_number = interface_num; - } - } - } /* altsettings */ - } /* interfaces */ - libusb_free_config_descriptor(conf_desc); - } - } - - libusb_free_device_list(devs, 1); - - return root; -} - -void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) -{ - struct hid_device_info *d = devs; - while (d) { - struct hid_device_info *next = d->next; - free(d->path); - free(d->serial_number); - free(d->manufacturer_string); - free(d->product_string); - free(d); - d = next; - } -} - -hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) -{ - struct hid_device_info *devs, *cur_dev; - const char *path_to_open = NULL; - hid_device *handle = NULL; - - devs = hid_enumerate(vendor_id, product_id); - cur_dev = devs; - while (cur_dev) { - if (cur_dev->vendor_id == vendor_id && - cur_dev->product_id == product_id) { - if (serial_number) { - if (cur_dev->serial_number && - wcscmp(serial_number, cur_dev->serial_number) == 0) { - path_to_open = cur_dev->path; - break; - } - } - else { - path_to_open = cur_dev->path; - break; - } - } - cur_dev = cur_dev->next; - } - - if (path_to_open) { - /* Open the device */ - handle = hid_open_path(path_to_open); - } - - hid_free_enumeration(devs); - - return handle; -} - -static void read_callback(struct libusb_transfer *transfer) -{ - hid_device *dev = transfer->user_data; - int res; - - if (transfer->status == LIBUSB_TRANSFER_COMPLETED) { - - struct input_report *rpt = malloc(sizeof(*rpt)); - rpt->data = malloc(transfer->actual_length); - memcpy(rpt->data, transfer->buffer, transfer->actual_length); - rpt->len = transfer->actual_length; - rpt->next = NULL; - - //pthread_mutex_lock(&dev->mutex); - - /* Attach the new report object to the end of the list. */ - if (dev->input_reports == NULL) { - /* The list is empty. Put it at the root. */ - dev->input_reports = rpt; - //pthread_cond_signal(&dev->condition); - } - else { - /* Find the end of the list and attach. */ - struct input_report *cur = dev->input_reports; - int num_queued = 0; - while (cur->next != NULL) { - cur = cur->next; - num_queued++; - } - cur->next = rpt; - - /* Pop one off if we've reached 30 in the queue. This - way we don't grow forever if the user never reads - anything from the device. */ - if (num_queued > 30) { - return_data(dev, NULL, 0); - } - } - //pthread_mutex_unlock(&dev->mutex); - } - else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { - dev->shutdown_thread = 1; - dev->cancelled = 1; - return; - } - else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) { - dev->shutdown_thread = 1; - dev->cancelled = 1; - return; - } - else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) { - //LOG("Timeout (normal)\n"); - } - else { - LOG("Unknown transfer code: %d\n", transfer->status); - } - - /* Re-submit the transfer object. */ - res = libusb_submit_transfer(transfer); - if (res != 0) { - LOG("Unable to submit URB. libusb error code: %d\n", res); - dev->shutdown_thread = 1; - dev->cancelled = 1; - } -} - - -static void *read_thread(void *param) -{ - hid_device *dev = param; - unsigned char *buf; - const size_t length = dev->input_ep_max_packet_size; - - /* Set up the transfer object. */ - buf = malloc(length); - dev->transfer = libusb_alloc_transfer(0); - libusb_fill_interrupt_transfer(dev->transfer, - dev->device_handle, - dev->input_endpoint, - buf, - length, - (libusb_transfer_cb_fn)read_callback, - dev, - 5000/*timeout*/); - - /* Make the first submission. Further submissions are made - from inside read_callback() */ - libusb_submit_transfer(dev->transfer); - - /* Notify the main thread that the read thread is up and running. */ - //pthread_barrier_wait(&dev->barrier); - - /* Handle all the events. */ - while (!dev->shutdown_thread) { - int res; - res = libusb_handle_events(usb_context); - if (res < 0) { - /* There was an error. */ - LOG("read_thread(): libusb reports error # %d\n", res); - - /* Break out of this loop only on fatal error.*/ - if (res != LIBUSB_ERROR_BUSY && - res != LIBUSB_ERROR_TIMEOUT && - res != LIBUSB_ERROR_OVERFLOW && - res != LIBUSB_ERROR_INTERRUPTED) { - break; - } - } - } - - /* Cancel any transfer that may be pending. This call will fail - if no transfers are pending, but that's OK. */ - libusb_cancel_transfer(dev->transfer); - - while (!dev->cancelled) - libusb_handle_events_completed(usb_context, &dev->cancelled); - - /* Now that the read thread is stopping, Wake any threads which are - waiting on data (in hid_read_timeout()). Do this under a mutex to - make sure that a thread which is about to go to sleep waiting on - the condition actually will go to sleep before the condition is - signaled. */ - //pthread_mutex_lock(&dev->mutex); - //pthread_cond_broadcast(&dev->condition); - //pthread_mutex_unlock(&dev->mutex); - - /* The dev->transfer->buffer and dev->transfer objects are cleaned up - in hid_close(). They are not cleaned up here because this thread - could end either due to a disconnect or due to a user - call to hid_close(). In both cases the objects can be safely - cleaned up after the call to pthread_join() (in hid_close()), but - since hid_close() calls libusb_cancel_transfer(), on these objects, - they can not be cleaned up here. */ - - return NULL; -} - - -hid_device * HID_API_EXPORT hid_open_path(const char *path) -{ - hid_device *dev = NULL; - - libusb_device **devs; - libusb_device *usb_dev; - int res; - int d = 0; - int good_open = 0; - - if(hid_init() < 0) - return NULL; - - dev = new_hid_device(); - - libusb_get_device_list(usb_context, &devs); - while ((usb_dev = devs[d++]) != NULL) { - struct libusb_device_descriptor desc; - struct libusb_config_descriptor *conf_desc = NULL; - int i,j,k; - libusb_get_device_descriptor(usb_dev, &desc); - - if (libusb_get_active_config_descriptor(usb_dev, &conf_desc) < 0) - continue; - for (j = 0; j < conf_desc->bNumInterfaces; j++) { - const struct libusb_interface *intf = &conf_desc->interface[j]; - for (k = 0; k < intf->num_altsetting; k++) { - const struct libusb_interface_descriptor *intf_desc; - intf_desc = &intf->altsetting[k]; - if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) { - char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber); - if (!strcmp(dev_path, path)) { - /* Matched Paths. Open this device */ - - /* OPEN HERE */ - res = libusb_open(usb_dev, &dev->device_handle); - if (res < 0) { - LOG("can't open device\n"); - free(dev_path); - break; - } - good_open = 1; -#ifdef DETACH_KERNEL_DRIVER - /* Detach the kernel driver, but only if the - device is managed by the kernel */ - if (libusb_kernel_driver_active(dev->device_handle, intf_desc->bInterfaceNumber) == 1) { - res = libusb_detach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber); - if (res < 0) { - libusb_close(dev->device_handle); - LOG("Unable to detach Kernel Driver\n"); - free(dev_path); - good_open = 0; - break; - } - } -#endif - res = libusb_claim_interface(dev->device_handle, intf_desc->bInterfaceNumber); - if (res < 0) { - LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res); - free(dev_path); - libusb_close(dev->device_handle); - good_open = 0; - break; - } - - /* Store off the string descriptor indexes */ - dev->manufacturer_index = desc.iManufacturer; - dev->product_index = desc.iProduct; - dev->serial_index = desc.iSerialNumber; - - /* Store off the interface number */ - dev->interface = intf_desc->bInterfaceNumber; - - /* Find the INPUT and OUTPUT endpoints. An - OUTPUT endpoint is not required. */ - for (i = 0; i < intf_desc->bNumEndpoints; i++) { - const struct libusb_endpoint_descriptor *ep - = &intf_desc->endpoint[i]; - - /* Determine the type and direction of this - endpoint. */ - int is_interrupt = - (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) - == LIBUSB_TRANSFER_TYPE_INTERRUPT; - int is_output = - (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) - == LIBUSB_ENDPOINT_OUT; - int is_input = - (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) - == LIBUSB_ENDPOINT_IN; - - /* Decide whether to use it for input or output. */ - if (dev->input_endpoint == 0 && - is_interrupt && is_input) { - /* Use this endpoint for INPUT */ - dev->input_endpoint = ep->bEndpointAddress; - dev->input_ep_max_packet_size = ep->wMaxPacketSize; - } - if (dev->output_endpoint == 0 && - is_interrupt && is_output) { - /* Use this endpoint for OUTPUT */ - dev->output_endpoint = ep->bEndpointAddress; - } - } - - //pthread_create(&dev->thread, NULL, read_thread, dev); - - /* Wait here for the read thread to be initialized. */ - //pthread_barrier_wait(&dev->barrier); - - } - free(dev_path); - } - } - } - libusb_free_config_descriptor(conf_desc); - - } - - libusb_free_device_list(devs, 1); - - /* If we have a good handle, return it. */ - if (good_open) { - return dev; - } - else { - /* Unable to open any devices. */ - free_hid_device(dev); - return NULL; - } -} - - -int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) -{ - int res; - int report_number = data[0]; - int skipped_report_id = 0; - - if (report_number == 0x0) { - data++; - length--; - skipped_report_id = 1; - } - - - if (dev->output_endpoint <= 0) { - /* No interrupt out endpoint. Use the Control Endpoint */ - res = libusb_control_transfer(dev->device_handle, - LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT, - 0x09/*HID Set_Report*/, - (2/*HID output*/ << 8) | report_number, - dev->interface, - (unsigned char *)data, length, - 1000/*timeout millis*/); - - if (res < 0) - return -1; - - if (skipped_report_id) - length++; - - return length; - } - else { - /* Use the interrupt out endpoint */ - int actual_length; - res = libusb_interrupt_transfer(dev->device_handle, - dev->output_endpoint, - (unsigned char*)data, - length, - &actual_length, 1000); - - if (res < 0) - return -1; - - if (skipped_report_id) - actual_length++; - - return actual_length; - } -} - -/* Helper function, to simplify hid_read(). - This should be called with dev->mutex locked. */ -static int return_data(hid_device *dev, unsigned char *data, size_t length) -{ - /* Copy the data out of the linked list item (rpt) into the - return buffer (data), and delete the liked list item. */ - struct input_report *rpt = dev->input_reports; - size_t len = (length < rpt->len)? length: rpt->len; - if (len > 0) - memcpy(data, rpt->data, len); - dev->input_reports = rpt->next; - free(rpt->data); - free(rpt); - return len; -} - -static void cleanup_mutex(void *param) -{ - hid_device *dev = param; - //pthread_mutex_unlock(&dev->mutex); -} - - -int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) -{ - int bytes_read = -1; - -#if 1 - int transferred; - int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000); - LOG("transferred: %d\n", transferred); - return transferred; -#endif - - //pthread_mutex_lock(&dev->mutex); - //pthread_cleanup_push(&cleanup_mutex, dev); - - /* There's an input report queued up. Return it. */ - if (dev->input_reports) { - /* Return the first one */ - bytes_read = return_data(dev, data, length); - goto ret; - } - - if (dev->shutdown_thread) { - /* This means the device has been disconnected. - An error code of -1 should be returned. */ - bytes_read = -1; - goto ret; - } - - if (milliseconds == -1) { - /* Blocking */ - while (!dev->input_reports && !dev->shutdown_thread) { - //pthread_cond_wait(&dev->condition, &dev->mutex); - } - if (dev->input_reports) { - bytes_read = return_data(dev, data, length); - } - } - else if (milliseconds > 0) { - /* Non-blocking, but called with timeout. */ - int res; - struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += milliseconds / 1000; - ts.tv_nsec += (milliseconds % 1000) * 1000000; - if (ts.tv_nsec >= 1000000000L) { - ts.tv_sec++; - ts.tv_nsec -= 1000000000L; - } - - while (!dev->input_reports && !dev->shutdown_thread) { - //res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts); - if (res == 0) { - if (dev->input_reports) { - bytes_read = return_data(dev, data, length); - break; - } - - /* If we're here, there was a spurious wake up - or the read thread was shutdown. Run the - loop again (ie: don't break). */ - } - else if (res == ETIMEDOUT) { - /* Timed out. */ - bytes_read = 0; - break; - } - else { - /* Error. */ - bytes_read = -1; - break; - } - } - } - else { - /* Purely non-blocking */ - bytes_read = 0; - } - -ret: - //pthread_mutex_unlock(&dev->mutex); - //pthread_cleanup_pop(0); - - return bytes_read; -} - -int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) -{ - return hid_read_timeout(dev, data, length, dev->blocking ? -1 : 0); -} - -int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) -{ - dev->blocking = !nonblock; - - return 0; -} - - -int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) -{ - int res = -1; - int skipped_report_id = 0; - int report_number = data[0]; - - if (report_number == 0x0) { - data++; - length--; - skipped_report_id = 1; - } - - res = libusb_control_transfer(dev->device_handle, - LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT, - 0x09/*HID set_report*/, - (3/*HID feature*/ << 8) | report_number, - dev->interface, - (unsigned char *)data, length, - 1000/*timeout millis*/); - - if (res < 0) - return -1; - - /* Account for the report ID */ - if (skipped_report_id) - length++; - - return length; -} - -int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) -{ - int res = -1; - int skipped_report_id = 0; - int report_number = data[0]; - - if (report_number == 0x0) { - /* Offset the return buffer by 1, so that the report ID - will remain in byte 0. */ - data++; - length--; - skipped_report_id = 1; - } - res = libusb_control_transfer(dev->device_handle, - LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN, - 0x01/*HID get_report*/, - (3/*HID feature*/ << 8) | report_number, - dev->interface, - (unsigned char *)data, length, - 1000/*timeout millis*/); - - if (res < 0) - return -1; - - if (skipped_report_id) - res++; - - return res; -} - - -void HID_API_EXPORT hid_close(hid_device *dev) -{ - if (!dev) - return; - - /* Cause read_thread() to stop. */ - dev->shutdown_thread = 1; - libusb_cancel_transfer(dev->transfer); - - /* Wait for read_thread() to end. */ - //pthread_join(dev->thread, NULL); - - /* Clean up the Transfer objects allocated in read_thread(). */ - free(dev->transfer->buffer); - libusb_free_transfer(dev->transfer); - - /* release the interface */ - libusb_release_interface(dev->device_handle, dev->interface); - - /* Close the handle */ - libusb_close(dev->device_handle); - - /* Clear out the queue of received reports. */ - //pthread_mutex_lock(&dev->mutex); - while (dev->input_reports) { - return_data(dev, NULL, 0); - } - //pthread_mutex_unlock(&dev->mutex); - - free_hid_device(dev); -} - - -int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - return hid_get_indexed_string(dev, dev->manufacturer_index, string, maxlen); -} - -int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - return hid_get_indexed_string(dev, dev->product_index, string, maxlen); -} - -int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) -{ - return hid_get_indexed_string(dev, dev->serial_index, string, maxlen); -} - -int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) -{ - wchar_t *str; - - str = get_usb_string(dev->device_handle, string_index); - if (str) { - wcsncpy(string, str, maxlen); - string[maxlen-1] = L'\0'; - free(str); - return 0; - } - else - return -1; -} - - -HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) -{ - return NULL; -} - - -struct lang_map_entry { - const char *name; - const char *string_code; - uint16_t usb_code; -}; - -#define LANG(name,code,usb_code) { name, code, usb_code } -static struct lang_map_entry lang_map[] = { - LANG("Afrikaans", "af", 0x0436), - LANG("Albanian", "sq", 0x041C), - LANG("Arabic - United Arab Emirates", "ar_ae", 0x3801), - LANG("Arabic - Bahrain", "ar_bh", 0x3C01), - LANG("Arabic - Algeria", "ar_dz", 0x1401), - LANG("Arabic - Egypt", "ar_eg", 0x0C01), - LANG("Arabic - Iraq", "ar_iq", 0x0801), - LANG("Arabic - Jordan", "ar_jo", 0x2C01), - LANG("Arabic - Kuwait", "ar_kw", 0x3401), - LANG("Arabic - Lebanon", "ar_lb", 0x3001), - LANG("Arabic - Libya", "ar_ly", 0x1001), - LANG("Arabic - Morocco", "ar_ma", 0x1801), - LANG("Arabic - Oman", "ar_om", 0x2001), - LANG("Arabic - Qatar", "ar_qa", 0x4001), - LANG("Arabic - Saudi Arabia", "ar_sa", 0x0401), - LANG("Arabic - Syria", "ar_sy", 0x2801), - LANG("Arabic - Tunisia", "ar_tn", 0x1C01), - LANG("Arabic - Yemen", "ar_ye", 0x2401), - LANG("Armenian", "hy", 0x042B), - LANG("Azeri - Latin", "az_az", 0x042C), - LANG("Azeri - Cyrillic", "az_az", 0x082C), - LANG("Basque", "eu", 0x042D), - LANG("Belarusian", "be", 0x0423), - LANG("Bulgarian", "bg", 0x0402), - LANG("Catalan", "ca", 0x0403), - LANG("Chinese - China", "zh_cn", 0x0804), - LANG("Chinese - Hong Kong SAR", "zh_hk", 0x0C04), - LANG("Chinese - Macau SAR", "zh_mo", 0x1404), - LANG("Chinese - Singapore", "zh_sg", 0x1004), - LANG("Chinese - Taiwan", "zh_tw", 0x0404), - LANG("Croatian", "hr", 0x041A), - LANG("Czech", "cs", 0x0405), - LANG("Danish", "da", 0x0406), - LANG("Dutch - Netherlands", "nl_nl", 0x0413), - LANG("Dutch - Belgium", "nl_be", 0x0813), - LANG("English - Australia", "en_au", 0x0C09), - LANG("English - Belize", "en_bz", 0x2809), - LANG("English - Canada", "en_ca", 0x1009), - LANG("English - Caribbean", "en_cb", 0x2409), - LANG("English - Ireland", "en_ie", 0x1809), - LANG("English - Jamaica", "en_jm", 0x2009), - LANG("English - New Zealand", "en_nz", 0x1409), - LANG("English - Phillippines", "en_ph", 0x3409), - LANG("English - Southern Africa", "en_za", 0x1C09), - LANG("English - Trinidad", "en_tt", 0x2C09), - LANG("English - Great Britain", "en_gb", 0x0809), - LANG("English - United States", "en_us", 0x0409), - LANG("Estonian", "et", 0x0425), - LANG("Farsi", "fa", 0x0429), - LANG("Finnish", "fi", 0x040B), - LANG("Faroese", "fo", 0x0438), - LANG("French - France", "fr_fr", 0x040C), - LANG("French - Belgium", "fr_be", 0x080C), - LANG("French - Canada", "fr_ca", 0x0C0C), - LANG("French - Luxembourg", "fr_lu", 0x140C), - LANG("French - Switzerland", "fr_ch", 0x100C), - LANG("Gaelic - Ireland", "gd_ie", 0x083C), - LANG("Gaelic - Scotland", "gd", 0x043C), - LANG("German - Germany", "de_de", 0x0407), - LANG("German - Austria", "de_at", 0x0C07), - LANG("German - Liechtenstein", "de_li", 0x1407), - LANG("German - Luxembourg", "de_lu", 0x1007), - LANG("German - Switzerland", "de_ch", 0x0807), - LANG("Greek", "el", 0x0408), - LANG("Hebrew", "he", 0x040D), - LANG("Hindi", "hi", 0x0439), - LANG("Hungarian", "hu", 0x040E), - LANG("Icelandic", "is", 0x040F), - LANG("Indonesian", "id", 0x0421), - LANG("Italian - Italy", "it_it", 0x0410), - LANG("Italian - Switzerland", "it_ch", 0x0810), - LANG("Japanese", "ja", 0x0411), - LANG("Korean", "ko", 0x0412), - LANG("Latvian", "lv", 0x0426), - LANG("Lithuanian", "lt", 0x0427), - LANG("F.Y.R.O. Macedonia", "mk", 0x042F), - LANG("Malay - Malaysia", "ms_my", 0x043E), - LANG("Malay – Brunei", "ms_bn", 0x083E), - LANG("Maltese", "mt", 0x043A), - LANG("Marathi", "mr", 0x044E), - LANG("Norwegian - Bokml", "no_no", 0x0414), - LANG("Norwegian - Nynorsk", "no_no", 0x0814), - LANG("Polish", "pl", 0x0415), - LANG("Portuguese - Portugal", "pt_pt", 0x0816), - LANG("Portuguese - Brazil", "pt_br", 0x0416), - LANG("Raeto-Romance", "rm", 0x0417), - LANG("Romanian - Romania", "ro", 0x0418), - LANG("Romanian - Republic of Moldova", "ro_mo", 0x0818), - LANG("Russian", "ru", 0x0419), - LANG("Russian - Republic of Moldova", "ru_mo", 0x0819), - LANG("Sanskrit", "sa", 0x044F), - LANG("Serbian - Cyrillic", "sr_sp", 0x0C1A), - LANG("Serbian - Latin", "sr_sp", 0x081A), - LANG("Setsuana", "tn", 0x0432), - LANG("Slovenian", "sl", 0x0424), - LANG("Slovak", "sk", 0x041B), - LANG("Sorbian", "sb", 0x042E), - LANG("Spanish - Spain (Traditional)", "es_es", 0x040A), - LANG("Spanish - Argentina", "es_ar", 0x2C0A), - LANG("Spanish - Bolivia", "es_bo", 0x400A), - LANG("Spanish - Chile", "es_cl", 0x340A), - LANG("Spanish - Colombia", "es_co", 0x240A), - LANG("Spanish - Costa Rica", "es_cr", 0x140A), - LANG("Spanish - Dominican Republic", "es_do", 0x1C0A), - LANG("Spanish - Ecuador", "es_ec", 0x300A), - LANG("Spanish - Guatemala", "es_gt", 0x100A), - LANG("Spanish - Honduras", "es_hn", 0x480A), - LANG("Spanish - Mexico", "es_mx", 0x080A), - LANG("Spanish - Nicaragua", "es_ni", 0x4C0A), - LANG("Spanish - Panama", "es_pa", 0x180A), - LANG("Spanish - Peru", "es_pe", 0x280A), - LANG("Spanish - Puerto Rico", "es_pr", 0x500A), - LANG("Spanish - Paraguay", "es_py", 0x3C0A), - LANG("Spanish - El Salvador", "es_sv", 0x440A), - LANG("Spanish - Uruguay", "es_uy", 0x380A), - LANG("Spanish - Venezuela", "es_ve", 0x200A), - LANG("Southern Sotho", "st", 0x0430), - LANG("Swahili", "sw", 0x0441), - LANG("Swedish - Sweden", "sv_se", 0x041D), - LANG("Swedish - Finland", "sv_fi", 0x081D), - LANG("Tamil", "ta", 0x0449), - LANG("Tatar", "tt", 0X0444), - LANG("Thai", "th", 0x041E), - LANG("Turkish", "tr", 0x041F), - LANG("Tsonga", "ts", 0x0431), - LANG("Ukrainian", "uk", 0x0422), - LANG("Urdu", "ur", 0x0420), - LANG("Uzbek - Cyrillic", "uz_uz", 0x0843), - LANG("Uzbek – Latin", "uz_uz", 0x0443), - LANG("Vietnamese", "vi", 0x042A), - LANG("Xhosa", "xh", 0x0434), - LANG("Yiddish", "yi", 0x043D), - LANG("Zulu", "zu", 0x0435), - LANG(NULL, NULL, 0x0), -}; - -uint16_t get_usb_code_for_current_locale(void) -{ - char *locale; - char search_string[64]; - char *ptr; - struct lang_map_entry *lang; - - /* Get the current locale. */ - locale = setlocale(0, NULL); - if (!locale) - return 0x0; - - /* Make a copy of the current locale string. */ - strncpy(search_string, locale, sizeof(search_string)); - search_string[sizeof(search_string)-1] = '\0'; - - /* Chop off the encoding part, and make it lower case. */ - ptr = search_string; - while (*ptr) { - *ptr = tolower(*ptr); - if (*ptr == '.') { - *ptr = '\0'; - break; - } - ptr++; - } - - /* Find the entry which matches the string code of our locale. */ - lang = lang_map; - while (lang->string_code) { - if (!strcmp(lang->string_code, search_string)) { - return lang->usb_code; - } - lang++; - } - - /* There was no match. Find with just the language only. */ - /* Chop off the variant. Chop it off at the '_'. */ - ptr = search_string; - while (*ptr) { - *ptr = tolower(*ptr); - if (*ptr == '_') { - *ptr = '\0'; - break; - } - ptr++; - } - -#if 0 /* TODO: Do we need this? */ - /* Find the entry which matches the string code of our language. */ - lang = lang_map; - while (lang->string_code) { - if (!strcmp(lang->string_code, search_string)) { - return lang->usb_code; - } - lang++; - } -#endif - - /* Found nothing. */ - return 0x0; -} - -#ifdef __cplusplus -} -#endif diff --git a/dependencies/httplib/httplib.h b/dependencies/httplib/httplib.h index 04a552f0..062f66b8 100644 --- a/dependencies/httplib/httplib.h +++ b/dependencies/httplib/httplib.h @@ -1,14 +1,14 @@ // // httplib.h // -// Copyright (c) 2022 Yuji Hirose. All rights reserved. +// Copyright (c) 2024 Yuji Hirose. All rights reserved. // MIT License // #ifndef CPPHTTPLIB_HTTPLIB_H #define CPPHTTPLIB_HTTPLIB_H -#define CPPHTTPLIB_VERSION "0.10.7" +#define CPPHTTPLIB_VERSION "0.16.0" /* * Configuration @@ -70,16 +70,28 @@ #define CPPHTTPLIB_REDIRECT_MAX_COUNT 20 #endif +#ifndef CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT +#define CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT 1024 +#endif + #ifndef CPPHTTPLIB_PAYLOAD_MAX_LENGTH #define CPPHTTPLIB_PAYLOAD_MAX_LENGTH ((std::numeric_limits::max)()) #endif +#ifndef CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH +#define CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH 8192 +#endif + +#ifndef CPPHTTPLIB_RANGE_MAX_COUNT +#define CPPHTTPLIB_RANGE_MAX_COUNT 1024 +#endif + #ifndef CPPHTTPLIB_TCP_NODELAY #define CPPHTTPLIB_TCP_NODELAY false #endif #ifndef CPPHTTPLIB_RECV_BUFSIZ -#define CPPHTTPLIB_RECV_BUFSIZ size_t(4096u) +#define CPPHTTPLIB_RECV_BUFSIZ size_t(16384u) #endif #ifndef CPPHTTPLIB_COMPRESSION_BUFSIZ @@ -119,23 +131,25 @@ #endif //_CRT_NONSTDC_NO_DEPRECATE #if defined(_MSC_VER) +#if _MSC_VER < 1900 +#error Sorry, Visual Studio versions prior to 2015 are not supported +#endif + +#pragma comment(lib, "ws2_32.lib") + #ifdef _WIN64 using ssize_t = __int64; #else -using ssize_t = int; -#endif - -#if _MSC_VER < 1900 -#define snprintf _snprintf_s +using ssize_t = long; #endif #endif // _MSC_VER #ifndef S_ISREG -#define S_ISREG(m) (((m)&S_IFREG) == S_IFREG) +#define S_ISREG(m) (((m) & S_IFREG) == S_IFREG) #endif // S_ISREG #ifndef S_ISDIR -#define S_ISDIR(m) (((m)&S_IFDIR) == S_IFDIR) +#define S_ISDIR(m) (((m) & S_IFDIR) == S_IFDIR) #endif // S_ISDIR #ifndef NOMINMAX @@ -150,14 +164,6 @@ using ssize_t = int; #define WSA_FLAG_NO_HANDLE_INHERIT 0x80 #endif -#ifdef _MSC_VER -#pragma comment(lib, "ws2_32.lib") -#endif - -#ifndef strcasecmp -#define strcasecmp _stricmp -#endif // strcasecmp - using socket_t = SOCKET; #ifdef CPPHTTPLIB_USE_POLL #define poll(fds, nfds, timeout) WSAPoll(fds, nfds, timeout) @@ -166,8 +172,15 @@ using socket_t = SOCKET; #else // not _WIN32 #include -#include +#if !defined(_AIX) && !defined(__MVS__) #include +#endif +#ifdef __MVS__ +#include +#ifndef NI_MAXHOST +#define NI_MAXHOST 1025 +#endif +#endif #include #include #include @@ -180,8 +193,10 @@ using socket_t = SOCKET; #endif #include #include +#include #include #include +#include #include using socket_t = int; @@ -197,7 +212,9 @@ using socket_t = int; #include #include #include +#include #include +#include #include #include #include @@ -214,6 +231,9 @@ using socket_t = int; #include #include #include +#include +#include +#include #ifdef CPPHTTPLIB_OPENSSL_SUPPORT #ifdef _WIN32 @@ -228,9 +248,14 @@ using socket_t = int; #ifdef _MSC_VER #pragma comment(lib, "crypt32.lib") -#pragma comment(lib, "cryptui.lib") #endif -#endif //_WIN32 +#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__) +#include +#if TARGET_OS_OSX +#include +#include +#endif // TARGET_OS_OSX +#endif // _WIN32 #include #include @@ -244,16 +269,10 @@ using socket_t = int; #include #include -#if OPENSSL_VERSION_NUMBER < 0x1010100fL -#error Sorry, OpenSSL versions prior to 1.1.1 are not supported +#if OPENSSL_VERSION_NUMBER < 0x30000000L +#error Sorry, OpenSSL versions prior to 3.0.0 are not supported #endif -#if OPENSSL_VERSION_NUMBER < 0x10100000L -#include -inline const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *asn1) { - return M_ASN1_STRING_data(asn1); -} -#endif #endif #ifdef CPPHTTPLIB_ZLIB_SUPPORT @@ -303,8 +322,111 @@ struct ci { } }; +// This is based on +// "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4189". + +struct scope_exit { + explicit scope_exit(std::function &&f) + : exit_function(std::move(f)), execute_on_destruction{true} {} + + scope_exit(scope_exit &&rhs) noexcept + : exit_function(std::move(rhs.exit_function)), + execute_on_destruction{rhs.execute_on_destruction} { + rhs.release(); + } + + ~scope_exit() { + if (execute_on_destruction) { this->exit_function(); } + } + + void release() { this->execute_on_destruction = false; } + +private: + scope_exit(const scope_exit &) = delete; + void operator=(const scope_exit &) = delete; + scope_exit &operator=(scope_exit &&) = delete; + + std::function exit_function; + bool execute_on_destruction; +}; + } // namespace detail +enum StatusCode { + // Information responses + Continue_100 = 100, + SwitchingProtocol_101 = 101, + Processing_102 = 102, + EarlyHints_103 = 103, + + // Successful responses + OK_200 = 200, + Created_201 = 201, + Accepted_202 = 202, + NonAuthoritativeInformation_203 = 203, + NoContent_204 = 204, + ResetContent_205 = 205, + PartialContent_206 = 206, + MultiStatus_207 = 207, + AlreadyReported_208 = 208, + IMUsed_226 = 226, + + // Redirection messages + MultipleChoices_300 = 300, + MovedPermanently_301 = 301, + Found_302 = 302, + SeeOther_303 = 303, + NotModified_304 = 304, + UseProxy_305 = 305, + unused_306 = 306, + TemporaryRedirect_307 = 307, + PermanentRedirect_308 = 308, + + // Client error responses + BadRequest_400 = 400, + Unauthorized_401 = 401, + PaymentRequired_402 = 402, + Forbidden_403 = 403, + NotFound_404 = 404, + MethodNotAllowed_405 = 405, + NotAcceptable_406 = 406, + ProxyAuthenticationRequired_407 = 407, + RequestTimeout_408 = 408, + Conflict_409 = 409, + Gone_410 = 410, + LengthRequired_411 = 411, + PreconditionFailed_412 = 412, + PayloadTooLarge_413 = 413, + UriTooLong_414 = 414, + UnsupportedMediaType_415 = 415, + RangeNotSatisfiable_416 = 416, + ExpectationFailed_417 = 417, + ImATeapot_418 = 418, + MisdirectedRequest_421 = 421, + UnprocessableContent_422 = 422, + Locked_423 = 423, + FailedDependency_424 = 424, + TooEarly_425 = 425, + UpgradeRequired_426 = 426, + PreconditionRequired_428 = 428, + TooManyRequests_429 = 429, + RequestHeaderFieldsTooLarge_431 = 431, + UnavailableForLegalReasons_451 = 451, + + // Server error responses + InternalServerError_500 = 500, + NotImplemented_501 = 501, + BadGateway_502 = 502, + ServiceUnavailable_503 = 503, + GatewayTimeout_504 = 504, + HttpVersionNotSupported_505 = 505, + VariantAlsoNegotiates_506 = 506, + InsufficientStorage_507 = 507, + LoopDetected_508 = 508, + NotExtended_510 = 510, + NetworkAuthenticationRequired_511 = 511, +}; + using Headers = std::multimap; using Params = std::multimap; @@ -334,17 +456,18 @@ public: DataSink &operator=(DataSink &&) = delete; std::function write; - std::function done; std::function is_writable; + std::function done; + std::function done_with_trailer; std::ostream os; private: - class data_sink_streambuf : public std::streambuf { + class data_sink_streambuf final : public std::streambuf { public: explicit data_sink_streambuf(DataSink &sink) : sink_(sink) {} protected: - std::streamsize xsputn(const char *s, std::streamsize n) { + std::streamsize xsputn(const char *s, std::streamsize n) override { sink_.write(s, static_cast(n)); return n; } @@ -364,6 +487,14 @@ using ContentProviderWithoutLength = using ContentProviderResourceReleaser = std::function; +struct MultipartFormDataProvider { + std::string name; + ContentProviderWithoutLength provider; + std::string filename; + std::string content_type; +}; +using MultipartFormDataProviderItems = std::vector; + using ContentReceiverWithProgress = std::function; @@ -408,6 +539,8 @@ struct Request { std::string remote_addr; int remote_port = -1; + std::string local_addr; + int local_port = -1; // for server std::string version; @@ -416,6 +549,7 @@ struct Request { MultipartFormDataMap files; Ranges ranges; Match matches; + std::unordered_map path_params; // for client ResponseHandler response_handler; @@ -425,22 +559,21 @@ struct Request { const SSL *ssl = nullptr; #endif - bool has_header(const char *key) const; - std::string get_header_value(const char *key, size_t id = 0) const; - template - T get_header_value(const char *key, size_t id = 0) const; - size_t get_header_value_count(const char *key) const; - void set_header(const char *key, const char *val); - void set_header(const char *key, const std::string &val); + bool has_header(const std::string &key) const; + std::string get_header_value(const std::string &key, size_t id = 0) const; + uint64_t get_header_value_u64(const std::string &key, size_t id = 0) const; + size_t get_header_value_count(const std::string &key) const; + void set_header(const std::string &key, const std::string &val); - bool has_param(const char *key) const; - std::string get_param_value(const char *key, size_t id = 0) const; - size_t get_param_value_count(const char *key) const; + bool has_param(const std::string &key) const; + std::string get_param_value(const std::string &key, size_t id = 0) const; + size_t get_param_value_count(const std::string &key) const; bool is_multipart_form_data() const; - bool has_file(const char *key) const; - MultipartFormData get_file_value(const char *key) const; + bool has_file(const std::string &key) const; + MultipartFormData get_file_value(const std::string &key) const; + std::vector get_file_values(const std::string &key) const; // private members... size_t redirect_count_ = CPPHTTPLIB_REDIRECT_MAX_COUNT; @@ -458,29 +591,27 @@ struct Response { std::string body; std::string location; // Redirect location - bool has_header(const char *key) const; - std::string get_header_value(const char *key, size_t id = 0) const; - template - T get_header_value(const char *key, size_t id = 0) const; - size_t get_header_value_count(const char *key) const; - void set_header(const char *key, const char *val); - void set_header(const char *key, const std::string &val); + bool has_header(const std::string &key) const; + std::string get_header_value(const std::string &key, size_t id = 0) const; + uint64_t get_header_value_u64(const std::string &key, size_t id = 0) const; + size_t get_header_value_count(const std::string &key) const; + void set_header(const std::string &key, const std::string &val); - void set_redirect(const char *url, int status = 302); - void set_redirect(const std::string &url, int status = 302); - void set_content(const char *s, size_t n, const char *content_type); - void set_content(const std::string &s, const char *content_type); + void set_redirect(const std::string &url, int status = StatusCode::Found_302); + void set_content(const char *s, size_t n, const std::string &content_type); + void set_content(const std::string &s, const std::string &content_type); + void set_content(std::string &&s, const std::string &content_type); void set_content_provider( - size_t length, const char *content_type, ContentProvider provider, + size_t length, const std::string &content_type, ContentProvider provider, ContentProviderResourceReleaser resource_releaser = nullptr); void set_content_provider( - const char *content_type, ContentProviderWithoutLength provider, + const std::string &content_type, ContentProviderWithoutLength provider, ContentProviderResourceReleaser resource_releaser = nullptr); void set_chunked_content_provider( - const char *content_type, ContentProviderWithoutLength provider, + const std::string &content_type, ContentProviderWithoutLength provider, ContentProviderResourceReleaser resource_releaser = nullptr); Response() = default; @@ -512,6 +643,7 @@ public: virtual ssize_t read(char *ptr, size_t size) = 0; virtual ssize_t write(const char *ptr, size_t size) = 0; virtual void get_remote_ip_and_port(std::string &ip, int &port) const = 0; + virtual void get_local_ip_and_port(std::string &ip, int &port) const = 0; virtual socket_t socket() const = 0; template @@ -525,15 +657,16 @@ public: TaskQueue() = default; virtual ~TaskQueue() = default; - virtual void enqueue(std::function fn) = 0; + virtual bool enqueue(std::function fn) = 0; virtual void shutdown() = 0; virtual void on_idle() {} }; -class ThreadPool : public TaskQueue { +class ThreadPool final : public TaskQueue { public: - explicit ThreadPool(size_t n) : shutdown_(false) { + explicit ThreadPool(size_t n, size_t mqr = 0) + : shutdown_(false), max_queued_requests_(mqr) { while (n) { threads_.emplace_back(worker(*this)); n--; @@ -543,10 +676,17 @@ public: ThreadPool(const ThreadPool &) = delete; ~ThreadPool() override = default; - void enqueue(std::function fn) override { - std::unique_lock lock(mutex_); - jobs_.push_back(std::move(fn)); + bool enqueue(std::function fn) override { + { + std::unique_lock lock(mutex_); + if (max_queued_requests_ > 0 && jobs_.size() >= max_queued_requests_) { + return false; + } + jobs_.push_back(std::move(fn)); + } + cond_.notify_one(); + return true; } void shutdown() override { @@ -596,6 +736,7 @@ private: std::list> jobs_; bool shutdown_; + size_t max_queued_requests_ = 0; std::condition_variable cond_; std::mutex mutex_; @@ -607,12 +748,88 @@ using SocketOptions = std::function; void default_socket_options(socket_t sock); +const char *status_message(int status); + +std::string get_bearer_token_auth(const Request &req); + +namespace detail { + +class MatcherBase { +public: + virtual ~MatcherBase() = default; + + // Match request path and populate its matches and + virtual bool match(Request &request) const = 0; +}; + +/** + * Captures parameters in request path and stores them in Request::path_params + * + * Capture name is a substring of a pattern from : to /. + * The rest of the pattern is matched agains the request path directly + * Parameters are captured starting from the next character after + * the end of the last matched static pattern fragment until the next /. + * + * Example pattern: + * "/path/fragments/:capture/more/fragments/:second_capture" + * Static fragments: + * "/path/fragments/", "more/fragments/" + * + * Given the following request path: + * "/path/fragments/:1/more/fragments/:2" + * the resulting capture will be + * {{"capture", "1"}, {"second_capture", "2"}} + */ +class PathParamsMatcher final : public MatcherBase { +public: + PathParamsMatcher(const std::string &pattern); + + bool match(Request &request) const override; + +private: + static constexpr char marker = ':'; + // Treat segment separators as the end of path parameter capture + // Does not need to handle query parameters as they are parsed before path + // matching + static constexpr char separator = '/'; + + // Contains static path fragments to match against, excluding the '/' after + // path params + // Fragments are separated by path params + std::vector static_fragments_; + // Stores the names of the path parameters to be used as keys in the + // Request::path_params map + std::vector param_names_; +}; + +/** + * Performs std::regex_match on request path + * and stores the result in Request::matches + * + * Note that regex match is performed directly on the whole request. + * This means that wildcard patterns may match multiple path segments with /: + * "/begin/(.*)/end" will match both "/begin/middle/end" and "/begin/1/2/end". + */ +class RegexMatcher final : public MatcherBase { +public: + RegexMatcher(const std::string &pattern) : regex_(pattern) {} + + bool match(Request &request) const override; + +private: + std::regex regex_; +}; + +ssize_t write_headers(Stream &strm, const Headers &headers); + +} // namespace detail + class Server { public: using Handler = std::function; using ExceptionHandler = - std::function; + std::function; enum class HandlerResponse { Handled, @@ -649,12 +866,18 @@ public: bool set_mount_point(const std::string &mount_point, const std::string &dir, Headers headers = Headers()); bool remove_mount_point(const std::string &mount_point); - Server &set_file_extension_and_mimetype_mapping(const char *ext, - const char *mime); + Server &set_file_extension_and_mimetype_mapping(const std::string &ext, + const std::string &mime); + Server &set_default_file_mimetype(const std::string &mime); Server &set_file_request_handler(Handler handler); - Server &set_error_handler(HandlerWithResponse handler); - Server &set_error_handler(Handler handler); + template + Server &set_error_handler(ErrorHandlerFunc &&handler) { + return set_error_handler_core( + std::forward(handler), + std::is_convertible{}); + } + Server &set_exception_handler(ExceptionHandler handler); Server &set_pre_routing_handler(HandlerWithResponse handler); Server &set_post_routing_handler(Handler handler); @@ -667,6 +890,8 @@ public: Server &set_socket_options(SocketOptions socket_options); Server &set_default_headers(Headers headers); + Server & + set_header_writer(std::function const &writer); Server &set_keep_alive_max_count(size_t count); Server &set_keep_alive_timeout(time_t sec); @@ -685,13 +910,14 @@ public: Server &set_payload_max_length(size_t length); - bool bind_to_port(const char *host, int port, int socket_flags = 0); - int bind_to_any_port(const char *host, int socket_flags = 0); + bool bind_to_port(const std::string &host, int port, int socket_flags = 0); + int bind_to_any_port(const std::string &host, int socket_flags = 0); bool listen_after_bind(); - bool listen(const char *host, int port, int socket_flags = 0); + bool listen(const std::string &host, int port, int socket_flags = 0); bool is_running() const; + void wait_until_ready() const; void stop(); std::function new_task_queue; @@ -701,7 +927,7 @@ protected: bool &connection_closed, const std::function &setup_request); - std::atomic svr_sock_; + std::atomic svr_sock_{INVALID_SOCKET}; size_t keep_alive_max_count_ = CPPHTTPLIB_KEEPALIVE_MAX_COUNT; time_t keep_alive_timeout_sec_ = CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND; time_t read_timeout_sec_ = CPPHTTPLIB_READ_TIMEOUT_SECOND; @@ -713,28 +939,37 @@ protected: size_t payload_max_length_ = CPPHTTPLIB_PAYLOAD_MAX_LENGTH; private: - using Handlers = std::vector>; + using Handlers = + std::vector, Handler>>; using HandlersForContentReader = - std::vector>; + std::vector, + HandlerWithContentReader>>; - socket_t create_server_socket(const char *host, int port, int socket_flags, + static std::unique_ptr + make_matcher(const std::string &pattern); + + Server &set_error_handler_core(HandlerWithResponse handler, std::true_type); + Server &set_error_handler_core(Handler handler, std::false_type); + + socket_t create_server_socket(const std::string &host, int port, + int socket_flags, SocketOptions socket_options) const; - int bind_internal(const char *host, int port, int socket_flags); + int bind_internal(const std::string &host, int port, int socket_flags); bool listen_internal(); bool routing(Request &req, Response &res, Stream &strm); bool handle_file_request(const Request &req, Response &res, bool head = false); - bool dispatch_request(Request &req, Response &res, const Handlers &handlers); - bool - dispatch_request_for_content_reader(Request &req, Response &res, - ContentReader content_reader, - const HandlersForContentReader &handlers); + bool dispatch_request(Request &req, Response &res, + const Handlers &handlers) const; + bool dispatch_request_for_content_reader( + Request &req, Response &res, ContentReader content_reader, + const HandlersForContentReader &handlers) const; - bool parse_request_line(const char *s, Request &req); + bool parse_request_line(const char *s, Request &req) const; void apply_ranges(const Request &req, Response &res, - std::string &content_type, std::string &boundary); - bool write_response(Stream &strm, bool close_connection, const Request &req, + std::string &content_type, std::string &boundary) const; + bool write_response(Stream &strm, bool close_connection, Request &req, Response &res); bool write_response_with_content(Stream &strm, bool close_connection, const Request &req, Response &res); @@ -752,21 +987,24 @@ private: ContentReceiver multipart_receiver); bool read_content_core(Stream &strm, Request &req, Response &res, ContentReceiver receiver, - MultipartContentHeader mulitpart_header, - ContentReceiver multipart_receiver); + MultipartContentHeader multipart_header, + ContentReceiver multipart_receiver) const; virtual bool process_and_close_socket(socket_t sock); + std::atomic is_running_{false}; + std::atomic done_{false}; + struct MountPointEntry { std::string mount_point; std::string base_dir; Headers headers; }; std::vector base_dirs_; - - std::atomic is_running_; std::map file_extension_and_mimetype_map_; + std::string default_file_mimetype_ = "application/octet-stream"; Handler file_request_handler_; + Handlers get_handlers_; Handlers post_handlers_; HandlersForContentReader post_handlers_for_content_reader_; @@ -777,18 +1015,22 @@ private: Handlers delete_handlers_; HandlersForContentReader delete_handlers_for_content_reader_; Handlers options_handlers_; + HandlerWithResponse error_handler_; ExceptionHandler exception_handler_; HandlerWithResponse pre_routing_handler_; Handler post_routing_handler_; - Logger logger_; Expect100ContinueHandler expect_100_continue_handler_; + Logger logger_; + int address_family_ = AF_UNSPEC; bool tcp_nodelay_ = CPPHTTPLIB_TCP_NODELAY; SocketOptions socket_options_ = default_socket_options; Headers default_headers_; + std::function header_writer_ = + detail::write_headers; }; enum class Error { @@ -806,14 +1048,19 @@ enum class Error { UnsupportedMultipartBoundaryChars, Compression, ConnectionTimeout, + ProxyConnection, + + // For internal use only + SSLPeerCouldBeClosed_, }; -std::string to_string(const Error error); +std::string to_string(Error error); std::ostream &operator<<(std::ostream &os, const Error &obj); class Result { public: + Result() = default; Result(std::unique_ptr &&res, Error err, Headers &&request_headers = Headers{}) : res_(std::move(res)), err_(err), @@ -833,15 +1080,16 @@ public: Error error() const { return err_; } // Request Headers - bool has_request_header(const char *key) const; - std::string get_request_header_value(const char *key, size_t id = 0) const; - template - T get_request_header_value(const char *key, size_t id = 0) const; - size_t get_request_header_value_count(const char *key) const; + bool has_request_header(const std::string &key) const; + std::string get_request_header_value(const std::string &key, + size_t id = 0) const; + uint64_t get_request_header_value_u64(const std::string &key, + size_t id = 0) const; + size_t get_request_header_value_count(const std::string &key) const; private: std::unique_ptr res_; - Error err_; + Error err_ = Error::Unknown; Headers request_headers_; }; @@ -859,130 +1107,204 @@ public: virtual bool is_valid() const; - Result Get(const char *path); - Result Get(const char *path, const Headers &headers); - Result Get(const char *path, Progress progress); - Result Get(const char *path, const Headers &headers, Progress progress); - Result Get(const char *path, ContentReceiver content_receiver); - Result Get(const char *path, const Headers &headers, - ContentReceiver content_receiver); - Result Get(const char *path, ContentReceiver content_receiver, + Result Get(const std::string &path); + Result Get(const std::string &path, const Headers &headers); + Result Get(const std::string &path, Progress progress); + Result Get(const std::string &path, const Headers &headers, Progress progress); - Result Get(const char *path, const Headers &headers, - ContentReceiver content_receiver, Progress progress); - Result Get(const char *path, ResponseHandler response_handler, + Result Get(const std::string &path, ContentReceiver content_receiver); + Result Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver); - Result Get(const char *path, const Headers &headers, + Result Get(const std::string &path, ContentReceiver content_receiver, + Progress progress); + Result Get(const std::string &path, const Headers &headers, + ContentReceiver content_receiver, Progress progress); + Result Get(const std::string &path, ResponseHandler response_handler, + ContentReceiver content_receiver); + Result Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver); - Result Get(const char *path, ResponseHandler response_handler, + Result Get(const std::string &path, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress); - Result Get(const char *path, const Headers &headers, + Result Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress); - Result Get(const char *path, const Params ¶ms, const Headers &headers, + Result Get(const std::string &path, const Params ¶ms, + const Headers &headers, Progress progress = nullptr); + Result Get(const std::string &path, const Params ¶ms, + const Headers &headers, ContentReceiver content_receiver, Progress progress = nullptr); - Result Get(const char *path, const Params ¶ms, const Headers &headers, + Result Get(const std::string &path, const Params ¶ms, + const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress = nullptr); - Result Get(const char *path, const Params ¶ms, const Headers &headers, - ResponseHandler response_handler, ContentReceiver content_receiver, - Progress progress = nullptr); - Result Head(const char *path); - Result Head(const char *path, const Headers &headers); + Result Head(const std::string &path); + Result Head(const std::string &path, const Headers &headers); - Result Post(const char *path); - Result Post(const char *path, const char *body, size_t content_length, - const char *content_type); - Result Post(const char *path, const Headers &headers, const char *body, - size_t content_length, const char *content_type); - Result Post(const char *path, const std::string &body, - const char *content_type); - Result Post(const char *path, const Headers &headers, const std::string &body, - const char *content_type); - Result Post(const char *path, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Post(const char *path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Post(const char *path, const Headers &headers, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Post(const char *path, const Headers &headers, + Result Post(const std::string &path); + Result Post(const std::string &path, const Headers &headers); + Result Post(const std::string &path, const char *body, size_t content_length, + const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, const char *body, + size_t content_length, const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, const char *body, + size_t content_length, const std::string &content_type, + Progress progress); + Result Post(const std::string &path, const std::string &body, + const std::string &content_type); + Result Post(const std::string &path, const std::string &body, + const std::string &content_type, Progress progress); + Result Post(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type, + Progress progress); + Result Post(const std::string &path, size_t content_length, + ContentProvider content_provider, + const std::string &content_type); + Result Post(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Post(const char *path, const Params ¶ms); - Result Post(const char *path, const Headers &headers, const Params ¶ms); - Result Post(const char *path, const MultipartFormDataItems &items); - Result Post(const char *path, const Headers &headers, + const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, + size_t content_length, ContentProvider content_provider, + const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, + ContentProviderWithoutLength content_provider, + const std::string &content_type); + Result Post(const std::string &path, const Params ¶ms); + Result Post(const std::string &path, const Headers &headers, + const Params ¶ms); + Result Post(const std::string &path, const Headers &headers, + const Params ¶ms, Progress progress); + Result Post(const std::string &path, const MultipartFormDataItems &items); + Result Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items); - Result Post(const char *path, const Headers &headers, + Result Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items, const std::string &boundary); + Result Post(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, + const MultipartFormDataProviderItems &provider_items); - Result Put(const char *path); - Result Put(const char *path, const char *body, size_t content_length, - const char *content_type); - Result Put(const char *path, const Headers &headers, const char *body, - size_t content_length, const char *content_type); - Result Put(const char *path, const std::string &body, - const char *content_type); - Result Put(const char *path, const Headers &headers, const std::string &body, - const char *content_type); - Result Put(const char *path, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Put(const char *path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Put(const char *path, const Headers &headers, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Put(const char *path, const Headers &headers, + Result Put(const std::string &path); + Result Put(const std::string &path, const char *body, size_t content_length, + const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, const char *body, + size_t content_length, const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, const char *body, + size_t content_length, const std::string &content_type, + Progress progress); + Result Put(const std::string &path, const std::string &body, + const std::string &content_type); + Result Put(const std::string &path, const std::string &body, + const std::string &content_type, Progress progress); + Result Put(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type, + Progress progress); + Result Put(const std::string &path, size_t content_length, + ContentProvider content_provider, const std::string &content_type); + Result Put(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Put(const char *path, const Params ¶ms); - Result Put(const char *path, const Headers &headers, const Params ¶ms); + const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, + size_t content_length, ContentProvider content_provider, + const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, + ContentProviderWithoutLength content_provider, + const std::string &content_type); + Result Put(const std::string &path, const Params ¶ms); + Result Put(const std::string &path, const Headers &headers, + const Params ¶ms); + Result Put(const std::string &path, const Headers &headers, + const Params ¶ms, Progress progress); + Result Put(const std::string &path, const MultipartFormDataItems &items); + Result Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items); + Result Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, const std::string &boundary); + Result Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, + const MultipartFormDataProviderItems &provider_items); - Result Patch(const char *path); - Result Patch(const char *path, const char *body, size_t content_length, - const char *content_type); - Result Patch(const char *path, const Headers &headers, const char *body, - size_t content_length, const char *content_type); - Result Patch(const char *path, const std::string &body, - const char *content_type); - Result Patch(const char *path, const Headers &headers, - const std::string &body, const char *content_type); - Result Patch(const char *path, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Patch(const char *path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Patch(const char *path, const Headers &headers, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Patch(const char *path, const Headers &headers, + Result Patch(const std::string &path); + Result Patch(const std::string &path, const char *body, size_t content_length, + const std::string &content_type); + Result Patch(const std::string &path, const char *body, size_t content_length, + const std::string &content_type, Progress progress); + Result Patch(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type); + Result Patch(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type, Progress progress); + Result Patch(const std::string &path, const std::string &body, + const std::string &content_type); + Result Patch(const std::string &path, const std::string &body, + const std::string &content_type, Progress progress); + Result Patch(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type); + Result Patch(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type, + Progress progress); + Result Patch(const std::string &path, size_t content_length, + ContentProvider content_provider, + const std::string &content_type); + Result Patch(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type); + const std::string &content_type); + Result Patch(const std::string &path, const Headers &headers, + size_t content_length, ContentProvider content_provider, + const std::string &content_type); + Result Patch(const std::string &path, const Headers &headers, + ContentProviderWithoutLength content_provider, + const std::string &content_type); - Result Delete(const char *path); - Result Delete(const char *path, const Headers &headers); - Result Delete(const char *path, const char *body, size_t content_length, - const char *content_type); - Result Delete(const char *path, const Headers &headers, const char *body, - size_t content_length, const char *content_type); - Result Delete(const char *path, const std::string &body, - const char *content_type); - Result Delete(const char *path, const Headers &headers, - const std::string &body, const char *content_type); + Result Delete(const std::string &path); + Result Delete(const std::string &path, const Headers &headers); + Result Delete(const std::string &path, const char *body, + size_t content_length, const std::string &content_type); + Result Delete(const std::string &path, const char *body, + size_t content_length, const std::string &content_type, + Progress progress); + Result Delete(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type); + Result Delete(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type, Progress progress); + Result Delete(const std::string &path, const std::string &body, + const std::string &content_type); + Result Delete(const std::string &path, const std::string &body, + const std::string &content_type, Progress progress); + Result Delete(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type); + Result Delete(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type, + Progress progress); - Result Options(const char *path); - Result Options(const char *path, const Headers &headers); + Result Options(const std::string &path); + Result Options(const std::string &path, const Headers &headers); bool send(Request &req, Response &res, Error &error); Result send(const Request &req); - size_t is_socket_open() const; - void stop(); + std::string host() const; + int port() const; + + size_t is_socket_open() const; + socket_t socket() const; + void set_hostname_addr_map(std::map addr_map); void set_default_headers(Headers headers); + void + set_header_writer(std::function const &writer); + void set_address_family(int family); void set_tcp_nodelay(bool on); void set_socket_options(SocketOptions socket_options); @@ -1000,10 +1322,11 @@ public: template void set_write_timeout(const std::chrono::duration &duration); - void set_basic_auth(const char *username, const char *password); - void set_bearer_token_auth(const char *token); + void set_basic_auth(const std::string &username, const std::string &password); + void set_bearer_token_auth(const std::string &token); #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_digest_auth(const char *username, const char *password); + void set_digest_auth(const std::string &username, + const std::string &password); #endif void set_keep_alive(bool on); @@ -1015,19 +1338,22 @@ public: void set_decompress(bool on); - void set_interface(const char *intf); + void set_interface(const std::string &intf); - void set_proxy(const char *host, int port); - void set_proxy_basic_auth(const char *username, const char *password); - void set_proxy_bearer_token_auth(const char *token); + void set_proxy(const std::string &host, int port); + void set_proxy_basic_auth(const std::string &username, + const std::string &password); + void set_proxy_bearer_token_auth(const std::string &token); #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_proxy_digest_auth(const char *username, const char *password); + void set_proxy_digest_auth(const std::string &username, + const std::string &password); #endif #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_ca_cert_path(const char *ca_cert_file_path, - const char *ca_cert_dir_path = nullptr); + void set_ca_cert_path(const std::string &ca_cert_file_path, + const std::string &ca_cert_dir_path = std::string()); void set_ca_cert_store(X509_STORE *ca_cert_store); + X509_STORE *create_ca_cert_store(const char *ca_cert, std::size_t size) const; #endif #ifdef CPPHTTPLIB_OPENSSL_SUPPORT @@ -1046,8 +1372,6 @@ protected: bool is_open() const { return sock != INVALID_SOCKET; } }; - Result send_(Request &&req); - virtual bool create_and_connect_socket(Socket &socket, Error &error); // All of: @@ -1058,18 +1382,18 @@ protected: // Also, shutdown_ssl and close_socket should also NOT be called concurrently // with a DIFFERENT thread sending requests using that socket. virtual void shutdown_ssl(Socket &socket, bool shutdown_gracefully); - void shutdown_socket(Socket &socket); + void shutdown_socket(Socket &socket) const; void close_socket(Socket &socket); bool process_request(Stream &strm, Request &req, Response &res, bool close_connection, Error &error); bool write_content_with_provider(Stream &strm, const Request &req, - Error &error); + Error &error) const; void copy_settings(const ClientImpl &rhs); - // Socket endoint information + // Socket endpoint information const std::string host_; const int port_; const std::string host_and_port_; @@ -1090,6 +1414,10 @@ protected: // Default headers Headers default_headers_; + // Header writer + std::function header_writer_ = + detail::write_headers; + // Settings std::string client_cert_path_; std::string client_key_path_; @@ -1148,24 +1476,31 @@ protected: Logger logger_; private: + bool send_(Request &req, Response &res, Error &error); + Result send_(Request &&req); + socket_t create_client_socket(Error &error) const; - bool read_response_line(Stream &strm, const Request &req, Response &res); + bool read_response_line(Stream &strm, const Request &req, + Response &res) const; bool write_request(Stream &strm, Request &req, bool close_connection, Error &error); bool redirect(Request &req, Response &res, Error &error); bool handle_request(Stream &strm, Request &req, Response &res, bool close_connection, Error &error); std::unique_ptr send_with_content_provider( - Request &req, - // const char *method, const char *path, const Headers &headers, - const char *body, size_t content_length, ContentProvider content_provider, + Request &req, const char *body, size_t content_length, + ContentProvider content_provider, ContentProviderWithoutLength content_provider_without_length, - const char *content_type, Error &error); + const std::string &content_type, Error &error); Result send_with_content_provider( - const char *method, const char *path, const Headers &headers, - const char *body, size_t content_length, ContentProvider content_provider, + const std::string &method, const std::string &path, + const Headers &headers, const char *body, size_t content_length, + ContentProvider content_provider, ContentProviderWithoutLength content_provider_without_length, - const char *content_type); + const std::string &content_type, Progress progress); + ContentProviderWithoutLength get_multipart_content_provider( + const std::string &boundary, const MultipartFormDataItems &items, + const MultipartFormDataProviderItems &provider_items) const; std::string adjust_host_string(const std::string &host) const; @@ -1196,128 +1531,204 @@ public: bool is_valid() const; - Result Get(const char *path); - Result Get(const char *path, const Headers &headers); - Result Get(const char *path, Progress progress); - Result Get(const char *path, const Headers &headers, Progress progress); - Result Get(const char *path, ContentReceiver content_receiver); - Result Get(const char *path, const Headers &headers, - ContentReceiver content_receiver); - Result Get(const char *path, ContentReceiver content_receiver, + Result Get(const std::string &path); + Result Get(const std::string &path, const Headers &headers); + Result Get(const std::string &path, Progress progress); + Result Get(const std::string &path, const Headers &headers, Progress progress); - Result Get(const char *path, const Headers &headers, - ContentReceiver content_receiver, Progress progress); - Result Get(const char *path, ResponseHandler response_handler, + Result Get(const std::string &path, ContentReceiver content_receiver); + Result Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver); - Result Get(const char *path, const Headers &headers, + Result Get(const std::string &path, ContentReceiver content_receiver, + Progress progress); + Result Get(const std::string &path, const Headers &headers, + ContentReceiver content_receiver, Progress progress); + Result Get(const std::string &path, ResponseHandler response_handler, + ContentReceiver content_receiver); + Result Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver); - Result Get(const char *path, const Headers &headers, + Result Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress); - Result Get(const char *path, ResponseHandler response_handler, + Result Get(const std::string &path, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress); - Result Get(const char *path, const Params ¶ms, const Headers &headers, + Result Get(const std::string &path, const Params ¶ms, + const Headers &headers, Progress progress = nullptr); + Result Get(const std::string &path, const Params ¶ms, + const Headers &headers, ContentReceiver content_receiver, Progress progress = nullptr); - Result Get(const char *path, const Params ¶ms, const Headers &headers, + Result Get(const std::string &path, const Params ¶ms, + const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress = nullptr); - Result Get(const char *path, const Params ¶ms, const Headers &headers, - ResponseHandler response_handler, ContentReceiver content_receiver, - Progress progress = nullptr); - Result Head(const char *path); - Result Head(const char *path, const Headers &headers); + Result Head(const std::string &path); + Result Head(const std::string &path, const Headers &headers); - Result Post(const char *path); - Result Post(const char *path, const char *body, size_t content_length, - const char *content_type); - Result Post(const char *path, const Headers &headers, const char *body, - size_t content_length, const char *content_type); - Result Post(const char *path, const std::string &body, - const char *content_type); - Result Post(const char *path, const Headers &headers, const std::string &body, - const char *content_type); - Result Post(const char *path, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Post(const char *path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Post(const char *path, const Headers &headers, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Post(const char *path, const Headers &headers, + Result Post(const std::string &path); + Result Post(const std::string &path, const Headers &headers); + Result Post(const std::string &path, const char *body, size_t content_length, + const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, const char *body, + size_t content_length, const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, const char *body, + size_t content_length, const std::string &content_type, + Progress progress); + Result Post(const std::string &path, const std::string &body, + const std::string &content_type); + Result Post(const std::string &path, const std::string &body, + const std::string &content_type, Progress progress); + Result Post(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type, + Progress progress); + Result Post(const std::string &path, size_t content_length, + ContentProvider content_provider, + const std::string &content_type); + Result Post(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Post(const char *path, const Params ¶ms); - Result Post(const char *path, const Headers &headers, const Params ¶ms); - Result Post(const char *path, const MultipartFormDataItems &items); - Result Post(const char *path, const Headers &headers, + const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, + size_t content_length, ContentProvider content_provider, + const std::string &content_type); + Result Post(const std::string &path, const Headers &headers, + ContentProviderWithoutLength content_provider, + const std::string &content_type); + Result Post(const std::string &path, const Params ¶ms); + Result Post(const std::string &path, const Headers &headers, + const Params ¶ms); + Result Post(const std::string &path, const Headers &headers, + const Params ¶ms, Progress progress); + Result Post(const std::string &path, const MultipartFormDataItems &items); + Result Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items); - Result Post(const char *path, const Headers &headers, + Result Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items, const std::string &boundary); - Result Put(const char *path); - Result Put(const char *path, const char *body, size_t content_length, - const char *content_type); - Result Put(const char *path, const Headers &headers, const char *body, - size_t content_length, const char *content_type); - Result Put(const char *path, const std::string &body, - const char *content_type); - Result Put(const char *path, const Headers &headers, const std::string &body, - const char *content_type); - Result Put(const char *path, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Put(const char *path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Put(const char *path, const Headers &headers, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Put(const char *path, const Headers &headers, + Result Post(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, + const MultipartFormDataProviderItems &provider_items); + + Result Put(const std::string &path); + Result Put(const std::string &path, const char *body, size_t content_length, + const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, const char *body, + size_t content_length, const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, const char *body, + size_t content_length, const std::string &content_type, + Progress progress); + Result Put(const std::string &path, const std::string &body, + const std::string &content_type); + Result Put(const std::string &path, const std::string &body, + const std::string &content_type, Progress progress); + Result Put(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type, + Progress progress); + Result Put(const std::string &path, size_t content_length, + ContentProvider content_provider, const std::string &content_type); + Result Put(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Put(const char *path, const Params ¶ms); - Result Put(const char *path, const Headers &headers, const Params ¶ms); - Result Patch(const char *path); - Result Patch(const char *path, const char *body, size_t content_length, - const char *content_type); - Result Patch(const char *path, const Headers &headers, const char *body, - size_t content_length, const char *content_type); - Result Patch(const char *path, const std::string &body, - const char *content_type); - Result Patch(const char *path, const Headers &headers, - const std::string &body, const char *content_type); - Result Patch(const char *path, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Patch(const char *path, ContentProviderWithoutLength content_provider, - const char *content_type); - Result Patch(const char *path, const Headers &headers, size_t content_length, - ContentProvider content_provider, const char *content_type); - Result Patch(const char *path, const Headers &headers, + const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, + size_t content_length, ContentProvider content_provider, + const std::string &content_type); + Result Put(const std::string &path, const Headers &headers, + ContentProviderWithoutLength content_provider, + const std::string &content_type); + Result Put(const std::string &path, const Params ¶ms); + Result Put(const std::string &path, const Headers &headers, + const Params ¶ms); + Result Put(const std::string &path, const Headers &headers, + const Params ¶ms, Progress progress); + Result Put(const std::string &path, const MultipartFormDataItems &items); + Result Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items); + Result Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, const std::string &boundary); + Result Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, + const MultipartFormDataProviderItems &provider_items); + + Result Patch(const std::string &path); + Result Patch(const std::string &path, const char *body, size_t content_length, + const std::string &content_type); + Result Patch(const std::string &path, const char *body, size_t content_length, + const std::string &content_type, Progress progress); + Result Patch(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type); + Result Patch(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type, Progress progress); + Result Patch(const std::string &path, const std::string &body, + const std::string &content_type); + Result Patch(const std::string &path, const std::string &body, + const std::string &content_type, Progress progress); + Result Patch(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type); + Result Patch(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type, + Progress progress); + Result Patch(const std::string &path, size_t content_length, + ContentProvider content_provider, + const std::string &content_type); + Result Patch(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type); + const std::string &content_type); + Result Patch(const std::string &path, const Headers &headers, + size_t content_length, ContentProvider content_provider, + const std::string &content_type); + Result Patch(const std::string &path, const Headers &headers, + ContentProviderWithoutLength content_provider, + const std::string &content_type); - Result Delete(const char *path); - Result Delete(const char *path, const Headers &headers); - Result Delete(const char *path, const char *body, size_t content_length, - const char *content_type); - Result Delete(const char *path, const Headers &headers, const char *body, - size_t content_length, const char *content_type); - Result Delete(const char *path, const std::string &body, - const char *content_type); - Result Delete(const char *path, const Headers &headers, - const std::string &body, const char *content_type); + Result Delete(const std::string &path); + Result Delete(const std::string &path, const Headers &headers); + Result Delete(const std::string &path, const char *body, + size_t content_length, const std::string &content_type); + Result Delete(const std::string &path, const char *body, + size_t content_length, const std::string &content_type, + Progress progress); + Result Delete(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type); + Result Delete(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type, Progress progress); + Result Delete(const std::string &path, const std::string &body, + const std::string &content_type); + Result Delete(const std::string &path, const std::string &body, + const std::string &content_type, Progress progress); + Result Delete(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type); + Result Delete(const std::string &path, const Headers &headers, + const std::string &body, const std::string &content_type, + Progress progress); - Result Options(const char *path); - Result Options(const char *path, const Headers &headers); + Result Options(const std::string &path); + Result Options(const std::string &path, const Headers &headers); bool send(Request &req, Response &res, Error &error); Result send(const Request &req); - size_t is_socket_open() const; - void stop(); + std::string host() const; + int port() const; + + size_t is_socket_open() const; + socket_t socket() const; + void set_hostname_addr_map(std::map addr_map); void set_default_headers(Headers headers); + void + set_header_writer(std::function const &writer); + void set_address_family(int family); void set_tcp_nodelay(bool on); void set_socket_options(SocketOptions socket_options); @@ -1335,10 +1746,11 @@ public: template void set_write_timeout(const std::chrono::duration &duration); - void set_basic_auth(const char *username, const char *password); - void set_bearer_token_auth(const char *token); + void set_basic_auth(const std::string &username, const std::string &password); + void set_bearer_token_auth(const std::string &token); #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_digest_auth(const char *username, const char *password); + void set_digest_auth(const std::string &username, + const std::string &password); #endif void set_keep_alive(bool on); @@ -1350,13 +1762,15 @@ public: void set_decompress(bool on); - void set_interface(const char *intf); + void set_interface(const std::string &intf); - void set_proxy(const char *host, int port); - void set_proxy_basic_auth(const char *username, const char *password); - void set_proxy_bearer_token_auth(const char *token); + void set_proxy(const std::string &host, int port); + void set_proxy_basic_auth(const std::string &username, + const std::string &password); + void set_proxy_bearer_token_auth(const std::string &token); #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_proxy_digest_auth(const char *username, const char *password); + void set_proxy_digest_auth(const std::string &username, + const std::string &password); #endif #ifdef CPPHTTPLIB_OPENSSL_SUPPORT @@ -1367,10 +1781,11 @@ public: // SSL #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - void set_ca_cert_path(const char *ca_cert_file_path, - const char *ca_cert_dir_path = nullptr); + void set_ca_cert_path(const std::string &ca_cert_file_path, + const std::string &ca_cert_dir_path = std::string()); void set_ca_cert_store(X509_STORE *ca_cert_store); + void load_ca_cert_store(const char *ca_cert, std::size_t size); long get_openssl_verify_result() const; @@ -1404,6 +1819,9 @@ public: bool is_valid() const override; SSL_CTX *ssl_context() const; + + void update_certs (X509 *cert, EVP_PKEY *private_key, + X509_STORE *client_ca_cert_store = nullptr); private: bool process_and_close_socket(socket_t sock) override; @@ -1412,7 +1830,7 @@ private: std::mutex ctx_mutex_; }; -class SSLClient : public ClientImpl { +class SSLClient final : public ClientImpl { public: explicit SSLClient(const std::string &host); @@ -1420,16 +1838,19 @@ public: explicit SSLClient(const std::string &host, int port, const std::string &client_cert_path, - const std::string &client_key_path); + const std::string &client_key_path, + const std::string &private_key_password = std::string()); explicit SSLClient(const std::string &host, int port, X509 *client_cert, - EVP_PKEY *client_key); + EVP_PKEY *client_key, + const std::string &private_key_password = std::string()); ~SSLClient() override; bool is_valid() const override; void set_ca_cert_store(X509_STORE *ca_cert_store); + void load_ca_cert_store(const char *ca_cert, std::size_t size); long get_openssl_verify_result() const; @@ -1438,7 +1859,7 @@ public: private: bool create_and_connect_socket(Socket &socket, Error &error) override; void shutdown_ssl(Socket &socket, bool shutdown_gracefully) override; - void shutdown_ssl_impl(Socket &socket, bool shutdown_socket); + void shutdown_ssl_impl(Socket &socket, bool shutdown_gracefully); bool process_socket(const Socket &socket, std::function callback) override; @@ -1479,17 +1900,12 @@ inline void duration_to_sec_and_usec(const T &duration, U callback) { auto usec = std::chrono::duration_cast( duration - std::chrono::seconds(sec)) .count(); - callback(sec, usec); + callback(static_cast(sec), static_cast(usec)); } -template -inline T get_header_value(const Headers & /*headers*/, const char * /*key*/, - size_t /*id*/ = 0, uint64_t /*def*/ = 0) {} - -template <> -inline uint64_t get_header_value(const Headers &headers, - const char *key, size_t id, - uint64_t def) { +inline uint64_t get_header_value_u64(const Headers &headers, + const std::string &key, size_t id, + uint64_t def) { auto rng = headers.equal_range(key); auto it = rng.first; std::advance(it, static_cast(id)); @@ -1501,14 +1917,14 @@ inline uint64_t get_header_value(const Headers &headers, } // namespace detail -template -inline T Request::get_header_value(const char *key, size_t id) const { - return detail::get_header_value(headers, key, id, 0); +inline uint64_t Request::get_header_value_u64(const std::string &key, + size_t id) const { + return detail::get_header_value_u64(headers, key, id, 0); } -template -inline T Response::get_header_value(const char *key, size_t id) const { - return detail::get_header_value(headers, key, id, 0); +inline uint64_t Response::get_header_value_u64(const std::string &key, + size_t id) const { + return detail::get_header_value_u64(headers, key, id, 0); } template @@ -1516,11 +1932,7 @@ inline ssize_t Stream::write_format(const char *fmt, const Args &...args) { const auto bufsiz = 2048; std::array buf{}; -#if defined(_MSC_VER) && _MSC_VER < 1900 - auto sn = _snprintf_s(buf.data(), bufsiz, _TRUNCATE, fmt, args...); -#else auto sn = snprintf(buf.data(), buf.size() - 1, fmt, args...); -#endif if (sn <= 0) { return sn; } auto n = static_cast(sn); @@ -1530,14 +1942,8 @@ inline ssize_t Stream::write_format(const char *fmt, const Args &...args) { while (n >= glowable_buf.size() - 1) { glowable_buf.resize(glowable_buf.size() * 2); -#if defined(_MSC_VER) && _MSC_VER < 1900 - n = static_cast(_snprintf_s(&glowable_buf[0], glowable_buf.size(), - glowable_buf.size() - 1, fmt, - args...)); -#else n = static_cast( snprintf(&glowable_buf[0], glowable_buf.size() - 1, fmt, args...)); -#endif } return write(&glowable_buf[0], n); } else { @@ -1548,21 +1954,106 @@ inline ssize_t Stream::write_format(const char *fmt, const Args &...args) { inline void default_socket_options(socket_t sock) { int yes = 1; #ifdef _WIN32 - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&yes), - sizeof(yes)); + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, + reinterpret_cast(&yes), sizeof(yes)); setsockopt(sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, - reinterpret_cast(&yes), sizeof(yes)); + reinterpret_cast(&yes), sizeof(yes)); #else #ifdef SO_REUSEPORT - setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, reinterpret_cast(&yes), - sizeof(yes)); + setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, + reinterpret_cast(&yes), sizeof(yes)); #else - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast(&yes), - sizeof(yes)); + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, + reinterpret_cast(&yes), sizeof(yes)); #endif #endif } +inline const char *status_message(int status) { + switch (status) { + case StatusCode::Continue_100: return "Continue"; + case StatusCode::SwitchingProtocol_101: return "Switching Protocol"; + case StatusCode::Processing_102: return "Processing"; + case StatusCode::EarlyHints_103: return "Early Hints"; + case StatusCode::OK_200: return "OK"; + case StatusCode::Created_201: return "Created"; + case StatusCode::Accepted_202: return "Accepted"; + case StatusCode::NonAuthoritativeInformation_203: + return "Non-Authoritative Information"; + case StatusCode::NoContent_204: return "No Content"; + case StatusCode::ResetContent_205: return "Reset Content"; + case StatusCode::PartialContent_206: return "Partial Content"; + case StatusCode::MultiStatus_207: return "Multi-Status"; + case StatusCode::AlreadyReported_208: return "Already Reported"; + case StatusCode::IMUsed_226: return "IM Used"; + case StatusCode::MultipleChoices_300: return "Multiple Choices"; + case StatusCode::MovedPermanently_301: return "Moved Permanently"; + case StatusCode::Found_302: return "Found"; + case StatusCode::SeeOther_303: return "See Other"; + case StatusCode::NotModified_304: return "Not Modified"; + case StatusCode::UseProxy_305: return "Use Proxy"; + case StatusCode::unused_306: return "unused"; + case StatusCode::TemporaryRedirect_307: return "Temporary Redirect"; + case StatusCode::PermanentRedirect_308: return "Permanent Redirect"; + case StatusCode::BadRequest_400: return "Bad Request"; + case StatusCode::Unauthorized_401: return "Unauthorized"; + case StatusCode::PaymentRequired_402: return "Payment Required"; + case StatusCode::Forbidden_403: return "Forbidden"; + case StatusCode::NotFound_404: return "Not Found"; + case StatusCode::MethodNotAllowed_405: return "Method Not Allowed"; + case StatusCode::NotAcceptable_406: return "Not Acceptable"; + case StatusCode::ProxyAuthenticationRequired_407: + return "Proxy Authentication Required"; + case StatusCode::RequestTimeout_408: return "Request Timeout"; + case StatusCode::Conflict_409: return "Conflict"; + case StatusCode::Gone_410: return "Gone"; + case StatusCode::LengthRequired_411: return "Length Required"; + case StatusCode::PreconditionFailed_412: return "Precondition Failed"; + case StatusCode::PayloadTooLarge_413: return "Payload Too Large"; + case StatusCode::UriTooLong_414: return "URI Too Long"; + case StatusCode::UnsupportedMediaType_415: return "Unsupported Media Type"; + case StatusCode::RangeNotSatisfiable_416: return "Range Not Satisfiable"; + case StatusCode::ExpectationFailed_417: return "Expectation Failed"; + case StatusCode::ImATeapot_418: return "I'm a teapot"; + case StatusCode::MisdirectedRequest_421: return "Misdirected Request"; + case StatusCode::UnprocessableContent_422: return "Unprocessable Content"; + case StatusCode::Locked_423: return "Locked"; + case StatusCode::FailedDependency_424: return "Failed Dependency"; + case StatusCode::TooEarly_425: return "Too Early"; + case StatusCode::UpgradeRequired_426: return "Upgrade Required"; + case StatusCode::PreconditionRequired_428: return "Precondition Required"; + case StatusCode::TooManyRequests_429: return "Too Many Requests"; + case StatusCode::RequestHeaderFieldsTooLarge_431: + return "Request Header Fields Too Large"; + case StatusCode::UnavailableForLegalReasons_451: + return "Unavailable For Legal Reasons"; + case StatusCode::NotImplemented_501: return "Not Implemented"; + case StatusCode::BadGateway_502: return "Bad Gateway"; + case StatusCode::ServiceUnavailable_503: return "Service Unavailable"; + case StatusCode::GatewayTimeout_504: return "Gateway Timeout"; + case StatusCode::HttpVersionNotSupported_505: + return "HTTP Version Not Supported"; + case StatusCode::VariantAlsoNegotiates_506: return "Variant Also Negotiates"; + case StatusCode::InsufficientStorage_507: return "Insufficient Storage"; + case StatusCode::LoopDetected_508: return "Loop Detected"; + case StatusCode::NotExtended_510: return "Not Extended"; + case StatusCode::NetworkAuthenticationRequired_511: + return "Network Authentication Required"; + + default: + case StatusCode::InternalServerError_500: return "Internal Server Error"; + } +} + +inline std::string get_bearer_token_auth(const Request &req) { + if (req.has_header("Authorization")) { + static std::string BearerHeaderPrefix = "Bearer "; + return req.get_header_value("Authorization") + .substr(BearerHeaderPrefix.length()); + } + return ""; +} + template inline Server & Server::set_read_timeout(const std::chrono::duration &duration) { @@ -1589,20 +2080,21 @@ Server::set_idle_interval(const std::chrono::duration &duration) { inline std::string to_string(const Error error) { switch (error) { - case Error::Success: return "Success"; - case Error::Connection: return "Connection"; - case Error::BindIPAddress: return "BindIPAddress"; - case Error::Read: return "Read"; - case Error::Write: return "Write"; - case Error::ExceedRedirectCount: return "ExceedRedirectCount"; - case Error::Canceled: return "Canceled"; - case Error::SSLConnection: return "SSLConnection"; - case Error::SSLLoadingCerts: return "SSLLoadingCerts"; - case Error::SSLServerVerification: return "SSLServerVerification"; + case Error::Success: return "Success (no error)"; + case Error::Connection: return "Could not establish connection"; + case Error::BindIPAddress: return "Failed to bind IP address"; + case Error::Read: return "Failed to read connection"; + case Error::Write: return "Failed to write connection"; + case Error::ExceedRedirectCount: return "Maximum redirect count exceeded"; + case Error::Canceled: return "Connection handling canceled"; + case Error::SSLConnection: return "SSL connection failed"; + case Error::SSLLoadingCerts: return "SSL certificate loading failed"; + case Error::SSLServerVerification: return "SSL server verification failed"; case Error::UnsupportedMultipartBoundaryChars: - return "UnsupportedMultipartBoundaryChars"; - case Error::Compression: return "Compression"; - case Error::ConnectionTimeout: return "ConnectionTimeout"; + return "Unsupported HTTP multipart boundary characters"; + case Error::Compression: return "Compression failed"; + case Error::ConnectionTimeout: return "Connection timed out"; + case Error::ProxyConnection: return "Proxy connection failed"; case Error::Unknown: return "Unknown"; default: break; } @@ -1616,9 +2108,9 @@ inline std::ostream &operator<<(std::ostream &os, const Error &obj) { return os; } -template -inline T Result::get_request_header_value(const char *key, size_t id) const { - return detail::get_header_value(request_headers_, key, id, 0); +inline uint64_t Result::get_request_header_value_u64(const std::string &key, + size_t id) const { + return detail::get_header_value_u64(request_headers_, key, id, 0); } template @@ -1666,13 +2158,13 @@ Client::set_write_timeout(const std::chrono::duration &duration) { * .h + .cc. */ -std::string hosted_at(const char *hostname); +std::string hosted_at(const std::string &hostname); -void hosted_at(const char *hostname, std::vector &addrs); +void hosted_at(const std::string &hostname, std::vector &addrs); -std::string append_query_params(const char *path, const Params ¶ms); +std::string append_query_params(const std::string &path, const Params ¶ms); -std::pair make_range_header(Ranges ranges); +std::pair make_range_header(const Ranges &ranges); std::pair make_basic_authentication_header(const std::string &username, @@ -1689,28 +2181,46 @@ void read_file(const std::string &path, std::string &out); std::string trim_copy(const std::string &s); +void divide( + const char *data, std::size_t size, char d, + std::function + fn); + +void divide( + const std::string &str, char d, + std::function + fn); + void split(const char *b, const char *e, char d, std::function fn); +void split(const char *b, const char *e, char d, size_t m, + std::function fn); + bool process_client_socket(socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, time_t write_timeout_usec, std::function callback); socket_t create_client_socket( - const char *host, const char *ip, int port, int address_family, - bool tcp_nodelay, SocketOptions socket_options, + const std::string &host, const std::string &ip, int port, + int address_family, bool tcp_nodelay, SocketOptions socket_options, time_t connection_timeout_sec, time_t connection_timeout_usec, time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, time_t write_timeout_usec, const std::string &intf, Error &error); -const char *get_header_value(const Headers &headers, const char *key, +const char *get_header_value(const Headers &headers, const std::string &key, size_t id = 0, const char *def = nullptr); std::string params_to_query_str(const Params ¶ms); +void parse_query_text(const char *data, std::size_t size, Params ¶ms); + void parse_query_text(const std::string &s, Params ¶ms); +bool parse_multipart_boundary(const std::string &content_type, + std::string &boundary); + bool parse_range_header(const std::string &s, Ranges &ranges); int close_socket(socket_t sock); @@ -1723,7 +2233,7 @@ enum class EncodingType { None = 0, Gzip, Brotli }; EncodingType encoding_type(const Request &req, const Response &res); -class BufferStream : public Stream { +class BufferStream final : public Stream { public: BufferStream() = default; ~BufferStream() override = default; @@ -1733,6 +2243,7 @@ public: ssize_t read(char *ptr, size_t size) override; ssize_t write(const char *ptr, size_t size) override; void get_remote_ip_and_port(std::string &ip, int &port) const override; + void get_local_ip_and_port(std::string &ip, int &port) const override; socket_t socket() const override; const std::string &get_buffer() const; @@ -1762,19 +2273,19 @@ public: Callback callback) = 0; }; -class nocompressor : public compressor { +class nocompressor final : public compressor { public: - virtual ~nocompressor() = default; + ~nocompressor() override = default; bool compress(const char *data, size_t data_length, bool /*last*/, Callback callback) override; }; #ifdef CPPHTTPLIB_ZLIB_SUPPORT -class gzip_compressor : public compressor { +class gzip_compressor final : public compressor { public: gzip_compressor(); - ~gzip_compressor(); + ~gzip_compressor() override; bool compress(const char *data, size_t data_length, bool last, Callback callback) override; @@ -1784,10 +2295,10 @@ private: z_stream strm_; }; -class gzip_decompressor : public decompressor { +class gzip_decompressor final : public decompressor { public: gzip_decompressor(); - ~gzip_decompressor(); + ~gzip_decompressor() override; bool is_valid() const override; @@ -1801,7 +2312,7 @@ private: #endif #ifdef CPPHTTPLIB_BROTLI_SUPPORT -class brotli_compressor : public compressor { +class brotli_compressor final : public compressor { public: brotli_compressor(); ~brotli_compressor(); @@ -1813,7 +2324,7 @@ private: BrotliEncoderState *state_ = nullptr; }; -class brotli_decompressor : public decompressor { +class brotli_decompressor final : public decompressor { public: brotli_decompressor(); ~brotli_decompressor(); @@ -1850,6 +2361,29 @@ private: std::string glowable_buffer_; }; +class mmap { +public: + mmap(const char *path); + ~mmap(); + + bool open(const char *path); + void close(); + + bool is_open() const; + size_t size() const; + const char *data() const; + +private: +#if defined(_WIN32) + HANDLE hFile_; + HANDLE hMapping_; +#else + int fd_; +#endif + size_t size_; + void *addr_; +}; + } // namespace detail // ---------------------------------------------------------------------------- @@ -1881,7 +2415,7 @@ inline bool from_hex_to_i(const std::string &s, size_t i, size_t cnt, val = 0; for (; cnt; i++, cnt--) { if (!s[i]) { return false; } - int v = 0; + auto v = 0; if (is_hex(s[i], v)) { val = val * 16 + v; } else { @@ -1892,7 +2426,7 @@ inline bool from_hex_to_i(const std::string &s, size_t i, size_t cnt, } inline std::string from_i_to_hex(size_t n) { - const char *charset = "0123456789abcdef"; + static const auto charset = "0123456789abcdef"; std::string ret; do { ret = charset[n & 15] + ret; @@ -1903,7 +2437,7 @@ inline std::string from_i_to_hex(size_t n) { inline size_t to_utf8(int code, char *buff) { if (code < 0x0080) { - buff[0] = (code & 0x7F); + buff[0] = static_cast(code & 0x7F); return 1; } else if (code < 0x0800) { buff[0] = static_cast(0xC0 | ((code >> 6) & 0x1F)); @@ -1942,8 +2476,8 @@ inline std::string base64_encode(const std::string &in) { std::string out; out.reserve(in.size()); - int val = 0; - int valb = -6; + auto val = 0; + auto valb = -6; for (auto c : in) { val = (val << 8) + static_cast(c); @@ -1990,6 +2524,11 @@ inline bool is_valid_path(const std::string &path) { // Read component auto beg = i; while (i < path.size() && path[i] != '/') { + if (path[i] == '\0') { + return false; + } else if (path[i] == '\\') { + return false; + } i++; } @@ -2074,7 +2613,7 @@ inline std::string decode_url(const std::string &s, for (size_t i = 0; i < s.size(); i++) { if (s[i] == '%' && i + 1 < s.size()) { if (s[i + 1] == 'u') { - int val = 0; + auto val = 0; if (from_hex_to_i(s, i + 2, 4, val)) { // 4 digits Unicode codes char buff[4]; @@ -2085,7 +2624,7 @@ inline std::string decode_url(const std::string &s, result += s[i]; } } else { - int val = 0; + auto val = 0; if (from_hex_to_i(s, i + 1, 2, val)) { // 2 digits hex codes result += static_cast(val); @@ -2138,16 +2677,51 @@ inline std::string trim_copy(const std::string &s) { return s.substr(r.first, r.second - r.first); } +inline std::string trim_double_quotes_copy(const std::string &s) { + if (s.length() >= 2 && s.front() == '"' && s.back() == '"') { + return s.substr(1, s.size() - 2); + } + return s; +} + +inline void +divide(const char *data, std::size_t size, char d, + std::function + fn) { + const auto it = std::find(data, data + size, d); + const auto found = static_cast(it != data + size); + const auto lhs_data = data; + const auto lhs_size = static_cast(it - data); + const auto rhs_data = it + found; + const auto rhs_size = size - lhs_size - found; + + fn(lhs_data, lhs_size, rhs_data, rhs_size); +} + +inline void +divide(const std::string &str, char d, + std::function + fn) { + divide(str.data(), str.size(), d, std::move(fn)); +} + inline void split(const char *b, const char *e, char d, std::function fn) { + return split(b, e, d, (std::numeric_limits::max)(), std::move(fn)); +} + +inline void split(const char *b, const char *e, char d, size_t m, + std::function fn) { size_t i = 0; size_t beg = 0; + size_t count = 1; while (e ? (b + i < e) : (b[i] != '\0')) { - if (b[i] == d) { + if (b[i] == d && count < m) { auto r = trim(b, e, beg, i); if (r.first < r.second) { fn(&b[r.first], &b[r.second]); } beg = i + 1; + count++; } i++; } @@ -2223,6 +2797,105 @@ inline void stream_line_reader::append(char c) { } } +inline mmap::mmap(const char *path) +#if defined(_WIN32) + : hFile_(NULL), hMapping_(NULL) +#else + : fd_(-1) +#endif + , + size_(0), addr_(nullptr) { + open(path); +} + +inline mmap::~mmap() { close(); } + +inline bool mmap::open(const char *path) { + close(); + +#if defined(_WIN32) + std::wstring wpath; + for (size_t i = 0; i < strlen(path); i++) { + wpath += path[i]; + } + + hFile_ = ::CreateFile2(wpath.c_str(), GENERIC_READ, FILE_SHARE_READ, + OPEN_EXISTING, NULL); + + if (hFile_ == INVALID_HANDLE_VALUE) { return false; } + + LARGE_INTEGER size{}; + if (!::GetFileSizeEx(hFile_, &size)) { return false; } + size_ = static_cast(size.QuadPart); + + hMapping_ = + ::CreateFileMappingFromApp(hFile_, NULL, PAGE_READONLY, size_, NULL); + + if (hMapping_ == NULL) { + close(); + return false; + } + + addr_ = ::MapViewOfFileFromApp(hMapping_, FILE_MAP_READ, 0, 0); +#else + fd_ = ::open(path, O_RDONLY); + if (fd_ == -1) { return false; } + + struct stat sb; + if (fstat(fd_, &sb) == -1) { + close(); + return false; + } + size_ = static_cast(sb.st_size); + + addr_ = ::mmap(NULL, size_, PROT_READ, MAP_PRIVATE, fd_, 0); +#endif + + if (addr_ == nullptr) { + close(); + return false; + } + + return true; +} + +inline bool mmap::is_open() const { return addr_ != nullptr; } + +inline size_t mmap::size() const { return size_; } + +inline const char *mmap::data() const { + return static_cast(addr_); +} + +inline void mmap::close() { +#if defined(_WIN32) + if (addr_) { + ::UnmapViewOfFile(addr_); + addr_ = nullptr; + } + + if (hMapping_) { + ::CloseHandle(hMapping_); + hMapping_ = NULL; + } + + if (hFile_ != INVALID_HANDLE_VALUE) { + ::CloseHandle(hFile_); + hFile_ = INVALID_HANDLE_VALUE; + } +#else + if (addr_ != nullptr) { + munmap(addr_, size_); + addr_ = nullptr; + } + + if (fd_ != -1) { + ::close(fd_); + fd_ = -1; + } +#endif + size_ = 0; +} inline int close_socket(socket_t sock) { #ifdef _WIN32 return closesocket(sock); @@ -2232,7 +2905,7 @@ inline int close_socket(socket_t sock) { } template inline ssize_t handle_EINTR(T fn) { - ssize_t res = false; + ssize_t res = 0; while (true) { res = fn(); if (res < 0 && errno == EINTR) { continue; } @@ -2277,7 +2950,7 @@ inline ssize_t select_read(socket_t sock, time_t sec, time_t usec) { return handle_EINTR([&]() { return poll(&pfd_read, 1, timeout); }); #else #ifndef _WIN32 - if (sock >= FD_SETSIZE) { return 1; } + if (sock >= FD_SETSIZE) { return -1; } #endif fd_set fds; @@ -2305,7 +2978,7 @@ inline ssize_t select_write(socket_t sock, time_t sec, time_t usec) { return handle_EINTR([&]() { return poll(&pfd_read, 1, timeout); }); #else #ifndef _WIN32 - if (sock >= FD_SETSIZE) { return 1; } + if (sock >= FD_SETSIZE) { return -1; } #endif fd_set fds; @@ -2336,7 +3009,7 @@ inline Error wait_until_socket_is_ready(socket_t sock, time_t sec, if (poll_res == 0) { return Error::ConnectionTimeout; } if (poll_res > 0 && pfd_read.revents & (POLLIN | POLLOUT)) { - int error = 0; + auto error = 0; socklen_t len = sizeof(error); auto res = getsockopt(sock, SOL_SOCKET, SO_ERROR, reinterpret_cast(&error), &len); @@ -2368,7 +3041,7 @@ inline Error wait_until_socket_is_ready(socket_t sock, time_t sec, if (ret == 0) { return Error::ConnectionTimeout; } if (ret > 0 && (FD_ISSET(sock, &fdsr) || FD_ISSET(sock, &fdsw))) { - int error = 0; + auto error = 0; socklen_t len = sizeof(error); auto res = getsockopt(sock, SOL_SOCKET, SO_ERROR, reinterpret_cast(&error), &len); @@ -2390,7 +3063,7 @@ inline bool is_socket_alive(socket_t sock) { return detail::read_socket(sock, &buf[0], sizeof(buf), MSG_PEEK) > 0; } -class SocketStream : public Stream { +class SocketStream final : public Stream { public: SocketStream(socket_t sock, time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, time_t write_timeout_usec); @@ -2401,6 +3074,7 @@ public: ssize_t read(char *ptr, size_t size) override; ssize_t write(const char *ptr, size_t size) override; void get_remote_ip_and_port(std::string &ip, int &port) const override; + void get_local_ip_and_port(std::string &ip, int &port) const override; socket_t socket() const override; private: @@ -2414,11 +3088,11 @@ private: size_t read_buff_off_ = 0; size_t read_buff_content_size_ = 0; - static const size_t read_buff_size_ = 1024 * 4; + static const size_t read_buff_size_ = 1024l * 4; }; #ifdef CPPHTTPLIB_OPENSSL_SUPPORT -class SSLSocketStream : public Stream { +class SSLSocketStream final : public Stream { public: SSLSocketStream(socket_t sock, SSL *ssl, time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, @@ -2430,6 +3104,7 @@ public: ssize_t read(char *ptr, size_t size) override; ssize_t write(const char *ptr, size_t size) override; void get_remote_ip_and_port(std::string &ip, int &port) const override; + void get_local_ip_and_port(std::string &ip, int &port) const override; socket_t socket() const override; private: @@ -2515,7 +3190,7 @@ inline int shutdown_socket(socket_t sock) { } template -socket_t create_socket(const char *host, const char *ip, int port, +socket_t create_socket(const std::string &host, const std::string &ip, int port, int address_family, int socket_flags, bool tcp_nodelay, SocketOptions socket_options, BindOrConnect bind_or_connect) { @@ -2528,17 +3203,44 @@ socket_t create_socket(const char *host, const char *ip, int port, hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; - if (ip[0] != '\0') { - node = ip; + if (!ip.empty()) { + node = ip.c_str(); // Ask getaddrinfo to convert IP in c-string to address hints.ai_family = AF_UNSPEC; hints.ai_flags = AI_NUMERICHOST; } else { - node = host; + if (!host.empty()) { node = host.c_str(); } hints.ai_family = address_family; hints.ai_flags = socket_flags; } +#ifndef _WIN32 + if (hints.ai_family == AF_UNIX) { + const auto addrlen = host.length(); + if (addrlen > sizeof(sockaddr_un::sun_path)) { return INVALID_SOCKET; } + + auto sock = socket(hints.ai_family, hints.ai_socktype, hints.ai_protocol); + if (sock != INVALID_SOCKET) { + sockaddr_un addr{}; + addr.sun_family = AF_UNIX; + std::copy(host.begin(), host.end(), addr.sun_path); + + hints.ai_addr = reinterpret_cast(&addr); + hints.ai_addrlen = static_cast( + sizeof(addr) - sizeof(addr.sun_path) + addrlen); + + fcntl(sock, F_SETFD, FD_CLOEXEC); + if (socket_options) { socket_options(sock); } + + if (!bind_or_connect(sock, hints)) { + close_socket(sock); + sock = INVALID_SOCKET; + } + } + return sock; + } +#endif + auto service = std::to_string(port); if (getaddrinfo(node, service.c_str(), &hints, &result)) { @@ -2577,21 +3279,34 @@ socket_t create_socket(const char *host, const char *ip, int port, if (sock == INVALID_SOCKET) { continue; } #ifndef _WIN32 - if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1) { continue; } + if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1) { + close_socket(sock); + continue; + } #endif if (tcp_nodelay) { - int yes = 1; - setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast(&yes), - sizeof(yes)); + auto yes = 1; +#ifdef _WIN32 + setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + reinterpret_cast(&yes), sizeof(yes)); +#else + setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, + reinterpret_cast(&yes), sizeof(yes)); +#endif } if (socket_options) { socket_options(sock); } if (rp->ai_family == AF_INET6) { - int no = 0; - setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast(&no), - sizeof(no)); + auto no = 0; +#ifdef _WIN32 + setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, + reinterpret_cast(&no), sizeof(no)); +#else + setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, + reinterpret_cast(&no), sizeof(no)); +#endif } // bind or connect @@ -2626,7 +3341,7 @@ inline bool is_connection_error() { #endif } -inline bool bind_ip_address(socket_t sock, const char *host) { +inline bool bind_ip_address(socket_t sock, const std::string &host) { struct addrinfo hints; struct addrinfo *result; @@ -2635,7 +3350,7 @@ inline bool bind_ip_address(socket_t sock, const char *host) { hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; - if (getaddrinfo(host, "0", &hints, &result)) { return false; } + if (getaddrinfo(host.c_str(), "0", &hints, &result)) { return false; } auto ret = false; for (auto rp = result; rp; rp = rp->ai_next) { @@ -2650,7 +3365,7 @@ inline bool bind_ip_address(socket_t sock, const char *host) { return ret; } -#if !defined _WIN32 && !defined ANDROID +#if !defined _WIN32 && !defined ANDROID && !defined _AIX && !defined __MVS__ #define USE_IF2IP #endif @@ -2694,8 +3409,8 @@ inline std::string if2ip(int address_family, const std::string &ifn) { #endif inline socket_t create_client_socket( - const char *host, const char *ip, int port, int address_family, - bool tcp_nodelay, SocketOptions socket_options, + const std::string &host, const std::string &ip, int port, + int address_family, bool tcp_nodelay, SocketOptions socket_options, time_t connection_timeout_sec, time_t connection_timeout_usec, time_t read_timeout_sec, time_t read_timeout_usec, time_t write_timeout_sec, time_t write_timeout_usec, const std::string &intf, Error &error) { @@ -2704,9 +3419,9 @@ inline socket_t create_client_socket( [&](socket_t sock2, struct addrinfo &ai) -> bool { if (!intf.empty()) { #ifdef USE_IF2IP - auto ip = if2ip(address_family, intf); - if (ip.empty()) { ip = intf; } - if (!bind_ip_address(sock2, ip.c_str())) { + auto ip_from_if = if2ip(address_family, intf); + if (ip_from_if.empty()) { ip_from_if = intf; } + if (!bind_ip_address(sock2, ip_from_if)) { error = Error::BindIPAddress; return false; } @@ -2734,13 +3449,14 @@ inline socket_t create_client_socket( #ifdef _WIN32 auto timeout = static_cast(read_timeout_sec * 1000 + read_timeout_usec / 1000); - setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, - sizeof(timeout)); + setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO, + reinterpret_cast(&timeout), sizeof(timeout)); #else timeval tv; tv.tv_sec = static_cast(read_timeout_sec); tv.tv_usec = static_cast(read_timeout_usec); - setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); + setsockopt(sock2, SOL_SOCKET, SO_RCVTIMEO, + reinterpret_cast(&tv), sizeof(tv)); #endif } { @@ -2748,13 +3464,14 @@ inline socket_t create_client_socket( #ifdef _WIN32 auto timeout = static_cast(write_timeout_sec * 1000 + write_timeout_usec / 1000); - setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, - sizeof(timeout)); + setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO, + reinterpret_cast(&timeout), sizeof(timeout)); #else timeval tv; tv.tv_sec = static_cast(write_timeout_sec); tv.tv_usec = static_cast(write_timeout_usec); - setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)); + setsockopt(sock2, SOL_SOCKET, SO_SNDTIMEO, + reinterpret_cast(&tv), sizeof(tv)); #endif } @@ -2771,9 +3488,8 @@ inline socket_t create_client_socket( return sock; } -inline bool get_remote_ip_and_port(const struct sockaddr_storage &addr, - socklen_t addr_len, std::string &ip, - int &port) { +inline bool get_ip_and_port(const struct sockaddr_storage &addr, + socklen_t addr_len, std::string &ip, int &port) { if (addr.ss_family == AF_INET) { port = ntohs(reinterpret_cast(&addr)->sin_port); } else if (addr.ss_family == AF_INET6) { @@ -2794,21 +3510,53 @@ inline bool get_remote_ip_and_port(const struct sockaddr_storage &addr, return true; } +inline void get_local_ip_and_port(socket_t sock, std::string &ip, int &port) { + struct sockaddr_storage addr; + socklen_t addr_len = sizeof(addr); + if (!getsockname(sock, reinterpret_cast(&addr), + &addr_len)) { + get_ip_and_port(addr, addr_len, ip, port); + } +} + inline void get_remote_ip_and_port(socket_t sock, std::string &ip, int &port) { struct sockaddr_storage addr; socklen_t addr_len = sizeof(addr); if (!getpeername(sock, reinterpret_cast(&addr), &addr_len)) { - get_remote_ip_and_port(addr, addr_len, ip, port); +#ifndef _WIN32 + if (addr.ss_family == AF_UNIX) { +#if defined(__linux__) + struct ucred ucred; + socklen_t len = sizeof(ucred); + if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == 0) { + port = ucred.pid; + } +#elif defined(SOL_LOCAL) && defined(SO_PEERPID) // __APPLE__ + pid_t pid; + socklen_t len = sizeof(pid); + if (getsockopt(sock, SOL_LOCAL, SO_PEERPID, &pid, &len) == 0) { + port = pid; + } +#endif + return; + } +#endif + get_ip_and_port(addr, addr_len, ip, port); } } inline constexpr unsigned int str2tag_core(const char *s, size_t l, unsigned int h) { - return (l == 0) ? h - : str2tag_core(s + 1, l - 1, - (h * 33) ^ static_cast(*s)); + return (l == 0) + ? h + : str2tag_core( + s + 1, l - 1, + // Unsets the 6 high bits of h, therefore no overflow happens + (((std::numeric_limits::max)() >> 6) & + h * 33) ^ + static_cast(*s)); } inline unsigned int str2tag(const std::string &s) { @@ -2823,18 +3571,20 @@ inline constexpr unsigned int operator"" _t(const char *s, size_t l) { } // namespace udl -inline const char * +inline std::string find_content_type(const std::string &path, - const std::map &user_data) { + const std::map &user_data, + const std::string &default_content_type) { auto ext = file_extension(path); auto it = user_data.find(ext); - if (it != user_data.end()) { return it->second.c_str(); } + if (it != user_data.end()) { return it->second; } using udl::operator""_t; switch (str2tag(ext)) { - default: return nullptr; + default: return default_content_type; + case "css"_t: return "text/css"; case "csv"_t: return "text/csv"; case "htm"_t: @@ -2887,76 +3637,6 @@ find_content_type(const std::string &path, } } -inline const char *status_message(int status) { - switch (status) { - case 100: return "Continue"; - case 101: return "Switching Protocol"; - case 102: return "Processing"; - case 103: return "Early Hints"; - case 200: return "OK"; - case 201: return "Created"; - case 202: return "Accepted"; - case 203: return "Non-Authoritative Information"; - case 204: return "No Content"; - case 205: return "Reset Content"; - case 206: return "Partial Content"; - case 207: return "Multi-Status"; - case 208: return "Already Reported"; - case 226: return "IM Used"; - case 300: return "Multiple Choice"; - case 301: return "Moved Permanently"; - case 302: return "Found"; - case 303: return "See Other"; - case 304: return "Not Modified"; - case 305: return "Use Proxy"; - case 306: return "unused"; - case 307: return "Temporary Redirect"; - case 308: return "Permanent Redirect"; - case 400: return "Bad Request"; - case 401: return "Unauthorized"; - case 402: return "Payment Required"; - case 403: return "Forbidden"; - case 404: return "Not Found"; - case 405: return "Method Not Allowed"; - case 406: return "Not Acceptable"; - case 407: return "Proxy Authentication Required"; - case 408: return "Request Timeout"; - case 409: return "Conflict"; - case 410: return "Gone"; - case 411: return "Length Required"; - case 412: return "Precondition Failed"; - case 413: return "Payload Too Large"; - case 414: return "URI Too Long"; - case 415: return "Unsupported Media Type"; - case 416: return "Range Not Satisfiable"; - case 417: return "Expectation Failed"; - case 418: return "I'm a teapot"; - case 421: return "Misdirected Request"; - case 422: return "Unprocessable Entity"; - case 423: return "Locked"; - case 424: return "Failed Dependency"; - case 425: return "Too Early"; - case 426: return "Upgrade Required"; - case 428: return "Precondition Required"; - case 429: return "Too Many Requests"; - case 431: return "Request Header Fields Too Large"; - case 451: return "Unavailable For Legal Reasons"; - case 501: return "Not Implemented"; - case 502: return "Bad Gateway"; - case 503: return "Service Unavailable"; - case 504: return "Gateway Timeout"; - case 505: return "HTTP Version Not Supported"; - case 506: return "Variant Also Negotiates"; - case 507: return "Insufficient Storage"; - case 508: return "Loop Detected"; - case 510: return "Not Extended"; - case 511: return "Network Authentication Required"; - - default: - case 500: return "Internal Server Error"; - } -} - inline bool can_compress_content_type(const std::string &content_type) { using udl::operator""_t; @@ -3033,7 +3713,7 @@ inline bool gzip_compressor::compress(const char *data, size_t data_length, data += strm_.avail_in; auto flush = (last && data_length == 0) ? Z_FINISH : Z_NO_FLUSH; - int ret = Z_OK; + auto ret = Z_OK; std::array buff{}; do { @@ -3077,7 +3757,7 @@ inline bool gzip_decompressor::decompress(const char *data, size_t data_length, Callback callback) { assert(is_valid_); - int ret = Z_OK; + auto ret = Z_OK; do { constexpr size_t max_avail_in = @@ -3091,16 +3771,12 @@ inline bool gzip_decompressor::decompress(const char *data, size_t data_length, data += strm_.avail_in; std::array buff{}; - while (strm_.avail_in > 0) { + while (strm_.avail_in > 0 && ret == Z_OK) { strm_.avail_out = static_cast(buff.size()); strm_.next_out = reinterpret_cast(buff.data()); - auto prev_avail_in = strm_.avail_in; - ret = inflate(&strm_, Z_NO_FLUSH); - if (prev_avail_in - strm_.avail_in == 0) { return false; } - assert(ret != Z_STREAM_ERROR); switch (ret) { case Z_NEED_DICT: @@ -3113,7 +3789,7 @@ inline bool gzip_decompressor::decompress(const char *data, size_t data_length, } } - if (ret != Z_OK && ret != Z_STREAM_END) return false; + if (ret != Z_OK && ret != Z_STREAM_END) { return false; } } while (data_length > 0); @@ -3182,7 +3858,7 @@ inline bool brotli_decompressor::decompress(const char *data, return 0; } - const uint8_t *next_in = (const uint8_t *)data; + auto next_in = reinterpret_cast(data); size_t avail_in = data_length; size_t total_out; @@ -3207,12 +3883,13 @@ inline bool brotli_decompressor::decompress(const char *data, } #endif -inline bool has_header(const Headers &headers, const char *key) { +inline bool has_header(const Headers &headers, const std::string &key) { return headers.find(key) != headers.end(); } -inline const char *get_header_value(const Headers &headers, const char *key, - size_t id, const char *def) { +inline const char *get_header_value(const Headers &headers, + const std::string &key, size_t id, + const char *def) { auto rng = headers.equal_range(key); auto it = rng.first; std::advance(it, static_cast(id)); @@ -3220,6 +3897,14 @@ inline const char *get_header_value(const Headers &headers, const char *key, return def; } +inline bool compare_case_ignore(const std::string &a, const std::string &b) { + if (a.size() != b.size()) { return false; } + for (size_t i = 0; i < b.size(); i++) { + if (::tolower(a[i]) != ::tolower(b[i])) { return false; } + } + return true; +} + template inline bool parse_header(const char *beg, const char *end, T fn) { // Skip trailing spaces and tabs. @@ -3243,7 +3928,14 @@ inline bool parse_header(const char *beg, const char *end, T fn) { } if (p < end) { - fn(std::string(beg, key_end), decode_url(std::string(p, end), false)); + auto key_len = key_end - beg; + if (!key_len) { return false; } + + auto key = std::string(beg, key_end); + auto val = compare_case_ignore(key, "Location") + ? std::string(p, end) + : decode_url(std::string(p, end), false); + fn(key, val); return true; } @@ -3281,8 +3973,8 @@ inline bool read_headers(Stream &strm, Headers &headers) { auto end = line_reader.ptr() + line_reader.size() - line_terminator_len; parse_header(line_reader.ptr(), end, - [&](std::string &&key, std::string &&val) { - headers.emplace(std::move(key), std::move(val)); + [&](const std::string &key, const std::string &val) { + headers.emplace(key, val); }); } @@ -3328,11 +4020,7 @@ inline bool read_content_without_length(Stream &strm, uint64_t r = 0; for (;;) { auto n = strm.read(buf, CPPHTTPLIB_RECV_BUFSIZ); - if (n < 0) { - return false; - } else if (n == 0) { - return true; - } + if (n <= 0) { return true; } if (!out(buf, static_cast(n), r, 0)) { return false; } r += static_cast(n); @@ -3341,7 +4029,8 @@ inline bool read_content_without_length(Stream &strm, return true; } -inline bool read_content_chunked(Stream &strm, +template +inline bool read_content_chunked(Stream &strm, T &x, ContentReceiverWithProgress out) { const auto bufsiz = 16; char buf[bufsiz]; @@ -3367,23 +4056,37 @@ inline bool read_content_chunked(Stream &strm, if (!line_reader.getline()) { return false; } - if (strcmp(line_reader.ptr(), "\r\n")) { break; } + if (strcmp(line_reader.ptr(), "\r\n") != 0) { return false; } if (!line_reader.getline()) { return false; } } - if (chunk_len == 0) { - // Reader terminator after chunks - if (!line_reader.getline() || strcmp(line_reader.ptr(), "\r\n")) - return false; + assert(chunk_len == 0); + + // Trailer + if (!line_reader.getline()) { return false; } + + while (strcmp(line_reader.ptr(), "\r\n") != 0) { + if (line_reader.size() > CPPHTTPLIB_HEADER_MAX_LENGTH) { return false; } + + // Exclude line terminator + constexpr auto line_terminator_len = 2; + auto end = line_reader.ptr() + line_reader.size() - line_terminator_len; + + parse_header(line_reader.ptr(), end, + [&](const std::string &key, const std::string &val) { + x.headers.emplace(key, val); + }); + + if (!line_reader.getline()) { return false; } } return true; } inline bool is_chunked_transfer_encoding(const Headers &headers) { - return !strcasecmp(get_header_value(headers, "Transfer-Encoding", 0, ""), - "chunked"); + return compare_case_ignore( + get_header_value(headers, "Transfer-Encoding", 0, ""), "chunked"); } template @@ -3398,14 +4101,14 @@ bool prepare_content_receiver(T &x, int &status, #ifdef CPPHTTPLIB_ZLIB_SUPPORT decompressor = detail::make_unique(); #else - status = 415; + status = StatusCode::UnsupportedMediaType_415; return false; #endif } else if (encoding.find("br") != std::string::npos) { #ifdef CPPHTTPLIB_BROTLI_SUPPORT decompressor = detail::make_unique(); #else - status = 415; + status = StatusCode::UnsupportedMediaType_415; return false; #endif } @@ -3421,7 +4124,7 @@ bool prepare_content_receiver(T &x, int &status, }; return callback(std::move(out)); } else { - status = 500; + status = StatusCode::InternalServerError_500; return false; } } @@ -3445,11 +4148,11 @@ bool read_content(Stream &strm, T &x, size_t payload_max_length, int &status, auto exceed_payload_max_length = false; if (is_chunked_transfer_encoding(x.headers)) { - ret = read_content_chunked(strm, out); + ret = read_content_chunked(strm, x, out); } else if (!has_header(x.headers, "Content-Length")) { ret = read_content_without_length(strm, out); } else { - auto len = get_header_value(x.headers, "Content-Length"); + auto len = get_header_value_u64(x.headers, "Content-Length", 0, 0); if (len > payload_max_length) { exceed_payload_max_length = true; skip_content_with_length(strm, len); @@ -3459,7 +4162,10 @@ bool read_content(Stream &strm, T &x, size_t payload_max_length, int &status, } } - if (!ret) { status = exceed_payload_max_length ? 413 : 400; } + if (!ret) { + status = exceed_payload_max_length ? StatusCode::PayloadTooLarge_413 + : StatusCode::BadRequest_400; + } return ret; }); } // namespace detail @@ -3498,7 +4204,7 @@ inline bool write_content(Stream &strm, const ContentProvider &content_provider, data_sink.write = [&](const char *d, size_t l) -> bool { if (ok) { - if (write_data(strm, d, l)) { + if (strm.is_writable() && write_data(strm, d, l)) { offset += l; } else { ok = false; @@ -3507,14 +4213,16 @@ inline bool write_content(Stream &strm, const ContentProvider &content_provider, return ok; }; - data_sink.is_writable = [&](void) { return ok && strm.is_writable(); }; + data_sink.is_writable = [&]() -> bool { return strm.is_writable(); }; while (offset < end_offset && !is_shutting_down()) { - if (!content_provider(offset, end_offset - offset, data_sink)) { + if (!strm.is_writable()) { + error = Error::Write; + return false; + } else if (!content_provider(offset, end_offset - offset, data_sink)) { error = Error::Canceled; return false; - } - if (!ok) { + } else if (!ok) { error = Error::Write; return false; } @@ -3546,18 +4254,23 @@ write_content_without_length(Stream &strm, data_sink.write = [&](const char *d, size_t l) -> bool { if (ok) { offset += l; - if (!write_data(strm, d, l)) { ok = false; } + if (!strm.is_writable() || !write_data(strm, d, l)) { ok = false; } } return ok; }; + data_sink.is_writable = [&]() -> bool { return strm.is_writable(); }; + data_sink.done = [&](void) { data_available = false; }; - data_sink.is_writable = [&](void) { return ok && strm.is_writable(); }; - while (data_available && !is_shutting_down()) { - if (!content_provider(offset, 0, data_sink)) { return false; } - if (!ok) { return false; } + if (!strm.is_writable()) { + return false; + } else if (!content_provider(offset, 0, data_sink)) { + return false; + } else if (!ok) { + return false; + } } return true; } @@ -3586,7 +4299,10 @@ write_content_chunked(Stream &strm, const ContentProvider &content_provider, // Emit chunked response header and footer for each chunk auto chunk = from_i_to_hex(payload.size()) + "\r\n" + payload + "\r\n"; - if (!write_data(strm, chunk.data(), chunk.size())) { ok = false; } + if (!strm.is_writable() || + !write_data(strm, chunk.data(), chunk.size())) { + ok = false; + } } } else { ok = false; @@ -3595,7 +4311,9 @@ write_content_chunked(Stream &strm, const ContentProvider &content_provider, return ok; }; - data_sink.done = [&](void) { + data_sink.is_writable = [&]() -> bool { return strm.is_writable(); }; + + auto done_with_trailer = [&](const Headers *trailer) { if (!ok) { return; } data_available = false; @@ -3613,26 +4331,46 @@ write_content_chunked(Stream &strm, const ContentProvider &content_provider, if (!payload.empty()) { // Emit chunked response header and footer for each chunk auto chunk = from_i_to_hex(payload.size()) + "\r\n" + payload + "\r\n"; - if (!write_data(strm, chunk.data(), chunk.size())) { + if (!strm.is_writable() || + !write_data(strm, chunk.data(), chunk.size())) { ok = false; return; } } - static const std::string done_marker("0\r\n\r\n"); + static const std::string done_marker("0\r\n"); if (!write_data(strm, done_marker.data(), done_marker.size())) { ok = false; } + + // Trailer + if (trailer) { + for (const auto &kv : *trailer) { + std::string field_line = kv.first + ": " + kv.second + "\r\n"; + if (!write_data(strm, field_line.data(), field_line.size())) { + ok = false; + } + } + } + + static const std::string crlf("\r\n"); + if (!write_data(strm, crlf.data(), crlf.size())) { ok = false; } }; - data_sink.is_writable = [&](void) { return ok && strm.is_writable(); }; + data_sink.done = [&](void) { done_with_trailer(nullptr); }; + + data_sink.done_with_trailer = [&](const Headers &trailer) { + done_with_trailer(&trailer); + }; while (data_available && !is_shutting_down()) { - if (!content_provider(offset, 0, data_sink)) { + if (!strm.is_writable()) { + error = Error::Write; + return false; + } else if (!content_provider(offset, 0, data_sink)) { error = Error::Canceled; return false; - } - if (!ok) { + } else if (!ok) { error = Error::Write; return false; } @@ -3659,7 +4397,8 @@ inline bool redirect(T &cli, Request &req, Response &res, new_req.path = path; new_req.redirect_count_ -= 1; - if (res.status == 303 && (req.method != "GET" && req.method != "HEAD")) { + if (res.status == StatusCode::SeeOther_303 && + (req.method != "GET" && req.method != "HEAD")) { new_req.method = "GET"; new_req.body.clear(); new_req.headers.clear(); @@ -3671,7 +4410,8 @@ inline bool redirect(T &cli, Request &req, Response &res, if (ret) { req = new_req; res = new_res; - res.location = location; + + if (res.location.empty()) { res.location = location; } } return ret; } @@ -3688,9 +4428,47 @@ inline std::string params_to_query_str(const Params ¶ms) { return query; } -inline void parse_query_text(const std::string &s, Params ¶ms) { +inline void parse_query_text(const char *data, std::size_t size, + Params ¶ms) { std::set cache; - split(s.data(), s.data() + s.size(), '&', [&](const char *b, const char *e) { + split(data, data + size, '&', [&](const char *b, const char *e) { + std::string kv(b, e); + if (cache.find(kv) != cache.end()) { return; } + cache.insert(std::move(kv)); + + std::string key; + std::string val; + divide(b, static_cast(e - b), '=', + [&](const char *lhs_data, std::size_t lhs_size, const char *rhs_data, + std::size_t rhs_size) { + key.assign(lhs_data, lhs_size); + val.assign(rhs_data, rhs_size); + }); + + if (!key.empty()) { + params.emplace(decode_url(key, true), decode_url(val, true)); + } + }); +} + +inline void parse_query_text(const std::string &s, Params ¶ms) { + parse_query_text(s.data(), s.size(), params); +} + +inline bool parse_multipart_boundary(const std::string &content_type, + std::string &boundary) { + auto boundary_keyword = "boundary="; + auto pos = content_type.find(boundary_keyword); + if (pos == std::string::npos) { return false; } + auto end = content_type.find(';', pos); + auto beg = pos + strlen(boundary_keyword); + boundary = trim_double_quotes_copy(content_type.substr(beg, end - beg)); + return !boundary.empty(); +} + +inline void parse_disposition_params(const std::string &s, Params ¶ms) { + std::set cache; + split(s.data(), s.data() + s.size(), ';', [&](const char *b, const char *e) { std::string kv(b, e); if (cache.find(kv) != cache.end()) { return; } cache.insert(kv); @@ -3706,57 +4484,55 @@ inline void parse_query_text(const std::string &s, Params ¶ms) { }); if (!key.empty()) { - params.emplace(decode_url(key, true), decode_url(val, true)); + params.emplace(trim_double_quotes_copy((key)), + trim_double_quotes_copy((val))); } }); } -inline bool parse_multipart_boundary(const std::string &content_type, - std::string &boundary) { - auto pos = content_type.find("boundary="); - if (pos == std::string::npos) { return false; } - boundary = content_type.substr(pos + 9); - if (boundary.length() >= 2 && boundary.front() == '"' && - boundary.back() == '"') { - boundary = boundary.substr(1, boundary.size() - 2); - } - return !boundary.empty(); -} - #ifdef CPPHTTPLIB_NO_EXCEPTIONS inline bool parse_range_header(const std::string &s, Ranges &ranges) { #else inline bool parse_range_header(const std::string &s, Ranges &ranges) try { #endif - static auto re_first_range = std::regex(R"(bytes=(\d*-\d*(?:,\s*\d*-\d*)*))"); - std::smatch m; - if (std::regex_match(s, m, re_first_range)) { - auto pos = static_cast(m.position(1)); - auto len = static_cast(m.length(1)); - bool all_valid_ranges = true; + auto is_valid = [](const std::string &str) { + return std::all_of(str.cbegin(), str.cend(), + [](unsigned char c) { return std::isdigit(c); }); + }; + + if (s.size() > 7 && s.compare(0, 6, "bytes=") == 0) { + const auto pos = static_cast(6); + const auto len = static_cast(s.size() - 6); + auto all_valid_ranges = true; split(&s[pos], &s[pos + len], ',', [&](const char *b, const char *e) { - if (!all_valid_ranges) return; - static auto re_another_range = std::regex(R"(\s*(\d*)-(\d*))"); - std::cmatch cm; - if (std::regex_match(b, e, cm, re_another_range)) { - ssize_t first = -1; - if (!cm.str(1).empty()) { - first = static_cast(std::stoll(cm.str(1))); - } + if (!all_valid_ranges) { return; } - ssize_t last = -1; - if (!cm.str(2).empty()) { - last = static_cast(std::stoll(cm.str(2))); - } - - if (first != -1 && last != -1 && first > last) { - all_valid_ranges = false; - return; - } - ranges.emplace_back(std::make_pair(first, last)); + const auto it = std::find(b, e, '-'); + if (it == e) { + all_valid_ranges = false; + return; } + + const auto lhs = std::string(b, it); + const auto rhs = std::string(it + 1, e); + if (!is_valid(lhs) || !is_valid(rhs)) { + all_valid_ranges = false; + return; + } + + const auto first = + static_cast(lhs.empty() ? -1 : std::stoll(lhs)); + const auto last = + static_cast(rhs.empty() ? -1 : std::stoll(rhs)); + if ((first == -1 && last == -1) || + (first != -1 && last != -1 && first > last)) { + all_valid_ranges = false; + return; + } + + ranges.emplace_back(first, last); }); - return all_valid_ranges; + return all_valid_ranges && !ranges.empty(); } return false; #ifdef CPPHTTPLIB_NO_EXCEPTIONS @@ -3769,30 +4545,26 @@ class MultipartFormDataParser { public: MultipartFormDataParser() = default; - void set_boundary(std::string &&boundary) { boundary_ = boundary; } + void set_boundary(std::string &&boundary) { + boundary_ = boundary; + dash_boundary_crlf_ = dash_ + boundary_ + crlf_; + crlf_dash_boundary_ = crlf_ + dash_ + boundary_; + } bool is_valid() const { return is_valid_; } bool parse(const char *buf, size_t n, const ContentReceiver &content_callback, const MultipartContentHeader &header_callback) { - // TODO: support 'filename*' - static const std::regex re_content_disposition( - R"~(^Content-Disposition:\s*form-data;\s*name="(.*?)"(?:;\s*filename="(.*?)")?(?:;\s*filename\*=\S+)?\s*$)~", - std::regex_constants::icase); - - static const std::string dash_ = "--"; - static const std::string crlf_ = "\r\n"; - buf_append(buf, n); while (buf_size() > 0) { switch (state_) { case 0: { // Initial boundary - auto pattern = dash_ + boundary_ + crlf_; - if (pattern.size() > buf_size()) { return true; } - if (!buf_start_with(pattern)) { return false; } - buf_erase(pattern.size()); + buf_erase(buf_find(dash_boundary_crlf_)); + if (dash_boundary_crlf_.size() > buf_size()) { return true; } + if (!buf_start_with(dash_boundary_crlf_)) { return false; } + buf_erase(dash_boundary_crlf_.size()); state_ = 1; break; } @@ -3816,18 +4588,56 @@ public: break; } - static const std::string header_name = "content-type:"; const auto header = buf_head(pos); - if (start_with_case_ignore(header, header_name)) { - file_.content_type = trim_copy(header.substr(header_name.size())); - } else { - std::smatch m; - if (std::regex_match(header, m, re_content_disposition)) { - file_.name = m[1]; - file_.filename = m[2]; - } + + if (!parse_header(header.data(), header.data() + header.size(), + [&](const std::string &, const std::string &) {})) { + is_valid_ = false; + return false; } + static const std::string header_content_type = "Content-Type:"; + + if (start_with_case_ignore(header, header_content_type)) { + file_.content_type = + trim_copy(header.substr(header_content_type.size())); + } else { + static const std::regex re_content_disposition( + R"~(^Content-Disposition:\s*form-data;\s*(.*)$)~", + std::regex_constants::icase); + + std::smatch m; + if (std::regex_match(header, m, re_content_disposition)) { + Params params; + parse_disposition_params(m[1], params); + + auto it = params.find("name"); + if (it != params.end()) { + file_.name = it->second; + } else { + is_valid_ = false; + return false; + } + + it = params.find("filename"); + if (it != params.end()) { file_.filename = it->second; } + + it = params.find("filename*"); + if (it != params.end()) { + // Only allow UTF-8 enconnding... + static const std::regex re_rfc5987_encoding( + R"~(^UTF-8''(.+?)$)~", std::regex_constants::icase); + + std::smatch m2; + if (std::regex_match(it->second, m2, re_rfc5987_encoding)) { + file_.filename = decode_url(m2[1], false); // override... + } else { + is_valid_ = false; + return false; + } + } + } + } buf_erase(pos + crlf_.size()); pos = buf_find(crlf_); } @@ -3835,40 +4645,25 @@ public: break; } case 3: { // Body - { - auto pattern = crlf_ + dash_; - if (pattern.size() > buf_size()) { return true; } - - auto pos = buf_find(pattern); - + if (crlf_dash_boundary_.size() > buf_size()) { return true; } + auto pos = buf_find(crlf_dash_boundary_); + if (pos < buf_size()) { if (!content_callback(buf_data(), pos)) { is_valid_ = false; return false; } - - buf_erase(pos); - } - { - auto pattern = crlf_ + dash_ + boundary_; - if (pattern.size() > buf_size()) { return true; } - - auto pos = buf_find(pattern); - if (pos < buf_size()) { - if (!content_callback(buf_data(), pos)) { + buf_erase(pos + crlf_dash_boundary_.size()); + state_ = 4; + } else { + auto len = buf_size() - crlf_dash_boundary_.size(); + if (len > 0) { + if (!content_callback(buf_data(), len)) { is_valid_ = false; return false; } - - buf_erase(pos + pattern.size()); - state_ = 4; - } else { - if (!content_callback(buf_data(), pattern.size())) { - is_valid_ = false; - return false; - } - - buf_erase(pattern.size()); + buf_erase(len); } + return true; } break; } @@ -3878,22 +4673,17 @@ public: buf_erase(crlf_.size()); state_ = 1; } else { - auto pattern = dash_ + crlf_; - if (pattern.size() > buf_size()) { return true; } - if (buf_start_with(pattern)) { - buf_erase(pattern.size()); + if (dash_.size() > buf_size()) { return true; } + if (buf_start_with(dash_)) { + buf_erase(dash_.size()); is_valid_ = true; - state_ = 5; + buf_erase(buf_size()); // Remove epilogue } else { return true; } } break; } - case 5: { // Done - is_valid_ = false; - return false; - } } } @@ -3916,7 +4706,11 @@ private: return true; } + const std::string dash_ = "--"; + const std::string crlf_ = "\r\n"; std::string boundary_; + std::string dash_boundary_crlf_; + std::string crlf_dash_boundary_; size_t state_ = 0; bool is_valid_ = false; @@ -4000,65 +4794,174 @@ inline std::string to_lower(const char *beg, const char *end) { return out; } -inline std::string make_multipart_data_boundary() { +inline std::string random_string(size_t length) { static const char data[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; // std::random_device might actually be deterministic on some // platforms, but due to lack of support in the c++ standard library, // doing better requires either some ugly hacks or breaking portability. - std::random_device seed_gen; + static std::random_device seed_gen; // Request 128 bits of entropy for initialization - std::seed_seq seed_sequence{seed_gen(), seed_gen(), seed_gen(), seed_gen()}; - std::mt19937 engine(seed_sequence); + static std::seed_seq seed_sequence{seed_gen(), seed_gen(), seed_gen(), + seed_gen()}; - std::string result = "--cpp-httplib-multipart-data-"; + static std::mt19937 engine(seed_sequence); - for (auto i = 0; i < 16; i++) { + std::string result; + for (size_t i = 0; i < length; i++) { result += data[engine() % (sizeof(data) - 1)]; } - return result; } +inline std::string make_multipart_data_boundary() { + return "--cpp-httplib-multipart-data-" + detail::random_string(16); +} + +inline bool is_multipart_boundary_chars_valid(const std::string &boundary) { + auto valid = true; + for (size_t i = 0; i < boundary.size(); i++) { + auto c = boundary[i]; + if (!std::isalnum(c) && c != '-' && c != '_') { + valid = false; + break; + } + } + return valid; +} + +template +inline std::string +serialize_multipart_formdata_item_begin(const T &item, + const std::string &boundary) { + std::string body = "--" + boundary + "\r\n"; + body += "Content-Disposition: form-data; name=\"" + item.name + "\""; + if (!item.filename.empty()) { + body += "; filename=\"" + item.filename + "\""; + } + body += "\r\n"; + if (!item.content_type.empty()) { + body += "Content-Type: " + item.content_type + "\r\n"; + } + body += "\r\n"; + + return body; +} + +inline std::string serialize_multipart_formdata_item_end() { return "\r\n"; } + +inline std::string +serialize_multipart_formdata_finish(const std::string &boundary) { + return "--" + boundary + "--\r\n"; +} + +inline std::string +serialize_multipart_formdata_get_content_type(const std::string &boundary) { + return "multipart/form-data; boundary=" + boundary; +} + +inline std::string +serialize_multipart_formdata(const MultipartFormDataItems &items, + const std::string &boundary, bool finish = true) { + std::string body; + + for (const auto &item : items) { + body += serialize_multipart_formdata_item_begin(item, boundary); + body += item.content + serialize_multipart_formdata_item_end(); + } + + if (finish) { body += serialize_multipart_formdata_finish(boundary); } + + return body; +} + +inline bool range_error(Request &req, Response &res) { + if (!req.ranges.empty() && 200 <= res.status && res.status < 300) { + ssize_t contant_len = static_cast( + res.content_length_ ? res.content_length_ : res.body.size()); + + ssize_t prev_first_pos = -1; + ssize_t prev_last_pos = -1; + size_t overwrapping_count = 0; + + // NOTE: The following Range check is based on '14.2. Range' in RFC 9110 + // 'HTTP Semantics' to avoid potential denial-of-service attacks. + // https://www.rfc-editor.org/rfc/rfc9110#section-14.2 + + // Too many ranges + if (req.ranges.size() > CPPHTTPLIB_RANGE_MAX_COUNT) { return true; } + + for (auto &r : req.ranges) { + auto &first_pos = r.first; + auto &last_pos = r.second; + + if (first_pos == -1 && last_pos == -1) { + first_pos = 0; + last_pos = contant_len; + } + + if (first_pos == -1) { + first_pos = contant_len - last_pos; + last_pos = contant_len - 1; + } + + if (last_pos == -1) { last_pos = contant_len - 1; } + + // Range must be within content length + if (!(0 <= first_pos && first_pos <= last_pos && + last_pos <= contant_len - 1)) { + return true; + } + + // Ranges must be in ascending order + if (first_pos <= prev_first_pos) { return true; } + + // Request must not have more than two overlapping ranges + if (first_pos <= prev_last_pos) { + overwrapping_count++; + if (overwrapping_count > 2) { return true; } + } + + prev_first_pos = (std::max)(prev_first_pos, first_pos); + prev_last_pos = (std::max)(prev_last_pos, last_pos); + } + } + + return false; +} + inline std::pair -get_range_offset_and_length(const Request &req, size_t content_length, - size_t index) { - auto r = req.ranges[index]; - - if (r.first == -1 && r.second == -1) { - return std::make_pair(0, content_length); - } - - auto slen = static_cast(content_length); - - if (r.first == -1) { - r.first = (std::max)(static_cast(0), slen - r.second); - r.second = slen - 1; - } - - if (r.second == -1) { r.second = slen - 1; } +get_range_offset_and_length(Range r, size_t content_length) { + assert(r.first != -1 && r.second != -1); + assert(0 <= r.first && r.first < static_cast(content_length)); + assert(r.first <= r.second && + r.second < static_cast(content_length)); + (void)(content_length); return std::make_pair(r.first, static_cast(r.second - r.first) + 1); } -inline std::string make_content_range_header_field(size_t offset, size_t length, - size_t content_length) { +inline std::string make_content_range_header_field( + const std::pair &offset_and_length, size_t content_length) { + auto st = offset_and_length.first; + auto ed = st + offset_and_length.second - 1; + std::string field = "bytes "; - field += std::to_string(offset); + field += std::to_string(st); field += "-"; - field += std::to_string(offset + length - 1); + field += std::to_string(ed); field += "/"; field += std::to_string(content_length); return field; } template -bool process_multipart_ranges_data(const Request &req, Response &res, +bool process_multipart_ranges_data(const Request &req, const std::string &boundary, const std::string &content_type, - SToken stoken, CToken ctoken, - Content content) { + size_t content_length, SToken stoken, + CToken ctoken, Content content) { for (size_t i = 0; i < req.ranges.size(); i++) { ctoken("--"); stoken(boundary); @@ -4069,52 +4972,53 @@ bool process_multipart_ranges_data(const Request &req, Response &res, ctoken("\r\n"); } - auto offsets = get_range_offset_and_length(req, res.body.size(), i); - auto offset = offsets.first; - auto length = offsets.second; + auto offset_and_length = + get_range_offset_and_length(req.ranges[i], content_length); ctoken("Content-Range: "); - stoken(make_content_range_header_field(offset, length, res.body.size())); + stoken(make_content_range_header_field(offset_and_length, content_length)); ctoken("\r\n"); ctoken("\r\n"); - if (!content(offset, length)) { return false; } + + if (!content(offset_and_length.first, offset_and_length.second)) { + return false; + } ctoken("\r\n"); } ctoken("--"); stoken(boundary); - ctoken("--\r\n"); + ctoken("--"); return true; } -inline bool make_multipart_ranges_data(const Request &req, Response &res, +inline void make_multipart_ranges_data(const Request &req, Response &res, const std::string &boundary, const std::string &content_type, + size_t content_length, std::string &data) { - return process_multipart_ranges_data( - req, res, boundary, content_type, + process_multipart_ranges_data( + req, boundary, content_type, content_length, + [&](const std::string &token) { data += token; }, [&](const std::string &token) { data += token; }, - [&](const char *token) { data += token; }, [&](size_t offset, size_t length) { - if (offset < res.body.size()) { - data += res.body.substr(offset, length); - return true; - } - return false; + assert(offset + length <= content_length); + data += res.body.substr(offset, length); + return true; }); } -inline size_t -get_multipart_ranges_data_length(const Request &req, Response &res, - const std::string &boundary, - const std::string &content_type) { +inline size_t get_multipart_ranges_data_length(const Request &req, + const std::string &boundary, + const std::string &content_type, + size_t content_length) { size_t data_length = 0; process_multipart_ranges_data( - req, res, boundary, content_type, + req, boundary, content_type, content_length, + [&](const std::string &token) { data_length += token.size(); }, [&](const std::string &token) { data_length += token.size(); }, - [&](const char *token) { data_length += strlen(token); }, [&](size_t /*offset*/, size_t length) { data_length += length; return true; @@ -4124,33 +5028,21 @@ get_multipart_ranges_data_length(const Request &req, Response &res, } template -inline bool write_multipart_ranges_data(Stream &strm, const Request &req, - Response &res, - const std::string &boundary, - const std::string &content_type, - const T &is_shutting_down) { +inline bool +write_multipart_ranges_data(Stream &strm, const Request &req, Response &res, + const std::string &boundary, + const std::string &content_type, + size_t content_length, const T &is_shutting_down) { return process_multipart_ranges_data( - req, res, boundary, content_type, + req, boundary, content_type, content_length, + [&](const std::string &token) { strm.write(token); }, [&](const std::string &token) { strm.write(token); }, - [&](const char *token) { strm.write(token); }, [&](size_t offset, size_t length) { return write_content(strm, res.content_provider_, offset, length, is_shutting_down); }); } -inline std::pair -get_range_offset_and_length(const Request &req, const Response &res, - size_t index) { - auto r = req.ranges[index]; - - if (r.second == -1) { - r.second = static_cast(res.content_length_) - 1; - } - - return std::make_pair(r.first, r.second - r.first + 1); -} - inline bool expect_content(const Request &req) { if (req.method == "POST" || req.method == "PUT" || req.method == "PATCH" || req.method == "PRI" || req.method == "DELETE") { @@ -4160,8 +5052,8 @@ inline bool expect_content(const Request &req) { return false; } -inline bool has_crlf(const char *s) { - auto p = s; +inline bool has_crlf(const std::string &s) { + auto p = s.c_str(); while (*p) { if (*p == '\r' || *p == '\n') { return true; } p++; @@ -4184,7 +5076,7 @@ inline std::string message_digest(const std::string &s, const EVP_MD *algo) { std::stringstream ss; for (auto i = 0u; i < hash_length; ++i) { ss << std::hex << std::setw(2) << std::setfill('0') - << (unsigned int)hash[i]; + << static_cast(hash[i]); } return ss.str(); @@ -4203,15 +5095,15 @@ inline std::string SHA_512(const std::string &s) { } #endif -#ifdef _WIN32 #ifdef CPPHTTPLIB_OPENSSL_SUPPORT +#ifdef _WIN32 // NOTE: This code came up with the following stackoverflow post: // https://stackoverflow.com/questions/9507184/can-openssl-on-windows-use-the-system-certificate-store inline bool load_system_certs_on_windows(X509_STORE *store) { auto hStore = CertOpenSystemStoreW((HCRYPTPROV_LEGACY)NULL, L"ROOT"); - if (!hStore) { return false; } + auto result = false; PCCERT_CONTEXT pContext = NULL; while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) != nullptr) { @@ -4222,16 +5114,109 @@ inline bool load_system_certs_on_windows(X509_STORE *store) { if (x509) { X509_STORE_add_cert(store, x509); X509_free(x509); + result = true; } } CertFreeCertificateContext(pContext); CertCloseStore(hStore, 0); + return result; +} +#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__) +#if TARGET_OS_OSX +template +using CFObjectPtr = + std::unique_ptr::type, void (*)(CFTypeRef)>; + +inline void cf_object_ptr_deleter(CFTypeRef obj) { + if (obj) { CFRelease(obj); } +} + +inline bool retrieve_certs_from_keychain(CFObjectPtr &certs) { + CFStringRef keys[] = {kSecClass, kSecMatchLimit, kSecReturnRef}; + CFTypeRef values[] = {kSecClassCertificate, kSecMatchLimitAll, + kCFBooleanTrue}; + + CFObjectPtr query( + CFDictionaryCreate(nullptr, reinterpret_cast(keys), values, + sizeof(keys) / sizeof(keys[0]), + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks), + cf_object_ptr_deleter); + + if (!query) { return false; } + + CFTypeRef security_items = nullptr; + if (SecItemCopyMatching(query.get(), &security_items) != errSecSuccess || + CFArrayGetTypeID() != CFGetTypeID(security_items)) { + return false; + } + + certs.reset(reinterpret_cast(security_items)); return true; } -#endif +inline bool retrieve_root_certs_from_keychain(CFObjectPtr &certs) { + CFArrayRef root_security_items = nullptr; + if (SecTrustCopyAnchorCertificates(&root_security_items) != errSecSuccess) { + return false; + } + + certs.reset(root_security_items); + return true; +} + +inline bool add_certs_to_x509_store(CFArrayRef certs, X509_STORE *store) { + auto result = false; + for (auto i = 0; i < CFArrayGetCount(certs); ++i) { + const auto cert = reinterpret_cast( + CFArrayGetValueAtIndex(certs, i)); + + if (SecCertificateGetTypeID() != CFGetTypeID(cert)) { continue; } + + CFDataRef cert_data = nullptr; + if (SecItemExport(cert, kSecFormatX509Cert, 0, nullptr, &cert_data) != + errSecSuccess) { + continue; + } + + CFObjectPtr cert_data_ptr(cert_data, cf_object_ptr_deleter); + + auto encoded_cert = static_cast( + CFDataGetBytePtr(cert_data_ptr.get())); + + auto x509 = + d2i_X509(NULL, &encoded_cert, CFDataGetLength(cert_data_ptr.get())); + + if (x509) { + X509_STORE_add_cert(store, x509); + X509_free(x509); + result = true; + } + } + + return result; +} + +inline bool load_system_certs_on_macos(X509_STORE *store) { + auto result = false; + CFObjectPtr certs(nullptr, cf_object_ptr_deleter); + if (retrieve_certs_from_keychain(certs) && certs) { + result = add_certs_to_x509_store(certs.get(), store); + } + + if (retrieve_root_certs_from_keychain(certs) && certs) { + result = add_certs_to_x509_store(certs.get(), store) || result; + } + + return result; +} +#endif // TARGET_OS_OSX +#endif // _WIN32 +#endif // CPPHTTPLIB_OPENSSL_SUPPORT + +#ifdef _WIN32 class WSInit { public: WSInit() { @@ -4327,7 +5312,7 @@ inline bool parse_www_authenticate(const Response &res, s = s.substr(pos + 1); auto beg = std::sregex_iterator(s.begin(), s.end(), re); for (auto i = beg; i != std::sregex_iterator(); ++i) { - auto m = *i; + const auto &m = *i; auto key = s.substr(static_cast(m.position(1)), static_cast(m.length(1))); auto val = m.length(2) > 0 @@ -4344,20 +5329,6 @@ inline bool parse_www_authenticate(const Response &res, return false; } -// https://stackoverflow.com/questions/440133/how-do-i-create-a-random-alpha-numeric-string-in-c/440240#answer-440240 -inline std::string random_string(size_t length) { - auto randchar = []() -> char { - const char charset[] = "0123456789" - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "abcdefghijklmnopqrstuvwxyz"; - const size_t max_index = (sizeof(charset) - 1); - return charset[static_cast(std::rand()) % max_index]; - }; - std::string str(length, 0); - std::generate_n(str.begin(), length, randchar); - return str; -} - class ContentProviderAdapter { public: explicit ContentProviderAdapter( @@ -4374,14 +5345,15 @@ private: } // namespace detail -inline std::string hosted_at(const char *hostname) { +inline std::string hosted_at(const std::string &hostname) { std::vector addrs; hosted_at(hostname, addrs); if (addrs.empty()) { return std::string(); } return addrs[0]; } -inline void hosted_at(const char *hostname, std::vector &addrs) { +inline void hosted_at(const std::string &hostname, + std::vector &addrs) { struct addrinfo hints; struct addrinfo *result; @@ -4390,7 +5362,7 @@ inline void hosted_at(const char *hostname, std::vector &addrs) { hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; - if (getaddrinfo(hostname, nullptr, &hints, &result)) { + if (getaddrinfo(hostname.c_str(), nullptr, &hints, &result)) { #if defined __linux__ && !defined __ANDROID__ res_init(); #endif @@ -4401,15 +5373,18 @@ inline void hosted_at(const char *hostname, std::vector &addrs) { const auto &addr = *reinterpret_cast(rp->ai_addr); std::string ip; - int dummy = -1; - if (detail::get_remote_ip_and_port(addr, sizeof(struct sockaddr_storage), - ip, dummy)) { + auto dummy = -1; + if (detail::get_ip_and_port(addr, sizeof(struct sockaddr_storage), ip, + dummy)) { addrs.push_back(ip); } } + + freeaddrinfo(result); } -inline std::string append_query_params(const char *path, const Params ¶ms) { +inline std::string append_query_params(const std::string &path, + const Params ¶ms) { std::string path_with_query = path; const static std::regex re("[^?]+\\?.*"); auto delm = std::regex_match(path, re) ? '&' : '?'; @@ -4418,10 +5393,11 @@ inline std::string append_query_params(const char *path, const Params ¶ms) { } // Header utilities -inline std::pair make_range_header(Ranges ranges) { +inline std::pair +make_range_header(const Ranges &ranges) { std::string field = "bytes="; auto i = 0; - for (auto r : ranges) { + for (const auto &r : ranges) { if (i != 0) { field += ", "; } if (r.first != -1) { field += std::to_string(r.first); } field += '-'; @@ -4448,36 +5424,33 @@ make_bearer_token_authentication_header(const std::string &token, } // Request implementation -inline bool Request::has_header(const char *key) const { +inline bool Request::has_header(const std::string &key) const { return detail::has_header(headers, key); } -inline std::string Request::get_header_value(const char *key, size_t id) const { +inline std::string Request::get_header_value(const std::string &key, + size_t id) const { return detail::get_header_value(headers, key, id, ""); } -inline size_t Request::get_header_value_count(const char *key) const { +inline size_t Request::get_header_value_count(const std::string &key) const { auto r = headers.equal_range(key); return static_cast(std::distance(r.first, r.second)); } -inline void Request::set_header(const char *key, const char *val) { +inline void Request::set_header(const std::string &key, + const std::string &val) { if (!detail::has_crlf(key) && !detail::has_crlf(val)) { headers.emplace(key, val); } } -inline void Request::set_header(const char *key, const std::string &val) { - if (!detail::has_crlf(key) && !detail::has_crlf(val.c_str())) { - headers.emplace(key, val); - } -} - -inline bool Request::has_param(const char *key) const { +inline bool Request::has_param(const std::string &key) const { return params.find(key) != params.end(); } -inline std::string Request::get_param_value(const char *key, size_t id) const { +inline std::string Request::get_param_value(const std::string &key, + size_t id) const { auto rng = params.equal_range(key); auto it = rng.first; std::advance(it, static_cast(id)); @@ -4485,7 +5458,7 @@ inline std::string Request::get_param_value(const char *key, size_t id) const { return std::string(); } -inline size_t Request::get_param_value_count(const char *key) const { +inline size_t Request::get_param_value_count(const std::string &key) const { auto r = params.equal_range(key); return static_cast(std::distance(r.first, r.second)); } @@ -4495,60 +5468,61 @@ inline bool Request::is_multipart_form_data() const { return !content_type.rfind("multipart/form-data", 0); } -inline bool Request::has_file(const char *key) const { +inline bool Request::has_file(const std::string &key) const { return files.find(key) != files.end(); } -inline MultipartFormData Request::get_file_value(const char *key) const { +inline MultipartFormData Request::get_file_value(const std::string &key) const { auto it = files.find(key); if (it != files.end()) { return it->second; } return MultipartFormData(); } +inline std::vector +Request::get_file_values(const std::string &key) const { + std::vector values; + auto rng = files.equal_range(key); + for (auto it = rng.first; it != rng.second; it++) { + values.push_back(it->second); + } + return values; +} + // Response implementation -inline bool Response::has_header(const char *key) const { +inline bool Response::has_header(const std::string &key) const { return headers.find(key) != headers.end(); } -inline std::string Response::get_header_value(const char *key, +inline std::string Response::get_header_value(const std::string &key, size_t id) const { return detail::get_header_value(headers, key, id, ""); } -inline size_t Response::get_header_value_count(const char *key) const { +inline size_t Response::get_header_value_count(const std::string &key) const { auto r = headers.equal_range(key); return static_cast(std::distance(r.first, r.second)); } -inline void Response::set_header(const char *key, const char *val) { +inline void Response::set_header(const std::string &key, + const std::string &val) { if (!detail::has_crlf(key) && !detail::has_crlf(val)) { headers.emplace(key, val); } } -inline void Response::set_header(const char *key, const std::string &val) { - if (!detail::has_crlf(key) && !detail::has_crlf(val.c_str())) { - headers.emplace(key, val); - } -} - -inline void Response::set_redirect(const char *url, int stat) { +inline void Response::set_redirect(const std::string &url, int stat) { if (!detail::has_crlf(url)) { set_header("Location", url); if (300 <= stat && stat < 400) { this->status = stat; } else { - this->status = 302; + this->status = StatusCode::Found_302; } } } -inline void Response::set_redirect(const std::string &url, int stat) { - set_redirect(url.c_str(), stat); -} - inline void Response::set_content(const char *s, size_t n, - const char *content_type) { + const std::string &content_type) { body.assign(s, n); auto rng = headers.equal_range("Content-Type"); @@ -4557,52 +5531,61 @@ inline void Response::set_content(const char *s, size_t n, } inline void Response::set_content(const std::string &s, - const char *content_type) { + const std::string &content_type) { set_content(s.data(), s.size(), content_type); } +inline void Response::set_content(std::string &&s, + const std::string &content_type) { + body = std::move(s); + + auto rng = headers.equal_range("Content-Type"); + headers.erase(rng.first, rng.second); + set_header("Content-Type", content_type); +} + inline void Response::set_content_provider( - size_t in_length, const char *content_type, ContentProvider provider, + size_t in_length, const std::string &content_type, ContentProvider provider, ContentProviderResourceReleaser resource_releaser) { - assert(in_length > 0); set_header("Content-Type", content_type); content_length_ = in_length; - content_provider_ = std::move(provider); - content_provider_resource_releaser_ = resource_releaser; + if (in_length > 0) { content_provider_ = std::move(provider); } + content_provider_resource_releaser_ = std::move(resource_releaser); is_chunked_content_provider_ = false; } inline void Response::set_content_provider( - const char *content_type, ContentProviderWithoutLength provider, + const std::string &content_type, ContentProviderWithoutLength provider, ContentProviderResourceReleaser resource_releaser) { set_header("Content-Type", content_type); content_length_ = 0; content_provider_ = detail::ContentProviderAdapter(std::move(provider)); - content_provider_resource_releaser_ = resource_releaser; + content_provider_resource_releaser_ = std::move(resource_releaser); is_chunked_content_provider_ = false; } inline void Response::set_chunked_content_provider( - const char *content_type, ContentProviderWithoutLength provider, + const std::string &content_type, ContentProviderWithoutLength provider, ContentProviderResourceReleaser resource_releaser) { set_header("Content-Type", content_type); content_length_ = 0; content_provider_ = detail::ContentProviderAdapter(std::move(provider)); - content_provider_resource_releaser_ = resource_releaser; + content_provider_resource_releaser_ = std::move(resource_releaser); is_chunked_content_provider_ = true; } // Result implementation -inline bool Result::has_request_header(const char *key) const { +inline bool Result::has_request_header(const std::string &key) const { return request_headers_.find(key) != request_headers_.end(); } -inline std::string Result::get_request_header_value(const char *key, +inline std::string Result::get_request_header_value(const std::string &key, size_t id) const { return detail::get_header_value(request_headers_, key, id, ""); } -inline size_t Result::get_request_header_value_count(const char *key) const { +inline size_t +Result::get_request_header_value_count(const std::string &key) const { auto r = request_headers_.equal_range(key); return static_cast(std::distance(r.first, r.second)); } @@ -4628,14 +5611,15 @@ inline SocketStream::SocketStream(socket_t sock, time_t read_timeout_sec, write_timeout_sec_(write_timeout_sec), write_timeout_usec_(write_timeout_usec), read_buff_(read_buff_size_, 0) {} -inline SocketStream::~SocketStream() {} +inline SocketStream::~SocketStream() = default; inline bool SocketStream::is_readable() const { return select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0; } inline bool SocketStream::is_writable() const { - return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0; + return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0 && + is_socket_alive(sock_); } inline ssize_t SocketStream::read(char *ptr, size_t size) { @@ -4687,7 +5671,7 @@ inline ssize_t SocketStream::read(char *ptr, size_t size) { inline ssize_t SocketStream::write(const char *ptr, size_t size) { if (!is_writable()) { return -1; } -#ifdef _WIN32 +#if defined(_WIN32) && !defined(_WIN64) size = (std::min)(size, static_cast((std::numeric_limits::max)())); #endif @@ -4700,6 +5684,11 @@ inline void SocketStream::get_remote_ip_and_port(std::string &ip, return detail::get_remote_ip_and_port(sock_, ip, port); } +inline void SocketStream::get_local_ip_and_port(std::string &ip, + int &port) const { + return detail::get_local_ip_and_port(sock_, ip, port); +} + inline socket_t SocketStream::socket() const { return sock_; } // Buffer stream implementation @@ -4708,7 +5697,7 @@ inline bool BufferStream::is_readable() const { return true; } inline bool BufferStream::is_writable() const { return true; } inline ssize_t BufferStream::read(char *ptr, size_t size) { -#if defined(_MSC_VER) && _MSC_VER <= 1900 +#if defined(_MSC_VER) && _MSC_VER < 1910 auto len_read = buffer._Copy_s(ptr, size, size, position); #else auto len_read = buffer.copy(ptr, size, position); @@ -4725,85 +5714,183 @@ inline ssize_t BufferStream::write(const char *ptr, size_t size) { inline void BufferStream::get_remote_ip_and_port(std::string & /*ip*/, int & /*port*/) const {} +inline void BufferStream::get_local_ip_and_port(std::string & /*ip*/, + int & /*port*/) const {} + inline socket_t BufferStream::socket() const { return 0; } inline const std::string &BufferStream::get_buffer() const { return buffer; } +inline PathParamsMatcher::PathParamsMatcher(const std::string &pattern) { + // One past the last ending position of a path param substring + std::size_t last_param_end = 0; + +#ifndef CPPHTTPLIB_NO_EXCEPTIONS + // Needed to ensure that parameter names are unique during matcher + // construction + // If exceptions are disabled, only last duplicate path + // parameter will be set + std::unordered_set param_name_set; +#endif + + while (true) { + const auto marker_pos = pattern.find(marker, last_param_end); + if (marker_pos == std::string::npos) { break; } + + static_fragments_.push_back( + pattern.substr(last_param_end, marker_pos - last_param_end)); + + const auto param_name_start = marker_pos + 1; + + auto sep_pos = pattern.find(separator, param_name_start); + if (sep_pos == std::string::npos) { sep_pos = pattern.length(); } + + auto param_name = + pattern.substr(param_name_start, sep_pos - param_name_start); + +#ifndef CPPHTTPLIB_NO_EXCEPTIONS + if (param_name_set.find(param_name) != param_name_set.cend()) { + std::string msg = "Encountered path parameter '" + param_name + + "' multiple times in route pattern '" + pattern + "'."; + throw std::invalid_argument(msg); + } +#endif + + param_names_.push_back(std::move(param_name)); + + last_param_end = sep_pos + 1; + } + + if (last_param_end < pattern.length()) { + static_fragments_.push_back(pattern.substr(last_param_end)); + } +} + +inline bool PathParamsMatcher::match(Request &request) const { + request.matches = std::smatch(); + request.path_params.clear(); + request.path_params.reserve(param_names_.size()); + + // One past the position at which the path matched the pattern last time + std::size_t starting_pos = 0; + for (size_t i = 0; i < static_fragments_.size(); ++i) { + const auto &fragment = static_fragments_[i]; + + if (starting_pos + fragment.length() > request.path.length()) { + return false; + } + + // Avoid unnecessary allocation by using strncmp instead of substr + + // comparison + if (std::strncmp(request.path.c_str() + starting_pos, fragment.c_str(), + fragment.length()) != 0) { + return false; + } + + starting_pos += fragment.length(); + + // Should only happen when we have a static fragment after a param + // Example: '/users/:id/subscriptions' + // The 'subscriptions' fragment here does not have a corresponding param + if (i >= param_names_.size()) { continue; } + + auto sep_pos = request.path.find(separator, starting_pos); + if (sep_pos == std::string::npos) { sep_pos = request.path.length(); } + + const auto ¶m_name = param_names_[i]; + + request.path_params.emplace( + param_name, request.path.substr(starting_pos, sep_pos - starting_pos)); + + // Mark everythin up to '/' as matched + starting_pos = sep_pos + 1; + } + // Returns false if the path is longer than the pattern + return starting_pos >= request.path.length(); +} + +inline bool RegexMatcher::match(Request &request) const { + request.path_params.clear(); + return std::regex_match(request.path, request.matches, regex_); +} + } // namespace detail // HTTP server implementation inline Server::Server() : new_task_queue( - [] { return new ThreadPool(CPPHTTPLIB_THREAD_POOL_COUNT); }), - svr_sock_(INVALID_SOCKET), is_running_(false) { + [] { return new ThreadPool(CPPHTTPLIB_THREAD_POOL_COUNT); }) { #ifndef _WIN32 signal(SIGPIPE, SIG_IGN); #endif } -inline Server::~Server() {} +inline Server::~Server() = default; + +inline std::unique_ptr +Server::make_matcher(const std::string &pattern) { + if (pattern.find("/:") != std::string::npos) { + return detail::make_unique(pattern); + } else { + return detail::make_unique(pattern); + } +} inline Server &Server::Get(const std::string &pattern, Handler handler) { - get_handlers_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); + get_handlers_.emplace_back(make_matcher(pattern), std::move(handler)); return *this; } inline Server &Server::Post(const std::string &pattern, Handler handler) { - post_handlers_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); + post_handlers_.emplace_back(make_matcher(pattern), std::move(handler)); return *this; } inline Server &Server::Post(const std::string &pattern, HandlerWithContentReader handler) { - post_handlers_for_content_reader_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); + post_handlers_for_content_reader_.emplace_back(make_matcher(pattern), + std::move(handler)); return *this; } inline Server &Server::Put(const std::string &pattern, Handler handler) { - put_handlers_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); + put_handlers_.emplace_back(make_matcher(pattern), std::move(handler)); return *this; } inline Server &Server::Put(const std::string &pattern, HandlerWithContentReader handler) { - put_handlers_for_content_reader_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); + put_handlers_for_content_reader_.emplace_back(make_matcher(pattern), + std::move(handler)); return *this; } inline Server &Server::Patch(const std::string &pattern, Handler handler) { - patch_handlers_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); + patch_handlers_.emplace_back(make_matcher(pattern), std::move(handler)); return *this; } inline Server &Server::Patch(const std::string &pattern, HandlerWithContentReader handler) { - patch_handlers_for_content_reader_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); + patch_handlers_for_content_reader_.emplace_back(make_matcher(pattern), + std::move(handler)); return *this; } inline Server &Server::Delete(const std::string &pattern, Handler handler) { - delete_handlers_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); + delete_handlers_.emplace_back(make_matcher(pattern), std::move(handler)); return *this; } inline Server &Server::Delete(const std::string &pattern, HandlerWithContentReader handler) { - delete_handlers_for_content_reader_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); + delete_handlers_for_content_reader_.emplace_back(make_matcher(pattern), + std::move(handler)); return *this; } inline Server &Server::Options(const std::string &pattern, Handler handler) { - options_handlers_.push_back( - std::make_pair(std::regex(pattern), std::move(handler))); + options_handlers_.emplace_back(make_matcher(pattern), std::move(handler)); return *this; } @@ -4835,23 +5922,30 @@ inline bool Server::remove_mount_point(const std::string &mount_point) { } inline Server & -Server::set_file_extension_and_mimetype_mapping(const char *ext, - const char *mime) { +Server::set_file_extension_and_mimetype_mapping(const std::string &ext, + const std::string &mime) { file_extension_and_mimetype_map_[ext] = mime; return *this; } +inline Server &Server::set_default_file_mimetype(const std::string &mime) { + default_file_mimetype_ = mime; + return *this; +} + inline Server &Server::set_file_request_handler(Handler handler) { file_request_handler_ = std::move(handler); return *this; } -inline Server &Server::set_error_handler(HandlerWithResponse handler) { +inline Server &Server::set_error_handler_core(HandlerWithResponse handler, + std::true_type) { error_handler_ = std::move(handler); return *this; } -inline Server &Server::set_error_handler(Handler handler) { +inline Server &Server::set_error_handler_core(Handler handler, + std::false_type) { error_handler_ = [handler](const Request &req, Response &res) { handler(req, res); return HandlerResponse::Handled; @@ -4882,7 +5976,6 @@ inline Server &Server::set_logger(Logger logger) { inline Server & Server::set_expect_100_continue_handler(Expect100ContinueHandler handler) { expect_100_continue_handler_ = std::move(handler); - return *this; } @@ -4906,6 +5999,12 @@ inline Server &Server::set_default_headers(Headers headers) { return *this; } +inline Server &Server::set_header_writer( + std::function const &writer) { + header_writer_ = writer; + return *this; +} + inline Server &Server::set_keep_alive_max_count(size_t count) { keep_alive_max_count_ = count; return *this; @@ -4939,22 +6038,33 @@ inline Server &Server::set_payload_max_length(size_t length) { return *this; } -inline bool Server::bind_to_port(const char *host, int port, int socket_flags) { - if (bind_internal(host, port, socket_flags) < 0) return false; - return true; +inline bool Server::bind_to_port(const std::string &host, int port, + int socket_flags) { + return bind_internal(host, port, socket_flags) >= 0; } -inline int Server::bind_to_any_port(const char *host, int socket_flags) { +inline int Server::bind_to_any_port(const std::string &host, int socket_flags) { return bind_internal(host, 0, socket_flags); } -inline bool Server::listen_after_bind() { return listen_internal(); } +inline bool Server::listen_after_bind() { + auto se = detail::scope_exit([&]() { done_ = true; }); + return listen_internal(); +} -inline bool Server::listen(const char *host, int port, int socket_flags) { +inline bool Server::listen(const std::string &host, int port, + int socket_flags) { + auto se = detail::scope_exit([&]() { done_ = true; }); return bind_to_port(host, port, socket_flags) && listen_internal(); } inline bool Server::is_running() const { return is_running_; } +inline void Server::wait_until_ready() const { + while (!is_running() && !done_) { + std::this_thread::sleep_for(std::chrono::milliseconds{1}); + } +} + inline void Server::stop() { if (is_running_) { assert(svr_sock_ != INVALID_SOCKET); @@ -4964,7 +6074,7 @@ inline void Server::stop() { } } -inline bool Server::parse_request_line(const char *s, Request &req) { +inline bool Server::parse_request_line(const char *s, Request &req) const { auto len = strlen(s); if (len < 2 || s[len - 2] != '\r' || s[len - 1] != '\n') { return false; } len -= 2; @@ -5002,33 +6112,23 @@ inline bool Server::parse_request_line(const char *s, Request &req) { } } - size_t count = 0; - - detail::split(req.target.data(), req.target.data() + req.target.size(), '?', - [&](const char *b, const char *e) { - switch (count) { - case 0: - req.path = detail::decode_url(std::string(b, e), false); - break; - case 1: { - if (e - b > 0) { - detail::parse_query_text(std::string(b, e), req.params); - } - break; - } - default: break; - } - count++; - }); - - if (count > 2) { return false; } + detail::divide(req.target, '?', + [&](const char *lhs_data, std::size_t lhs_size, + const char *rhs_data, std::size_t rhs_size) { + req.path = detail::decode_url( + std::string(lhs_data, lhs_size), false); + detail::parse_query_text(rhs_data, rhs_size, req.params); + }); } return true; } inline bool Server::write_response(Stream &strm, bool close_connection, - const Request &req, Response &res) { + Request &req, Response &res) { + // NOTE: `req.ranges` should be empty, otherwise it will be applied + // incorrectly to the error content. + req.ranges.clear(); return write_response_core(strm, close_connection, req, res, false); } @@ -5084,27 +6184,28 @@ inline bool Server::write_response_core(Stream &strm, bool close_connection, detail::BufferStream bstrm; if (!bstrm.write_format("HTTP/1.1 %d %s\r\n", res.status, - detail::status_message(res.status))) { + status_message(res.status))) { return false; } - if (!detail::write_headers(bstrm, res.headers)) { return false; } + if (!header_writer_(bstrm, res.headers)) { return false; } // Flush buffer auto &data = bstrm.get_buffer(); - strm.write(data.data(), data.size()); + detail::write_data(strm, data.data(), data.size()); } // Body auto ret = true; if (req.method != "HEAD") { if (!res.body.empty()) { - if (!strm.write(res.body)) { ret = false; } + if (!detail::write_data(strm, res.body.data(), res.body.size())) { + ret = false; + } } else if (res.content_provider_) { if (write_content_with_provider(strm, req, res, boundary, content_type)) { res.content_provider_success_ = true; } else { - res.content_provider_success_ = false; ret = false; } } @@ -5129,15 +6230,16 @@ Server::write_content_with_provider(Stream &strm, const Request &req, return detail::write_content(strm, res.content_provider_, 0, res.content_length_, is_shutting_down); } else if (req.ranges.size() == 1) { - auto offsets = - detail::get_range_offset_and_length(req, res.content_length_, 0); - auto offset = offsets.first; - auto length = offsets.second; - return detail::write_content(strm, res.content_provider_, offset, length, - is_shutting_down); + auto offset_and_length = detail::get_range_offset_and_length( + req.ranges[0], res.content_length_); + + return detail::write_content(strm, res.content_provider_, + offset_and_length.first, + offset_and_length.second, is_shutting_down); } else { return detail::write_multipart_ranges_data( - strm, req, res, boundary, content_type, is_shutting_down); + strm, req, res, boundary, content_type, res.content_length_, + is_shutting_down); } } else { if (res.is_chunked_content_provider_) { @@ -5168,6 +6270,7 @@ Server::write_content_with_provider(Stream &strm, const Request &req, inline bool Server::read_content(Stream &strm, Request &req, Response &res) { MultipartFormDataMap::iterator cur; + auto file_count = 0; if (read_content_core( strm, req, res, // Regular @@ -5178,6 +6281,9 @@ inline bool Server::read_content(Stream &strm, Request &req, Response &res) { }, // Multipart [&](const MultipartFormData &file) { + if (file_count++ == CPPHTTPLIB_MULTIPART_FORM_DATA_FILE_MAX_COUNT) { + return false; + } cur = req.files.emplace(file.name, file); return true; }, @@ -5189,8 +6295,8 @@ inline bool Server::read_content(Stream &strm, Request &req, Response &res) { })) { const auto &content_type = req.get_header_value("Content-Type"); if (!content_type.find("application/x-www-form-urlencoded")) { - if (req.body.size() > CPPHTTPLIB_REQUEST_URI_MAX_LENGTH) { - res.status = 413; // NOTE: should be 414? + if (req.body.size() > CPPHTTPLIB_FORM_URL_ENCODED_PAYLOAD_MAX_LENGTH) { + res.status = StatusCode::PayloadTooLarge_413; // NOTE: should be 414? return false; } detail::parse_query_text(req.body, req.params); @@ -5209,10 +6315,11 @@ inline bool Server::read_content_with_content_receiver( std::move(multipart_receiver)); } -inline bool Server::read_content_core(Stream &strm, Request &req, Response &res, - ContentReceiver receiver, - MultipartContentHeader mulitpart_header, - ContentReceiver multipart_receiver) { +inline bool +Server::read_content_core(Stream &strm, Request &req, Response &res, + ContentReceiver receiver, + MultipartContentHeader multipart_header, + ContentReceiver multipart_receiver) const { detail::MultipartFormDataParser multipart_form_data_parser; ContentReceiverWithProgress out; @@ -5220,7 +6327,7 @@ inline bool Server::read_content_core(Stream &strm, Request &req, Response &res, const auto &content_type = req.get_header_value("Content-Type"); std::string boundary; if (!detail::parse_multipart_boundary(content_type, boundary)) { - res.status = 400; + res.status = StatusCode::BadRequest_400; return false; } @@ -5231,14 +6338,14 @@ inline bool Server::read_content_core(Stream &strm, Request &req, Response &res, while (pos < n) { auto read_size = (std::min)(1, n - pos); auto ret = multipart_form_data_parser.parse( - buf + pos, read_size, multipart_receiver, mulitpart_header); + buf + pos, read_size, multipart_receiver, multipart_header); if (!ret) { return false; } pos += read_size; } return true; */ return multipart_form_data_parser.parse(buf, n, multipart_receiver, - mulitpart_header); + multipart_header); }; } else { out = [receiver](const char *buf, size_t n, uint64_t /*off*/, @@ -5256,7 +6363,7 @@ inline bool Server::read_content_core(Stream &strm, Request &req, Response &res, if (req.is_multipart_form_data()) { if (!multipart_form_data_parser.is_valid()) { - res.status = 400; + res.status = StatusCode::BadRequest_400; return false; } } @@ -5275,17 +6382,26 @@ inline bool Server::handle_file_request(const Request &req, Response &res, if (path.back() == '/') { path += "index.html"; } if (detail::is_file(path)) { - detail::read_file(path, res.body); - auto type = - detail::find_content_type(path, file_extension_and_mimetype_map_); - if (type) { res.set_header("Content-Type", type); } for (const auto &kv : entry.headers) { - res.set_header(kv.first.c_str(), kv.second); + res.set_header(kv.first, kv.second); } - res.status = req.has_header("Range") ? 206 : 200; + + auto mm = std::make_shared(path.c_str()); + if (!mm->is_open()) { return false; } + + res.set_content_provider( + mm->size(), + detail::find_content_type(path, file_extension_and_mimetype_map_, + default_file_mimetype_), + [mm](size_t offset, size_t length, DataSink &sink) -> bool { + sink.write(mm->data() + offset, length); + return true; + }); + if (!head && file_request_handler_) { file_request_handler_(req, res); } + return true; } } @@ -5295,10 +6411,11 @@ inline bool Server::handle_file_request(const Request &req, Response &res, } inline socket_t -Server::create_server_socket(const char *host, int port, int socket_flags, +Server::create_server_socket(const std::string &host, int port, + int socket_flags, SocketOptions socket_options) const { return detail::create_socket( - host, "", port, address_family_, socket_flags, tcp_nodelay_, + host, std::string(), port, address_family_, socket_flags, tcp_nodelay_, std::move(socket_options), [](socket_t sock, struct addrinfo &ai) -> bool { if (::bind(sock, ai.ai_addr, static_cast(ai.ai_addrlen))) { @@ -5309,7 +6426,8 @@ Server::create_server_socket(const char *host, int port, int socket_flags, }); } -inline int Server::bind_internal(const char *host, int port, int socket_flags) { +inline int Server::bind_internal(const std::string &host, int port, + int socket_flags) { if (!is_valid()) { return -1; } svr_sock_ = create_server_socket(host, port, socket_flags, socket_options_); @@ -5337,6 +6455,7 @@ inline int Server::bind_internal(const char *host, int port, int socket_flags) { inline bool Server::listen_internal() { auto ret = true; is_running_ = true; + auto se = detail::scope_exit([&]() { is_running_ = false; }); { std::unique_ptr task_queue(new_task_queue()); @@ -5362,6 +6481,8 @@ inline bool Server::listen_internal() { // Try to accept new connections after a short sleep. std::this_thread::sleep_for(std::chrono::milliseconds(1)); continue; + } else if (errno == EINTR || errno == EAGAIN) { + continue; } if (svr_sock_ != INVALID_SOCKET) { detail::close_socket(svr_sock_); @@ -5376,13 +6497,14 @@ inline bool Server::listen_internal() { #ifdef _WIN32 auto timeout = static_cast(read_timeout_sec_ * 1000 + read_timeout_usec_ / 1000); - setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, - sizeof(timeout)); + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, + reinterpret_cast(&timeout), sizeof(timeout)); #else timeval tv; tv.tv_sec = static_cast(read_timeout_sec_); tv.tv_usec = static_cast(read_timeout_usec_); - setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)); + setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, + reinterpret_cast(&tv), sizeof(tv)); #endif } { @@ -5390,27 +6512,27 @@ inline bool Server::listen_internal() { #ifdef _WIN32 auto timeout = static_cast(write_timeout_sec_ * 1000 + write_timeout_usec_ / 1000); - setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, - sizeof(timeout)); + setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, + reinterpret_cast(&timeout), sizeof(timeout)); #else timeval tv; tv.tv_sec = static_cast(write_timeout_sec_); tv.tv_usec = static_cast(write_timeout_usec_); - setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)); + setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, + reinterpret_cast(&tv), sizeof(tv)); #endif } -#if __cplusplus > 201703L - task_queue->enqueue([=, this]() { process_and_close_socket(sock); }); -#else - task_queue->enqueue([=]() { process_and_close_socket(sock); }); -#endif + if (!task_queue->enqueue( + [this, sock]() { process_and_close_socket(sock); })) { + detail::shutdown_socket(sock); + detail::close_socket(sock); + } } task_queue->shutdown(); } - is_running_ = false; return ret; } @@ -5421,7 +6543,7 @@ inline bool Server::routing(Request &req, Response &res, Stream &strm) { } // File handler - bool is_head_request = req.method == "HEAD"; + auto is_head_request = req.method == "HEAD"; if ((req.method == "GET" || is_head_request) && handle_file_request(req, res, is_head_request)) { return true; @@ -5487,17 +6609,17 @@ inline bool Server::routing(Request &req, Response &res, Stream &strm) { return dispatch_request(req, res, patch_handlers_); } - res.status = 400; + res.status = StatusCode::BadRequest_400; return false; } inline bool Server::dispatch_request(Request &req, Response &res, - const Handlers &handlers) { + const Handlers &handlers) const { for (const auto &x : handlers) { - const auto &pattern = x.first; + const auto &matcher = x.first; const auto &handler = x.second; - if (std::regex_match(req.path, req.matches, pattern)) { + if (matcher->match(req)) { handler(req, res); return true; } @@ -5507,18 +6629,18 @@ inline bool Server::dispatch_request(Request &req, Response &res, inline void Server::apply_ranges(const Request &req, Response &res, std::string &content_type, - std::string &boundary) { - if (req.ranges.size() > 1) { - boundary = detail::make_multipart_data_boundary(); - + std::string &boundary) const { + if (req.ranges.size() > 1 && res.status == StatusCode::PartialContent_206) { auto it = res.headers.find("Content-Type"); if (it != res.headers.end()) { content_type = it->second; res.headers.erase(it); } - res.headers.emplace("Content-Type", - "multipart/byteranges; boundary=" + boundary); + boundary = detail::make_multipart_data_boundary(); + + res.set_header("Content-Type", + "multipart/byteranges; boundary=" + boundary); } auto type = detail::encoding_type(req, res); @@ -5526,19 +6648,20 @@ inline void Server::apply_ranges(const Request &req, Response &res, if (res.body.empty()) { if (res.content_length_ > 0) { size_t length = 0; - if (req.ranges.empty()) { + if (req.ranges.empty() || res.status != StatusCode::PartialContent_206) { length = res.content_length_; } else if (req.ranges.size() == 1) { - auto offsets = - detail::get_range_offset_and_length(req, res.content_length_, 0); - auto offset = offsets.first; - length = offsets.second; + auto offset_and_length = detail::get_range_offset_and_length( + req.ranges[0], res.content_length_); + + length = offset_and_length.second; + auto content_range = detail::make_content_range_header_field( - offset, length, res.content_length_); + offset_and_length, res.content_length_); res.set_header("Content-Range", content_range); } else { - length = detail::get_multipart_ranges_data_length(req, res, boundary, - content_type); + length = detail::get_multipart_ranges_data_length( + req, boundary, content_type, res.content_length_); } res.set_header("Content-Length", std::to_string(length)); } else { @@ -5554,31 +6677,25 @@ inline void Server::apply_ranges(const Request &req, Response &res, } } } else { - if (req.ranges.empty()) { + if (req.ranges.empty() || res.status != StatusCode::PartialContent_206) { ; } else if (req.ranges.size() == 1) { - auto offsets = - detail::get_range_offset_and_length(req, res.body.size(), 0); - auto offset = offsets.first; - auto length = offsets.second; + auto offset_and_length = + detail::get_range_offset_and_length(req.ranges[0], res.body.size()); + auto offset = offset_and_length.first; + auto length = offset_and_length.second; + auto content_range = detail::make_content_range_header_field( - offset, length, res.body.size()); + offset_and_length, res.body.size()); res.set_header("Content-Range", content_range); - if (offset < res.body.size()) { - res.body = res.body.substr(offset, length); - } else { - res.body.clear(); - res.status = 416; - } + + assert(offset + length <= res.body.size()); + res.body = res.body.substr(offset, length); } else { std::string data; - if (detail::make_multipart_ranges_data(req, res, boundary, content_type, - data)) { - res.body.swap(data); - } else { - res.body.clear(); - res.status = 416; - } + detail::make_multipart_ranges_data(req, res, boundary, content_type, + res.body.size(), data); + res.body.swap(data); } if (type != detail::EncodingType::None) { @@ -5617,12 +6734,12 @@ inline void Server::apply_ranges(const Request &req, Response &res, inline bool Server::dispatch_request_for_content_reader( Request &req, Response &res, ContentReader content_reader, - const HandlersForContentReader &handlers) { + const HandlersForContentReader &handlers) const { for (const auto &x : handlers) { - const auto &pattern = x.first; + const auto &matcher = x.first; const auto &handler = x.second; - if (std::regex_match(req.path, req.matches, pattern)) { + if (matcher->match(req)) { handler(req, res, content_reader); return true; } @@ -5642,15 +6759,10 @@ Server::process_request(Stream &strm, bool close_connection, if (!line_reader.getline()) { return false; } Request req; + Response res; - res.version = "HTTP/1.1"; - - for (const auto &header : default_headers_) { - if (res.headers.find(header.first) == res.headers.end()) { - res.headers.insert(header); - } - } + res.headers = default_headers_; #ifdef _WIN32 // TODO: Increase FD_SETSIZE statically (libzmq), dynamically (MySQL). @@ -5660,7 +6772,7 @@ Server::process_request(Stream &strm, bool close_connection, if (strm.socket() >= FD_SETSIZE) { Headers dummy; detail::read_headers(strm, dummy); - res.status = 500; + res.status = StatusCode::InternalServerError_500; return write_response(strm, close_connection, req, res); } #endif @@ -5670,14 +6782,14 @@ Server::process_request(Stream &strm, bool close_connection, if (line_reader.size() > CPPHTTPLIB_REQUEST_URI_MAX_LENGTH) { Headers dummy; detail::read_headers(strm, dummy); - res.status = 414; + res.status = StatusCode::UriTooLong_414; return write_response(strm, close_connection, req, res); } // Request line and headers if (!parse_request_line(line_reader.ptr(), req) || !detail::read_headers(strm, req.headers)) { - res.status = 400; + res.status = StatusCode::BadRequest_400; return write_response(strm, close_connection, req, res); } @@ -5694,10 +6806,14 @@ Server::process_request(Stream &strm, bool close_connection, req.set_header("REMOTE_ADDR", req.remote_addr); req.set_header("REMOTE_PORT", std::to_string(req.remote_port)); + strm.get_local_ip_and_port(req.local_addr, req.local_port); + req.set_header("LOCAL_ADDR", req.local_addr); + req.set_header("LOCAL_PORT", std::to_string(req.local_port)); + if (req.has_header("Range")) { const auto &range_header_value = req.get_header_value("Range"); if (!detail::parse_range_header(range_header_value, req.ranges)) { - res.status = 416; + res.status = StatusCode::RangeNotSatisfiable_416; return write_response(strm, close_connection, req, res); } } @@ -5705,22 +6821,22 @@ Server::process_request(Stream &strm, bool close_connection, if (setup_request) { setup_request(req); } if (req.get_header_value("Expect") == "100-continue") { - auto status = 100; + int status = StatusCode::Continue_100; if (expect_100_continue_handler_) { status = expect_100_continue_handler_(req, res); } switch (status) { - case 100: - case 417: + case StatusCode::Continue_100: + case StatusCode::ExpectationFailed_417: strm.write_format("HTTP/1.1 %d %s\r\n\r\n", status, - detail::status_message(status)); + status_message(status)); break; default: return write_response(strm, close_connection, req, res); } } - // Rounting - bool routed = false; + // Routing + auto routed = false; #ifdef CPPHTTPLIB_NO_EXCEPTIONS routed = routing(req, res, strm); #else @@ -5728,23 +6844,51 @@ Server::process_request(Stream &strm, bool close_connection, routed = routing(req, res, strm); } catch (std::exception &e) { if (exception_handler_) { - exception_handler_(req, res, e); + auto ep = std::current_exception(); + exception_handler_(req, res, ep); routed = true; } else { - res.status = 500; - res.set_header("EXCEPTION_WHAT", e.what()); + res.status = StatusCode::InternalServerError_500; + std::string val; + auto s = e.what(); + for (size_t i = 0; s[i]; i++) { + switch (s[i]) { + case '\r': val += "\\r"; break; + case '\n': val += "\\n"; break; + default: val += s[i]; break; + } + } + res.set_header("EXCEPTION_WHAT", val); } } catch (...) { - res.status = 500; - res.set_header("EXCEPTION_WHAT", "UNKNOWN"); + if (exception_handler_) { + auto ep = std::current_exception(); + exception_handler_(req, res, ep); + routed = true; + } else { + res.status = StatusCode::InternalServerError_500; + res.set_header("EXCEPTION_WHAT", "UNKNOWN"); + } } #endif - if (routed) { - if (res.status == -1) { res.status = req.ranges.empty() ? 200 : 206; } + if (res.status == -1) { + res.status = req.ranges.empty() ? StatusCode::OK_200 + : StatusCode::PartialContent_206; + } + + if (detail::range_error(req, res)) { + res.body.clear(); + res.content_length_ = 0; + res.content_provider_ = nullptr; + res.status = StatusCode::RangeNotSatisfiable_416; + return write_response(strm, close_connection, req, res); + } + return write_response_with_content(strm, close_connection, req, res); } else { - if (res.status == -1) { res.status = 404; } + if (res.status == -1) { res.status = StatusCode::NotFound_404; } + return write_response(strm, close_connection, req, res); } } @@ -5835,7 +6979,7 @@ inline void ClientImpl::copy_settings(const ClientImpl &rhs) { inline socket_t ClientImpl::create_client_socket(Error &error) const { if (!proxy_host_.empty() && proxy_port_ != -1) { return detail::create_client_socket( - proxy_host_.c_str(), "", proxy_port_, address_family_, tcp_nodelay_, + proxy_host_, std::string(), proxy_port_, address_family_, tcp_nodelay_, socket_options_, connection_timeout_sec_, connection_timeout_usec_, read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, write_timeout_usec_, interface_, error); @@ -5844,13 +6988,13 @@ inline socket_t ClientImpl::create_client_socket(Error &error) const { // Check is custom IP specified for host_ std::string ip; auto it = addr_map_.find(host_); - if (it != addr_map_.end()) ip = it->second; + if (it != addr_map_.end()) { ip = it->second; } return detail::create_client_socket( - host_.c_str(), ip.c_str(), port_, address_family_, tcp_nodelay_, - socket_options_, connection_timeout_sec_, connection_timeout_usec_, - read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, - write_timeout_usec_, interface_, error); + host_, ip, port_, address_family_, tcp_nodelay_, socket_options_, + connection_timeout_sec_, connection_timeout_usec_, read_timeout_sec_, + read_timeout_usec_, write_timeout_sec_, write_timeout_usec_, interface_, + error); } inline bool ClientImpl::create_and_connect_socket(Socket &socket, @@ -5869,7 +7013,7 @@ inline void ClientImpl::shutdown_ssl(Socket & /*socket*/, socket_requests_are_from_thread_ == std::this_thread::get_id()); } -inline void ClientImpl::shutdown_socket(Socket &socket) { +inline void ClientImpl::shutdown_socket(Socket &socket) const { if (socket.sock == INVALID_SOCKET) { return; } detail::shutdown_socket(socket.sock); } @@ -5894,7 +7038,7 @@ inline void ClientImpl::close_socket(Socket &socket) { } inline bool ClientImpl::read_response_line(Stream &strm, const Request &req, - Response &res) { + Response &res) const { std::array buf{}; detail::stream_line_reader line_reader(strm, buf.data(), buf.size()); @@ -5902,9 +7046,9 @@ inline bool ClientImpl::read_response_line(Stream &strm, const Request &req, if (!line_reader.getline()) { return false; } #ifdef CPPHTTPLIB_ALLOW_LF_AS_LINE_TERMINATOR - const static std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r\n"); -#else const static std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r?\n"); +#else + const static std::regex re("(HTTP/1\\.[01]) (\\d{3})(?: (.*?))?\r\n"); #endif std::cmatch m; @@ -5916,7 +7060,7 @@ inline bool ClientImpl::read_response_line(Stream &strm, const Request &req, res.reason = std::string(m[3]); // Ignore '100 Continue' - while (res.status == 100) { + while (res.status == StatusCode::Continue_100) { if (!line_reader.getline()) { return false; } // CRLF if (!line_reader.getline()) { return false; } // next response line @@ -5931,7 +7075,15 @@ inline bool ClientImpl::read_response_line(Stream &strm, const Request &req, inline bool ClientImpl::send(Request &req, Response &res, Error &error) { std::lock_guard request_mutex_guard(request_mutex_); + auto ret = send_(req, res, error); + if (error == Error::SSLPeerCouldBeClosed_) { + assert(!ret); + ret = send_(req, res, error); + } + return ret; +} +inline bool ClientImpl::send_(Request &req, Response &res, Error &error) { { std::lock_guard guard(socket_mutex_); @@ -5962,7 +7114,7 @@ inline bool ClientImpl::send(Request &req, Response &res, Error &error) { if (is_ssl()) { auto &scli = static_cast(*this); if (!proxy_host_.empty() && proxy_port_ != -1) { - bool success = false; + auto success = false; if (!scli.connect_with_proxy(socket_, res, success, error)) { return success; } @@ -5989,13 +7141,11 @@ inline bool ClientImpl::send(Request &req, Response &res, Error &error) { } } + auto ret = false; auto close_connection = !keep_alive_; - auto ret = process_socket(socket_, [&](Stream &strm) { - return handle_request(strm, req, res, close_connection, error); - }); - // Briefly lock mutex in order to mark that a request is no longer ongoing - { + auto se = detail::scope_exit([&]() { + // Briefly lock mutex in order to mark that a request is no longer ongoing std::lock_guard guard(socket_mutex_); socket_requests_in_flight_ -= 1; if (socket_requests_in_flight_ <= 0) { @@ -6009,7 +7159,11 @@ inline bool ClientImpl::send(Request &req, Response &res, Error &error) { shutdown_socket(socket_); close_socket(socket_); } - } + }); + + ret = process_socket(socket_, [&](Stream &strm) { + return handle_request(strm, req, res, close_connection, error); + }); if (!ret) { if (error == Error::Success) { error = Error::Unknown; } @@ -6054,15 +7208,31 @@ inline bool ClientImpl::handle_request(Stream &strm, Request &req, if (!ret) { return false; } + if (res.get_header_value("Connection") == "close" || + (res.version == "HTTP/1.0" && res.reason != "Connection established")) { + // TODO this requires a not-entirely-obvious chain of calls to be correct + // for this to be safe. + + // This is safe to call because handle_request is only called by send_ + // which locks the request mutex during the process. It would be a bug + // to call it from a different thread since it's a thread-safety issue + // to do these things to the socket if another thread is using the socket. + std::lock_guard guard(socket_mutex_); + shutdown_ssl(socket_, true); + shutdown_socket(socket_); + close_socket(socket_); + } + if (300 < res.status && res.status < 400 && follow_location_) { req = req_save; ret = redirect(req, res, error); } #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - if ((res.status == 401 || res.status == 407) && + if ((res.status == StatusCode::Unauthorized_401 || + res.status == StatusCode::ProxyAuthenticationRequired_407) && req.authorization_count_ < 5) { - auto is_proxy = res.status == 407; + auto is_proxy = res.status == StatusCode::ProxyAuthenticationRequired_407; const auto &username = is_proxy ? proxy_digest_auth_username_ : digest_auth_username_; const auto &password = @@ -6097,11 +7267,11 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) { return false; } - auto location = detail::decode_url(res.get_header_value("location"), true); + auto location = res.get_header_value("location"); if (location.empty()) { return false; } const static std::regex re( - R"((?:(https?):)?(?://(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)?([^?#]*(?:\?[^#]*)?)(?:#.*)?)"); + R"((?:(https?):)?(?://(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)?([^?#]*)(\?[^#]*)?(?:#.*)?)"); std::smatch m; if (!std::regex_match(location, m, re)) { return false; } @@ -6113,6 +7283,7 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) { if (next_host.empty()) { next_host = m[3].str(); } auto port_str = m[4].str(); auto next_path = m[5].str(); + auto next_query = m[6].str(); auto next_port = port_; if (!port_str.empty()) { @@ -6125,33 +7296,35 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) { if (next_host.empty()) { next_host = host_; } if (next_path.empty()) { next_path = "/"; } + auto path = detail::decode_url(next_path, true) + next_query; + if (next_scheme == scheme && next_host == host_ && next_port == port_) { - return detail::redirect(*this, req, res, next_path, location, error); + return detail::redirect(*this, req, res, path, location, error); } else { if (next_scheme == "https") { #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - SSLClient cli(next_host.c_str(), next_port); + SSLClient cli(next_host, next_port); cli.copy_settings(*this); if (ca_cert_store_) { cli.set_ca_cert_store(ca_cert_store_); } - return detail::redirect(cli, req, res, next_path, location, error); + return detail::redirect(cli, req, res, path, location, error); #else return false; #endif } else { - ClientImpl cli(next_host.c_str(), next_port); + ClientImpl cli(next_host, next_port); cli.copy_settings(*this); - return detail::redirect(cli, req, res, next_path, location, error); + return detail::redirect(cli, req, res, path, location, error); } } } inline bool ClientImpl::write_content_with_provider(Stream &strm, const Request &req, - Error &error) { + Error &error) const { auto is_shutting_down = []() { return false; }; if (req.is_chunked_content_provider_) { - // TODO: Brotli suport + // TODO: Brotli support std::unique_ptr compressor; #ifdef CPPHTTPLIB_ZLIB_SUPPORT if (compress_) { @@ -6168,39 +7341,39 @@ inline bool ClientImpl::write_content_with_provider(Stream &strm, return detail::write_content(strm, req.content_provider_, 0, req.content_length_, is_shutting_down, error); } -} // namespace httplib +} inline bool ClientImpl::write_request(Stream &strm, Request &req, bool close_connection, Error &error) { // Prepare additional headers if (close_connection) { if (!req.has_header("Connection")) { - req.headers.emplace("Connection", "close"); + req.set_header("Connection", "close"); } } if (!req.has_header("Host")) { if (is_ssl()) { if (port_ == 443) { - req.headers.emplace("Host", host_); + req.set_header("Host", host_); } else { - req.headers.emplace("Host", host_and_port_); + req.set_header("Host", host_and_port_); } } else { if (port_ == 80) { - req.headers.emplace("Host", host_); + req.set_header("Host", host_); } else { - req.headers.emplace("Host", host_and_port_); + req.set_header("Host", host_and_port_); } } } - if (!req.has_header("Accept")) { req.headers.emplace("Accept", "*/*"); } + if (!req.has_header("Accept")) { req.set_header("Accept", "*/*"); } #ifndef CPPHTTPLIB_NO_DEFAULT_USER_AGENT if (!req.has_header("User-Agent")) { auto agent = std::string("cpp-httplib/") + CPPHTTPLIB_VERSION; - req.headers.emplace("User-Agent", agent); + req.set_header("User-Agent", agent); } #endif @@ -6209,23 +7382,23 @@ inline bool ClientImpl::write_request(Stream &strm, Request &req, if (!req.is_chunked_content_provider_) { if (!req.has_header("Content-Length")) { auto length = std::to_string(req.content_length_); - req.headers.emplace("Content-Length", length); + req.set_header("Content-Length", length); } } } else { if (req.method == "POST" || req.method == "PUT" || req.method == "PATCH") { - req.headers.emplace("Content-Length", "0"); + req.set_header("Content-Length", "0"); } } } else { if (!req.has_header("Content-Type")) { - req.headers.emplace("Content-Type", "text/plain"); + req.set_header("Content-Type", "text/plain"); } if (!req.has_header("Content-Length")) { auto length = std::to_string(req.body.size()); - req.headers.emplace("Content-Length", length); + req.set_header("Content-Length", length); } } @@ -6265,7 +7438,7 @@ inline bool ClientImpl::write_request(Stream &strm, Request &req, const auto &path = url_encode_ ? detail::encode_url(req.path) : req.path; bstrm.write_format("%s %s HTTP/1.1\r\n", req.method.c_str(), path.c_str()); - detail::write_headers(bstrm, req.headers); + header_writer_(bstrm, req.headers); // Flush buffer auto &data = bstrm.get_buffer(); @@ -6289,16 +7462,14 @@ inline bool ClientImpl::write_request(Stream &strm, Request &req, } inline std::unique_ptr ClientImpl::send_with_content_provider( - Request &req, - // const char *method, const char *path, const Headers &headers, - const char *body, size_t content_length, ContentProvider content_provider, + Request &req, const char *body, size_t content_length, + ContentProvider content_provider, ContentProviderWithoutLength content_provider_without_length, - const char *content_type, Error &error) { - - if (content_type) { req.headers.emplace("Content-Type", content_type); } + const std::string &content_type, Error &error) { + if (!content_type.empty()) { req.set_header("Content-Type", content_type); } #ifdef CPPHTTPLIB_ZLIB_SUPPORT - if (compress_) { req.headers.emplace("Content-Encoding", "gzip"); } + if (compress_) { req.set_header("Content-Encoding", "gzip"); } #endif #ifdef CPPHTTPLIB_ZLIB_SUPPORT @@ -6316,8 +7487,9 @@ inline std::unique_ptr ClientImpl::send_with_content_provider( auto last = offset + data_len == content_length; auto ret = compressor.compress( - data, data_len, last, [&](const char *data, size_t data_len) { - req.body.append(data, data_len); + data, data_len, last, + [&](const char *compressed_data, size_t compressed_data_len) { + req.body.append(compressed_data, compressed_data_len); return true; }); @@ -6330,8 +7502,6 @@ inline std::unique_ptr ClientImpl::send_with_content_provider( return ok; }; - data_sink.is_writable = [&](void) { return ok && true; }; - while (ok && offset < content_length) { if (!content_provider(offset, content_length - offset, data_sink)) { error = Error::Canceled; @@ -6360,10 +7530,9 @@ inline std::unique_ptr ClientImpl::send_with_content_provider( req.content_provider_ = detail::ContentProviderAdapter( std::move(content_provider_without_length)); req.is_chunked_content_provider_ = true; - req.headers.emplace("Transfer-Encoding", "chunked"); + req.set_header("Transfer-Encoding", "chunked"); } else { req.body.assign(body, content_length); - ; } } @@ -6372,21 +7541,20 @@ inline std::unique_ptr ClientImpl::send_with_content_provider( } inline Result ClientImpl::send_with_content_provider( - const char *method, const char *path, const Headers &headers, + const std::string &method, const std::string &path, const Headers &headers, const char *body, size_t content_length, ContentProvider content_provider, ContentProviderWithoutLength content_provider_without_length, - const char *content_type) { + const std::string &content_type, Progress progress) { Request req; req.method = method; req.headers = headers; req.path = path; + req.progress = progress; auto error = Error::Success; auto res = send_with_content_provider( - req, - // method, path, headers, - body, content_length, std::move(content_provider), + req, body, content_length, std::move(content_provider), std::move(content_provider_without_length), content_type, error); return Result{std::move(res), error, std::move(req.headers)}; @@ -6404,6 +7572,20 @@ inline bool ClientImpl::process_request(Stream &strm, Request &req, // Send request if (!write_request(strm, req, close_connection, error)) { return false; } +#ifdef CPPHTTPLIB_OPENSSL_SUPPORT + if (is_ssl()) { + auto is_proxy_enabled = !proxy_host_.empty() && proxy_port_ != -1; + if (!is_proxy_enabled) { + char buf[1]; + if (SSL_peek(socket_.ssl, buf, 1) == 0 && + SSL_get_error(socket_.ssl, 0) == SSL_ERROR_ZERO_RETURN) { + error = Error::SSLPeerCouldBeClosed_; + return false; + } + } + } +#endif + // Receive response and headers if (!read_response_line(strm, req, res) || !detail::read_headers(strm, res.headers)) { @@ -6412,7 +7594,8 @@ inline bool ClientImpl::process_request(Stream &strm, Request &req, } // Body - if ((res.status != 204) && req.method != "HEAD" && req.method != "CONNECT") { + if ((res.status != StatusCode::NoContent_204) && req.method != "HEAD" && + req.method != "CONNECT") { auto redirect = 300 < res.status && res.status < 400 && follow_location_; if (req.response_handler && !redirect) { @@ -6457,30 +7640,56 @@ inline bool ClientImpl::process_request(Stream &strm, Request &req, } } - if (res.get_header_value("Connection") == "close" || - (res.version == "HTTP/1.0" && res.reason != "Connection established")) { - // TODO this requires a not-entirely-obvious chain of calls to be correct - // for this to be safe. Maybe a code refactor (such as moving this out to - // the send function and getting rid of the recursiveness of the mutex) - // could make this more obvious. - - // This is safe to call because process_request is only called by - // handle_request which is only called by send, which locks the request - // mutex during the process. It would be a bug to call it from a different - // thread since it's a thread-safety issue to do these things to the socket - // if another thread is using the socket. - std::lock_guard guard(socket_mutex_); - shutdown_ssl(socket_, true); - shutdown_socket(socket_); - close_socket(socket_); - } - // Log if (logger_) { logger_(req, res); } return true; } +inline ContentProviderWithoutLength ClientImpl::get_multipart_content_provider( + const std::string &boundary, const MultipartFormDataItems &items, + const MultipartFormDataProviderItems &provider_items) const { + size_t cur_item = 0; + size_t cur_start = 0; + // cur_item and cur_start are copied to within the std::function and maintain + // state between successive calls + return [&, cur_item, cur_start](size_t offset, + DataSink &sink) mutable -> bool { + if (!offset && !items.empty()) { + sink.os << detail::serialize_multipart_formdata(items, boundary, false); + return true; + } else if (cur_item < provider_items.size()) { + if (!cur_start) { + const auto &begin = detail::serialize_multipart_formdata_item_begin( + provider_items[cur_item], boundary); + offset += begin.size(); + cur_start = offset; + sink.os << begin; + } + + DataSink cur_sink; + auto has_data = true; + cur_sink.write = sink.write; + cur_sink.done = [&]() { has_data = false; }; + + if (!provider_items[cur_item].provider(offset - cur_start, cur_sink)) { + return false; + } + + if (!has_data) { + sink.os << detail::serialize_multipart_formdata_item_end(); + cur_item++; + cur_start = 0; + } + return true; + } else { + sink.os << detail::serialize_multipart_formdata_finish(boundary); + sink.done(); + return true; + } + }; +} + inline bool ClientImpl::process_socket(const Socket &socket, std::function callback) { @@ -6491,19 +7700,19 @@ ClientImpl::process_socket(const Socket &socket, inline bool ClientImpl::is_ssl() const { return false; } -inline Result ClientImpl::Get(const char *path) { +inline Result ClientImpl::Get(const std::string &path) { return Get(path, Headers(), Progress()); } -inline Result ClientImpl::Get(const char *path, Progress progress) { +inline Result ClientImpl::Get(const std::string &path, Progress progress) { return Get(path, Headers(), std::move(progress)); } -inline Result ClientImpl::Get(const char *path, const Headers &headers) { +inline Result ClientImpl::Get(const std::string &path, const Headers &headers) { return Get(path, headers, Progress()); } -inline Result ClientImpl::Get(const char *path, const Headers &headers, +inline Result ClientImpl::Get(const std::string &path, const Headers &headers, Progress progress) { Request req; req.method = "GET"; @@ -6514,45 +7723,45 @@ inline Result ClientImpl::Get(const char *path, const Headers &headers, return send_(std::move(req)); } -inline Result ClientImpl::Get(const char *path, +inline Result ClientImpl::Get(const std::string &path, ContentReceiver content_receiver) { return Get(path, Headers(), nullptr, std::move(content_receiver), nullptr); } -inline Result ClientImpl::Get(const char *path, +inline Result ClientImpl::Get(const std::string &path, ContentReceiver content_receiver, Progress progress) { return Get(path, Headers(), nullptr, std::move(content_receiver), std::move(progress)); } -inline Result ClientImpl::Get(const char *path, const Headers &headers, +inline Result ClientImpl::Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver) { return Get(path, headers, nullptr, std::move(content_receiver), nullptr); } -inline Result ClientImpl::Get(const char *path, const Headers &headers, +inline Result ClientImpl::Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver, Progress progress) { return Get(path, headers, nullptr, std::move(content_receiver), std::move(progress)); } -inline Result ClientImpl::Get(const char *path, +inline Result ClientImpl::Get(const std::string &path, ResponseHandler response_handler, ContentReceiver content_receiver) { return Get(path, Headers(), std::move(response_handler), std::move(content_receiver), nullptr); } -inline Result ClientImpl::Get(const char *path, const Headers &headers, +inline Result ClientImpl::Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver) { return Get(path, headers, std::move(response_handler), std::move(content_receiver), nullptr); } -inline Result ClientImpl::Get(const char *path, +inline Result ClientImpl::Get(const std::string &path, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress) { @@ -6560,7 +7769,7 @@ inline Result ClientImpl::Get(const char *path, std::move(content_receiver), std::move(progress)); } -inline Result ClientImpl::Get(const char *path, const Headers &headers, +inline Result ClientImpl::Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress) { @@ -6579,40 +7788,43 @@ inline Result ClientImpl::Get(const char *path, const Headers &headers, return send_(std::move(req)); } -inline Result ClientImpl::Get(const char *path, const Params ¶ms, +inline Result ClientImpl::Get(const std::string &path, const Params ¶ms, const Headers &headers, Progress progress) { if (params.empty()) { return Get(path, headers); } std::string path_with_query = append_query_params(path, params); - return Get(path_with_query.c_str(), headers, progress); + return Get(path_with_query, headers, std::move(progress)); } -inline Result ClientImpl::Get(const char *path, const Params ¶ms, +inline Result ClientImpl::Get(const std::string &path, const Params ¶ms, const Headers &headers, ContentReceiver content_receiver, Progress progress) { - return Get(path, params, headers, nullptr, content_receiver, progress); + return Get(path, params, headers, nullptr, std::move(content_receiver), + std::move(progress)); } -inline Result ClientImpl::Get(const char *path, const Params ¶ms, +inline Result ClientImpl::Get(const std::string &path, const Params ¶ms, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress) { if (params.empty()) { - return Get(path, headers, response_handler, content_receiver, progress); + return Get(path, headers, std::move(response_handler), + std::move(content_receiver), std::move(progress)); } std::string path_with_query = append_query_params(path, params); - return Get(path_with_query.c_str(), headers, response_handler, - content_receiver, progress); + return Get(path_with_query, headers, std::move(response_handler), + std::move(content_receiver), std::move(progress)); } -inline Result ClientImpl::Head(const char *path) { +inline Result ClientImpl::Head(const std::string &path) { return Head(path, Headers()); } -inline Result ClientImpl::Head(const char *path, const Headers &headers) { +inline Result ClientImpl::Head(const std::string &path, + const Headers &headers) { Request req; req.method = "HEAD"; req.headers = headers; @@ -6621,288 +7833,461 @@ inline Result ClientImpl::Head(const char *path, const Headers &headers) { return send_(std::move(req)); } -inline Result ClientImpl::Post(const char *path) { - return Post(path, std::string(), nullptr); +inline Result ClientImpl::Post(const std::string &path) { + return Post(path, std::string(), std::string()); } -inline Result ClientImpl::Post(const char *path, const char *body, +inline Result ClientImpl::Post(const std::string &path, + const Headers &headers) { + return Post(path, headers, nullptr, 0, std::string()); +} + +inline Result ClientImpl::Post(const std::string &path, const char *body, size_t content_length, - const char *content_type) { - return Post(path, Headers(), body, content_length, content_type); + const std::string &content_type) { + return Post(path, Headers(), body, content_length, content_type, nullptr); } -inline Result ClientImpl::Post(const char *path, const Headers &headers, +inline Result ClientImpl::Post(const std::string &path, const Headers &headers, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("POST", path, headers, body, content_length, - nullptr, nullptr, content_type); + nullptr, nullptr, content_type, nullptr); } -inline Result ClientImpl::Post(const char *path, const std::string &body, - const char *content_type) { +inline Result ClientImpl::Post(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type, + Progress progress) { + return send_with_content_provider("POST", path, headers, body, content_length, + nullptr, nullptr, content_type, progress); +} + +inline Result ClientImpl::Post(const std::string &path, const std::string &body, + const std::string &content_type) { return Post(path, Headers(), body, content_type); } -inline Result ClientImpl::Post(const char *path, const Headers &headers, - const std::string &body, - const char *content_type) { - return send_with_content_provider("POST", path, headers, body.data(), - body.size(), nullptr, nullptr, - content_type); +inline Result ClientImpl::Post(const std::string &path, const std::string &body, + const std::string &content_type, + Progress progress) { + return Post(path, Headers(), body, content_type, progress); } -inline Result ClientImpl::Post(const char *path, const Params ¶ms) { +inline Result ClientImpl::Post(const std::string &path, const Headers &headers, + const std::string &body, + const std::string &content_type) { + return send_with_content_provider("POST", path, headers, body.data(), + body.size(), nullptr, nullptr, content_type, + nullptr); +} + +inline Result ClientImpl::Post(const std::string &path, const Headers &headers, + const std::string &body, + const std::string &content_type, + Progress progress) { + return send_with_content_provider("POST", path, headers, body.data(), + body.size(), nullptr, nullptr, content_type, + progress); +} + +inline Result ClientImpl::Post(const std::string &path, const Params ¶ms) { return Post(path, Headers(), params); } -inline Result ClientImpl::Post(const char *path, size_t content_length, +inline Result ClientImpl::Post(const std::string &path, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return Post(path, Headers(), content_length, std::move(content_provider), content_type); } -inline Result ClientImpl::Post(const char *path, +inline Result ClientImpl::Post(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return Post(path, Headers(), std::move(content_provider), content_type); } -inline Result ClientImpl::Post(const char *path, const Headers &headers, +inline Result ClientImpl::Post(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("POST", path, headers, nullptr, content_length, std::move(content_provider), - nullptr, content_type); + nullptr, content_type, nullptr); } -inline Result ClientImpl::Post(const char *path, const Headers &headers, +inline Result ClientImpl::Post(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("POST", path, headers, nullptr, 0, nullptr, - std::move(content_provider), content_type); + std::move(content_provider), content_type, + nullptr); } -inline Result ClientImpl::Post(const char *path, const Headers &headers, +inline Result ClientImpl::Post(const std::string &path, const Headers &headers, const Params ¶ms) { auto query = detail::params_to_query_str(params); return Post(path, headers, query, "application/x-www-form-urlencoded"); } -inline Result ClientImpl::Post(const char *path, +inline Result ClientImpl::Post(const std::string &path, const Headers &headers, + const Params ¶ms, Progress progress) { + auto query = detail::params_to_query_str(params); + return Post(path, headers, query, "application/x-www-form-urlencoded", + progress); +} + +inline Result ClientImpl::Post(const std::string &path, const MultipartFormDataItems &items) { return Post(path, Headers(), items); } -inline Result ClientImpl::Post(const char *path, const Headers &headers, +inline Result ClientImpl::Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items) { - return Post(path, headers, items, detail::make_multipart_data_boundary()); + const auto &boundary = detail::make_multipart_data_boundary(); + const auto &content_type = + detail::serialize_multipart_formdata_get_content_type(boundary); + const auto &body = detail::serialize_multipart_formdata(items, boundary); + return Post(path, headers, body, content_type); } -inline Result ClientImpl::Post(const char *path, const Headers &headers, + +inline Result ClientImpl::Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items, const std::string &boundary) { - for (size_t i = 0; i < boundary.size(); i++) { - char c = boundary[i]; - if (!std::isalnum(c) && c != '-' && c != '_') { - return Result{nullptr, Error::UnsupportedMultipartBoundaryChars}; - } + if (!detail::is_multipart_boundary_chars_valid(boundary)) { + return Result{nullptr, Error::UnsupportedMultipartBoundaryChars}; } - std::string body; - - for (const auto &item : items) { - body += "--" + boundary + "\r\n"; - body += "Content-Disposition: form-data; name=\"" + item.name + "\""; - if (!item.filename.empty()) { - body += "; filename=\"" + item.filename + "\""; - } - body += "\r\n"; - if (!item.content_type.empty()) { - body += "Content-Type: " + item.content_type + "\r\n"; - } - body += "\r\n"; - body += item.content + "\r\n"; - } - - body += "--" + boundary + "--\r\n"; - - std::string content_type = "multipart/form-data; boundary=" + boundary; - return Post(path, headers, body, content_type.c_str()); + const auto &content_type = + detail::serialize_multipart_formdata_get_content_type(boundary); + const auto &body = detail::serialize_multipart_formdata(items, boundary); + return Post(path, headers, body, content_type); } -inline Result ClientImpl::Put(const char *path) { - return Put(path, std::string(), nullptr); +inline Result +ClientImpl::Post(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, + const MultipartFormDataProviderItems &provider_items) { + const auto &boundary = detail::make_multipart_data_boundary(); + const auto &content_type = + detail::serialize_multipart_formdata_get_content_type(boundary); + return send_with_content_provider( + "POST", path, headers, nullptr, 0, nullptr, + get_multipart_content_provider(boundary, items, provider_items), + content_type, nullptr); } -inline Result ClientImpl::Put(const char *path, const char *body, - size_t content_length, const char *content_type) { +inline Result ClientImpl::Put(const std::string &path) { + return Put(path, std::string(), std::string()); +} + +inline Result ClientImpl::Put(const std::string &path, const char *body, + size_t content_length, + const std::string &content_type) { return Put(path, Headers(), body, content_length, content_type); } -inline Result ClientImpl::Put(const char *path, const Headers &headers, +inline Result ClientImpl::Put(const std::string &path, const Headers &headers, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("PUT", path, headers, body, content_length, - nullptr, nullptr, content_type); + nullptr, nullptr, content_type, nullptr); } -inline Result ClientImpl::Put(const char *path, const std::string &body, - const char *content_type) { +inline Result ClientImpl::Put(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type, + Progress progress) { + return send_with_content_provider("PUT", path, headers, body, content_length, + nullptr, nullptr, content_type, progress); +} + +inline Result ClientImpl::Put(const std::string &path, const std::string &body, + const std::string &content_type) { return Put(path, Headers(), body, content_type); } -inline Result ClientImpl::Put(const char *path, const Headers &headers, - const std::string &body, - const char *content_type) { - return send_with_content_provider("PUT", path, headers, body.data(), - body.size(), nullptr, nullptr, - content_type); +inline Result ClientImpl::Put(const std::string &path, const std::string &body, + const std::string &content_type, + Progress progress) { + return Put(path, Headers(), body, content_type, progress); } -inline Result ClientImpl::Put(const char *path, size_t content_length, +inline Result ClientImpl::Put(const std::string &path, const Headers &headers, + const std::string &body, + const std::string &content_type) { + return send_with_content_provider("PUT", path, headers, body.data(), + body.size(), nullptr, nullptr, content_type, + nullptr); +} + +inline Result ClientImpl::Put(const std::string &path, const Headers &headers, + const std::string &body, + const std::string &content_type, + Progress progress) { + return send_with_content_provider("PUT", path, headers, body.data(), + body.size(), nullptr, nullptr, content_type, + progress); +} + +inline Result ClientImpl::Put(const std::string &path, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return Put(path, Headers(), content_length, std::move(content_provider), content_type); } -inline Result ClientImpl::Put(const char *path, +inline Result ClientImpl::Put(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return Put(path, Headers(), std::move(content_provider), content_type); } -inline Result ClientImpl::Put(const char *path, const Headers &headers, +inline Result ClientImpl::Put(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("PUT", path, headers, nullptr, content_length, std::move(content_provider), - nullptr, content_type); + nullptr, content_type, nullptr); } -inline Result ClientImpl::Put(const char *path, const Headers &headers, +inline Result ClientImpl::Put(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("PUT", path, headers, nullptr, 0, nullptr, - std::move(content_provider), content_type); + std::move(content_provider), content_type, + nullptr); } -inline Result ClientImpl::Put(const char *path, const Params ¶ms) { +inline Result ClientImpl::Put(const std::string &path, const Params ¶ms) { return Put(path, Headers(), params); } -inline Result ClientImpl::Put(const char *path, const Headers &headers, +inline Result ClientImpl::Put(const std::string &path, const Headers &headers, const Params ¶ms) { auto query = detail::params_to_query_str(params); return Put(path, headers, query, "application/x-www-form-urlencoded"); } -inline Result ClientImpl::Patch(const char *path) { - return Patch(path, std::string(), nullptr); +inline Result ClientImpl::Put(const std::string &path, const Headers &headers, + const Params ¶ms, Progress progress) { + auto query = detail::params_to_query_str(params); + return Put(path, headers, query, "application/x-www-form-urlencoded", + progress); } -inline Result ClientImpl::Patch(const char *path, const char *body, +inline Result ClientImpl::Put(const std::string &path, + const MultipartFormDataItems &items) { + return Put(path, Headers(), items); +} + +inline Result ClientImpl::Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items) { + const auto &boundary = detail::make_multipart_data_boundary(); + const auto &content_type = + detail::serialize_multipart_formdata_get_content_type(boundary); + const auto &body = detail::serialize_multipart_formdata(items, boundary); + return Put(path, headers, body, content_type); +} + +inline Result ClientImpl::Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, + const std::string &boundary) { + if (!detail::is_multipart_boundary_chars_valid(boundary)) { + return Result{nullptr, Error::UnsupportedMultipartBoundaryChars}; + } + + const auto &content_type = + detail::serialize_multipart_formdata_get_content_type(boundary); + const auto &body = detail::serialize_multipart_formdata(items, boundary); + return Put(path, headers, body, content_type); +} + +inline Result +ClientImpl::Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, + const MultipartFormDataProviderItems &provider_items) { + const auto &boundary = detail::make_multipart_data_boundary(); + const auto &content_type = + detail::serialize_multipart_formdata_get_content_type(boundary); + return send_with_content_provider( + "PUT", path, headers, nullptr, 0, nullptr, + get_multipart_content_provider(boundary, items, provider_items), + content_type, nullptr); +} +inline Result ClientImpl::Patch(const std::string &path) { + return Patch(path, std::string(), std::string()); +} + +inline Result ClientImpl::Patch(const std::string &path, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return Patch(path, Headers(), body, content_length, content_type); } -inline Result ClientImpl::Patch(const char *path, const Headers &headers, - const char *body, size_t content_length, - const char *content_type) { - return send_with_content_provider("PATCH", path, headers, body, - content_length, nullptr, nullptr, - content_type); +inline Result ClientImpl::Patch(const std::string &path, const char *body, + size_t content_length, + const std::string &content_type, + Progress progress) { + return Patch(path, Headers(), body, content_length, content_type, progress); } -inline Result ClientImpl::Patch(const char *path, const std::string &body, - const char *content_type) { +inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type) { + return Patch(path, headers, body, content_length, content_type, nullptr); +} + +inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type, + Progress progress) { + return send_with_content_provider("PATCH", path, headers, body, + content_length, nullptr, nullptr, + content_type, progress); +} + +inline Result ClientImpl::Patch(const std::string &path, + const std::string &body, + const std::string &content_type) { return Patch(path, Headers(), body, content_type); } -inline Result ClientImpl::Patch(const char *path, const Headers &headers, +inline Result ClientImpl::Patch(const std::string &path, const std::string &body, - const char *content_type) { - return send_with_content_provider("PATCH", path, headers, body.data(), - body.size(), nullptr, nullptr, - content_type); + const std::string &content_type, Progress progress) { + return Patch(path, Headers(), body, content_type, progress); } -inline Result ClientImpl::Patch(const char *path, size_t content_length, +inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, + const std::string &body, + const std::string &content_type) { + return Patch(path, headers, body, content_type, nullptr); +} + +inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, + const std::string &body, + const std::string &content_type, + Progress progress) { + return send_with_content_provider("PATCH", path, headers, body.data(), + body.size(), nullptr, nullptr, content_type, + progress); +} + +inline Result ClientImpl::Patch(const std::string &path, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return Patch(path, Headers(), content_length, std::move(content_provider), content_type); } -inline Result ClientImpl::Patch(const char *path, +inline Result ClientImpl::Patch(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return Patch(path, Headers(), std::move(content_provider), content_type); } -inline Result ClientImpl::Patch(const char *path, const Headers &headers, +inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("PATCH", path, headers, nullptr, content_length, std::move(content_provider), - nullptr, content_type); + nullptr, content_type, nullptr); } -inline Result ClientImpl::Patch(const char *path, const Headers &headers, +inline Result ClientImpl::Patch(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return send_with_content_provider("PATCH", path, headers, nullptr, 0, nullptr, - std::move(content_provider), content_type); + std::move(content_provider), content_type, + nullptr); } -inline Result ClientImpl::Delete(const char *path) { - return Delete(path, Headers(), std::string(), nullptr); +inline Result ClientImpl::Delete(const std::string &path) { + return Delete(path, Headers(), std::string(), std::string()); } -inline Result ClientImpl::Delete(const char *path, const Headers &headers) { - return Delete(path, headers, std::string(), nullptr); +inline Result ClientImpl::Delete(const std::string &path, + const Headers &headers) { + return Delete(path, headers, std::string(), std::string()); } -inline Result ClientImpl::Delete(const char *path, const char *body, +inline Result ClientImpl::Delete(const std::string &path, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return Delete(path, Headers(), body, content_length, content_type); } -inline Result ClientImpl::Delete(const char *path, const Headers &headers, - const char *body, size_t content_length, - const char *content_type) { +inline Result ClientImpl::Delete(const std::string &path, const char *body, + size_t content_length, + const std::string &content_type, + Progress progress) { + return Delete(path, Headers(), body, content_length, content_type, progress); +} + +inline Result ClientImpl::Delete(const std::string &path, + const Headers &headers, const char *body, + size_t content_length, + const std::string &content_type) { + return Delete(path, headers, body, content_length, content_type, nullptr); +} + +inline Result ClientImpl::Delete(const std::string &path, + const Headers &headers, const char *body, + size_t content_length, + const std::string &content_type, + Progress progress) { Request req; req.method = "DELETE"; req.headers = headers; req.path = path; + req.progress = progress; - if (content_type) { req.headers.emplace("Content-Type", content_type); } + if (!content_type.empty()) { req.set_header("Content-Type", content_type); } req.body.assign(body, content_length); return send_(std::move(req)); } -inline Result ClientImpl::Delete(const char *path, const std::string &body, - const char *content_type) { +inline Result ClientImpl::Delete(const std::string &path, + const std::string &body, + const std::string &content_type) { return Delete(path, Headers(), body.data(), body.size(), content_type); } -inline Result ClientImpl::Delete(const char *path, const Headers &headers, +inline Result ClientImpl::Delete(const std::string &path, const std::string &body, - const char *content_type) { + const std::string &content_type, + Progress progress) { + return Delete(path, Headers(), body.data(), body.size(), content_type, + progress); +} + +inline Result ClientImpl::Delete(const std::string &path, + const Headers &headers, + const std::string &body, + const std::string &content_type) { return Delete(path, headers, body.data(), body.size(), content_type); } -inline Result ClientImpl::Options(const char *path) { +inline Result ClientImpl::Delete(const std::string &path, + const Headers &headers, + const std::string &body, + const std::string &content_type, + Progress progress) { + return Delete(path, headers, body.data(), body.size(), content_type, + progress); +} + +inline Result ClientImpl::Options(const std::string &path) { return Options(path, Headers()); } -inline Result ClientImpl::Options(const char *path, const Headers &headers) { +inline Result ClientImpl::Options(const std::string &path, + const Headers &headers) { Request req; req.method = "OPTIONS"; req.headers = headers; @@ -6911,11 +8296,6 @@ inline Result ClientImpl::Options(const char *path, const Headers &headers) { return send_(std::move(req)); } -inline size_t ClientImpl::is_socket_open() const { - std::lock_guard guard(socket_mutex_); - return socket_.is_open(); -} - inline void ClientImpl::stop() { std::lock_guard guard(socket_mutex_); @@ -6933,12 +8313,23 @@ inline void ClientImpl::stop() { return; } - // Otherwise, sitll holding the mutex, we can shut everything down ourselves + // Otherwise, still holding the mutex, we can shut everything down ourselves shutdown_ssl(socket_, true); shutdown_socket(socket_); close_socket(socket_); } +inline std::string ClientImpl::host() const { return host_; } + +inline int ClientImpl::port() const { return port_; } + +inline size_t ClientImpl::is_socket_open() const { + std::lock_guard guard(socket_mutex_); + return socket_.is_open(); +} + +inline socket_t ClientImpl::socket() const { return socket_.sock; } + inline void ClientImpl::set_connection_timeout(time_t sec, time_t usec) { connection_timeout_sec_ = sec; connection_timeout_usec_ = usec; @@ -6954,19 +8345,19 @@ inline void ClientImpl::set_write_timeout(time_t sec, time_t usec) { write_timeout_usec_ = usec; } -inline void ClientImpl::set_basic_auth(const char *username, - const char *password) { +inline void ClientImpl::set_basic_auth(const std::string &username, + const std::string &password) { basic_auth_username_ = username; basic_auth_password_ = password; } -inline void ClientImpl::set_bearer_token_auth(const char *token) { +inline void ClientImpl::set_bearer_token_auth(const std::string &token) { bearer_token_auth_token_ = token; } #ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void ClientImpl::set_digest_auth(const char *username, - const char *password) { +inline void ClientImpl::set_digest_auth(const std::string &username, + const std::string &password) { digest_auth_username_ = username; digest_auth_password_ = password; } @@ -6987,6 +8378,11 @@ inline void ClientImpl::set_default_headers(Headers headers) { default_headers_ = std::move(headers); } +inline void ClientImpl::set_header_writer( + std::function const &writer) { + header_writer_ = writer; +} + inline void ClientImpl::set_address_family(int family) { address_family_ = family; } @@ -7001,36 +8397,36 @@ inline void ClientImpl::set_compress(bool on) { compress_ = on; } inline void ClientImpl::set_decompress(bool on) { decompress_ = on; } -inline void ClientImpl::set_interface(const char *intf) { interface_ = intf; } +inline void ClientImpl::set_interface(const std::string &intf) { + interface_ = intf; +} -inline void ClientImpl::set_proxy(const char *host, int port) { +inline void ClientImpl::set_proxy(const std::string &host, int port) { proxy_host_ = host; proxy_port_ = port; } -inline void ClientImpl::set_proxy_basic_auth(const char *username, - const char *password) { +inline void ClientImpl::set_proxy_basic_auth(const std::string &username, + const std::string &password) { proxy_basic_auth_username_ = username; proxy_basic_auth_password_ = password; } -inline void ClientImpl::set_proxy_bearer_token_auth(const char *token) { +inline void ClientImpl::set_proxy_bearer_token_auth(const std::string &token) { proxy_bearer_token_auth_token_ = token; } #ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void ClientImpl::set_proxy_digest_auth(const char *username, - const char *password) { +inline void ClientImpl::set_proxy_digest_auth(const std::string &username, + const std::string &password) { proxy_digest_auth_username_ = username; proxy_digest_auth_password_ = password; } -#endif -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void ClientImpl::set_ca_cert_path(const char *ca_cert_file_path, - const char *ca_cert_dir_path) { - if (ca_cert_file_path) { ca_cert_file_path_ = ca_cert_file_path; } - if (ca_cert_dir_path) { ca_cert_dir_path_ = ca_cert_dir_path; } +inline void ClientImpl::set_ca_cert_path(const std::string &ca_cert_file_path, + const std::string &ca_cert_dir_path) { + ca_cert_file_path_ = ca_cert_file_path; + ca_cert_dir_path_ = ca_cert_dir_path; } inline void ClientImpl::set_ca_cert_store(X509_STORE *ca_cert_store) { @@ -7038,9 +8434,34 @@ inline void ClientImpl::set_ca_cert_store(X509_STORE *ca_cert_store) { ca_cert_store_ = ca_cert_store; } } -#endif -#ifdef CPPHTTPLIB_OPENSSL_SUPPORT +inline X509_STORE *ClientImpl::create_ca_cert_store(const char *ca_cert, + std::size_t size) const { + auto mem = BIO_new_mem_buf(ca_cert, static_cast(size)); + if (!mem) { return nullptr; } + + auto inf = PEM_X509_INFO_read_bio(mem, nullptr, nullptr, nullptr); + if (!inf) { + BIO_free_all(mem); + return nullptr; + } + + auto cts = X509_STORE_new(); + if (cts) { + for (auto i = 0; i < static_cast(sk_X509_INFO_num(inf)); i++) { + auto itmp = sk_X509_INFO_value(inf, i); + if (!itmp) { continue; } + + if (itmp->x509) { X509_STORE_add_cert(cts, itmp->x509); } + if (itmp->crl) { X509_STORE_add_crl(cts, itmp->crl); } + } + } + + sk_X509_INFO_pop_free(inf, X509_INFO_free); + BIO_free_all(mem); + return cts; +} + inline void ClientImpl::enable_server_certificate_verification(bool enabled) { server_certificate_verification_ = enabled; } @@ -7104,7 +8525,7 @@ bool ssl_connect_or_accept_nonblocking(socket_t sock, SSL *ssl, U ssl_connect_or_accept, time_t timeout_sec, time_t timeout_usec) { - int res = 0; + auto res = 0; while ((res = ssl_connect_or_accept(ssl)) != 1) { auto err = SSL_get_error(ssl, res); switch (err) { @@ -7146,55 +8567,12 @@ process_client_socket_ssl(SSL *ssl, socket_t sock, time_t read_timeout_sec, return callback(strm); } -#if OPENSSL_VERSION_NUMBER < 0x10100000L -static std::shared_ptr> openSSL_locks_; - -class SSLThreadLocks { -public: - SSLThreadLocks() { - openSSL_locks_ = - std::make_shared>(CRYPTO_num_locks()); - CRYPTO_set_locking_callback(locking_callback); - } - - ~SSLThreadLocks() { CRYPTO_set_locking_callback(nullptr); } - -private: - static void locking_callback(int mode, int type, const char * /*file*/, - int /*line*/) { - auto &lk = (*openSSL_locks_)[static_cast(type)]; - if (mode & CRYPTO_LOCK) { - lk.lock(); - } else { - lk.unlock(); - } - } -}; - -#endif - class SSLInit { public: SSLInit() { -#if OPENSSL_VERSION_NUMBER < 0x1010001fL - SSL_load_error_strings(); - SSL_library_init(); -#else OPENSSL_init_ssl( OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); -#endif } - - ~SSLInit() { -#if OPENSSL_VERSION_NUMBER < 0x1010001fL - ERR_free_strings(); -#endif - } - -private: -#if OPENSSL_VERSION_NUMBER < 0x10100000L - SSLThreadLocks thread_init_; -#endif }; // SSL socket stream implementation @@ -7210,75 +8588,77 @@ inline SSLSocketStream::SSLSocketStream(socket_t sock, SSL *ssl, SSL_clear_mode(ssl, SSL_MODE_AUTO_RETRY); } -inline SSLSocketStream::~SSLSocketStream() {} +inline SSLSocketStream::~SSLSocketStream() = default; inline bool SSLSocketStream::is_readable() const { return detail::select_read(sock_, read_timeout_sec_, read_timeout_usec_) > 0; } inline bool SSLSocketStream::is_writable() const { - return detail::select_write(sock_, write_timeout_sec_, write_timeout_usec_) > - 0; + return select_write(sock_, write_timeout_sec_, write_timeout_usec_) > 0 && + is_socket_alive(sock_); } inline ssize_t SSLSocketStream::read(char *ptr, size_t size) { - size_t readbytes = 0; if (SSL_pending(ssl_) > 0) { - auto ret = SSL_read_ex(ssl_, ptr, size, &readbytes); - if (ret == 1) { return static_cast(readbytes); } - if (SSL_get_error(ssl_, ret) == SSL_ERROR_ZERO_RETURN) { return 0; } - return -1; - } - if (!is_readable()) { return -1; } - - auto ret = SSL_read_ex(ssl_, ptr, size, &readbytes); - if (ret == 1) { return static_cast(readbytes); } - auto err = SSL_get_error(ssl_, ret); - int n = 1000; + return SSL_read(ssl_, ptr, static_cast(size)); + } else if (is_readable()) { + auto ret = SSL_read(ssl_, ptr, static_cast(size)); + if (ret < 0) { + auto err = SSL_get_error(ssl_, ret); + auto n = 1000; #ifdef _WIN32 - while (--n >= 0 && - (err == SSL_ERROR_WANT_READ || - (err == SSL_ERROR_SYSCALL && WSAGetLastError() == WSAETIMEDOUT))) { + while (--n >= 0 && (err == SSL_ERROR_WANT_READ || + (err == SSL_ERROR_SYSCALL && + WSAGetLastError() == WSAETIMEDOUT))) { #else - while (--n >= 0 && err == SSL_ERROR_WANT_READ) { + while (--n >= 0 && err == SSL_ERROR_WANT_READ) { #endif - if (SSL_pending(ssl_) > 0) { - ret = SSL_read_ex(ssl_, ptr, size, &readbytes); - if (ret == 1) { return static_cast(readbytes); } - if (SSL_get_error(ssl_, ret) == SSL_ERROR_ZERO_RETURN) { return 0; } - return -1; + if (SSL_pending(ssl_) > 0) { + return SSL_read(ssl_, ptr, static_cast(size)); + } else if (is_readable()) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + ret = SSL_read(ssl_, ptr, static_cast(size)); + if (ret >= 0) { return ret; } + err = SSL_get_error(ssl_, ret); + } else { + return -1; + } + } } - if (!is_readable()) { return -1; } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - ret = SSL_read_ex(ssl_, ptr, size, &readbytes); - if (ret == 1) { return static_cast(readbytes); } - err = SSL_get_error(ssl_, ret); + return ret; } - if (err == SSL_ERROR_ZERO_RETURN) { return 0; } return -1; } inline ssize_t SSLSocketStream::write(const char *ptr, size_t size) { - if (!is_writable()) { return -1; } - size_t written = 0; - auto ret = SSL_write_ex(ssl_, ptr, size, &written); - if (ret == 1) { return static_cast(written); } - auto err = SSL_get_error(ssl_, ret); - int n = 1000; + if (is_writable()) { + auto handle_size = static_cast( + std::min(size, (std::numeric_limits::max)())); + + auto ret = SSL_write(ssl_, ptr, static_cast(handle_size)); + if (ret < 0) { + auto err = SSL_get_error(ssl_, ret); + auto n = 1000; #ifdef _WIN32 - while (--n >= 0 && - (err == SSL_ERROR_WANT_WRITE || - (err == SSL_ERROR_SYSCALL && WSAGetLastError() == WSAETIMEDOUT))) { + while (--n >= 0 && (err == SSL_ERROR_WANT_WRITE || + (err == SSL_ERROR_SYSCALL && + WSAGetLastError() == WSAETIMEDOUT))) { #else - while (--n >= 0 && err == SSL_ERROR_WANT_WRITE) { + while (--n >= 0 && err == SSL_ERROR_WANT_WRITE) { #endif - if (!is_writable()) { return -1; } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); - ret = SSL_write_ex(ssl_, ptr, size, &written); - if (ret == 1) { return static_cast(written); } - err = SSL_get_error(ssl_, ret); + if (is_writable()) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + ret = SSL_write(ssl_, ptr, static_cast(handle_size)); + if (ret >= 0) { return ret; } + err = SSL_get_error(ssl_, ret); + } else { + return -1; + } + } + } + return ret; } - if (err == SSL_ERROR_ZERO_RETURN) { return 0; } return -1; } @@ -7287,6 +8667,11 @@ inline void SSLSocketStream::get_remote_ip_and_port(std::string &ip, detail::get_remote_ip_and_port(sock_, ip, port); } +inline void SSLSocketStream::get_local_ip_and_port(std::string &ip, + int &port) const { + detail::get_local_ip_and_port(sock_, ip, port); +} + inline socket_t SSLSocketStream::socket() const { return sock_; } static SSLInit sslinit_; @@ -7307,10 +8692,10 @@ inline SSLServer::SSLServer(const char *cert_path, const char *private_key_path, SSL_CTX_set_min_proto_version(ctx_, TLS1_1_VERSION); - // add default password callback before opening encrypted private key if (private_key_password != nullptr && (private_key_password[0] != '\0')) { - SSL_CTX_set_default_passwd_cb_userdata(ctx_, - (char *)private_key_password); + SSL_CTX_set_default_passwd_cb_userdata( + ctx_, + reinterpret_cast(const_cast(private_key_password))); } if (SSL_CTX_use_certificate_chain_file(ctx_, cert_path) != 1 || @@ -7371,16 +8756,29 @@ inline bool SSLServer::is_valid() const { return ctx_; } inline SSL_CTX *SSLServer::ssl_context() const { return ctx_; } +inline void SSLServer::update_certs (X509 *cert, EVP_PKEY *private_key, + X509_STORE *client_ca_cert_store) { + + std::lock_guard guard(ctx_mutex_); + + SSL_CTX_use_certificate (ctx_, cert); + SSL_CTX_use_PrivateKey (ctx_, private_key); + + if (client_ca_cert_store != nullptr) { + SSL_CTX_set_cert_store (ctx_, client_ca_cert_store); + } +} + inline bool SSLServer::process_and_close_socket(socket_t sock) { auto ssl = detail::ssl_new( sock, ctx_, ctx_mutex_, - [&](SSL *ssl) { + [&](SSL *ssl2) { return detail::ssl_connect_or_accept_nonblocking( - sock, ssl, SSL_accept, read_timeout_sec_, read_timeout_usec_); + sock, ssl2, SSL_accept, read_timeout_sec_, read_timeout_usec_); }, - [](SSL * /*ssl*/) { return true; }); + [](SSL * /*ssl2*/) { return true; }); - bool ret = false; + auto ret = false; if (ssl) { ret = detail::process_server_socket_ssl( svr_sock_, ssl, sock, keep_alive_max_count_, keep_alive_timeout_sec_, @@ -7412,16 +8810,23 @@ inline SSLClient::SSLClient(const std::string &host, int port) inline SSLClient::SSLClient(const std::string &host, int port, const std::string &client_cert_path, - const std::string &client_key_path) + const std::string &client_key_path, + const std::string &private_key_password) : ClientImpl(host, port, client_cert_path, client_key_path) { ctx_ = SSL_CTX_new(TLS_client_method()); detail::split(&host_[0], &host_[host_.size()], '.', [&](const char *b, const char *e) { - host_components_.emplace_back(std::string(b, e)); + host_components_.emplace_back(b, e); }); if (!client_cert_path.empty() && !client_key_path.empty()) { + if (!private_key_password.empty()) { + SSL_CTX_set_default_passwd_cb_userdata( + ctx_, reinterpret_cast( + const_cast(private_key_password.c_str()))); + } + if (SSL_CTX_use_certificate_file(ctx_, client_cert_path.c_str(), SSL_FILETYPE_PEM) != 1 || SSL_CTX_use_PrivateKey_file(ctx_, client_key_path.c_str(), @@ -7433,16 +8838,23 @@ inline SSLClient::SSLClient(const std::string &host, int port, } inline SSLClient::SSLClient(const std::string &host, int port, - X509 *client_cert, EVP_PKEY *client_key) + X509 *client_cert, EVP_PKEY *client_key, + const std::string &private_key_password) : ClientImpl(host, port) { ctx_ = SSL_CTX_new(TLS_client_method()); detail::split(&host_[0], &host_[host_.size()], '.', [&](const char *b, const char *e) { - host_components_.emplace_back(std::string(b, e)); + host_components_.emplace_back(b, e); }); if (client_cert != nullptr && client_key != nullptr) { + if (!private_key_password.empty()) { + SSL_CTX_set_default_passwd_cb_userdata( + ctx_, reinterpret_cast( + const_cast(private_key_password.c_str()))); + } + if (SSL_CTX_use_certificate(ctx_, client_cert) != 1 || SSL_CTX_use_PrivateKey(ctx_, client_key) != 1) { SSL_CTX_free(ctx_); @@ -7474,6 +8886,11 @@ inline void SSLClient::set_ca_cert_store(X509_STORE *ca_cert_store) { } } +inline void SSLClient::load_ca_cert_store(const char *ca_cert, + std::size_t size) { + set_ca_cert_store(ClientImpl::create_ca_cert_store(ca_cert, size)); +} + inline long SSLClient::get_openssl_verify_result() const { return verify_result_; } @@ -7488,14 +8905,14 @@ inline bool SSLClient::create_and_connect_socket(Socket &socket, Error &error) { inline bool SSLClient::connect_with_proxy(Socket &socket, Response &res, bool &success, Error &error) { success = true; - Response res2; + Response proxy_res; if (!detail::process_client_socket( socket.sock, read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, write_timeout_usec_, [&](Stream &strm) { Request req2; req2.method = "CONNECT"; req2.path = host_and_port_; - return process_request(strm, req2, res2, false, error); + return process_request(strm, req2, proxy_res, false, error); })) { // Thread-safe to close everything because we are assuming there are no // requests in flight @@ -7506,12 +8923,12 @@ inline bool SSLClient::connect_with_proxy(Socket &socket, Response &res, return false; } - if (res2.status == 407) { + if (proxy_res.status == StatusCode::ProxyAuthenticationRequired_407) { if (!proxy_digest_auth_username_.empty() && !proxy_digest_auth_password_.empty()) { std::map auth; - if (detail::parse_www_authenticate(res2, auth, true)) { - Response res3; + if (detail::parse_www_authenticate(proxy_res, auth, true)) { + proxy_res = Response(); if (!detail::process_client_socket( socket.sock, read_timeout_sec_, read_timeout_usec_, write_timeout_sec_, write_timeout_usec_, [&](Stream &strm) { @@ -7522,7 +8939,7 @@ inline bool SSLClient::connect_with_proxy(Socket &socket, Response &res, req3, auth, 1, detail::random_string(10), proxy_digest_auth_username_, proxy_digest_auth_password_, true)); - return process_request(strm, req3, res3, false, error); + return process_request(strm, req3, proxy_res, false, error); })) { // Thread-safe to close everything because we are assuming there are // no requests in flight @@ -7533,17 +8950,28 @@ inline bool SSLClient::connect_with_proxy(Socket &socket, Response &res, return false; } } - } else { - res = res2; - return false; } } + // If status code is not 200, proxy request is failed. + // Set error to ProxyConnection and return proxy response + // as the response of the request + if (proxy_res.status != StatusCode::OK_200) { + error = Error::ProxyConnection; + res = std::move(proxy_res); + // Thread-safe to close everything because we are assuming there are + // no requests in flight + shutdown_ssl(socket, true); + shutdown_socket(socket); + close_socket(socket); + return false; + } + return true; } inline bool SSLClient::load_certs() { - bool ret = true; + auto ret = true; std::call_once(initialize_cert_, [&]() { std::lock_guard guard(ctx_mutex_); @@ -7558,11 +8986,16 @@ inline bool SSLClient::load_certs() { ret = false; } } else { + auto loaded = false; #ifdef _WIN32 - detail::load_system_certs_on_windows(SSL_CTX_get_cert_store(ctx_)); -#else - SSL_CTX_set_default_verify_paths(ctx_); -#endif + loaded = + detail::load_system_certs_on_windows(SSL_CTX_get_cert_store(ctx_)); +#elif defined(CPPHTTPLIB_USE_CERTS_FROM_MACOSX_KEYCHAIN) && defined(__APPLE__) +#if TARGET_OS_OSX + loaded = detail::load_system_certs_on_macos(SSL_CTX_get_cert_store(ctx_)); +#endif // TARGET_OS_OSX +#endif // _WIN32 + if (!loaded) { SSL_CTX_set_default_verify_paths(ctx_); } } }); @@ -7572,31 +9005,31 @@ inline bool SSLClient::load_certs() { inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) { auto ssl = detail::ssl_new( socket.sock, ctx_, ctx_mutex_, - [&](SSL *ssl) { + [&](SSL *ssl2) { if (server_certificate_verification_) { if (!load_certs()) { error = Error::SSLLoadingCerts; return false; } - SSL_set_verify(ssl, SSL_VERIFY_NONE, nullptr); + SSL_set_verify(ssl2, SSL_VERIFY_NONE, nullptr); } if (!detail::ssl_connect_or_accept_nonblocking( - socket.sock, ssl, SSL_connect, connection_timeout_sec_, + socket.sock, ssl2, SSL_connect, connection_timeout_sec_, connection_timeout_usec_)) { error = Error::SSLConnection; return false; } if (server_certificate_verification_) { - verify_result_ = SSL_get_verify_result(ssl); + verify_result_ = SSL_get_verify_result(ssl2); if (verify_result_ != X509_V_OK) { error = Error::SSLServerVerification; return false; } - auto server_cert = SSL_get_peer_certificate(ssl); + auto server_cert = SSL_get1_peer_certificate(ssl2); if (server_cert == nullptr) { error = Error::SSLServerVerification; @@ -7613,8 +9046,12 @@ inline bool SSLClient::initialize_ssl(Socket &socket, Error &error) { return true; }, - [&](SSL *ssl) { - SSL_set_tlsext_host_name(ssl, host_.c_str()); + [&](SSL *ssl2) { + // NOTE: Direct call instead of using the OpenSSL macro to suppress + // -Wold-style-cast warning + // SSL_set_tlsext_host_name(ssl2, host_.c_str()); + SSL_ctrl(ssl2, SSL_CTRL_SET_TLSEXT_HOSTNAME, TLSEXT_NAMETYPE_host_name, + static_cast(const_cast(host_.c_str()))); return true; }); @@ -7688,8 +9125,8 @@ SSLClient::verify_host_with_subject_alt_name(X509 *server_cert) const { auto type = GEN_DNS; - struct in6_addr addr6; - struct in_addr addr; + struct in6_addr addr6 {}; + struct in_addr addr {}; size_t addr_len = 0; #ifndef __MINGW32__ @@ -7707,15 +9144,16 @@ SSLClient::verify_host_with_subject_alt_name(X509 *server_cert) const { if (alt_names) { auto dsn_matched = false; - auto ip_mached = false; + auto ip_matched = false; auto count = sk_GENERAL_NAME_num(alt_names); for (decltype(count) i = 0; i < count && !dsn_matched; i++) { auto val = sk_GENERAL_NAME_value(alt_names, i); if (val->type == type) { - auto name = (const char *)ASN1_STRING_get0_data(val->d.ia5); - auto name_len = (size_t)ASN1_STRING_length(val->d.ia5); + auto name = + reinterpret_cast(ASN1_STRING_get0_data(val->d.ia5)); + auto name_len = static_cast(ASN1_STRING_length(val->d.ia5)); switch (type) { case GEN_DNS: dsn_matched = check_host_name(name, name_len); break; @@ -7723,17 +9161,18 @@ SSLClient::verify_host_with_subject_alt_name(X509 *server_cert) const { case GEN_IPADD: if (!memcmp(&addr6, name, addr_len) || !memcmp(&addr, name, addr_len)) { - ip_mached = true; + ip_matched = true; } break; } } } - if (dsn_matched || ip_mached) { ret = true; } + if (dsn_matched || ip_matched) { ret = true; } } - GENERAL_NAMES_free((STACK_OF(GENERAL_NAME) *)alt_names); + GENERAL_NAMES_free(const_cast( + reinterpret_cast(alt_names))); return ret; } @@ -7762,7 +9201,7 @@ inline bool SSLClient::check_host_name(const char *pattern, std::vector pattern_components; detail::split(&pattern[0], &pattern[pattern_len], '.', [&](const char *b, const char *e) { - pattern_components.emplace_back(std::string(b, e)); + pattern_components.emplace_back(b, e); }); if (host_components_.size() != pattern_components.size()) { return false; } @@ -7790,7 +9229,7 @@ inline Client::Client(const std::string &scheme_host_port, const std::string &client_cert_path, const std::string &client_key_path) { const static std::regex re( - R"((?:([a-z]+):\/\/)?(?:\[([\d:]+)\]|([^:/?#]+))(?::(\d+))?)"); + R"((?:([a-z]+):\/\/)?(?:\[([a-fA-F\d:]+)\]|([^:/?#]+))(?::(\d+))?)"); std::smatch m; if (std::regex_match(scheme_host_port, m, re)) { @@ -7818,15 +9257,17 @@ inline Client::Client(const std::string &scheme_host_port, if (is_ssl) { #ifdef CPPHTTPLIB_OPENSSL_SUPPORT - cli_ = detail::make_unique(host.c_str(), port, - client_cert_path, client_key_path); + cli_ = detail::make_unique(host, port, client_cert_path, + client_key_path); is_ssl_ = is_ssl; #endif } else { - cli_ = detail::make_unique(host.c_str(), port, - client_cert_path, client_key_path); + cli_ = detail::make_unique(host, port, client_cert_path, + client_key_path); } } else { + // NOTE: Update TEST(UniversalClientImplTest, Ipv6LiteralAddress) + // if port param below changes. cli_ = detail::make_unique(scheme_host_port, 80, client_cert_path, client_key_path); } @@ -7841,257 +9282,377 @@ inline Client::Client(const std::string &host, int port, : cli_(detail::make_unique(host, port, client_cert_path, client_key_path)) {} -inline Client::~Client() {} +inline Client::~Client() = default; inline bool Client::is_valid() const { return cli_ != nullptr && cli_->is_valid(); } -inline Result Client::Get(const char *path) { return cli_->Get(path); } -inline Result Client::Get(const char *path, const Headers &headers) { +inline Result Client::Get(const std::string &path) { return cli_->Get(path); } +inline Result Client::Get(const std::string &path, const Headers &headers) { return cli_->Get(path, headers); } -inline Result Client::Get(const char *path, Progress progress) { +inline Result Client::Get(const std::string &path, Progress progress) { return cli_->Get(path, std::move(progress)); } -inline Result Client::Get(const char *path, const Headers &headers, +inline Result Client::Get(const std::string &path, const Headers &headers, Progress progress) { return cli_->Get(path, headers, std::move(progress)); } -inline Result Client::Get(const char *path, ContentReceiver content_receiver) { +inline Result Client::Get(const std::string &path, + ContentReceiver content_receiver) { return cli_->Get(path, std::move(content_receiver)); } -inline Result Client::Get(const char *path, const Headers &headers, +inline Result Client::Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver) { return cli_->Get(path, headers, std::move(content_receiver)); } -inline Result Client::Get(const char *path, ContentReceiver content_receiver, - Progress progress) { +inline Result Client::Get(const std::string &path, + ContentReceiver content_receiver, Progress progress) { return cli_->Get(path, std::move(content_receiver), std::move(progress)); } -inline Result Client::Get(const char *path, const Headers &headers, +inline Result Client::Get(const std::string &path, const Headers &headers, ContentReceiver content_receiver, Progress progress) { return cli_->Get(path, headers, std::move(content_receiver), std::move(progress)); } -inline Result Client::Get(const char *path, ResponseHandler response_handler, +inline Result Client::Get(const std::string &path, + ResponseHandler response_handler, ContentReceiver content_receiver) { return cli_->Get(path, std::move(response_handler), std::move(content_receiver)); } -inline Result Client::Get(const char *path, const Headers &headers, +inline Result Client::Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver) { return cli_->Get(path, headers, std::move(response_handler), std::move(content_receiver)); } -inline Result Client::Get(const char *path, ResponseHandler response_handler, +inline Result Client::Get(const std::string &path, + ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress) { return cli_->Get(path, std::move(response_handler), std::move(content_receiver), std::move(progress)); } -inline Result Client::Get(const char *path, const Headers &headers, +inline Result Client::Get(const std::string &path, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress) { return cli_->Get(path, headers, std::move(response_handler), std::move(content_receiver), std::move(progress)); } -inline Result Client::Get(const char *path, const Params ¶ms, +inline Result Client::Get(const std::string &path, const Params ¶ms, const Headers &headers, Progress progress) { - return cli_->Get(path, params, headers, progress); + return cli_->Get(path, params, headers, std::move(progress)); } -inline Result Client::Get(const char *path, const Params ¶ms, +inline Result Client::Get(const std::string &path, const Params ¶ms, const Headers &headers, ContentReceiver content_receiver, Progress progress) { - return cli_->Get(path, params, headers, content_receiver, progress); + return cli_->Get(path, params, headers, std::move(content_receiver), + std::move(progress)); } -inline Result Client::Get(const char *path, const Params ¶ms, +inline Result Client::Get(const std::string &path, const Params ¶ms, const Headers &headers, ResponseHandler response_handler, ContentReceiver content_receiver, Progress progress) { - return cli_->Get(path, params, headers, response_handler, content_receiver, - progress); + return cli_->Get(path, params, headers, std::move(response_handler), + std::move(content_receiver), std::move(progress)); } -inline Result Client::Head(const char *path) { return cli_->Head(path); } -inline Result Client::Head(const char *path, const Headers &headers) { +inline Result Client::Head(const std::string &path) { return cli_->Head(path); } +inline Result Client::Head(const std::string &path, const Headers &headers) { return cli_->Head(path, headers); } -inline Result Client::Post(const char *path) { return cli_->Post(path); } -inline Result Client::Post(const char *path, const char *body, - size_t content_length, const char *content_type) { +inline Result Client::Post(const std::string &path) { return cli_->Post(path); } +inline Result Client::Post(const std::string &path, const Headers &headers) { + return cli_->Post(path, headers); +} +inline Result Client::Post(const std::string &path, const char *body, + size_t content_length, + const std::string &content_type) { return cli_->Post(path, body, content_length, content_type); } -inline Result Client::Post(const char *path, const Headers &headers, +inline Result Client::Post(const std::string &path, const Headers &headers, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return cli_->Post(path, headers, body, content_length, content_type); } -inline Result Client::Post(const char *path, const std::string &body, - const char *content_type) { +inline Result Client::Post(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type, Progress progress) { + return cli_->Post(path, headers, body, content_length, content_type, + progress); +} +inline Result Client::Post(const std::string &path, const std::string &body, + const std::string &content_type) { return cli_->Post(path, body, content_type); } -inline Result Client::Post(const char *path, const Headers &headers, - const std::string &body, const char *content_type) { +inline Result Client::Post(const std::string &path, const std::string &body, + const std::string &content_type, Progress progress) { + return cli_->Post(path, body, content_type, progress); +} +inline Result Client::Post(const std::string &path, const Headers &headers, + const std::string &body, + const std::string &content_type) { return cli_->Post(path, headers, body, content_type); } -inline Result Client::Post(const char *path, size_t content_length, +inline Result Client::Post(const std::string &path, const Headers &headers, + const std::string &body, + const std::string &content_type, Progress progress) { + return cli_->Post(path, headers, body, content_type, progress); +} +inline Result Client::Post(const std::string &path, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Post(path, content_length, std::move(content_provider), content_type); } -inline Result Client::Post(const char *path, +inline Result Client::Post(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Post(path, std::move(content_provider), content_type); } -inline Result Client::Post(const char *path, const Headers &headers, +inline Result Client::Post(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Post(path, headers, content_length, std::move(content_provider), content_type); } -inline Result Client::Post(const char *path, const Headers &headers, +inline Result Client::Post(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Post(path, headers, std::move(content_provider), content_type); } -inline Result Client::Post(const char *path, const Params ¶ms) { +inline Result Client::Post(const std::string &path, const Params ¶ms) { return cli_->Post(path, params); } -inline Result Client::Post(const char *path, const Headers &headers, +inline Result Client::Post(const std::string &path, const Headers &headers, const Params ¶ms) { return cli_->Post(path, headers, params); } -inline Result Client::Post(const char *path, +inline Result Client::Post(const std::string &path, const Headers &headers, + const Params ¶ms, Progress progress) { + return cli_->Post(path, headers, params, progress); +} +inline Result Client::Post(const std::string &path, const MultipartFormDataItems &items) { return cli_->Post(path, items); } -inline Result Client::Post(const char *path, const Headers &headers, +inline Result Client::Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items) { return cli_->Post(path, headers, items); } -inline Result Client::Post(const char *path, const Headers &headers, +inline Result Client::Post(const std::string &path, const Headers &headers, const MultipartFormDataItems &items, const std::string &boundary) { return cli_->Post(path, headers, items, boundary); } -inline Result Client::Put(const char *path) { return cli_->Put(path); } -inline Result Client::Put(const char *path, const char *body, - size_t content_length, const char *content_type) { +inline Result +Client::Post(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, + const MultipartFormDataProviderItems &provider_items) { + return cli_->Post(path, headers, items, provider_items); +} +inline Result Client::Put(const std::string &path) { return cli_->Put(path); } +inline Result Client::Put(const std::string &path, const char *body, + size_t content_length, + const std::string &content_type) { return cli_->Put(path, body, content_length, content_type); } -inline Result Client::Put(const char *path, const Headers &headers, +inline Result Client::Put(const std::string &path, const Headers &headers, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return cli_->Put(path, headers, body, content_length, content_type); } -inline Result Client::Put(const char *path, const std::string &body, - const char *content_type) { +inline Result Client::Put(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type, Progress progress) { + return cli_->Put(path, headers, body, content_length, content_type, progress); +} +inline Result Client::Put(const std::string &path, const std::string &body, + const std::string &content_type) { return cli_->Put(path, body, content_type); } -inline Result Client::Put(const char *path, const Headers &headers, - const std::string &body, const char *content_type) { +inline Result Client::Put(const std::string &path, const std::string &body, + const std::string &content_type, Progress progress) { + return cli_->Put(path, body, content_type, progress); +} +inline Result Client::Put(const std::string &path, const Headers &headers, + const std::string &body, + const std::string &content_type) { return cli_->Put(path, headers, body, content_type); } -inline Result Client::Put(const char *path, size_t content_length, +inline Result Client::Put(const std::string &path, const Headers &headers, + const std::string &body, + const std::string &content_type, Progress progress) { + return cli_->Put(path, headers, body, content_type, progress); +} +inline Result Client::Put(const std::string &path, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Put(path, content_length, std::move(content_provider), content_type); } -inline Result Client::Put(const char *path, +inline Result Client::Put(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Put(path, std::move(content_provider), content_type); } -inline Result Client::Put(const char *path, const Headers &headers, +inline Result Client::Put(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Put(path, headers, content_length, std::move(content_provider), content_type); } -inline Result Client::Put(const char *path, const Headers &headers, +inline Result Client::Put(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Put(path, headers, std::move(content_provider), content_type); } -inline Result Client::Put(const char *path, const Params ¶ms) { +inline Result Client::Put(const std::string &path, const Params ¶ms) { return cli_->Put(path, params); } -inline Result Client::Put(const char *path, const Headers &headers, +inline Result Client::Put(const std::string &path, const Headers &headers, const Params ¶ms) { return cli_->Put(path, headers, params); } -inline Result Client::Patch(const char *path) { return cli_->Patch(path); } -inline Result Client::Patch(const char *path, const char *body, - size_t content_length, const char *content_type) { +inline Result Client::Put(const std::string &path, const Headers &headers, + const Params ¶ms, Progress progress) { + return cli_->Put(path, headers, params, progress); +} +inline Result Client::Put(const std::string &path, + const MultipartFormDataItems &items) { + return cli_->Put(path, items); +} +inline Result Client::Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items) { + return cli_->Put(path, headers, items); +} +inline Result Client::Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, + const std::string &boundary) { + return cli_->Put(path, headers, items, boundary); +} +inline Result +Client::Put(const std::string &path, const Headers &headers, + const MultipartFormDataItems &items, + const MultipartFormDataProviderItems &provider_items) { + return cli_->Put(path, headers, items, provider_items); +} +inline Result Client::Patch(const std::string &path) { + return cli_->Patch(path); +} +inline Result Client::Patch(const std::string &path, const char *body, + size_t content_length, + const std::string &content_type) { return cli_->Patch(path, body, content_length, content_type); } -inline Result Client::Patch(const char *path, const Headers &headers, +inline Result Client::Patch(const std::string &path, const char *body, + size_t content_length, + const std::string &content_type, Progress progress) { + return cli_->Patch(path, body, content_length, content_type, progress); +} +inline Result Client::Patch(const std::string &path, const Headers &headers, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return cli_->Patch(path, headers, body, content_length, content_type); } -inline Result Client::Patch(const char *path, const std::string &body, - const char *content_type) { +inline Result Client::Patch(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type, Progress progress) { + return cli_->Patch(path, headers, body, content_length, content_type, progress); +} +inline Result Client::Patch(const std::string &path, const std::string &body, + const std::string &content_type) { return cli_->Patch(path, body, content_type); } -inline Result Client::Patch(const char *path, const Headers &headers, - const std::string &body, const char *content_type) { +inline Result Client::Patch(const std::string &path, const std::string &body, + const std::string &content_type, Progress progress) { + return cli_->Patch(path, body, content_type, progress); +} +inline Result Client::Patch(const std::string &path, const Headers &headers, + const std::string &body, + const std::string &content_type) { return cli_->Patch(path, headers, body, content_type); } -inline Result Client::Patch(const char *path, size_t content_length, +inline Result Client::Patch(const std::string &path, const Headers &headers, + const std::string &body, + const std::string &content_type, Progress progress) { + return cli_->Patch(path, headers, body, content_type, progress); +} +inline Result Client::Patch(const std::string &path, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Patch(path, content_length, std::move(content_provider), content_type); } -inline Result Client::Patch(const char *path, +inline Result Client::Patch(const std::string &path, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Patch(path, std::move(content_provider), content_type); } -inline Result Client::Patch(const char *path, const Headers &headers, +inline Result Client::Patch(const std::string &path, const Headers &headers, size_t content_length, ContentProvider content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Patch(path, headers, content_length, std::move(content_provider), content_type); } -inline Result Client::Patch(const char *path, const Headers &headers, +inline Result Client::Patch(const std::string &path, const Headers &headers, ContentProviderWithoutLength content_provider, - const char *content_type) { + const std::string &content_type) { return cli_->Patch(path, headers, std::move(content_provider), content_type); } -inline Result Client::Delete(const char *path) { return cli_->Delete(path); } -inline Result Client::Delete(const char *path, const Headers &headers) { +inline Result Client::Delete(const std::string &path) { + return cli_->Delete(path); +} +inline Result Client::Delete(const std::string &path, const Headers &headers) { return cli_->Delete(path, headers); } -inline Result Client::Delete(const char *path, const char *body, - size_t content_length, const char *content_type) { +inline Result Client::Delete(const std::string &path, const char *body, + size_t content_length, + const std::string &content_type) { return cli_->Delete(path, body, content_length, content_type); } -inline Result Client::Delete(const char *path, const Headers &headers, +inline Result Client::Delete(const std::string &path, const char *body, + size_t content_length, + const std::string &content_type, Progress progress) { + return cli_->Delete(path, body, content_length, content_type, progress); +} +inline Result Client::Delete(const std::string &path, const Headers &headers, const char *body, size_t content_length, - const char *content_type) { + const std::string &content_type) { return cli_->Delete(path, headers, body, content_length, content_type); } -inline Result Client::Delete(const char *path, const std::string &body, - const char *content_type) { +inline Result Client::Delete(const std::string &path, const Headers &headers, + const char *body, size_t content_length, + const std::string &content_type, Progress progress) { + return cli_->Delete(path, headers, body, content_length, content_type, progress); +} +inline Result Client::Delete(const std::string &path, const std::string &body, + const std::string &content_type) { return cli_->Delete(path, body, content_type); } -inline Result Client::Delete(const char *path, const Headers &headers, +inline Result Client::Delete(const std::string &path, const std::string &body, + const std::string &content_type, Progress progress) { + return cli_->Delete(path, body, content_type, progress); +} +inline Result Client::Delete(const std::string &path, const Headers &headers, const std::string &body, - const char *content_type) { + const std::string &content_type) { return cli_->Delete(path, headers, body, content_type); } -inline Result Client::Options(const char *path) { return cli_->Options(path); } -inline Result Client::Options(const char *path, const Headers &headers) { +inline Result Client::Delete(const std::string &path, const Headers &headers, + const std::string &body, + const std::string &content_type, Progress progress) { + return cli_->Delete(path, headers, body, content_type, progress); +} +inline Result Client::Options(const std::string &path) { + return cli_->Options(path); +} +inline Result Client::Options(const std::string &path, const Headers &headers) { return cli_->Options(path, headers); } @@ -8101,9 +9662,15 @@ inline bool Client::send(Request &req, Response &res, Error &error) { inline Result Client::send(const Request &req) { return cli_->send(req); } +inline void Client::stop() { cli_->stop(); } + +inline std::string Client::host() const { return cli_->host(); } + +inline int Client::port() const { return cli_->port(); } + inline size_t Client::is_socket_open() const { return cli_->is_socket_open(); } -inline void Client::stop() { cli_->stop(); } +inline socket_t Client::socket() const { return cli_->socket(); } inline void Client::set_hostname_addr_map(std::map addr_map) { @@ -8114,6 +9681,11 @@ inline void Client::set_default_headers(Headers headers) { cli_->set_default_headers(std::move(headers)); } +inline void Client::set_header_writer( + std::function const &writer) { + cli_->set_header_writer(writer); +} + inline void Client::set_address_family(int family) { cli_->set_address_family(family); } @@ -8136,15 +9708,16 @@ inline void Client::set_write_timeout(time_t sec, time_t usec) { cli_->set_write_timeout(sec, usec); } -inline void Client::set_basic_auth(const char *username, const char *password) { +inline void Client::set_basic_auth(const std::string &username, + const std::string &password) { cli_->set_basic_auth(username, password); } -inline void Client::set_bearer_token_auth(const char *token) { +inline void Client::set_bearer_token_auth(const std::string &token) { cli_->set_bearer_token_auth(token); } #ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void Client::set_digest_auth(const char *username, - const char *password) { +inline void Client::set_digest_auth(const std::string &username, + const std::string &password) { cli_->set_digest_auth(username, password); } #endif @@ -8160,23 +9733,23 @@ inline void Client::set_compress(bool on) { cli_->set_compress(on); } inline void Client::set_decompress(bool on) { cli_->set_decompress(on); } -inline void Client::set_interface(const char *intf) { +inline void Client::set_interface(const std::string &intf) { cli_->set_interface(intf); } -inline void Client::set_proxy(const char *host, int port) { +inline void Client::set_proxy(const std::string &host, int port) { cli_->set_proxy(host, port); } -inline void Client::set_proxy_basic_auth(const char *username, - const char *password) { +inline void Client::set_proxy_basic_auth(const std::string &username, + const std::string &password) { cli_->set_proxy_basic_auth(username, password); } -inline void Client::set_proxy_bearer_token_auth(const char *token) { +inline void Client::set_proxy_bearer_token_auth(const std::string &token) { cli_->set_proxy_bearer_token_auth(token); } #ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void Client::set_proxy_digest_auth(const char *username, - const char *password) { +inline void Client::set_proxy_digest_auth(const std::string &username, + const std::string &password) { cli_->set_proxy_digest_auth(username, password); } #endif @@ -8187,11 +9760,13 @@ inline void Client::enable_server_certificate_verification(bool enabled) { } #endif -inline void Client::set_logger(Logger logger) { cli_->set_logger(logger); } +inline void Client::set_logger(Logger logger) { + cli_->set_logger(std::move(logger)); +} #ifdef CPPHTTPLIB_OPENSSL_SUPPORT -inline void Client::set_ca_cert_path(const char *ca_cert_file_path, - const char *ca_cert_dir_path) { +inline void Client::set_ca_cert_path(const std::string &ca_cert_file_path, + const std::string &ca_cert_dir_path) { cli_->set_ca_cert_path(ca_cert_file_path, ca_cert_dir_path); } @@ -8203,6 +9778,10 @@ inline void Client::set_ca_cert_store(X509_STORE *ca_cert_store) { } } +inline void Client::load_ca_cert_store(const char *ca_cert, std::size_t size) { + set_ca_cert_store(cli_->create_ca_cert_store(ca_cert, size)); +} + inline long Client::get_openssl_verify_result() const { if (is_ssl_) { return static_cast(*cli_).get_openssl_verify_result(); @@ -8220,4 +9799,8 @@ inline SSL_CTX *Client::ssl_context() const { } // namespace httplib +#if defined(_WIN32) && defined(CPPHTTPLIB_USE_POLL) +#undef poll +#endif + #endif // CPPHTTPLIB_HTTPLIB_H diff --git a/dependencies/hueplusplus-1.0.0/.gitmodules b/dependencies/hueplusplus-1.0.0/.gitmodules deleted file mode 100644 index 544374b4..00000000 --- a/dependencies/hueplusplus-1.0.0/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "lib/mbedtls"] - path = lib/mbedtls - url = https://github.com/ARMmbed/mbedtls.git diff --git a/dependencies/hueplusplus-1.0.0/CMakeLists.txt b/dependencies/hueplusplus-1.0.0/CMakeLists.txt deleted file mode 100644 index c4aac6af..00000000 --- a/dependencies/hueplusplus-1.0.0/CMakeLists.txt +++ /dev/null @@ -1,105 +0,0 @@ -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() diff --git a/dependencies/hueplusplus-1.0.0/Jenkinsfile b/dependencies/hueplusplus-1.0.0/Jenkinsfile deleted file mode 100644 index 797bac28..00000000 --- a/dependencies/hueplusplus-1.0.0/Jenkinsfile +++ /dev/null @@ -1,55 +0,0 @@ -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' - } - } - -} diff --git a/dependencies/hueplusplus-1.0.0/README.md b/dependencies/hueplusplus-1.0.0/README.md deleted file mode 100644 index eae853c0..00000000 --- a/dependencies/hueplusplus-1.0.0/README.md +++ /dev/null @@ -1,165 +0,0 @@ -# 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) | [![Build Status](https://travis-ci.com/enwi/hueplusplus.svg?branch=master)](https://travis-ci.com/enwi/hueplusplus) | [![codecov](https://codecov.io/gh/enwi/hueplusplus/branch/master/graph/badge.svg)](https://codecov.io/gh/enwi/hueplusplus) | [![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/enwi/hueplusplus.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/enwi/hueplusplus/context:cpp) | -| [Development](https://github.com/enwi/hueplusplus/tree/development) | [![Build Status](https://travis-ci.com/enwi/hueplusplus.svg?branch=development)](https://travis-ci.com/enwi/hueplusplus) | [![codecov](https://codecov.io/gh/enwi/hueplusplus/branch/development/graph/badge.svg)](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 -### 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(); -handler = std::make_shared(); -hueplusplus::BridgeFinder finder(handler); -std::vector 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[\]), -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, ""); -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(); -handler = std::make_shared(); -hueplusplus::Bridge bridge("192.168.2.102", 80, "", 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(\) 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 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\, 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( 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}//hueplusplus" "${CMAKE_CURRENT_BINARY_DIR}/hueplusplus") -endif() - -target_link_libraries( 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. diff --git a/dependencies/hueplusplus-1.0.0/include/json/json.hpp b/dependencies/hueplusplus-1.0.0/include/json/json.hpp deleted file mode 100644 index e821c79a..00000000 --- a/dependencies/hueplusplus-1.0.0/include/json/json.hpp +++ /dev/null @@ -1,25533 +0,0 @@ -/* - __ _____ _____ _____ - __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 3.9.1 -|_____|_____|_____|_|___| https://github.com/nlohmann/json - -Licensed under the MIT License . -SPDX-License-Identifier: MIT -Copyright (c) 2013-2019 Niels Lohmann . - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#ifndef INCLUDE_NLOHMANN_JSON_HPP_ -#define INCLUDE_NLOHMANN_JSON_HPP_ - -#define NLOHMANN_JSON_VERSION_MAJOR 3 -#define NLOHMANN_JSON_VERSION_MINOR 9 -#define NLOHMANN_JSON_VERSION_PATCH 1 - -#include // all_of, find, for_each -#include // nullptr_t, ptrdiff_t, size_t -#include // hash, less -#include // initializer_list -#include // istream, ostream -#include // random_access_iterator_tag -#include // unique_ptr -#include // accumulate -#include // string, stoi, to_string -#include // declval, forward, move, pair, swap -#include // vector - -// #include - - -#include - -// #include - - -#include // transform -#include // array -#include // forward_list -#include // inserter, front_inserter, end -#include // map -#include // string -#include // tuple, make_tuple -#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible -#include // unordered_map -#include // pair, declval -#include // valarray - -// #include - - -#include // exception -#include // runtime_error -#include // to_string - -// #include - - -#include // size_t - -namespace nlohmann -{ -namespace detail -{ -/// struct to capture the start position of the current token -struct position_t -{ - /// the total number of characters read - std::size_t chars_read_total = 0; - /// the number of characters read in the current line - std::size_t chars_read_current_line = 0; - /// the number of lines read - std::size_t lines_read = 0; - - /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } -}; - -} // namespace detail -} // namespace nlohmann - -// #include - - -#include // pair -// #include -/* Hedley - https://nemequ.github.io/hedley - * Created by Evan Nemerson - * - * To the extent possible under law, the author(s) have dedicated all - * copyright and related and neighboring rights to this software to - * the public domain worldwide. This software is distributed without - * any warranty. - * - * For details, see . - * SPDX-License-Identifier: CC0-1.0 - */ - -#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 14) -#if defined(JSON_HEDLEY_VERSION) - #undef JSON_HEDLEY_VERSION -#endif -#define JSON_HEDLEY_VERSION 14 - -#if defined(JSON_HEDLEY_STRINGIFY_EX) - #undef JSON_HEDLEY_STRINGIFY_EX -#endif -#define JSON_HEDLEY_STRINGIFY_EX(x) #x - -#if defined(JSON_HEDLEY_STRINGIFY) - #undef JSON_HEDLEY_STRINGIFY -#endif -#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) - -#if defined(JSON_HEDLEY_CONCAT_EX) - #undef JSON_HEDLEY_CONCAT_EX -#endif -#define JSON_HEDLEY_CONCAT_EX(a,b) a##b - -#if defined(JSON_HEDLEY_CONCAT) - #undef JSON_HEDLEY_CONCAT -#endif -#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) - -#if defined(JSON_HEDLEY_CONCAT3_EX) - #undef JSON_HEDLEY_CONCAT3_EX -#endif -#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c - -#if defined(JSON_HEDLEY_CONCAT3) - #undef JSON_HEDLEY_CONCAT3 -#endif -#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) - -#if defined(JSON_HEDLEY_VERSION_ENCODE) - #undef JSON_HEDLEY_VERSION_ENCODE -#endif -#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) - -#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) - #undef JSON_HEDLEY_VERSION_DECODE_MAJOR -#endif -#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) - -#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) - #undef JSON_HEDLEY_VERSION_DECODE_MINOR -#endif -#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) - -#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) - #undef JSON_HEDLEY_VERSION_DECODE_REVISION -#endif -#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) - -#if defined(JSON_HEDLEY_GNUC_VERSION) - #undef JSON_HEDLEY_GNUC_VERSION -#endif -#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) - #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#elif defined(__GNUC__) - #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) -#endif - -#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) - #undef JSON_HEDLEY_GNUC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_GNUC_VERSION) - #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_MSVC_VERSION) - #undef JSON_HEDLEY_MSVC_VERSION -#endif -#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) -#elif defined(_MSC_FULL_VER) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) -#elif defined(_MSC_VER) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) -#endif - -#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) - #undef JSON_HEDLEY_MSVC_VERSION_CHECK -#endif -#if !defined(JSON_HEDLEY_MSVC_VERSION) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) -#elif defined(_MSC_VER) && (_MSC_VER >= 1400) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) -#elif defined(_MSC_VER) && (_MSC_VER >= 1200) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) -#else - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) -#endif - -#if defined(JSON_HEDLEY_INTEL_VERSION) - #undef JSON_HEDLEY_INTEL_VERSION -#endif -#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) - #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) -#elif defined(__INTEL_COMPILER) && !defined(__ICL) - #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) -#endif - -#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) - #undef JSON_HEDLEY_INTEL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_INTEL_VERSION) - #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_INTEL_CL_VERSION) - #undef JSON_HEDLEY_INTEL_CL_VERSION -#endif -#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) - #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) -#endif - -#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) - #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_INTEL_CL_VERSION) - #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_PGI_VERSION) - #undef JSON_HEDLEY_PGI_VERSION -#endif -#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) - #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) -#endif - -#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) - #undef JSON_HEDLEY_PGI_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_PGI_VERSION) - #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_SUNPRO_VERSION) - #undef JSON_HEDLEY_SUNPRO_VERSION -#endif -#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) -#elif defined(__SUNPRO_C) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) -#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) -#elif defined(__SUNPRO_CC) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) -#endif - -#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) - #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_SUNPRO_VERSION) - #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) - #undef JSON_HEDLEY_EMSCRIPTEN_VERSION -#endif -#if defined(__EMSCRIPTEN__) - #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) -#endif - -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) - #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) - #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_ARM_VERSION) - #undef JSON_HEDLEY_ARM_VERSION -#endif -#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) - #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) -#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) - #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) -#endif - -#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) - #undef JSON_HEDLEY_ARM_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_ARM_VERSION) - #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_IBM_VERSION) - #undef JSON_HEDLEY_IBM_VERSION -#endif -#if defined(__ibmxl__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) -#elif defined(__xlC__) && defined(__xlC_ver__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) -#elif defined(__xlC__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) -#endif - -#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) - #undef JSON_HEDLEY_IBM_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_IBM_VERSION) - #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_VERSION) - #undef JSON_HEDLEY_TI_VERSION -#endif -#if \ - defined(__TI_COMPILER_VERSION__) && \ - ( \ - defined(__TMS470__) || defined(__TI_ARM__) || \ - defined(__MSP430__) || \ - defined(__TMS320C2000__) \ - ) -#if (__TI_COMPILER_VERSION__ >= 16000000) - #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif -#endif - -#if defined(JSON_HEDLEY_TI_VERSION_CHECK) - #undef JSON_HEDLEY_TI_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_VERSION) - #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL2000_VERSION) - #undef JSON_HEDLEY_TI_CL2000_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) - #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL2000_VERSION) - #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL430_VERSION) - #undef JSON_HEDLEY_TI_CL430_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) - #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL430_VERSION) - #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) - #undef JSON_HEDLEY_TI_ARMCL_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) - #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) - #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) - #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL6X_VERSION) - #undef JSON_HEDLEY_TI_CL6X_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) - #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL6X_VERSION) - #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL7X_VERSION) - #undef JSON_HEDLEY_TI_CL7X_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) - #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL7X_VERSION) - #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) - #undef JSON_HEDLEY_TI_CLPRU_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) - #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) - #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_CRAY_VERSION) - #undef JSON_HEDLEY_CRAY_VERSION -#endif -#if defined(_CRAYC) - #if defined(_RELEASE_PATCHLEVEL) - #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) - #else - #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) - #endif -#endif - -#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) - #undef JSON_HEDLEY_CRAY_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_CRAY_VERSION) - #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_IAR_VERSION) - #undef JSON_HEDLEY_IAR_VERSION -#endif -#if defined(__IAR_SYSTEMS_ICC__) - #if __VER__ > 1000 - #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) - #else - #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(VER / 100, __VER__ % 100, 0) - #endif -#endif - -#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) - #undef JSON_HEDLEY_IAR_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_IAR_VERSION) - #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TINYC_VERSION) - #undef JSON_HEDLEY_TINYC_VERSION -#endif -#if defined(__TINYC__) - #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) -#endif - -#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) - #undef JSON_HEDLEY_TINYC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TINYC_VERSION) - #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_DMC_VERSION) - #undef JSON_HEDLEY_DMC_VERSION -#endif -#if defined(__DMC__) - #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) -#endif - -#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) - #undef JSON_HEDLEY_DMC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_DMC_VERSION) - #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_COMPCERT_VERSION) - #undef JSON_HEDLEY_COMPCERT_VERSION -#endif -#if defined(__COMPCERT_VERSION__) - #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) -#endif - -#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) - #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_COMPCERT_VERSION) - #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_PELLES_VERSION) - #undef JSON_HEDLEY_PELLES_VERSION -#endif -#if defined(__POCC__) - #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) -#endif - -#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) - #undef JSON_HEDLEY_PELLES_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_PELLES_VERSION) - #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_GCC_VERSION) - #undef JSON_HEDLEY_GCC_VERSION -#endif -#if \ - defined(JSON_HEDLEY_GNUC_VERSION) && \ - !defined(__clang__) && \ - !defined(JSON_HEDLEY_INTEL_VERSION) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_ARM_VERSION) && \ - !defined(JSON_HEDLEY_TI_VERSION) && \ - !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ - !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ - !defined(__COMPCERT__) - #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION -#endif - -#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) - #undef JSON_HEDLEY_GCC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_GCC_VERSION) - #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_ATTRIBUTE -#endif -#if defined(__has_attribute) - #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) -#else - #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE -#endif -#if defined(__has_attribute) - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE -#endif -#if defined(__has_attribute) - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE -#endif -#if \ - defined(__has_cpp_attribute) && \ - defined(__cplusplus) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) - #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS -#endif -#if !defined(__cplusplus) || !defined(__has_cpp_attribute) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) -#elif \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_IAR_VERSION) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ - (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) -#else - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE -#endif -#if defined(__has_cpp_attribute) && defined(__cplusplus) - #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE -#endif -#if defined(__has_cpp_attribute) && defined(__cplusplus) - #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_BUILTIN) - #undef JSON_HEDLEY_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) -#else - #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) - #undef JSON_HEDLEY_GNUC_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) -#else - #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) - #undef JSON_HEDLEY_GCC_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) -#else - #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_FEATURE) - #undef JSON_HEDLEY_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) -#else - #define JSON_HEDLEY_HAS_FEATURE(feature) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) - #undef JSON_HEDLEY_GNUC_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) -#else - #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) - #undef JSON_HEDLEY_GCC_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) -#else - #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_EXTENSION) - #undef JSON_HEDLEY_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) -#else - #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) - #undef JSON_HEDLEY_GNUC_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) -#else - #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) - #undef JSON_HEDLEY_GCC_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) -#else - #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_WARNING) - #undef JSON_HEDLEY_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) -#else - #define JSON_HEDLEY_HAS_WARNING(warning) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) - #undef JSON_HEDLEY_GNUC_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) -#else - #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_WARNING) - #undef JSON_HEDLEY_GCC_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) -#else - #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - defined(__clang__) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) - #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_PRAGMA(value) __pragma(value) -#else - #define JSON_HEDLEY_PRAGMA(value) -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) - #undef JSON_HEDLEY_DIAGNOSTIC_PUSH -#endif -#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) - #undef JSON_HEDLEY_DIAGNOSTIC_POP -#endif -#if defined(__clang__) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) - #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) -#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#else - #define JSON_HEDLEY_DIAGNOSTIC_PUSH - #define JSON_HEDLEY_DIAGNOSTIC_POP -#endif - -/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for - HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ -#endif -#if defined(__cplusplus) -# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") -# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") -# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ - _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# endif -# else -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# endif -# endif -#endif -#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x -#endif - -#if defined(JSON_HEDLEY_CONST_CAST) - #undef JSON_HEDLEY_CONST_CAST -#endif -#if defined(__cplusplus) -# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) -#elif \ - JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ - ((T) (expr)); \ - JSON_HEDLEY_DIAGNOSTIC_POP \ - })) -#else -# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_REINTERPRET_CAST) - #undef JSON_HEDLEY_REINTERPRET_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) -#else - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_STATIC_CAST) - #undef JSON_HEDLEY_STATIC_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) -#else - #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_CPP_CAST) - #undef JSON_HEDLEY_CPP_CAST -#endif -#if defined(__cplusplus) -# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") -# define JSON_HEDLEY_CPP_CAST(T, expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ - ((T) (expr)) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) -# define JSON_HEDLEY_CPP_CAST(T, expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("diag_suppress=Pe137") \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) -# endif -#else -# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#endif - -#if defined(JSON_HEDLEY_DEPRECATED) - #undef JSON_HEDLEY_DEPRECATED -#endif -#if defined(JSON_HEDLEY_DEPRECATED_FOR) - #undef JSON_HEDLEY_DEPRECATED_FOR -#endif -#if \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) -#elif \ - JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) - #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) -#elif defined(__cplusplus) && (__cplusplus >= 201402L) - #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") -#else - #define JSON_HEDLEY_DEPRECATED(since) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) -#endif - -#if defined(JSON_HEDLEY_UNAVAILABLE) - #undef JSON_HEDLEY_UNAVAILABLE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) -#else - #define JSON_HEDLEY_UNAVAILABLE(available_since) -#endif - -#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) - #undef JSON_HEDLEY_WARN_UNUSED_RESULT -#endif -#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) - #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) -#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) -#elif defined(_Check_return_) /* SAL */ - #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ -#else - #define JSON_HEDLEY_WARN_UNUSED_RESULT - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) -#endif - -#if defined(JSON_HEDLEY_SENTINEL) - #undef JSON_HEDLEY_SENTINEL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) - #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) -#else - #define JSON_HEDLEY_SENTINEL(position) -#endif - -#if defined(JSON_HEDLEY_NO_RETURN) - #undef JSON_HEDLEY_NO_RETURN -#endif -#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_NO_RETURN __noreturn -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) -#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L - #define JSON_HEDLEY_NO_RETURN _Noreturn -#elif defined(__cplusplus) && (__cplusplus >= 201103L) - #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) - #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") -#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) - #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) - #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) -#else - #define JSON_HEDLEY_NO_RETURN -#endif - -#if defined(JSON_HEDLEY_NO_ESCAPE) - #undef JSON_HEDLEY_NO_ESCAPE -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) - #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) -#else - #define JSON_HEDLEY_NO_ESCAPE -#endif - -#if defined(JSON_HEDLEY_UNREACHABLE) - #undef JSON_HEDLEY_UNREACHABLE -#endif -#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) - #undef JSON_HEDLEY_UNREACHABLE_RETURN -#endif -#if defined(JSON_HEDLEY_ASSUME) - #undef JSON_HEDLEY_ASSUME -#endif -#if \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_ASSUME(expr) __assume(expr) -#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) - #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) -#elif \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) - #if defined(__cplusplus) - #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) - #else - #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) - #endif -#endif -#if \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) - #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() -#elif defined(JSON_HEDLEY_ASSUME) - #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) -#endif -#if !defined(JSON_HEDLEY_ASSUME) - #if defined(JSON_HEDLEY_UNREACHABLE) - #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) - #else - #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) - #endif -#endif -#if defined(JSON_HEDLEY_UNREACHABLE) - #if \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) - #else - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() - #endif -#else - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) -#endif -#if !defined(JSON_HEDLEY_UNREACHABLE) - #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) -#endif - -JSON_HEDLEY_DIAGNOSTIC_PUSH -#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") - #pragma clang diagnostic ignored "-Wpedantic" -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) - #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif -#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) - #if defined(__clang__) - #pragma clang diagnostic ignored "-Wvariadic-macros" - #elif defined(JSON_HEDLEY_GCC_VERSION) - #pragma GCC diagnostic ignored "-Wvariadic-macros" - #endif -#endif -#if defined(JSON_HEDLEY_NON_NULL) - #undef JSON_HEDLEY_NON_NULL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) - #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) -#else - #define JSON_HEDLEY_NON_NULL(...) -#endif -JSON_HEDLEY_DIAGNOSTIC_POP - -#if defined(JSON_HEDLEY_PRINTF_FORMAT) - #undef JSON_HEDLEY_PRINTF_FORMAT -#endif -#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) -#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) -#else - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) -#endif - -#if defined(JSON_HEDLEY_CONSTEXPR) - #undef JSON_HEDLEY_CONSTEXPR -#endif -#if defined(__cplusplus) - #if __cplusplus >= 201103L - #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) - #endif -#endif -#if !defined(JSON_HEDLEY_CONSTEXPR) - #define JSON_HEDLEY_CONSTEXPR -#endif - -#if defined(JSON_HEDLEY_PREDICT) - #undef JSON_HEDLEY_PREDICT -#endif -#if defined(JSON_HEDLEY_LIKELY) - #undef JSON_HEDLEY_LIKELY -#endif -#if defined(JSON_HEDLEY_UNLIKELY) - #undef JSON_HEDLEY_UNLIKELY -#endif -#if defined(JSON_HEDLEY_UNPREDICTABLE) - #undef JSON_HEDLEY_UNPREDICTABLE -#endif -#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) - #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) -#endif -#if \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) -# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) -# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) -# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) -#elif \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) -# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ - (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ - (__extension__ ({ \ - double hedley_probability_ = (probability); \ - ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ - })) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ - (__extension__ ({ \ - double hedley_probability_ = (probability); \ - ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ - })) -# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) -# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) -#else -# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) -# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) -# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) -#endif -#if !defined(JSON_HEDLEY_UNPREDICTABLE) - #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) -#endif - -#if defined(JSON_HEDLEY_MALLOC) - #undef JSON_HEDLEY_MALLOC -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_MALLOC __declspec(restrict) -#else - #define JSON_HEDLEY_MALLOC -#endif - -#if defined(JSON_HEDLEY_PURE) - #undef JSON_HEDLEY_PURE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) -# define JSON_HEDLEY_PURE __attribute__((__pure__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) -# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") -#elif defined(__cplusplus) && \ - ( \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ - ) -# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") -#else -# define JSON_HEDLEY_PURE -#endif - -#if defined(JSON_HEDLEY_CONST) - #undef JSON_HEDLEY_CONST -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_CONST __attribute__((__const__)) -#elif \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_CONST _Pragma("no_side_effect") -#else - #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE -#endif - -#if defined(JSON_HEDLEY_RESTRICT) - #undef JSON_HEDLEY_RESTRICT -#endif -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) - #define JSON_HEDLEY_RESTRICT restrict -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - defined(__clang__) - #define JSON_HEDLEY_RESTRICT __restrict -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) - #define JSON_HEDLEY_RESTRICT _Restrict -#else - #define JSON_HEDLEY_RESTRICT -#endif - -#if defined(JSON_HEDLEY_INLINE) - #undef JSON_HEDLEY_INLINE -#endif -#if \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - (defined(__cplusplus) && (__cplusplus >= 199711L)) - #define JSON_HEDLEY_INLINE inline -#elif \ - defined(JSON_HEDLEY_GCC_VERSION) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) - #define JSON_HEDLEY_INLINE __inline__ -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_INLINE __inline -#else - #define JSON_HEDLEY_INLINE -#endif - -#if defined(JSON_HEDLEY_ALWAYS_INLINE) - #undef JSON_HEDLEY_ALWAYS_INLINE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) -# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_ALWAYS_INLINE __forceinline -#elif defined(__cplusplus) && \ - ( \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ - ) -# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) -# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") -#else -# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE -#endif - -#if defined(JSON_HEDLEY_NEVER_INLINE) - #undef JSON_HEDLEY_NEVER_INLINE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") -#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) - #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) - #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) -#else - #define JSON_HEDLEY_NEVER_INLINE -#endif - -#if defined(JSON_HEDLEY_PRIVATE) - #undef JSON_HEDLEY_PRIVATE -#endif -#if defined(JSON_HEDLEY_PUBLIC) - #undef JSON_HEDLEY_PUBLIC -#endif -#if defined(JSON_HEDLEY_IMPORT) - #undef JSON_HEDLEY_IMPORT -#endif -#if defined(_WIN32) || defined(__CYGWIN__) -# define JSON_HEDLEY_PRIVATE -# define JSON_HEDLEY_PUBLIC __declspec(dllexport) -# define JSON_HEDLEY_IMPORT __declspec(dllimport) -#else -# if \ - JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - ( \ - defined(__TI_EABI__) && \ - ( \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ - ) \ - ) -# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) -# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) -# else -# define JSON_HEDLEY_PRIVATE -# define JSON_HEDLEY_PUBLIC -# endif -# define JSON_HEDLEY_IMPORT extern -#endif - -#if defined(JSON_HEDLEY_NO_THROW) - #undef JSON_HEDLEY_NO_THROW -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) - #define JSON_HEDLEY_NO_THROW __declspec(nothrow) -#else - #define JSON_HEDLEY_NO_THROW -#endif - -#if defined(JSON_HEDLEY_FALL_THROUGH) - #undef JSON_HEDLEY_FALL_THROUGH -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) - #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) - #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) - #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) -#elif defined(__fallthrough) /* SAL */ - #define JSON_HEDLEY_FALL_THROUGH __fallthrough -#else - #define JSON_HEDLEY_FALL_THROUGH -#endif - -#if defined(JSON_HEDLEY_RETURNS_NON_NULL) - #undef JSON_HEDLEY_RETURNS_NON_NULL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) - #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) -#elif defined(_Ret_notnull_) /* SAL */ - #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ -#else - #define JSON_HEDLEY_RETURNS_NON_NULL -#endif - -#if defined(JSON_HEDLEY_ARRAY_PARAM) - #undef JSON_HEDLEY_ARRAY_PARAM -#endif -#if \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - !defined(__STDC_NO_VLA__) && \ - !defined(__cplusplus) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_TINYC_VERSION) - #define JSON_HEDLEY_ARRAY_PARAM(name) (name) -#else - #define JSON_HEDLEY_ARRAY_PARAM(name) -#endif - -#if defined(JSON_HEDLEY_IS_CONSTANT) - #undef JSON_HEDLEY_IS_CONSTANT -#endif -#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) - #undef JSON_HEDLEY_REQUIRE_CONSTEXPR -#endif -/* JSON_HEDLEY_IS_CONSTEXPR_ is for - HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ -#if defined(JSON_HEDLEY_IS_CONSTEXPR_) - #undef JSON_HEDLEY_IS_CONSTEXPR_ -#endif -#if \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) - #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) -#endif -#if !defined(__cplusplus) -# if \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) -#if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) -#else - #include - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) -#endif -# elif \ - ( \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ - !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_IAR_VERSION)) || \ - JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) -#if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) -#else - #include - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) -#endif -# elif \ - defined(JSON_HEDLEY_GCC_VERSION) || \ - defined(JSON_HEDLEY_INTEL_VERSION) || \ - defined(JSON_HEDLEY_TINYC_VERSION) || \ - defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ - defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ - defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ - defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ - defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ - defined(__clang__) -# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ - sizeof(void) != \ - sizeof(*( \ - 1 ? \ - ((void*) ((expr) * 0L) ) : \ -((struct { char v[sizeof(void) * 2]; } *) 1) \ - ) \ - ) \ - ) -# endif -#endif -#if defined(JSON_HEDLEY_IS_CONSTEXPR_) - #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) - #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) -#else - #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) (0) - #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) -#endif - -#if defined(JSON_HEDLEY_BEGIN_C_DECLS) - #undef JSON_HEDLEY_BEGIN_C_DECLS -#endif -#if defined(JSON_HEDLEY_END_C_DECLS) - #undef JSON_HEDLEY_END_C_DECLS -#endif -#if defined(JSON_HEDLEY_C_DECL) - #undef JSON_HEDLEY_C_DECL -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { - #define JSON_HEDLEY_END_C_DECLS } - #define JSON_HEDLEY_C_DECL extern "C" -#else - #define JSON_HEDLEY_BEGIN_C_DECLS - #define JSON_HEDLEY_END_C_DECLS - #define JSON_HEDLEY_C_DECL -#endif - -#if defined(JSON_HEDLEY_STATIC_ASSERT) - #undef JSON_HEDLEY_STATIC_ASSERT -#endif -#if \ - !defined(__cplusplus) && ( \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ - (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - defined(_Static_assert) \ - ) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) -#elif \ - (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) -#else -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) -#endif - -#if defined(JSON_HEDLEY_NULL) - #undef JSON_HEDLEY_NULL -#endif -#if defined(__cplusplus) - #if __cplusplus >= 201103L - #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) - #elif defined(NULL) - #define JSON_HEDLEY_NULL NULL - #else - #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) - #endif -#elif defined(NULL) - #define JSON_HEDLEY_NULL NULL -#else - #define JSON_HEDLEY_NULL ((void*) 0) -#endif - -#if defined(JSON_HEDLEY_MESSAGE) - #undef JSON_HEDLEY_MESSAGE -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") -# define JSON_HEDLEY_MESSAGE(msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ - JSON_HEDLEY_PRAGMA(message msg) \ - JSON_HEDLEY_DIAGNOSTIC_POP -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) -#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#else -# define JSON_HEDLEY_MESSAGE(msg) -#endif - -#if defined(JSON_HEDLEY_WARNING) - #undef JSON_HEDLEY_WARNING -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") -# define JSON_HEDLEY_WARNING(msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ - JSON_HEDLEY_PRAGMA(clang warning msg) \ - JSON_HEDLEY_DIAGNOSTIC_POP -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#else -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) -#endif - -#if defined(JSON_HEDLEY_REQUIRE) - #undef JSON_HEDLEY_REQUIRE -#endif -#if defined(JSON_HEDLEY_REQUIRE_MSG) - #undef JSON_HEDLEY_REQUIRE_MSG -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) -# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") -# define JSON_HEDLEY_REQUIRE(expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((diagnose_if(!(expr), #expr, "error"))) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((diagnose_if(!(expr), msg, "error"))) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) -# endif -#else -# define JSON_HEDLEY_REQUIRE(expr) -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) -#endif - -#if defined(JSON_HEDLEY_FLAGS) - #undef JSON_HEDLEY_FLAGS -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) - #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) -#else - #define JSON_HEDLEY_FLAGS -#endif - -#if defined(JSON_HEDLEY_FLAGS_CAST) - #undef JSON_HEDLEY_FLAGS_CAST -#endif -#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) -# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("warning(disable:188)") \ - ((T) (expr)); \ - JSON_HEDLEY_DIAGNOSTIC_POP \ - })) -#else -# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) -#endif - -#if defined(JSON_HEDLEY_EMPTY_BASES) - #undef JSON_HEDLEY_EMPTY_BASES -#endif -#if \ - (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) -#else - #define JSON_HEDLEY_EMPTY_BASES -#endif - -/* Remaining macros are deprecated. */ - -#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) - #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK -#endif -#if defined(__clang__) - #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) -#else - #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) - #undef JSON_HEDLEY_CLANG_HAS_BUILTIN -#endif -#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) - -#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) - #undef JSON_HEDLEY_CLANG_HAS_FEATURE -#endif -#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) - -#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) - #undef JSON_HEDLEY_CLANG_HAS_EXTENSION -#endif -#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) - -#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) - #undef JSON_HEDLEY_CLANG_HAS_WARNING -#endif -#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) - -#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ - - -// This file contains all internal macro definitions -// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them - -// exclude unsupported compilers -#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) - #if defined(__clang__) - #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 - #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) - #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 - #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #endif -#endif - -// C++ language standard detection -#if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) - #define JSON_HAS_CPP_20 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 -#elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 -#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) - #define JSON_HAS_CPP_14 -#endif - -// disable float-equal warnings on GCC/clang -#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -// disable documentation warnings on clang -#if defined(__clang__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdocumentation" -#endif - -// allow to disable exceptions -#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) - #define JSON_THROW(exception) throw exception - #define JSON_TRY try - #define JSON_CATCH(exception) catch(exception) - #define JSON_INTERNAL_CATCH(exception) catch(exception) -#else - #include - #define JSON_THROW(exception) std::abort() - #define JSON_TRY if(true) - #define JSON_CATCH(exception) if(false) - #define JSON_INTERNAL_CATCH(exception) if(false) -#endif - -// override exception macros -#if defined(JSON_THROW_USER) - #undef JSON_THROW - #define JSON_THROW JSON_THROW_USER -#endif -#if defined(JSON_TRY_USER) - #undef JSON_TRY - #define JSON_TRY JSON_TRY_USER -#endif -#if defined(JSON_CATCH_USER) - #undef JSON_CATCH - #define JSON_CATCH JSON_CATCH_USER - #undef JSON_INTERNAL_CATCH - #define JSON_INTERNAL_CATCH JSON_CATCH_USER -#endif -#if defined(JSON_INTERNAL_CATCH_USER) - #undef JSON_INTERNAL_CATCH - #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER -#endif - -// allow to override assert -#if !defined(JSON_ASSERT) - #include // assert - #define JSON_ASSERT(x) assert(x) -#endif - -// allow to access some private functions (needed by the test suite) -#if defined(JSON_TESTS_PRIVATE) - #define JSON_PRIVATE_UNLESS_TESTED public -#else - #define JSON_PRIVATE_UNLESS_TESTED private -#endif - -/*! -@brief macro to briefly define a mapping between an enum and JSON -@def NLOHMANN_JSON_SERIALIZE_ENUM -@since version 3.4.0 -*/ -#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ - template \ - inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [e](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.first == e; \ - }); \ - j = ((it != std::end(m)) ? it : std::begin(m))->second; \ - } \ - template \ - inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [&j](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.second == j; \ - }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ - } - -// Ugly macros to avoid uglier copy-paste when specializing basic_json. They -// may be removed in the future once the class is split. - -#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ - template class ObjectType, \ - template class ArrayType, \ - class StringType, class BooleanType, class NumberIntegerType, \ - class NumberUnsignedType, class NumberFloatType, \ - template class AllocatorType, \ - template class JSONSerializer, \ - class BinaryType> - -#define NLOHMANN_BASIC_JSON_TPL \ - basic_json - -// Macros to simplify conversion from/to types - -#define NLOHMANN_JSON_EXPAND( x ) x -#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME -#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ - NLOHMANN_JSON_PASTE64, \ - NLOHMANN_JSON_PASTE63, \ - NLOHMANN_JSON_PASTE62, \ - NLOHMANN_JSON_PASTE61, \ - NLOHMANN_JSON_PASTE60, \ - NLOHMANN_JSON_PASTE59, \ - NLOHMANN_JSON_PASTE58, \ - NLOHMANN_JSON_PASTE57, \ - NLOHMANN_JSON_PASTE56, \ - NLOHMANN_JSON_PASTE55, \ - NLOHMANN_JSON_PASTE54, \ - NLOHMANN_JSON_PASTE53, \ - NLOHMANN_JSON_PASTE52, \ - NLOHMANN_JSON_PASTE51, \ - NLOHMANN_JSON_PASTE50, \ - NLOHMANN_JSON_PASTE49, \ - NLOHMANN_JSON_PASTE48, \ - NLOHMANN_JSON_PASTE47, \ - NLOHMANN_JSON_PASTE46, \ - NLOHMANN_JSON_PASTE45, \ - NLOHMANN_JSON_PASTE44, \ - NLOHMANN_JSON_PASTE43, \ - NLOHMANN_JSON_PASTE42, \ - NLOHMANN_JSON_PASTE41, \ - NLOHMANN_JSON_PASTE40, \ - NLOHMANN_JSON_PASTE39, \ - NLOHMANN_JSON_PASTE38, \ - NLOHMANN_JSON_PASTE37, \ - NLOHMANN_JSON_PASTE36, \ - NLOHMANN_JSON_PASTE35, \ - NLOHMANN_JSON_PASTE34, \ - NLOHMANN_JSON_PASTE33, \ - NLOHMANN_JSON_PASTE32, \ - NLOHMANN_JSON_PASTE31, \ - NLOHMANN_JSON_PASTE30, \ - NLOHMANN_JSON_PASTE29, \ - NLOHMANN_JSON_PASTE28, \ - NLOHMANN_JSON_PASTE27, \ - NLOHMANN_JSON_PASTE26, \ - NLOHMANN_JSON_PASTE25, \ - NLOHMANN_JSON_PASTE24, \ - NLOHMANN_JSON_PASTE23, \ - NLOHMANN_JSON_PASTE22, \ - NLOHMANN_JSON_PASTE21, \ - NLOHMANN_JSON_PASTE20, \ - NLOHMANN_JSON_PASTE19, \ - NLOHMANN_JSON_PASTE18, \ - NLOHMANN_JSON_PASTE17, \ - NLOHMANN_JSON_PASTE16, \ - NLOHMANN_JSON_PASTE15, \ - NLOHMANN_JSON_PASTE14, \ - NLOHMANN_JSON_PASTE13, \ - NLOHMANN_JSON_PASTE12, \ - NLOHMANN_JSON_PASTE11, \ - NLOHMANN_JSON_PASTE10, \ - NLOHMANN_JSON_PASTE9, \ - NLOHMANN_JSON_PASTE8, \ - NLOHMANN_JSON_PASTE7, \ - NLOHMANN_JSON_PASTE6, \ - NLOHMANN_JSON_PASTE5, \ - NLOHMANN_JSON_PASTE4, \ - NLOHMANN_JSON_PASTE3, \ - NLOHMANN_JSON_PASTE2, \ - NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) -#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) -#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) -#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) -#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) -#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) -#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) -#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) -#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) -#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) -#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) -#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) -#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) -#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) -#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) -#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) -#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) -#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) -#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) -#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) -#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) -#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) -#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) -#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) -#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) -#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) -#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) -#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) -#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) -#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) -#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) -#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) -#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) -#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) -#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) -#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) -#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) -#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) -#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) -#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) -#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) -#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) -#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) -#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) -#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) -#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) -#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) -#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) -#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) -#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) -#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) -#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) -#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) -#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) -#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) -#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) -#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) -#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) -#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) -#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) -#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) -#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) -#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) - -#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; -#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_INTRUSIVE -@since version 3.9.0 -*/ -#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ - friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE -@since version 3.9.0 -*/ -#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ - inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } - -#ifndef JSON_USE_IMPLICIT_CONVERSIONS - #define JSON_USE_IMPLICIT_CONVERSIONS 1 -#endif - -#if JSON_USE_IMPLICIT_CONVERSIONS - #define JSON_EXPLICIT -#else - #define JSON_EXPLICIT explicit -#endif - - -namespace nlohmann -{ -namespace detail -{ -//////////////// -// exceptions // -//////////////// - -/*! -@brief general exception of the @ref basic_json class - -This class is an extension of `std::exception` objects with a member @a id for -exception ids. It is used as the base class for all exceptions thrown by the -@ref basic_json class. This class can hence be used as "wildcard" to catch -exceptions. - -Subclasses: -- @ref parse_error for exceptions indicating a parse error -- @ref invalid_iterator for exceptions indicating errors with iterators -- @ref type_error for exceptions indicating executing a member function with - a wrong type -- @ref out_of_range for exceptions indicating access out of the defined range -- @ref other_error for exceptions indicating other library errors - -@internal -@note To have nothrow-copy-constructible exceptions, we internally use - `std::runtime_error` which can cope with arbitrary-length error messages. - Intermediate strings are built with static functions and then passed to - the actual constructor. -@endinternal - -@liveexample{The following code shows how arbitrary library exceptions can be -caught.,exception} - -@since version 3.0.0 -*/ -class exception : public std::exception -{ - public: - /// returns the explanatory string - JSON_HEDLEY_RETURNS_NON_NULL - const char* what() const noexcept override - { - return m.what(); - } - - /// the id of the exception - const int id; - - protected: - JSON_HEDLEY_NON_NULL(3) - exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} - - static std::string name(const std::string& ename, int id_) - { - return "[json.exception." + ename + "." + std::to_string(id_) + "] "; - } - - private: - /// an exception object as storage for error messages - std::runtime_error m; -}; - -/*! -@brief exception indicating a parse error - -This exception is thrown by the library when a parse error occurs. Parse errors -can occur during the deserialization of JSON text, CBOR, MessagePack, as well -as when using JSON Patch. - -Member @a byte holds the byte index of the last read character in the input -file. - -Exceptions have ids 1xx. - -name / id | example message | description ------------------------------- | --------------- | ------------------------- -json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. -json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. -json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. -json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. -json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. -json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. -json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. -json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. -json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. -json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. -json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. -json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. -json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet). -json.exception.parse_error.115 | parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A | A UBJSON high-precision number could not be parsed. - -@note For an input with n bytes, 1 is the index of the first character and n+1 - is the index of the terminating null byte or the end of file. This also - holds true when reading a byte vector (CBOR or MessagePack). - -@liveexample{The following code shows how a `parse_error` exception can be -caught.,parse_error} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class parse_error : public exception -{ - public: - /*! - @brief create a parse error exception - @param[in] id_ the id of the exception - @param[in] pos the position where the error occurred (or with - chars_read_total=0 if the position cannot be - determined) - @param[in] what_arg the explanatory string - @return parse_error object - */ - static parse_error create(int id_, const position_t& pos, const std::string& what_arg) - { - std::string w = exception::name("parse_error", id_) + "parse error" + - position_string(pos) + ": " + what_arg; - return parse_error(id_, pos.chars_read_total, w.c_str()); - } - - static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) - { - std::string w = exception::name("parse_error", id_) + "parse error" + - (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + - ": " + what_arg; - return parse_error(id_, byte_, w.c_str()); - } - - /*! - @brief byte index of the parse error - - The byte index of the last read character in the input file. - - @note For an input with n bytes, 1 is the index of the first character and - n+1 is the index of the terminating null byte or the end of file. - This also holds true when reading a byte vector (CBOR or MessagePack). - */ - const std::size_t byte; - - private: - parse_error(int id_, std::size_t byte_, const char* what_arg) - : exception(id_, what_arg), byte(byte_) {} - - static std::string position_string(const position_t& pos) - { - return " at line " + std::to_string(pos.lines_read + 1) + - ", column " + std::to_string(pos.chars_read_current_line); - } -}; - -/*! -@brief exception indicating errors with iterators - -This exception is thrown if iterators passed to a library function do not match -the expected semantics. - -Exceptions have ids 2xx. - -name / id | example message | description ------------------------------------ | --------------- | ------------------------- -json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. -json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. -json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. -json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. -json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. -json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. -json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. -json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. -json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered. -json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). - -@liveexample{The following code shows how an `invalid_iterator` exception can be -caught.,invalid_iterator} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class invalid_iterator : public exception -{ - public: - static invalid_iterator create(int id_, const std::string& what_arg) - { - std::string w = exception::name("invalid_iterator", id_) + what_arg; - return invalid_iterator(id_, w.c_str()); - } - - private: - JSON_HEDLEY_NON_NULL(3) - invalid_iterator(int id_, const char* what_arg) - : exception(id_, what_arg) {} -}; - -/*! -@brief exception indicating executing a member function with a wrong type - -This exception is thrown in case of a type error; that is, a library function is -executed on a JSON value whose type does not match the expected semantics. - -Exceptions have ids 3xx. - -name / id | example message | description ------------------------------ | --------------- | ------------------------- -json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. -json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. -json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &. -json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. -json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. -json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. -json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. -json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. -json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. -json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. -json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. -json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types. -json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. -json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. -json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. -json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. | -json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) | - -@liveexample{The following code shows how a `type_error` exception can be -caught.,type_error} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class type_error : public exception -{ - public: - static type_error create(int id_, const std::string& what_arg) - { - std::string w = exception::name("type_error", id_) + what_arg; - return type_error(id_, w.c_str()); - } - - private: - JSON_HEDLEY_NON_NULL(3) - type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; - -/*! -@brief exception indicating access out of the defined range - -This exception is thrown in case a library function is called on an input -parameter that exceeds the expected range, for instance in case of array -indices or nonexisting object keys. - -Exceptions have ids 4xx. - -name / id | example message | description -------------------------------- | --------------- | ------------------------- -json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. -json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. -json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. -json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. -json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. -json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. -json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. (until version 3.8.0) | -json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | -json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | - -@liveexample{The following code shows how an `out_of_range` exception can be -caught.,out_of_range} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class out_of_range : public exception -{ - public: - static out_of_range create(int id_, const std::string& what_arg) - { - std::string w = exception::name("out_of_range", id_) + what_arg; - return out_of_range(id_, w.c_str()); - } - - private: - JSON_HEDLEY_NON_NULL(3) - out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; - -/*! -@brief exception indicating other library errors - -This exception is thrown in case of errors that cannot be classified with the -other exception types. - -Exceptions have ids 5xx. - -name / id | example message | description ------------------------------- | --------------- | ------------------------- -json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range - -@liveexample{The following code shows how an `other_error` exception can be -caught.,other_error} - -@since version 3.0.0 -*/ -class other_error : public exception -{ - public: - static other_error create(int id_, const std::string& what_arg) - { - std::string w = exception::name("other_error", id_) + what_arg; - return other_error(id_, w.c_str()); - } - - private: - JSON_HEDLEY_NON_NULL(3) - other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - - -#include // size_t -#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type - -namespace nlohmann -{ -namespace detail -{ -// alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; - -template -using uncvref_t = typename std::remove_cv::type>::type; - -// implementation of C++14 index_sequence and affiliates -// source: https://stackoverflow.com/a/32223343 -template -struct index_sequence -{ - using type = index_sequence; - using value_type = std::size_t; - static constexpr std::size_t size() noexcept - { - return sizeof...(Ints); - } -}; - -template -struct merge_and_renumber; - -template -struct merge_and_renumber, index_sequence> - : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; - -template -struct make_index_sequence - : merge_and_renumber < typename make_index_sequence < N / 2 >::type, - typename make_index_sequence < N - N / 2 >::type > {}; - -template<> struct make_index_sequence<0> : index_sequence<> {}; -template<> struct make_index_sequence<1> : index_sequence<0> {}; - -template -using index_sequence_for = make_index_sequence; - -// dispatch utility (taken from ranges-v3) -template struct priority_tag : priority_tag < N - 1 > {}; -template<> struct priority_tag<0> {}; - -// taken from ranges-v3 -template -struct static_const -{ - static constexpr T value{}; -}; - -template -constexpr T static_const::value; -} // namespace detail -} // namespace nlohmann - -// #include - - -#include // numeric_limits -#include // false_type, is_constructible, is_integral, is_same, true_type -#include // declval - -// #include - - -#include // random_access_iterator_tag - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template struct make_void -{ - using type = void; -}; -template using void_t = typename make_void::type; -} // namespace detail -} // namespace nlohmann - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template -struct iterator_types {}; - -template -struct iterator_types < - It, - void_t> -{ - using difference_type = typename It::difference_type; - using value_type = typename It::value_type; - using pointer = typename It::pointer; - using reference = typename It::reference; - using iterator_category = typename It::iterator_category; -}; - -// This is required as some compilers implement std::iterator_traits in a way that -// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. -template -struct iterator_traits -{ -}; - -template -struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> - : iterator_types -{ -}; - -template -struct iterator_traits::value>> -{ - using iterator_category = std::random_access_iterator_tag; - using value_type = T; - using difference_type = ptrdiff_t; - using pointer = T*; - using reference = T&; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - -// #include - - -#include - -// #include - - -// https://en.cppreference.com/w/cpp/experimental/is_detected -namespace nlohmann -{ -namespace detail -{ -struct nonesuch -{ - nonesuch() = delete; - ~nonesuch() = delete; - nonesuch(nonesuch const&) = delete; - nonesuch(nonesuch const&&) = delete; - void operator=(nonesuch const&) = delete; - void operator=(nonesuch&&) = delete; -}; - -template class Op, - class... Args> -struct detector -{ - using value_t = std::false_type; - using type = Default; -}; - -template class Op, class... Args> -struct detector>, Op, Args...> -{ - using value_t = std::true_type; - using type = Op; -}; - -template class Op, class... Args> -using is_detected = typename detector::value_t; - -template class Op, class... Args> -using detected_t = typename detector::type; - -template class Op, class... Args> -using detected_or = detector; - -template class Op, class... Args> -using detected_or_t = typename detected_or::type; - -template class Op, class... Args> -using is_detected_exact = std::is_same>; - -template class Op, class... Args> -using is_detected_convertible = - std::is_convertible, To>; -} // namespace detail -} // namespace nlohmann - -// #include -#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ -#define INCLUDE_NLOHMANN_JSON_FWD_HPP_ - -#include // int64_t, uint64_t -#include // map -#include // allocator -#include // string -#include // vector - -/*! -@brief namespace for Niels Lohmann -@see https://github.com/nlohmann -@since version 1.0.0 -*/ -namespace nlohmann -{ -/*! -@brief default JSONSerializer template argument - -This serializer ignores the template arguments and uses ADL -([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) -for serialization. -*/ -template -struct adl_serializer; - -template class ObjectType = - std::map, - template class ArrayType = std::vector, - class StringType = std::string, class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer, - class BinaryType = std::vector> -class basic_json; - -/*! -@brief JSON Pointer - -A JSON pointer defines a string syntax for identifying a specific value -within a JSON document. It can be used with functions `at` and -`operator[]`. Furthermore, JSON pointers are the base for JSON patches. - -@sa [RFC 6901](https://tools.ietf.org/html/rfc6901) - -@since version 2.0.0 -*/ -template -class json_pointer; - -/*! -@brief default JSON class - -This type is the default specialization of the @ref basic_json class which -uses the standard template types. - -@since version 1.0.0 -*/ -using json = basic_json<>; - -template -struct ordered_map; - -/*! -@brief ordered JSON class - -This type preserves the insertion order of object keys. - -@since version 3.9.0 -*/ -using ordered_json = basic_json; - -} // namespace nlohmann - -#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ - - -namespace nlohmann -{ -/*! -@brief detail namespace with internal helper functions - -This namespace collects functions that should not be exposed, -implementations of some @ref basic_json methods, and meta-programming helpers. - -@since version 2.1.0 -*/ -namespace detail -{ -///////////// -// helpers // -///////////// - -// Note to maintainers: -// -// Every trait in this file expects a non CV-qualified type. -// The only exceptions are in the 'aliases for detected' section -// (i.e. those of the form: decltype(T::member_function(std::declval()))) -// -// In this case, T has to be properly CV-qualified to constraint the function arguments -// (e.g. to_json(BasicJsonType&, const T&)) - -template struct is_basic_json : std::false_type {}; - -NLOHMANN_BASIC_JSON_TPL_DECLARATION -struct is_basic_json : std::true_type {}; - -////////////////////// -// json_ref helpers // -////////////////////// - -template -class json_ref; - -template -struct is_json_ref : std::false_type {}; - -template -struct is_json_ref> : std::true_type {}; - -////////////////////////// -// aliases for detected // -////////////////////////// - -template -using mapped_type_t = typename T::mapped_type; - -template -using key_type_t = typename T::key_type; - -template -using value_type_t = typename T::value_type; - -template -using difference_type_t = typename T::difference_type; - -template -using pointer_t = typename T::pointer; - -template -using reference_t = typename T::reference; - -template -using iterator_category_t = typename T::iterator_category; - -template -using iterator_t = typename T::iterator; - -template -using to_json_function = decltype(T::to_json(std::declval()...)); - -template -using from_json_function = decltype(T::from_json(std::declval()...)); - -template -using get_template_function = decltype(std::declval().template get()); - -// trait checking if JSONSerializer::from_json(json const&, udt&) exists -template -struct has_from_json : std::false_type {}; - -// trait checking if j.get is valid -// use this trait instead of std::is_constructible or std::is_convertible, -// both rely on, or make use of implicit conversions, and thus fail when T -// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) -template -struct is_getable -{ - static constexpr bool value = is_detected::value; -}; - -template -struct has_from_json < BasicJsonType, T, - enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -// This trait checks if JSONSerializer::from_json(json const&) exists -// this overload is used for non-default-constructible user-defined-types -template -struct has_non_default_from_json : std::false_type {}; - -template -struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -// This trait checks if BasicJsonType::json_serializer::to_json exists -// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. -template -struct has_to_json : std::false_type {}; - -template -struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - - -/////////////////// -// is_ functions // -/////////////////// - -template -struct is_iterator_traits : std::false_type {}; - -template -struct is_iterator_traits> -{ - private: - using traits = iterator_traits; - - public: - static constexpr auto value = - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value; -}; - -// source: https://stackoverflow.com/a/37193089/4116453 - -template -struct is_complete_type : std::false_type {}; - -template -struct is_complete_type : std::true_type {}; - -template -struct is_compatible_object_type_impl : std::false_type {}; - -template -struct is_compatible_object_type_impl < - BasicJsonType, CompatibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - - using object_t = typename BasicJsonType::object_t; - - // macOS's is_constructible does not play well with nonesuch... - static constexpr bool value = - std::is_constructible::value && - std::is_constructible::value; -}; - -template -struct is_compatible_object_type - : is_compatible_object_type_impl {}; - -template -struct is_constructible_object_type_impl : std::false_type {}; - -template -struct is_constructible_object_type_impl < - BasicJsonType, ConstructibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - using object_t = typename BasicJsonType::object_t; - - static constexpr bool value = - (std::is_default_constructible::value && - (std::is_move_assignable::value || - std::is_copy_assignable::value) && - (std::is_constructible::value && - std::is_same < - typename object_t::mapped_type, - typename ConstructibleObjectType::mapped_type >::value)) || - (has_from_json::value || - has_non_default_from_json < - BasicJsonType, - typename ConstructibleObjectType::mapped_type >::value); -}; - -template -struct is_constructible_object_type - : is_constructible_object_type_impl {}; - -template -struct is_compatible_string_type_impl : std::false_type {}; - -template -struct is_compatible_string_type_impl < - BasicJsonType, CompatibleStringType, - enable_if_t::value >> -{ - static constexpr auto value = - std::is_constructible::value; -}; - -template -struct is_compatible_string_type - : is_compatible_string_type_impl {}; - -template -struct is_constructible_string_type_impl : std::false_type {}; - -template -struct is_constructible_string_type_impl < - BasicJsonType, ConstructibleStringType, - enable_if_t::value >> -{ - static constexpr auto value = - std::is_constructible::value; -}; - -template -struct is_constructible_string_type - : is_constructible_string_type_impl {}; - -template -struct is_compatible_array_type_impl : std::false_type {}; - -template -struct is_compatible_array_type_impl < - BasicJsonType, CompatibleArrayType, - enable_if_t < is_detected::value&& - is_detected::value&& -// This is needed because json_reverse_iterator has a ::iterator type... -// Therefore it is detected as a CompatibleArrayType. -// The real fix would be to have an Iterable concept. - !is_iterator_traits < - iterator_traits>::value >> -{ - static constexpr bool value = - std::is_constructible::value; -}; - -template -struct is_compatible_array_type - : is_compatible_array_type_impl {}; - -template -struct is_constructible_array_type_impl : std::false_type {}; - -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t::value >> - : std::true_type {}; - -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t < !std::is_same::value&& - std::is_default_constructible::value&& -(std::is_move_assignable::value || - std::is_copy_assignable::value)&& -is_detected::value&& -is_detected::value&& -is_complete_type < -detected_t>::value >> -{ - static constexpr bool value = - // This is needed because json_reverse_iterator has a ::iterator type, - // furthermore, std::back_insert_iterator (and other iterators) have a - // base class `iterator`... Therefore it is detected as a - // ConstructibleArrayType. The real fix would be to have an Iterable - // concept. - !is_iterator_traits>::value && - - (std::is_same::value || - has_from_json::value || - has_non_default_from_json < - BasicJsonType, typename ConstructibleArrayType::value_type >::value); -}; - -template -struct is_constructible_array_type - : is_constructible_array_type_impl {}; - -template -struct is_compatible_integer_type_impl : std::false_type {}; - -template -struct is_compatible_integer_type_impl < - RealIntegerType, CompatibleNumberIntegerType, - enable_if_t < std::is_integral::value&& - std::is_integral::value&& - !std::is_same::value >> -{ - // is there an assert somewhere on overflows? - using RealLimits = std::numeric_limits; - using CompatibleLimits = std::numeric_limits; - - static constexpr auto value = - std::is_constructible::value && - CompatibleLimits::is_integer && - RealLimits::is_signed == CompatibleLimits::is_signed; -}; - -template -struct is_compatible_integer_type - : is_compatible_integer_type_impl {}; - -template -struct is_compatible_type_impl: std::false_type {}; - -template -struct is_compatible_type_impl < - BasicJsonType, CompatibleType, - enable_if_t::value >> -{ - static constexpr bool value = - has_to_json::value; -}; - -template -struct is_compatible_type - : is_compatible_type_impl {}; - -// https://en.cppreference.com/w/cpp/types/conjunction -template struct conjunction : std::true_type { }; -template struct conjunction : B1 { }; -template -struct conjunction -: std::conditional, B1>::type {}; - -template -struct is_constructible_tuple : std::false_type {}; - -template -struct is_constructible_tuple> : conjunction...> {}; -} // namespace detail -} // namespace nlohmann - -// #include - - -#include // array -#include // size_t -#include // uint8_t -#include // string - -namespace nlohmann -{ -namespace detail -{ -/////////////////////////// -// JSON type enumeration // -/////////////////////////// - -/*! -@brief the JSON type enumeration - -This enumeration collects the different JSON types. It is internally used to -distinguish the stored values, and the functions @ref basic_json::is_null(), -@ref basic_json::is_object(), @ref basic_json::is_array(), -@ref basic_json::is_string(), @ref basic_json::is_boolean(), -@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), -@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), -@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and -@ref basic_json::is_structured() rely on it. - -@note There are three enumeration entries (number_integer, number_unsigned, and -number_float), because the library distinguishes these three types for numbers: -@ref basic_json::number_unsigned_t is used for unsigned integers, -@ref basic_json::number_integer_t is used for signed integers, and -@ref basic_json::number_float_t is used for floating-point numbers or to -approximate integers which do not fit in the limits of their respective type. - -@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON -value with the default value for a given type - -@since version 1.0.0 -*/ -enum class value_t : std::uint8_t -{ - null, ///< null value - object, ///< object (unordered set of name/value pairs) - array, ///< array (ordered collection of values) - string, ///< string value - boolean, ///< boolean value - number_integer, ///< number value (signed integer) - number_unsigned, ///< number value (unsigned integer) - number_float, ///< number value (floating-point) - binary, ///< binary array (ordered collection of bytes) - discarded ///< discarded by the parser callback function -}; - -/*! -@brief comparison operator for JSON types - -Returns an ordering that is similar to Python: -- order: null < boolean < number < object < array < string < binary -- furthermore, each type is not smaller than itself -- discarded values are not comparable -- binary is represented as a b"" string in python and directly comparable to a - string; however, making a binary array directly comparable with a string would - be surprising behavior in a JSON file. - -@since version 1.0.0 -*/ -inline bool operator<(const value_t lhs, const value_t rhs) noexcept -{ - static constexpr std::array order = {{ - 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, - 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, - 6 /* binary */ - } - }; - - const auto l_index = static_cast(lhs); - const auto r_index = static_cast(rhs); - return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; -} -} // namespace detail -} // namespace nlohmann - - -namespace nlohmann -{ -namespace detail -{ -template -void from_json(const BasicJsonType& j, typename std::nullptr_t& n) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_null())) - { - JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()))); - } - n = nullptr; -} - -// overloads for basic_json template parameters -template < typename BasicJsonType, typename ArithmeticType, - enable_if_t < std::is_arithmetic::value&& - !std::is_same::value, - int > = 0 > -void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) -{ - switch (static_cast(j)) - { - case value_t::number_unsigned: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_integer: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_float: - { - val = static_cast(*j.template get_ptr()); - break; - } - - default: - JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); - } -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) - { - JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()))); - } - b = *j.template get_ptr(); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_string())) - { - JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); - } - s = *j.template get_ptr(); -} - -template < - typename BasicJsonType, typename ConstructibleStringType, - enable_if_t < - is_constructible_string_type::value&& - !std::is_same::value, - int > = 0 > -void from_json(const BasicJsonType& j, ConstructibleStringType& s) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_string())) - { - JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); - } - - s = *j.template get_ptr(); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) -{ - get_arithmetic_value(j, val); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) -{ - get_arithmetic_value(j, val); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) -{ - get_arithmetic_value(j, val); -} - -template::value, int> = 0> -void from_json(const BasicJsonType& j, EnumType& e) -{ - typename std::underlying_type::type val; - get_arithmetic_value(j, val); - e = static_cast(val); -} - -// forward_list doesn't have an insert method -template::value, int> = 0> -void from_json(const BasicJsonType& j, std::forward_list& l) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); - } - l.clear(); - std::transform(j.rbegin(), j.rend(), - std::front_inserter(l), [](const BasicJsonType & i) - { - return i.template get(); - }); -} - -// valarray doesn't have an insert method -template::value, int> = 0> -void from_json(const BasicJsonType& j, std::valarray& l) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); - } - l.resize(j.size()); - std::transform(j.begin(), j.end(), std::begin(l), - [](const BasicJsonType & elem) - { - return elem.template get(); - }); -} - -template -auto from_json(const BasicJsonType& j, T (&arr)[N]) --> decltype(j.template get(), void()) -{ - for (std::size_t i = 0; i < N; ++i) - { - arr[i] = j.at(i).template get(); - } -} - -template -void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) -{ - arr = *j.template get_ptr(); -} - -template -auto from_json_array_impl(const BasicJsonType& j, std::array& arr, - priority_tag<2> /*unused*/) --> decltype(j.template get(), void()) -{ - for (std::size_t i = 0; i < N; ++i) - { - arr[i] = j.at(i).template get(); - } -} - -template -auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) --> decltype( - arr.reserve(std::declval()), - j.template get(), - void()) -{ - using std::end; - - ConstructibleArrayType ret; - ret.reserve(j.size()); - std::transform(j.begin(), j.end(), - std::inserter(ret, end(ret)), [](const BasicJsonType & i) - { - // get() returns *this, this won't call a from_json - // method when value_type is BasicJsonType - return i.template get(); - }); - arr = std::move(ret); -} - -template -void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, - priority_tag<0> /*unused*/) -{ - using std::end; - - ConstructibleArrayType ret; - std::transform( - j.begin(), j.end(), std::inserter(ret, end(ret)), - [](const BasicJsonType & i) - { - // get() returns *this, this won't call a from_json - // method when value_type is BasicJsonType - return i.template get(); - }); - arr = std::move(ret); -} - -template < typename BasicJsonType, typename ConstructibleArrayType, - enable_if_t < - is_constructible_array_type::value&& - !is_constructible_object_type::value&& - !is_constructible_string_type::value&& - !std::is_same::value&& - !is_basic_json::value, - int > = 0 > -auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) --> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), -j.template get(), -void()) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + - std::string(j.type_name()))); - } - - from_json_array_impl(j, arr, priority_tag<3> {}); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) - { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()))); - } - - bin = *j.template get_ptr(); -} - -template::value, int> = 0> -void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_object())) - { - JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()))); - } - - ConstructibleObjectType ret; - auto inner_object = j.template get_ptr(); - using value_type = typename ConstructibleObjectType::value_type; - std::transform( - inner_object->begin(), inner_object->end(), - std::inserter(ret, ret.begin()), - [](typename BasicJsonType::object_t::value_type const & p) - { - return value_type(p.first, p.second.template get()); - }); - obj = std::move(ret); -} - -// overload for arithmetic types, not chosen for basic_json template arguments -// (BooleanType, etc..); note: Is it really necessary to provide explicit -// overloads for boolean_t etc. in case of a custom BooleanType which is not -// an arithmetic type? -template < typename BasicJsonType, typename ArithmeticType, - enable_if_t < - std::is_arithmetic::value&& - !std::is_same::value&& - !std::is_same::value&& - !std::is_same::value&& - !std::is_same::value, - int > = 0 > -void from_json(const BasicJsonType& j, ArithmeticType& val) -{ - switch (static_cast(j)) - { - case value_t::number_unsigned: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_integer: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_float: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::boolean: - { - val = static_cast(*j.template get_ptr()); - break; - } - - default: - JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); - } -} - -template -void from_json(const BasicJsonType& j, std::pair& p) -{ - p = {j.at(0).template get(), j.at(1).template get()}; -} - -template -void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence /*unused*/) -{ - t = std::make_tuple(j.at(Idx).template get::type>()...); -} - -template -void from_json(const BasicJsonType& j, std::tuple& t) -{ - from_json_tuple_impl(j, t, index_sequence_for {}); -} - -template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, - typename = enable_if_t < !std::is_constructible < - typename BasicJsonType::string_t, Key >::value >> -void from_json(const BasicJsonType& j, std::map& m) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); - } - m.clear(); - for (const auto& p : j) - { - if (JSON_HEDLEY_UNLIKELY(!p.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); - } - m.emplace(p.at(0).template get(), p.at(1).template get()); - } -} - -template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, - typename = enable_if_t < !std::is_constructible < - typename BasicJsonType::string_t, Key >::value >> -void from_json(const BasicJsonType& j, std::unordered_map& m) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); - } - m.clear(); - for (const auto& p : j) - { - if (JSON_HEDLEY_UNLIKELY(!p.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); - } - m.emplace(p.at(0).template get(), p.at(1).template get()); - } -} - -struct from_json_fn -{ - template - auto operator()(const BasicJsonType& j, T& val) const - noexcept(noexcept(from_json(j, val))) - -> decltype(from_json(j, val), void()) - { - return from_json(j, val); - } -}; -} // namespace detail - -/// namespace to hold default `from_json` function -/// to see why this is required: -/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html -namespace -{ -constexpr const auto& from_json = detail::static_const::value; -} // namespace -} // namespace nlohmann - -// #include - - -#include // copy -#include // begin, end -#include // string -#include // tuple, get -#include // is_same, is_constructible, is_floating_point, is_enum, underlying_type -#include // move, forward, declval, pair -#include // valarray -#include // vector - -// #include - - -#include // size_t -#include // input_iterator_tag -#include // string, to_string -#include // tuple_size, get, tuple_element - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template -void int_to_string( string_type& target, std::size_t value ) -{ - // For ADL - using std::to_string; - target = to_string(value); -} -template class iteration_proxy_value -{ - public: - using difference_type = std::ptrdiff_t; - using value_type = iteration_proxy_value; - using pointer = value_type * ; - using reference = value_type & ; - using iterator_category = std::input_iterator_tag; - using string_type = typename std::remove_cv< typename std::remove_reference().key() ) >::type >::type; - - private: - /// the iterator - IteratorType anchor; - /// an index for arrays (used to create key names) - std::size_t array_index = 0; - /// last stringified array index - mutable std::size_t array_index_last = 0; - /// a string representation of the array index - mutable string_type array_index_str = "0"; - /// an empty string (to return a reference for primitive values) - const string_type empty_str = ""; - - public: - explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {} - - /// dereference operator (needed for range-based for) - iteration_proxy_value& operator*() - { - return *this; - } - - /// increment operator (needed for range-based for) - iteration_proxy_value& operator++() - { - ++anchor; - ++array_index; - - return *this; - } - - /// equality operator (needed for InputIterator) - bool operator==(const iteration_proxy_value& o) const - { - return anchor == o.anchor; - } - - /// inequality operator (needed for range-based for) - bool operator!=(const iteration_proxy_value& o) const - { - return anchor != o.anchor; - } - - /// return key of the iterator - const string_type& key() const - { - JSON_ASSERT(anchor.m_object != nullptr); - - switch (anchor.m_object->type()) - { - // use integer array index as key - case value_t::array: - { - if (array_index != array_index_last) - { - int_to_string( array_index_str, array_index ); - array_index_last = array_index; - } - return array_index_str; - } - - // use key from the object - case value_t::object: - return anchor.key(); - - // use an empty key for all primitive types - default: - return empty_str; - } - } - - /// return value of the iterator - typename IteratorType::reference value() const - { - return anchor.value(); - } -}; - -/// proxy class for the items() function -template class iteration_proxy -{ - private: - /// the container to iterate - typename IteratorType::reference container; - - public: - /// construct iteration proxy from a container - explicit iteration_proxy(typename IteratorType::reference cont) noexcept - : container(cont) {} - - /// return iterator begin (needed for range-based for) - iteration_proxy_value begin() noexcept - { - return iteration_proxy_value(container.begin()); - } - - /// return iterator end (needed for range-based for) - iteration_proxy_value end() noexcept - { - return iteration_proxy_value(container.end()); - } -}; -// Structured Bindings Support -// For further reference see https://blog.tartanllama.xyz/structured-bindings/ -// And see https://github.com/nlohmann/json/pull/1391 -template = 0> -auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.key()) -{ - return i.key(); -} -// Structured Bindings Support -// For further reference see https://blog.tartanllama.xyz/structured-bindings/ -// And see https://github.com/nlohmann/json/pull/1391 -template = 0> -auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.value()) -{ - return i.value(); -} -} // namespace detail -} // namespace nlohmann - -// The Addition to the STD Namespace is required to add -// Structured Bindings Support to the iteration_proxy_value class -// For further reference see https://blog.tartanllama.xyz/structured-bindings/ -// And see https://github.com/nlohmann/json/pull/1391 -namespace std -{ -#if defined(__clang__) - // Fix: https://github.com/nlohmann/json/issues/1401 - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wmismatched-tags" -#endif -template -class tuple_size<::nlohmann::detail::iteration_proxy_value> - : public std::integral_constant {}; - -template -class tuple_element> -{ - public: - using type = decltype( - get(std::declval < - ::nlohmann::detail::iteration_proxy_value> ())); -}; -#if defined(__clang__) - #pragma clang diagnostic pop -#endif -} // namespace std - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -////////////////// -// constructors // -////////////////// - -template struct external_constructor; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept - { - j.m_type = value_t::boolean; - j.m_value = b; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) - { - j.m_type = value_t::string; - j.m_value = s; - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) - { - j.m_type = value_t::string; - j.m_value = std::move(s); - j.assert_invariant(); - } - - template < typename BasicJsonType, typename CompatibleStringType, - enable_if_t < !std::is_same::value, - int > = 0 > - static void construct(BasicJsonType& j, const CompatibleStringType& str) - { - j.m_type = value_t::string; - j.m_value.string = j.template create(str); - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) - { - j.m_type = value_t::binary; - typename BasicJsonType::binary_t value{b}; - j.m_value = value; - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) - { - j.m_type = value_t::binary; - typename BasicJsonType::binary_t value{std::move(b)}; - j.m_value = value; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept - { - j.m_type = value_t::number_float; - j.m_value = val; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept - { - j.m_type = value_t::number_unsigned; - j.m_value = val; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept - { - j.m_type = value_t::number_integer; - j.m_value = val; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) - { - j.m_type = value_t::array; - j.m_value = arr; - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) - { - j.m_type = value_t::array; - j.m_value = std::move(arr); - j.assert_invariant(); - } - - template < typename BasicJsonType, typename CompatibleArrayType, - enable_if_t < !std::is_same::value, - int > = 0 > - static void construct(BasicJsonType& j, const CompatibleArrayType& arr) - { - using std::begin; - using std::end; - j.m_type = value_t::array; - j.m_value.array = j.template create(begin(arr), end(arr)); - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, const std::vector& arr) - { - j.m_type = value_t::array; - j.m_value = value_t::array; - j.m_value.array->reserve(arr.size()); - for (const bool x : arr) - { - j.m_value.array->push_back(x); - } - j.assert_invariant(); - } - - template::value, int> = 0> - static void construct(BasicJsonType& j, const std::valarray& arr) - { - j.m_type = value_t::array; - j.m_value = value_t::array; - j.m_value.array->resize(arr.size()); - if (arr.size() > 0) - { - std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); - } - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) - { - j.m_type = value_t::object; - j.m_value = obj; - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) - { - j.m_type = value_t::object; - j.m_value = std::move(obj); - j.assert_invariant(); - } - - template < typename BasicJsonType, typename CompatibleObjectType, - enable_if_t < !std::is_same::value, int > = 0 > - static void construct(BasicJsonType& j, const CompatibleObjectType& obj) - { - using std::begin; - using std::end; - - j.m_type = value_t::object; - j.m_value.object = j.template create(begin(obj), end(obj)); - j.assert_invariant(); - } -}; - -///////////// -// to_json // -///////////// - -template::value, int> = 0> -void to_json(BasicJsonType& j, T b) noexcept -{ - external_constructor::construct(j, b); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, const CompatibleString& s) -{ - external_constructor::construct(j, s); -} - -template -void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) -{ - external_constructor::construct(j, std::move(s)); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, FloatType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, EnumType e) noexcept -{ - using underlying_type = typename std::underlying_type::type; - external_constructor::construct(j, static_cast(e)); -} - -template -void to_json(BasicJsonType& j, const std::vector& e) -{ - external_constructor::construct(j, e); -} - -template < typename BasicJsonType, typename CompatibleArrayType, - enable_if_t < is_compatible_array_type::value&& - !is_compatible_object_type::value&& - !is_compatible_string_type::value&& - !std::is_same::value&& - !is_basic_json::value, - int > = 0 > -void to_json(BasicJsonType& j, const CompatibleArrayType& arr) -{ - external_constructor::construct(j, arr); -} - -template -void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) -{ - external_constructor::construct(j, bin); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, const std::valarray& arr) -{ - external_constructor::construct(j, std::move(arr)); -} - -template -void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) -{ - external_constructor::construct(j, std::move(arr)); -} - -template < typename BasicJsonType, typename CompatibleObjectType, - enable_if_t < is_compatible_object_type::value&& !is_basic_json::value, int > = 0 > -void to_json(BasicJsonType& j, const CompatibleObjectType& obj) -{ - external_constructor::construct(j, obj); -} - -template -void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) -{ - external_constructor::construct(j, std::move(obj)); -} - -template < - typename BasicJsonType, typename T, std::size_t N, - enable_if_t < !std::is_constructible::value, - int > = 0 > -void to_json(BasicJsonType& j, const T(&arr)[N]) -{ - external_constructor::construct(j, arr); -} - -template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible::value&& std::is_constructible::value, int > = 0 > -void to_json(BasicJsonType& j, const std::pair& p) -{ - j = { p.first, p.second }; -} - -// for https://github.com/nlohmann/json/pull/1134 -template>::value, int> = 0> -void to_json(BasicJsonType& j, const T& b) -{ - j = { {b.key(), b.value()} }; -} - -template -void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence /*unused*/) -{ - j = { std::get(t)... }; -} - -template::value, int > = 0> -void to_json(BasicJsonType& j, const T& t) -{ - to_json_tuple_impl(j, t, make_index_sequence::value> {}); -} - -struct to_json_fn -{ - template - auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward(val)))) - -> decltype(to_json(j, std::forward(val)), void()) - { - return to_json(j, std::forward(val)); - } -}; -} // namespace detail - -/// namespace to hold default `to_json` function -namespace -{ -constexpr const auto& to_json = detail::static_const::value; -} // namespace -} // namespace nlohmann - - -namespace nlohmann -{ - -template -struct adl_serializer -{ - /*! - @brief convert a JSON value to any value type - - This function is usually called by the `get()` function of the - @ref basic_json class (either explicit or via conversion operators). - - @param[in] j JSON value to read from - @param[in,out] val value to write to - */ - template - static auto from_json(BasicJsonType&& j, ValueType& val) noexcept( - noexcept(::nlohmann::from_json(std::forward(j), val))) - -> decltype(::nlohmann::from_json(std::forward(j), val), void()) - { - ::nlohmann::from_json(std::forward(j), val); - } - - /*! - @brief convert any value type to a JSON value - - This function is usually called by the constructors of the @ref basic_json - class. - - @param[in,out] j JSON value to write to - @param[in] val value to read from - */ - template - static auto to_json(BasicJsonType& j, ValueType&& val) noexcept( - noexcept(::nlohmann::to_json(j, std::forward(val)))) - -> decltype(::nlohmann::to_json(j, std::forward(val)), void()) - { - ::nlohmann::to_json(j, std::forward(val)); - } -}; - -} // namespace nlohmann - -// #include - - -#include // uint8_t -#include // tie -#include // move - -namespace nlohmann -{ - -/*! -@brief an internal type for a backed binary type - -This type extends the template parameter @a BinaryType provided to `basic_json` -with a subtype used by BSON and MessagePack. This type exists so that the user -does not have to specify a type themselves with a specific naming scheme in -order to override the binary type. - -@tparam BinaryType container to store bytes (`std::vector` by - default) - -@since version 3.8.0 -*/ -template -class byte_container_with_subtype : public BinaryType -{ - public: - /// the type of the underlying container - using container_type = BinaryType; - - byte_container_with_subtype() noexcept(noexcept(container_type())) - : container_type() - {} - - byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b))) - : container_type(b) - {} - - byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b)))) - : container_type(std::move(b)) - {} - - byte_container_with_subtype(const container_type& b, std::uint8_t subtype) noexcept(noexcept(container_type(b))) - : container_type(b) - , m_subtype(subtype) - , m_has_subtype(true) - {} - - byte_container_with_subtype(container_type&& b, std::uint8_t subtype) noexcept(noexcept(container_type(std::move(b)))) - : container_type(std::move(b)) - , m_subtype(subtype) - , m_has_subtype(true) - {} - - bool operator==(const byte_container_with_subtype& rhs) const - { - return std::tie(static_cast(*this), m_subtype, m_has_subtype) == - std::tie(static_cast(rhs), rhs.m_subtype, rhs.m_has_subtype); - } - - bool operator!=(const byte_container_with_subtype& rhs) const - { - return !(rhs == *this); - } - - /*! - @brief sets the binary subtype - - Sets the binary subtype of the value, also flags a binary JSON value as - having a subtype, which has implications for serialization. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @sa @ref subtype() -- return the binary subtype - @sa @ref clear_subtype() -- clears the binary subtype - @sa @ref has_subtype() -- returns whether or not the binary value has a - subtype - - @since version 3.8.0 - */ - void set_subtype(std::uint8_t subtype) noexcept - { - m_subtype = subtype; - m_has_subtype = true; - } - - /*! - @brief return the binary subtype - - Returns the numerical subtype of the value if it has a subtype. If it does - not have a subtype, this function will return size_t(-1) as a sentinel - value. - - @return the numerical subtype of the binary value - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @sa @ref set_subtype() -- sets the binary subtype - @sa @ref clear_subtype() -- clears the binary subtype - @sa @ref has_subtype() -- returns whether or not the binary value has a - subtype - - @since version 3.8.0 - */ - constexpr std::uint8_t subtype() const noexcept - { - return m_subtype; - } - - /*! - @brief return whether the value has a subtype - - @return whether the value has a subtype - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @sa @ref subtype() -- return the binary subtype - @sa @ref set_subtype() -- sets the binary subtype - @sa @ref clear_subtype() -- clears the binary subtype - - @since version 3.8.0 - */ - constexpr bool has_subtype() const noexcept - { - return m_has_subtype; - } - - /*! - @brief clears the binary subtype - - Clears the binary subtype and flags the value as not having a subtype, which - has implications for serialization; for instance MessagePack will prefer the - bin family over the ext family. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @sa @ref subtype() -- return the binary subtype - @sa @ref set_subtype() -- sets the binary subtype - @sa @ref has_subtype() -- returns whether or not the binary value has a - subtype - - @since version 3.8.0 - */ - void clear_subtype() noexcept - { - m_subtype = 0; - m_has_subtype = false; - } - - private: - std::uint8_t m_subtype = 0; - bool m_has_subtype = false; -}; - -} // namespace nlohmann - -// #include - -// #include - -// #include - -// #include - - -#include // size_t, uint8_t -#include // hash - -namespace nlohmann -{ -namespace detail -{ - -// boost::hash_combine -inline std::size_t combine(std::size_t seed, std::size_t h) noexcept -{ - seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U); - return seed; -} - -/*! -@brief hash a JSON value - -The hash function tries to rely on std::hash where possible. Furthermore, the -type of the JSON value is taken into account to have different hash values for -null, 0, 0U, and false, etc. - -@tparam BasicJsonType basic_json specialization -@param j JSON value to hash -@return hash value of j -*/ -template -std::size_t hash(const BasicJsonType& j) -{ - using string_t = typename BasicJsonType::string_t; - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - - const auto type = static_cast(j.type()); - switch (j.type()) - { - case BasicJsonType::value_t::null: - case BasicJsonType::value_t::discarded: - { - return combine(type, 0); - } - - case BasicJsonType::value_t::object: - { - auto seed = combine(type, j.size()); - for (const auto& element : j.items()) - { - const auto h = std::hash {}(element.key()); - seed = combine(seed, h); - seed = combine(seed, hash(element.value())); - } - return seed; - } - - case BasicJsonType::value_t::array: - { - auto seed = combine(type, j.size()); - for (const auto& element : j) - { - seed = combine(seed, hash(element)); - } - return seed; - } - - case BasicJsonType::value_t::string: - { - const auto h = std::hash {}(j.template get_ref()); - return combine(type, h); - } - - case BasicJsonType::value_t::boolean: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } - - case BasicJsonType::value_t::number_integer: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } - - case BasicJsonType::value_t::number_unsigned: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } - - case BasicJsonType::value_t::number_float: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } - - case BasicJsonType::value_t::binary: - { - auto seed = combine(type, j.get_binary().size()); - const auto h = std::hash {}(j.get_binary().has_subtype()); - seed = combine(seed, h); - seed = combine(seed, j.get_binary().subtype()); - for (const auto byte : j.get_binary()) - { - seed = combine(seed, std::hash {}(byte)); - } - return seed; - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - return 0; // LCOV_EXCL_LINE - } -} - -} // namespace detail -} // namespace nlohmann - -// #include - - -#include // generate_n -#include // array -#include // ldexp -#include // size_t -#include // uint8_t, uint16_t, uint32_t, uint64_t -#include // snprintf -#include // memcpy -#include // back_inserter -#include // numeric_limits -#include // char_traits, string -#include // make_pair, move - -// #include - -// #include - - -#include // array -#include // size_t -#include //FILE * -#include // strlen -#include // istream -#include // begin, end, iterator_traits, random_access_iterator_tag, distance, next -#include // shared_ptr, make_shared, addressof -#include // accumulate -#include // string, char_traits -#include // enable_if, is_base_of, is_pointer, is_integral, remove_pointer -#include // pair, declval - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -/// the supported input formats -enum class input_format_t { json, cbor, msgpack, ubjson, bson }; - -//////////////////// -// input adapters // -//////////////////// - -/*! -Input adapter for stdio file access. This adapter read only 1 byte and do not use any - buffer. This adapter is a very low level adapter. -*/ -class file_input_adapter -{ - public: - using char_type = char; - - JSON_HEDLEY_NON_NULL(2) - explicit file_input_adapter(std::FILE* f) noexcept - : m_file(f) - {} - - // make class move-only - file_input_adapter(const file_input_adapter&) = delete; - file_input_adapter(file_input_adapter&&) = default; - file_input_adapter& operator=(const file_input_adapter&) = delete; - file_input_adapter& operator=(file_input_adapter&&) = delete; - - std::char_traits::int_type get_character() noexcept - { - return std::fgetc(m_file); - } - - private: - /// the file pointer to read from - std::FILE* m_file; -}; - - -/*! -Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at -beginning of input. Does not support changing the underlying std::streambuf -in mid-input. Maintains underlying std::istream and std::streambuf to support -subsequent use of standard std::istream operations to process any input -characters following those used in parsing the JSON input. Clears the -std::istream flags; any input errors (e.g., EOF) will be detected by the first -subsequent call for input from the std::istream. -*/ -class input_stream_adapter -{ - public: - using char_type = char; - - ~input_stream_adapter() - { - // clear stream flags; we use underlying streambuf I/O, do not - // maintain ifstream flags, except eof - if (is != nullptr) - { - is->clear(is->rdstate() & std::ios::eofbit); - } - } - - explicit input_stream_adapter(std::istream& i) - : is(&i), sb(i.rdbuf()) - {} - - // delete because of pointer members - input_stream_adapter(const input_stream_adapter&) = delete; - input_stream_adapter& operator=(input_stream_adapter&) = delete; - input_stream_adapter& operator=(input_stream_adapter&& rhs) = delete; - - input_stream_adapter(input_stream_adapter&& rhs) noexcept : is(rhs.is), sb(rhs.sb) - { - rhs.is = nullptr; - rhs.sb = nullptr; - } - - // std::istream/std::streambuf use std::char_traits::to_int_type, to - // ensure that std::char_traits::eof() and the character 0xFF do not - // end up as the same value, eg. 0xFFFFFFFF. - std::char_traits::int_type get_character() - { - auto res = sb->sbumpc(); - // set eof manually, as we don't use the istream interface. - if (JSON_HEDLEY_UNLIKELY(res == EOF)) - { - is->clear(is->rdstate() | std::ios::eofbit); - } - return res; - } - - private: - /// the associated input stream - std::istream* is = nullptr; - std::streambuf* sb = nullptr; -}; - -// General-purpose iterator-based adapter. It might not be as fast as -// theoretically possible for some containers, but it is extremely versatile. -template -class iterator_input_adapter -{ - public: - using char_type = typename std::iterator_traits::value_type; - - iterator_input_adapter(IteratorType first, IteratorType last) - : current(std::move(first)), end(std::move(last)) {} - - typename std::char_traits::int_type get_character() - { - if (JSON_HEDLEY_LIKELY(current != end)) - { - auto result = std::char_traits::to_int_type(*current); - std::advance(current, 1); - return result; - } - else - { - return std::char_traits::eof(); - } - } - - private: - IteratorType current; - IteratorType end; - - template - friend struct wide_string_input_helper; - - bool empty() const - { - return current == end; - } - -}; - - -template -struct wide_string_input_helper; - -template -struct wide_string_input_helper -{ - // UTF-32 - static void fill_buffer(BaseInputAdapter& input, - std::array::int_type, 4>& utf8_bytes, - size_t& utf8_bytes_index, - size_t& utf8_bytes_filled) - { - utf8_bytes_index = 0; - - if (JSON_HEDLEY_UNLIKELY(input.empty())) - { - utf8_bytes[0] = std::char_traits::eof(); - utf8_bytes_filled = 1; - } - else - { - // get the current character - const auto wc = input.get_character(); - - // UTF-32 to UTF-8 encoding - if (wc < 0x80) - { - utf8_bytes[0] = static_cast::int_type>(wc); - utf8_bytes_filled = 1; - } - else if (wc <= 0x7FF) - { - utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u) & 0x1Fu)); - utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 2; - } - else if (wc <= 0xFFFF) - { - utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u) & 0x0Fu)); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 3; - } - else if (wc <= 0x10FFFF) - { - utf8_bytes[0] = static_cast::int_type>(0xF0u | ((static_cast(wc) >> 18u) & 0x07u)); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 12u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); - utf8_bytes[3] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 4; - } - else - { - // unknown character - utf8_bytes[0] = static_cast::int_type>(wc); - utf8_bytes_filled = 1; - } - } - } -}; - -template -struct wide_string_input_helper -{ - // UTF-16 - static void fill_buffer(BaseInputAdapter& input, - std::array::int_type, 4>& utf8_bytes, - size_t& utf8_bytes_index, - size_t& utf8_bytes_filled) - { - utf8_bytes_index = 0; - - if (JSON_HEDLEY_UNLIKELY(input.empty())) - { - utf8_bytes[0] = std::char_traits::eof(); - utf8_bytes_filled = 1; - } - else - { - // get the current character - const auto wc = input.get_character(); - - // UTF-16 to UTF-8 encoding - if (wc < 0x80) - { - utf8_bytes[0] = static_cast::int_type>(wc); - utf8_bytes_filled = 1; - } - else if (wc <= 0x7FF) - { - utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u))); - utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 2; - } - else if (0xD800 > wc || wc >= 0xE000) - { - utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u))); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 3; - } - else - { - if (JSON_HEDLEY_UNLIKELY(!input.empty())) - { - const auto wc2 = static_cast(input.get_character()); - const auto charcode = 0x10000u + (((static_cast(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); - utf8_bytes[0] = static_cast::int_type>(0xF0u | (charcode >> 18u)); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); - utf8_bytes[3] = static_cast::int_type>(0x80u | (charcode & 0x3Fu)); - utf8_bytes_filled = 4; - } - else - { - utf8_bytes[0] = static_cast::int_type>(wc); - utf8_bytes_filled = 1; - } - } - } - } -}; - -// Wraps another input apdater to convert wide character types into individual bytes. -template -class wide_string_input_adapter -{ - public: - using char_type = char; - - wide_string_input_adapter(BaseInputAdapter base) - : base_adapter(base) {} - - typename std::char_traits::int_type get_character() noexcept - { - // check if buffer needs to be filled - if (utf8_bytes_index == utf8_bytes_filled) - { - fill_buffer(); - - JSON_ASSERT(utf8_bytes_filled > 0); - JSON_ASSERT(utf8_bytes_index == 0); - } - - // use buffer - JSON_ASSERT(utf8_bytes_filled > 0); - JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled); - return utf8_bytes[utf8_bytes_index++]; - } - - private: - BaseInputAdapter base_adapter; - - template - void fill_buffer() - { - wide_string_input_helper::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); - } - - /// a buffer for UTF-8 bytes - std::array::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; - - /// index to the utf8_codes array for the next valid byte - std::size_t utf8_bytes_index = 0; - /// number of valid bytes in the utf8_codes array - std::size_t utf8_bytes_filled = 0; -}; - - -template -struct iterator_input_adapter_factory -{ - using iterator_type = IteratorType; - using char_type = typename std::iterator_traits::value_type; - using adapter_type = iterator_input_adapter; - - static adapter_type create(IteratorType first, IteratorType last) - { - return adapter_type(std::move(first), std::move(last)); - } -}; - -template -struct is_iterator_of_multibyte -{ - using value_type = typename std::iterator_traits::value_type; - enum - { - value = sizeof(value_type) > 1 - }; -}; - -template -struct iterator_input_adapter_factory::value>> -{ - using iterator_type = IteratorType; - using char_type = typename std::iterator_traits::value_type; - using base_adapter_type = iterator_input_adapter; - using adapter_type = wide_string_input_adapter; - - static adapter_type create(IteratorType first, IteratorType last) - { - return adapter_type(base_adapter_type(std::move(first), std::move(last))); - } -}; - -// General purpose iterator-based input -template -typename iterator_input_adapter_factory::adapter_type input_adapter(IteratorType first, IteratorType last) -{ - using factory_type = iterator_input_adapter_factory; - return factory_type::create(first, last); -} - -// Convenience shorthand from container to iterator -template -auto input_adapter(const ContainerType& container) -> decltype(input_adapter(begin(container), end(container))) -{ - // Enable ADL - using std::begin; - using std::end; - - return input_adapter(begin(container), end(container)); -} - -// Special cases with fast paths -inline file_input_adapter input_adapter(std::FILE* file) -{ - return file_input_adapter(file); -} - -inline input_stream_adapter input_adapter(std::istream& stream) -{ - return input_stream_adapter(stream); -} - -inline input_stream_adapter input_adapter(std::istream&& stream) -{ - return input_stream_adapter(stream); -} - -using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval(), std::declval())); - -// Null-delimited strings, and the like. -template < typename CharT, - typename std::enable_if < - std::is_pointer::value&& - !std::is_array::value&& - std::is_integral::type>::value&& - sizeof(typename std::remove_pointer::type) == 1, - int >::type = 0 > -contiguous_bytes_input_adapter input_adapter(CharT b) -{ - auto length = std::strlen(reinterpret_cast(b)); - const auto* ptr = reinterpret_cast(b); - return input_adapter(ptr, ptr + length); -} - -template -auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) -{ - return input_adapter(array, array + N); -} - -// This class only handles inputs of input_buffer_adapter type. -// It's required so that expressions like {ptr, len} can be implicitely casted -// to the correct adapter. -class span_input_adapter -{ - public: - template < typename CharT, - typename std::enable_if < - std::is_pointer::value&& - std::is_integral::type>::value&& - sizeof(typename std::remove_pointer::type) == 1, - int >::type = 0 > - span_input_adapter(CharT b, std::size_t l) - : ia(reinterpret_cast(b), reinterpret_cast(b) + l) {} - - template::iterator_category, std::random_access_iterator_tag>::value, - int>::type = 0> - span_input_adapter(IteratorType first, IteratorType last) - : ia(input_adapter(first, last)) {} - - contiguous_bytes_input_adapter&& get() - { - return std::move(ia); - } - - private: - contiguous_bytes_input_adapter ia; -}; -} // namespace detail -} // namespace nlohmann - -// #include - - -#include -#include // string -#include // move -#include // vector - -// #include - -// #include - - -namespace nlohmann -{ - -/*! -@brief SAX interface - -This class describes the SAX interface used by @ref nlohmann::json::sax_parse. -Each function is called in different situations while the input is parsed. The -boolean return value informs the parser whether to continue processing the -input. -*/ -template -struct json_sax -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - - /*! - @brief a null value was read - @return whether parsing should proceed - */ - virtual bool null() = 0; - - /*! - @brief a boolean value was read - @param[in] val boolean value - @return whether parsing should proceed - */ - virtual bool boolean(bool val) = 0; - - /*! - @brief an integer number was read - @param[in] val integer value - @return whether parsing should proceed - */ - virtual bool number_integer(number_integer_t val) = 0; - - /*! - @brief an unsigned integer number was read - @param[in] val unsigned integer value - @return whether parsing should proceed - */ - virtual bool number_unsigned(number_unsigned_t val) = 0; - - /*! - @brief an floating-point number was read - @param[in] val floating-point value - @param[in] s raw token value - @return whether parsing should proceed - */ - virtual bool number_float(number_float_t val, const string_t& s) = 0; - - /*! - @brief a string was read - @param[in] val string value - @return whether parsing should proceed - @note It is safe to move the passed string. - */ - virtual bool string(string_t& val) = 0; - - /*! - @brief a binary string was read - @param[in] val binary value - @return whether parsing should proceed - @note It is safe to move the passed binary. - */ - virtual bool binary(binary_t& val) = 0; - - /*! - @brief the beginning of an object was read - @param[in] elements number of object elements or -1 if unknown - @return whether parsing should proceed - @note binary formats may report the number of elements - */ - virtual bool start_object(std::size_t elements) = 0; - - /*! - @brief an object key was read - @param[in] val object key - @return whether parsing should proceed - @note It is safe to move the passed string. - */ - virtual bool key(string_t& val) = 0; - - /*! - @brief the end of an object was read - @return whether parsing should proceed - */ - virtual bool end_object() = 0; - - /*! - @brief the beginning of an array was read - @param[in] elements number of array elements or -1 if unknown - @return whether parsing should proceed - @note binary formats may report the number of elements - */ - virtual bool start_array(std::size_t elements) = 0; - - /*! - @brief the end of an array was read - @return whether parsing should proceed - */ - virtual bool end_array() = 0; - - /*! - @brief a parse error occurred - @param[in] position the position in the input where the error occurs - @param[in] last_token the last read token - @param[in] ex an exception object describing the error - @return whether parsing should proceed (must return false) - */ - virtual bool parse_error(std::size_t position, - const std::string& last_token, - const detail::exception& ex) = 0; - - virtual ~json_sax() = default; -}; - - -namespace detail -{ -/*! -@brief SAX implementation to create a JSON value from SAX events - -This class implements the @ref json_sax interface and processes the SAX events -to create a JSON value which makes it basically a DOM parser. The structure or -hierarchy of the JSON value is managed by the stack `ref_stack` which contains -a pointer to the respective array or object for each recursion depth. - -After successful parsing, the value that is passed by reference to the -constructor contains the parsed value. - -@tparam BasicJsonType the JSON type -*/ -template -class json_sax_dom_parser -{ - public: - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - - /*! - @param[in, out] r reference to a JSON value that is manipulated while - parsing - @param[in] allow_exceptions_ whether parse errors yield exceptions - */ - explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) - : root(r), allow_exceptions(allow_exceptions_) - {} - - // make class move-only - json_sax_dom_parser(const json_sax_dom_parser&) = delete; - json_sax_dom_parser(json_sax_dom_parser&&) = default; - json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; - json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; - ~json_sax_dom_parser() = default; - - bool null() - { - handle_value(nullptr); - return true; - } - - bool boolean(bool val) - { - handle_value(val); - return true; - } - - bool number_integer(number_integer_t val) - { - handle_value(val); - return true; - } - - bool number_unsigned(number_unsigned_t val) - { - handle_value(val); - return true; - } - - bool number_float(number_float_t val, const string_t& /*unused*/) - { - handle_value(val); - return true; - } - - bool string(string_t& val) - { - handle_value(val); - return true; - } - - bool binary(binary_t& val) - { - handle_value(std::move(val)); - return true; - } - - bool start_object(std::size_t len) - { - ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); - - if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, - "excessive object size: " + std::to_string(len))); - } - - return true; - } - - bool key(string_t& val) - { - // add null at given key and store the reference for later - object_element = &(ref_stack.back()->m_value.object->operator[](val)); - return true; - } - - bool end_object() - { - ref_stack.pop_back(); - return true; - } - - bool start_array(std::size_t len) - { - ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); - - if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, - "excessive array size: " + std::to_string(len))); - } - - return true; - } - - bool end_array() - { - ref_stack.pop_back(); - return true; - } - - template - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, - const Exception& ex) - { - errored = true; - static_cast(ex); - if (allow_exceptions) - { - JSON_THROW(ex); - } - return false; - } - - constexpr bool is_errored() const - { - return errored; - } - - private: - /*! - @invariant If the ref stack is empty, then the passed value will be the new - root. - @invariant If the ref stack contains a value, then it is an array or an - object to which we can add elements - */ - template - JSON_HEDLEY_RETURNS_NON_NULL - BasicJsonType* handle_value(Value&& v) - { - if (ref_stack.empty()) - { - root = BasicJsonType(std::forward(v)); - return &root; - } - - JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); - - if (ref_stack.back()->is_array()) - { - ref_stack.back()->m_value.array->emplace_back(std::forward(v)); - return &(ref_stack.back()->m_value.array->back()); - } - - JSON_ASSERT(ref_stack.back()->is_object()); - JSON_ASSERT(object_element); - *object_element = BasicJsonType(std::forward(v)); - return object_element; - } - - /// the parsed JSON value - BasicJsonType& root; - /// stack to model hierarchy of values - std::vector ref_stack {}; - /// helper to hold the reference for the next object element - BasicJsonType* object_element = nullptr; - /// whether a syntax error occurred - bool errored = false; - /// whether to throw exceptions in case of errors - const bool allow_exceptions = true; -}; - -template -class json_sax_dom_callback_parser -{ - public: - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using parser_callback_t = typename BasicJsonType::parser_callback_t; - using parse_event_t = typename BasicJsonType::parse_event_t; - - json_sax_dom_callback_parser(BasicJsonType& r, - const parser_callback_t cb, - const bool allow_exceptions_ = true) - : root(r), callback(cb), allow_exceptions(allow_exceptions_) - { - keep_stack.push_back(true); - } - - // make class move-only - json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; - json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; - json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; - json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; - ~json_sax_dom_callback_parser() = default; - - bool null() - { - handle_value(nullptr); - return true; - } - - bool boolean(bool val) - { - handle_value(val); - return true; - } - - bool number_integer(number_integer_t val) - { - handle_value(val); - return true; - } - - bool number_unsigned(number_unsigned_t val) - { - handle_value(val); - return true; - } - - bool number_float(number_float_t val, const string_t& /*unused*/) - { - handle_value(val); - return true; - } - - bool string(string_t& val) - { - handle_value(val); - return true; - } - - bool binary(binary_t& val) - { - handle_value(std::move(val)); - return true; - } - - bool start_object(std::size_t len) - { - // check callback for object start - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::object_start, discarded); - keep_stack.push_back(keep); - - auto val = handle_value(BasicJsonType::value_t::object, true); - ref_stack.push_back(val.second); - - // check object limit - if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len))); - } - - return true; - } - - bool key(string_t& val) - { - BasicJsonType k = BasicJsonType(val); - - // check callback for key - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::key, k); - key_keep_stack.push_back(keep); - - // add discarded value at given key and store the reference for later - if (keep && ref_stack.back()) - { - object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded); - } - - return true; - } - - bool end_object() - { - if (ref_stack.back() && !callback(static_cast(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) - { - // discard object - *ref_stack.back() = discarded; - } - - JSON_ASSERT(!ref_stack.empty()); - JSON_ASSERT(!keep_stack.empty()); - ref_stack.pop_back(); - keep_stack.pop_back(); - - if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) - { - // remove discarded value - for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) - { - if (it->is_discarded()) - { - ref_stack.back()->erase(it); - break; - } - } - } - - return true; - } - - bool start_array(std::size_t len) - { - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::array_start, discarded); - keep_stack.push_back(keep); - - auto val = handle_value(BasicJsonType::value_t::array, true); - ref_stack.push_back(val.second); - - // check array limit - if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len))); - } - - return true; - } - - bool end_array() - { - bool keep = true; - - if (ref_stack.back()) - { - keep = callback(static_cast(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); - if (!keep) - { - // discard array - *ref_stack.back() = discarded; - } - } - - JSON_ASSERT(!ref_stack.empty()); - JSON_ASSERT(!keep_stack.empty()); - ref_stack.pop_back(); - keep_stack.pop_back(); - - // remove discarded value - if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) - { - ref_stack.back()->m_value.array->pop_back(); - } - - return true; - } - - template - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, - const Exception& ex) - { - errored = true; - static_cast(ex); - if (allow_exceptions) - { - JSON_THROW(ex); - } - return false; - } - - constexpr bool is_errored() const - { - return errored; - } - - private: - /*! - @param[in] v value to add to the JSON value we build during parsing - @param[in] skip_callback whether we should skip calling the callback - function; this is required after start_array() and - start_object() SAX events, because otherwise we would call the - callback function with an empty array or object, respectively. - - @invariant If the ref stack is empty, then the passed value will be the new - root. - @invariant If the ref stack contains a value, then it is an array or an - object to which we can add elements - - @return pair of boolean (whether value should be kept) and pointer (to the - passed value in the ref_stack hierarchy; nullptr if not kept) - */ - template - std::pair handle_value(Value&& v, const bool skip_callback = false) - { - JSON_ASSERT(!keep_stack.empty()); - - // do not handle this value if we know it would be added to a discarded - // container - if (!keep_stack.back()) - { - return {false, nullptr}; - } - - // create value - auto value = BasicJsonType(std::forward(v)); - - // check callback - const bool keep = skip_callback || callback(static_cast(ref_stack.size()), parse_event_t::value, value); - - // do not handle this value if we just learnt it shall be discarded - if (!keep) - { - return {false, nullptr}; - } - - if (ref_stack.empty()) - { - root = std::move(value); - return {true, &root}; - } - - // skip this value if we already decided to skip the parent - // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) - if (!ref_stack.back()) - { - return {false, nullptr}; - } - - // we now only expect arrays and objects - JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); - - // array - if (ref_stack.back()->is_array()) - { - ref_stack.back()->m_value.array->push_back(std::move(value)); - return {true, &(ref_stack.back()->m_value.array->back())}; - } - - // object - JSON_ASSERT(ref_stack.back()->is_object()); - // check if we should store an element for the current key - JSON_ASSERT(!key_keep_stack.empty()); - const bool store_element = key_keep_stack.back(); - key_keep_stack.pop_back(); - - if (!store_element) - { - return {false, nullptr}; - } - - JSON_ASSERT(object_element); - *object_element = std::move(value); - return {true, object_element}; - } - - /// the parsed JSON value - BasicJsonType& root; - /// stack to model hierarchy of values - std::vector ref_stack {}; - /// stack to manage which values to keep - std::vector keep_stack {}; - /// stack to manage which object keys to keep - std::vector key_keep_stack {}; - /// helper to hold the reference for the next object element - BasicJsonType* object_element = nullptr; - /// whether a syntax error occurred - bool errored = false; - /// callback function - const parser_callback_t callback = nullptr; - /// whether to throw exceptions in case of errors - const bool allow_exceptions = true; - /// a discarded value for the callback - BasicJsonType discarded = BasicJsonType::value_t::discarded; -}; - -template -class json_sax_acceptor -{ - public: - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - - bool null() - { - return true; - } - - bool boolean(bool /*unused*/) - { - return true; - } - - bool number_integer(number_integer_t /*unused*/) - { - return true; - } - - bool number_unsigned(number_unsigned_t /*unused*/) - { - return true; - } - - bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) - { - return true; - } - - bool string(string_t& /*unused*/) - { - return true; - } - - bool binary(binary_t& /*unused*/) - { - return true; - } - - bool start_object(std::size_t /*unused*/ = std::size_t(-1)) - { - return true; - } - - bool key(string_t& /*unused*/) - { - return true; - } - - bool end_object() - { - return true; - } - - bool start_array(std::size_t /*unused*/ = std::size_t(-1)) - { - return true; - } - - bool end_array() - { - return true; - } - - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) - { - return false; - } -}; -} // namespace detail - -} // namespace nlohmann - -// #include - - -#include // array -#include // localeconv -#include // size_t -#include // snprintf -#include // strtof, strtod, strtold, strtoll, strtoull -#include // initializer_list -#include // char_traits, string -#include // move -#include // vector - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -/////////// -// lexer // -/////////// - -template -class lexer_base -{ - public: - /// token types for the parser - enum class token_type - { - uninitialized, ///< indicating the scanner is uninitialized - literal_true, ///< the `true` literal - literal_false, ///< the `false` literal - literal_null, ///< the `null` literal - value_string, ///< a string -- use get_string() for actual value - value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value - value_integer, ///< a signed integer -- use get_number_integer() for actual value - value_float, ///< an floating point number -- use get_number_float() for actual value - begin_array, ///< the character for array begin `[` - begin_object, ///< the character for object begin `{` - end_array, ///< the character for array end `]` - end_object, ///< the character for object end `}` - name_separator, ///< the name separator `:` - value_separator, ///< the value separator `,` - parse_error, ///< indicating a parse error - end_of_input, ///< indicating the end of the input buffer - literal_or_value ///< a literal or the begin of a value (only for diagnostics) - }; - - /// return name of values of type token_type (only used for errors) - JSON_HEDLEY_RETURNS_NON_NULL - JSON_HEDLEY_CONST - static const char* token_type_name(const token_type t) noexcept - { - switch (t) - { - case token_type::uninitialized: - return ""; - case token_type::literal_true: - return "true literal"; - case token_type::literal_false: - return "false literal"; - case token_type::literal_null: - return "null literal"; - case token_type::value_string: - return "string literal"; - case token_type::value_unsigned: - case token_type::value_integer: - case token_type::value_float: - return "number literal"; - case token_type::begin_array: - return "'['"; - case token_type::begin_object: - return "'{'"; - case token_type::end_array: - return "']'"; - case token_type::end_object: - return "'}'"; - case token_type::name_separator: - return "':'"; - case token_type::value_separator: - return "','"; - case token_type::parse_error: - return ""; - case token_type::end_of_input: - return "end of input"; - case token_type::literal_or_value: - return "'[', '{', or a literal"; - // LCOV_EXCL_START - default: // catch non-enum values - return "unknown token"; - // LCOV_EXCL_STOP - } - } -}; -/*! -@brief lexical analysis - -This class organizes the lexical analysis during JSON deserialization. -*/ -template -class lexer : public lexer_base -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using char_type = typename InputAdapterType::char_type; - using char_int_type = typename std::char_traits::int_type; - - public: - using token_type = typename lexer_base::token_type; - - explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) - : ia(std::move(adapter)) - , ignore_comments(ignore_comments_) - , decimal_point_char(static_cast(get_decimal_point())) - {} - - // delete because of pointer members - lexer(const lexer&) = delete; - lexer(lexer&&) = default; - lexer& operator=(lexer&) = delete; - lexer& operator=(lexer&&) = default; - ~lexer() = default; - - private: - ///////////////////// - // locales - ///////////////////// - - /// return the locale-dependent decimal point - JSON_HEDLEY_PURE - static char get_decimal_point() noexcept - { - const auto* loc = localeconv(); - JSON_ASSERT(loc != nullptr); - return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); - } - - ///////////////////// - // scan functions - ///////////////////// - - /*! - @brief get codepoint from 4 hex characters following `\u` - - For input "\u c1 c2 c3 c4" the codepoint is: - (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 - = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) - - Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' - must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The - conversion is done by subtracting the offset (0x30, 0x37, and 0x57) - between the ASCII value of the character and the desired integer value. - - @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or - non-hex character) - */ - int get_codepoint() - { - // this function only makes sense after reading `\u` - JSON_ASSERT(current == 'u'); - int codepoint = 0; - - const auto factors = { 12u, 8u, 4u, 0u }; - for (const auto factor : factors) - { - get(); - - if (current >= '0' && current <= '9') - { - codepoint += static_cast((static_cast(current) - 0x30u) << factor); - } - else if (current >= 'A' && current <= 'F') - { - codepoint += static_cast((static_cast(current) - 0x37u) << factor); - } - else if (current >= 'a' && current <= 'f') - { - codepoint += static_cast((static_cast(current) - 0x57u) << factor); - } - else - { - return -1; - } - } - - JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF); - return codepoint; - } - - /*! - @brief check if the next byte(s) are inside a given range - - Adds the current byte and, for each passed range, reads a new byte and - checks if it is inside the range. If a violation was detected, set up an - error message and return false. Otherwise, return true. - - @param[in] ranges list of integers; interpreted as list of pairs of - inclusive lower and upper bound, respectively - - @pre The passed list @a ranges must have 2, 4, or 6 elements; that is, - 1, 2, or 3 pairs. This precondition is enforced by an assertion. - - @return true if and only if no range violation was detected - */ - bool next_byte_in_range(std::initializer_list ranges) - { - JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6); - add(current); - - for (auto range = ranges.begin(); range != ranges.end(); ++range) - { - get(); - if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) - { - add(current); - } - else - { - error_message = "invalid string: ill-formed UTF-8 byte"; - return false; - } - } - - return true; - } - - /*! - @brief scan a string literal - - This function scans a string according to Sect. 7 of RFC 7159. While - scanning, bytes are escaped and copied into buffer token_buffer. Then the - function returns successfully, token_buffer is *not* null-terminated (as it - may contain \0 bytes), and token_buffer.size() is the number of bytes in the - string. - - @return token_type::value_string if string could be successfully scanned, - token_type::parse_error otherwise - - @note In case of errors, variable error_message contains a textual - description. - */ - token_type scan_string() - { - // reset token_buffer (ignore opening quote) - reset(); - - // we entered the function by reading an open quote - JSON_ASSERT(current == '\"'); - - while (true) - { - // get next character - switch (get()) - { - // end of file while parsing string - case std::char_traits::eof(): - { - error_message = "invalid string: missing closing quote"; - return token_type::parse_error; - } - - // closing quote - case '\"': - { - return token_type::value_string; - } - - // escapes - case '\\': - { - switch (get()) - { - // quotation mark - case '\"': - add('\"'); - break; - // reverse solidus - case '\\': - add('\\'); - break; - // solidus - case '/': - add('/'); - break; - // backspace - case 'b': - add('\b'); - break; - // form feed - case 'f': - add('\f'); - break; - // line feed - case 'n': - add('\n'); - break; - // carriage return - case 'r': - add('\r'); - break; - // tab - case 't': - add('\t'); - break; - - // unicode escapes - case 'u': - { - const int codepoint1 = get_codepoint(); - int codepoint = codepoint1; // start with codepoint1 - - if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) - { - error_message = "invalid string: '\\u' must be followed by 4 hex digits"; - return token_type::parse_error; - } - - // check if code point is a high surrogate - if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) - { - // expect next \uxxxx entry - if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) - { - const int codepoint2 = get_codepoint(); - - if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) - { - error_message = "invalid string: '\\u' must be followed by 4 hex digits"; - return token_type::parse_error; - } - - // check if codepoint2 is a low surrogate - if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) - { - // overwrite codepoint - codepoint = static_cast( - // high surrogate occupies the most significant 22 bits - (static_cast(codepoint1) << 10u) - // low surrogate occupies the least significant 15 bits - + static_cast(codepoint2) - // there is still the 0xD800, 0xDC00 and 0x10000 noise - // in the result so we have to subtract with: - // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 - - 0x35FDC00u); - } - else - { - error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; - return token_type::parse_error; - } - } - else - { - error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; - return token_type::parse_error; - } - } - else - { - if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) - { - error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF"; - return token_type::parse_error; - } - } - - // result of the above calculation yields a proper codepoint - JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF); - - // translate codepoint into bytes - if (codepoint < 0x80) - { - // 1-byte characters: 0xxxxxxx (ASCII) - add(static_cast(codepoint)); - } - else if (codepoint <= 0x7FF) - { - // 2-byte characters: 110xxxxx 10xxxxxx - add(static_cast(0xC0u | (static_cast(codepoint) >> 6u))); - add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); - } - else if (codepoint <= 0xFFFF) - { - // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx - add(static_cast(0xE0u | (static_cast(codepoint) >> 12u))); - add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); - add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); - } - else - { - // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - add(static_cast(0xF0u | (static_cast(codepoint) >> 18u))); - add(static_cast(0x80u | ((static_cast(codepoint) >> 12u) & 0x3Fu))); - add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); - add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); - } - - break; - } - - // other characters after escape - default: - error_message = "invalid string: forbidden character after backslash"; - return token_type::parse_error; - } - - break; - } - - // invalid control characters - case 0x00: - { - error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; - return token_type::parse_error; - } - - case 0x01: - { - error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; - return token_type::parse_error; - } - - case 0x02: - { - error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; - return token_type::parse_error; - } - - case 0x03: - { - error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; - return token_type::parse_error; - } - - case 0x04: - { - error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; - return token_type::parse_error; - } - - case 0x05: - { - error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; - return token_type::parse_error; - } - - case 0x06: - { - error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; - return token_type::parse_error; - } - - case 0x07: - { - error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; - return token_type::parse_error; - } - - case 0x08: - { - error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; - return token_type::parse_error; - } - - case 0x09: - { - error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; - return token_type::parse_error; - } - - case 0x0A: - { - error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; - return token_type::parse_error; - } - - case 0x0B: - { - error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; - return token_type::parse_error; - } - - case 0x0C: - { - error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; - return token_type::parse_error; - } - - case 0x0D: - { - error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; - return token_type::parse_error; - } - - case 0x0E: - { - error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; - return token_type::parse_error; - } - - case 0x0F: - { - error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; - return token_type::parse_error; - } - - case 0x10: - { - error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; - return token_type::parse_error; - } - - case 0x11: - { - error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; - return token_type::parse_error; - } - - case 0x12: - { - error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; - return token_type::parse_error; - } - - case 0x13: - { - error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; - return token_type::parse_error; - } - - case 0x14: - { - error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; - return token_type::parse_error; - } - - case 0x15: - { - error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; - return token_type::parse_error; - } - - case 0x16: - { - error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; - return token_type::parse_error; - } - - case 0x17: - { - error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; - return token_type::parse_error; - } - - case 0x18: - { - error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; - return token_type::parse_error; - } - - case 0x19: - { - error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; - return token_type::parse_error; - } - - case 0x1A: - { - error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; - return token_type::parse_error; - } - - case 0x1B: - { - error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; - return token_type::parse_error; - } - - case 0x1C: - { - error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; - return token_type::parse_error; - } - - case 0x1D: - { - error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; - return token_type::parse_error; - } - - case 0x1E: - { - error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; - return token_type::parse_error; - } - - case 0x1F: - { - error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; - return token_type::parse_error; - } - - // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) - case 0x20: - case 0x21: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3A: - case 0x3B: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: - case 0x59: - case 0x5A: - case 0x5B: - case 0x5D: - case 0x5E: - case 0x5F: - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - case 0x78: - case 0x79: - case 0x7A: - case 0x7B: - case 0x7C: - case 0x7D: - case 0x7E: - case 0x7F: - { - add(current); - break; - } - - // U+0080..U+07FF: bytes C2..DF 80..BF - case 0xC2: - case 0xC3: - case 0xC4: - case 0xC5: - case 0xC6: - case 0xC7: - case 0xC8: - case 0xC9: - case 0xCA: - case 0xCB: - case 0xCC: - case 0xCD: - case 0xCE: - case 0xCF: - case 0xD0: - case 0xD1: - case 0xD2: - case 0xD3: - case 0xD4: - case 0xD5: - case 0xD6: - case 0xD7: - case 0xD8: - case 0xD9: - case 0xDA: - case 0xDB: - case 0xDC: - case 0xDD: - case 0xDE: - case 0xDF: - { - if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF}))) - { - return token_type::parse_error; - } - break; - } - - // U+0800..U+0FFF: bytes E0 A0..BF 80..BF - case 0xE0: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF - // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF - case 0xE1: - case 0xE2: - case 0xE3: - case 0xE4: - case 0xE5: - case 0xE6: - case 0xE7: - case 0xE8: - case 0xE9: - case 0xEA: - case 0xEB: - case 0xEC: - case 0xEE: - case 0xEF: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+D000..U+D7FF: bytes ED 80..9F 80..BF - case 0xED: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF - case 0xF0: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF - case 0xF1: - case 0xF2: - case 0xF3: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF - case 0xF4: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // remaining bytes (80..C1 and F5..FF) are ill-formed - default: - { - error_message = "invalid string: ill-formed UTF-8 byte"; - return token_type::parse_error; - } - } - } - } - - /*! - * @brief scan a comment - * @return whether comment could be scanned successfully - */ - bool scan_comment() - { - switch (get()) - { - // single-line comments skip input until a newline or EOF is read - case '/': - { - while (true) - { - switch (get()) - { - case '\n': - case '\r': - case std::char_traits::eof(): - case '\0': - return true; - - default: - break; - } - } - } - - // multi-line comments skip input until */ is read - case '*': - { - while (true) - { - switch (get()) - { - case std::char_traits::eof(): - case '\0': - { - error_message = "invalid comment; missing closing '*/'"; - return false; - } - - case '*': - { - switch (get()) - { - case '/': - return true; - - default: - { - unget(); - continue; - } - } - } - - default: - continue; - } - } - } - - // unexpected character after reading '/' - default: - { - error_message = "invalid comment; expecting '/' or '*' after '/'"; - return false; - } - } - } - - JSON_HEDLEY_NON_NULL(2) - static void strtof(float& f, const char* str, char** endptr) noexcept - { - f = std::strtof(str, endptr); - } - - JSON_HEDLEY_NON_NULL(2) - static void strtof(double& f, const char* str, char** endptr) noexcept - { - f = std::strtod(str, endptr); - } - - JSON_HEDLEY_NON_NULL(2) - static void strtof(long double& f, const char* str, char** endptr) noexcept - { - f = std::strtold(str, endptr); - } - - /*! - @brief scan a number literal - - This function scans a string according to Sect. 6 of RFC 7159. - - The function is realized with a deterministic finite state machine derived - from the grammar described in RFC 7159. Starting in state "init", the - input is read and used to determined the next state. Only state "done" - accepts the number. State "error" is a trap state to model errors. In the - table below, "anything" means any character but the ones listed before. - - state | 0 | 1-9 | e E | + | - | . | anything - ---------|----------|----------|----------|---------|---------|----------|----------- - init | zero | any1 | [error] | [error] | minus | [error] | [error] - minus | zero | any1 | [error] | [error] | [error] | [error] | [error] - zero | done | done | exponent | done | done | decimal1 | done - any1 | any1 | any1 | exponent | done | done | decimal1 | done - decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error] - decimal2 | decimal2 | decimal2 | exponent | done | done | done | done - exponent | any2 | any2 | [error] | sign | sign | [error] | [error] - sign | any2 | any2 | [error] | [error] | [error] | [error] | [error] - any2 | any2 | any2 | done | done | done | done | done - - The state machine is realized with one label per state (prefixed with - "scan_number_") and `goto` statements between them. The state machine - contains cycles, but any cycle can be left when EOF is read. Therefore, - the function is guaranteed to terminate. - - During scanning, the read bytes are stored in token_buffer. This string is - then converted to a signed integer, an unsigned integer, or a - floating-point number. - - @return token_type::value_unsigned, token_type::value_integer, or - token_type::value_float if number could be successfully scanned, - token_type::parse_error otherwise - - @note The scanner is independent of the current locale. Internally, the - locale's decimal point is used instead of `.` to work with the - locale-dependent converters. - */ - token_type scan_number() // lgtm [cpp/use-of-goto] - { - // reset token_buffer to store the number's bytes - reset(); - - // the type of the parsed number; initially set to unsigned; will be - // changed if minus sign, decimal point or exponent is read - token_type number_type = token_type::value_unsigned; - - // state (init): we just found out we need to scan a number - switch (current) - { - case '-': - { - add(current); - goto scan_number_minus; - } - - case '0': - { - add(current); - goto scan_number_zero; - } - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any1; - } - - // all other characters are rejected outside scan_number() - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - -scan_number_minus: - // state: we just parsed a leading minus sign - number_type = token_type::value_integer; - switch (get()) - { - case '0': - { - add(current); - goto scan_number_zero; - } - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any1; - } - - default: - { - error_message = "invalid number; expected digit after '-'"; - return token_type::parse_error; - } - } - -scan_number_zero: - // state: we just parse a zero (maybe with a leading minus sign) - switch (get()) - { - case '.': - { - add(decimal_point_char); - goto scan_number_decimal1; - } - - case 'e': - case 'E': - { - add(current); - goto scan_number_exponent; - } - - default: - goto scan_number_done; - } - -scan_number_any1: - // state: we just parsed a number 0-9 (maybe with a leading minus sign) - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any1; - } - - case '.': - { - add(decimal_point_char); - goto scan_number_decimal1; - } - - case 'e': - case 'E': - { - add(current); - goto scan_number_exponent; - } - - default: - goto scan_number_done; - } - -scan_number_decimal1: - // state: we just parsed a decimal point - number_type = token_type::value_float; - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_decimal2; - } - - default: - { - error_message = "invalid number; expected digit after '.'"; - return token_type::parse_error; - } - } - -scan_number_decimal2: - // we just parsed at least one number after a decimal point - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_decimal2; - } - - case 'e': - case 'E': - { - add(current); - goto scan_number_exponent; - } - - default: - goto scan_number_done; - } - -scan_number_exponent: - // we just parsed an exponent - number_type = token_type::value_float; - switch (get()) - { - case '+': - case '-': - { - add(current); - goto scan_number_sign; - } - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any2; - } - - default: - { - error_message = - "invalid number; expected '+', '-', or digit after exponent"; - return token_type::parse_error; - } - } - -scan_number_sign: - // we just parsed an exponent sign - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any2; - } - - default: - { - error_message = "invalid number; expected digit after exponent sign"; - return token_type::parse_error; - } - } - -scan_number_any2: - // we just parsed a number after the exponent or exponent sign - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any2; - } - - default: - goto scan_number_done; - } - -scan_number_done: - // unget the character after the number (we only read it to know that - // we are done scanning a number) - unget(); - - char* endptr = nullptr; - errno = 0; - - // try to parse integers first and fall back to floats - if (number_type == token_type::value_unsigned) - { - const auto x = std::strtoull(token_buffer.data(), &endptr, 10); - - // we checked the number format before - JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - - if (errno == 0) - { - value_unsigned = static_cast(x); - if (value_unsigned == x) - { - return token_type::value_unsigned; - } - } - } - else if (number_type == token_type::value_integer) - { - const auto x = std::strtoll(token_buffer.data(), &endptr, 10); - - // we checked the number format before - JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - - if (errno == 0) - { - value_integer = static_cast(x); - if (value_integer == x) - { - return token_type::value_integer; - } - } - } - - // this code is reached if we parse a floating-point number or if an - // integer conversion above failed - strtof(value_float, token_buffer.data(), &endptr); - - // we checked the number format before - JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - - return token_type::value_float; - } - - /*! - @param[in] literal_text the literal text to expect - @param[in] length the length of the passed literal text - @param[in] return_type the token type to return on success - */ - JSON_HEDLEY_NON_NULL(2) - token_type scan_literal(const char_type* literal_text, const std::size_t length, - token_type return_type) - { - JSON_ASSERT(std::char_traits::to_char_type(current) == literal_text[0]); - for (std::size_t i = 1; i < length; ++i) - { - if (JSON_HEDLEY_UNLIKELY(std::char_traits::to_char_type(get()) != literal_text[i])) - { - error_message = "invalid literal"; - return token_type::parse_error; - } - } - return return_type; - } - - ///////////////////// - // input management - ///////////////////// - - /// reset token_buffer; current character is beginning of token - void reset() noexcept - { - token_buffer.clear(); - token_string.clear(); - token_string.push_back(std::char_traits::to_char_type(current)); - } - - /* - @brief get next character from the input - - This function provides the interface to the used input adapter. It does - not throw in case the input reached EOF, but returns a - `std::char_traits::eof()` in that case. Stores the scanned characters - for use in error messages. - - @return character read from the input - */ - char_int_type get() - { - ++position.chars_read_total; - ++position.chars_read_current_line; - - if (next_unget) - { - // just reset the next_unget variable and work with current - next_unget = false; - } - else - { - current = ia.get_character(); - } - - if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) - { - token_string.push_back(std::char_traits::to_char_type(current)); - } - - if (current == '\n') - { - ++position.lines_read; - position.chars_read_current_line = 0; - } - - return current; - } - - /*! - @brief unget current character (read it again on next get) - - We implement unget by setting variable next_unget to true. The input is not - changed - we just simulate ungetting by modifying chars_read_total, - chars_read_current_line, and token_string. The next call to get() will - behave as if the unget character is read again. - */ - void unget() - { - next_unget = true; - - --position.chars_read_total; - - // in case we "unget" a newline, we have to also decrement the lines_read - if (position.chars_read_current_line == 0) - { - if (position.lines_read > 0) - { - --position.lines_read; - } - } - else - { - --position.chars_read_current_line; - } - - if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) - { - JSON_ASSERT(!token_string.empty()); - token_string.pop_back(); - } - } - - /// add a character to token_buffer - void add(char_int_type c) - { - token_buffer.push_back(static_cast(c)); - } - - public: - ///////////////////// - // value getters - ///////////////////// - - /// return integer value - constexpr number_integer_t get_number_integer() const noexcept - { - return value_integer; - } - - /// return unsigned integer value - constexpr number_unsigned_t get_number_unsigned() const noexcept - { - return value_unsigned; - } - - /// return floating-point value - constexpr number_float_t get_number_float() const noexcept - { - return value_float; - } - - /// return current string value (implicitly resets the token; useful only once) - string_t& get_string() - { - return token_buffer; - } - - ///////////////////// - // diagnostics - ///////////////////// - - /// return position of last read token - constexpr position_t get_position() const noexcept - { - return position; - } - - /// return the last read token (for errors only). Will never contain EOF - /// (an arbitrary value that is not a valid char value, often -1), because - /// 255 may legitimately occur. May contain NUL, which should be escaped. - std::string get_token_string() const - { - // escape control characters - std::string result; - for (const auto c : token_string) - { - if (static_cast(c) <= '\x1F') - { - // escape control characters - std::array cs{{}}; - (std::snprintf)(cs.data(), cs.size(), "", static_cast(c)); - result += cs.data(); - } - else - { - // add character as is - result.push_back(static_cast(c)); - } - } - - return result; - } - - /// return syntax error message - JSON_HEDLEY_RETURNS_NON_NULL - constexpr const char* get_error_message() const noexcept - { - return error_message; - } - - ///////////////////// - // actual scanner - ///////////////////// - - /*! - @brief skip the UTF-8 byte order mark - @return true iff there is no BOM or the correct BOM has been skipped - */ - bool skip_bom() - { - if (get() == 0xEF) - { - // check if we completely parse the BOM - return get() == 0xBB && get() == 0xBF; - } - - // the first character is not the beginning of the BOM; unget it to - // process is later - unget(); - return true; - } - - void skip_whitespace() - { - do - { - get(); - } - while (current == ' ' || current == '\t' || current == '\n' || current == '\r'); - } - - token_type scan() - { - // initially, skip the BOM - if (position.chars_read_total == 0 && !skip_bom()) - { - error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; - return token_type::parse_error; - } - - // read next character and ignore whitespace - skip_whitespace(); - - // ignore comments - while (ignore_comments && current == '/') - { - if (!scan_comment()) - { - return token_type::parse_error; - } - - // skip following whitespace - skip_whitespace(); - } - - switch (current) - { - // structural characters - case '[': - return token_type::begin_array; - case ']': - return token_type::end_array; - case '{': - return token_type::begin_object; - case '}': - return token_type::end_object; - case ':': - return token_type::name_separator; - case ',': - return token_type::value_separator; - - // literals - case 't': - { - std::array true_literal = {{'t', 'r', 'u', 'e'}}; - return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); - } - case 'f': - { - std::array false_literal = {{'f', 'a', 'l', 's', 'e'}}; - return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); - } - case 'n': - { - std::array null_literal = {{'n', 'u', 'l', 'l'}}; - return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); - } - - // string - case '\"': - return scan_string(); - - // number - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return scan_number(); - - // end of input (the null byte is needed when parsing from - // string literals) - case '\0': - case std::char_traits::eof(): - return token_type::end_of_input; - - // error - default: - error_message = "invalid literal"; - return token_type::parse_error; - } - } - - private: - /// input adapter - InputAdapterType ia; - - /// whether comments should be ignored (true) or signaled as errors (false) - const bool ignore_comments = false; - - /// the current character - char_int_type current = std::char_traits::eof(); - - /// whether the next get() call should just return current - bool next_unget = false; - - /// the start position of the current token - position_t position {}; - - /// raw input token string (for error messages) - std::vector token_string {}; - - /// buffer for variable-length tokens (numbers, strings) - string_t token_buffer {}; - - /// a description of occurred lexer errors - const char* error_message = ""; - - // number values - number_integer_t value_integer = 0; - number_unsigned_t value_unsigned = 0; - number_float_t value_float = 0; - - /// the decimal point - const char_int_type decimal_point_char = '.'; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - - -#include // size_t -#include // declval -#include // string - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template -using null_function_t = decltype(std::declval().null()); - -template -using boolean_function_t = - decltype(std::declval().boolean(std::declval())); - -template -using number_integer_function_t = - decltype(std::declval().number_integer(std::declval())); - -template -using number_unsigned_function_t = - decltype(std::declval().number_unsigned(std::declval())); - -template -using number_float_function_t = decltype(std::declval().number_float( - std::declval(), std::declval())); - -template -using string_function_t = - decltype(std::declval().string(std::declval())); - -template -using binary_function_t = - decltype(std::declval().binary(std::declval())); - -template -using start_object_function_t = - decltype(std::declval().start_object(std::declval())); - -template -using key_function_t = - decltype(std::declval().key(std::declval())); - -template -using end_object_function_t = decltype(std::declval().end_object()); - -template -using start_array_function_t = - decltype(std::declval().start_array(std::declval())); - -template -using end_array_function_t = decltype(std::declval().end_array()); - -template -using parse_error_function_t = decltype(std::declval().parse_error( - std::declval(), std::declval(), - std::declval())); - -template -struct is_sax -{ - private: - static_assert(is_basic_json::value, - "BasicJsonType must be of type basic_json<...>"); - - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using exception_t = typename BasicJsonType::exception; - - public: - static constexpr bool value = - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value; -}; - -template -struct is_sax_static_asserts -{ - private: - static_assert(is_basic_json::value, - "BasicJsonType must be of type basic_json<...>"); - - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using exception_t = typename BasicJsonType::exception; - - public: - static_assert(is_detected_exact::value, - "Missing/invalid function: bool null()"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool boolean(bool)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool boolean(bool)"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool number_integer(number_integer_t)"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool number_unsigned(number_unsigned_t)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool number_float(number_float_t, const string_t&)"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool string(string_t&)"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool binary(binary_t&)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool start_object(std::size_t)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool key(string_t&)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool end_object()"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool start_array(std::size_t)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool end_array()"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool parse_error(std::size_t, const " - "std::string&, const exception&)"); -}; -} // namespace detail -} // namespace nlohmann - -// #include - - -namespace nlohmann -{ -namespace detail -{ - -/// how to treat CBOR tags -enum class cbor_tag_handler_t -{ - error, ///< throw a parse_error exception in case of a tag - ignore ///< ignore tags -}; - -/*! -@brief determine system byte order - -@return true if and only if system's byte order is little endian - -@note from https://stackoverflow.com/a/1001328/266378 -*/ -static inline bool little_endianess(int num = 1) noexcept -{ - return *reinterpret_cast(&num) == 1; -} - - -/////////////////// -// binary reader // -/////////////////// - -/*! -@brief deserialization of CBOR, MessagePack, and UBJSON values -*/ -template> -class binary_reader -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using json_sax_t = SAX; - using char_type = typename InputAdapterType::char_type; - using char_int_type = typename std::char_traits::int_type; - - public: - /*! - @brief create a binary reader - - @param[in] adapter input adapter to read from - */ - explicit binary_reader(InputAdapterType&& adapter) : ia(std::move(adapter)) - { - (void)detail::is_sax_static_asserts {}; - } - - // make class move-only - binary_reader(const binary_reader&) = delete; - binary_reader(binary_reader&&) = default; - binary_reader& operator=(const binary_reader&) = delete; - binary_reader& operator=(binary_reader&&) = default; - ~binary_reader() = default; - - /*! - @param[in] format the binary format to parse - @param[in] sax_ a SAX event processor - @param[in] strict whether to expect the input to be consumed completed - @param[in] tag_handler how to treat CBOR tags - - @return - */ - JSON_HEDLEY_NON_NULL(3) - bool sax_parse(const input_format_t format, - json_sax_t* sax_, - const bool strict = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - sax = sax_; - bool result = false; - - switch (format) - { - case input_format_t::bson: - result = parse_bson_internal(); - break; - - case input_format_t::cbor: - result = parse_cbor_internal(true, tag_handler); - break; - - case input_format_t::msgpack: - result = parse_msgpack_internal(); - break; - - case input_format_t::ubjson: - result = parse_ubjson_internal(); - break; - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - - // strict mode: next byte must be EOF - if (result && strict) - { - if (format == input_format_t::ubjson) - { - get_ignore_noop(); - } - else - { - get(); - } - - if (JSON_HEDLEY_UNLIKELY(current != std::char_traits::eof())) - { - return sax->parse_error(chars_read, get_token_string(), - parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"))); - } - } - - return result; - } - - private: - ////////// - // BSON // - ////////// - - /*! - @brief Reads in a BSON-object and passes it to the SAX-parser. - @return whether a valid BSON-value was passed to the SAX parser - */ - bool parse_bson_internal() - { - std::int32_t document_size{}; - get_number(input_format_t::bson, document_size); - - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false))) - { - return false; - } - - return sax->end_object(); - } - - /*! - @brief Parses a C-style string from the BSON input. - @param[in, out] result A reference to the string variable where the read - string is to be stored. - @return `true` if the \x00-byte indicating the end of the string was - encountered before the EOF; false` indicates an unexpected EOF. - */ - bool get_bson_cstr(string_t& result) - { - auto out = std::back_inserter(result); - while (true) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) - { - return false; - } - if (current == 0x00) - { - return true; - } - *out++ = static_cast(current); - } - } - - /*! - @brief Parses a zero-terminated string of length @a len from the BSON - input. - @param[in] len The length (including the zero-byte at the end) of the - string to be read. - @param[in, out] result A reference to the string variable where the read - string is to be stored. - @tparam NumberType The type of the length @a len - @pre len >= 1 - @return `true` if the string was successfully parsed - */ - template - bool get_bson_string(const NumberType len, string_t& result) - { - if (JSON_HEDLEY_UNLIKELY(len < 1)) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"))); - } - - return get_string(input_format_t::bson, len - static_cast(1), result) && get() != std::char_traits::eof(); - } - - /*! - @brief Parses a byte array input of length @a len from the BSON input. - @param[in] len The length of the byte array to be read. - @param[in, out] result A reference to the binary variable where the read - array is to be stored. - @tparam NumberType The type of the length @a len - @pre len >= 0 - @return `true` if the byte array was successfully parsed - */ - template - bool get_bson_binary(const NumberType len, binary_t& result) - { - if (JSON_HEDLEY_UNLIKELY(len < 0)) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"))); - } - - // All BSON binary values have a subtype - std::uint8_t subtype{}; - get_number(input_format_t::bson, subtype); - result.set_subtype(subtype); - - return get_binary(input_format_t::bson, len, result); - } - - /*! - @brief Read a BSON document element of the given @a element_type. - @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html - @param[in] element_type_parse_position The position in the input stream, - where the `element_type` was read. - @warning Not all BSON element types are supported yet. An unsupported - @a element_type will give rise to a parse_error.114: - Unsupported BSON record type 0x... - @return whether a valid BSON-object/array was passed to the SAX parser - */ - bool parse_bson_element_internal(const char_int_type element_type, - const std::size_t element_type_parse_position) - { - switch (element_type) - { - case 0x01: // double - { - double number{}; - return get_number(input_format_t::bson, number) && sax->number_float(static_cast(number), ""); - } - - case 0x02: // string - { - std::int32_t len{}; - string_t value; - return get_number(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value); - } - - case 0x03: // object - { - return parse_bson_internal(); - } - - case 0x04: // array - { - return parse_bson_array(); - } - - case 0x05: // binary - { - std::int32_t len{}; - binary_t value; - return get_number(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value); - } - - case 0x08: // boolean - { - return sax->boolean(get() != 0); - } - - case 0x0A: // null - { - return sax->null(); - } - - case 0x10: // int32 - { - std::int32_t value{}; - return get_number(input_format_t::bson, value) && sax->number_integer(value); - } - - case 0x12: // int64 - { - std::int64_t value{}; - return get_number(input_format_t::bson, value) && sax->number_integer(value); - } - - default: // anything else not supported (yet) - { - std::array cr{{}}; - (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type)); - return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()))); - } - } - } - - /*! - @brief Read a BSON element list (as specified in the BSON-spec) - - The same binary layout is used for objects and arrays, hence it must be - indicated with the argument @a is_array which one is expected - (true --> array, false --> object). - - @param[in] is_array Determines if the element list being read is to be - treated as an object (@a is_array == false), or as an - array (@a is_array == true). - @return whether a valid BSON-object/array was passed to the SAX parser - */ - bool parse_bson_element_list(const bool is_array) - { - string_t key; - - while (auto element_type = get()) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) - { - return false; - } - - const std::size_t element_type_parse_position = chars_read; - if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) - { - return false; - } - - if (!is_array && !sax->key(key)) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) - { - return false; - } - - // get_bson_cstr only appends - key.clear(); - } - - return true; - } - - /*! - @brief Reads an array from the BSON input and passes it to the SAX-parser. - @return whether a valid BSON-array was passed to the SAX parser - */ - bool parse_bson_array() - { - std::int32_t document_size{}; - get_number(input_format_t::bson, document_size); - - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true))) - { - return false; - } - - return sax->end_array(); - } - - ////////// - // CBOR // - ////////// - - /*! - @param[in] get_char whether a new character should be retrieved from the - input (true) or whether the last read character should - be considered instead (false) - @param[in] tag_handler how CBOR tags should be treated - - @return whether a valid CBOR value was passed to the SAX parser - */ - bool parse_cbor_internal(const bool get_char, - const cbor_tag_handler_t tag_handler) - { - switch (get_char ? get() : current) - { - // EOF - case std::char_traits::eof(): - return unexpect_eof(input_format_t::cbor, "value"); - - // Integer 0x00..0x17 (0..23) - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - return sax->number_unsigned(static_cast(current)); - - case 0x18: // Unsigned integer (one-byte uint8_t follows) - { - std::uint8_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } - - case 0x19: // Unsigned integer (two-byte uint16_t follows) - { - std::uint16_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } - - case 0x1A: // Unsigned integer (four-byte uint32_t follows) - { - std::uint32_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } - - case 0x1B: // Unsigned integer (eight-byte uint64_t follows) - { - std::uint64_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } - - // Negative integer -1-0x00..-1-0x17 (-1..-24) - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - return sax->number_integer(static_cast(0x20 - 1 - current)); - - case 0x38: // Negative integer (one-byte uint8_t follows) - { - std::uint8_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); - } - - case 0x39: // Negative integer -1-n (two-byte uint16_t follows) - { - std::uint16_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); - } - - case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) - { - std::uint32_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); - } - - case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) - { - std::uint64_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - - static_cast(number)); - } - - // Binary data (0x00..0x17 bytes follow) - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: // Binary data (one-byte uint8_t for n follows) - case 0x59: // Binary data (two-byte uint16_t for n follow) - case 0x5A: // Binary data (four-byte uint32_t for n follow) - case 0x5B: // Binary data (eight-byte uint64_t for n follow) - case 0x5F: // Binary data (indefinite length) - { - binary_t b; - return get_cbor_binary(b) && sax->binary(b); - } - - // UTF-8 string (0x00..0x17 bytes follow) - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - case 0x78: // UTF-8 string (one-byte uint8_t for n follows) - case 0x79: // UTF-8 string (two-byte uint16_t for n follow) - case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) - case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) - case 0x7F: // UTF-8 string (indefinite length) - { - string_t s; - return get_cbor_string(s) && sax->string(s); - } - - // array (0x00..0x17 data items follow) - case 0x80: - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x85: - case 0x86: - case 0x87: - case 0x88: - case 0x89: - case 0x8A: - case 0x8B: - case 0x8C: - case 0x8D: - case 0x8E: - case 0x8F: - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - return get_cbor_array(static_cast(static_cast(current) & 0x1Fu), tag_handler); - - case 0x98: // array (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } - - case 0x99: // array (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } - - case 0x9A: // array (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } - - case 0x9B: // array (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } - - case 0x9F: // array (indefinite length) - return get_cbor_array(std::size_t(-1), tag_handler); - - // map (0x00..0x17 pairs of data items follow) - case 0xA0: - case 0xA1: - case 0xA2: - case 0xA3: - case 0xA4: - case 0xA5: - case 0xA6: - case 0xA7: - case 0xA8: - case 0xA9: - case 0xAA: - case 0xAB: - case 0xAC: - case 0xAD: - case 0xAE: - case 0xAF: - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - return get_cbor_object(static_cast(static_cast(current) & 0x1Fu), tag_handler); - - case 0xB8: // map (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } - - case 0xB9: // map (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } - - case 0xBA: // map (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } - - case 0xBB: // map (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } - - case 0xBF: // map (indefinite length) - return get_cbor_object(std::size_t(-1), tag_handler); - - case 0xC6: // tagged item - case 0xC7: - case 0xC8: - case 0xC9: - case 0xCA: - case 0xCB: - case 0xCC: - case 0xCD: - case 0xCE: - case 0xCF: - case 0xD0: - case 0xD1: - case 0xD2: - case 0xD3: - case 0xD4: - case 0xD8: // tagged item (1 bytes follow) - case 0xD9: // tagged item (2 bytes follow) - case 0xDA: // tagged item (4 bytes follow) - case 0xDB: // tagged item (8 bytes follow) - { - switch (tag_handler) - { - case cbor_tag_handler_t::error: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"))); - } - - case cbor_tag_handler_t::ignore: - { - switch (current) - { - case 0xD8: - { - std::uint8_t len{}; - get_number(input_format_t::cbor, len); - break; - } - case 0xD9: - { - std::uint16_t len{}; - get_number(input_format_t::cbor, len); - break; - } - case 0xDA: - { - std::uint32_t len{}; - get_number(input_format_t::cbor, len); - break; - } - case 0xDB: - { - std::uint64_t len{}; - get_number(input_format_t::cbor, len); - break; - } - default: - break; - } - return parse_cbor_internal(true, tag_handler); - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - return false; // LCOV_EXCL_LINE - } - } - - case 0xF4: // false - return sax->boolean(false); - - case 0xF5: // true - return sax->boolean(true); - - case 0xF6: // null - return sax->null(); - - case 0xF9: // Half-Precision Float (two-byte IEEE 754) - { - const auto byte1_raw = get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) - { - return false; - } - const auto byte2_raw = get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) - { - return false; - } - - const auto byte1 = static_cast(byte1_raw); - const auto byte2 = static_cast(byte2_raw); - - // code from RFC 7049, Appendix D, Figure 3: - // As half-precision floating-point numbers were only added - // to IEEE 754 in 2008, today's programming platforms often - // still only have limited support for them. It is very - // easy to include at least decoding support for them even - // without such support. An example of a small decoder for - // half-precision floating-point numbers in the C language - // is shown in Fig. 3. - const auto half = static_cast((byte1 << 8u) + byte2); - const double val = [&half] - { - const int exp = (half >> 10u) & 0x1Fu; - const unsigned int mant = half & 0x3FFu; - JSON_ASSERT(0 <= exp&& exp <= 32); - JSON_ASSERT(mant <= 1024); - switch (exp) - { - case 0: - return std::ldexp(mant, -24); - case 31: - return (mant == 0) - ? std::numeric_limits::infinity() - : std::numeric_limits::quiet_NaN(); - default: - return std::ldexp(mant + 1024, exp - 25); - } - }(); - return sax->number_float((half & 0x8000u) != 0 - ? static_cast(-val) - : static_cast(val), ""); - } - - case 0xFA: // Single-Precision Float (four-byte IEEE 754) - { - float number{}; - return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); - } - - case 0xFB: // Double-Precision Float (eight-byte IEEE 754) - { - double number{}; - return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); - } - - default: // anything else (0xFF is handled inside the other types) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"))); - } - } - } - - /*! - @brief reads a CBOR string - - This function first reads starting bytes to determine the expected - string length and then copies this number of bytes into a string. - Additionally, CBOR's strings with indefinite lengths are supported. - - @param[out] result created string - - @return whether string creation completed - */ - bool get_cbor_string(string_t& result) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) - { - return false; - } - - switch (current) - { - // UTF-8 string (0x00..0x17 bytes follow) - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - { - return get_string(input_format_t::cbor, static_cast(current) & 0x1Fu, result); - } - - case 0x78: // UTF-8 string (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } - - case 0x79: // UTF-8 string (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } - - case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } - - case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } - - case 0x7F: // UTF-8 string (indefinite length) - { - while (get() != 0xFF) - { - string_t chunk; - if (!get_cbor_string(chunk)) - { - return false; - } - result.append(chunk); - } - return true; - } - - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"))); - } - } - } - - /*! - @brief reads a CBOR byte array - - This function first reads starting bytes to determine the expected - byte array length and then copies this number of bytes into the byte array. - Additionally, CBOR's byte arrays with indefinite lengths are supported. - - @param[out] result created byte array - - @return whether byte array creation completed - */ - bool get_cbor_binary(binary_t& result) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) - { - return false; - } - - switch (current) - { - // Binary data (0x00..0x17 bytes follow) - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - { - return get_binary(input_format_t::cbor, static_cast(current) & 0x1Fu, result); - } - - case 0x58: // Binary data (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } - - case 0x59: // Binary data (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } - - case 0x5A: // Binary data (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } - - case 0x5B: // Binary data (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } - - case 0x5F: // Binary data (indefinite length) - { - while (get() != 0xFF) - { - binary_t chunk; - if (!get_cbor_binary(chunk)) - { - return false; - } - result.insert(result.end(), chunk.begin(), chunk.end()); - } - return true; - } - - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"))); - } - } - } - - /*! - @param[in] len the length of the array or std::size_t(-1) for an - array of indefinite size - @param[in] tag_handler how CBOR tags should be treated - @return whether array creation completed - */ - bool get_cbor_array(const std::size_t len, - const cbor_tag_handler_t tag_handler) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) - { - return false; - } - - if (len != std::size_t(-1)) - { - for (std::size_t i = 0; i < len; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) - { - return false; - } - } - } - else - { - while (get() != 0xFF) - { - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) - { - return false; - } - } - } - - return sax->end_array(); - } - - /*! - @param[in] len the length of the object or std::size_t(-1) for an - object of indefinite size - @param[in] tag_handler how CBOR tags should be treated - @return whether object creation completed - */ - bool get_cbor_object(const std::size_t len, - const cbor_tag_handler_t tag_handler) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) - { - return false; - } - - string_t key; - if (len != std::size_t(-1)) - { - for (std::size_t i = 0; i < len; ++i) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) - { - return false; - } - key.clear(); - } - } - else - { - while (get() != 0xFF) - { - if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) - { - return false; - } - key.clear(); - } - } - - return sax->end_object(); - } - - ///////////// - // MsgPack // - ///////////// - - /*! - @return whether a valid MessagePack value was passed to the SAX parser - */ - bool parse_msgpack_internal() - { - switch (get()) - { - // EOF - case std::char_traits::eof(): - return unexpect_eof(input_format_t::msgpack, "value"); - - // positive fixint - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1A: - case 0x1B: - case 0x1C: - case 0x1D: - case 0x1E: - case 0x1F: - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3A: - case 0x3B: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: - case 0x59: - case 0x5A: - case 0x5B: - case 0x5C: - case 0x5D: - case 0x5E: - case 0x5F: - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - case 0x78: - case 0x79: - case 0x7A: - case 0x7B: - case 0x7C: - case 0x7D: - case 0x7E: - case 0x7F: - return sax->number_unsigned(static_cast(current)); - - // fixmap - case 0x80: - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x85: - case 0x86: - case 0x87: - case 0x88: - case 0x89: - case 0x8A: - case 0x8B: - case 0x8C: - case 0x8D: - case 0x8E: - case 0x8F: - return get_msgpack_object(static_cast(static_cast(current) & 0x0Fu)); - - // fixarray - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - case 0x98: - case 0x99: - case 0x9A: - case 0x9B: - case 0x9C: - case 0x9D: - case 0x9E: - case 0x9F: - return get_msgpack_array(static_cast(static_cast(current) & 0x0Fu)); - - // fixstr - case 0xA0: - case 0xA1: - case 0xA2: - case 0xA3: - case 0xA4: - case 0xA5: - case 0xA6: - case 0xA7: - case 0xA8: - case 0xA9: - case 0xAA: - case 0xAB: - case 0xAC: - case 0xAD: - case 0xAE: - case 0xAF: - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - case 0xB8: - case 0xB9: - case 0xBA: - case 0xBB: - case 0xBC: - case 0xBD: - case 0xBE: - case 0xBF: - case 0xD9: // str 8 - case 0xDA: // str 16 - case 0xDB: // str 32 - { - string_t s; - return get_msgpack_string(s) && sax->string(s); - } - - case 0xC0: // nil - return sax->null(); - - case 0xC2: // false - return sax->boolean(false); - - case 0xC3: // true - return sax->boolean(true); - - case 0xC4: // bin 8 - case 0xC5: // bin 16 - case 0xC6: // bin 32 - case 0xC7: // ext 8 - case 0xC8: // ext 16 - case 0xC9: // ext 32 - case 0xD4: // fixext 1 - case 0xD5: // fixext 2 - case 0xD6: // fixext 4 - case 0xD7: // fixext 8 - case 0xD8: // fixext 16 - { - binary_t b; - return get_msgpack_binary(b) && sax->binary(b); - } - - case 0xCA: // float 32 - { - float number{}; - return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); - } - - case 0xCB: // float 64 - { - double number{}; - return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); - } - - case 0xCC: // uint 8 - { - std::uint8_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } - - case 0xCD: // uint 16 - { - std::uint16_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } - - case 0xCE: // uint 32 - { - std::uint32_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } - - case 0xCF: // uint 64 - { - std::uint64_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } - - case 0xD0: // int 8 - { - std::int8_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } - - case 0xD1: // int 16 - { - std::int16_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } - - case 0xD2: // int 32 - { - std::int32_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } - - case 0xD3: // int 64 - { - std::int64_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } - - case 0xDC: // array 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); - } - - case 0xDD: // array 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); - } - - case 0xDE: // map 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); - } - - case 0xDF: // map 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); - } - - // negative fixint - case 0xE0: - case 0xE1: - case 0xE2: - case 0xE3: - case 0xE4: - case 0xE5: - case 0xE6: - case 0xE7: - case 0xE8: - case 0xE9: - case 0xEA: - case 0xEB: - case 0xEC: - case 0xED: - case 0xEE: - case 0xEF: - case 0xF0: - case 0xF1: - case 0xF2: - case 0xF3: - case 0xF4: - case 0xF5: - case 0xF6: - case 0xF7: - case 0xF8: - case 0xF9: - case 0xFA: - case 0xFB: - case 0xFC: - case 0xFD: - case 0xFE: - case 0xFF: - return sax->number_integer(static_cast(current)); - - default: // anything else - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"))); - } - } - } - - /*! - @brief reads a MessagePack string - - This function first reads starting bytes to determine the expected - string length and then copies this number of bytes into a string. - - @param[out] result created string - - @return whether string creation completed - */ - bool get_msgpack_string(string_t& result) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) - { - return false; - } - - switch (current) - { - // fixstr - case 0xA0: - case 0xA1: - case 0xA2: - case 0xA3: - case 0xA4: - case 0xA5: - case 0xA6: - case 0xA7: - case 0xA8: - case 0xA9: - case 0xAA: - case 0xAB: - case 0xAC: - case 0xAD: - case 0xAE: - case 0xAF: - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - case 0xB8: - case 0xB9: - case 0xBA: - case 0xBB: - case 0xBC: - case 0xBD: - case 0xBE: - case 0xBF: - { - return get_string(input_format_t::msgpack, static_cast(current) & 0x1Fu, result); - } - - case 0xD9: // str 8 - { - std::uint8_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); - } - - case 0xDA: // str 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); - } - - case 0xDB: // str 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); - } - - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"))); - } - } - } - - /*! - @brief reads a MessagePack byte array - - This function first reads starting bytes to determine the expected - byte array length and then copies this number of bytes into a byte array. - - @param[out] result created byte array - - @return whether byte array creation completed - */ - bool get_msgpack_binary(binary_t& result) - { - // helper function to set the subtype - auto assign_and_return_true = [&result](std::int8_t subtype) - { - result.set_subtype(static_cast(subtype)); - return true; - }; - - switch (current) - { - case 0xC4: // bin 8 - { - std::uint8_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); - } - - case 0xC5: // bin 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); - } - - case 0xC6: // bin 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); - } - - case 0xC7: // ext 8 - { - std::uint8_t len{}; - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && - assign_and_return_true(subtype); - } - - case 0xC8: // ext 16 - { - std::uint16_t len{}; - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && - assign_and_return_true(subtype); - } - - case 0xC9: // ext 32 - { - std::uint32_t len{}; - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && - assign_and_return_true(subtype); - } - - case 0xD4: // fixext 1 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 1, result) && - assign_and_return_true(subtype); - } - - case 0xD5: // fixext 2 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 2, result) && - assign_and_return_true(subtype); - } - - case 0xD6: // fixext 4 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 4, result) && - assign_and_return_true(subtype); - } - - case 0xD7: // fixext 8 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 8, result) && - assign_and_return_true(subtype); - } - - case 0xD8: // fixext 16 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 16, result) && - assign_and_return_true(subtype); - } - - default: // LCOV_EXCL_LINE - return false; // LCOV_EXCL_LINE - } - } - - /*! - @param[in] len the length of the array - @return whether array creation completed - */ - bool get_msgpack_array(const std::size_t len) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) - { - return false; - } - - for (std::size_t i = 0; i < len; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) - { - return false; - } - } - - return sax->end_array(); - } - - /*! - @param[in] len the length of the object - @return whether object creation completed - */ - bool get_msgpack_object(const std::size_t len) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) - { - return false; - } - - string_t key; - for (std::size_t i = 0; i < len; ++i) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) - { - return false; - } - key.clear(); - } - - return sax->end_object(); - } - - //////////// - // UBJSON // - //////////// - - /*! - @param[in] get_char whether a new character should be retrieved from the - input (true, default) or whether the last read - character should be considered instead - - @return whether a valid UBJSON value was passed to the SAX parser - */ - bool parse_ubjson_internal(const bool get_char = true) - { - return get_ubjson_value(get_char ? get_ignore_noop() : current); - } - - /*! - @brief reads a UBJSON string - - This function is either called after reading the 'S' byte explicitly - indicating a string, or in case of an object key where the 'S' byte can be - left out. - - @param[out] result created string - @param[in] get_char whether a new character should be retrieved from the - input (true, default) or whether the last read - character should be considered instead - - @return whether string creation completed - */ - bool get_ubjson_string(string_t& result, const bool get_char = true) - { - if (get_char) - { - get(); // TODO(niels): may we ignore N here? - } - - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) - { - return false; - } - - switch (current) - { - case 'U': - { - std::uint8_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - case 'i': - { - std::int8_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - case 'I': - { - std::int16_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - case 'l': - { - std::int32_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - case 'L': - { - std::int64_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - default: - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"))); - } - } - - /*! - @param[out] result determined size - @return whether size determination completed - */ - bool get_ubjson_size_value(std::size_t& result) - { - switch (get_ignore_noop()) - { - case 'U': - { - std::uint8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - case 'i': - { - std::int8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - case 'I': - { - std::int16_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - case 'l': - { - std::int32_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - case 'L': - { - std::int64_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"))); - } - } - } - - /*! - @brief determine the type and size for a container - - In the optimized UBJSON format, a type and a size can be provided to allow - for a more compact representation. - - @param[out] result pair of the size and the type - - @return whether pair creation completed - */ - bool get_ubjson_size_type(std::pair& result) - { - result.first = string_t::npos; // size - result.second = 0; // type - - get_ignore_noop(); - - if (current == '$') - { - result.second = get(); // must not ignore 'N', because 'N' maybe the type - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type"))) - { - return false; - } - - get_ignore_noop(); - if (JSON_HEDLEY_UNLIKELY(current != '#')) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) - { - return false; - } - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"))); - } - - return get_ubjson_size_value(result.first); - } - - if (current == '#') - { - return get_ubjson_size_value(result.first); - } - - return true; - } - - /*! - @param prefix the previously read or set type prefix - @return whether value creation completed - */ - bool get_ubjson_value(const char_int_type prefix) - { - switch (prefix) - { - case std::char_traits::eof(): // EOF - return unexpect_eof(input_format_t::ubjson, "value"); - - case 'T': // true - return sax->boolean(true); - case 'F': // false - return sax->boolean(false); - - case 'Z': // null - return sax->null(); - - case 'U': - { - std::uint8_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number); - } - - case 'i': - { - std::int8_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); - } - - case 'I': - { - std::int16_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); - } - - case 'l': - { - std::int32_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); - } - - case 'L': - { - std::int64_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); - } - - case 'd': - { - float number{}; - return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); - } - - case 'D': - { - double number{}; - return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); - } - - case 'H': - { - return get_ubjson_high_precision_number(); - } - - case 'C': // char - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char"))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(current > 127)) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"))); - } - string_t s(1, static_cast(current)); - return sax->string(s); - } - - case 'S': // string - { - string_t s; - return get_ubjson_string(s) && sax->string(s); - } - - case '[': // array - return get_ubjson_array(); - - case '{': // object - return get_ubjson_object(); - - default: // anything else - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"))); - } - } - } - - /*! - @return whether array creation completed - */ - bool get_ubjson_array() - { - std::pair size_and_type; - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) - { - return false; - } - - if (size_and_type.first != string_t::npos) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) - { - return false; - } - - if (size_and_type.second != 0) - { - if (size_and_type.second != 'N') - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) - { - return false; - } - } - } - } - else - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) - { - return false; - } - } - } - } - else - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) - { - return false; - } - - while (current != ']') - { - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) - { - return false; - } - get_ignore_noop(); - } - } - - return sax->end_array(); - } - - /*! - @return whether object creation completed - */ - bool get_ubjson_object() - { - std::pair size_and_type; - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) - { - return false; - } - - string_t key; - if (size_and_type.first != string_t::npos) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) - { - return false; - } - - if (size_and_type.second != 0) - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) - { - return false; - } - key.clear(); - } - } - else - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) - { - return false; - } - key.clear(); - } - } - } - else - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) - { - return false; - } - - while (current != '}') - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) - { - return false; - } - get_ignore_noop(); - key.clear(); - } - } - - return sax->end_object(); - } - - // Note, no reader for UBJSON binary types is implemented because they do - // not exist - - bool get_ubjson_high_precision_number() - { - // get size of following number string - std::size_t size{}; - auto res = get_ubjson_size_value(size); - if (JSON_HEDLEY_UNLIKELY(!res)) - { - return res; - } - - // get number string - std::vector number_vector; - for (std::size_t i = 0; i < size; ++i) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number"))) - { - return false; - } - number_vector.push_back(static_cast(current)); - } - - // parse number string - auto number_ia = detail::input_adapter(std::forward(number_vector)); - auto number_lexer = detail::lexer(std::move(number_ia), false); - const auto result_number = number_lexer.scan(); - const auto number_string = number_lexer.get_token_string(); - const auto result_remainder = number_lexer.scan(); - - using token_type = typename detail::lexer_base::token_type; - - if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) - { - return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"))); - } - - switch (result_number) - { - case token_type::value_integer: - return sax->number_integer(number_lexer.get_number_integer()); - case token_type::value_unsigned: - return sax->number_unsigned(number_lexer.get_number_unsigned()); - case token_type::value_float: - return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); - default: - return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"))); - } - } - - /////////////////////// - // Utility functions // - /////////////////////// - - /*! - @brief get next character from the input - - This function provides the interface to the used input adapter. It does - not throw in case the input reached EOF, but returns a -'ve valued - `std::char_traits::eof()` in that case. - - @return character read from the input - */ - char_int_type get() - { - ++chars_read; - return current = ia.get_character(); - } - - /*! - @return character read from the input after ignoring all 'N' entries - */ - char_int_type get_ignore_noop() - { - do - { - get(); - } - while (current == 'N'); - - return current; - } - - /* - @brief read a number from the input - - @tparam NumberType the type of the number - @param[in] format the current format (for diagnostics) - @param[out] result number of type @a NumberType - - @return whether conversion completed - - @note This function needs to respect the system's endianess, because - bytes in CBOR, MessagePack, and UBJSON are stored in network order - (big endian) and therefore need reordering on little endian systems. - */ - template - bool get_number(const input_format_t format, NumberType& result) - { - // step 1: read input into array with system's byte order - std::array vec; - for (std::size_t i = 0; i < sizeof(NumberType); ++i) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) - { - return false; - } - - // reverse byte order prior to conversion if necessary - if (is_little_endian != InputIsLittleEndian) - { - vec[sizeof(NumberType) - i - 1] = static_cast(current); - } - else - { - vec[i] = static_cast(current); // LCOV_EXCL_LINE - } - } - - // step 2: convert array into number of type T and return - std::memcpy(&result, vec.data(), sizeof(NumberType)); - return true; - } - - /*! - @brief create a string by reading characters from the input - - @tparam NumberType the type of the number - @param[in] format the current format (for diagnostics) - @param[in] len number of characters to read - @param[out] result string created by reading @a len bytes - - @return whether string creation completed - - @note We can not reserve @a len bytes for the result, because @a len - may be too large. Usually, @ref unexpect_eof() detects the end of - the input before we run out of string memory. - */ - template - bool get_string(const input_format_t format, - const NumberType len, - string_t& result) - { - bool success = true; - for (NumberType i = 0; i < len; i++) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) - { - success = false; - break; - } - result.push_back(static_cast(current)); - }; - return success; - } - - /*! - @brief create a byte array by reading bytes from the input - - @tparam NumberType the type of the number - @param[in] format the current format (for diagnostics) - @param[in] len number of bytes to read - @param[out] result byte array created by reading @a len bytes - - @return whether byte array creation completed - - @note We can not reserve @a len bytes for the result, because @a len - may be too large. Usually, @ref unexpect_eof() detects the end of - the input before we run out of memory. - */ - template - bool get_binary(const input_format_t format, - const NumberType len, - binary_t& result) - { - bool success = true; - for (NumberType i = 0; i < len; i++) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) - { - success = false; - break; - } - result.push_back(static_cast(current)); - } - return success; - } - - /*! - @param[in] format the current format (for diagnostics) - @param[in] context further context information (for diagnostics) - @return whether the last read character is not EOF - */ - JSON_HEDLEY_NON_NULL(3) - bool unexpect_eof(const input_format_t format, const char* context) const - { - if (JSON_HEDLEY_UNLIKELY(current == std::char_traits::eof())) - { - return sax->parse_error(chars_read, "", - parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context))); - } - return true; - } - - /*! - @return a string representation of the last read byte - */ - std::string get_token_string() const - { - std::array cr{{}}; - (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(current)); - return std::string{cr.data()}; - } - - /*! - @param[in] format the current format - @param[in] detail a detailed error message - @param[in] context further context information - @return a message string to use in the parse_error exceptions - */ - std::string exception_message(const input_format_t format, - const std::string& detail, - const std::string& context) const - { - std::string error_msg = "syntax error while parsing "; - - switch (format) - { - case input_format_t::cbor: - error_msg += "CBOR"; - break; - - case input_format_t::msgpack: - error_msg += "MessagePack"; - break; - - case input_format_t::ubjson: - error_msg += "UBJSON"; - break; - - case input_format_t::bson: - error_msg += "BSON"; - break; - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - - return error_msg + " " + context + ": " + detail; - } - - private: - /// input adapter - InputAdapterType ia; - - /// the current character - char_int_type current = std::char_traits::eof(); - - /// the number of characters read - std::size_t chars_read = 0; - - /// whether we can assume little endianess - const bool is_little_endian = little_endianess(); - - /// the SAX parser - json_sax_t* sax = nullptr; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - -// #include - - -#include // isfinite -#include // uint8_t -#include // function -#include // string -#include // move -#include // vector - -// #include - -// #include - -// #include - -// #include - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -//////////// -// parser // -//////////// - -enum class parse_event_t : uint8_t -{ - /// the parser read `{` and started to process a JSON object - object_start, - /// the parser read `}` and finished processing a JSON object - object_end, - /// the parser read `[` and started to process a JSON array - array_start, - /// the parser read `]` and finished processing a JSON array - array_end, - /// the parser read a key of a value in an object - key, - /// the parser finished reading a JSON value - value -}; - -template -using parser_callback_t = - std::function; - -/*! -@brief syntax analysis - -This class implements a recursive descent parser. -*/ -template -class parser -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using lexer_t = lexer; - using token_type = typename lexer_t::token_type; - - public: - /// a parser reading from an input adapter - explicit parser(InputAdapterType&& adapter, - const parser_callback_t cb = nullptr, - const bool allow_exceptions_ = true, - const bool skip_comments = false) - : callback(cb) - , m_lexer(std::move(adapter), skip_comments) - , allow_exceptions(allow_exceptions_) - { - // read first token - get_token(); - } - - /*! - @brief public parser interface - - @param[in] strict whether to expect the last token to be EOF - @param[in,out] result parsed JSON value - - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - */ - void parse(const bool strict, BasicJsonType& result) - { - if (callback) - { - json_sax_dom_callback_parser sdp(result, callback, allow_exceptions); - sax_parse_internal(&sdp); - result.assert_invariant(); - - // in strict mode, input must be completely read - if (strict && (get_token() != token_type::end_of_input)) - { - sdp.parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_of_input, "value"))); - } - - // in case of an error, return discarded value - if (sdp.is_errored()) - { - result = value_t::discarded; - return; - } - - // set top-level value to null if it was discarded by the callback - // function - if (result.is_discarded()) - { - result = nullptr; - } - } - else - { - json_sax_dom_parser sdp(result, allow_exceptions); - sax_parse_internal(&sdp); - result.assert_invariant(); - - // in strict mode, input must be completely read - if (strict && (get_token() != token_type::end_of_input)) - { - sdp.parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_of_input, "value"))); - } - - // in case of an error, return discarded value - if (sdp.is_errored()) - { - result = value_t::discarded; - return; - } - } - } - - /*! - @brief public accept interface - - @param[in] strict whether to expect the last token to be EOF - @return whether the input is a proper JSON text - */ - bool accept(const bool strict = true) - { - json_sax_acceptor sax_acceptor; - return sax_parse(&sax_acceptor, strict); - } - - template - JSON_HEDLEY_NON_NULL(2) - bool sax_parse(SAX* sax, const bool strict = true) - { - (void)detail::is_sax_static_asserts {}; - const bool result = sax_parse_internal(sax); - - // strict mode: next byte must be EOF - if (result && strict && (get_token() != token_type::end_of_input)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_of_input, "value"))); - } - - return result; - } - - private: - template - JSON_HEDLEY_NON_NULL(2) - bool sax_parse_internal(SAX* sax) - { - // stack to remember the hierarchy of structured values we are parsing - // true = array; false = object - std::vector states; - // value to avoid a goto (see comment where set to true) - bool skip_to_state_evaluation = false; - - while (true) - { - if (!skip_to_state_evaluation) - { - // invariant: get_token() was called before each iteration - switch (last_token) - { - case token_type::begin_object: - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) - { - return false; - } - - // closing } -> we are done - if (get_token() == token_type::end_object) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) - { - return false; - } - break; - } - - // parse key - if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::value_string, "object key"))); - } - if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) - { - return false; - } - - // parse separator (:) - if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::name_separator, "object separator"))); - } - - // remember we are now inside an object - states.push_back(false); - - // parse values - get_token(); - continue; - } - - case token_type::begin_array: - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) - { - return false; - } - - // closing ] -> we are done - if (get_token() == token_type::end_array) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) - { - return false; - } - break; - } - - // remember we are now inside an array - states.push_back(true); - - // parse values (no need to call get_token) - continue; - } - - case token_type::value_float: - { - const auto res = m_lexer.get_number_float(); - - if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'")); - } - - if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) - { - return false; - } - - break; - } - - case token_type::literal_false: - { - if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) - { - return false; - } - break; - } - - case token_type::literal_null: - { - if (JSON_HEDLEY_UNLIKELY(!sax->null())) - { - return false; - } - break; - } - - case token_type::literal_true: - { - if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) - { - return false; - } - break; - } - - case token_type::value_integer: - { - if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) - { - return false; - } - break; - } - - case token_type::value_string: - { - if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) - { - return false; - } - break; - } - - case token_type::value_unsigned: - { - if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) - { - return false; - } - break; - } - - case token_type::parse_error: - { - // using "uninitialized" to avoid "expected" message - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::uninitialized, "value"))); - } - - default: // the last token was unexpected - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::literal_or_value, "value"))); - } - } - } - else - { - skip_to_state_evaluation = false; - } - - // we reached this line after we successfully parsed a value - if (states.empty()) - { - // empty stack: we reached the end of the hierarchy: done - return true; - } - - if (states.back()) // array - { - // comma -> next value - if (get_token() == token_type::value_separator) - { - // parse a new value - get_token(); - continue; - } - - // closing ] - if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) - { - return false; - } - - // We are done with this array. Before we can parse a - // new value, we need to evaluate the new state first. - // By setting skip_to_state_evaluation to false, we - // are effectively jumping to the beginning of this if. - JSON_ASSERT(!states.empty()); - states.pop_back(); - skip_to_state_evaluation = true; - continue; - } - - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_array, "array"))); - } - else // object - { - // comma -> next value - if (get_token() == token_type::value_separator) - { - // parse key - if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::value_string, "object key"))); - } - - if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) - { - return false; - } - - // parse separator (:) - if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::name_separator, "object separator"))); - } - - // parse values - get_token(); - continue; - } - - // closing } - if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) - { - return false; - } - - // We are done with this object. Before we can parse a - // new value, we need to evaluate the new state first. - // By setting skip_to_state_evaluation to false, we - // are effectively jumping to the beginning of this if. - JSON_ASSERT(!states.empty()); - states.pop_back(); - skip_to_state_evaluation = true; - continue; - } - - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_object, "object"))); - } - } - } - - /// get next token from lexer - token_type get_token() - { - return last_token = m_lexer.scan(); - } - - std::string exception_message(const token_type expected, const std::string& context) - { - std::string error_msg = "syntax error "; - - if (!context.empty()) - { - error_msg += "while parsing " + context + " "; - } - - error_msg += "- "; - - if (last_token == token_type::parse_error) - { - error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" + - m_lexer.get_token_string() + "'"; - } - else - { - error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token)); - } - - if (expected != token_type::uninitialized) - { - error_msg += "; expected " + std::string(lexer_t::token_type_name(expected)); - } - - return error_msg; - } - - private: - /// callback function - const parser_callback_t callback = nullptr; - /// the type of the last read token - token_type last_token = token_type::uninitialized; - /// the lexer - lexer_t m_lexer; - /// whether to throw exceptions in case of errors - const bool allow_exceptions = true; -}; -} // namespace detail -} // namespace nlohmann - -// #include - - -// #include - - -#include // ptrdiff_t -#include // numeric_limits - -namespace nlohmann -{ -namespace detail -{ -/* -@brief an iterator for primitive JSON types - -This class models an iterator for primitive JSON types (boolean, number, -string). It's only purpose is to allow the iterator/const_iterator classes -to "iterate" over primitive values. Internally, the iterator is modeled by -a `difference_type` variable. Value begin_value (`0`) models the begin, -end_value (`1`) models past the end. -*/ -class primitive_iterator_t -{ - private: - using difference_type = std::ptrdiff_t; - static constexpr difference_type begin_value = 0; - static constexpr difference_type end_value = begin_value + 1; - - JSON_PRIVATE_UNLESS_TESTED: - /// iterator as signed integer type - difference_type m_it = (std::numeric_limits::min)(); - - public: - constexpr difference_type get_value() const noexcept - { - return m_it; - } - - /// set iterator to a defined beginning - void set_begin() noexcept - { - m_it = begin_value; - } - - /// set iterator to a defined past the end - void set_end() noexcept - { - m_it = end_value; - } - - /// return whether the iterator can be dereferenced - constexpr bool is_begin() const noexcept - { - return m_it == begin_value; - } - - /// return whether the iterator is at end - constexpr bool is_end() const noexcept - { - return m_it == end_value; - } - - friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it == rhs.m_it; - } - - friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it < rhs.m_it; - } - - primitive_iterator_t operator+(difference_type n) noexcept - { - auto result = *this; - result += n; - return result; - } - - friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it - rhs.m_it; - } - - primitive_iterator_t& operator++() noexcept - { - ++m_it; - return *this; - } - - primitive_iterator_t const operator++(int) noexcept - { - auto result = *this; - ++m_it; - return result; - } - - primitive_iterator_t& operator--() noexcept - { - --m_it; - return *this; - } - - primitive_iterator_t const operator--(int) noexcept - { - auto result = *this; - --m_it; - return result; - } - - primitive_iterator_t& operator+=(difference_type n) noexcept - { - m_it += n; - return *this; - } - - primitive_iterator_t& operator-=(difference_type n) noexcept - { - m_it -= n; - return *this; - } -}; -} // namespace detail -} // namespace nlohmann - - -namespace nlohmann -{ -namespace detail -{ -/*! -@brief an iterator value - -@note This structure could easily be a union, but MSVC currently does not allow -unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. -*/ -template struct internal_iterator -{ - /// iterator for JSON objects - typename BasicJsonType::object_t::iterator object_iterator {}; - /// iterator for JSON arrays - typename BasicJsonType::array_t::iterator array_iterator {}; - /// generic iterator for all other types - primitive_iterator_t primitive_iterator {}; -}; -} // namespace detail -} // namespace nlohmann - -// #include - - -#include // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next -#include // conditional, is_const, remove_const - -// #include - -// #include - -// #include - -// #include - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -// forward declare, to be able to friend it later on -template class iteration_proxy; -template class iteration_proxy_value; - -/*! -@brief a template for a bidirectional iterator for the @ref basic_json class -This class implements a both iterators (iterator and const_iterator) for the -@ref basic_json class. -@note An iterator is called *initialized* when a pointer to a JSON value has - been set (e.g., by a constructor or a copy assignment). If the iterator is - default-constructed, it is *uninitialized* and most methods are undefined. - **The library uses assertions to detect calls on uninitialized iterators.** -@requirement The class satisfies the following concept requirements: -- -[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): - The iterator that can be moved can be moved in both directions (i.e. - incremented and decremented). -@since version 1.0.0, simplified in version 2.0.9, change to bidirectional - iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) -*/ -template -class iter_impl -{ - /// allow basic_json to access private members - friend iter_impl::value, typename std::remove_const::type, const BasicJsonType>::type>; - friend BasicJsonType; - friend iteration_proxy; - friend iteration_proxy_value; - - using object_t = typename BasicJsonType::object_t; - using array_t = typename BasicJsonType::array_t; - // make sure BasicJsonType is basic_json or const basic_json - static_assert(is_basic_json::type>::value, - "iter_impl only accepts (const) basic_json"); - - public: - - /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. - /// The C++ Standard has never required user-defined iterators to derive from std::iterator. - /// A user-defined iterator should provide publicly accessible typedefs named - /// iterator_category, value_type, difference_type, pointer, and reference. - /// Note that value_type is required to be non-const, even for constant iterators. - using iterator_category = std::bidirectional_iterator_tag; - - /// the type of the values when the iterator is dereferenced - using value_type = typename BasicJsonType::value_type; - /// a type to represent differences between iterators - using difference_type = typename BasicJsonType::difference_type; - /// defines a pointer to the type iterated over (value_type) - using pointer = typename std::conditional::value, - typename BasicJsonType::const_pointer, - typename BasicJsonType::pointer>::type; - /// defines a reference to the type iterated over (value_type) - using reference = - typename std::conditional::value, - typename BasicJsonType::const_reference, - typename BasicJsonType::reference>::type; - - /// default constructor - iter_impl() = default; - - /*! - @brief constructor for a given JSON instance - @param[in] object pointer to a JSON object for this iterator - @pre object != nullptr - @post The iterator is initialized; i.e. `m_object != nullptr`. - */ - explicit iter_impl(pointer object) noexcept : m_object(object) - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - m_it.object_iterator = typename object_t::iterator(); - break; - } - - case value_t::array: - { - m_it.array_iterator = typename array_t::iterator(); - break; - } - - default: - { - m_it.primitive_iterator = primitive_iterator_t(); - break; - } - } - } - - /*! - @note The conventional copy constructor and copy assignment are implicitly - defined. Combined with the following converting constructor and - assignment, they support: (1) copy from iterator to iterator, (2) - copy from const iterator to const iterator, and (3) conversion from - iterator to const iterator. However conversion from const iterator - to iterator is not defined. - */ - - /*! - @brief const copy constructor - @param[in] other const iterator to copy from - @note This copy constructor had to be defined explicitly to circumvent a bug - occurring on msvc v19.0 compiler (VS 2015) debug build. For more - information refer to: https://github.com/nlohmann/json/issues/1608 - */ - iter_impl(const iter_impl& other) noexcept - : m_object(other.m_object), m_it(other.m_it) - {} - - /*! - @brief converting assignment - @param[in] other const iterator to copy from - @return const/non-const iterator - @note It is not checked whether @a other is initialized. - */ - iter_impl& operator=(const iter_impl& other) noexcept - { - m_object = other.m_object; - m_it = other.m_it; - return *this; - } - - /*! - @brief converting constructor - @param[in] other non-const iterator to copy from - @note It is not checked whether @a other is initialized. - */ - iter_impl(const iter_impl::type>& other) noexcept - : m_object(other.m_object), m_it(other.m_it) - {} - - /*! - @brief converting assignment - @param[in] other non-const iterator to copy from - @return const/non-const iterator - @note It is not checked whether @a other is initialized. - */ - iter_impl& operator=(const iter_impl::type>& other) noexcept - { - m_object = other.m_object; - m_it = other.m_it; - return *this; - } - - JSON_PRIVATE_UNLESS_TESTED: - /*! - @brief set the iterator to the first value - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - void set_begin() noexcept - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - m_it.object_iterator = m_object->m_value.object->begin(); - break; - } - - case value_t::array: - { - m_it.array_iterator = m_object->m_value.array->begin(); - break; - } - - case value_t::null: - { - // set to end so begin()==end() is true: null is empty - m_it.primitive_iterator.set_end(); - break; - } - - default: - { - m_it.primitive_iterator.set_begin(); - break; - } - } - } - - /*! - @brief set the iterator past the last value - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - void set_end() noexcept - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - m_it.object_iterator = m_object->m_value.object->end(); - break; - } - - case value_t::array: - { - m_it.array_iterator = m_object->m_value.array->end(); - break; - } - - default: - { - m_it.primitive_iterator.set_end(); - break; - } - } - } - - public: - /*! - @brief return a reference to the value pointed to by the iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - reference operator*() const - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); - return m_it.object_iterator->second; - } - - case value_t::array: - { - JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); - return *m_it.array_iterator; - } - - case value_t::null: - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - - default: - { - if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) - { - return *m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - } - } - } - - /*! - @brief dereference the iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - pointer operator->() const - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); - return &(m_it.object_iterator->second); - } - - case value_t::array: - { - JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); - return &*m_it.array_iterator; - } - - default: - { - if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) - { - return m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - } - } - } - - /*! - @brief post-increment (it++) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl const operator++(int) - { - auto result = *this; - ++(*this); - return result; - } - - /*! - @brief pre-increment (++it) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator++() - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - std::advance(m_it.object_iterator, 1); - break; - } - - case value_t::array: - { - std::advance(m_it.array_iterator, 1); - break; - } - - default: - { - ++m_it.primitive_iterator; - break; - } - } - - return *this; - } - - /*! - @brief post-decrement (it--) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl const operator--(int) - { - auto result = *this; - --(*this); - return result; - } - - /*! - @brief pre-decrement (--it) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator--() - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - std::advance(m_it.object_iterator, -1); - break; - } - - case value_t::array: - { - std::advance(m_it.array_iterator, -1); - break; - } - - default: - { - --m_it.primitive_iterator; - break; - } - } - - return *this; - } - - /*! - @brief comparison: equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator==(const iter_impl& other) const - { - // if objects are not the same, the comparison is undefined - if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) - { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); - } - - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - return (m_it.object_iterator == other.m_it.object_iterator); - - case value_t::array: - return (m_it.array_iterator == other.m_it.array_iterator); - - default: - return (m_it.primitive_iterator == other.m_it.primitive_iterator); - } - } - - /*! - @brief comparison: not equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator!=(const iter_impl& other) const - { - return !operator==(other); - } - - /*! - @brief comparison: smaller - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator<(const iter_impl& other) const - { - // if objects are not the same, the comparison is undefined - if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) - { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); - } - - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators")); - - case value_t::array: - return (m_it.array_iterator < other.m_it.array_iterator); - - default: - return (m_it.primitive_iterator < other.m_it.primitive_iterator); - } - } - - /*! - @brief comparison: less than or equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator<=(const iter_impl& other) const - { - return !other.operator < (*this); - } - - /*! - @brief comparison: greater than - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator>(const iter_impl& other) const - { - return !operator<=(other); - } - - /*! - @brief comparison: greater than or equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator>=(const iter_impl& other) const - { - return !operator<(other); - } - - /*! - @brief add to iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator+=(difference_type i) - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); - - case value_t::array: - { - std::advance(m_it.array_iterator, i); - break; - } - - default: - { - m_it.primitive_iterator += i; - break; - } - } - - return *this; - } - - /*! - @brief subtract from iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator-=(difference_type i) - { - return operator+=(-i); - } - - /*! - @brief add to iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl operator+(difference_type i) const - { - auto result = *this; - result += i; - return result; - } - - /*! - @brief addition of distance and iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - friend iter_impl operator+(difference_type i, const iter_impl& it) - { - auto result = it; - result += i; - return result; - } - - /*! - @brief subtract from iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl operator-(difference_type i) const - { - auto result = *this; - result -= i; - return result; - } - - /*! - @brief return difference - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - difference_type operator-(const iter_impl& other) const - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); - - case value_t::array: - return m_it.array_iterator - other.m_it.array_iterator; - - default: - return m_it.primitive_iterator - other.m_it.primitive_iterator; - } - } - - /*! - @brief access to successor - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - reference operator[](difference_type n) const - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators")); - - case value_t::array: - return *std::next(m_it.array_iterator, n); - - case value_t::null: - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - - default: - { - if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) - { - return *m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - } - } - } - - /*! - @brief return the key of an object iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - const typename object_t::key_type& key() const - { - JSON_ASSERT(m_object != nullptr); - - if (JSON_HEDLEY_LIKELY(m_object->is_object())) - { - return m_it.object_iterator->first; - } - - JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators")); - } - - /*! - @brief return the value of an iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - reference value() const - { - return operator*(); - } - - JSON_PRIVATE_UNLESS_TESTED: - /// associated JSON instance - pointer m_object = nullptr; - /// the actual iterator of the associated instance - internal_iterator::type> m_it {}; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - - -#include // ptrdiff_t -#include // reverse_iterator -#include // declval - -namespace nlohmann -{ -namespace detail -{ -////////////////////// -// reverse_iterator // -////////////////////// - -/*! -@brief a template for a reverse iterator class - -@tparam Base the base iterator type to reverse. Valid types are @ref -iterator (to create @ref reverse_iterator) and @ref const_iterator (to -create @ref const_reverse_iterator). - -@requirement The class satisfies the following concept requirements: -- -[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): - The iterator that can be moved can be moved in both directions (i.e. - incremented and decremented). -- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator): - It is possible to write to the pointed-to element (only if @a Base is - @ref iterator). - -@since version 1.0.0 -*/ -template -class json_reverse_iterator : public std::reverse_iterator -{ - public: - using difference_type = std::ptrdiff_t; - /// shortcut to the reverse iterator adapter - using base_iterator = std::reverse_iterator; - /// the reference type for the pointed-to element - using reference = typename Base::reference; - - /// create reverse iterator from iterator - explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept - : base_iterator(it) {} - - /// create reverse iterator from base class - explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} - - /// post-increment (it++) - json_reverse_iterator const operator++(int) - { - return static_cast(base_iterator::operator++(1)); - } - - /// pre-increment (++it) - json_reverse_iterator& operator++() - { - return static_cast(base_iterator::operator++()); - } - - /// post-decrement (it--) - json_reverse_iterator const operator--(int) - { - return static_cast(base_iterator::operator--(1)); - } - - /// pre-decrement (--it) - json_reverse_iterator& operator--() - { - return static_cast(base_iterator::operator--()); - } - - /// add to iterator - json_reverse_iterator& operator+=(difference_type i) - { - return static_cast(base_iterator::operator+=(i)); - } - - /// add to iterator - json_reverse_iterator operator+(difference_type i) const - { - return static_cast(base_iterator::operator+(i)); - } - - /// subtract from iterator - json_reverse_iterator operator-(difference_type i) const - { - return static_cast(base_iterator::operator-(i)); - } - - /// return difference - difference_type operator-(const json_reverse_iterator& other) const - { - return base_iterator(*this) - base_iterator(other); - } - - /// access to successor - reference operator[](difference_type n) const - { - return *(this->operator+(n)); - } - - /// return the key of an object iterator - auto key() const -> decltype(std::declval().key()) - { - auto it = --this->base(); - return it.key(); - } - - /// return the value of an iterator - reference value() const - { - auto it = --this->base(); - return it.operator * (); - } -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - - -#include // all_of -#include // isdigit -#include // max -#include // accumulate -#include // string -#include // move -#include // vector - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -template -class json_pointer -{ - // allow basic_json to access private members - NLOHMANN_BASIC_JSON_TPL_DECLARATION - friend class basic_json; - - public: - /*! - @brief create JSON pointer - - Create a JSON pointer according to the syntax described in - [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3). - - @param[in] s string representing the JSON pointer; if omitted, the empty - string is assumed which references the whole JSON value - - @throw parse_error.107 if the given JSON pointer @a s is nonempty and does - not begin with a slash (`/`); see example below - - @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is - not followed by `0` (representing `~`) or `1` (representing `/`); see - example below - - @liveexample{The example shows the construction several valid JSON pointers - as well as the exceptional behavior.,json_pointer} - - @since version 2.0.0 - */ - explicit json_pointer(const std::string& s = "") - : reference_tokens(split(s)) - {} - - /*! - @brief return a string representation of the JSON pointer - - @invariant For each JSON pointer `ptr`, it holds: - @code {.cpp} - ptr == json_pointer(ptr.to_string()); - @endcode - - @return a string representation of the JSON pointer - - @liveexample{The example shows the result of `to_string`.,json_pointer__to_string} - - @since version 2.0.0 - */ - std::string to_string() const - { - return std::accumulate(reference_tokens.begin(), reference_tokens.end(), - std::string{}, - [](const std::string & a, const std::string & b) - { - return a + "/" + escape(b); - }); - } - - /// @copydoc to_string() - operator std::string() const - { - return to_string(); - } - - /*! - @brief append another JSON pointer at the end of this JSON pointer - - @param[in] ptr JSON pointer to append - @return JSON pointer with @a ptr appended - - @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} - - @complexity Linear in the length of @a ptr. - - @sa @ref operator/=(std::string) to append a reference token - @sa @ref operator/=(std::size_t) to append an array index - @sa @ref operator/(const json_pointer&, const json_pointer&) for a binary operator - - @since version 3.6.0 - */ - json_pointer& operator/=(const json_pointer& ptr) - { - reference_tokens.insert(reference_tokens.end(), - ptr.reference_tokens.begin(), - ptr.reference_tokens.end()); - return *this; - } - - /*! - @brief append an unescaped reference token at the end of this JSON pointer - - @param[in] token reference token to append - @return JSON pointer with @a token appended without escaping @a token - - @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} - - @complexity Amortized constant. - - @sa @ref operator/=(const json_pointer&) to append a JSON pointer - @sa @ref operator/=(std::size_t) to append an array index - @sa @ref operator/(const json_pointer&, std::size_t) for a binary operator - - @since version 3.6.0 - */ - json_pointer& operator/=(std::string token) - { - push_back(std::move(token)); - return *this; - } - - /*! - @brief append an array index at the end of this JSON pointer - - @param[in] array_idx array index to append - @return JSON pointer with @a array_idx appended - - @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} - - @complexity Amortized constant. - - @sa @ref operator/=(const json_pointer&) to append a JSON pointer - @sa @ref operator/=(std::string) to append a reference token - @sa @ref operator/(const json_pointer&, std::string) for a binary operator - - @since version 3.6.0 - */ - json_pointer& operator/=(std::size_t array_idx) - { - return *this /= std::to_string(array_idx); - } - - /*! - @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer - - @param[in] lhs JSON pointer - @param[in] rhs JSON pointer - @return a new JSON pointer with @a rhs appended to @a lhs - - @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} - - @complexity Linear in the length of @a lhs and @a rhs. - - @sa @ref operator/=(const json_pointer&) to append a JSON pointer - - @since version 3.6.0 - */ - friend json_pointer operator/(const json_pointer& lhs, - const json_pointer& rhs) - { - return json_pointer(lhs) /= rhs; - } - - /*! - @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer - - @param[in] ptr JSON pointer - @param[in] token reference token - @return a new JSON pointer with unescaped @a token appended to @a ptr - - @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} - - @complexity Linear in the length of @a ptr. - - @sa @ref operator/=(std::string) to append a reference token - - @since version 3.6.0 - */ - friend json_pointer operator/(const json_pointer& ptr, std::string token) - { - return json_pointer(ptr) /= std::move(token); - } - - /*! - @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer - - @param[in] ptr JSON pointer - @param[in] array_idx array index - @return a new JSON pointer with @a array_idx appended to @a ptr - - @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} - - @complexity Linear in the length of @a ptr. - - @sa @ref operator/=(std::size_t) to append an array index - - @since version 3.6.0 - */ - friend json_pointer operator/(const json_pointer& ptr, std::size_t array_idx) - { - return json_pointer(ptr) /= array_idx; - } - - /*! - @brief returns the parent of this JSON pointer - - @return parent of this JSON pointer; in case this JSON pointer is the root, - the root itself is returned - - @complexity Linear in the length of the JSON pointer. - - @liveexample{The example shows the result of `parent_pointer` for different - JSON Pointers.,json_pointer__parent_pointer} - - @since version 3.6.0 - */ - json_pointer parent_pointer() const - { - if (empty()) - { - return *this; - } - - json_pointer res = *this; - res.pop_back(); - return res; - } - - /*! - @brief remove last reference token - - @pre not `empty()` - - @liveexample{The example shows the usage of `pop_back`.,json_pointer__pop_back} - - @complexity Constant. - - @throw out_of_range.405 if JSON pointer has no parent - - @since version 3.6.0 - */ - void pop_back() - { - if (JSON_HEDLEY_UNLIKELY(empty())) - { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); - } - - reference_tokens.pop_back(); - } - - /*! - @brief return last reference token - - @pre not `empty()` - @return last reference token - - @liveexample{The example shows the usage of `back`.,json_pointer__back} - - @complexity Constant. - - @throw out_of_range.405 if JSON pointer has no parent - - @since version 3.6.0 - */ - const std::string& back() const - { - if (JSON_HEDLEY_UNLIKELY(empty())) - { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); - } - - return reference_tokens.back(); - } - - /*! - @brief append an unescaped token at the end of the reference pointer - - @param[in] token token to add - - @complexity Amortized constant. - - @liveexample{The example shows the result of `push_back` for different - JSON Pointers.,json_pointer__push_back} - - @since version 3.6.0 - */ - void push_back(const std::string& token) - { - reference_tokens.push_back(token); - } - - /// @copydoc push_back(const std::string&) - void push_back(std::string&& token) - { - reference_tokens.push_back(std::move(token)); - } - - /*! - @brief return whether pointer points to the root document - - @return true iff the JSON pointer points to the root document - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example shows the result of `empty` for different JSON - Pointers.,json_pointer__empty} - - @since version 3.6.0 - */ - bool empty() const noexcept - { - return reference_tokens.empty(); - } - - private: - /*! - @param[in] s reference token to be converted into an array index - - @return integer representation of @a s - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index begins not with a digit - @throw out_of_range.404 if string @a s could not be converted to an integer - @throw out_of_range.410 if an array index exceeds size_type - */ - static typename BasicJsonType::size_type array_index(const std::string& s) - { - using size_type = typename BasicJsonType::size_type; - - // error condition (cf. RFC 6901, Sect. 4) - if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) - { - JSON_THROW(detail::parse_error::create(106, 0, - "array index '" + s + - "' must not begin with '0'")); - } - - // error condition (cf. RFC 6901, Sect. 4) - if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) - { - JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number")); - } - - std::size_t processed_chars = 0; - unsigned long long res = 0; - JSON_TRY - { - res = std::stoull(s, &processed_chars); - } - JSON_CATCH(std::out_of_range&) - { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); - } - - // check if the string was completely read - if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size())) - { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); - } - - // only triggered on special platforms (like 32bit), see also - // https://github.com/nlohmann/json/pull/2203 - if (res >= static_cast((std::numeric_limits::max)())) - { - JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE - } - - return static_cast(res); - } - - JSON_PRIVATE_UNLESS_TESTED: - json_pointer top() const - { - if (JSON_HEDLEY_UNLIKELY(empty())) - { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); - } - - json_pointer result = *this; - result.reference_tokens = {reference_tokens[0]}; - return result; - } - - private: - /*! - @brief create and return a reference to the pointed to value - - @complexity Linear in the number of reference tokens. - - @throw parse_error.109 if array index is not a number - @throw type_error.313 if value cannot be unflattened - */ - BasicJsonType& get_and_create(BasicJsonType& j) const - { - auto result = &j; - - // in case no reference tokens exist, return a reference to the JSON value - // j which will be overwritten by a primitive value - for (const auto& reference_token : reference_tokens) - { - switch (result->type()) - { - case detail::value_t::null: - { - if (reference_token == "0") - { - // start a new array if reference token is 0 - result = &result->operator[](0); - } - else - { - // start a new object otherwise - result = &result->operator[](reference_token); - } - break; - } - - case detail::value_t::object: - { - // create an entry in the object - result = &result->operator[](reference_token); - break; - } - - case detail::value_t::array: - { - // create an entry in the array - result = &result->operator[](array_index(reference_token)); - break; - } - - /* - The following code is only reached if there exists a reference - token _and_ the current value is primitive. In this case, we have - an error situation, because primitive values may only occur as - single value; that is, with an empty list of reference tokens. - */ - default: - JSON_THROW(detail::type_error::create(313, "invalid value to unflatten")); - } - } - - return *result; - } - - /*! - @brief return a reference to the pointed to value - - @note This version does not throw if a value is not present, but tries to - create nested values instead. For instance, calling this function - with pointer `"/this/that"` on a null value is equivalent to calling - `operator[]("this").operator[]("that")` on that value, effectively - changing the null value to an object. - - @param[in] ptr a JSON value - - @return reference to the JSON value pointed to by the JSON pointer - - @complexity Linear in the length of the JSON pointer. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - BasicJsonType& get_unchecked(BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - // convert null values to arrays or objects before continuing - if (ptr->is_null()) - { - // check if reference token is a number - const bool nums = - std::all_of(reference_token.begin(), reference_token.end(), - [](const unsigned char x) - { - return std::isdigit(x); - }); - - // change value to array for numbers or "-" or to object otherwise - *ptr = (nums || reference_token == "-") - ? detail::value_t::array - : detail::value_t::object; - } - - switch (ptr->type()) - { - case detail::value_t::object: - { - // use unchecked object access - ptr = &ptr->operator[](reference_token); - break; - } - - case detail::value_t::array: - { - if (reference_token == "-") - { - // explicitly treat "-" as index beyond the end - ptr = &ptr->operator[](ptr->m_value.array->size()); - } - else - { - // convert array index to number; unchecked access - ptr = &ptr->operator[](array_index(reference_token)); - } - break; - } - - default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); - } - } - - return *ptr; - } - - /*! - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - BasicJsonType& get_checked(BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - // note: at performs range check - ptr = &ptr->at(reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" always fails the range check - JSON_THROW(detail::out_of_range::create(402, - "array index '-' (" + std::to_string(ptr->m_value.array->size()) + - ") is out of range")); - } - - // note: at performs range check - ptr = &ptr->at(array_index(reference_token)); - break; - } - - default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); - } - } - - return *ptr; - } - - /*! - @brief return a const reference to the pointed to value - - @param[in] ptr a JSON value - - @return const reference to the JSON value pointed to by the JSON - pointer - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - // use unchecked object access - ptr = &ptr->operator[](reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" cannot be used for const access - JSON_THROW(detail::out_of_range::create(402, - "array index '-' (" + std::to_string(ptr->m_value.array->size()) + - ") is out of range")); - } - - // use unchecked array access - ptr = &ptr->operator[](array_index(reference_token)); - break; - } - - default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); - } - } - - return *ptr; - } - - /*! - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - const BasicJsonType& get_checked(const BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - // note: at performs range check - ptr = &ptr->at(reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" always fails the range check - JSON_THROW(detail::out_of_range::create(402, - "array index '-' (" + std::to_string(ptr->m_value.array->size()) + - ") is out of range")); - } - - // note: at performs range check - ptr = &ptr->at(array_index(reference_token)); - break; - } - - default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); - } - } - - return *ptr; - } - - /*! - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - */ - bool contains(const BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - if (!ptr->contains(reference_token)) - { - // we did not find the key in the object - return false; - } - - ptr = &ptr->operator[](reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" always fails the range check - return false; - } - if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9"))) - { - // invalid char - return false; - } - if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) - { - if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) - { - // first char should be between '1' and '9' - return false; - } - for (std::size_t i = 1; i < reference_token.size(); i++) - { - if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) - { - // other char should be between '0' and '9' - return false; - } - } - } - - const auto idx = array_index(reference_token); - if (idx >= ptr->size()) - { - // index out of range - return false; - } - - ptr = &ptr->operator[](idx); - break; - } - - default: - { - // we do not expect primitive values if there is still a - // reference token to process - return false; - } - } - } - - // no reference token left means we found a primitive value - return true; - } - - /*! - @brief split the string input to reference tokens - - @note This function is only called by the json_pointer constructor. - All exceptions below are documented there. - - @throw parse_error.107 if the pointer is not empty or begins with '/' - @throw parse_error.108 if character '~' is not followed by '0' or '1' - */ - static std::vector split(const std::string& reference_string) - { - std::vector result; - - // special case: empty reference string -> no reference tokens - if (reference_string.empty()) - { - return result; - } - - // check if nonempty reference string begins with slash - if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) - { - JSON_THROW(detail::parse_error::create(107, 1, - "JSON pointer must be empty or begin with '/' - was: '" + - reference_string + "'")); - } - - // extract the reference tokens: - // - slash: position of the last read slash (or end of string) - // - start: position after the previous slash - for ( - // search for the first slash after the first character - std::size_t slash = reference_string.find_first_of('/', 1), - // set the beginning of the first reference token - start = 1; - // we can stop if start == 0 (if slash == std::string::npos) - start != 0; - // set the beginning of the next reference token - // (will eventually be 0 if slash == std::string::npos) - start = (slash == std::string::npos) ? 0 : slash + 1, - // find next slash - slash = reference_string.find_first_of('/', start)) - { - // use the text between the beginning of the reference token - // (start) and the last slash (slash). - auto reference_token = reference_string.substr(start, slash - start); - - // check reference tokens are properly escaped - for (std::size_t pos = reference_token.find_first_of('~'); - pos != std::string::npos; - pos = reference_token.find_first_of('~', pos + 1)) - { - JSON_ASSERT(reference_token[pos] == '~'); - - // ~ must be followed by 0 or 1 - if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || - (reference_token[pos + 1] != '0' && - reference_token[pos + 1] != '1'))) - { - JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'")); - } - } - - // finally, store the reference token - unescape(reference_token); - result.push_back(reference_token); - } - - return result; - } - - /*! - @brief replace all occurrences of a substring by another string - - @param[in,out] s the string to manipulate; changed so that all - occurrences of @a f are replaced with @a t - @param[in] f the substring to replace with @a t - @param[in] t the string to replace @a f - - @pre The search string @a f must not be empty. **This precondition is - enforced with an assertion.** - - @since version 2.0.0 - */ - static void replace_substring(std::string& s, const std::string& f, - const std::string& t) - { - JSON_ASSERT(!f.empty()); - for (auto pos = s.find(f); // find first occurrence of f - pos != std::string::npos; // make sure f was found - s.replace(pos, f.size(), t), // replace with t, and - pos = s.find(f, pos + t.size())) // find next occurrence of f - {} - } - - JSON_PRIVATE_UNLESS_TESTED: - /// escape "~" to "~0" and "/" to "~1" - static std::string escape(std::string s) - { - replace_substring(s, "~", "~0"); - replace_substring(s, "/", "~1"); - return s; - } - - /// unescape "~1" to tilde and "~0" to slash (order is important!) - static void unescape(std::string& s) - { - replace_substring(s, "~1", "/"); - replace_substring(s, "~0", "~"); - } - - private: - /*! - @param[in] reference_string the reference string to the current value - @param[in] value the value to consider - @param[in,out] result the result object to insert values to - - @note Empty objects or arrays are flattened to `null`. - */ - static void flatten(const std::string& reference_string, - const BasicJsonType& value, - BasicJsonType& result) - { - switch (value.type()) - { - case detail::value_t::array: - { - if (value.m_value.array->empty()) - { - // flatten empty array as null - result[reference_string] = nullptr; - } - else - { - // iterate array and use index as reference string - for (std::size_t i = 0; i < value.m_value.array->size(); ++i) - { - flatten(reference_string + "/" + std::to_string(i), - value.m_value.array->operator[](i), result); - } - } - break; - } - - case detail::value_t::object: - { - if (value.m_value.object->empty()) - { - // flatten empty object as null - result[reference_string] = nullptr; - } - else - { - // iterate object and use keys as reference string - for (const auto& element : *value.m_value.object) - { - flatten(reference_string + "/" + escape(element.first), element.second, result); - } - } - break; - } - - default: - { - // add primitive value with its reference string - result[reference_string] = value; - break; - } - } - } - - /*! - @param[in] value flattened JSON - - @return unflattened JSON - - @throw parse_error.109 if array index is not a number - @throw type_error.314 if value is not an object - @throw type_error.315 if object values are not primitive - @throw type_error.313 if value cannot be unflattened - */ - static BasicJsonType - unflatten(const BasicJsonType& value) - { - if (JSON_HEDLEY_UNLIKELY(!value.is_object())) - { - JSON_THROW(detail::type_error::create(314, "only objects can be unflattened")); - } - - BasicJsonType result; - - // iterate the JSON object values - for (const auto& element : *value.m_value.object) - { - if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) - { - JSON_THROW(detail::type_error::create(315, "values in object must be primitive")); - } - - // assign value to reference pointed to by JSON pointer; Note that if - // the JSON pointer is "" (i.e., points to the whole value), function - // get_and_create returns a reference to result itself. An assignment - // will then create a primitive value. - json_pointer(element.first).get_and_create(result) = element.second; - } - - return result; - } - - /*! - @brief compares two JSON pointers for equality - - @param[in] lhs JSON pointer to compare - @param[in] rhs JSON pointer to compare - @return whether @a lhs is equal to @a rhs - - @complexity Linear in the length of the JSON pointer - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - */ - friend bool operator==(json_pointer const& lhs, - json_pointer const& rhs) noexcept - { - return lhs.reference_tokens == rhs.reference_tokens; - } - - /*! - @brief compares two JSON pointers for inequality - - @param[in] lhs JSON pointer to compare - @param[in] rhs JSON pointer to compare - @return whether @a lhs is not equal @a rhs - - @complexity Linear in the length of the JSON pointer - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - */ - friend bool operator!=(json_pointer const& lhs, - json_pointer const& rhs) noexcept - { - return !(lhs == rhs); - } - - /// the reference tokens - std::vector reference_tokens; -}; -} // namespace nlohmann - -// #include - - -#include -#include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template -class json_ref -{ - public: - using value_type = BasicJsonType; - - json_ref(value_type&& value) - : owned_value(std::move(value)) - , value_ref(&owned_value) - , is_rvalue(true) - {} - - json_ref(const value_type& value) - : value_ref(const_cast(&value)) - , is_rvalue(false) - {} - - json_ref(std::initializer_list init) - : owned_value(init) - , value_ref(&owned_value) - , is_rvalue(true) - {} - - template < - class... Args, - enable_if_t::value, int> = 0 > - json_ref(Args && ... args) - : owned_value(std::forward(args)...) - , value_ref(&owned_value) - , is_rvalue(true) - {} - - // class should be movable only - json_ref(json_ref&&) = default; - json_ref(const json_ref&) = delete; - json_ref& operator=(const json_ref&) = delete; - json_ref& operator=(json_ref&&) = delete; - ~json_ref() = default; - - value_type moved_or_copied() const - { - if (is_rvalue) - { - return std::move(*value_ref); - } - return *value_ref; - } - - value_type const& operator*() const - { - return *static_cast(value_ref); - } - - value_type const* operator->() const - { - return static_cast(value_ref); - } - - private: - mutable value_type owned_value = nullptr; - value_type* value_ref = nullptr; - const bool is_rvalue = true; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - -// #include - -// #include - - -#include // reverse -#include // array -#include // uint8_t, uint16_t, uint32_t, uint64_t -#include // memcpy -#include // numeric_limits -#include // string -#include // isnan, isinf - -// #include - -// #include - -// #include - - -#include // copy -#include // size_t -#include // streamsize -#include // back_inserter -#include // shared_ptr, make_shared -#include // basic_ostream -#include // basic_string -#include // vector -// #include - - -namespace nlohmann -{ -namespace detail -{ -/// abstract output adapter interface -template struct output_adapter_protocol -{ - virtual void write_character(CharType c) = 0; - virtual void write_characters(const CharType* s, std::size_t length) = 0; - virtual ~output_adapter_protocol() = default; -}; - -/// a type to simplify interfaces -template -using output_adapter_t = std::shared_ptr>; - -/// output adapter for byte vectors -template -class output_vector_adapter : public output_adapter_protocol -{ - public: - explicit output_vector_adapter(std::vector& vec) noexcept - : v(vec) - {} - - void write_character(CharType c) override - { - v.push_back(c); - } - - JSON_HEDLEY_NON_NULL(2) - void write_characters(const CharType* s, std::size_t length) override - { - std::copy(s, s + length, std::back_inserter(v)); - } - - private: - std::vector& v; -}; - -/// output adapter for output streams -template -class output_stream_adapter : public output_adapter_protocol -{ - public: - explicit output_stream_adapter(std::basic_ostream& s) noexcept - : stream(s) - {} - - void write_character(CharType c) override - { - stream.put(c); - } - - JSON_HEDLEY_NON_NULL(2) - void write_characters(const CharType* s, std::size_t length) override - { - stream.write(s, static_cast(length)); - } - - private: - std::basic_ostream& stream; -}; - -/// output adapter for basic_string -template> -class output_string_adapter : public output_adapter_protocol -{ - public: - explicit output_string_adapter(StringType& s) noexcept - : str(s) - {} - - void write_character(CharType c) override - { - str.push_back(c); - } - - JSON_HEDLEY_NON_NULL(2) - void write_characters(const CharType* s, std::size_t length) override - { - str.append(s, length); - } - - private: - StringType& str; -}; - -template> -class output_adapter -{ - public: - output_adapter(std::vector& vec) - : oa(std::make_shared>(vec)) {} - - output_adapter(std::basic_ostream& s) - : oa(std::make_shared>(s)) {} - - output_adapter(StringType& s) - : oa(std::make_shared>(s)) {} - - operator output_adapter_t() - { - return oa; - } - - private: - output_adapter_t oa = nullptr; -}; -} // namespace detail -} // namespace nlohmann - - -namespace nlohmann -{ -namespace detail -{ -/////////////////// -// binary writer // -/////////////////// - -/*! -@brief serialization to CBOR and MessagePack values -*/ -template -class binary_writer -{ - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using number_float_t = typename BasicJsonType::number_float_t; - - public: - /*! - @brief create a binary writer - - @param[in] adapter output adapter to write to - */ - explicit binary_writer(output_adapter_t adapter) : oa(adapter) - { - JSON_ASSERT(oa); - } - - /*! - @param[in] j JSON value to serialize - @pre j.type() == value_t::object - */ - void write_bson(const BasicJsonType& j) - { - switch (j.type()) - { - case value_t::object: - { - write_bson_object(*j.m_value.object); - break; - } - - default: - { - JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()))); - } - } - } - - /*! - @param[in] j JSON value to serialize - */ - void write_cbor(const BasicJsonType& j) - { - switch (j.type()) - { - case value_t::null: - { - oa->write_character(to_char_type(0xF6)); - break; - } - - case value_t::boolean: - { - oa->write_character(j.m_value.boolean - ? to_char_type(0xF5) - : to_char_type(0xF4)); - break; - } - - case value_t::number_integer: - { - if (j.m_value.number_integer >= 0) - { - // CBOR does not differentiate between positive signed - // integers and unsigned integers. Therefore, we used the - // code from the value_t::number_unsigned case here. - if (j.m_value.number_integer <= 0x17) - { - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x18)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x19)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x1A)); - write_number(static_cast(j.m_value.number_integer)); - } - else - { - oa->write_character(to_char_type(0x1B)); - write_number(static_cast(j.m_value.number_integer)); - } - } - else - { - // The conversions below encode the sign in the first - // byte, and the value is converted to a positive number. - const auto positive_number = -1 - j.m_value.number_integer; - if (j.m_value.number_integer >= -24) - { - write_number(static_cast(0x20 + positive_number)); - } - else if (positive_number <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x38)); - write_number(static_cast(positive_number)); - } - else if (positive_number <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x39)); - write_number(static_cast(positive_number)); - } - else if (positive_number <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x3A)); - write_number(static_cast(positive_number)); - } - else - { - oa->write_character(to_char_type(0x3B)); - write_number(static_cast(positive_number)); - } - } - break; - } - - case value_t::number_unsigned: - { - if (j.m_value.number_unsigned <= 0x17) - { - write_number(static_cast(j.m_value.number_unsigned)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x18)); - write_number(static_cast(j.m_value.number_unsigned)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x19)); - write_number(static_cast(j.m_value.number_unsigned)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x1A)); - write_number(static_cast(j.m_value.number_unsigned)); - } - else - { - oa->write_character(to_char_type(0x1B)); - write_number(static_cast(j.m_value.number_unsigned)); - } - break; - } - - case value_t::number_float: - { - if (std::isnan(j.m_value.number_float)) - { - // NaN is 0xf97e00 in CBOR - oa->write_character(to_char_type(0xF9)); - oa->write_character(to_char_type(0x7E)); - oa->write_character(to_char_type(0x00)); - } - else if (std::isinf(j.m_value.number_float)) - { - // Infinity is 0xf97c00, -Infinity is 0xf9fc00 - oa->write_character(to_char_type(0xf9)); - oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); - oa->write_character(to_char_type(0x00)); - } - else - { - write_compact_float(j.m_value.number_float, detail::input_format_t::cbor); - } - break; - } - - case value_t::string: - { - // step 1: write control byte and the string length - const auto N = j.m_value.string->size(); - if (N <= 0x17) - { - write_number(static_cast(0x60 + N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x78)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x79)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x7A)); - write_number(static_cast(N)); - } - // LCOV_EXCL_START - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x7B)); - write_number(static_cast(N)); - } - // LCOV_EXCL_STOP - - // step 2: write the string - oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.m_value.string->size()); - break; - } - - case value_t::array: - { - // step 1: write control byte and the array size - const auto N = j.m_value.array->size(); - if (N <= 0x17) - { - write_number(static_cast(0x80 + N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x98)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x99)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x9A)); - write_number(static_cast(N)); - } - // LCOV_EXCL_START - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x9B)); - write_number(static_cast(N)); - } - // LCOV_EXCL_STOP - - // step 2: write each element - for (const auto& el : *j.m_value.array) - { - write_cbor(el); - } - break; - } - - case value_t::binary: - { - if (j.m_value.binary->has_subtype()) - { - write_number(static_cast(0xd8)); - write_number(j.m_value.binary->subtype()); - } - - // step 1: write control byte and the binary array size - const auto N = j.m_value.binary->size(); - if (N <= 0x17) - { - write_number(static_cast(0x40 + N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x58)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x59)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x5A)); - write_number(static_cast(N)); - } - // LCOV_EXCL_START - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x5B)); - write_number(static_cast(N)); - } - // LCOV_EXCL_STOP - - // step 2: write each element - oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), - N); - - break; - } - - case value_t::object: - { - // step 1: write control byte and the object size - const auto N = j.m_value.object->size(); - if (N <= 0x17) - { - write_number(static_cast(0xA0 + N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0xB8)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0xB9)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0xBA)); - write_number(static_cast(N)); - } - // LCOV_EXCL_START - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0xBB)); - write_number(static_cast(N)); - } - // LCOV_EXCL_STOP - - // step 2: write each element - for (const auto& el : *j.m_value.object) - { - write_cbor(el.first); - write_cbor(el.second); - } - break; - } - - default: - break; - } - } - - /*! - @param[in] j JSON value to serialize - */ - void write_msgpack(const BasicJsonType& j) - { - switch (j.type()) - { - case value_t::null: // nil - { - oa->write_character(to_char_type(0xC0)); - break; - } - - case value_t::boolean: // true and false - { - oa->write_character(j.m_value.boolean - ? to_char_type(0xC3) - : to_char_type(0xC2)); - break; - } - - case value_t::number_integer: - { - if (j.m_value.number_integer >= 0) - { - // MessagePack does not differentiate between positive - // signed integers and unsigned integers. Therefore, we used - // the code from the value_t::number_unsigned case here. - if (j.m_value.number_unsigned < 128) - { - // positive fixnum - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 8 - oa->write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 16 - oa->write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 32 - oa->write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 64 - oa->write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_value.number_integer)); - } - } - else - { - if (j.m_value.number_integer >= -32) - { - // negative fixnum - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 8 - oa->write_character(to_char_type(0xD0)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 16 - oa->write_character(to_char_type(0xD1)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 32 - oa->write_character(to_char_type(0xD2)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 64 - oa->write_character(to_char_type(0xD3)); - write_number(static_cast(j.m_value.number_integer)); - } - } - break; - } - - case value_t::number_unsigned: - { - if (j.m_value.number_unsigned < 128) - { - // positive fixnum - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 8 - oa->write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 16 - oa->write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 32 - oa->write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 64 - oa->write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_value.number_integer)); - } - break; - } - - case value_t::number_float: - { - write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack); - break; - } - - case value_t::string: - { - // step 1: write control byte and the string length - const auto N = j.m_value.string->size(); - if (N <= 31) - { - // fixstr - write_number(static_cast(0xA0 | N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // str 8 - oa->write_character(to_char_type(0xD9)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // str 16 - oa->write_character(to_char_type(0xDA)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // str 32 - oa->write_character(to_char_type(0xDB)); - write_number(static_cast(N)); - } - - // step 2: write the string - oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.m_value.string->size()); - break; - } - - case value_t::array: - { - // step 1: write control byte and the array size - const auto N = j.m_value.array->size(); - if (N <= 15) - { - // fixarray - write_number(static_cast(0x90 | N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // array 16 - oa->write_character(to_char_type(0xDC)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // array 32 - oa->write_character(to_char_type(0xDD)); - write_number(static_cast(N)); - } - - // step 2: write each element - for (const auto& el : *j.m_value.array) - { - write_msgpack(el); - } - break; - } - - case value_t::binary: - { - // step 0: determine if the binary type has a set subtype to - // determine whether or not to use the ext or fixext types - const bool use_ext = j.m_value.binary->has_subtype(); - - // step 1: write control byte and the byte string length - const auto N = j.m_value.binary->size(); - if (N <= (std::numeric_limits::max)()) - { - std::uint8_t output_type{}; - bool fixed = true; - if (use_ext) - { - switch (N) - { - case 1: - output_type = 0xD4; // fixext 1 - break; - case 2: - output_type = 0xD5; // fixext 2 - break; - case 4: - output_type = 0xD6; // fixext 4 - break; - case 8: - output_type = 0xD7; // fixext 8 - break; - case 16: - output_type = 0xD8; // fixext 16 - break; - default: - output_type = 0xC7; // ext 8 - fixed = false; - break; - } - - } - else - { - output_type = 0xC4; // bin 8 - fixed = false; - } - - oa->write_character(to_char_type(output_type)); - if (!fixed) - { - write_number(static_cast(N)); - } - } - else if (N <= (std::numeric_limits::max)()) - { - std::uint8_t output_type = use_ext - ? 0xC8 // ext 16 - : 0xC5; // bin 16 - - oa->write_character(to_char_type(output_type)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - std::uint8_t output_type = use_ext - ? 0xC9 // ext 32 - : 0xC6; // bin 32 - - oa->write_character(to_char_type(output_type)); - write_number(static_cast(N)); - } - - // step 1.5: if this is an ext type, write the subtype - if (use_ext) - { - write_number(static_cast(j.m_value.binary->subtype())); - } - - // step 2: write the byte string - oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), - N); - - break; - } - - case value_t::object: - { - // step 1: write control byte and the object size - const auto N = j.m_value.object->size(); - if (N <= 15) - { - // fixmap - write_number(static_cast(0x80 | (N & 0xF))); - } - else if (N <= (std::numeric_limits::max)()) - { - // map 16 - oa->write_character(to_char_type(0xDE)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // map 32 - oa->write_character(to_char_type(0xDF)); - write_number(static_cast(N)); - } - - // step 2: write each element - for (const auto& el : *j.m_value.object) - { - write_msgpack(el.first); - write_msgpack(el.second); - } - break; - } - - default: - break; - } - } - - /*! - @param[in] j JSON value to serialize - @param[in] use_count whether to use '#' prefixes (optimized format) - @param[in] use_type whether to use '$' prefixes (optimized format) - @param[in] add_prefix whether prefixes need to be used for this value - */ - void write_ubjson(const BasicJsonType& j, const bool use_count, - const bool use_type, const bool add_prefix = true) - { - switch (j.type()) - { - case value_t::null: - { - if (add_prefix) - { - oa->write_character(to_char_type('Z')); - } - break; - } - - case value_t::boolean: - { - if (add_prefix) - { - oa->write_character(j.m_value.boolean - ? to_char_type('T') - : to_char_type('F')); - } - break; - } - - case value_t::number_integer: - { - write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix); - break; - } - - case value_t::number_unsigned: - { - write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix); - break; - } - - case value_t::number_float: - { - write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix); - break; - } - - case value_t::string: - { - if (add_prefix) - { - oa->write_character(to_char_type('S')); - } - write_number_with_ubjson_prefix(j.m_value.string->size(), true); - oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.m_value.string->size()); - break; - } - - case value_t::array: - { - if (add_prefix) - { - oa->write_character(to_char_type('[')); - } - - bool prefix_required = true; - if (use_type && !j.m_value.array->empty()) - { - JSON_ASSERT(use_count); - const CharType first_prefix = ubjson_prefix(j.front()); - const bool same_prefix = std::all_of(j.begin() + 1, j.end(), - [this, first_prefix](const BasicJsonType & v) - { - return ubjson_prefix(v) == first_prefix; - }); - - if (same_prefix) - { - prefix_required = false; - oa->write_character(to_char_type('$')); - oa->write_character(first_prefix); - } - } - - if (use_count) - { - oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.array->size(), true); - } - - for (const auto& el : *j.m_value.array) - { - write_ubjson(el, use_count, use_type, prefix_required); - } - - if (!use_count) - { - oa->write_character(to_char_type(']')); - } - - break; - } - - case value_t::binary: - { - if (add_prefix) - { - oa->write_character(to_char_type('[')); - } - - if (use_type && !j.m_value.binary->empty()) - { - JSON_ASSERT(use_count); - oa->write_character(to_char_type('$')); - oa->write_character('U'); - } - - if (use_count) - { - oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.binary->size(), true); - } - - if (use_type) - { - oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), - j.m_value.binary->size()); - } - else - { - for (size_t i = 0; i < j.m_value.binary->size(); ++i) - { - oa->write_character(to_char_type('U')); - oa->write_character(j.m_value.binary->data()[i]); - } - } - - if (!use_count) - { - oa->write_character(to_char_type(']')); - } - - break; - } - - case value_t::object: - { - if (add_prefix) - { - oa->write_character(to_char_type('{')); - } - - bool prefix_required = true; - if (use_type && !j.m_value.object->empty()) - { - JSON_ASSERT(use_count); - const CharType first_prefix = ubjson_prefix(j.front()); - const bool same_prefix = std::all_of(j.begin(), j.end(), - [this, first_prefix](const BasicJsonType & v) - { - return ubjson_prefix(v) == first_prefix; - }); - - if (same_prefix) - { - prefix_required = false; - oa->write_character(to_char_type('$')); - oa->write_character(first_prefix); - } - } - - if (use_count) - { - oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.object->size(), true); - } - - for (const auto& el : *j.m_value.object) - { - write_number_with_ubjson_prefix(el.first.size(), true); - oa->write_characters( - reinterpret_cast(el.first.c_str()), - el.first.size()); - write_ubjson(el.second, use_count, use_type, prefix_required); - } - - if (!use_count) - { - oa->write_character(to_char_type('}')); - } - - break; - } - - default: - break; - } - } - - private: - ////////// - // BSON // - ////////// - - /*! - @return The size of a BSON document entry header, including the id marker - and the entry name size (and its null-terminator). - */ - static std::size_t calc_bson_entry_header_size(const string_t& name) - { - const auto it = name.find(static_cast(0)); - if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) - { - JSON_THROW(out_of_range::create(409, - "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")")); - } - - return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; - } - - /*! - @brief Writes the given @a element_type and @a name to the output adapter - */ - void write_bson_entry_header(const string_t& name, - const std::uint8_t element_type) - { - oa->write_character(to_char_type(element_type)); // boolean - oa->write_characters( - reinterpret_cast(name.c_str()), - name.size() + 1u); - } - - /*! - @brief Writes a BSON element with key @a name and boolean value @a value - */ - void write_bson_boolean(const string_t& name, - const bool value) - { - write_bson_entry_header(name, 0x08); - oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00)); - } - - /*! - @brief Writes a BSON element with key @a name and double value @a value - */ - void write_bson_double(const string_t& name, - const double value) - { - write_bson_entry_header(name, 0x01); - write_number(value); - } - - /*! - @return The size of the BSON-encoded string in @a value - */ - static std::size_t calc_bson_string_size(const string_t& value) - { - return sizeof(std::int32_t) + value.size() + 1ul; - } - - /*! - @brief Writes a BSON element with key @a name and string value @a value - */ - void write_bson_string(const string_t& name, - const string_t& value) - { - write_bson_entry_header(name, 0x02); - - write_number(static_cast(value.size() + 1ul)); - oa->write_characters( - reinterpret_cast(value.c_str()), - value.size() + 1); - } - - /*! - @brief Writes a BSON element with key @a name and null value - */ - void write_bson_null(const string_t& name) - { - write_bson_entry_header(name, 0x0A); - } - - /*! - @return The size of the BSON-encoded integer @a value - */ - static std::size_t calc_bson_integer_size(const std::int64_t value) - { - return (std::numeric_limits::min)() <= value && value <= (std::numeric_limits::max)() - ? sizeof(std::int32_t) - : sizeof(std::int64_t); - } - - /*! - @brief Writes a BSON element with key @a name and integer @a value - */ - void write_bson_integer(const string_t& name, - const std::int64_t value) - { - if ((std::numeric_limits::min)() <= value && value <= (std::numeric_limits::max)()) - { - write_bson_entry_header(name, 0x10); // int32 - write_number(static_cast(value)); - } - else - { - write_bson_entry_header(name, 0x12); // int64 - write_number(static_cast(value)); - } - } - - /*! - @return The size of the BSON-encoded unsigned integer in @a j - */ - static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept - { - return (value <= static_cast((std::numeric_limits::max)())) - ? sizeof(std::int32_t) - : sizeof(std::int64_t); - } - - /*! - @brief Writes a BSON element with key @a name and unsigned @a value - */ - void write_bson_unsigned(const string_t& name, - const std::uint64_t value) - { - if (value <= static_cast((std::numeric_limits::max)())) - { - write_bson_entry_header(name, 0x10 /* int32 */); - write_number(static_cast(value)); - } - else if (value <= static_cast((std::numeric_limits::max)())) - { - write_bson_entry_header(name, 0x12 /* int64 */); - write_number(static_cast(value)); - } - else - { - JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64")); - } - } - - /*! - @brief Writes a BSON element with key @a name and object @a value - */ - void write_bson_object_entry(const string_t& name, - const typename BasicJsonType::object_t& value) - { - write_bson_entry_header(name, 0x03); // object - write_bson_object(value); - } - - /*! - @return The size of the BSON-encoded array @a value - */ - static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) - { - std::size_t array_index = 0ul; - - const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), std::size_t(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el) - { - return result + calc_bson_element_size(std::to_string(array_index++), el); - }); - - return sizeof(std::int32_t) + embedded_document_size + 1ul; - } - - /*! - @return The size of the BSON-encoded binary array @a value - */ - static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value) - { - return sizeof(std::int32_t) + value.size() + 1ul; - } - - /*! - @brief Writes a BSON element with key @a name and array @a value - */ - void write_bson_array(const string_t& name, - const typename BasicJsonType::array_t& value) - { - write_bson_entry_header(name, 0x04); // array - write_number(static_cast(calc_bson_array_size(value))); - - std::size_t array_index = 0ul; - - for (const auto& el : value) - { - write_bson_element(std::to_string(array_index++), el); - } - - oa->write_character(to_char_type(0x00)); - } - - /*! - @brief Writes a BSON element with key @a name and binary value @a value - */ - void write_bson_binary(const string_t& name, - const binary_t& value) - { - write_bson_entry_header(name, 0x05); - - write_number(static_cast(value.size())); - write_number(value.has_subtype() ? value.subtype() : std::uint8_t(0x00)); - - oa->write_characters(reinterpret_cast(value.data()), value.size()); - } - - /*! - @brief Calculates the size necessary to serialize the JSON value @a j with its @a name - @return The calculated size for the BSON document entry for @a j with the given @a name. - */ - static std::size_t calc_bson_element_size(const string_t& name, - const BasicJsonType& j) - { - const auto header_size = calc_bson_entry_header_size(name); - switch (j.type()) - { - case value_t::object: - return header_size + calc_bson_object_size(*j.m_value.object); - - case value_t::array: - return header_size + calc_bson_array_size(*j.m_value.array); - - case value_t::binary: - return header_size + calc_bson_binary_size(*j.m_value.binary); - - case value_t::boolean: - return header_size + 1ul; - - case value_t::number_float: - return header_size + 8ul; - - case value_t::number_integer: - return header_size + calc_bson_integer_size(j.m_value.number_integer); - - case value_t::number_unsigned: - return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned); - - case value_t::string: - return header_size + calc_bson_string_size(*j.m_value.string); - - case value_t::null: - return header_size + 0ul; - - // LCOV_EXCL_START - default: - JSON_ASSERT(false); - return 0ul; - // LCOV_EXCL_STOP - } - } - - /*! - @brief Serializes the JSON value @a j to BSON and associates it with the - key @a name. - @param name The name to associate with the JSON entity @a j within the - current BSON document - @return The size of the BSON entry - */ - void write_bson_element(const string_t& name, - const BasicJsonType& j) - { - switch (j.type()) - { - case value_t::object: - return write_bson_object_entry(name, *j.m_value.object); - - case value_t::array: - return write_bson_array(name, *j.m_value.array); - - case value_t::binary: - return write_bson_binary(name, *j.m_value.binary); - - case value_t::boolean: - return write_bson_boolean(name, j.m_value.boolean); - - case value_t::number_float: - return write_bson_double(name, j.m_value.number_float); - - case value_t::number_integer: - return write_bson_integer(name, j.m_value.number_integer); - - case value_t::number_unsigned: - return write_bson_unsigned(name, j.m_value.number_unsigned); - - case value_t::string: - return write_bson_string(name, *j.m_value.string); - - case value_t::null: - return write_bson_null(name); - - // LCOV_EXCL_START - default: - JSON_ASSERT(false); - return; - // LCOV_EXCL_STOP - } - } - - /*! - @brief Calculates the size of the BSON serialization of the given - JSON-object @a j. - @param[in] j JSON value to serialize - @pre j.type() == value_t::object - */ - static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) - { - std::size_t document_size = std::accumulate(value.begin(), value.end(), std::size_t(0), - [](size_t result, const typename BasicJsonType::object_t::value_type & el) - { - return result += calc_bson_element_size(el.first, el.second); - }); - - return sizeof(std::int32_t) + document_size + 1ul; - } - - /*! - @param[in] j JSON value to serialize - @pre j.type() == value_t::object - */ - void write_bson_object(const typename BasicJsonType::object_t& value) - { - write_number(static_cast(calc_bson_object_size(value))); - - for (const auto& el : value) - { - write_bson_element(el.first, el.second); - } - - oa->write_character(to_char_type(0x00)); - } - - ////////// - // CBOR // - ////////// - - static constexpr CharType get_cbor_float_prefix(float /*unused*/) - { - return to_char_type(0xFA); // Single-Precision Float - } - - static constexpr CharType get_cbor_float_prefix(double /*unused*/) - { - return to_char_type(0xFB); // Double-Precision Float - } - - ///////////// - // MsgPack // - ///////////// - - static constexpr CharType get_msgpack_float_prefix(float /*unused*/) - { - return to_char_type(0xCA); // float 32 - } - - static constexpr CharType get_msgpack_float_prefix(double /*unused*/) - { - return to_char_type(0xCB); // float 64 - } - - //////////// - // UBJSON // - //////////// - - // UBJSON: write number (floating point) - template::value, int>::type = 0> - void write_number_with_ubjson_prefix(const NumberType n, - const bool add_prefix) - { - if (add_prefix) - { - oa->write_character(get_ubjson_float_prefix(n)); - } - write_number(n); - } - - // UBJSON: write number (unsigned integer) - template::value, int>::type = 0> - void write_number_with_ubjson_prefix(const NumberType n, - const bool add_prefix) - { - if (n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('i')); // int8 - } - write_number(static_cast(n)); - } - else if (n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('U')); // uint8 - } - write_number(static_cast(n)); - } - else if (n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('I')); // int16 - } - write_number(static_cast(n)); - } - else if (n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('l')); // int32 - } - write_number(static_cast(n)); - } - else if (n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('L')); // int64 - } - write_number(static_cast(n)); - } - else - { - if (add_prefix) - { - oa->write_character(to_char_type('H')); // high-precision number - } - - const auto number = BasicJsonType(n).dump(); - write_number_with_ubjson_prefix(number.size(), true); - for (std::size_t i = 0; i < number.size(); ++i) - { - oa->write_character(to_char_type(static_cast(number[i]))); - } - } - } - - // UBJSON: write number (signed integer) - template < typename NumberType, typename std::enable_if < - std::is_signed::value&& - !std::is_floating_point::value, int >::type = 0 > - void write_number_with_ubjson_prefix(const NumberType n, - const bool add_prefix) - { - if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('i')); // int8 - } - write_number(static_cast(n)); - } - else if (static_cast((std::numeric_limits::min)()) <= n && n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('U')); // uint8 - } - write_number(static_cast(n)); - } - else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('I')); // int16 - } - write_number(static_cast(n)); - } - else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('l')); // int32 - } - write_number(static_cast(n)); - } - else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('L')); // int64 - } - write_number(static_cast(n)); - } - // LCOV_EXCL_START - else - { - if (add_prefix) - { - oa->write_character(to_char_type('H')); // high-precision number - } - - const auto number = BasicJsonType(n).dump(); - write_number_with_ubjson_prefix(number.size(), true); - for (std::size_t i = 0; i < number.size(); ++i) - { - oa->write_character(to_char_type(static_cast(number[i]))); - } - } - // LCOV_EXCL_STOP - } - - /*! - @brief determine the type prefix of container values - */ - CharType ubjson_prefix(const BasicJsonType& j) const noexcept - { - switch (j.type()) - { - case value_t::null: - return 'Z'; - - case value_t::boolean: - return j.m_value.boolean ? 'T' : 'F'; - - case value_t::number_integer: - { - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'i'; - } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'U'; - } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'I'; - } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'l'; - } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'L'; - } - // anything else is treated as high-precision number - return 'H'; // LCOV_EXCL_LINE - } - - case value_t::number_unsigned: - { - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'i'; - } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'U'; - } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'I'; - } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'l'; - } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'L'; - } - // anything else is treated as high-precision number - return 'H'; // LCOV_EXCL_LINE - } - - case value_t::number_float: - return get_ubjson_float_prefix(j.m_value.number_float); - - case value_t::string: - return 'S'; - - case value_t::array: // fallthrough - case value_t::binary: - return '['; - - case value_t::object: - return '{'; - - default: // discarded values - return 'N'; - } - } - - static constexpr CharType get_ubjson_float_prefix(float /*unused*/) - { - return 'd'; // float 32 - } - - static constexpr CharType get_ubjson_float_prefix(double /*unused*/) - { - return 'D'; // float 64 - } - - /////////////////////// - // Utility functions // - /////////////////////// - - /* - @brief write a number to output input - @param[in] n number of type @a NumberType - @tparam NumberType the type of the number - @tparam OutputIsLittleEndian Set to true if output data is - required to be little endian - - @note This function needs to respect the system's endianess, because bytes - in CBOR, MessagePack, and UBJSON are stored in network order (big - endian) and therefore need reordering on little endian systems. - */ - template - void write_number(const NumberType n) - { - // step 1: write number to array of length NumberType - std::array vec; - std::memcpy(vec.data(), &n, sizeof(NumberType)); - - // step 2: write array to output (with possible reordering) - if (is_little_endian != OutputIsLittleEndian) - { - // reverse byte order prior to conversion if necessary - std::reverse(vec.begin(), vec.end()); - } - - oa->write_characters(vec.data(), sizeof(NumberType)); - } - - void write_compact_float(const number_float_t n, detail::input_format_t format) - { - if (static_cast(n) >= static_cast(std::numeric_limits::lowest()) && - static_cast(n) <= static_cast((std::numeric_limits::max)()) && - static_cast(static_cast(n)) == static_cast(n)) - { - oa->write_character(format == detail::input_format_t::cbor - ? get_cbor_float_prefix(static_cast(n)) - : get_msgpack_float_prefix(static_cast(n))); - write_number(static_cast(n)); - } - else - { - oa->write_character(format == detail::input_format_t::cbor - ? get_cbor_float_prefix(n) - : get_msgpack_float_prefix(n)); - write_number(n); - } - } - - public: - // The following to_char_type functions are implement the conversion - // between uint8_t and CharType. In case CharType is not unsigned, - // such a conversion is required to allow values greater than 128. - // See for a discussion. - template < typename C = CharType, - enable_if_t < std::is_signed::value && std::is_signed::value > * = nullptr > - static constexpr CharType to_char_type(std::uint8_t x) noexcept - { - return *reinterpret_cast(&x); - } - - template < typename C = CharType, - enable_if_t < std::is_signed::value && std::is_unsigned::value > * = nullptr > - static CharType to_char_type(std::uint8_t x) noexcept - { - static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t"); - static_assert(std::is_trivial::value, "CharType must be trivial"); - CharType result; - std::memcpy(&result, &x, sizeof(x)); - return result; - } - - template::value>* = nullptr> - static constexpr CharType to_char_type(std::uint8_t x) noexcept - { - return x; - } - - template < typename InputCharType, typename C = CharType, - enable_if_t < - std::is_signed::value && - std::is_signed::value && - std::is_same::type>::value - > * = nullptr > - static constexpr CharType to_char_type(InputCharType x) noexcept - { - return x; - } - - private: - /// whether we can assume little endianess - const bool is_little_endian = little_endianess(); - - /// the output - output_adapter_t oa = nullptr; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - - -#include // reverse, remove, fill, find, none_of -#include // array -#include // localeconv, lconv -#include // labs, isfinite, isnan, signbit -#include // size_t, ptrdiff_t -#include // uint8_t -#include // snprintf -#include // numeric_limits -#include // string, char_traits -#include // is_same -#include // move - -// #include - - -#include // array -#include // signbit, isfinite -#include // intN_t, uintN_t -#include // memcpy, memmove -#include // numeric_limits -#include // conditional - -// #include - - -namespace nlohmann -{ -namespace detail -{ - -/*! -@brief implements the Grisu2 algorithm for binary to decimal floating-point -conversion. - -This implementation is a slightly modified version of the reference -implementation which may be obtained from -http://florian.loitsch.com/publications (bench.tar.gz). - -The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. - -For a detailed description of the algorithm see: - -[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with - Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming - Language Design and Implementation, PLDI 2010 -[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", - Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language - Design and Implementation, PLDI 1996 -*/ -namespace dtoa_impl -{ - -template -Target reinterpret_bits(const Source source) -{ - static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); - - Target target; - std::memcpy(&target, &source, sizeof(Source)); - return target; -} - -struct diyfp // f * 2^e -{ - static constexpr int kPrecision = 64; // = q - - std::uint64_t f = 0; - int e = 0; - - constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} - - /*! - @brief returns x - y - @pre x.e == y.e and x.f >= y.f - */ - static diyfp sub(const diyfp& x, const diyfp& y) noexcept - { - JSON_ASSERT(x.e == y.e); - JSON_ASSERT(x.f >= y.f); - - return {x.f - y.f, x.e}; - } - - /*! - @brief returns x * y - @note The result is rounded. (Only the upper q bits are returned.) - */ - static diyfp mul(const diyfp& x, const diyfp& y) noexcept - { - static_assert(kPrecision == 64, "internal error"); - - // Computes: - // f = round((x.f * y.f) / 2^q) - // e = x.e + y.e + q - - // Emulate the 64-bit * 64-bit multiplication: - // - // p = u * v - // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) - // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) - // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) - // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) - // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) - // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) - // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) - // - // (Since Q might be larger than 2^32 - 1) - // - // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) - // - // (Q_hi + H does not overflow a 64-bit int) - // - // = p_lo + 2^64 p_hi - - const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; - const std::uint64_t u_hi = x.f >> 32u; - const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; - const std::uint64_t v_hi = y.f >> 32u; - - const std::uint64_t p0 = u_lo * v_lo; - const std::uint64_t p1 = u_lo * v_hi; - const std::uint64_t p2 = u_hi * v_lo; - const std::uint64_t p3 = u_hi * v_hi; - - const std::uint64_t p0_hi = p0 >> 32u; - const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; - const std::uint64_t p1_hi = p1 >> 32u; - const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; - const std::uint64_t p2_hi = p2 >> 32u; - - std::uint64_t Q = p0_hi + p1_lo + p2_lo; - - // The full product might now be computed as - // - // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) - // p_lo = p0_lo + (Q << 32) - // - // But in this particular case here, the full p_lo is not required. - // Effectively we only need to add the highest bit in p_lo to p_hi (and - // Q_hi + 1 does not overflow). - - Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up - - const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); - - return {h, x.e + y.e + 64}; - } - - /*! - @brief normalize x such that the significand is >= 2^(q-1) - @pre x.f != 0 - */ - static diyfp normalize(diyfp x) noexcept - { - JSON_ASSERT(x.f != 0); - - while ((x.f >> 63u) == 0) - { - x.f <<= 1u; - x.e--; - } - - return x; - } - - /*! - @brief normalize x such that the result has the exponent E - @pre e >= x.e and the upper e - x.e bits of x.f must be zero. - */ - static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept - { - const int delta = x.e - target_exponent; - - JSON_ASSERT(delta >= 0); - JSON_ASSERT(((x.f << delta) >> delta) == x.f); - - return {x.f << delta, target_exponent}; - } -}; - -struct boundaries -{ - diyfp w; - diyfp minus; - diyfp plus; -}; - -/*! -Compute the (normalized) diyfp representing the input number 'value' and its -boundaries. - -@pre value must be finite and positive -*/ -template -boundaries compute_boundaries(FloatType value) -{ - JSON_ASSERT(std::isfinite(value)); - JSON_ASSERT(value > 0); - - // Convert the IEEE representation into a diyfp. - // - // If v is denormal: - // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) - // If v is normalized: - // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) - - static_assert(std::numeric_limits::is_iec559, - "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); - - constexpr int kPrecision = std::numeric_limits::digits; // = p (includes the hidden bit) - constexpr int kBias = std::numeric_limits::max_exponent - 1 + (kPrecision - 1); - constexpr int kMinExp = 1 - kBias; - constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) - - using bits_type = typename std::conditional::type; - - const std::uint64_t bits = reinterpret_bits(value); - const std::uint64_t E = bits >> (kPrecision - 1); - const std::uint64_t F = bits & (kHiddenBit - 1); - - const bool is_denormal = E == 0; - const diyfp v = is_denormal - ? diyfp(F, kMinExp) - : diyfp(F + kHiddenBit, static_cast(E) - kBias); - - // Compute the boundaries m- and m+ of the floating-point value - // v = f * 2^e. - // - // Determine v- and v+, the floating-point predecessor and successor if v, - // respectively. - // - // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) - // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) - // - // v+ = v + 2^e - // - // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ - // between m- and m+ round to v, regardless of how the input rounding - // algorithm breaks ties. - // - // ---+-------------+-------------+-------------+-------------+--- (A) - // v- m- v m+ v+ - // - // -----------------+------+------+-------------+-------------+--- (B) - // v- m- v m+ v+ - - const bool lower_boundary_is_closer = F == 0 && E > 1; - const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); - const diyfp m_minus = lower_boundary_is_closer - ? diyfp(4 * v.f - 1, v.e - 2) // (B) - : diyfp(2 * v.f - 1, v.e - 1); // (A) - - // Determine the normalized w+ = m+. - const diyfp w_plus = diyfp::normalize(m_plus); - - // Determine w- = m- such that e_(w-) = e_(w+). - const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); - - return {diyfp::normalize(v), w_minus, w_plus}; -} - -// Given normalized diyfp w, Grisu needs to find a (normalized) cached -// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies -// within a certain range [alpha, gamma] (Definition 3.2 from [1]) -// -// alpha <= e = e_c + e_w + q <= gamma -// -// or -// -// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q -// <= f_c * f_w * 2^gamma -// -// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies -// -// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma -// -// or -// -// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) -// -// The choice of (alpha,gamma) determines the size of the table and the form of -// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well -// in practice: -// -// The idea is to cut the number c * w = f * 2^e into two parts, which can be -// processed independently: An integral part p1, and a fractional part p2: -// -// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e -// = (f div 2^-e) + (f mod 2^-e) * 2^e -// = p1 + p2 * 2^e -// -// The conversion of p1 into decimal form requires a series of divisions and -// modulos by (a power of) 10. These operations are faster for 32-bit than for -// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be -// achieved by choosing -// -// -e >= 32 or e <= -32 := gamma -// -// In order to convert the fractional part -// -// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... -// -// into decimal form, the fraction is repeatedly multiplied by 10 and the digits -// d[-i] are extracted in order: -// -// (10 * p2) div 2^-e = d[-1] -// (10 * p2) mod 2^-e = d[-2] / 10^1 + ... -// -// The multiplication by 10 must not overflow. It is sufficient to choose -// -// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. -// -// Since p2 = f mod 2^-e < 2^-e, -// -// -e <= 60 or e >= -60 := alpha - -constexpr int kAlpha = -60; -constexpr int kGamma = -32; - -struct cached_power // c = f * 2^e ~= 10^k -{ - std::uint64_t f; - int e; - int k; -}; - -/*! -For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached -power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c -satisfies (Definition 3.2 from [1]) - - alpha <= e_c + e + q <= gamma. -*/ -inline cached_power get_cached_power_for_binary_exponent(int e) -{ - // Now - // - // alpha <= e_c + e + q <= gamma (1) - // ==> f_c * 2^alpha <= c * 2^e * 2^q - // - // and since the c's are normalized, 2^(q-1) <= f_c, - // - // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) - // ==> 2^(alpha - e - 1) <= c - // - // If c were an exact power of ten, i.e. c = 10^k, one may determine k as - // - // k = ceil( log_10( 2^(alpha - e - 1) ) ) - // = ceil( (alpha - e - 1) * log_10(2) ) - // - // From the paper: - // "In theory the result of the procedure could be wrong since c is rounded, - // and the computation itself is approximated [...]. In practice, however, - // this simple function is sufficient." - // - // For IEEE double precision floating-point numbers converted into - // normalized diyfp's w = f * 2^e, with q = 64, - // - // e >= -1022 (min IEEE exponent) - // -52 (p - 1) - // -52 (p - 1, possibly normalize denormal IEEE numbers) - // -11 (normalize the diyfp) - // = -1137 - // - // and - // - // e <= +1023 (max IEEE exponent) - // -52 (p - 1) - // -11 (normalize the diyfp) - // = 960 - // - // This binary exponent range [-1137,960] results in a decimal exponent - // range [-307,324]. One does not need to store a cached power for each - // k in this range. For each such k it suffices to find a cached power - // such that the exponent of the product lies in [alpha,gamma]. - // This implies that the difference of the decimal exponents of adjacent - // table entries must be less than or equal to - // - // floor( (gamma - alpha) * log_10(2) ) = 8. - // - // (A smaller distance gamma-alpha would require a larger table.) - - // NB: - // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. - - constexpr int kCachedPowersMinDecExp = -300; - constexpr int kCachedPowersDecStep = 8; - - static constexpr std::array kCachedPowers = - { - { - { 0xAB70FE17C79AC6CA, -1060, -300 }, - { 0xFF77B1FCBEBCDC4F, -1034, -292 }, - { 0xBE5691EF416BD60C, -1007, -284 }, - { 0x8DD01FAD907FFC3C, -980, -276 }, - { 0xD3515C2831559A83, -954, -268 }, - { 0x9D71AC8FADA6C9B5, -927, -260 }, - { 0xEA9C227723EE8BCB, -901, -252 }, - { 0xAECC49914078536D, -874, -244 }, - { 0x823C12795DB6CE57, -847, -236 }, - { 0xC21094364DFB5637, -821, -228 }, - { 0x9096EA6F3848984F, -794, -220 }, - { 0xD77485CB25823AC7, -768, -212 }, - { 0xA086CFCD97BF97F4, -741, -204 }, - { 0xEF340A98172AACE5, -715, -196 }, - { 0xB23867FB2A35B28E, -688, -188 }, - { 0x84C8D4DFD2C63F3B, -661, -180 }, - { 0xC5DD44271AD3CDBA, -635, -172 }, - { 0x936B9FCEBB25C996, -608, -164 }, - { 0xDBAC6C247D62A584, -582, -156 }, - { 0xA3AB66580D5FDAF6, -555, -148 }, - { 0xF3E2F893DEC3F126, -529, -140 }, - { 0xB5B5ADA8AAFF80B8, -502, -132 }, - { 0x87625F056C7C4A8B, -475, -124 }, - { 0xC9BCFF6034C13053, -449, -116 }, - { 0x964E858C91BA2655, -422, -108 }, - { 0xDFF9772470297EBD, -396, -100 }, - { 0xA6DFBD9FB8E5B88F, -369, -92 }, - { 0xF8A95FCF88747D94, -343, -84 }, - { 0xB94470938FA89BCF, -316, -76 }, - { 0x8A08F0F8BF0F156B, -289, -68 }, - { 0xCDB02555653131B6, -263, -60 }, - { 0x993FE2C6D07B7FAC, -236, -52 }, - { 0xE45C10C42A2B3B06, -210, -44 }, - { 0xAA242499697392D3, -183, -36 }, - { 0xFD87B5F28300CA0E, -157, -28 }, - { 0xBCE5086492111AEB, -130, -20 }, - { 0x8CBCCC096F5088CC, -103, -12 }, - { 0xD1B71758E219652C, -77, -4 }, - { 0x9C40000000000000, -50, 4 }, - { 0xE8D4A51000000000, -24, 12 }, - { 0xAD78EBC5AC620000, 3, 20 }, - { 0x813F3978F8940984, 30, 28 }, - { 0xC097CE7BC90715B3, 56, 36 }, - { 0x8F7E32CE7BEA5C70, 83, 44 }, - { 0xD5D238A4ABE98068, 109, 52 }, - { 0x9F4F2726179A2245, 136, 60 }, - { 0xED63A231D4C4FB27, 162, 68 }, - { 0xB0DE65388CC8ADA8, 189, 76 }, - { 0x83C7088E1AAB65DB, 216, 84 }, - { 0xC45D1DF942711D9A, 242, 92 }, - { 0x924D692CA61BE758, 269, 100 }, - { 0xDA01EE641A708DEA, 295, 108 }, - { 0xA26DA3999AEF774A, 322, 116 }, - { 0xF209787BB47D6B85, 348, 124 }, - { 0xB454E4A179DD1877, 375, 132 }, - { 0x865B86925B9BC5C2, 402, 140 }, - { 0xC83553C5C8965D3D, 428, 148 }, - { 0x952AB45CFA97A0B3, 455, 156 }, - { 0xDE469FBD99A05FE3, 481, 164 }, - { 0xA59BC234DB398C25, 508, 172 }, - { 0xF6C69A72A3989F5C, 534, 180 }, - { 0xB7DCBF5354E9BECE, 561, 188 }, - { 0x88FCF317F22241E2, 588, 196 }, - { 0xCC20CE9BD35C78A5, 614, 204 }, - { 0x98165AF37B2153DF, 641, 212 }, - { 0xE2A0B5DC971F303A, 667, 220 }, - { 0xA8D9D1535CE3B396, 694, 228 }, - { 0xFB9B7CD9A4A7443C, 720, 236 }, - { 0xBB764C4CA7A44410, 747, 244 }, - { 0x8BAB8EEFB6409C1A, 774, 252 }, - { 0xD01FEF10A657842C, 800, 260 }, - { 0x9B10A4E5E9913129, 827, 268 }, - { 0xE7109BFBA19C0C9D, 853, 276 }, - { 0xAC2820D9623BF429, 880, 284 }, - { 0x80444B5E7AA7CF85, 907, 292 }, - { 0xBF21E44003ACDD2D, 933, 300 }, - { 0x8E679C2F5E44FF8F, 960, 308 }, - { 0xD433179D9C8CB841, 986, 316 }, - { 0x9E19DB92B4E31BA9, 1013, 324 }, - } - }; - - // This computation gives exactly the same results for k as - // k = ceil((kAlpha - e - 1) * 0.30102999566398114) - // for |e| <= 1500, but doesn't require floating-point operations. - // NB: log_10(2) ~= 78913 / 2^18 - JSON_ASSERT(e >= -1500); - JSON_ASSERT(e <= 1500); - const int f = kAlpha - e - 1; - const int k = (f * 78913) / (1 << 18) + static_cast(f > 0); - - const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; - JSON_ASSERT(index >= 0); - JSON_ASSERT(static_cast(index) < kCachedPowers.size()); - - const cached_power cached = kCachedPowers[static_cast(index)]; - JSON_ASSERT(kAlpha <= cached.e + e + 64); - JSON_ASSERT(kGamma >= cached.e + e + 64); - - return cached; -} - -/*! -For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. -For n == 0, returns 1 and sets pow10 := 1. -*/ -inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) -{ - // LCOV_EXCL_START - if (n >= 1000000000) - { - pow10 = 1000000000; - return 10; - } - // LCOV_EXCL_STOP - else if (n >= 100000000) - { - pow10 = 100000000; - return 9; - } - else if (n >= 10000000) - { - pow10 = 10000000; - return 8; - } - else if (n >= 1000000) - { - pow10 = 1000000; - return 7; - } - else if (n >= 100000) - { - pow10 = 100000; - return 6; - } - else if (n >= 10000) - { - pow10 = 10000; - return 5; - } - else if (n >= 1000) - { - pow10 = 1000; - return 4; - } - else if (n >= 100) - { - pow10 = 100; - return 3; - } - else if (n >= 10) - { - pow10 = 10; - return 2; - } - else - { - pow10 = 1; - return 1; - } -} - -inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, - std::uint64_t rest, std::uint64_t ten_k) -{ - JSON_ASSERT(len >= 1); - JSON_ASSERT(dist <= delta); - JSON_ASSERT(rest <= delta); - JSON_ASSERT(ten_k > 0); - - // <--------------------------- delta ----> - // <---- dist ---------> - // --------------[------------------+-------------------]-------------- - // M- w M+ - // - // ten_k - // <------> - // <---- rest ----> - // --------------[------------------+----+--------------]-------------- - // w V - // = buf * 10^k - // - // ten_k represents a unit-in-the-last-place in the decimal representation - // stored in buf. - // Decrement buf by ten_k while this takes buf closer to w. - - // The tests are written in this order to avoid overflow in unsigned - // integer arithmetic. - - while (rest < dist - && delta - rest >= ten_k - && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) - { - JSON_ASSERT(buf[len - 1] != '0'); - buf[len - 1]--; - rest += ten_k; - } -} - -/*! -Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. -M- and M+ must be normalized and share the same exponent -60 <= e <= -32. -*/ -inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, - diyfp M_minus, diyfp w, diyfp M_plus) -{ - static_assert(kAlpha >= -60, "internal error"); - static_assert(kGamma <= -32, "internal error"); - - // Generates the digits (and the exponent) of a decimal floating-point - // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's - // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. - // - // <--------------------------- delta ----> - // <---- dist ---------> - // --------------[------------------+-------------------]-------------- - // M- w M+ - // - // Grisu2 generates the digits of M+ from left to right and stops as soon as - // V is in [M-,M+]. - - JSON_ASSERT(M_plus.e >= kAlpha); - JSON_ASSERT(M_plus.e <= kGamma); - - std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) - std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) - - // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): - // - // M+ = f * 2^e - // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e - // = ((p1 ) * 2^-e + (p2 )) * 2^e - // = p1 + p2 * 2^e - - const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); - - auto p1 = static_cast(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) - std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e - - // 1) - // - // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] - - JSON_ASSERT(p1 > 0); - - std::uint32_t pow10; - const int k = find_largest_pow10(p1, pow10); - - // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) - // - // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) - // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) - // - // M+ = p1 + p2 * 2^e - // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e - // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e - // = d[k-1] * 10^(k-1) + ( rest) * 2^e - // - // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) - // - // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] - // - // but stop as soon as - // - // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e - - int n = k; - while (n > 0) - { - // Invariants: - // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) - // pow10 = 10^(n-1) <= p1 < 10^n - // - const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) - const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) - // - // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e - // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) - // - JSON_ASSERT(d <= 9); - buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d - // - // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) - // - p1 = r; - n--; - // - // M+ = buffer * 10^n + (p1 + p2 * 2^e) - // pow10 = 10^n - // - - // Now check if enough digits have been generated. - // Compute - // - // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e - // - // Note: - // Since rest and delta share the same exponent e, it suffices to - // compare the significands. - const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; - if (rest <= delta) - { - // V = buffer * 10^n, with M- <= V <= M+. - - decimal_exponent += n; - - // We may now just stop. But instead look if the buffer could be - // decremented to bring V closer to w. - // - // pow10 = 10^n is now 1 ulp in the decimal representation V. - // The rounding procedure works with diyfp's with an implicit - // exponent of e. - // - // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e - // - const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; - grisu2_round(buffer, length, dist, delta, rest, ten_n); - - return; - } - - pow10 /= 10; - // - // pow10 = 10^(n-1) <= p1 < 10^n - // Invariants restored. - } - - // 2) - // - // The digits of the integral part have been generated: - // - // M+ = d[k-1]...d[1]d[0] + p2 * 2^e - // = buffer + p2 * 2^e - // - // Now generate the digits of the fractional part p2 * 2^e. - // - // Note: - // No decimal point is generated: the exponent is adjusted instead. - // - // p2 actually represents the fraction - // - // p2 * 2^e - // = p2 / 2^-e - // = d[-1] / 10^1 + d[-2] / 10^2 + ... - // - // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) - // - // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m - // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) - // - // using - // - // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) - // = ( d) * 2^-e + ( r) - // - // or - // 10^m * p2 * 2^e = d + r * 2^e - // - // i.e. - // - // M+ = buffer + p2 * 2^e - // = buffer + 10^-m * (d + r * 2^e) - // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e - // - // and stop as soon as 10^-m * r * 2^e <= delta * 2^e - - JSON_ASSERT(p2 > delta); - - int m = 0; - for (;;) - { - // Invariant: - // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e - // = buffer * 10^-m + 10^-m * (p2 ) * 2^e - // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e - // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e - // - JSON_ASSERT(p2 <= (std::numeric_limits::max)() / 10); - p2 *= 10; - const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e - const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e - // - // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e - // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) - // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e - // - JSON_ASSERT(d <= 9); - buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d - // - // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e - // - p2 = r; - m++; - // - // M+ = buffer * 10^-m + 10^-m * p2 * 2^e - // Invariant restored. - - // Check if enough digits have been generated. - // - // 10^-m * p2 * 2^e <= delta * 2^e - // p2 * 2^e <= 10^m * delta * 2^e - // p2 <= 10^m * delta - delta *= 10; - dist *= 10; - if (p2 <= delta) - { - break; - } - } - - // V = buffer * 10^-m, with M- <= V <= M+. - - decimal_exponent -= m; - - // 1 ulp in the decimal representation is now 10^-m. - // Since delta and dist are now scaled by 10^m, we need to do the - // same with ulp in order to keep the units in sync. - // - // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e - // - const std::uint64_t ten_m = one.f; - grisu2_round(buffer, length, dist, delta, p2, ten_m); - - // By construction this algorithm generates the shortest possible decimal - // number (Loitsch, Theorem 6.2) which rounds back to w. - // For an input number of precision p, at least - // - // N = 1 + ceil(p * log_10(2)) - // - // decimal digits are sufficient to identify all binary floating-point - // numbers (Matula, "In-and-Out conversions"). - // This implies that the algorithm does not produce more than N decimal - // digits. - // - // N = 17 for p = 53 (IEEE double precision) - // N = 9 for p = 24 (IEEE single precision) -} - -/*! -v = buf * 10^decimal_exponent -len is the length of the buffer (number of decimal digits) -The buffer must be large enough, i.e. >= max_digits10. -*/ -JSON_HEDLEY_NON_NULL(1) -inline void grisu2(char* buf, int& len, int& decimal_exponent, - diyfp m_minus, diyfp v, diyfp m_plus) -{ - JSON_ASSERT(m_plus.e == m_minus.e); - JSON_ASSERT(m_plus.e == v.e); - - // --------(-----------------------+-----------------------)-------- (A) - // m- v m+ - // - // --------------------(-----------+-----------------------)-------- (B) - // m- v m+ - // - // First scale v (and m- and m+) such that the exponent is in the range - // [alpha, gamma]. - - const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); - - const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k - - // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] - const diyfp w = diyfp::mul(v, c_minus_k); - const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); - const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); - - // ----(---+---)---------------(---+---)---------------(---+---)---- - // w- w w+ - // = c*m- = c*v = c*m+ - // - // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and - // w+ are now off by a small amount. - // In fact: - // - // w - v * 10^k < 1 ulp - // - // To account for this inaccuracy, add resp. subtract 1 ulp. - // - // --------+---[---------------(---+---)---------------]---+-------- - // w- M- w M+ w+ - // - // Now any number in [M-, M+] (bounds included) will round to w when input, - // regardless of how the input rounding algorithm breaks ties. - // - // And digit_gen generates the shortest possible such number in [M-, M+]. - // Note that this does not mean that Grisu2 always generates the shortest - // possible number in the interval (m-, m+). - const diyfp M_minus(w_minus.f + 1, w_minus.e); - const diyfp M_plus (w_plus.f - 1, w_plus.e ); - - decimal_exponent = -cached.k; // = -(-k) = k - - grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); -} - -/*! -v = buf * 10^decimal_exponent -len is the length of the buffer (number of decimal digits) -The buffer must be large enough, i.e. >= max_digits10. -*/ -template -JSON_HEDLEY_NON_NULL(1) -void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) -{ - static_assert(diyfp::kPrecision >= std::numeric_limits::digits + 3, - "internal error: not enough precision"); - - JSON_ASSERT(std::isfinite(value)); - JSON_ASSERT(value > 0); - - // If the neighbors (and boundaries) of 'value' are always computed for double-precision - // numbers, all float's can be recovered using strtod (and strtof). However, the resulting - // decimal representations are not exactly "short". - // - // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) - // says "value is converted to a string as if by std::sprintf in the default ("C") locale" - // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars' - // does. - // On the other hand, the documentation for 'std::to_chars' requires that "parsing the - // representation using the corresponding std::from_chars function recovers value exactly". That - // indicates that single precision floating-point numbers should be recovered using - // 'std::strtof'. - // - // NB: If the neighbors are computed for single-precision numbers, there is a single float - // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision - // value is off by 1 ulp. -#if 0 - const boundaries w = compute_boundaries(static_cast(value)); -#else - const boundaries w = compute_boundaries(value); -#endif - - grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); -} - -/*! -@brief appends a decimal representation of e to buf -@return a pointer to the element following the exponent. -@pre -1000 < e < 1000 -*/ -JSON_HEDLEY_NON_NULL(1) -JSON_HEDLEY_RETURNS_NON_NULL -inline char* append_exponent(char* buf, int e) -{ - JSON_ASSERT(e > -1000); - JSON_ASSERT(e < 1000); - - if (e < 0) - { - e = -e; - *buf++ = '-'; - } - else - { - *buf++ = '+'; - } - - auto k = static_cast(e); - if (k < 10) - { - // Always print at least two digits in the exponent. - // This is for compatibility with printf("%g"). - *buf++ = '0'; - *buf++ = static_cast('0' + k); - } - else if (k < 100) - { - *buf++ = static_cast('0' + k / 10); - k %= 10; - *buf++ = static_cast('0' + k); - } - else - { - *buf++ = static_cast('0' + k / 100); - k %= 100; - *buf++ = static_cast('0' + k / 10); - k %= 10; - *buf++ = static_cast('0' + k); - } - - return buf; -} - -/*! -@brief prettify v = buf * 10^decimal_exponent - -If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point -notation. Otherwise it will be printed in exponential notation. - -@pre min_exp < 0 -@pre max_exp > 0 -*/ -JSON_HEDLEY_NON_NULL(1) -JSON_HEDLEY_RETURNS_NON_NULL -inline char* format_buffer(char* buf, int len, int decimal_exponent, - int min_exp, int max_exp) -{ - JSON_ASSERT(min_exp < 0); - JSON_ASSERT(max_exp > 0); - - const int k = len; - const int n = len + decimal_exponent; - - // v = buf * 10^(n-k) - // k is the length of the buffer (number of decimal digits) - // n is the position of the decimal point relative to the start of the buffer. - - if (k <= n && n <= max_exp) - { - // digits[000] - // len <= max_exp + 2 - - std::memset(buf + k, '0', static_cast(n) - static_cast(k)); - // Make it look like a floating-point number (#362, #378) - buf[n + 0] = '.'; - buf[n + 1] = '0'; - return buf + (static_cast(n) + 2); - } - - if (0 < n && n <= max_exp) - { - // dig.its - // len <= max_digits10 + 1 - - JSON_ASSERT(k > n); - - std::memmove(buf + (static_cast(n) + 1), buf + n, static_cast(k) - static_cast(n)); - buf[n] = '.'; - return buf + (static_cast(k) + 1U); - } - - if (min_exp < n && n <= 0) - { - // 0.[000]digits - // len <= 2 + (-min_exp - 1) + max_digits10 - - std::memmove(buf + (2 + static_cast(-n)), buf, static_cast(k)); - buf[0] = '0'; - buf[1] = '.'; - std::memset(buf + 2, '0', static_cast(-n)); - return buf + (2U + static_cast(-n) + static_cast(k)); - } - - if (k == 1) - { - // dE+123 - // len <= 1 + 5 - - buf += 1; - } - else - { - // d.igitsE+123 - // len <= max_digits10 + 1 + 5 - - std::memmove(buf + 2, buf + 1, static_cast(k) - 1); - buf[1] = '.'; - buf += 1 + static_cast(k); - } - - *buf++ = 'e'; - return append_exponent(buf, n - 1); -} - -} // namespace dtoa_impl - -/*! -@brief generates a decimal representation of the floating-point number value in [first, last). - -The format of the resulting decimal representation is similar to printf's %g -format. Returns an iterator pointing past-the-end of the decimal representation. - -@note The input number must be finite, i.e. NaN's and Inf's are not supported. -@note The buffer must be large enough. -@note The result is NOT null-terminated. -*/ -template -JSON_HEDLEY_NON_NULL(1, 2) -JSON_HEDLEY_RETURNS_NON_NULL -char* to_chars(char* first, const char* last, FloatType value) -{ - static_cast(last); // maybe unused - fix warning - JSON_ASSERT(std::isfinite(value)); - - // Use signbit(value) instead of (value < 0) since signbit works for -0. - if (std::signbit(value)) - { - value = -value; - *first++ = '-'; - } - - if (value == 0) // +-0 - { - *first++ = '0'; - // Make it look like a floating-point number (#362, #378) - *first++ = '.'; - *first++ = '0'; - return first; - } - - JSON_ASSERT(last - first >= std::numeric_limits::max_digits10); - - // Compute v = buffer * 10^decimal_exponent. - // The decimal digits are stored in the buffer, which needs to be interpreted - // as an unsigned decimal integer. - // len is the length of the buffer, i.e. the number of decimal digits. - int len = 0; - int decimal_exponent = 0; - dtoa_impl::grisu2(first, len, decimal_exponent, value); - - JSON_ASSERT(len <= std::numeric_limits::max_digits10); - - // Format the buffer like printf("%.*g", prec, value) - constexpr int kMinExp = -4; - // Use digits10 here to increase compatibility with version 2. - constexpr int kMaxExp = std::numeric_limits::digits10; - - JSON_ASSERT(last - first >= kMaxExp + 2); - JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits::max_digits10); - JSON_ASSERT(last - first >= std::numeric_limits::max_digits10 + 6); - - return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); -} - -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - -// #include - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -/////////////////// -// serialization // -/////////////////// - -/// how to treat decoding errors -enum class error_handler_t -{ - strict, ///< throw a type_error exception in case of invalid UTF-8 - replace, ///< replace invalid UTF-8 sequences with U+FFFD - ignore ///< ignore invalid UTF-8 sequences -}; - -template -class serializer -{ - using string_t = typename BasicJsonType::string_t; - using number_float_t = typename BasicJsonType::number_float_t; - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using binary_char_t = typename BasicJsonType::binary_t::value_type; - static constexpr std::uint8_t UTF8_ACCEPT = 0; - static constexpr std::uint8_t UTF8_REJECT = 1; - - public: - /*! - @param[in] s output stream to serialize to - @param[in] ichar indentation character to use - @param[in] error_handler_ how to react on decoding errors - */ - serializer(output_adapter_t s, const char ichar, - error_handler_t error_handler_ = error_handler_t::strict) - : o(std::move(s)) - , loc(std::localeconv()) - , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->thousands_sep))) - , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->decimal_point))) - , indent_char(ichar) - , indent_string(512, indent_char) - , error_handler(error_handler_) - {} - - // delete because of pointer members - serializer(const serializer&) = delete; - serializer& operator=(const serializer&) = delete; - serializer(serializer&&) = delete; - serializer& operator=(serializer&&) = delete; - ~serializer() = default; - - /*! - @brief internal implementation of the serialization function - - This function is called by the public member function dump and organizes - the serialization internally. The indentation level is propagated as - additional parameter. In case of arrays and objects, the function is - called recursively. - - - strings and object keys are escaped using `escape_string()` - - integer numbers are converted implicitly via `operator<<` - - floating-point numbers are converted to a string using `"%g"` format - - binary values are serialized as objects containing the subtype and the - byte array - - @param[in] val value to serialize - @param[in] pretty_print whether the output shall be pretty-printed - @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters - in the output are escaped with `\uXXXX` sequences, and the result consists - of ASCII characters only. - @param[in] indent_step the indent level - @param[in] current_indent the current indent level (only used internally) - */ - void dump(const BasicJsonType& val, - const bool pretty_print, - const bool ensure_ascii, - const unsigned int indent_step, - const unsigned int current_indent = 0) - { - switch (val.m_type) - { - case value_t::object: - { - if (val.m_value.object->empty()) - { - o->write_characters("{}", 2); - return; - } - - if (pretty_print) - { - o->write_characters("{\n", 2); - - // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; - if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) - { - indent_string.resize(indent_string.size() * 2, ' '); - } - - // first n-1 elements - auto i = val.m_value.object->cbegin(); - for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) - { - o->write_characters(indent_string.c_str(), new_indent); - o->write_character('\"'); - dump_escaped(i->first, ensure_ascii); - o->write_characters("\": ", 3); - dump(i->second, true, ensure_ascii, indent_step, new_indent); - o->write_characters(",\n", 2); - } - - // last element - JSON_ASSERT(i != val.m_value.object->cend()); - JSON_ASSERT(std::next(i) == val.m_value.object->cend()); - o->write_characters(indent_string.c_str(), new_indent); - o->write_character('\"'); - dump_escaped(i->first, ensure_ascii); - o->write_characters("\": ", 3); - dump(i->second, true, ensure_ascii, indent_step, new_indent); - - o->write_character('\n'); - o->write_characters(indent_string.c_str(), current_indent); - o->write_character('}'); - } - else - { - o->write_character('{'); - - // first n-1 elements - auto i = val.m_value.object->cbegin(); - for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) - { - o->write_character('\"'); - dump_escaped(i->first, ensure_ascii); - o->write_characters("\":", 2); - dump(i->second, false, ensure_ascii, indent_step, current_indent); - o->write_character(','); - } - - // last element - JSON_ASSERT(i != val.m_value.object->cend()); - JSON_ASSERT(std::next(i) == val.m_value.object->cend()); - o->write_character('\"'); - dump_escaped(i->first, ensure_ascii); - o->write_characters("\":", 2); - dump(i->second, false, ensure_ascii, indent_step, current_indent); - - o->write_character('}'); - } - - return; - } - - case value_t::array: - { - if (val.m_value.array->empty()) - { - o->write_characters("[]", 2); - return; - } - - if (pretty_print) - { - o->write_characters("[\n", 2); - - // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; - if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) - { - indent_string.resize(indent_string.size() * 2, ' '); - } - - // first n-1 elements - for (auto i = val.m_value.array->cbegin(); - i != val.m_value.array->cend() - 1; ++i) - { - o->write_characters(indent_string.c_str(), new_indent); - dump(*i, true, ensure_ascii, indent_step, new_indent); - o->write_characters(",\n", 2); - } - - // last element - JSON_ASSERT(!val.m_value.array->empty()); - o->write_characters(indent_string.c_str(), new_indent); - dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); - - o->write_character('\n'); - o->write_characters(indent_string.c_str(), current_indent); - o->write_character(']'); - } - else - { - o->write_character('['); - - // first n-1 elements - for (auto i = val.m_value.array->cbegin(); - i != val.m_value.array->cend() - 1; ++i) - { - dump(*i, false, ensure_ascii, indent_step, current_indent); - o->write_character(','); - } - - // last element - JSON_ASSERT(!val.m_value.array->empty()); - dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); - - o->write_character(']'); - } - - return; - } - - case value_t::string: - { - o->write_character('\"'); - dump_escaped(*val.m_value.string, ensure_ascii); - o->write_character('\"'); - return; - } - - case value_t::binary: - { - if (pretty_print) - { - o->write_characters("{\n", 2); - - // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; - if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) - { - indent_string.resize(indent_string.size() * 2, ' '); - } - - o->write_characters(indent_string.c_str(), new_indent); - - o->write_characters("\"bytes\": [", 10); - - if (!val.m_value.binary->empty()) - { - for (auto i = val.m_value.binary->cbegin(); - i != val.m_value.binary->cend() - 1; ++i) - { - dump_integer(*i); - o->write_characters(", ", 2); - } - dump_integer(val.m_value.binary->back()); - } - - o->write_characters("],\n", 3); - o->write_characters(indent_string.c_str(), new_indent); - - o->write_characters("\"subtype\": ", 11); - if (val.m_value.binary->has_subtype()) - { - dump_integer(val.m_value.binary->subtype()); - } - else - { - o->write_characters("null", 4); - } - o->write_character('\n'); - o->write_characters(indent_string.c_str(), current_indent); - o->write_character('}'); - } - else - { - o->write_characters("{\"bytes\":[", 10); - - if (!val.m_value.binary->empty()) - { - for (auto i = val.m_value.binary->cbegin(); - i != val.m_value.binary->cend() - 1; ++i) - { - dump_integer(*i); - o->write_character(','); - } - dump_integer(val.m_value.binary->back()); - } - - o->write_characters("],\"subtype\":", 12); - if (val.m_value.binary->has_subtype()) - { - dump_integer(val.m_value.binary->subtype()); - o->write_character('}'); - } - else - { - o->write_characters("null}", 5); - } - } - return; - } - - case value_t::boolean: - { - if (val.m_value.boolean) - { - o->write_characters("true", 4); - } - else - { - o->write_characters("false", 5); - } - return; - } - - case value_t::number_integer: - { - dump_integer(val.m_value.number_integer); - return; - } - - case value_t::number_unsigned: - { - dump_integer(val.m_value.number_unsigned); - return; - } - - case value_t::number_float: - { - dump_float(val.m_value.number_float); - return; - } - - case value_t::discarded: - { - o->write_characters("", 11); - return; - } - - case value_t::null: - { - o->write_characters("null", 4); - return; - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - } - - JSON_PRIVATE_UNLESS_TESTED: - /*! - @brief dump escaped string - - Escape a string by replacing certain special characters by a sequence of an - escape character (backslash) and another character and other control - characters by a sequence of "\u" followed by a four-digit hex - representation. The escaped string is written to output stream @a o. - - @param[in] s the string to escape - @param[in] ensure_ascii whether to escape non-ASCII characters with - \uXXXX sequences - - @complexity Linear in the length of string @a s. - */ - void dump_escaped(const string_t& s, const bool ensure_ascii) - { - std::uint32_t codepoint; - std::uint8_t state = UTF8_ACCEPT; - std::size_t bytes = 0; // number of bytes written to string_buffer - - // number of bytes written at the point of the last valid byte - std::size_t bytes_after_last_accept = 0; - std::size_t undumped_chars = 0; - - for (std::size_t i = 0; i < s.size(); ++i) - { - const auto byte = static_cast(s[i]); - - switch (decode(state, codepoint, byte)) - { - case UTF8_ACCEPT: // decode found a new code point - { - switch (codepoint) - { - case 0x08: // backspace - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'b'; - break; - } - - case 0x09: // horizontal tab - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 't'; - break; - } - - case 0x0A: // newline - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'n'; - break; - } - - case 0x0C: // formfeed - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'f'; - break; - } - - case 0x0D: // carriage return - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'r'; - break; - } - - case 0x22: // quotation mark - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = '\"'; - break; - } - - case 0x5C: // reverse solidus - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = '\\'; - break; - } - - default: - { - // escape control characters (0x00..0x1F) or, if - // ensure_ascii parameter is used, non-ASCII characters - if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) - { - if (codepoint <= 0xFFFF) - { - (std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x", - static_cast(codepoint)); - bytes += 6; - } - else - { - (std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x", - static_cast(0xD7C0u + (codepoint >> 10u)), - static_cast(0xDC00u + (codepoint & 0x3FFu))); - bytes += 12; - } - } - else - { - // copy byte to buffer (all previous bytes - // been copied have in default case above) - string_buffer[bytes++] = s[i]; - } - break; - } - } - - // write buffer and reset index; there must be 13 bytes - // left, as this is the maximal number of bytes to be - // written ("\uxxxx\uxxxx\0") for one code point - if (string_buffer.size() - bytes < 13) - { - o->write_characters(string_buffer.data(), bytes); - bytes = 0; - } - - // remember the byte position of this accept - bytes_after_last_accept = bytes; - undumped_chars = 0; - break; - } - - case UTF8_REJECT: // decode found invalid UTF-8 byte - { - switch (error_handler) - { - case error_handler_t::strict: - { - std::string sn(3, '\0'); - (std::snprintf)(&sn[0], sn.size(), "%.2X", byte); - JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn)); - } - - case error_handler_t::ignore: - case error_handler_t::replace: - { - // in case we saw this character the first time, we - // would like to read it again, because the byte - // may be OK for itself, but just not OK for the - // previous sequence - if (undumped_chars > 0) - { - --i; - } - - // reset length buffer to the last accepted index; - // thus removing/ignoring the invalid characters - bytes = bytes_after_last_accept; - - if (error_handler == error_handler_t::replace) - { - // add a replacement character - if (ensure_ascii) - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'u'; - string_buffer[bytes++] = 'f'; - string_buffer[bytes++] = 'f'; - string_buffer[bytes++] = 'f'; - string_buffer[bytes++] = 'd'; - } - else - { - string_buffer[bytes++] = detail::binary_writer::to_char_type('\xEF'); - string_buffer[bytes++] = detail::binary_writer::to_char_type('\xBF'); - string_buffer[bytes++] = detail::binary_writer::to_char_type('\xBD'); - } - - // write buffer and reset index; there must be 13 bytes - // left, as this is the maximal number of bytes to be - // written ("\uxxxx\uxxxx\0") for one code point - if (string_buffer.size() - bytes < 13) - { - o->write_characters(string_buffer.data(), bytes); - bytes = 0; - } - - bytes_after_last_accept = bytes; - } - - undumped_chars = 0; - - // continue processing the string - state = UTF8_ACCEPT; - break; - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - break; - } - - default: // decode found yet incomplete multi-byte code point - { - if (!ensure_ascii) - { - // code point will not be escaped - copy byte to buffer - string_buffer[bytes++] = s[i]; - } - ++undumped_chars; - break; - } - } - } - - // we finished processing the string - if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) - { - // write buffer - if (bytes > 0) - { - o->write_characters(string_buffer.data(), bytes); - } - } - else - { - // we finish reading, but do not accept: string was incomplete - switch (error_handler) - { - case error_handler_t::strict: - { - std::string sn(3, '\0'); - (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast(s.back())); - JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn)); - } - - case error_handler_t::ignore: - { - // write all accepted bytes - o->write_characters(string_buffer.data(), bytes_after_last_accept); - break; - } - - case error_handler_t::replace: - { - // write all accepted bytes - o->write_characters(string_buffer.data(), bytes_after_last_accept); - // add a replacement character - if (ensure_ascii) - { - o->write_characters("\\ufffd", 6); - } - else - { - o->write_characters("\xEF\xBF\xBD", 3); - } - break; - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - } - } - - private: - /*! - @brief count digits - - Count the number of decimal (base 10) digits for an input unsigned integer. - - @param[in] x unsigned integer number to count its digits - @return number of decimal digits - */ - inline unsigned int count_digits(number_unsigned_t x) noexcept - { - unsigned int n_digits = 1; - for (;;) - { - if (x < 10) - { - return n_digits; - } - if (x < 100) - { - return n_digits + 1; - } - if (x < 1000) - { - return n_digits + 2; - } - if (x < 10000) - { - return n_digits + 3; - } - x = x / 10000u; - n_digits += 4; - } - } - - /*! - @brief dump an integer - - Dump a given integer to output stream @a o. Works internally with - @a number_buffer. - - @param[in] x integer number (signed or unsigned) to dump - @tparam NumberType either @a number_integer_t or @a number_unsigned_t - */ - template < typename NumberType, detail::enable_if_t < - std::is_same::value || - std::is_same::value || - std::is_same::value, - int > = 0 > - void dump_integer(NumberType x) - { - static constexpr std::array, 100> digits_to_99 - { - { - {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}}, - {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}}, - {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}}, - {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}}, - {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}}, - {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}}, - {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}}, - {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}}, - {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}}, - {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}}, - } - }; - - // special case for "0" - if (x == 0) - { - o->write_character('0'); - return; - } - - // use a pointer to fill the buffer - auto buffer_ptr = number_buffer.begin(); - - const bool is_negative = std::is_same::value && !(x >= 0); // see issue #755 - number_unsigned_t abs_value; - - unsigned int n_chars; - - if (is_negative) - { - *buffer_ptr = '-'; - abs_value = remove_sign(static_cast(x)); - - // account one more byte for the minus sign - n_chars = 1 + count_digits(abs_value); - } - else - { - abs_value = static_cast(x); - n_chars = count_digits(abs_value); - } - - // spare 1 byte for '\0' - JSON_ASSERT(n_chars < number_buffer.size() - 1); - - // jump to the end to generate the string from backward - // so we later avoid reversing the result - buffer_ptr += n_chars; - - // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu - // See: https://www.youtube.com/watch?v=o4-CwDo2zpg - while (abs_value >= 100) - { - const auto digits_index = static_cast((abs_value % 100)); - abs_value /= 100; - *(--buffer_ptr) = digits_to_99[digits_index][1]; - *(--buffer_ptr) = digits_to_99[digits_index][0]; - } - - if (abs_value >= 10) - { - const auto digits_index = static_cast(abs_value); - *(--buffer_ptr) = digits_to_99[digits_index][1]; - *(--buffer_ptr) = digits_to_99[digits_index][0]; - } - else - { - *(--buffer_ptr) = static_cast('0' + abs_value); - } - - o->write_characters(number_buffer.data(), n_chars); - } - - /*! - @brief dump a floating-point number - - Dump a given floating-point number to output stream @a o. Works internally - with @a number_buffer. - - @param[in] x floating-point number to dump - */ - void dump_float(number_float_t x) - { - // NaN / inf - if (!std::isfinite(x)) - { - o->write_characters("null", 4); - return; - } - - // If number_float_t is an IEEE-754 single or double precision number, - // use the Grisu2 algorithm to produce short numbers which are - // guaranteed to round-trip, using strtof and strtod, resp. - // - // NB: The test below works if == . - static constexpr bool is_ieee_single_or_double - = (std::numeric_limits::is_iec559 && std::numeric_limits::digits == 24 && std::numeric_limits::max_exponent == 128) || - (std::numeric_limits::is_iec559 && std::numeric_limits::digits == 53 && std::numeric_limits::max_exponent == 1024); - - dump_float(x, std::integral_constant()); - } - - void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) - { - char* begin = number_buffer.data(); - char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); - - o->write_characters(begin, static_cast(end - begin)); - } - - void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) - { - // get number of digits for a float -> text -> float round-trip - static constexpr auto d = std::numeric_limits::max_digits10; - - // the actual conversion - std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x); - - // negative value indicates an error - JSON_ASSERT(len > 0); - // check if buffer was large enough - JSON_ASSERT(static_cast(len) < number_buffer.size()); - - // erase thousands separator - if (thousands_sep != '\0') - { - const auto end = std::remove(number_buffer.begin(), - number_buffer.begin() + len, thousands_sep); - std::fill(end, number_buffer.end(), '\0'); - JSON_ASSERT((end - number_buffer.begin()) <= len); - len = (end - number_buffer.begin()); - } - - // convert decimal point to '.' - if (decimal_point != '\0' && decimal_point != '.') - { - const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point); - if (dec_pos != number_buffer.end()) - { - *dec_pos = '.'; - } - } - - o->write_characters(number_buffer.data(), static_cast(len)); - - // determine if need to append ".0" - const bool value_is_int_like = - std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, - [](char c) - { - return c == '.' || c == 'e'; - }); - - if (value_is_int_like) - { - o->write_characters(".0", 2); - } - } - - /*! - @brief check whether a string is UTF-8 encoded - - The function checks each byte of a string whether it is UTF-8 encoded. The - result of the check is stored in the @a state parameter. The function must - be called initially with state 0 (accept). State 1 means the string must - be rejected, because the current byte is not allowed. If the string is - completely processed, but the state is non-zero, the string ended - prematurely; that is, the last byte indicated more bytes should have - followed. - - @param[in,out] state the state of the decoding - @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT) - @param[in] byte next byte to decode - @return new state - - @note The function has been edited: a std::array is used. - - @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann - @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ - */ - static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept - { - static const std::array utf8d = - { - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF - 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF - 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF - 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF - 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2 - 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4 - 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6 - 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8 - } - }; - - const std::uint8_t type = utf8d[byte]; - - codep = (state != UTF8_ACCEPT) - ? (byte & 0x3fu) | (codep << 6u) - : (0xFFu >> type) & (byte); - - std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); - JSON_ASSERT(index < 400); - state = utf8d[index]; - return state; - } - - /* - * Overload to make the compiler happy while it is instantiating - * dump_integer for number_unsigned_t. - * Must never be called. - */ - number_unsigned_t remove_sign(number_unsigned_t x) - { - JSON_ASSERT(false); // LCOV_EXCL_LINE - return x; // LCOV_EXCL_LINE - } - - /* - * Helper function for dump_integer - * - * This function takes a negative signed integer and returns its absolute - * value as unsigned integer. The plus/minus shuffling is necessary as we can - * not directly remove the sign of an arbitrary signed integer as the - * absolute values of INT_MIN and INT_MAX are usually not the same. See - * #1708 for details. - */ - inline number_unsigned_t remove_sign(number_integer_t x) noexcept - { - JSON_ASSERT(x < 0 && x < (std::numeric_limits::max)()); - return static_cast(-(x + 1)) + 1; - } - - private: - /// the output of the serializer - output_adapter_t o = nullptr; - - /// a (hopefully) large enough character buffer - std::array number_buffer{{}}; - - /// the locale - const std::lconv* loc = nullptr; - /// the locale's thousand separator character - const char thousands_sep = '\0'; - /// the locale's decimal point character - const char decimal_point = '\0'; - - /// string buffer - std::array string_buffer{{}}; - - /// the indentation character - const char indent_char; - /// the indentation string - string_t indent_string; - - /// error_handler how to react on decoding errors - const error_handler_t error_handler; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - -// #include - - -#include // less -#include // allocator -#include // pair -#include // vector - -// #include - - -namespace nlohmann -{ - -/// ordered_map: a minimal map-like container that preserves insertion order -/// for use within nlohmann::basic_json -template , - class Allocator = std::allocator>> - struct ordered_map : std::vector, Allocator> -{ - using key_type = Key; - using mapped_type = T; - using Container = std::vector, Allocator>; - using typename Container::iterator; - using typename Container::const_iterator; - using typename Container::size_type; - using typename Container::value_type; - - // Explicit constructors instead of `using Container::Container` - // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) - ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {} - template - ordered_map(It first, It last, const Allocator& alloc = Allocator()) - : Container{first, last, alloc} {} - ordered_map(std::initializer_list init, const Allocator& alloc = Allocator() ) - : Container{init, alloc} {} - - std::pair emplace(const key_type& key, T&& t) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return {it, false}; - } - } - Container::emplace_back(key, t); - return {--this->end(), true}; - } - - T& operator[](const Key& key) - { - return emplace(key, T{}).first->second; - } - - const T& operator[](const Key& key) const - { - return at(key); - } - - T& at(const Key& key) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return it->second; - } - } - - JSON_THROW(std::out_of_range("key not found")); - } - - const T& at(const Key& key) const - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return it->second; - } - } - - JSON_THROW(std::out_of_range("key not found")); - } - - size_type erase(const Key& key) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - // Since we cannot move const Keys, re-construct them in place - for (auto next = it; ++next != this->end(); ++it) - { - it->~value_type(); // Destroy but keep allocation - new (&*it) value_type{std::move(*next)}; - } - Container::pop_back(); - return 1; - } - } - return 0; - } - - iterator erase(iterator pos) - { - auto it = pos; - - // Since we cannot move const Keys, re-construct them in place - for (auto next = it; ++next != this->end(); ++it) - { - it->~value_type(); // Destroy but keep allocation - new (&*it) value_type{std::move(*next)}; - } - Container::pop_back(); - return pos; - } - - size_type count(const Key& key) const - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return 1; - } - } - return 0; - } - - iterator find(const Key& key) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return it; - } - } - return Container::end(); - } - - const_iterator find(const Key& key) const - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return it; - } - } - return Container::end(); - } - - std::pair insert( value_type&& value ) - { - return emplace(value.first, std::move(value.second)); - } - - std::pair insert( const value_type& value ) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == value.first) - { - return {it, false}; - } - } - Container::push_back(value); - return {--this->end(), true}; - } -}; - -} // namespace nlohmann - - -/*! -@brief namespace for Niels Lohmann -@see https://github.com/nlohmann -@since version 1.0.0 -*/ -namespace nlohmann -{ - -/*! -@brief a class to store JSON values - -@tparam ObjectType type for JSON objects (`std::map` by default; will be used -in @ref object_t) -@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used -in @ref array_t) -@tparam StringType type for JSON strings and object keys (`std::string` by -default; will be used in @ref string_t) -@tparam BooleanType type for JSON booleans (`bool` by default; will be used -in @ref boolean_t) -@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by -default; will be used in @ref number_integer_t) -@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c -`uint64_t` by default; will be used in @ref number_unsigned_t) -@tparam NumberFloatType type for JSON floating-point numbers (`double` by -default; will be used in @ref number_float_t) -@tparam BinaryType type for packed binary data for compatibility with binary -serialization formats (`std::vector` by default; will be used in -@ref binary_t) -@tparam AllocatorType type of the allocator to use (`std::allocator` by -default) -@tparam JSONSerializer the serializer to resolve internal calls to `to_json()` -and `from_json()` (@ref adl_serializer by default) - -@requirement The class satisfies the following concept requirements: -- Basic - - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible): - JSON values can be default constructed. The result will be a JSON null - value. - - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible): - A JSON value can be constructed from an rvalue argument. - - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible): - A JSON value can be copy-constructed from an lvalue expression. - - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable): - A JSON value van be assigned from an rvalue argument. - - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable): - A JSON value can be copy-assigned from an lvalue expression. - - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible): - JSON values can be destructed. -- Layout - - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType): - JSON values have - [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout): - All non-static data members are private and standard layout types, the - class has no virtual functions or (virtual) base classes. -- Library-wide - - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable): - JSON values can be compared with `==`, see @ref - operator==(const_reference,const_reference). - - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable): - JSON values can be compared with `<`, see @ref - operator<(const_reference,const_reference). - - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable): - Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of - other compatible types, using unqualified function call @ref swap(). - - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer): - JSON values can be compared against `std::nullptr_t` objects which are used - to model the `null` value. -- Container - - [Container](https://en.cppreference.com/w/cpp/named_req/Container): - JSON values can be used like STL containers and provide iterator access. - - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer); - JSON values can be used like STL containers and provide reverse iterator - access. - -@invariant The member variables @a m_value and @a m_type have the following -relationship: -- If `m_type == value_t::object`, then `m_value.object != nullptr`. -- If `m_type == value_t::array`, then `m_value.array != nullptr`. -- If `m_type == value_t::string`, then `m_value.string != nullptr`. -The invariants are checked by member function assert_invariant(). - -@internal -@note ObjectType trick from https://stackoverflow.com/a/9860911 -@endinternal - -@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange -Format](http://rfc7159.net/rfc7159) - -@since version 1.0.0 - -@nosubgrouping -*/ -NLOHMANN_BASIC_JSON_TPL_DECLARATION -class basic_json -{ - private: - template friend struct detail::external_constructor; - friend ::nlohmann::json_pointer; - - template - friend class ::nlohmann::detail::parser; - friend ::nlohmann::detail::serializer; - template - friend class ::nlohmann::detail::iter_impl; - template - friend class ::nlohmann::detail::binary_writer; - template - friend class ::nlohmann::detail::binary_reader; - template - friend class ::nlohmann::detail::json_sax_dom_parser; - template - friend class ::nlohmann::detail::json_sax_dom_callback_parser; - - /// workaround type for MSVC - using basic_json_t = NLOHMANN_BASIC_JSON_TPL; - - JSON_PRIVATE_UNLESS_TESTED: - // convenience aliases for types residing in namespace detail; - using lexer = ::nlohmann::detail::lexer_base; - - template - static ::nlohmann::detail::parser parser( - InputAdapterType adapter, - detail::parser_callback_tcb = nullptr, - const bool allow_exceptions = true, - const bool ignore_comments = false - ) - { - return ::nlohmann::detail::parser(std::move(adapter), - std::move(cb), allow_exceptions, ignore_comments); - } - - private: - using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t; - template - using internal_iterator = ::nlohmann::detail::internal_iterator; - template - using iter_impl = ::nlohmann::detail::iter_impl; - template - using iteration_proxy = ::nlohmann::detail::iteration_proxy; - template using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator; - - template - using output_adapter_t = ::nlohmann::detail::output_adapter_t; - - template - using binary_reader = ::nlohmann::detail::binary_reader; - template using binary_writer = ::nlohmann::detail::binary_writer; - - JSON_PRIVATE_UNLESS_TESTED: - using serializer = ::nlohmann::detail::serializer; - - public: - using value_t = detail::value_t; - /// JSON Pointer, see @ref nlohmann::json_pointer - using json_pointer = ::nlohmann::json_pointer; - template - using json_serializer = JSONSerializer; - /// how to treat decoding errors - using error_handler_t = detail::error_handler_t; - /// how to treat CBOR tags - using cbor_tag_handler_t = detail::cbor_tag_handler_t; - /// helper type for initializer lists of basic_json values - using initializer_list_t = std::initializer_list>; - - using input_format_t = detail::input_format_t; - /// SAX interface type, see @ref nlohmann::json_sax - using json_sax_t = json_sax; - - //////////////// - // exceptions // - //////////////// - - /// @name exceptions - /// Classes to implement user-defined exceptions. - /// @{ - - /// @copydoc detail::exception - using exception = detail::exception; - /// @copydoc detail::parse_error - using parse_error = detail::parse_error; - /// @copydoc detail::invalid_iterator - using invalid_iterator = detail::invalid_iterator; - /// @copydoc detail::type_error - using type_error = detail::type_error; - /// @copydoc detail::out_of_range - using out_of_range = detail::out_of_range; - /// @copydoc detail::other_error - using other_error = detail::other_error; - - /// @} - - - ///////////////////// - // container types // - ///////////////////// - - /// @name container types - /// The canonic container types to use @ref basic_json like any other STL - /// container. - /// @{ - - /// the type of elements in a basic_json container - using value_type = basic_json; - - /// the type of an element reference - using reference = value_type&; - /// the type of an element const reference - using const_reference = const value_type&; - - /// a type to represent differences between iterators - using difference_type = std::ptrdiff_t; - /// a type to represent container sizes - using size_type = std::size_t; - - /// the allocator type - using allocator_type = AllocatorType; - - /// the type of an element pointer - using pointer = typename std::allocator_traits::pointer; - /// the type of an element const pointer - using const_pointer = typename std::allocator_traits::const_pointer; - - /// an iterator for a basic_json container - using iterator = iter_impl; - /// a const iterator for a basic_json container - using const_iterator = iter_impl; - /// a reverse iterator for a basic_json container - using reverse_iterator = json_reverse_iterator; - /// a const reverse iterator for a basic_json container - using const_reverse_iterator = json_reverse_iterator; - - /// @} - - - /*! - @brief returns the allocator associated with the container - */ - static allocator_type get_allocator() - { - return allocator_type(); - } - - /*! - @brief returns version information on the library - - This function returns a JSON object with information about the library, - including the version number and information on the platform and compiler. - - @return JSON object holding version information - key | description - ----------- | --------------- - `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version). - `copyright` | The copyright line for the library as string. - `name` | The name of the library as string. - `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`. - `url` | The URL of the project as string. - `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string). - - @liveexample{The following code shows an example output of the `meta()` - function.,meta} - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @complexity Constant. - - @since 2.1.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json meta() - { - basic_json result; - - result["copyright"] = "(C) 2013-2020 Niels Lohmann"; - result["name"] = "JSON for Modern C++"; - result["url"] = "https://github.com/nlohmann/json"; - result["version"]["string"] = - std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." + - std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." + - std::to_string(NLOHMANN_JSON_VERSION_PATCH); - result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR; - result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR; - result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH; - -#ifdef _WIN32 - result["platform"] = "win32"; -#elif defined __linux__ - result["platform"] = "linux"; -#elif defined __APPLE__ - result["platform"] = "apple"; -#elif defined __unix__ - result["platform"] = "unix"; -#else - result["platform"] = "unknown"; -#endif - -#if defined(__ICC) || defined(__INTEL_COMPILER) - result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; -#elif defined(__clang__) - result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; -#elif defined(__GNUC__) || defined(__GNUG__) - result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; -#elif defined(__HP_cc) || defined(__HP_aCC) - result["compiler"] = "hp" -#elif defined(__IBMCPP__) - result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; -#elif defined(_MSC_VER) - result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; -#elif defined(__PGI) - result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; -#elif defined(__SUNPRO_CC) - result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; -#else - result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; -#endif - -#ifdef __cplusplus - result["compiler"]["c++"] = std::to_string(__cplusplus); -#else - result["compiler"]["c++"] = "unknown"; -#endif - return result; - } - - - /////////////////////////// - // JSON value data types // - /////////////////////////// - - /// @name JSON value data types - /// The data types to store a JSON value. These types are derived from - /// the template arguments passed to class @ref basic_json. - /// @{ - -#if defined(JSON_HAS_CPP_14) - // Use transparent comparator if possible, combined with perfect forwarding - // on find() and count() calls prevents unnecessary string construction. - using object_comparator_t = std::less<>; -#else - using object_comparator_t = std::less; -#endif - - /*! - @brief a type for an object - - [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows: - > An object is an unordered collection of zero or more name/value pairs, - > where a name is a string and a value is a string, number, boolean, null, - > object, or array. - - To store objects in C++, a type is defined by the template parameters - described below. - - @tparam ObjectType the container to store objects (e.g., `std::map` or - `std::unordered_map`) - @tparam StringType the type of the keys or names (e.g., `std::string`). - The comparison function `std::less` is used to order elements - inside the container. - @tparam AllocatorType the allocator to use for objects (e.g., - `std::allocator`) - - #### Default type - - With the default values for @a ObjectType (`std::map`), @a StringType - (`std::string`), and @a AllocatorType (`std::allocator`), the default - value for @a object_t is: - - @code {.cpp} - std::map< - std::string, // key_type - basic_json, // value_type - std::less, // key_compare - std::allocator> // allocator_type - > - @endcode - - #### Behavior - - The choice of @a object_t influences the behavior of the JSON class. With - the default type, objects have the following behavior: - - - When all names are unique, objects will be interoperable in the sense - that all software implementations receiving that object will agree on - the name-value mappings. - - When the names within an object are not unique, it is unspecified which - one of the values for a given key will be chosen. For instance, - `{"key": 2, "key": 1}` could be equal to either `{"key": 1}` or - `{"key": 2}`. - - Internally, name/value pairs are stored in lexicographical order of the - names. Objects will also be serialized (see @ref dump) in this order. - For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored - and serialized as `{"a": 2, "b": 1}`. - - When comparing objects, the order of the name/value pairs is irrelevant. - This makes objects interoperable in the sense that they will not be - affected by these differences. For instance, `{"b": 1, "a": 2}` and - `{"a": 2, "b": 1}` will be treated as equal. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the maximum depth of nesting. - - In this class, the object's limit of nesting is not explicitly constrained. - However, a maximum depth of nesting may be introduced by the compiler or - runtime environment. A theoretical limit can be queried by calling the - @ref max_size function of a JSON object. - - #### Storage - - Objects are stored as pointers in a @ref basic_json type. That is, for any - access to object values, a pointer of type `object_t*` must be - dereferenced. - - @sa @ref array_t -- type for an array value - - @since version 1.0.0 - - @note The order name/value pairs are added to the object is *not* - preserved by the library. Therefore, iterating an object may return - name/value pairs in a different order than they were originally stored. In - fact, keys will be traversed in alphabetical order as `std::map` with - `std::less` is used by default. Please note this behavior conforms to [RFC - 7159](http://rfc7159.net/rfc7159), because any order implements the - specified "unordered" nature of JSON objects. - */ - using object_t = ObjectType>>; - - /*! - @brief a type for an array - - [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows: - > An array is an ordered sequence of zero or more values. - - To store objects in C++, a type is defined by the template parameters - explained below. - - @tparam ArrayType container type to store arrays (e.g., `std::vector` or - `std::list`) - @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) - - #### Default type - - With the default values for @a ArrayType (`std::vector`) and @a - AllocatorType (`std::allocator`), the default value for @a array_t is: - - @code {.cpp} - std::vector< - basic_json, // value_type - std::allocator // allocator_type - > - @endcode - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the maximum depth of nesting. - - In this class, the array's limit of nesting is not explicitly constrained. - However, a maximum depth of nesting may be introduced by the compiler or - runtime environment. A theoretical limit can be queried by calling the - @ref max_size function of a JSON array. - - #### Storage - - Arrays are stored as pointers in a @ref basic_json type. That is, for any - access to array values, a pointer of type `array_t*` must be dereferenced. - - @sa @ref object_t -- type for an object value - - @since version 1.0.0 - */ - using array_t = ArrayType>; - - /*! - @brief a type for a string - - [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows: - > A string is a sequence of zero or more Unicode characters. - - To store objects in C++, a type is defined by the template parameter - described below. Unicode values are split by the JSON class into - byte-sized characters during deserialization. - - @tparam StringType the container to store strings (e.g., `std::string`). - Note this container is used for keys/names in objects, see @ref object_t. - - #### Default type - - With the default values for @a StringType (`std::string`), the default - value for @a string_t is: - - @code {.cpp} - std::string - @endcode - - #### Encoding - - Strings are stored in UTF-8 encoding. Therefore, functions like - `std::string::size()` or `std::string::length()` return the number of - bytes in the string rather than the number of characters or glyphs. - - #### String comparison - - [RFC 7159](http://rfc7159.net/rfc7159) states: - > Software implementations are typically required to test names of object - > members for equality. Implementations that transform the textual - > representation into sequences of Unicode code units and then perform the - > comparison numerically, code unit by code unit, are interoperable in the - > sense that implementations will agree in all cases on equality or - > inequality of two strings. For example, implementations that compare - > strings with escaped characters unconverted may incorrectly find that - > `"a\\b"` and `"a\u005Cb"` are not equal. - - This implementation is interoperable as it does compare strings code unit - by code unit. - - #### Storage - - String values are stored as pointers in a @ref basic_json type. That is, - for any access to string values, a pointer of type `string_t*` must be - dereferenced. - - @since version 1.0.0 - */ - using string_t = StringType; - - /*! - @brief a type for a boolean - - [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a - type which differentiates the two literals `true` and `false`. - - To store objects in C++, a type is defined by the template parameter @a - BooleanType which chooses the type to use. - - #### Default type - - With the default values for @a BooleanType (`bool`), the default value for - @a boolean_t is: - - @code {.cpp} - bool - @endcode - - #### Storage - - Boolean values are stored directly inside a @ref basic_json type. - - @since version 1.0.0 - */ - using boolean_t = BooleanType; - - /*! - @brief a type for a number (integer) - - [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. - - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. - - To store integer numbers in C++, a type is defined by the template - parameter @a NumberIntegerType which chooses the type to use. - - #### Default type - - With the default values for @a NumberIntegerType (`int64_t`), the default - value for @a number_integer_t is: - - @code {.cpp} - int64_t - @endcode - - #### Default behavior - - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in integer literals lead to an interpretation as octal - number. Internally, the value will be stored as decimal number. For - instance, the C++ integer literal `010` will be serialized to `8`. - During deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the range and precision of numbers. - - When the default type is used, the maximal integer number that can be - stored is `9223372036854775807` (INT64_MAX) and the minimal integer number - that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers - that are out of range will yield over/underflow when used in a - constructor. During deserialization, too large or small integer numbers - will be automatically be stored as @ref number_unsigned_t or @ref - number_float_t. - - [RFC 7159](http://rfc7159.net/rfc7159) further states: - > Note that when such software is used, numbers that are integers and are - > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense - > that implementations will agree exactly on their numeric values. - - As this range is a subrange of the exactly supported range [INT64_MIN, - INT64_MAX], this class's integer type is interoperable. - - #### Storage - - Integer number values are stored directly inside a @ref basic_json type. - - @sa @ref number_float_t -- type for number values (floating-point) - - @sa @ref number_unsigned_t -- type for number values (unsigned integer) - - @since version 1.0.0 - */ - using number_integer_t = NumberIntegerType; - - /*! - @brief a type for a number (unsigned) - - [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. - - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. - - To store unsigned integer numbers in C++, a type is defined by the - template parameter @a NumberUnsignedType which chooses the type to use. - - #### Default type - - With the default values for @a NumberUnsignedType (`uint64_t`), the - default value for @a number_unsigned_t is: - - @code {.cpp} - uint64_t - @endcode - - #### Default behavior - - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in integer literals lead to an interpretation as octal - number. Internally, the value will be stored as decimal number. For - instance, the C++ integer literal `010` will be serialized to `8`. - During deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the range and precision of numbers. - - When the default type is used, the maximal integer number that can be - stored is `18446744073709551615` (UINT64_MAX) and the minimal integer - number that can be stored is `0`. Integer numbers that are out of range - will yield over/underflow when used in a constructor. During - deserialization, too large or small integer numbers will be automatically - be stored as @ref number_integer_t or @ref number_float_t. - - [RFC 7159](http://rfc7159.net/rfc7159) further states: - > Note that when such software is used, numbers that are integers and are - > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense - > that implementations will agree exactly on their numeric values. - - As this range is a subrange (when considered in conjunction with the - number_integer_t type) of the exactly supported range [0, UINT64_MAX], - this class's integer type is interoperable. - - #### Storage - - Integer number values are stored directly inside a @ref basic_json type. - - @sa @ref number_float_t -- type for number values (floating-point) - @sa @ref number_integer_t -- type for number values (integer) - - @since version 2.0.0 - */ - using number_unsigned_t = NumberUnsignedType; - - /*! - @brief a type for a number (floating-point) - - [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. - - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. - - To store floating-point numbers in C++, a type is defined by the template - parameter @a NumberFloatType which chooses the type to use. - - #### Default type - - With the default values for @a NumberFloatType (`double`), the default - value for @a number_float_t is: - - @code {.cpp} - double - @endcode - - #### Default behavior - - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in floating-point literals will be ignored. Internally, - the value will be stored as decimal number. For instance, the C++ - floating-point literal `01.2` will be serialized to `1.2`. During - deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) states: - > This specification allows implementations to set limits on the range and - > precision of numbers accepted. Since software that implements IEEE - > 754-2008 binary64 (double precision) numbers is generally available and - > widely used, good interoperability can be achieved by implementations - > that expect no more precision or range than these provide, in the sense - > that implementations will approximate JSON numbers within the expected - > precision. - - This implementation does exactly follow this approach, as it uses double - precision floating-point numbers. Note values smaller than - `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` - will be stored as NaN internally and be serialized to `null`. - - #### Storage - - Floating-point number values are stored directly inside a @ref basic_json - type. - - @sa @ref number_integer_t -- type for number values (integer) - - @sa @ref number_unsigned_t -- type for number values (unsigned integer) - - @since version 1.0.0 - */ - using number_float_t = NumberFloatType; - - /*! - @brief a type for a packed binary type - - This type is a type designed to carry binary data that appears in various - serialized formats, such as CBOR's Major Type 2, MessagePack's bin, and - BSON's generic binary subtype. This type is NOT a part of standard JSON and - exists solely for compatibility with these binary types. As such, it is - simply defined as an ordered sequence of zero or more byte values. - - Additionally, as an implementation detail, the subtype of the binary data is - carried around as a `std::uint8_t`, which is compatible with both of the - binary data formats that use binary subtyping, (though the specific - numbering is incompatible with each other, and it is up to the user to - translate between them). - - [CBOR's RFC 7049](https://tools.ietf.org/html/rfc7049) describes this type - as: - > Major type 2: a byte string. The string's length in bytes is represented - > following the rules for positive integers (major type 0). - - [MessagePack's documentation on the bin type - family](https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family) - describes this type as: - > Bin format family stores an byte array in 2, 3, or 5 bytes of extra bytes - > in addition to the size of the byte array. - - [BSON's specifications](http://bsonspec.org/spec.html) describe several - binary types; however, this type is intended to represent the generic binary - type which has the description: - > Generic binary subtype - This is the most commonly used binary subtype and - > should be the 'default' for drivers and tools. - - None of these impose any limitations on the internal representation other - than the basic unit of storage be some type of array whose parts are - decomposable into bytes. - - The default representation of this binary format is a - `std::vector`, which is a very common way to represent a byte - array in modern C++. - - #### Default type - - The default values for @a BinaryType is `std::vector` - - #### Storage - - Binary Arrays are stored as pointers in a @ref basic_json type. That is, - for any access to array values, a pointer of the type `binary_t*` must be - dereferenced. - - #### Notes on subtypes - - - CBOR - - Binary values are represented as byte strings. No subtypes are - supported and will be ignored when CBOR is written. - - MessagePack - - If a subtype is given and the binary array contains exactly 1, 2, 4, 8, - or 16 elements, the fixext family (fixext1, fixext2, fixext4, fixext8) - is used. For other sizes, the ext family (ext8, ext16, ext32) is used. - The subtype is then added as singed 8-bit integer. - - If no subtype is given, the bin family (bin8, bin16, bin32) is used. - - BSON - - If a subtype is given, it is used and added as unsigned 8-bit integer. - - If no subtype is given, the generic binary subtype 0x00 is used. - - @sa @ref binary -- create a binary array - - @since version 3.8.0 - */ - using binary_t = nlohmann::byte_container_with_subtype; - /// @} - - private: - - /// helper for exception-safe object creation - template - JSON_HEDLEY_RETURNS_NON_NULL - static T* create(Args&& ... args) - { - AllocatorType alloc; - using AllocatorTraits = std::allocator_traits>; - - auto deleter = [&](T * object) - { - AllocatorTraits::deallocate(alloc, object, 1); - }; - std::unique_ptr object(AllocatorTraits::allocate(alloc, 1), deleter); - AllocatorTraits::construct(alloc, object.get(), std::forward(args)...); - JSON_ASSERT(object != nullptr); - return object.release(); - } - - //////////////////////// - // JSON value storage // - //////////////////////// - - JSON_PRIVATE_UNLESS_TESTED: - /*! - @brief a JSON value - - The actual storage for a JSON value of the @ref basic_json class. This - union combines the different storage types for the JSON value types - defined in @ref value_t. - - JSON type | value_t type | used type - --------- | --------------- | ------------------------ - object | object | pointer to @ref object_t - array | array | pointer to @ref array_t - string | string | pointer to @ref string_t - boolean | boolean | @ref boolean_t - number | number_integer | @ref number_integer_t - number | number_unsigned | @ref number_unsigned_t - number | number_float | @ref number_float_t - binary | binary | pointer to @ref binary_t - null | null | *no value is stored* - - @note Variable-length types (objects, arrays, and strings) are stored as - pointers. The size of the union should not exceed 64 bits if the default - value types are used. - - @since version 1.0.0 - */ - union json_value - { - /// object (stored with pointer to save storage) - object_t* object; - /// array (stored with pointer to save storage) - array_t* array; - /// string (stored with pointer to save storage) - string_t* string; - /// binary (stored with pointer to save storage) - binary_t* binary; - /// boolean - boolean_t boolean; - /// number (integer) - number_integer_t number_integer; - /// number (unsigned integer) - number_unsigned_t number_unsigned; - /// number (floating-point) - number_float_t number_float; - - /// default constructor (for null values) - json_value() = default; - /// constructor for booleans - json_value(boolean_t v) noexcept : boolean(v) {} - /// constructor for numbers (integer) - json_value(number_integer_t v) noexcept : number_integer(v) {} - /// constructor for numbers (unsigned) - json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} - /// constructor for numbers (floating-point) - json_value(number_float_t v) noexcept : number_float(v) {} - /// constructor for empty values of a given type - json_value(value_t t) - { - switch (t) - { - case value_t::object: - { - object = create(); - break; - } - - case value_t::array: - { - array = create(); - break; - } - - case value_t::string: - { - string = create(""); - break; - } - - case value_t::binary: - { - binary = create(); - break; - } - - case value_t::boolean: - { - boolean = boolean_t(false); - break; - } - - case value_t::number_integer: - { - number_integer = number_integer_t(0); - break; - } - - case value_t::number_unsigned: - { - number_unsigned = number_unsigned_t(0); - break; - } - - case value_t::number_float: - { - number_float = number_float_t(0.0); - break; - } - - case value_t::null: - { - object = nullptr; // silence warning, see #821 - break; - } - - default: - { - object = nullptr; // silence warning, see #821 - if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) - { - JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.9.1")); // LCOV_EXCL_LINE - } - break; - } - } - } - - /// constructor for strings - json_value(const string_t& value) - { - string = create(value); - } - - /// constructor for rvalue strings - json_value(string_t&& value) - { - string = create(std::move(value)); - } - - /// constructor for objects - json_value(const object_t& value) - { - object = create(value); - } - - /// constructor for rvalue objects - json_value(object_t&& value) - { - object = create(std::move(value)); - } - - /// constructor for arrays - json_value(const array_t& value) - { - array = create(value); - } - - /// constructor for rvalue arrays - json_value(array_t&& value) - { - array = create(std::move(value)); - } - - /// constructor for binary arrays - json_value(const typename binary_t::container_type& value) - { - binary = create(value); - } - - /// constructor for rvalue binary arrays - json_value(typename binary_t::container_type&& value) - { - binary = create(std::move(value)); - } - - /// constructor for binary arrays (internal type) - json_value(const binary_t& value) - { - binary = create(value); - } - - /// constructor for rvalue binary arrays (internal type) - json_value(binary_t&& value) - { - binary = create(std::move(value)); - } - - void destroy(value_t t) noexcept - { - // flatten the current json_value to a heap-allocated stack - std::vector stack; - - // move the top-level items to stack - if (t == value_t::array) - { - stack.reserve(array->size()); - std::move(array->begin(), array->end(), std::back_inserter(stack)); - } - else if (t == value_t::object) - { - stack.reserve(object->size()); - for (auto&& it : *object) - { - stack.push_back(std::move(it.second)); - } - } - - while (!stack.empty()) - { - // move the last item to local variable to be processed - basic_json current_item(std::move(stack.back())); - stack.pop_back(); - - // if current_item is array/object, move - // its children to the stack to be processed later - if (current_item.is_array()) - { - std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), - std::back_inserter(stack)); - - current_item.m_value.array->clear(); - } - else if (current_item.is_object()) - { - for (auto&& it : *current_item.m_value.object) - { - stack.push_back(std::move(it.second)); - } - - current_item.m_value.object->clear(); - } - - // it's now safe that current_item get destructed - // since it doesn't have any children - } - - switch (t) - { - case value_t::object: - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, object); - std::allocator_traits::deallocate(alloc, object, 1); - break; - } - - case value_t::array: - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, array); - std::allocator_traits::deallocate(alloc, array, 1); - break; - } - - case value_t::string: - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, string); - std::allocator_traits::deallocate(alloc, string, 1); - break; - } - - case value_t::binary: - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, binary); - std::allocator_traits::deallocate(alloc, binary, 1); - break; - } - - default: - { - break; - } - } - } - }; - - private: - /*! - @brief checks the class invariants - - This function asserts the class invariants. It needs to be called at the - end of every constructor to make sure that created objects respect the - invariant. Furthermore, it has to be called each time the type of a JSON - value is changed, because the invariant expresses a relationship between - @a m_type and @a m_value. - */ - void assert_invariant() const noexcept - { - JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr); - JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr); - JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr); - JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr); - } - - public: - ////////////////////////// - // JSON parser callback // - ////////////////////////// - - /*! - @brief parser event types - - The parser callback distinguishes the following events: - - `object_start`: the parser read `{` and started to process a JSON object - - `key`: the parser read a key of a value in an object - - `object_end`: the parser read `}` and finished processing a JSON object - - `array_start`: the parser read `[` and started to process a JSON array - - `array_end`: the parser read `]` and finished processing a JSON array - - `value`: the parser finished reading a JSON value - - @image html callback_events.png "Example when certain parse events are triggered" - - @sa @ref parser_callback_t for more information and examples - */ - using parse_event_t = detail::parse_event_t; - - /*! - @brief per-element parser callback type - - With a parser callback function, the result of parsing a JSON text can be - influenced. When passed to @ref parse, it is called on certain events - (passed as @ref parse_event_t via parameter @a event) with a set recursion - depth @a depth and context JSON value @a parsed. The return value of the - callback function is a boolean indicating whether the element that emitted - the callback shall be kept or not. - - We distinguish six scenarios (determined by the event type) in which the - callback function can be called. The following table describes the values - of the parameters @a depth, @a event, and @a parsed. - - parameter @a event | description | parameter @a depth | parameter @a parsed - ------------------ | ----------- | ------------------ | ------------------- - parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded - parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key - parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object - parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded - parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array - parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value - - @image html callback_events.png "Example when certain parse events are triggered" - - Discarding a value (i.e., returning `false`) has different effects - depending on the context in which function was called: - - - Discarded values in structured types are skipped. That is, the parser - will behave as if the discarded value was never read. - - In case a value outside a structured type is skipped, it is replaced - with `null`. This case happens if the top-level element is skipped. - - @param[in] depth the depth of the recursion during parsing - - @param[in] event an event of type parse_event_t indicating the context in - the callback function has been called - - @param[in,out] parsed the current intermediate parse result; note that - writing to this value has no effect for parse_event_t::key events - - @return Whether the JSON value which called the function during parsing - should be kept (`true`) or not (`false`). In the latter case, it is either - skipped completely or replaced by an empty discarded object. - - @sa @ref parse for examples - - @since version 1.0.0 - */ - using parser_callback_t = detail::parser_callback_t; - - ////////////////// - // constructors // - ////////////////// - - /// @name constructors and destructors - /// Constructors of class @ref basic_json, copy/move constructor, copy - /// assignment, static functions creating objects, and the destructor. - /// @{ - - /*! - @brief create an empty value with a given type - - Create an empty JSON value with a given type. The value will be default - initialized with an empty value which depends on the type: - - Value type | initial value - ----------- | ------------- - null | `null` - boolean | `false` - string | `""` - number | `0` - object | `{}` - array | `[]` - binary | empty array - - @param[in] v the type of the value to create - - @complexity Constant. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The following code shows the constructor for different @ref - value_t values,basic_json__value_t} - - @sa @ref clear() -- restores the postcondition of this constructor - - @since version 1.0.0 - */ - basic_json(const value_t v) - : m_type(v), m_value(v) - { - assert_invariant(); - } - - /*! - @brief create a null object - - Create a `null` JSON value. It either takes a null pointer as parameter - (explicitly creating `null`) or no parameter (implicitly creating `null`). - The passed null pointer itself is not read -- it is only used to choose - the right constructor. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this constructor never throws - exceptions. - - @liveexample{The following code shows the constructor with and without a - null pointer parameter.,basic_json__nullptr_t} - - @since version 1.0.0 - */ - basic_json(std::nullptr_t = nullptr) noexcept - : basic_json(value_t::null) - { - assert_invariant(); - } - - /*! - @brief create a JSON value - - This is a "catch all" constructor for all compatible JSON types; that is, - types for which a `to_json()` method exists. The constructor forwards the - parameter @a val to that method (to `json_serializer::to_json` method - with `U = uncvref_t`, to be exact). - - Template type @a CompatibleType includes, but is not limited to, the - following types: - - **arrays**: @ref array_t and all kinds of compatible containers such as - `std::vector`, `std::deque`, `std::list`, `std::forward_list`, - `std::array`, `std::valarray`, `std::set`, `std::unordered_set`, - `std::multiset`, and `std::unordered_multiset` with a `value_type` from - which a @ref basic_json value can be constructed. - - **objects**: @ref object_t and all kinds of compatible associative - containers such as `std::map`, `std::unordered_map`, `std::multimap`, - and `std::unordered_multimap` with a `key_type` compatible to - @ref string_t and a `value_type` from which a @ref basic_json value can - be constructed. - - **strings**: @ref string_t, string literals, and all compatible string - containers can be used. - - **numbers**: @ref number_integer_t, @ref number_unsigned_t, - @ref number_float_t, and all convertible number types such as `int`, - `size_t`, `int64_t`, `float` or `double` can be used. - - **boolean**: @ref boolean_t / `bool` can be used. - - **binary**: @ref binary_t / `std::vector` may be used, - unfortunately because string literals cannot be distinguished from binary - character arrays by the C++ type system, all types compatible with `const - char*` will be directed to the string constructor instead. This is both - for backwards compatibility, and due to the fact that a binary type is not - a standard JSON type. - - See the examples below. - - @tparam CompatibleType a type such that: - - @a CompatibleType is not derived from `std::istream`, - - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move - constructors), - - @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments) - - @a CompatibleType is not a @ref basic_json nested type (e.g., - @ref json_pointer, @ref iterator, etc ...) - - @ref @ref json_serializer has a - `to_json(basic_json_t&, CompatibleType&&)` method - - @tparam U = `uncvref_t` - - @param[in] val the value to be forwarded to the respective constructor - - @complexity Usually linear in the size of the passed @a val, also - depending on the implementation of the called `to_json()` - method. - - @exceptionsafety Depends on the called constructor. For types directly - supported by the library (i.e., all types for which no `to_json()` function - was provided), strong guarantee holds: if an exception is thrown, there are - no changes to any JSON value. - - @liveexample{The following code shows the constructor with several - compatible types.,basic_json__CompatibleType} - - @since version 2.1.0 - */ - template < typename CompatibleType, - typename U = detail::uncvref_t, - detail::enable_if_t < - !detail::is_basic_json::value && detail::is_compatible_type::value, int > = 0 > - basic_json(CompatibleType && val) noexcept(noexcept( - JSONSerializer::to_json(std::declval(), - std::forward(val)))) - { - JSONSerializer::to_json(*this, std::forward(val)); - assert_invariant(); - } - - /*! - @brief create a JSON value from an existing one - - This is a constructor for existing @ref basic_json types. - It does not hijack copy/move constructors, since the parameter has different - template arguments than the current ones. - - The constructor tries to convert the internal @ref m_value of the parameter. - - @tparam BasicJsonType a type such that: - - @a BasicJsonType is a @ref basic_json type. - - @a BasicJsonType has different template arguments than @ref basic_json_t. - - @param[in] val the @ref basic_json value to be converted. - - @complexity Usually linear in the size of the passed @a val, also - depending on the implementation of the called `to_json()` - method. - - @exceptionsafety Depends on the called constructor. For types directly - supported by the library (i.e., all types for which no `to_json()` function - was provided), strong guarantee holds: if an exception is thrown, there are - no changes to any JSON value. - - @since version 3.2.0 - */ - template < typename BasicJsonType, - detail::enable_if_t < - detail::is_basic_json::value&& !std::is_same::value, int > = 0 > - basic_json(const BasicJsonType& val) - { - using other_boolean_t = typename BasicJsonType::boolean_t; - using other_number_float_t = typename BasicJsonType::number_float_t; - using other_number_integer_t = typename BasicJsonType::number_integer_t; - using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using other_string_t = typename BasicJsonType::string_t; - using other_object_t = typename BasicJsonType::object_t; - using other_array_t = typename BasicJsonType::array_t; - using other_binary_t = typename BasicJsonType::binary_t; - - switch (val.type()) - { - case value_t::boolean: - JSONSerializer::to_json(*this, val.template get()); - break; - case value_t::number_float: - JSONSerializer::to_json(*this, val.template get()); - break; - case value_t::number_integer: - JSONSerializer::to_json(*this, val.template get()); - break; - case value_t::number_unsigned: - JSONSerializer::to_json(*this, val.template get()); - break; - case value_t::string: - JSONSerializer::to_json(*this, val.template get_ref()); - break; - case value_t::object: - JSONSerializer::to_json(*this, val.template get_ref()); - break; - case value_t::array: - JSONSerializer::to_json(*this, val.template get_ref()); - break; - case value_t::binary: - JSONSerializer::to_json(*this, val.template get_ref()); - break; - case value_t::null: - *this = nullptr; - break; - case value_t::discarded: - m_type = value_t::discarded; - break; - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - assert_invariant(); - } - - /*! - @brief create a container (array or object) from an initializer list - - Creates a JSON value of type array or object from the passed initializer - list @a init. In case @a type_deduction is `true` (default), the type of - the JSON value to be created is deducted from the initializer list @a init - according to the following rules: - - 1. If the list is empty, an empty JSON object value `{}` is created. - 2. If the list consists of pairs whose first element is a string, a JSON - object value is created where the first elements of the pairs are - treated as keys and the second elements are as values. - 3. In all other cases, an array is created. - - The rules aim to create the best fit between a C++ initializer list and - JSON values. The rationale is as follows: - - 1. The empty initializer list is written as `{}` which is exactly an empty - JSON object. - 2. C++ has no way of describing mapped types other than to list a list of - pairs. As JSON requires that keys must be of type string, rule 2 is the - weakest constraint one can pose on initializer lists to interpret them - as an object. - 3. In all other cases, the initializer list could not be interpreted as - JSON object type, so interpreting it as JSON array type is safe. - - With the rules described above, the following JSON values cannot be - expressed by an initializer list: - - - the empty array (`[]`): use @ref array(initializer_list_t) - with an empty initializer list in this case - - arrays whose elements satisfy rule 2: use @ref - array(initializer_list_t) with the same initializer list - in this case - - @note When used without parentheses around an empty initializer list, @ref - basic_json() is called instead of this function, yielding the JSON null - value. - - @param[in] init initializer list with JSON values - - @param[in] type_deduction internal parameter; when set to `true`, the type - of the JSON value is deducted from the initializer list @a init; when set - to `false`, the type provided via @a manual_type is forced. This mode is - used by the functions @ref array(initializer_list_t) and - @ref object(initializer_list_t). - - @param[in] manual_type internal parameter; when @a type_deduction is set - to `false`, the created JSON value will use the provided type (only @ref - value_t::array and @ref value_t::object are valid); when @a type_deduction - is set to `true`, this parameter has no effect - - @throw type_error.301 if @a type_deduction is `false`, @a manual_type is - `value_t::object`, but @a init contains an element which is not a pair - whose first element is a string. In this case, the constructor could not - create an object. If @a type_deduction would have be `true`, an array - would have been created. See @ref object(initializer_list_t) - for an example. - - @complexity Linear in the size of the initializer list @a init. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The example below shows how JSON values are created from - initializer lists.,basic_json__list_init_t} - - @sa @ref array(initializer_list_t) -- create a JSON array - value from an initializer list - @sa @ref object(initializer_list_t) -- create a JSON object - value from an initializer list - - @since version 1.0.0 - */ - basic_json(initializer_list_t init, - bool type_deduction = true, - value_t manual_type = value_t::array) - { - // check if each element is an array with two elements whose first - // element is a string - bool is_an_object = std::all_of(init.begin(), init.end(), - [](const detail::json_ref& element_ref) - { - return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string(); - }); - - // adjust type if type deduction is not wanted - if (!type_deduction) - { - // if array is wanted, do not create an object though possible - if (manual_type == value_t::array) - { - is_an_object = false; - } - - // if object is wanted but impossible, throw an exception - if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) - { - JSON_THROW(type_error::create(301, "cannot create object from initializer list")); - } - } - - if (is_an_object) - { - // the initializer list is a list of pairs -> create object - m_type = value_t::object; - m_value = value_t::object; - - std::for_each(init.begin(), init.end(), [this](const detail::json_ref& element_ref) - { - auto element = element_ref.moved_or_copied(); - m_value.object->emplace( - std::move(*((*element.m_value.array)[0].m_value.string)), - std::move((*element.m_value.array)[1])); - }); - } - else - { - // the initializer list describes an array -> create array - m_type = value_t::array; - m_value.array = create(init.begin(), init.end()); - } - - assert_invariant(); - } - - /*! - @brief explicitly create a binary array (without subtype) - - Creates a JSON binary array value from a given binary container. Binary - values are part of various binary formats, such as CBOR, MessagePack, and - BSON. This constructor is used to create a value for serialization to those - formats. - - @note Note, this function exists because of the difficulty in correctly - specifying the correct template overload in the standard value ctor, as both - JSON arrays and JSON binary arrays are backed with some form of a - `std::vector`. Because JSON binary arrays are a non-standard extension it - was decided that it would be best to prevent automatic initialization of a - binary array type, for backwards compatibility and so it does not happen on - accident. - - @param[in] init container containing bytes to use as binary type - - @return JSON binary array value - - @complexity Linear in the size of @a init. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @since version 3.8.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json binary(const typename binary_t::container_type& init) - { - auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = init; - return res; - } - - /*! - @brief explicitly create a binary array (with subtype) - - Creates a JSON binary array value from a given binary container. Binary - values are part of various binary formats, such as CBOR, MessagePack, and - BSON. This constructor is used to create a value for serialization to those - formats. - - @note Note, this function exists because of the difficulty in correctly - specifying the correct template overload in the standard value ctor, as both - JSON arrays and JSON binary arrays are backed with some form of a - `std::vector`. Because JSON binary arrays are a non-standard extension it - was decided that it would be best to prevent automatic initialization of a - binary array type, for backwards compatibility and so it does not happen on - accident. - - @param[in] init container containing bytes to use as binary type - @param[in] subtype subtype to use in MessagePack and BSON - - @return JSON binary array value - - @complexity Linear in the size of @a init. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @since version 3.8.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json binary(const typename binary_t::container_type& init, std::uint8_t subtype) - { - auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = binary_t(init, subtype); - return res; - } - - /// @copydoc binary(const typename binary_t::container_type&) - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json binary(typename binary_t::container_type&& init) - { - auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = std::move(init); - return res; - } - - /// @copydoc binary(const typename binary_t::container_type&, std::uint8_t) - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json binary(typename binary_t::container_type&& init, std::uint8_t subtype) - { - auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = binary_t(std::move(init), subtype); - return res; - } - - /*! - @brief explicitly create an array from an initializer list - - Creates a JSON array value from a given initializer list. That is, given a - list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the - initializer list is empty, the empty array `[]` is created. - - @note This function is only needed to express two edge cases that cannot - be realized with the initializer list constructor (@ref - basic_json(initializer_list_t, bool, value_t)). These cases - are: - 1. creating an array whose elements are all pairs whose first element is a - string -- in this case, the initializer list constructor would create an - object, taking the first elements as keys - 2. creating an empty array -- passing the empty initializer list to the - initializer list constructor yields an empty object - - @param[in] init initializer list with JSON values to create an array from - (optional) - - @return JSON array value - - @complexity Linear in the size of @a init. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The following code shows an example for the `array` - function.,array} - - @sa @ref basic_json(initializer_list_t, bool, value_t) -- - create a JSON value from an initializer list - @sa @ref object(initializer_list_t) -- create a JSON object - value from an initializer list - - @since version 1.0.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json array(initializer_list_t init = {}) - { - return basic_json(init, false, value_t::array); - } - - /*! - @brief explicitly create an object from an initializer list - - Creates a JSON object value from a given initializer list. The initializer - lists elements must be pairs, and their first elements must be strings. If - the initializer list is empty, the empty object `{}` is created. - - @note This function is only added for symmetry reasons. In contrast to the - related function @ref array(initializer_list_t), there are - no cases which can only be expressed by this function. That is, any - initializer list @a init can also be passed to the initializer list - constructor @ref basic_json(initializer_list_t, bool, value_t). - - @param[in] init initializer list to create an object from (optional) - - @return JSON object value - - @throw type_error.301 if @a init is not a list of pairs whose first - elements are strings. In this case, no object can be created. When such a - value is passed to @ref basic_json(initializer_list_t, bool, value_t), - an array would have been created from the passed initializer list @a init. - See example below. - - @complexity Linear in the size of @a init. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The following code shows an example for the `object` - function.,object} - - @sa @ref basic_json(initializer_list_t, bool, value_t) -- - create a JSON value from an initializer list - @sa @ref array(initializer_list_t) -- create a JSON array - value from an initializer list - - @since version 1.0.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json object(initializer_list_t init = {}) - { - return basic_json(init, false, value_t::object); - } - - /*! - @brief construct an array with count copies of given value - - Constructs a JSON array value by creating @a cnt copies of a passed value. - In case @a cnt is `0`, an empty array is created. - - @param[in] cnt the number of JSON copies of @a val to create - @param[in] val the JSON value to copy - - @post `std::distance(begin(),end()) == cnt` holds. - - @complexity Linear in @a cnt. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The following code shows examples for the @ref - basic_json(size_type\, const basic_json&) - constructor.,basic_json__size_type_basic_json} - - @since version 1.0.0 - */ - basic_json(size_type cnt, const basic_json& val) - : m_type(value_t::array) - { - m_value.array = create(cnt, val); - assert_invariant(); - } - - /*! - @brief construct a JSON container given an iterator range - - Constructs the JSON value with the contents of the range `[first, last)`. - The semantics depends on the different types a JSON value can have: - - In case of a null type, invalid_iterator.206 is thrown. - - In case of other primitive types (number, boolean, or string), @a first - must be `begin()` and @a last must be `end()`. In this case, the value is - copied. Otherwise, invalid_iterator.204 is thrown. - - In case of structured types (array, object), the constructor behaves as - similar versions for `std::vector` or `std::map`; that is, a JSON array - or object is constructed from the values in the range. - - @tparam InputIT an input iterator type (@ref iterator or @ref - const_iterator) - - @param[in] first begin of the range to copy from (included) - @param[in] last end of the range to copy from (excluded) - - @pre Iterators @a first and @a last must be initialized. **This - precondition is enforced with an assertion (see warning).** If - assertions are switched off, a violation of this precondition yields - undefined behavior. - - @pre Range `[first, last)` is valid. Usually, this precondition cannot be - checked efficiently. Only certain edge cases are detected; see the - description of the exceptions below. A violation of this precondition - yields undefined behavior. - - @warning A precondition is enforced with a runtime assertion that will - result in calling `std::abort` if this precondition is not met. - Assertions can be disabled by defining `NDEBUG` at compile time. - See https://en.cppreference.com/w/cpp/error/assert for more - information. - - @throw invalid_iterator.201 if iterators @a first and @a last are not - compatible (i.e., do not belong to the same JSON value). In this case, - the range `[first, last)` is undefined. - @throw invalid_iterator.204 if iterators @a first and @a last belong to a - primitive type (number, boolean, or string), but @a first does not point - to the first element any more. In this case, the range `[first, last)` is - undefined. See example code below. - @throw invalid_iterator.206 if iterators @a first and @a last belong to a - null value. In this case, the range `[first, last)` is undefined. - - @complexity Linear in distance between @a first and @a last. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The example below shows several ways to create JSON values by - specifying a subrange with iterators.,basic_json__InputIt_InputIt} - - @since version 1.0.0 - */ - template < class InputIT, typename std::enable_if < - std::is_same::value || - std::is_same::value, int >::type = 0 > - basic_json(InputIT first, InputIT last) - { - JSON_ASSERT(first.m_object != nullptr); - JSON_ASSERT(last.m_object != nullptr); - - // make sure iterator fits the current value - if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) - { - JSON_THROW(invalid_iterator::create(201, "iterators are not compatible")); - } - - // copy type from first iterator - m_type = first.m_object->m_type; - - // check if iterator range is complete for primitive values - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - { - if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin() - || !last.m_it.primitive_iterator.is_end())) - { - JSON_THROW(invalid_iterator::create(204, "iterators out of range")); - } - break; - } - - default: - break; - } - - switch (m_type) - { - case value_t::number_integer: - { - m_value.number_integer = first.m_object->m_value.number_integer; - break; - } - - case value_t::number_unsigned: - { - m_value.number_unsigned = first.m_object->m_value.number_unsigned; - break; - } - - case value_t::number_float: - { - m_value.number_float = first.m_object->m_value.number_float; - break; - } - - case value_t::boolean: - { - m_value.boolean = first.m_object->m_value.boolean; - break; - } - - case value_t::string: - { - m_value = *first.m_object->m_value.string; - break; - } - - case value_t::object: - { - m_value.object = create(first.m_it.object_iterator, - last.m_it.object_iterator); - break; - } - - case value_t::array: - { - m_value.array = create(first.m_it.array_iterator, - last.m_it.array_iterator); - break; - } - - case value_t::binary: - { - m_value = *first.m_object->m_value.binary; - break; - } - - default: - JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + - std::string(first.m_object->type_name()))); - } - - assert_invariant(); - } - - - /////////////////////////////////////// - // other constructors and destructor // - /////////////////////////////////////// - - template, - std::is_same>::value, int> = 0 > - basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {} - - /*! - @brief copy constructor - - Creates a copy of a given JSON value. - - @param[in] other the JSON value to copy - - @post `*this == other` - - @complexity Linear in the size of @a other. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is linear. - - As postcondition, it holds: `other == basic_json(other)`. - - @liveexample{The following code shows an example for the copy - constructor.,basic_json__basic_json} - - @since version 1.0.0 - */ - basic_json(const basic_json& other) - : m_type(other.m_type) - { - // check of passed value is valid - other.assert_invariant(); - - switch (m_type) - { - case value_t::object: - { - m_value = *other.m_value.object; - break; - } - - case value_t::array: - { - m_value = *other.m_value.array; - break; - } - - case value_t::string: - { - m_value = *other.m_value.string; - break; - } - - case value_t::boolean: - { - m_value = other.m_value.boolean; - break; - } - - case value_t::number_integer: - { - m_value = other.m_value.number_integer; - break; - } - - case value_t::number_unsigned: - { - m_value = other.m_value.number_unsigned; - break; - } - - case value_t::number_float: - { - m_value = other.m_value.number_float; - break; - } - - case value_t::binary: - { - m_value = *other.m_value.binary; - break; - } - - default: - break; - } - - assert_invariant(); - } - - /*! - @brief move constructor - - Move constructor. Constructs a JSON value with the contents of the given - value @a other using move semantics. It "steals" the resources from @a - other and leaves it as JSON null value. - - @param[in,out] other value to move to this object - - @post `*this` has the same value as @a other before the call. - @post @a other is a JSON null value. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this constructor never throws - exceptions. - - @requirement This function helps `basic_json` satisfying the - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible) - requirements. - - @liveexample{The code below shows the move constructor explicitly called - via std::move.,basic_json__moveconstructor} - - @since version 1.0.0 - */ - basic_json(basic_json&& other) noexcept - : m_type(std::move(other.m_type)), - m_value(std::move(other.m_value)) - { - // check that passed value is valid - other.assert_invariant(); - - // invalidate payload - other.m_type = value_t::null; - other.m_value = {}; - - assert_invariant(); - } - - /*! - @brief copy assignment - - Copy assignment operator. Copies a JSON value via the "copy and swap" - strategy: It is expressed in terms of the copy constructor, destructor, - and the `swap()` member function. - - @param[in] other value to copy from - - @complexity Linear. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is linear. - - @liveexample{The code below shows and example for the copy assignment. It - creates a copy of value `a` which is then swapped with `b`. Finally\, the - copy of `a` (which is the null value after the swap) is - destroyed.,basic_json__copyassignment} - - @since version 1.0.0 - */ - basic_json& operator=(basic_json other) noexcept ( - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value - ) - { - // check that passed value is valid - other.assert_invariant(); - - using std::swap; - swap(m_type, other.m_type); - swap(m_value, other.m_value); - - assert_invariant(); - return *this; - } - - /*! - @brief destructor - - Destroys the JSON value and frees all allocated memory. - - @complexity Linear. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is linear. - - All stored elements are destroyed and all memory is freed. - - @since version 1.0.0 - */ - ~basic_json() noexcept - { - assert_invariant(); - m_value.destroy(m_type); - } - - /// @} - - public: - /////////////////////// - // object inspection // - /////////////////////// - - /// @name object inspection - /// Functions to inspect the type of a JSON value. - /// @{ - - /*! - @brief serialization - - Serialization function for JSON values. The function tries to mimic - Python's `json.dumps()` function, and currently supports its @a indent - and @a ensure_ascii parameters. - - @param[in] indent If indent is nonnegative, then array elements and object - members will be pretty-printed with that indent level. An indent level of - `0` will only insert newlines. `-1` (the default) selects the most compact - representation. - @param[in] indent_char The character to use for indentation if @a indent is - greater than `0`. The default is ` ` (space). - @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters - in the output are escaped with `\uXXXX` sequences, and the result consists - of ASCII characters only. - @param[in] error_handler how to react on decoding errors; there are three - possible values: `strict` (throws and exception in case a decoding error - occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD), - and `ignore` (ignore invalid UTF-8 sequences during serialization; all - bytes are copied to the output unchanged). - - @return string containing the serialization of the JSON value - - @throw type_error.316 if a string stored inside the JSON value is not - UTF-8 encoded and @a error_handler is set to strict - - @note Binary values are serialized as object containing two keys: - - "bytes": an array of bytes as integers - - "subtype": the subtype as integer or "null" if the binary has no subtype - - @complexity Linear. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @liveexample{The following example shows the effect of different @a indent\, - @a indent_char\, and @a ensure_ascii parameters to the result of the - serialization.,dump} - - @see https://docs.python.org/2/library/json.html#json.dump - - @since version 1.0.0; indentation character @a indent_char, option - @a ensure_ascii and exceptions added in version 3.0.0; error - handlers added in version 3.4.0; serialization of binary values added - in version 3.8.0. - */ - string_t dump(const int indent = -1, - const char indent_char = ' ', - const bool ensure_ascii = false, - const error_handler_t error_handler = error_handler_t::strict) const - { - string_t result; - serializer s(detail::output_adapter(result), indent_char, error_handler); - - if (indent >= 0) - { - s.dump(*this, true, ensure_ascii, static_cast(indent)); - } - else - { - s.dump(*this, false, ensure_ascii, 0); - } - - return result; - } - - /*! - @brief return the type of the JSON value (explicit) - - Return the type of the JSON value as a value from the @ref value_t - enumeration. - - @return the type of the JSON value - Value type | return value - ------------------------- | ------------------------- - null | value_t::null - boolean | value_t::boolean - string | value_t::string - number (integer) | value_t::number_integer - number (unsigned integer) | value_t::number_unsigned - number (floating-point) | value_t::number_float - object | value_t::object - array | value_t::array - binary | value_t::binary - discarded | value_t::discarded - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `type()` for all JSON - types.,type} - - @sa @ref operator value_t() -- return the type of the JSON value (implicit) - @sa @ref type_name() -- return the type as string - - @since version 1.0.0 - */ - constexpr value_t type() const noexcept - { - return m_type; - } - - /*! - @brief return whether type is primitive - - This function returns true if and only if the JSON type is primitive - (string, number, boolean, or null). - - @return `true` if type is primitive (string, number, boolean, or null), - `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_primitive()` for all JSON - types.,is_primitive} - - @sa @ref is_structured() -- returns whether JSON value is structured - @sa @ref is_null() -- returns whether JSON value is `null` - @sa @ref is_string() -- returns whether JSON value is a string - @sa @ref is_boolean() -- returns whether JSON value is a boolean - @sa @ref is_number() -- returns whether JSON value is a number - @sa @ref is_binary() -- returns whether JSON value is a binary array - - @since version 1.0.0 - */ - constexpr bool is_primitive() const noexcept - { - return is_null() || is_string() || is_boolean() || is_number() || is_binary(); - } - - /*! - @brief return whether type is structured - - This function returns true if and only if the JSON type is structured - (array or object). - - @return `true` if type is structured (array or object), `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_structured()` for all JSON - types.,is_structured} - - @sa @ref is_primitive() -- returns whether value is primitive - @sa @ref is_array() -- returns whether value is an array - @sa @ref is_object() -- returns whether value is an object - - @since version 1.0.0 - */ - constexpr bool is_structured() const noexcept - { - return is_array() || is_object(); - } - - /*! - @brief return whether value is null - - This function returns true if and only if the JSON value is null. - - @return `true` if type is null, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_null()` for all JSON - types.,is_null} - - @since version 1.0.0 - */ - constexpr bool is_null() const noexcept - { - return m_type == value_t::null; - } - - /*! - @brief return whether value is a boolean - - This function returns true if and only if the JSON value is a boolean. - - @return `true` if type is boolean, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_boolean()` for all JSON - types.,is_boolean} - - @since version 1.0.0 - */ - constexpr bool is_boolean() const noexcept - { - return m_type == value_t::boolean; - } - - /*! - @brief return whether value is a number - - This function returns true if and only if the JSON value is a number. This - includes both integer (signed and unsigned) and floating-point values. - - @return `true` if type is number (regardless whether integer, unsigned - integer or floating-type), `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number()` for all JSON - types.,is_number} - - @sa @ref is_number_integer() -- check if value is an integer or unsigned - integer number - @sa @ref is_number_unsigned() -- check if value is an unsigned integer - number - @sa @ref is_number_float() -- check if value is a floating-point number - - @since version 1.0.0 - */ - constexpr bool is_number() const noexcept - { - return is_number_integer() || is_number_float(); - } - - /*! - @brief return whether value is an integer number - - This function returns true if and only if the JSON value is a signed or - unsigned integer number. This excludes floating-point values. - - @return `true` if type is an integer or unsigned integer number, `false` - otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number_integer()` for all - JSON types.,is_number_integer} - - @sa @ref is_number() -- check if value is a number - @sa @ref is_number_unsigned() -- check if value is an unsigned integer - number - @sa @ref is_number_float() -- check if value is a floating-point number - - @since version 1.0.0 - */ - constexpr bool is_number_integer() const noexcept - { - return m_type == value_t::number_integer || m_type == value_t::number_unsigned; - } - - /*! - @brief return whether value is an unsigned integer number - - This function returns true if and only if the JSON value is an unsigned - integer number. This excludes floating-point and signed integer values. - - @return `true` if type is an unsigned integer number, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number_unsigned()` for all - JSON types.,is_number_unsigned} - - @sa @ref is_number() -- check if value is a number - @sa @ref is_number_integer() -- check if value is an integer or unsigned - integer number - @sa @ref is_number_float() -- check if value is a floating-point number - - @since version 2.0.0 - */ - constexpr bool is_number_unsigned() const noexcept - { - return m_type == value_t::number_unsigned; - } - - /*! - @brief return whether value is a floating-point number - - This function returns true if and only if the JSON value is a - floating-point number. This excludes signed and unsigned integer values. - - @return `true` if type is a floating-point number, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number_float()` for all - JSON types.,is_number_float} - - @sa @ref is_number() -- check if value is number - @sa @ref is_number_integer() -- check if value is an integer number - @sa @ref is_number_unsigned() -- check if value is an unsigned integer - number - - @since version 1.0.0 - */ - constexpr bool is_number_float() const noexcept - { - return m_type == value_t::number_float; - } - - /*! - @brief return whether value is an object - - This function returns true if and only if the JSON value is an object. - - @return `true` if type is object, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_object()` for all JSON - types.,is_object} - - @since version 1.0.0 - */ - constexpr bool is_object() const noexcept - { - return m_type == value_t::object; - } - - /*! - @brief return whether value is an array - - This function returns true if and only if the JSON value is an array. - - @return `true` if type is array, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_array()` for all JSON - types.,is_array} - - @since version 1.0.0 - */ - constexpr bool is_array() const noexcept - { - return m_type == value_t::array; - } - - /*! - @brief return whether value is a string - - This function returns true if and only if the JSON value is a string. - - @return `true` if type is string, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_string()` for all JSON - types.,is_string} - - @since version 1.0.0 - */ - constexpr bool is_string() const noexcept - { - return m_type == value_t::string; - } - - /*! - @brief return whether value is a binary array - - This function returns true if and only if the JSON value is a binary array. - - @return `true` if type is binary array, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_binary()` for all JSON - types.,is_binary} - - @since version 3.8.0 - */ - constexpr bool is_binary() const noexcept - { - return m_type == value_t::binary; - } - - /*! - @brief return whether value is discarded - - This function returns true if and only if the JSON value was discarded - during parsing with a callback function (see @ref parser_callback_t). - - @note This function will always be `false` for JSON values after parsing. - That is, discarded values can only occur during parsing, but will be - removed when inside a structured value or replaced by null in other cases. - - @return `true` if type is discarded, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_discarded()` for all JSON - types.,is_discarded} - - @since version 1.0.0 - */ - constexpr bool is_discarded() const noexcept - { - return m_type == value_t::discarded; - } - - /*! - @brief return the type of the JSON value (implicit) - - Implicitly return the type of the JSON value as a value from the @ref - value_t enumeration. - - @return the type of the JSON value - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies the @ref value_t operator for - all JSON types.,operator__value_t} - - @sa @ref type() -- return the type of the JSON value (explicit) - @sa @ref type_name() -- return the type as string - - @since version 1.0.0 - */ - constexpr operator value_t() const noexcept - { - return m_type; - } - - /// @} - - private: - ////////////////// - // value access // - ////////////////// - - /// get a boolean (explicit) - boolean_t get_impl(boolean_t* /*unused*/) const - { - if (JSON_HEDLEY_LIKELY(is_boolean())) - { - return m_value.boolean; - } - - JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()))); - } - - /// get a pointer to the value (object) - object_t* get_impl_ptr(object_t* /*unused*/) noexcept - { - return is_object() ? m_value.object : nullptr; - } - - /// get a pointer to the value (object) - constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept - { - return is_object() ? m_value.object : nullptr; - } - - /// get a pointer to the value (array) - array_t* get_impl_ptr(array_t* /*unused*/) noexcept - { - return is_array() ? m_value.array : nullptr; - } - - /// get a pointer to the value (array) - constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept - { - return is_array() ? m_value.array : nullptr; - } - - /// get a pointer to the value (string) - string_t* get_impl_ptr(string_t* /*unused*/) noexcept - { - return is_string() ? m_value.string : nullptr; - } - - /// get a pointer to the value (string) - constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept - { - return is_string() ? m_value.string : nullptr; - } - - /// get a pointer to the value (boolean) - boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept - { - return is_boolean() ? &m_value.boolean : nullptr; - } - - /// get a pointer to the value (boolean) - constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept - { - return is_boolean() ? &m_value.boolean : nullptr; - } - - /// get a pointer to the value (integer number) - number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept - { - return is_number_integer() ? &m_value.number_integer : nullptr; - } - - /// get a pointer to the value (integer number) - constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept - { - return is_number_integer() ? &m_value.number_integer : nullptr; - } - - /// get a pointer to the value (unsigned number) - number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept - { - return is_number_unsigned() ? &m_value.number_unsigned : nullptr; - } - - /// get a pointer to the value (unsigned number) - constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept - { - return is_number_unsigned() ? &m_value.number_unsigned : nullptr; - } - - /// get a pointer to the value (floating-point number) - number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept - { - return is_number_float() ? &m_value.number_float : nullptr; - } - - /// get a pointer to the value (floating-point number) - constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept - { - return is_number_float() ? &m_value.number_float : nullptr; - } - - /// get a pointer to the value (binary) - binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept - { - return is_binary() ? m_value.binary : nullptr; - } - - /// get a pointer to the value (binary) - constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept - { - return is_binary() ? m_value.binary : nullptr; - } - - /*! - @brief helper function to implement get_ref() - - This function helps to implement get_ref() without code duplication for - const and non-const overloads - - @tparam ThisType will be deduced as `basic_json` or `const basic_json` - - @throw type_error.303 if ReferenceType does not match underlying value - type of the current JSON - */ - template - static ReferenceType get_ref_impl(ThisType& obj) - { - // delegate the call to get_ptr<>() - auto ptr = obj.template get_ptr::type>(); - - if (JSON_HEDLEY_LIKELY(ptr != nullptr)) - { - return *ptr; - } - - JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()))); - } - - public: - /// @name value access - /// Direct access to the stored value of a JSON value. - /// @{ - - /*! - @brief get special-case overload - - This overloads avoids a lot of template boilerplate, it can be seen as the - identity method - - @tparam BasicJsonType == @ref basic_json - - @return a copy of *this - - @complexity Constant. - - @since version 2.1.0 - */ - template::type, basic_json_t>::value, - int> = 0> - basic_json get() const - { - return *this; - } - - /*! - @brief get special-case overload - - This overloads converts the current @ref basic_json in a different - @ref basic_json type - - @tparam BasicJsonType == @ref basic_json - - @return a copy of *this, converted into @tparam BasicJsonType - - @complexity Depending on the implementation of the called `from_json()` - method. - - @since version 3.2.0 - */ - template < typename BasicJsonType, detail::enable_if_t < - !std::is_same::value&& - detail::is_basic_json::value, int > = 0 > - BasicJsonType get() const - { - return *this; - } - - /*! - @brief get a value (explicit) - - Explicit type conversion between the JSON value and a compatible value - which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) - and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). - The value is converted by calling the @ref json_serializer - `from_json()` method. - - The function is equivalent to executing - @code {.cpp} - ValueType ret; - JSONSerializer::from_json(*this, ret); - return ret; - @endcode - - This overloads is chosen if: - - @a ValueType is not @ref basic_json, - - @ref json_serializer has a `from_json()` method of the form - `void from_json(const basic_json&, ValueType&)`, and - - @ref json_serializer does not have a `from_json()` method of - the form `ValueType from_json(const basic_json&)` - - @tparam ValueTypeCV the provided value type - @tparam ValueType the returned value type - - @return copy of the JSON value, converted to @a ValueType - - @throw what @ref json_serializer `from_json()` method throws - - @liveexample{The example below shows several conversions from JSON values - to other types. There a few things to note: (1) Floating-point numbers can - be converted to integers\, (2) A JSON array can be converted to a standard - `std::vector`\, (3) A JSON object can be converted to C++ - associative containers such as `std::unordered_map`.,get__ValueType_const} - - @since version 2.1.0 - */ - template < typename ValueTypeCV, typename ValueType = detail::uncvref_t, - detail::enable_if_t < - !detail::is_basic_json::value && - detail::has_from_json::value && - !detail::has_non_default_from_json::value, - int > = 0 > - ValueType get() const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), std::declval()))) - { - // we cannot static_assert on ValueTypeCV being non-const, because - // there is support for get(), which is why we - // still need the uncvref - static_assert(!std::is_reference::value, - "get() cannot be used with reference types, you might want to use get_ref()"); - static_assert(std::is_default_constructible::value, - "types must be DefaultConstructible when used with get()"); - - ValueType ret; - JSONSerializer::from_json(*this, ret); - return ret; - } - - /*! - @brief get a value (explicit); special case - - Explicit type conversion between the JSON value and a compatible value - which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) - and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). - The value is converted by calling the @ref json_serializer - `from_json()` method. - - The function is equivalent to executing - @code {.cpp} - return JSONSerializer::from_json(*this); - @endcode - - This overloads is chosen if: - - @a ValueType is not @ref basic_json and - - @ref json_serializer has a `from_json()` method of the form - `ValueType from_json(const basic_json&)` - - @note If @ref json_serializer has both overloads of - `from_json()`, this one is chosen. - - @tparam ValueTypeCV the provided value type - @tparam ValueType the returned value type - - @return copy of the JSON value, converted to @a ValueType - - @throw what @ref json_serializer `from_json()` method throws - - @since version 2.1.0 - */ - template < typename ValueTypeCV, typename ValueType = detail::uncvref_t, - detail::enable_if_t < !std::is_same::value && - detail::has_non_default_from_json::value, - int > = 0 > - ValueType get() const noexcept(noexcept( - JSONSerializer::from_json(std::declval()))) - { - static_assert(!std::is_reference::value, - "get() cannot be used with reference types, you might want to use get_ref()"); - return JSONSerializer::from_json(*this); - } - - /*! - @brief get a value (explicit) - - Explicit type conversion between the JSON value and a compatible value. - The value is filled into the input parameter by calling the @ref json_serializer - `from_json()` method. - - The function is equivalent to executing - @code {.cpp} - ValueType v; - JSONSerializer::from_json(*this, v); - @endcode - - This overloads is chosen if: - - @a ValueType is not @ref basic_json, - - @ref json_serializer has a `from_json()` method of the form - `void from_json(const basic_json&, ValueType&)`, and - - @tparam ValueType the input parameter type. - - @return the input parameter, allowing chaining calls. - - @throw what @ref json_serializer `from_json()` method throws - - @liveexample{The example below shows several conversions from JSON values - to other types. There a few things to note: (1) Floating-point numbers can - be converted to integers\, (2) A JSON array can be converted to a standard - `std::vector`\, (3) A JSON object can be converted to C++ - associative containers such as `std::unordered_map`.,get_to} - - @since version 3.3.0 - */ - template < typename ValueType, - detail::enable_if_t < - !detail::is_basic_json::value&& - detail::has_from_json::value, - int > = 0 > - ValueType & get_to(ValueType& v) const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), v))) - { - JSONSerializer::from_json(*this, v); - return v; - } - - // specialization to allow to call get_to with a basic_json value - // see https://github.com/nlohmann/json/issues/2175 - template::value, - int> = 0> - ValueType & get_to(ValueType& v) const - { - v = *this; - return v; - } - - template < - typename T, std::size_t N, - typename Array = T (&)[N], - detail::enable_if_t < - detail::has_from_json::value, int > = 0 > - Array get_to(T (&v)[N]) const - noexcept(noexcept(JSONSerializer::from_json( - std::declval(), v))) - { - JSONSerializer::from_json(*this, v); - return v; - } - - - /*! - @brief get a pointer value (implicit) - - Implicit pointer access to the internally stored JSON value. No copies are - made. - - @warning Writing data to the pointee of the result yields an undefined - state. - - @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref - object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, - @ref number_unsigned_t, or @ref number_float_t. Enforced by a static - assertion. - - @return pointer to the internally stored JSON value if the requested - pointer type @a PointerType fits to the JSON value; `nullptr` otherwise - - @complexity Constant. - - @liveexample{The example below shows how pointers to internal values of a - JSON value can be requested. Note that no type conversions are made and a - `nullptr` is returned if the value and the requested pointer type does not - match.,get_ptr} - - @since version 1.0.0 - */ - template::value, int>::type = 0> - auto get_ptr() noexcept -> decltype(std::declval().get_impl_ptr(std::declval())) - { - // delegate the call to get_impl_ptr<>() - return get_impl_ptr(static_cast(nullptr)); - } - - /*! - @brief get a pointer value (implicit) - @copydoc get_ptr() - */ - template < typename PointerType, typename std::enable_if < - std::is_pointer::value&& - std::is_const::type>::value, int >::type = 0 > - constexpr auto get_ptr() const noexcept -> decltype(std::declval().get_impl_ptr(std::declval())) - { - // delegate the call to get_impl_ptr<>() const - return get_impl_ptr(static_cast(nullptr)); - } - - /*! - @brief get a pointer value (explicit) - - Explicit pointer access to the internally stored JSON value. No copies are - made. - - @warning The pointer becomes invalid if the underlying JSON object - changes. - - @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref - object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, - @ref number_unsigned_t, or @ref number_float_t. - - @return pointer to the internally stored JSON value if the requested - pointer type @a PointerType fits to the JSON value; `nullptr` otherwise - - @complexity Constant. - - @liveexample{The example below shows how pointers to internal values of a - JSON value can be requested. Note that no type conversions are made and a - `nullptr` is returned if the value and the requested pointer type does not - match.,get__PointerType} - - @sa @ref get_ptr() for explicit pointer-member access - - @since version 1.0.0 - */ - template::value, int>::type = 0> - auto get() noexcept -> decltype(std::declval().template get_ptr()) - { - // delegate the call to get_ptr - return get_ptr(); - } - - /*! - @brief get a pointer value (explicit) - @copydoc get() - */ - template::value, int>::type = 0> - constexpr auto get() const noexcept -> decltype(std::declval().template get_ptr()) - { - // delegate the call to get_ptr - return get_ptr(); - } - - /*! - @brief get a reference value (implicit) - - Implicit reference access to the internally stored JSON value. No copies - are made. - - @warning Writing data to the referee of the result yields an undefined - state. - - @tparam ReferenceType reference type; must be a reference to @ref array_t, - @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or - @ref number_float_t. Enforced by static assertion. - - @return reference to the internally stored JSON value if the requested - reference type @a ReferenceType fits to the JSON value; throws - type_error.303 otherwise - - @throw type_error.303 in case passed type @a ReferenceType is incompatible - with the stored JSON value; see example below - - @complexity Constant. - - @liveexample{The example shows several calls to `get_ref()`.,get_ref} - - @since version 1.1.0 - */ - template::value, int>::type = 0> - ReferenceType get_ref() - { - // delegate call to get_ref_impl - return get_ref_impl(*this); - } - - /*! - @brief get a reference value (implicit) - @copydoc get_ref() - */ - template < typename ReferenceType, typename std::enable_if < - std::is_reference::value&& - std::is_const::type>::value, int >::type = 0 > - ReferenceType get_ref() const - { - // delegate call to get_ref_impl - return get_ref_impl(*this); - } - - /*! - @brief get a value (implicit) - - Implicit type conversion between the JSON value and a compatible value. - The call is realized by calling @ref get() const. - - @tparam ValueType non-pointer type compatible to the JSON value, for - instance `int` for JSON integer numbers, `bool` for JSON booleans, or - `std::vector` types for JSON arrays. The character type of @ref string_t - as well as an initializer list of this type is excluded to avoid - ambiguities as these types implicitly convert to `std::string`. - - @return copy of the JSON value, converted to type @a ValueType - - @throw type_error.302 in case passed type @a ValueType is incompatible - to the JSON value type (e.g., the JSON value is of type boolean, but a - string is requested); see example below - - @complexity Linear in the size of the JSON value. - - @liveexample{The example below shows several conversions from JSON values - to other types. There a few things to note: (1) Floating-point numbers can - be converted to integers\, (2) A JSON array can be converted to a standard - `std::vector`\, (3) A JSON object can be converted to C++ - associative containers such as `std::unordered_map`.,operator__ValueType} - - @since version 1.0.0 - */ - template < typename ValueType, typename std::enable_if < - !std::is_pointer::value&& - !std::is_same>::value&& - !std::is_same::value&& - !detail::is_basic_json::value - && !std::is_same>::value -#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914)) - && !std::is_same::value -#endif - && detail::is_detected::value - , int >::type = 0 > - JSON_EXPLICIT operator ValueType() const - { - // delegate the call to get<>() const - return get(); - } - - /*! - @return reference to the binary value - - @throw type_error.302 if the value is not binary - - @sa @ref is_binary() to check if the value is binary - - @since version 3.8.0 - */ - binary_t& get_binary() - { - if (!is_binary()) - { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()))); - } - - return *get_ptr(); - } - - /// @copydoc get_binary() - const binary_t& get_binary() const - { - if (!is_binary()) - { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()))); - } - - return *get_ptr(); - } - - /// @} - - - //////////////////// - // element access // - //////////////////// - - /// @name element access - /// Access to the JSON value. - /// @{ - - /*! - @brief access specified array element with bounds checking - - Returns a reference to the element at specified location @a idx, with - bounds checking. - - @param[in] idx index of the element to access - - @return reference to the element at index @a idx - - @throw type_error.304 if the JSON value is not an array; in this case, - calling `at` with an index makes no sense. See example below. - @throw out_of_range.401 if the index @a idx is out of range of the array; - that is, `idx >= size()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 1.0.0 - - @liveexample{The example below shows how array elements can be read and - written using `at()`. It also demonstrates the different exceptions that - can be thrown.,at__size_type} - */ - reference at(size_type idx) - { - // at only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - JSON_TRY - { - return m_value.array->at(idx); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); - } - } - - /*! - @brief access specified array element with bounds checking - - Returns a const reference to the element at specified location @a idx, - with bounds checking. - - @param[in] idx index of the element to access - - @return const reference to the element at index @a idx - - @throw type_error.304 if the JSON value is not an array; in this case, - calling `at` with an index makes no sense. See example below. - @throw out_of_range.401 if the index @a idx is out of range of the array; - that is, `idx >= size()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 1.0.0 - - @liveexample{The example below shows how array elements can be read using - `at()`. It also demonstrates the different exceptions that can be thrown., - at__size_type_const} - */ - const_reference at(size_type idx) const - { - // at only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - JSON_TRY - { - return m_value.array->at(idx); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); - } - } - - /*! - @brief access specified object element with bounds checking - - Returns a reference to the element at with specified key @a key, with - bounds checking. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.304 if the JSON value is not an object; in this case, - calling `at` with a key makes no sense. See example below. - @throw out_of_range.403 if the key @a key is is not stored in the object; - that is, `find(key) == end()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Logarithmic in the size of the container. - - @sa @ref operator[](const typename object_t::key_type&) for unchecked - access by reference - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - - @liveexample{The example below shows how object elements can be read and - written using `at()`. It also demonstrates the different exceptions that - can be thrown.,at__object_t_key_type} - */ - reference at(const typename object_t::key_type& key) - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_TRY - { - return m_value.object->at(key); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); - } - } - - /*! - @brief access specified object element with bounds checking - - Returns a const reference to the element at with specified key @a key, - with bounds checking. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @throw type_error.304 if the JSON value is not an object; in this case, - calling `at` with a key makes no sense. See example below. - @throw out_of_range.403 if the key @a key is is not stored in the object; - that is, `find(key) == end()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Logarithmic in the size of the container. - - @sa @ref operator[](const typename object_t::key_type&) for unchecked - access by reference - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - - @liveexample{The example below shows how object elements can be read using - `at()`. It also demonstrates the different exceptions that can be thrown., - at__object_t_key_type_const} - */ - const_reference at(const typename object_t::key_type& key) const - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_TRY - { - return m_value.object->at(key); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); - } - } - - /*! - @brief access specified array element - - Returns a reference to the element at specified location @a idx. - - @note If @a idx is beyond the range of the array (i.e., `idx >= size()`), - then the array is silently filled up with `null` values to make `idx` a - valid reference to the last stored element. - - @param[in] idx index of the element to access - - @return reference to the element at index @a idx - - @throw type_error.305 if the JSON value is not an array or null; in that - cases, using the [] operator with an index makes no sense. - - @complexity Constant if @a idx is in the range of the array. Otherwise - linear in `idx - size()`. - - @liveexample{The example below shows how array elements can be read and - written using `[]` operator. Note the addition of `null` - values.,operatorarray__size_type} - - @since version 1.0.0 - */ - reference operator[](size_type idx) - { - // implicitly convert null value to an empty array - if (is_null()) - { - m_type = value_t::array; - m_value.array = create(); - assert_invariant(); - } - - // operator[] only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - // fill up array with null values if given idx is outside range - if (idx >= m_value.array->size()) - { - m_value.array->insert(m_value.array->end(), - idx - m_value.array->size() + 1, - basic_json()); - } - - return m_value.array->operator[](idx); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()))); - } - - /*! - @brief access specified array element - - Returns a const reference to the element at specified location @a idx. - - @param[in] idx index of the element to access - - @return const reference to the element at index @a idx - - @throw type_error.305 if the JSON value is not an array; in that case, - using the [] operator with an index makes no sense. - - @complexity Constant. - - @liveexample{The example below shows how array elements can be read using - the `[]` operator.,operatorarray__size_type_const} - - @since version 1.0.0 - */ - const_reference operator[](size_type idx) const - { - // const operator[] only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - return m_value.array->operator[](idx); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()))); - } - - /*! - @brief access specified object element - - Returns a reference to the element at with specified key @a key. - - @note If @a key is not found in the object, then it is silently added to - the object and filled with a `null` value to make `key` a valid reference. - In case the value was `null` before, it is converted to an object. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.305 if the JSON value is not an object or null; in that - cases, using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read and - written using the `[]` operator.,operatorarray__key_type} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - */ - reference operator[](const typename object_t::key_type& key) - { - // implicitly convert null value to an empty object - if (is_null()) - { - m_type = value_t::object; - m_value.object = create(); - assert_invariant(); - } - - // operator[] only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - return m_value.object->operator[](key); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); - } - - /*! - @brief read-only access specified object element - - Returns a const reference to the element at with specified key @a key. No - bounds checking is performed. - - @warning If the element with key @a key does not exist, the behavior is - undefined. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @pre The element with key @a key must exist. **This precondition is - enforced with an assertion.** - - @throw type_error.305 if the JSON value is not an object; in that case, - using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read using - the `[]` operator.,operatorarray__key_type_const} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - */ - const_reference operator[](const typename object_t::key_type& key) const - { - // const operator[] only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_ASSERT(m_value.object->find(key) != m_value.object->end()); - return m_value.object->find(key)->second; - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); - } - - /*! - @brief access specified object element - - Returns a reference to the element at with specified key @a key. - - @note If @a key is not found in the object, then it is silently added to - the object and filled with a `null` value to make `key` a valid reference. - In case the value was `null` before, it is converted to an object. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.305 if the JSON value is not an object or null; in that - cases, using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read and - written using the `[]` operator.,operatorarray__key_type} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.1.0 - */ - template - JSON_HEDLEY_NON_NULL(2) - reference operator[](T* key) - { - // implicitly convert null to object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); - } - - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - return m_value.object->operator[](key); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); - } - - /*! - @brief read-only access specified object element - - Returns a const reference to the element at with specified key @a key. No - bounds checking is performed. - - @warning If the element with key @a key does not exist, the behavior is - undefined. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @pre The element with key @a key must exist. **This precondition is - enforced with an assertion.** - - @throw type_error.305 if the JSON value is not an object; in that case, - using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read using - the `[]` operator.,operatorarray__key_type_const} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.1.0 - */ - template - JSON_HEDLEY_NON_NULL(2) - const_reference operator[](T* key) const - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_ASSERT(m_value.object->find(key) != m_value.object->end()); - return m_value.object->find(key)->second; - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); - } - - /*! - @brief access specified object element with default value - - Returns either a copy of an object's element at the specified key @a key - or a given default value if no element with key @a key exists. - - The function is basically equivalent to executing - @code {.cpp} - try { - return at(key); - } catch(out_of_range) { - return default_value; - } - @endcode - - @note Unlike @ref at(const typename object_t::key_type&), this function - does not throw if the given key @a key was not found. - - @note Unlike @ref operator[](const typename object_t::key_type& key), this - function does not implicitly add an element to the position defined by @a - key. This function is furthermore also applicable to const objects. - - @param[in] key key of the element to access - @param[in] default_value the value to return if @a key is not found - - @tparam ValueType type compatible to JSON values, for instance `int` for - JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for - JSON arrays. Note the type of the expected value at @a key and the default - value @a default_value must be compatible. - - @return copy of the element at key @a key or @a default_value if @a key - is not found - - @throw type_error.302 if @a default_value does not match the type of the - value at @a key - @throw type_error.306 if the JSON value is not an object; in that case, - using `value()` with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be queried - with a default value.,basic_json__value} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref operator[](const typename object_t::key_type&) for unchecked - access by reference - - @since version 1.0.0 - */ - // using std::is_convertible in a std::enable_if will fail when using explicit conversions - template < class ValueType, typename std::enable_if < - detail::is_getable::value - && !std::is_same::value, int >::type = 0 > - ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - // if key is found, return value and given default value otherwise - const auto it = find(key); - if (it != end()) - { - return it->template get(); - } - - return default_value; - } - - JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); - } - - /*! - @brief overload for a default value of type const char* - @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const - */ - string_t value(const typename object_t::key_type& key, const char* default_value) const - { - return value(key, string_t(default_value)); - } - - /*! - @brief access specified object element via JSON Pointer with default value - - Returns either a copy of an object's element at the specified key @a key - or a given default value if no element with key @a key exists. - - The function is basically equivalent to executing - @code {.cpp} - try { - return at(ptr); - } catch(out_of_range) { - return default_value; - } - @endcode - - @note Unlike @ref at(const json_pointer&), this function does not throw - if the given key @a key was not found. - - @param[in] ptr a JSON pointer to the element to access - @param[in] default_value the value to return if @a ptr found no value - - @tparam ValueType type compatible to JSON values, for instance `int` for - JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for - JSON arrays. Note the type of the expected value at @a key and the default - value @a default_value must be compatible. - - @return copy of the element at key @a key or @a default_value if @a key - is not found - - @throw type_error.302 if @a default_value does not match the type of the - value at @a ptr - @throw type_error.306 if the JSON value is not an object; in that case, - using `value()` with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be queried - with a default value.,basic_json__value_ptr} - - @sa @ref operator[](const json_pointer&) for unchecked access by reference - - @since version 2.0.2 - */ - template::value, int>::type = 0> - ValueType value(const json_pointer& ptr, const ValueType& default_value) const - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - // if pointer resolves a value, return it or use default value - JSON_TRY - { - return ptr.get_checked(this).template get(); - } - JSON_INTERNAL_CATCH (out_of_range&) - { - return default_value; - } - } - - JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); - } - - /*! - @brief overload for a default value of type const char* - @copydoc basic_json::value(const json_pointer&, ValueType) const - */ - JSON_HEDLEY_NON_NULL(3) - string_t value(const json_pointer& ptr, const char* default_value) const - { - return value(ptr, string_t(default_value)); - } - - /*! - @brief access the first element - - Returns a reference to the first element in the container. For a JSON - container `c`, the expression `c.front()` is equivalent to `*c.begin()`. - - @return In case of a structured type (array or object), a reference to the - first element is returned. In case of number, string, boolean, or binary - values, a reference to the value is returned. - - @complexity Constant. - - @pre The JSON value must not be `null` (would throw `std::out_of_range`) - or an empty array or object (undefined behavior, **guarded by - assertions**). - @post The JSON value remains unchanged. - - @throw invalid_iterator.214 when called on `null` value - - @liveexample{The following code shows an example for `front()`.,front} - - @sa @ref back() -- access the last element - - @since version 1.0.0 - */ - reference front() - { - return *begin(); - } - - /*! - @copydoc basic_json::front() - */ - const_reference front() const - { - return *cbegin(); - } - - /*! - @brief access the last element - - Returns a reference to the last element in the container. For a JSON - container `c`, the expression `c.back()` is equivalent to - @code {.cpp} - auto tmp = c.end(); - --tmp; - return *tmp; - @endcode - - @return In case of a structured type (array or object), a reference to the - last element is returned. In case of number, string, boolean, or binary - values, a reference to the value is returned. - - @complexity Constant. - - @pre The JSON value must not be `null` (would throw `std::out_of_range`) - or an empty array or object (undefined behavior, **guarded by - assertions**). - @post The JSON value remains unchanged. - - @throw invalid_iterator.214 when called on a `null` value. See example - below. - - @liveexample{The following code shows an example for `back()`.,back} - - @sa @ref front() -- access the first element - - @since version 1.0.0 - */ - reference back() - { - auto tmp = end(); - --tmp; - return *tmp; - } - - /*! - @copydoc basic_json::back() - */ - const_reference back() const - { - auto tmp = cend(); - --tmp; - return *tmp; - } - - /*! - @brief remove element given an iterator - - Removes the element specified by iterator @a pos. The iterator @a pos must - be valid and dereferenceable. Thus the `end()` iterator (which is valid, - but is not dereferenceable) cannot be used as a value for @a pos. - - If called on a primitive type other than `null`, the resulting JSON value - will be `null`. - - @param[in] pos iterator to the element to remove - @return Iterator following the last removed element. If the iterator @a - pos refers to the last element, the `end()` iterator is returned. - - @tparam IteratorType an @ref iterator or @ref const_iterator - - @post Invalidates iterators and references at or after the point of the - erase, including the `end()` iterator. - - @throw type_error.307 if called on a `null` value; example: `"cannot use - erase() with null"` - @throw invalid_iterator.202 if called on an iterator which does not belong - to the current JSON value; example: `"iterator does not fit current - value"` - @throw invalid_iterator.205 if called on a primitive type with invalid - iterator (i.e., any iterator which is not `begin()`); example: `"iterator - out of range"` - - @complexity The complexity depends on the type: - - objects: amortized constant - - arrays: linear in distance between @a pos and the end of the container - - strings and binary: linear in the length of the member - - other types: constant - - @liveexample{The example shows the result of `erase()` for different JSON - types.,erase__IteratorType} - - @sa @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa @ref erase(const typename object_t::key_type&) -- removes the element - from an object at the given key - @sa @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 1.0.0 - */ - template < class IteratorType, typename std::enable_if < - std::is_same::value || - std::is_same::value, int >::type - = 0 > - IteratorType erase(IteratorType pos) - { - // make sure iterator fits the current value - if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - IteratorType result = end(); - - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - case value_t::binary: - { - if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) - { - JSON_THROW(invalid_iterator::create(205, "iterator out of range")); - } - - if (is_string()) - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.string); - std::allocator_traits::deallocate(alloc, m_value.string, 1); - m_value.string = nullptr; - } - else if (is_binary()) - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.binary); - std::allocator_traits::deallocate(alloc, m_value.binary, 1); - m_value.binary = nullptr; - } - - m_type = value_t::null; - assert_invariant(); - break; - } - - case value_t::object: - { - result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); - break; - } - - case value_t::array: - { - result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); - break; - } - - default: - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); - } - - return result; - } - - /*! - @brief remove elements given an iterator range - - Removes the element specified by the range `[first; last)`. The iterator - @a first does not need to be dereferenceable if `first == last`: erasing - an empty range is a no-op. - - If called on a primitive type other than `null`, the resulting JSON value - will be `null`. - - @param[in] first iterator to the beginning of the range to remove - @param[in] last iterator past the end of the range to remove - @return Iterator following the last removed element. If the iterator @a - second refers to the last element, the `end()` iterator is returned. - - @tparam IteratorType an @ref iterator or @ref const_iterator - - @post Invalidates iterators and references at or after the point of the - erase, including the `end()` iterator. - - @throw type_error.307 if called on a `null` value; example: `"cannot use - erase() with null"` - @throw invalid_iterator.203 if called on iterators which does not belong - to the current JSON value; example: `"iterators do not fit current value"` - @throw invalid_iterator.204 if called on a primitive type with invalid - iterators (i.e., if `first != begin()` and `last != end()`); example: - `"iterators out of range"` - - @complexity The complexity depends on the type: - - objects: `log(size()) + std::distance(first, last)` - - arrays: linear in the distance between @a first and @a last, plus linear - in the distance between @a last and end of the container - - strings and binary: linear in the length of the member - - other types: constant - - @liveexample{The example shows the result of `erase()` for different JSON - types.,erase__IteratorType_IteratorType} - - @sa @ref erase(IteratorType) -- removes the element at a given position - @sa @ref erase(const typename object_t::key_type&) -- removes the element - from an object at the given key - @sa @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 1.0.0 - */ - template < class IteratorType, typename std::enable_if < - std::is_same::value || - std::is_same::value, int >::type - = 0 > - IteratorType erase(IteratorType first, IteratorType last) - { - // make sure iterator fits the current value - if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) - { - JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value")); - } - - IteratorType result = end(); - - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - case value_t::binary: - { - if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin() - || !last.m_it.primitive_iterator.is_end())) - { - JSON_THROW(invalid_iterator::create(204, "iterators out of range")); - } - - if (is_string()) - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.string); - std::allocator_traits::deallocate(alloc, m_value.string, 1); - m_value.string = nullptr; - } - else if (is_binary()) - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.binary); - std::allocator_traits::deallocate(alloc, m_value.binary, 1); - m_value.binary = nullptr; - } - - m_type = value_t::null; - assert_invariant(); - break; - } - - case value_t::object: - { - result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, - last.m_it.object_iterator); - break; - } - - case value_t::array: - { - result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, - last.m_it.array_iterator); - break; - } - - default: - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); - } - - return result; - } - - /*! - @brief remove element from a JSON object given a key - - Removes elements from a JSON object with the key value @a key. - - @param[in] key value of the elements to remove - - @return Number of elements removed. If @a ObjectType is the default - `std::map` type, the return value will always be `0` (@a key was not - found) or `1` (@a key was found). - - @post References and iterators to the erased elements are invalidated. - Other references and iterators are not affected. - - @throw type_error.307 when called on a type other than JSON object; - example: `"cannot use erase() with null"` - - @complexity `log(size()) + count(key)` - - @liveexample{The example shows the effect of `erase()`.,erase__key_type} - - @sa @ref erase(IteratorType) -- removes the element at a given position - @sa @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 1.0.0 - */ - size_type erase(const typename object_t::key_type& key) - { - // this erase only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - return m_value.object->erase(key); - } - - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); - } - - /*! - @brief remove element from a JSON array given an index - - Removes element from a JSON array at the index @a idx. - - @param[in] idx index of the element to remove - - @throw type_error.307 when called on a type other than JSON object; - example: `"cannot use erase() with null"` - @throw out_of_range.401 when `idx >= size()`; example: `"array index 17 - is out of range"` - - @complexity Linear in distance between @a idx and the end of the container. - - @liveexample{The example shows the effect of `erase()`.,erase__size_type} - - @sa @ref erase(IteratorType) -- removes the element at a given position - @sa @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa @ref erase(const typename object_t::key_type&) -- removes the element - from an object at the given key - - @since version 1.0.0 - */ - void erase(const size_type idx) - { - // this erase only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - if (JSON_HEDLEY_UNLIKELY(idx >= size())) - { - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - - m_value.array->erase(m_value.array->begin() + static_cast(idx)); - } - else - { - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); - } - } - - /// @} - - - //////////// - // lookup // - //////////// - - /// @name lookup - /// @{ - - /*! - @brief find an element in a JSON object - - Finds an element in a JSON object with key equivalent to @a key. If the - element is not found or the JSON value is not an object, end() is - returned. - - @note This method always returns @ref end() when executed on a JSON type - that is not an object. - - @param[in] key key value of the element to search for. - - @return Iterator to an element with key equivalent to @a key. If no such - element is found or the JSON value is not an object, past-the-end (see - @ref end()) iterator is returned. - - @complexity Logarithmic in the size of the JSON object. - - @liveexample{The example shows how `find()` is used.,find__key_type} - - @sa @ref contains(KeyT&&) const -- checks whether a key exists - - @since version 1.0.0 - */ - template - iterator find(KeyT&& key) - { - auto result = end(); - - if (is_object()) - { - result.m_it.object_iterator = m_value.object->find(std::forward(key)); - } - - return result; - } - - /*! - @brief find an element in a JSON object - @copydoc find(KeyT&&) - */ - template - const_iterator find(KeyT&& key) const - { - auto result = cend(); - - if (is_object()) - { - result.m_it.object_iterator = m_value.object->find(std::forward(key)); - } - - return result; - } - - /*! - @brief returns the number of occurrences of a key in a JSON object - - Returns the number of elements with key @a key. If ObjectType is the - default `std::map` type, the return value will always be `0` (@a key was - not found) or `1` (@a key was found). - - @note This method always returns `0` when executed on a JSON type that is - not an object. - - @param[in] key key value of the element to count - - @return Number of elements with key @a key. If the JSON value is not an - object, the return value will be `0`. - - @complexity Logarithmic in the size of the JSON object. - - @liveexample{The example shows how `count()` is used.,count} - - @since version 1.0.0 - */ - template - size_type count(KeyT&& key) const - { - // return 0 for all nonobject types - return is_object() ? m_value.object->count(std::forward(key)) : 0; - } - - /*! - @brief check the existence of an element in a JSON object - - Check whether an element exists in a JSON object with key equivalent to - @a key. If the element is not found or the JSON value is not an object, - false is returned. - - @note This method always returns false when executed on a JSON type - that is not an object. - - @param[in] key key value to check its existence. - - @return true if an element with specified @a key exists. If no such - element with such key is found or the JSON value is not an object, - false is returned. - - @complexity Logarithmic in the size of the JSON object. - - @liveexample{The following code shows an example for `contains()`.,contains} - - @sa @ref find(KeyT&&) -- returns an iterator to an object element - @sa @ref contains(const json_pointer&) const -- checks the existence for a JSON pointer - - @since version 3.6.0 - */ - template < typename KeyT, typename std::enable_if < - !std::is_same::type, json_pointer>::value, int >::type = 0 > - bool contains(KeyT && key) const - { - return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end(); - } - - /*! - @brief check the existence of an element in a JSON object given a JSON pointer - - Check whether the given JSON pointer @a ptr can be resolved in the current - JSON value. - - @note This method can be executed on any JSON value type. - - @param[in] ptr JSON pointer to check its existence. - - @return true if the JSON pointer can be resolved to a stored value, false - otherwise. - - @post If `j.contains(ptr)` returns true, it is safe to call `j[ptr]`. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - - @complexity Logarithmic in the size of the JSON object. - - @liveexample{The following code shows an example for `contains()`.,contains_json_pointer} - - @sa @ref contains(KeyT &&) const -- checks the existence of a key - - @since version 3.7.0 - */ - bool contains(const json_pointer& ptr) const - { - return ptr.contains(this); - } - - /// @} - - - /////////////// - // iterators // - /////////////// - - /// @name iterators - /// @{ - - /*! - @brief returns an iterator to the first element - - Returns an iterator to the first element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return iterator to the first element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - @liveexample{The following code shows an example for `begin()`.,begin} - - @sa @ref cbegin() -- returns a const iterator to the beginning - @sa @ref end() -- returns an iterator to the end - @sa @ref cend() -- returns a const iterator to the end - - @since version 1.0.0 - */ - iterator begin() noexcept - { - iterator result(this); - result.set_begin(); - return result; - } - - /*! - @copydoc basic_json::cbegin() - */ - const_iterator begin() const noexcept - { - return cbegin(); - } - - /*! - @brief returns a const iterator to the first element - - Returns a const iterator to the first element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return const iterator to the first element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).begin()`. - - @liveexample{The following code shows an example for `cbegin()`.,cbegin} - - @sa @ref begin() -- returns an iterator to the beginning - @sa @ref end() -- returns an iterator to the end - @sa @ref cend() -- returns a const iterator to the end - - @since version 1.0.0 - */ - const_iterator cbegin() const noexcept - { - const_iterator result(this); - result.set_begin(); - return result; - } - - /*! - @brief returns an iterator to one past the last element - - Returns an iterator to one past the last element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return iterator one past the last element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - @liveexample{The following code shows an example for `end()`.,end} - - @sa @ref cend() -- returns a const iterator to the end - @sa @ref begin() -- returns an iterator to the beginning - @sa @ref cbegin() -- returns a const iterator to the beginning - - @since version 1.0.0 - */ - iterator end() noexcept - { - iterator result(this); - result.set_end(); - return result; - } - - /*! - @copydoc basic_json::cend() - */ - const_iterator end() const noexcept - { - return cend(); - } - - /*! - @brief returns a const iterator to one past the last element - - Returns a const iterator to one past the last element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return const iterator one past the last element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).end()`. - - @liveexample{The following code shows an example for `cend()`.,cend} - - @sa @ref end() -- returns an iterator to the end - @sa @ref begin() -- returns an iterator to the beginning - @sa @ref cbegin() -- returns a const iterator to the beginning - - @since version 1.0.0 - */ - const_iterator cend() const noexcept - { - const_iterator result(this); - result.set_end(); - return result; - } - - /*! - @brief returns an iterator to the reverse-beginning - - Returns an iterator to the reverse-beginning; that is, the last element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `reverse_iterator(end())`. - - @liveexample{The following code shows an example for `rbegin()`.,rbegin} - - @sa @ref crbegin() -- returns a const reverse iterator to the beginning - @sa @ref rend() -- returns a reverse iterator to the end - @sa @ref crend() -- returns a const reverse iterator to the end - - @since version 1.0.0 - */ - reverse_iterator rbegin() noexcept - { - return reverse_iterator(end()); - } - - /*! - @copydoc basic_json::crbegin() - */ - const_reverse_iterator rbegin() const noexcept - { - return crbegin(); - } - - /*! - @brief returns an iterator to the reverse-end - - Returns an iterator to the reverse-end; that is, one before the first - element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `reverse_iterator(begin())`. - - @liveexample{The following code shows an example for `rend()`.,rend} - - @sa @ref crend() -- returns a const reverse iterator to the end - @sa @ref rbegin() -- returns a reverse iterator to the beginning - @sa @ref crbegin() -- returns a const reverse iterator to the beginning - - @since version 1.0.0 - */ - reverse_iterator rend() noexcept - { - return reverse_iterator(begin()); - } - - /*! - @copydoc basic_json::crend() - */ - const_reverse_iterator rend() const noexcept - { - return crend(); - } - - /*! - @brief returns a const reverse iterator to the last element - - Returns a const iterator to the reverse-beginning; that is, the last - element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).rbegin()`. - - @liveexample{The following code shows an example for `crbegin()`.,crbegin} - - @sa @ref rbegin() -- returns a reverse iterator to the beginning - @sa @ref rend() -- returns a reverse iterator to the end - @sa @ref crend() -- returns a const reverse iterator to the end - - @since version 1.0.0 - */ - const_reverse_iterator crbegin() const noexcept - { - return const_reverse_iterator(cend()); - } - - /*! - @brief returns a const reverse iterator to one before the first - - Returns a const reverse iterator to the reverse-end; that is, one before - the first element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).rend()`. - - @liveexample{The following code shows an example for `crend()`.,crend} - - @sa @ref rend() -- returns a reverse iterator to the end - @sa @ref rbegin() -- returns a reverse iterator to the beginning - @sa @ref crbegin() -- returns a const reverse iterator to the beginning - - @since version 1.0.0 - */ - const_reverse_iterator crend() const noexcept - { - return const_reverse_iterator(cbegin()); - } - - public: - /*! - @brief wrapper to access iterator member functions in range-based for - - This function allows to access @ref iterator::key() and @ref - iterator::value() during range-based for loops. In these loops, a - reference to the JSON values is returned, so there is no access to the - underlying iterator. - - For loop without iterator_wrapper: - - @code{cpp} - for (auto it = j_object.begin(); it != j_object.end(); ++it) - { - std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; - } - @endcode - - Range-based for loop without iterator proxy: - - @code{cpp} - for (auto it : j_object) - { - // "it" is of type json::reference and has no key() member - std::cout << "value: " << it << '\n'; - } - @endcode - - Range-based for loop with iterator proxy: - - @code{cpp} - for (auto it : json::iterator_wrapper(j_object)) - { - std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; - } - @endcode - - @note When iterating over an array, `key()` will return the index of the - element as string (see example). - - @param[in] ref reference to a JSON value - @return iteration proxy object wrapping @a ref with an interface to use in - range-based for loops - - @liveexample{The following code shows how the wrapper is used,iterator_wrapper} - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @note The name of this function is not yet final and may change in the - future. - - @deprecated This stream operator is deprecated and will be removed in - future 4.0.0 of the library. Please use @ref items() instead; - that is, replace `json::iterator_wrapper(j)` with `j.items()`. - */ - JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) - static iteration_proxy iterator_wrapper(reference ref) noexcept - { - return ref.items(); - } - - /*! - @copydoc iterator_wrapper(reference) - */ - JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) - static iteration_proxy iterator_wrapper(const_reference ref) noexcept - { - return ref.items(); - } - - /*! - @brief helper to access iterator member functions in range-based for - - This function allows to access @ref iterator::key() and @ref - iterator::value() during range-based for loops. In these loops, a - reference to the JSON values is returned, so there is no access to the - underlying iterator. - - For loop without `items()` function: - - @code{cpp} - for (auto it = j_object.begin(); it != j_object.end(); ++it) - { - std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; - } - @endcode - - Range-based for loop without `items()` function: - - @code{cpp} - for (auto it : j_object) - { - // "it" is of type json::reference and has no key() member - std::cout << "value: " << it << '\n'; - } - @endcode - - Range-based for loop with `items()` function: - - @code{cpp} - for (auto& el : j_object.items()) - { - std::cout << "key: " << el.key() << ", value:" << el.value() << '\n'; - } - @endcode - - The `items()` function also allows to use - [structured bindings](https://en.cppreference.com/w/cpp/language/structured_binding) - (C++17): - - @code{cpp} - for (auto& [key, val] : j_object.items()) - { - std::cout << "key: " << key << ", value:" << val << '\n'; - } - @endcode - - @note When iterating over an array, `key()` will return the index of the - element as string (see example). For primitive types (e.g., numbers), - `key()` returns an empty string. - - @warning Using `items()` on temporary objects is dangerous. Make sure the - object's lifetime exeeds the iteration. See - for more - information. - - @return iteration proxy object wrapping @a ref with an interface to use in - range-based for loops - - @liveexample{The following code shows how the function is used.,items} - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 3.1.0, structured bindings support since 3.5.0. - */ - iteration_proxy items() noexcept - { - return iteration_proxy(*this); - } - - /*! - @copydoc items() - */ - iteration_proxy items() const noexcept - { - return iteration_proxy(*this); - } - - /// @} - - - ////////////// - // capacity // - ////////////// - - /// @name capacity - /// @{ - - /*! - @brief checks whether the container is empty. - - Checks if a JSON value has no elements (i.e. whether its @ref size is `0`). - - @return The return value depends on the different types and is - defined as follows: - Value type | return value - ----------- | ------------- - null | `true` - boolean | `false` - string | `false` - number | `false` - binary | `false` - object | result of function `object_t::empty()` - array | result of function `array_t::empty()` - - @liveexample{The following code uses `empty()` to check if a JSON - object contains any elements.,empty} - - @complexity Constant, as long as @ref array_t and @ref object_t satisfy - the Container concept; that is, their `empty()` functions have constant - complexity. - - @iterators No changes. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @note This function does not return whether a string stored as JSON value - is empty - it returns whether the JSON container itself is empty which is - false in the case of a string. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - Has the semantics of `begin() == end()`. - - @sa @ref size() -- returns the number of elements - - @since version 1.0.0 - */ - bool empty() const noexcept - { - switch (m_type) - { - case value_t::null: - { - // null values are empty - return true; - } - - case value_t::array: - { - // delegate call to array_t::empty() - return m_value.array->empty(); - } - - case value_t::object: - { - // delegate call to object_t::empty() - return m_value.object->empty(); - } - - default: - { - // all other types are nonempty - return false; - } - } - } - - /*! - @brief returns the number of elements - - Returns the number of elements in a JSON value. - - @return The return value depends on the different types and is - defined as follows: - Value type | return value - ----------- | ------------- - null | `0` - boolean | `1` - string | `1` - number | `1` - binary | `1` - object | result of function object_t::size() - array | result of function array_t::size() - - @liveexample{The following code calls `size()` on the different value - types.,size} - - @complexity Constant, as long as @ref array_t and @ref object_t satisfy - the Container concept; that is, their size() functions have constant - complexity. - - @iterators No changes. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @note This function does not return the length of a string stored as JSON - value - it returns the number of elements in the JSON value which is 1 in - the case of a string. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - Has the semantics of `std::distance(begin(), end())`. - - @sa @ref empty() -- checks whether the container is empty - @sa @ref max_size() -- returns the maximal number of elements - - @since version 1.0.0 - */ - size_type size() const noexcept - { - switch (m_type) - { - case value_t::null: - { - // null values are empty - return 0; - } - - case value_t::array: - { - // delegate call to array_t::size() - return m_value.array->size(); - } - - case value_t::object: - { - // delegate call to object_t::size() - return m_value.object->size(); - } - - default: - { - // all other types have size 1 - return 1; - } - } - } - - /*! - @brief returns the maximum possible number of elements - - Returns the maximum number of elements a JSON value is able to hold due to - system or library implementation limitations, i.e. `std::distance(begin(), - end())` for the JSON value. - - @return The return value depends on the different types and is - defined as follows: - Value type | return value - ----------- | ------------- - null | `0` (same as `size()`) - boolean | `1` (same as `size()`) - string | `1` (same as `size()`) - number | `1` (same as `size()`) - binary | `1` (same as `size()`) - object | result of function `object_t::max_size()` - array | result of function `array_t::max_size()` - - @liveexample{The following code calls `max_size()` on the different value - types. Note the output is implementation specific.,max_size} - - @complexity Constant, as long as @ref array_t and @ref object_t satisfy - the Container concept; that is, their `max_size()` functions have constant - complexity. - - @iterators No changes. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - Has the semantics of returning `b.size()` where `b` is the largest - possible JSON value. - - @sa @ref size() -- returns the number of elements - - @since version 1.0.0 - */ - size_type max_size() const noexcept - { - switch (m_type) - { - case value_t::array: - { - // delegate call to array_t::max_size() - return m_value.array->max_size(); - } - - case value_t::object: - { - // delegate call to object_t::max_size() - return m_value.object->max_size(); - } - - default: - { - // all other types have max_size() == size() - return size(); - } - } - } - - /// @} - - - /////////////// - // modifiers // - /////////////// - - /// @name modifiers - /// @{ - - /*! - @brief clears the contents - - Clears the content of a JSON value and resets it to the default value as - if @ref basic_json(value_t) would have been called with the current value - type from @ref type(): - - Value type | initial value - ----------- | ------------- - null | `null` - boolean | `false` - string | `""` - number | `0` - binary | An empty byte vector - object | `{}` - array | `[]` - - @post Has the same effect as calling - @code {.cpp} - *this = basic_json(type()); - @endcode - - @liveexample{The example below shows the effect of `clear()` to different - JSON types.,clear} - - @complexity Linear in the size of the JSON value. - - @iterators All iterators, pointers and references related to this container - are invalidated. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @sa @ref basic_json(value_t) -- constructor that creates an object with the - same value than calling `clear()` - - @since version 1.0.0 - */ - void clear() noexcept - { - switch (m_type) - { - case value_t::number_integer: - { - m_value.number_integer = 0; - break; - } - - case value_t::number_unsigned: - { - m_value.number_unsigned = 0; - break; - } - - case value_t::number_float: - { - m_value.number_float = 0.0; - break; - } - - case value_t::boolean: - { - m_value.boolean = false; - break; - } - - case value_t::string: - { - m_value.string->clear(); - break; - } - - case value_t::binary: - { - m_value.binary->clear(); - break; - } - - case value_t::array: - { - m_value.array->clear(); - break; - } - - case value_t::object: - { - m_value.object->clear(); - break; - } - - default: - break; - } - } - - /*! - @brief add an object to an array - - Appends the given element @a val to the end of the JSON value. If the - function is called on a JSON null value, an empty array is created before - appending @a val. - - @param[in] val the value to add to the JSON array - - @throw type_error.308 when called on a type other than JSON array or - null; example: `"cannot use push_back() with number"` - - @complexity Amortized constant. - - @liveexample{The example shows how `push_back()` and `+=` can be used to - add elements to a JSON array. Note how the `null` value was silently - converted to a JSON array.,push_back} - - @since version 1.0.0 - */ - void push_back(basic_json&& val) - { - // push_back only works for null objects or arrays - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); - } - - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array (move semantics) - m_value.array->push_back(std::move(val)); - // if val is moved from, basic_json move constructor marks it null so we do not call the destructor - } - - /*! - @brief add an object to an array - @copydoc push_back(basic_json&&) - */ - reference operator+=(basic_json&& val) - { - push_back(std::move(val)); - return *this; - } - - /*! - @brief add an object to an array - @copydoc push_back(basic_json&&) - */ - void push_back(const basic_json& val) - { - // push_back only works for null objects or arrays - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); - } - - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array - m_value.array->push_back(val); - } - - /*! - @brief add an object to an array - @copydoc push_back(basic_json&&) - */ - reference operator+=(const basic_json& val) - { - push_back(val); - return *this; - } - - /*! - @brief add an object to an object - - Inserts the given element @a val to the JSON object. If the function is - called on a JSON null value, an empty object is created before inserting - @a val. - - @param[in] val the value to add to the JSON object - - @throw type_error.308 when called on a type other than JSON object or - null; example: `"cannot use push_back() with number"` - - @complexity Logarithmic in the size of the container, O(log(`size()`)). - - @liveexample{The example shows how `push_back()` and `+=` can be used to - add elements to a JSON object. Note how the `null` value was silently - converted to a JSON object.,push_back__object_t__value} - - @since version 1.0.0 - */ - void push_back(const typename object_t::value_type& val) - { - // push_back only works for null objects or objects - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); - } - - // transform null object into an object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); - } - - // add element to array - m_value.object->insert(val); - } - - /*! - @brief add an object to an object - @copydoc push_back(const typename object_t::value_type&) - */ - reference operator+=(const typename object_t::value_type& val) - { - push_back(val); - return *this; - } - - /*! - @brief add an object to an object - - This function allows to use `push_back` with an initializer list. In case - - 1. the current value is an object, - 2. the initializer list @a init contains only two elements, and - 3. the first element of @a init is a string, - - @a init is converted into an object element and added using - @ref push_back(const typename object_t::value_type&). Otherwise, @a init - is converted to a JSON value and added using @ref push_back(basic_json&&). - - @param[in] init an initializer list - - @complexity Linear in the size of the initializer list @a init. - - @note This function is required to resolve an ambiguous overload error, - because pairs like `{"key", "value"}` can be both interpreted as - `object_t::value_type` or `std::initializer_list`, see - https://github.com/nlohmann/json/issues/235 for more information. - - @liveexample{The example shows how initializer lists are treated as - objects when possible.,push_back__initializer_list} - */ - void push_back(initializer_list_t init) - { - if (is_object() && init.size() == 2 && (*init.begin())->is_string()) - { - basic_json&& key = init.begin()->moved_or_copied(); - push_back(typename object_t::value_type( - std::move(key.get_ref()), (init.begin() + 1)->moved_or_copied())); - } - else - { - push_back(basic_json(init)); - } - } - - /*! - @brief add an object to an object - @copydoc push_back(initializer_list_t) - */ - reference operator+=(initializer_list_t init) - { - push_back(init); - return *this; - } - - /*! - @brief add an object to an array - - Creates a JSON value from the passed parameters @a args to the end of the - JSON value. If the function is called on a JSON null value, an empty array - is created before appending the value created from @a args. - - @param[in] args arguments to forward to a constructor of @ref basic_json - @tparam Args compatible types to create a @ref basic_json object - - @return reference to the inserted element - - @throw type_error.311 when called on a type other than JSON array or - null; example: `"cannot use emplace_back() with number"` - - @complexity Amortized constant. - - @liveexample{The example shows how `push_back()` can be used to add - elements to a JSON array. Note how the `null` value was silently converted - to a JSON array.,emplace_back} - - @since version 2.0.8, returns reference since 3.7.0 - */ - template - reference emplace_back(Args&& ... args) - { - // emplace_back only works for null objects or arrays - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) - { - JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()))); - } - - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array (perfect forwarding) -#ifdef JSON_HAS_CPP_17 - return m_value.array->emplace_back(std::forward(args)...); -#else - m_value.array->emplace_back(std::forward(args)...); - return m_value.array->back(); -#endif - } - - /*! - @brief add an object to an object if key does not exist - - Inserts a new element into a JSON object constructed in-place with the - given @a args if there is no element with the key in the container. If the - function is called on a JSON null value, an empty object is created before - appending the value created from @a args. - - @param[in] args arguments to forward to a constructor of @ref basic_json - @tparam Args compatible types to create a @ref basic_json object - - @return a pair consisting of an iterator to the inserted element, or the - already-existing element if no insertion happened, and a bool - denoting whether the insertion took place. - - @throw type_error.311 when called on a type other than JSON object or - null; example: `"cannot use emplace() with number"` - - @complexity Logarithmic in the size of the container, O(log(`size()`)). - - @liveexample{The example shows how `emplace()` can be used to add elements - to a JSON object. Note how the `null` value was silently converted to a - JSON object. Further note how no value is added if there was already one - value stored with the same key.,emplace} - - @since version 2.0.8 - */ - template - std::pair emplace(Args&& ... args) - { - // emplace only works for null objects or arrays - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) - { - JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()))); - } - - // transform null object into an object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); - } - - // add element to array (perfect forwarding) - auto res = m_value.object->emplace(std::forward(args)...); - // create result iterator and set iterator to the result of emplace - auto it = begin(); - it.m_it.object_iterator = res.first; - - // return pair of iterator and boolean - return {it, res.second}; - } - - /// Helper for insertion of an iterator - /// @note: This uses std::distance to support GCC 4.8, - /// see https://github.com/nlohmann/json/pull/1257 - template - iterator insert_iterator(const_iterator pos, Args&& ... args) - { - iterator result(this); - JSON_ASSERT(m_value.array != nullptr); - - auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); - m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); - result.m_it.array_iterator = m_value.array->begin() + insert_pos; - - // This could have been written as: - // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); - // but the return value of insert is missing in GCC 4.8, so it is written this way instead. - - return result; - } - - /*! - @brief inserts element - - Inserts element @a val before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] val element to insert - @return iterator pointing to the inserted @a val. - - @throw type_error.309 if called on JSON values other than arrays; - example: `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - - @complexity Constant plus linear in the distance between @a pos and end of - the container. - - @liveexample{The example shows how `insert()` is used.,insert} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, const basic_json& val) - { - // insert only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - // check if iterator pos fits to this JSON value - if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // insert to array and return iterator - return insert_iterator(pos, val); - } - - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); - } - - /*! - @brief inserts element - @copydoc insert(const_iterator, const basic_json&) - */ - iterator insert(const_iterator pos, basic_json&& val) - { - return insert(pos, val); - } - - /*! - @brief inserts elements - - Inserts @a cnt copies of @a val before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] cnt number of copies of @a val to insert - @param[in] val element to insert - @return iterator pointing to the first element inserted, or @a pos if - `cnt==0` - - @throw type_error.309 if called on JSON values other than arrays; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - - @complexity Linear in @a cnt plus linear in the distance between @a pos - and end of the container. - - @liveexample{The example shows how `insert()` is used.,insert__count} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, size_type cnt, const basic_json& val) - { - // insert only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - // check if iterator pos fits to this JSON value - if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // insert to array and return iterator - return insert_iterator(pos, cnt, val); - } - - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); - } - - /*! - @brief inserts elements - - Inserts elements from range `[first, last)` before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] first begin of the range of elements to insert - @param[in] last end of the range of elements to insert - - @throw type_error.309 if called on JSON values other than arrays; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - @throw invalid_iterator.210 if @a first and @a last do not belong to the - same JSON value; example: `"iterators do not fit"` - @throw invalid_iterator.211 if @a first or @a last are iterators into - container for which insert is called; example: `"passed iterators may not - belong to container"` - - @return iterator pointing to the first element inserted, or @a pos if - `first==last` - - @complexity Linear in `std::distance(first, last)` plus linear in the - distance between @a pos and end of the container. - - @liveexample{The example shows how `insert()` is used.,insert__range} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, const_iterator first, const_iterator last) - { - // insert only works for arrays - if (JSON_HEDLEY_UNLIKELY(!is_array())) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); - } - - // check if iterator pos fits to this JSON value - if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // check if range iterators belong to the same JSON object - if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) - { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); - } - - if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) - { - JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container")); - } - - // insert to array and return iterator - return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); - } - - /*! - @brief inserts elements - - Inserts elements from initializer list @a ilist before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] ilist initializer list to insert the values from - - @throw type_error.309 if called on JSON values other than arrays; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - - @return iterator pointing to the first element inserted, or @a pos if - `ilist` is empty - - @complexity Linear in `ilist.size()` plus linear in the distance between - @a pos and end of the container. - - @liveexample{The example shows how `insert()` is used.,insert__ilist} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, initializer_list_t ilist) - { - // insert only works for arrays - if (JSON_HEDLEY_UNLIKELY(!is_array())) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); - } - - // check if iterator pos fits to this JSON value - if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // insert to array and return iterator - return insert_iterator(pos, ilist.begin(), ilist.end()); - } - - /*! - @brief inserts elements - - Inserts elements from range `[first, last)`. - - @param[in] first begin of the range of elements to insert - @param[in] last end of the range of elements to insert - - @throw type_error.309 if called on JSON values other than objects; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if iterator @a first or @a last does does not - point to an object; example: `"iterators first and last must point to - objects"` - @throw invalid_iterator.210 if @a first and @a last do not belong to the - same JSON value; example: `"iterators do not fit"` - - @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number - of elements to insert. - - @liveexample{The example shows how `insert()` is used.,insert__range_object} - - @since version 3.0.0 - */ - void insert(const_iterator first, const_iterator last) - { - // insert only works for objects - if (JSON_HEDLEY_UNLIKELY(!is_object())) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); - } - - // check if range iterators belong to the same JSON object - if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) - { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); - } - - // passed iterators must belong to objects - if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) - { - JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); - } - - m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); - } - - /*! - @brief updates a JSON object from another object, overwriting existing keys - - Inserts all values from JSON object @a j and overwrites existing keys. - - @param[in] j JSON object to read values from - - @throw type_error.312 if called on JSON values other than objects; example: - `"cannot use update() with string"` - - @complexity O(N*log(size() + N)), where N is the number of elements to - insert. - - @liveexample{The example shows how `update()` is used.,update} - - @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update - - @since version 3.0.0 - */ - void update(const_reference j) - { - // implicitly convert null value to an empty object - if (is_null()) - { - m_type = value_t::object; - m_value.object = create(); - assert_invariant(); - } - - if (JSON_HEDLEY_UNLIKELY(!is_object())) - { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()))); - } - if (JSON_HEDLEY_UNLIKELY(!j.is_object())) - { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name()))); - } - - for (auto it = j.cbegin(); it != j.cend(); ++it) - { - m_value.object->operator[](it.key()) = it.value(); - } - } - - /*! - @brief updates a JSON object from another object, overwriting existing keys - - Inserts all values from from range `[first, last)` and overwrites existing - keys. - - @param[in] first begin of the range of elements to insert - @param[in] last end of the range of elements to insert - - @throw type_error.312 if called on JSON values other than objects; example: - `"cannot use update() with string"` - @throw invalid_iterator.202 if iterator @a first or @a last does does not - point to an object; example: `"iterators first and last must point to - objects"` - @throw invalid_iterator.210 if @a first and @a last do not belong to the - same JSON value; example: `"iterators do not fit"` - - @complexity O(N*log(size() + N)), where N is the number of elements to - insert. - - @liveexample{The example shows how `update()` is used__range.,update} - - @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update - - @since version 3.0.0 - */ - void update(const_iterator first, const_iterator last) - { - // implicitly convert null value to an empty object - if (is_null()) - { - m_type = value_t::object; - m_value.object = create(); - assert_invariant(); - } - - if (JSON_HEDLEY_UNLIKELY(!is_object())) - { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()))); - } - - // check if range iterators belong to the same JSON object - if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) - { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); - } - - // passed iterators must belong to objects - if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object() - || !last.m_object->is_object())) - { - JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); - } - - for (auto it = first; it != last; ++it) - { - m_value.object->operator[](it.key()) = it.value(); - } - } - - /*! - @brief exchanges the values - - Exchanges the contents of the JSON value with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other JSON value to exchange the contents with - - @complexity Constant. - - @liveexample{The example below shows how JSON values can be swapped with - `swap()`.,swap__reference} - - @since version 1.0.0 - */ - void swap(reference other) noexcept ( - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value - ) - { - std::swap(m_type, other.m_type); - std::swap(m_value, other.m_value); - assert_invariant(); - } - - /*! - @brief exchanges the values - - Exchanges the contents of the JSON value from @a left with those of @a right. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. implemented as a friend function callable via ADL. - - @param[in,out] left JSON value to exchange the contents with - @param[in,out] right JSON value to exchange the contents with - - @complexity Constant. - - @liveexample{The example below shows how JSON values can be swapped with - `swap()`.,swap__reference} - - @since version 1.0.0 - */ - friend void swap(reference left, reference right) noexcept ( - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value - ) - { - left.swap(right); - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON array with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other array to exchange the contents with - - @throw type_error.310 when JSON value is not an array; example: `"cannot - use swap() with string"` - - @complexity Constant. - - @liveexample{The example below shows how arrays can be swapped with - `swap()`.,swap__array_t} - - @since version 1.0.0 - */ - void swap(array_t& other) - { - // swap only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - std::swap(*(m_value.array), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); - } - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON object with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other object to exchange the contents with - - @throw type_error.310 when JSON value is not an object; example: - `"cannot use swap() with string"` - - @complexity Constant. - - @liveexample{The example below shows how objects can be swapped with - `swap()`.,swap__object_t} - - @since version 1.0.0 - */ - void swap(object_t& other) - { - // swap only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - std::swap(*(m_value.object), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); - } - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON string with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other string to exchange the contents with - - @throw type_error.310 when JSON value is not a string; example: `"cannot - use swap() with boolean"` - - @complexity Constant. - - @liveexample{The example below shows how strings can be swapped with - `swap()`.,swap__string_t} - - @since version 1.0.0 - */ - void swap(string_t& other) - { - // swap only works for strings - if (JSON_HEDLEY_LIKELY(is_string())) - { - std::swap(*(m_value.string), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); - } - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON string with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other binary to exchange the contents with - - @throw type_error.310 when JSON value is not a string; example: `"cannot - use swap() with boolean"` - - @complexity Constant. - - @liveexample{The example below shows how strings can be swapped with - `swap()`.,swap__binary_t} - - @since version 3.8.0 - */ - void swap(binary_t& other) - { - // swap only works for strings - if (JSON_HEDLEY_LIKELY(is_binary())) - { - std::swap(*(m_value.binary), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); - } - } - - /// @copydoc swap(binary_t) - void swap(typename binary_t::container_type& other) - { - // swap only works for strings - if (JSON_HEDLEY_LIKELY(is_binary())) - { - std::swap(*(m_value.binary), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); - } - } - - /// @} - - public: - ////////////////////////////////////////// - // lexicographical comparison operators // - ////////////////////////////////////////// - - /// @name lexicographical comparison operators - /// @{ - - /*! - @brief comparison: equal - - Compares two JSON values for equality according to the following rules: - - Two JSON values are equal if (1) they are from the same type and (2) - their stored values are the same according to their respective - `operator==`. - - Integer and floating-point numbers are automatically converted before - comparison. Note that two NaN values are always treated as unequal. - - Two JSON null values are equal. - - @note Floating-point inside JSON values numbers are compared with - `json::number_float_t::operator==` which is `double::operator==` by - default. To compare floating-point while respecting an epsilon, an alternative - [comparison function](https://github.com/mariokonrad/marnav/blob/master/include/marnav/math/floatingpoint.hpp#L34-#L39) - could be used, for instance - @code {.cpp} - template::value, T>::type> - inline bool is_same(T a, T b, T epsilon = std::numeric_limits::epsilon()) noexcept - { - return std::abs(a - b) <= epsilon; - } - @endcode - Or you can self-defined operator equal function like this: - @code {.cpp} - bool my_equal(const_reference lhs, const_reference rhs) { - const auto lhs_type lhs.type(); - const auto rhs_type rhs.type(); - if (lhs_type == rhs_type) { - switch(lhs_type) - // self_defined case - case value_t::number_float: - return std::abs(lhs - rhs) <= std::numeric_limits::epsilon(); - // other cases remain the same with the original - ... - } - ... - } - @endcode - - @note NaN values never compare equal to themselves or to other NaN values. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether the values @a lhs and @a rhs are equal - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @complexity Linear. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__equal} - - @since version 1.0.0 - */ - friend bool operator==(const_reference lhs, const_reference rhs) noexcept - { - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); - - if (lhs_type == rhs_type) - { - switch (lhs_type) - { - case value_t::array: - return *lhs.m_value.array == *rhs.m_value.array; - - case value_t::object: - return *lhs.m_value.object == *rhs.m_value.object; - - case value_t::null: - return true; - - case value_t::string: - return *lhs.m_value.string == *rhs.m_value.string; - - case value_t::boolean: - return lhs.m_value.boolean == rhs.m_value.boolean; - - case value_t::number_integer: - return lhs.m_value.number_integer == rhs.m_value.number_integer; - - case value_t::number_unsigned: - return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned; - - case value_t::number_float: - return lhs.m_value.number_float == rhs.m_value.number_float; - - case value_t::binary: - return *lhs.m_value.binary == *rhs.m_value.binary; - - default: - return false; - } - } - else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_integer) == rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) - { - return lhs.m_value.number_float == static_cast(rhs.m_value.number_integer); - } - else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_float == static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) - { - return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_integer; - } - else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_integer == static_cast(rhs.m_value.number_unsigned); - } - - return false; - } - - /*! - @brief comparison: equal - @copydoc operator==(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs == basic_json(rhs); - } - - /*! - @brief comparison: equal - @copydoc operator==(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) == rhs; - } - - /*! - @brief comparison: not equal - - Compares two JSON values for inequality by calculating `not (lhs == rhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether the values @a lhs and @a rhs are not equal - - @complexity Linear. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__notequal} - - @since version 1.0.0 - */ - friend bool operator!=(const_reference lhs, const_reference rhs) noexcept - { - return !(lhs == rhs); - } - - /*! - @brief comparison: not equal - @copydoc operator!=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs != basic_json(rhs); - } - - /*! - @brief comparison: not equal - @copydoc operator!=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) != rhs; - } - - /*! - @brief comparison: less than - - Compares whether one JSON value @a lhs is less than another JSON value @a - rhs according to the following rules: - - If @a lhs and @a rhs have the same type, the values are compared using - the default `<` operator. - - Integer and floating-point numbers are automatically converted before - comparison - - In case @a lhs and @a rhs have different types, the values are ignored - and the order of the types is considered, see - @ref operator<(const value_t, const value_t). - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is less than @a rhs - - @complexity Linear. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__less} - - @since version 1.0.0 - */ - friend bool operator<(const_reference lhs, const_reference rhs) noexcept - { - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); - - if (lhs_type == rhs_type) - { - switch (lhs_type) - { - case value_t::array: - // note parentheses are necessary, see - // https://github.com/nlohmann/json/issues/1530 - return (*lhs.m_value.array) < (*rhs.m_value.array); - - case value_t::object: - return (*lhs.m_value.object) < (*rhs.m_value.object); - - case value_t::null: - return false; - - case value_t::string: - return (*lhs.m_value.string) < (*rhs.m_value.string); - - case value_t::boolean: - return (lhs.m_value.boolean) < (rhs.m_value.boolean); - - case value_t::number_integer: - return (lhs.m_value.number_integer) < (rhs.m_value.number_integer); - - case value_t::number_unsigned: - return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned); - - case value_t::number_float: - return (lhs.m_value.number_float) < (rhs.m_value.number_float); - - case value_t::binary: - return (*lhs.m_value.binary) < (*rhs.m_value.binary); - - default: - return false; - } - } - else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_integer) < rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) - { - return lhs.m_value.number_float < static_cast(rhs.m_value.number_integer); - } - else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_float < static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_integer < static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) - { - return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_integer; - } - - // We only reach this line if we cannot compare values. In that case, - // we compare types. Note we have to call the operator explicitly, - // because MSVC has problems otherwise. - return operator<(lhs_type, rhs_type); - } - - /*! - @brief comparison: less than - @copydoc operator<(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs < basic_json(rhs); - } - - /*! - @brief comparison: less than - @copydoc operator<(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) < rhs; - } - - /*! - @brief comparison: less than or equal - - Compares whether one JSON value @a lhs is less than or equal to another - JSON value by calculating `not (rhs < lhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is less than or equal to @a rhs - - @complexity Linear. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__greater} - - @since version 1.0.0 - */ - friend bool operator<=(const_reference lhs, const_reference rhs) noexcept - { - return !(rhs < lhs); - } - - /*! - @brief comparison: less than or equal - @copydoc operator<=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs <= basic_json(rhs); - } - - /*! - @brief comparison: less than or equal - @copydoc operator<=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) <= rhs; - } - - /*! - @brief comparison: greater than - - Compares whether one JSON value @a lhs is greater than another - JSON value by calculating `not (lhs <= rhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is greater than to @a rhs - - @complexity Linear. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__lessequal} - - @since version 1.0.0 - */ - friend bool operator>(const_reference lhs, const_reference rhs) noexcept - { - return !(lhs <= rhs); - } - - /*! - @brief comparison: greater than - @copydoc operator>(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs > basic_json(rhs); - } - - /*! - @brief comparison: greater than - @copydoc operator>(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) > rhs; - } - - /*! - @brief comparison: greater than or equal - - Compares whether one JSON value @a lhs is greater than or equal to another - JSON value by calculating `not (lhs < rhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is greater than or equal to @a rhs - - @complexity Linear. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__greaterequal} - - @since version 1.0.0 - */ - friend bool operator>=(const_reference lhs, const_reference rhs) noexcept - { - return !(lhs < rhs); - } - - /*! - @brief comparison: greater than or equal - @copydoc operator>=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs >= basic_json(rhs); - } - - /*! - @brief comparison: greater than or equal - @copydoc operator>=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) >= rhs; - } - - /// @} - - /////////////////// - // serialization // - /////////////////// - - /// @name serialization - /// @{ - - /*! - @brief serialize to stream - - Serialize the given JSON value @a j to the output stream @a o. The JSON - value will be serialized using the @ref dump member function. - - - The indentation of the output can be controlled with the member variable - `width` of the output stream @a o. For instance, using the manipulator - `std::setw(4)` on @a o sets the indentation level to `4` and the - serialization result is the same as calling `dump(4)`. - - - The indentation character can be controlled with the member variable - `fill` of the output stream @a o. For instance, the manipulator - `std::setfill('\\t')` sets indentation to use a tab character rather than - the default space character. - - @param[in,out] o stream to serialize to - @param[in] j JSON value to serialize - - @return the stream @a o - - @throw type_error.316 if a string stored inside the JSON value is not - UTF-8 encoded - - @complexity Linear. - - @liveexample{The example below shows the serialization with different - parameters to `width` to adjust the indentation level.,operator_serialize} - - @since version 1.0.0; indentation character added in version 3.0.0 - */ - friend std::ostream& operator<<(std::ostream& o, const basic_json& j) - { - // read width member and use it as indentation parameter if nonzero - const bool pretty_print = o.width() > 0; - const auto indentation = pretty_print ? o.width() : 0; - - // reset width to 0 for subsequent calls to this stream - o.width(0); - - // do the actual serialization - serializer s(detail::output_adapter(o), o.fill()); - s.dump(j, pretty_print, false, static_cast(indentation)); - return o; - } - - /*! - @brief serialize to stream - @deprecated This stream operator is deprecated and will be removed in - future 4.0.0 of the library. Please use - @ref operator<<(std::ostream&, const basic_json&) - instead; that is, replace calls like `j >> o;` with `o << j;`. - @since version 1.0.0; deprecated since version 3.0.0 - */ - JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&)) - friend std::ostream& operator>>(const basic_json& j, std::ostream& o) - { - return o << j; - } - - /// @} - - - ///////////////////// - // deserialization // - ///////////////////// - - /// @name deserialization - /// @{ - - /*! - @brief deserialize from a compatible input - - @tparam InputType A compatible input, for instance - - an std::istream object - - a FILE pointer - - a C-style array of characters - - a pointer to a null-terminated string of single byte characters - - an object obj for which begin(obj) and end(obj) produces a valid pair of - iterators. - - @param[in] i input to read from - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - @param[in] ignore_comments whether comments should be ignored and treated - like whitespace (true) or yield a parse error (true); (optional, false by - default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.101 if a parse error occurs; example: `""unexpected end - of input; expected string literal""` - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the parser callback function - @a cb or reading from the input @a i has a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `parse()` function reading - from an array.,parse__array__parser_callback_t} - - @liveexample{The example below demonstrates the `parse()` function with - and without callback function.,parse__string__parser_callback_t} - - @liveexample{The example below demonstrates the `parse()` function with - and without callback function.,parse__istream__parser_callback_t} - - @liveexample{The example below demonstrates the `parse()` function reading - from a contiguous container.,parse__contiguouscontainer__parser_callback_t} - - @since version 2.0.3 (contiguous containers); version 3.9.0 allowed to - ignore comments. - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json parse(InputType&& i, - const parser_callback_t cb = nullptr, - const bool allow_exceptions = true, - const bool ignore_comments = false) - { - basic_json result; - parser(detail::input_adapter(std::forward(i)), cb, allow_exceptions, ignore_comments).parse(true, result); - return result; - } - - /*! - @brief deserialize from a pair of character iterators - - The value_type of the iterator must be a integral type with size of 1, 2 or - 4 bytes, which will be interpreted respectively as UTF-8, UTF-16 and UTF-32. - - @param[in] first iterator to start of character range - @param[in] last iterator to end of character range - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - @param[in] ignore_comments whether comments should be ignored and treated - like whitespace (true) or yield a parse error (true); (optional, false by - default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.101 if a parse error occurs; example: `""unexpected end - of input; expected string literal""` - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json parse(IteratorType first, - IteratorType last, - const parser_callback_t cb = nullptr, - const bool allow_exceptions = true, - const bool ignore_comments = false) - { - basic_json result; - parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result); - return result; - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) - static basic_json parse(detail::span_input_adapter&& i, - const parser_callback_t cb = nullptr, - const bool allow_exceptions = true, - const bool ignore_comments = false) - { - basic_json result; - parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result); - return result; - } - - /*! - @brief check if the input is valid JSON - - Unlike the @ref parse(InputType&&, const parser_callback_t,const bool) - function, this function neither throws an exception in case of invalid JSON - input (i.e., a parse error) nor creates diagnostic information. - - @tparam InputType A compatible input, for instance - - an std::istream object - - a FILE pointer - - a C-style array of characters - - a pointer to a null-terminated string of single byte characters - - an object obj for which begin(obj) and end(obj) produces a valid pair of - iterators. - - @param[in] i input to read from - @param[in] ignore_comments whether comments should be ignored and treated - like whitespace (true) or yield a parse error (true); (optional, false by - default) - - @return Whether the input read from @a i is valid JSON. - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `accept()` function reading - from a string.,accept__string} - */ - template - static bool accept(InputType&& i, - const bool ignore_comments = false) - { - return parser(detail::input_adapter(std::forward(i)), nullptr, false, ignore_comments).accept(true); - } - - template - static bool accept(IteratorType first, IteratorType last, - const bool ignore_comments = false) - { - return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true); - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len)) - static bool accept(detail::span_input_adapter&& i, - const bool ignore_comments = false) - { - return parser(i.get(), nullptr, false, ignore_comments).accept(true); - } - - /*! - @brief generate SAX events - - The SAX event lister must follow the interface of @ref json_sax. - - This function reads from a compatible input. Examples are: - - an std::istream object - - a FILE pointer - - a C-style array of characters - - a pointer to a null-terminated string of single byte characters - - an object obj for which begin(obj) and end(obj) produces a valid pair of - iterators. - - @param[in] i input to read from - @param[in,out] sax SAX event listener - @param[in] format the format to parse (JSON, CBOR, MessagePack, or UBJSON) - @param[in] strict whether the input has to be consumed completely - @param[in] ignore_comments whether comments should be ignored and treated - like whitespace (true) or yield a parse error (true); (optional, false by - default); only applies to the JSON file format. - - @return return value of the last processed SAX event - - @throw parse_error.101 if a parse error occurs; example: `""unexpected end - of input; expected string literal""` - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the SAX consumer @a sax has - a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `sax_parse()` function - reading from string and processing the events with a user-defined SAX - event consumer.,sax_parse} - - @since version 3.2.0 - */ - template - JSON_HEDLEY_NON_NULL(2) - static bool sax_parse(InputType&& i, SAX* sax, - input_format_t format = input_format_t::json, - const bool strict = true, - const bool ignore_comments = false) - { - auto ia = detail::input_adapter(std::forward(i)); - return format == input_format_t::json - ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) - : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); - } - - template - JSON_HEDLEY_NON_NULL(3) - static bool sax_parse(IteratorType first, IteratorType last, SAX* sax, - input_format_t format = input_format_t::json, - const bool strict = true, - const bool ignore_comments = false) - { - auto ia = detail::input_adapter(std::move(first), std::move(last)); - return format == input_format_t::json - ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) - : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); - } - - template - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) - JSON_HEDLEY_NON_NULL(2) - static bool sax_parse(detail::span_input_adapter&& i, SAX* sax, - input_format_t format = input_format_t::json, - const bool strict = true, - const bool ignore_comments = false) - { - auto ia = i.get(); - return format == input_format_t::json - ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) - : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); - } - - /*! - @brief deserialize from stream - @deprecated This stream operator is deprecated and will be removed in - version 4.0.0 of the library. Please use - @ref operator>>(std::istream&, basic_json&) - instead; that is, replace calls like `j << i;` with `i >> j;`. - @since version 1.0.0; deprecated since version 3.0.0 - */ - JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&)) - friend std::istream& operator<<(basic_json& j, std::istream& i) - { - return operator>>(i, j); - } - - /*! - @brief deserialize from stream - - Deserializes an input stream to a JSON value. - - @param[in,out] i input stream to read a serialized JSON value from - @param[in,out] j JSON value to write the deserialized input to - - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below shows how a JSON value is constructed by - reading a serialization from a stream.,operator_deserialize} - - @sa parse(std::istream&, const parser_callback_t) for a variant with a - parser callback function to filter values while parsing - - @since version 1.0.0 - */ - friend std::istream& operator>>(std::istream& i, basic_json& j) - { - parser(detail::input_adapter(i)).parse(false, j); - return i; - } - - /// @} - - /////////////////////////// - // convenience functions // - /////////////////////////// - - /*! - @brief return the type as string - - Returns the type name as string to be used in error messages - usually to - indicate that a function was called on a wrong JSON type. - - @return a string representation of a the @a m_type member: - Value type | return value - ----------- | ------------- - null | `"null"` - boolean | `"boolean"` - string | `"string"` - number | `"number"` (for all number types) - object | `"object"` - array | `"array"` - binary | `"binary"` - discarded | `"discarded"` - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @complexity Constant. - - @liveexample{The following code exemplifies `type_name()` for all JSON - types.,type_name} - - @sa @ref type() -- return the type of the JSON value - @sa @ref operator value_t() -- return the type of the JSON value (implicit) - - @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept` - since 3.0.0 - */ - JSON_HEDLEY_RETURNS_NON_NULL - const char* type_name() const noexcept - { - { - switch (m_type) - { - case value_t::null: - return "null"; - case value_t::object: - return "object"; - case value_t::array: - return "array"; - case value_t::string: - return "string"; - case value_t::boolean: - return "boolean"; - case value_t::binary: - return "binary"; - case value_t::discarded: - return "discarded"; - default: - return "number"; - } - } - } - - - JSON_PRIVATE_UNLESS_TESTED: - ////////////////////// - // member variables // - ////////////////////// - - /// the type of the current element - value_t m_type = value_t::null; - - /// the value of the current element - json_value m_value = {}; - - ////////////////////////////////////////// - // binary serialization/deserialization // - ////////////////////////////////////////// - - /// @name binary serialization/deserialization support - /// @{ - - public: - /*! - @brief create a CBOR serialization of a given JSON value - - Serializes a given JSON value @a j to a byte vector using the CBOR (Concise - Binary Object Representation) serialization format. CBOR is a binary - serialization format which aims to be more compact than JSON itself, yet - more efficient to parse. - - The library uses the following mapping from JSON values types to - CBOR types according to the CBOR specification (RFC 7049): - - JSON value type | value/range | CBOR type | first byte - --------------- | ------------------------------------------ | ---------------------------------- | --------------- - null | `null` | Null | 0xF6 - boolean | `true` | True | 0xF5 - boolean | `false` | False | 0xF4 - number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3B - number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3A - number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39 - number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38 - number_integer | -24..-1 | Negative integer | 0x20..0x37 - number_integer | 0..23 | Integer | 0x00..0x17 - number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18 - number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 - number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A - number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B - number_unsigned | 0..23 | Integer | 0x00..0x17 - number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18 - number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 - number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A - number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B - number_float | *any value representable by a float* | Single-Precision Float | 0xFA - number_float | *any value NOT representable by a float* | Double-Precision Float | 0xFB - string | *length*: 0..23 | UTF-8 string | 0x60..0x77 - string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78 - string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79 - string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A - string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B - array | *size*: 0..23 | array | 0x80..0x97 - array | *size*: 23..255 | array (1 byte follow) | 0x98 - array | *size*: 256..65535 | array (2 bytes follow) | 0x99 - array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A - array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B - object | *size*: 0..23 | map | 0xA0..0xB7 - object | *size*: 23..255 | map (1 byte follow) | 0xB8 - object | *size*: 256..65535 | map (2 bytes follow) | 0xB9 - object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA - object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB - binary | *size*: 0..23 | byte string | 0x40..0x57 - binary | *size*: 23..255 | byte string (1 byte follow) | 0x58 - binary | *size*: 256..65535 | byte string (2 bytes follow) | 0x59 - binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A - binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B - - @note The mapping is **complete** in the sense that any JSON value type - can be converted to a CBOR value. - - @note If NaN or Infinity are stored inside a JSON number, they are - serialized properly. This behavior differs from the @ref dump() - function which serializes NaN or Infinity to `null`. - - @note The following CBOR types are not used in the conversion: - - UTF-8 strings terminated by "break" (0x7F) - - arrays terminated by "break" (0x9F) - - maps terminated by "break" (0xBF) - - byte strings terminated by "break" (0x5F) - - date/time (0xC0..0xC1) - - bignum (0xC2..0xC3) - - decimal fraction (0xC4) - - bigfloat (0xC5) - - expected conversions (0xD5..0xD7) - - simple values (0xE0..0xF3, 0xF8) - - undefined (0xF7) - - half-precision floats (0xF9) - - break (0xFF) - - @param[in] j JSON value to serialize - @return CBOR serialization as byte vector - - @complexity Linear in the size of the JSON value @a j. - - @liveexample{The example shows the serialization of a JSON value to a byte - vector in CBOR format.,to_cbor} - - @sa http://cbor.io - @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the - analogous deserialization - @sa @ref to_msgpack(const basic_json&) for the related MessagePack format - @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the - related UBJSON format - - @since version 2.0.9; compact representation of floating-point numbers - since version 3.8.0 - */ - static std::vector to_cbor(const basic_json& j) - { - std::vector result; - to_cbor(j, result); - return result; - } - - static void to_cbor(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_cbor(j); - } - - static void to_cbor(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_cbor(j); - } - - /*! - @brief create a MessagePack serialization of a given JSON value - - Serializes a given JSON value @a j to a byte vector using the MessagePack - serialization format. MessagePack is a binary serialization format which - aims to be more compact than JSON itself, yet more efficient to parse. - - The library uses the following mapping from JSON values types to - MessagePack types according to the MessagePack specification: - - JSON value type | value/range | MessagePack type | first byte - --------------- | --------------------------------- | ---------------- | ---------- - null | `null` | nil | 0xC0 - boolean | `true` | true | 0xC3 - boolean | `false` | false | 0xC2 - number_integer | -9223372036854775808..-2147483649 | int64 | 0xD3 - number_integer | -2147483648..-32769 | int32 | 0xD2 - number_integer | -32768..-129 | int16 | 0xD1 - number_integer | -128..-33 | int8 | 0xD0 - number_integer | -32..-1 | negative fixint | 0xE0..0xFF - number_integer | 0..127 | positive fixint | 0x00..0x7F - number_integer | 128..255 | uint 8 | 0xCC - number_integer | 256..65535 | uint 16 | 0xCD - number_integer | 65536..4294967295 | uint 32 | 0xCE - number_integer | 4294967296..18446744073709551615 | uint 64 | 0xCF - number_unsigned | 0..127 | positive fixint | 0x00..0x7F - number_unsigned | 128..255 | uint 8 | 0xCC - number_unsigned | 256..65535 | uint 16 | 0xCD - number_unsigned | 65536..4294967295 | uint 32 | 0xCE - number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF - number_float | *any value representable by a float* | float 32 | 0xCA - number_float | *any value NOT representable by a float* | float 64 | 0xCB - string | *length*: 0..31 | fixstr | 0xA0..0xBF - string | *length*: 32..255 | str 8 | 0xD9 - string | *length*: 256..65535 | str 16 | 0xDA - string | *length*: 65536..4294967295 | str 32 | 0xDB - array | *size*: 0..15 | fixarray | 0x90..0x9F - array | *size*: 16..65535 | array 16 | 0xDC - array | *size*: 65536..4294967295 | array 32 | 0xDD - object | *size*: 0..15 | fix map | 0x80..0x8F - object | *size*: 16..65535 | map 16 | 0xDE - object | *size*: 65536..4294967295 | map 32 | 0xDF - binary | *size*: 0..255 | bin 8 | 0xC4 - binary | *size*: 256..65535 | bin 16 | 0xC5 - binary | *size*: 65536..4294967295 | bin 32 | 0xC6 - - @note The mapping is **complete** in the sense that any JSON value type - can be converted to a MessagePack value. - - @note The following values can **not** be converted to a MessagePack value: - - strings with more than 4294967295 bytes - - byte strings with more than 4294967295 bytes - - arrays with more than 4294967295 elements - - objects with more than 4294967295 elements - - @note Any MessagePack output created @ref to_msgpack can be successfully - parsed by @ref from_msgpack. - - @note If NaN or Infinity are stored inside a JSON number, they are - serialized properly. This behavior differs from the @ref dump() - function which serializes NaN or Infinity to `null`. - - @param[in] j JSON value to serialize - @return MessagePack serialization as byte vector - - @complexity Linear in the size of the JSON value @a j. - - @liveexample{The example shows the serialization of a JSON value to a byte - vector in MessagePack format.,to_msgpack} - - @sa http://msgpack.org - @sa @ref from_msgpack for the analogous deserialization - @sa @ref to_cbor(const basic_json& for the related CBOR format - @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the - related UBJSON format - - @since version 2.0.9 - */ - static std::vector to_msgpack(const basic_json& j) - { - std::vector result; - to_msgpack(j, result); - return result; - } - - static void to_msgpack(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_msgpack(j); - } - - static void to_msgpack(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_msgpack(j); - } - - /*! - @brief create a UBJSON serialization of a given JSON value - - Serializes a given JSON value @a j to a byte vector using the UBJSON - (Universal Binary JSON) serialization format. UBJSON aims to be more compact - than JSON itself, yet more efficient to parse. - - The library uses the following mapping from JSON values types to - UBJSON types according to the UBJSON specification: - - JSON value type | value/range | UBJSON type | marker - --------------- | --------------------------------- | ----------- | ------ - null | `null` | null | `Z` - boolean | `true` | true | `T` - boolean | `false` | false | `F` - number_integer | -9223372036854775808..-2147483649 | int64 | `L` - number_integer | -2147483648..-32769 | int32 | `l` - number_integer | -32768..-129 | int16 | `I` - number_integer | -128..127 | int8 | `i` - number_integer | 128..255 | uint8 | `U` - number_integer | 256..32767 | int16 | `I` - number_integer | 32768..2147483647 | int32 | `l` - number_integer | 2147483648..9223372036854775807 | int64 | `L` - number_unsigned | 0..127 | int8 | `i` - number_unsigned | 128..255 | uint8 | `U` - number_unsigned | 256..32767 | int16 | `I` - number_unsigned | 32768..2147483647 | int32 | `l` - number_unsigned | 2147483648..9223372036854775807 | int64 | `L` - number_unsigned | 2147483649..18446744073709551615 | high-precision | `H` - number_float | *any value* | float64 | `D` - string | *with shortest length indicator* | string | `S` - array | *see notes on optimized format* | array | `[` - object | *see notes on optimized format* | map | `{` - - @note The mapping is **complete** in the sense that any JSON value type - can be converted to a UBJSON value. - - @note The following values can **not** be converted to a UBJSON value: - - strings with more than 9223372036854775807 bytes (theoretical) - - @note The following markers are not used in the conversion: - - `Z`: no-op values are not created. - - `C`: single-byte strings are serialized with `S` markers. - - @note Any UBJSON output created @ref to_ubjson can be successfully parsed - by @ref from_ubjson. - - @note If NaN or Infinity are stored inside a JSON number, they are - serialized properly. This behavior differs from the @ref dump() - function which serializes NaN or Infinity to `null`. - - @note The optimized formats for containers are supported: Parameter - @a use_size adds size information to the beginning of a container and - removes the closing marker. Parameter @a use_type further checks - whether all elements of a container have the same type and adds the - type marker to the beginning of the container. The @a use_type - parameter must only be used together with @a use_size = true. Note - that @a use_size = true alone may result in larger representations - - the benefit of this parameter is that the receiving side is - immediately informed on the number of elements of the container. - - @note If the JSON data contains the binary type, the value stored is a list - of integers, as suggested by the UBJSON documentation. In particular, - this means that serialization and the deserialization of a JSON - containing binary values into UBJSON and back will result in a - different JSON object. - - @param[in] j JSON value to serialize - @param[in] use_size whether to add size annotations to container types - @param[in] use_type whether to add type annotations to container types - (must be combined with @a use_size = true) - @return UBJSON serialization as byte vector - - @complexity Linear in the size of the JSON value @a j. - - @liveexample{The example shows the serialization of a JSON value to a byte - vector in UBJSON format.,to_ubjson} - - @sa http://ubjson.org - @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the - analogous deserialization - @sa @ref to_cbor(const basic_json& for the related CBOR format - @sa @ref to_msgpack(const basic_json&) for the related MessagePack format - - @since version 3.1.0 - */ - static std::vector to_ubjson(const basic_json& j, - const bool use_size = false, - const bool use_type = false) - { - std::vector result; - to_ubjson(j, result, use_size, use_type); - return result; - } - - static void to_ubjson(const basic_json& j, detail::output_adapter o, - const bool use_size = false, const bool use_type = false) - { - binary_writer(o).write_ubjson(j, use_size, use_type); - } - - static void to_ubjson(const basic_json& j, detail::output_adapter o, - const bool use_size = false, const bool use_type = false) - { - binary_writer(o).write_ubjson(j, use_size, use_type); - } - - - /*! - @brief Serializes the given JSON object `j` to BSON and returns a vector - containing the corresponding BSON-representation. - - BSON (Binary JSON) is a binary format in which zero or more ordered key/value pairs are - stored as a single entity (a so-called document). - - The library uses the following mapping from JSON values types to BSON types: - - JSON value type | value/range | BSON type | marker - --------------- | --------------------------------- | ----------- | ------ - null | `null` | null | 0x0A - boolean | `true`, `false` | boolean | 0x08 - number_integer | -9223372036854775808..-2147483649 | int64 | 0x12 - number_integer | -2147483648..2147483647 | int32 | 0x10 - number_integer | 2147483648..9223372036854775807 | int64 | 0x12 - number_unsigned | 0..2147483647 | int32 | 0x10 - number_unsigned | 2147483648..9223372036854775807 | int64 | 0x12 - number_unsigned | 9223372036854775808..18446744073709551615| -- | -- - number_float | *any value* | double | 0x01 - string | *any value* | string | 0x02 - array | *any value* | document | 0x04 - object | *any value* | document | 0x03 - binary | *any value* | binary | 0x05 - - @warning The mapping is **incomplete**, since only JSON-objects (and things - contained therein) can be serialized to BSON. - Also, integers larger than 9223372036854775807 cannot be serialized to BSON, - and the keys may not contain U+0000, since they are serialized a - zero-terminated c-strings. - - @throw out_of_range.407 if `j.is_number_unsigned() && j.get() > 9223372036854775807` - @throw out_of_range.409 if a key in `j` contains a NULL (U+0000) - @throw type_error.317 if `!j.is_object()` - - @pre The input `j` is required to be an object: `j.is_object() == true`. - - @note Any BSON output created via @ref to_bson can be successfully parsed - by @ref from_bson. - - @param[in] j JSON value to serialize - @return BSON serialization as byte vector - - @complexity Linear in the size of the JSON value @a j. - - @liveexample{The example shows the serialization of a JSON value to a byte - vector in BSON format.,to_bson} - - @sa http://bsonspec.org/spec.html - @sa @ref from_bson(detail::input_adapter&&, const bool strict) for the - analogous deserialization - @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the - related UBJSON format - @sa @ref to_cbor(const basic_json&) for the related CBOR format - @sa @ref to_msgpack(const basic_json&) for the related MessagePack format - */ - static std::vector to_bson(const basic_json& j) - { - std::vector result; - to_bson(j, result); - return result; - } - - /*! - @brief Serializes the given JSON object `j` to BSON and forwards the - corresponding BSON-representation to the given output_adapter `o`. - @param j The JSON object to convert to BSON. - @param o The output adapter that receives the binary BSON representation. - @pre The input `j` shall be an object: `j.is_object() == true` - @sa @ref to_bson(const basic_json&) - */ - static void to_bson(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_bson(j); - } - - /*! - @copydoc to_bson(const basic_json&, detail::output_adapter) - */ - static void to_bson(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_bson(j); - } - - - /*! - @brief create a JSON value from an input in CBOR format - - Deserializes a given input @a i to a JSON value using the CBOR (Concise - Binary Object Representation) serialization format. - - The library maps CBOR types to JSON value types as follows: - - CBOR type | JSON value type | first byte - ---------------------- | --------------- | ---------- - Integer | number_unsigned | 0x00..0x17 - Unsigned integer | number_unsigned | 0x18 - Unsigned integer | number_unsigned | 0x19 - Unsigned integer | number_unsigned | 0x1A - Unsigned integer | number_unsigned | 0x1B - Negative integer | number_integer | 0x20..0x37 - Negative integer | number_integer | 0x38 - Negative integer | number_integer | 0x39 - Negative integer | number_integer | 0x3A - Negative integer | number_integer | 0x3B - Byte string | binary | 0x40..0x57 - Byte string | binary | 0x58 - Byte string | binary | 0x59 - Byte string | binary | 0x5A - Byte string | binary | 0x5B - UTF-8 string | string | 0x60..0x77 - UTF-8 string | string | 0x78 - UTF-8 string | string | 0x79 - UTF-8 string | string | 0x7A - UTF-8 string | string | 0x7B - UTF-8 string | string | 0x7F - array | array | 0x80..0x97 - array | array | 0x98 - array | array | 0x99 - array | array | 0x9A - array | array | 0x9B - array | array | 0x9F - map | object | 0xA0..0xB7 - map | object | 0xB8 - map | object | 0xB9 - map | object | 0xBA - map | object | 0xBB - map | object | 0xBF - False | `false` | 0xF4 - True | `true` | 0xF5 - Null | `null` | 0xF6 - Half-Precision Float | number_float | 0xF9 - Single-Precision Float | number_float | 0xFA - Double-Precision Float | number_float | 0xFB - - @warning The mapping is **incomplete** in the sense that not all CBOR - types can be converted to a JSON value. The following CBOR types - are not supported and will yield parse errors (parse_error.112): - - date/time (0xC0..0xC1) - - bignum (0xC2..0xC3) - - decimal fraction (0xC4) - - bigfloat (0xC5) - - expected conversions (0xD5..0xD7) - - simple values (0xE0..0xF3, 0xF8) - - undefined (0xF7) - - @warning CBOR allows map keys of any type, whereas JSON only allows - strings as keys in object values. Therefore, CBOR maps with keys - other than UTF-8 strings are rejected (parse_error.113). - - @note Any CBOR output created @ref to_cbor can be successfully parsed by - @ref from_cbor. - - @param[in] i an input in CBOR format convertible to an input adapter - @param[in] strict whether to expect the input to be consumed until EOF - (true by default) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - @param[in] tag_handler how to treat CBOR tags (optional, error by default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.110 if the given input ends prematurely or the end of - file was not reached when @a strict was set to true - @throw parse_error.112 if unsupported features from CBOR were - used in the given input @a v or if the input is not valid CBOR - @throw parse_error.113 if a string was expected as map key, but not found - - @complexity Linear in the size of the input @a i. - - @liveexample{The example shows the deserialization of a byte vector in CBOR - format to a JSON value.,from_cbor} - - @sa http://cbor.io - @sa @ref to_cbor(const basic_json&) for the analogous serialization - @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for the - related MessagePack format - @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the - related UBJSON format - - @since version 2.0.9; parameter @a start_index since 2.1.1; changed to - consume input adapters, removed start_index parameter, and added - @a strict parameter since 3.0.0; added @a allow_exceptions parameter - since 3.2.0; added @a tag_handler parameter since 3.9.0. - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_cbor(InputType&& i, - const bool strict = true, - const bool allow_exceptions = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); - return res ? result : basic_json(value_t::discarded); - } - - /*! - @copydoc from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_cbor(IteratorType first, IteratorType last, - const bool strict = true, - const bool allow_exceptions = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); - return res ? result : basic_json(value_t::discarded); - } - - template - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) - static basic_json from_cbor(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); - } - - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) - static basic_json from_cbor(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); - return res ? result : basic_json(value_t::discarded); - } - - /*! - @brief create a JSON value from an input in MessagePack format - - Deserializes a given input @a i to a JSON value using the MessagePack - serialization format. - - The library maps MessagePack types to JSON value types as follows: - - MessagePack type | JSON value type | first byte - ---------------- | --------------- | ---------- - positive fixint | number_unsigned | 0x00..0x7F - fixmap | object | 0x80..0x8F - fixarray | array | 0x90..0x9F - fixstr | string | 0xA0..0xBF - nil | `null` | 0xC0 - false | `false` | 0xC2 - true | `true` | 0xC3 - float 32 | number_float | 0xCA - float 64 | number_float | 0xCB - uint 8 | number_unsigned | 0xCC - uint 16 | number_unsigned | 0xCD - uint 32 | number_unsigned | 0xCE - uint 64 | number_unsigned | 0xCF - int 8 | number_integer | 0xD0 - int 16 | number_integer | 0xD1 - int 32 | number_integer | 0xD2 - int 64 | number_integer | 0xD3 - str 8 | string | 0xD9 - str 16 | string | 0xDA - str 32 | string | 0xDB - array 16 | array | 0xDC - array 32 | array | 0xDD - map 16 | object | 0xDE - map 32 | object | 0xDF - bin 8 | binary | 0xC4 - bin 16 | binary | 0xC5 - bin 32 | binary | 0xC6 - ext 8 | binary | 0xC7 - ext 16 | binary | 0xC8 - ext 32 | binary | 0xC9 - fixext 1 | binary | 0xD4 - fixext 2 | binary | 0xD5 - fixext 4 | binary | 0xD6 - fixext 8 | binary | 0xD7 - fixext 16 | binary | 0xD8 - negative fixint | number_integer | 0xE0-0xFF - - @note Any MessagePack output created @ref to_msgpack can be successfully - parsed by @ref from_msgpack. - - @param[in] i an input in MessagePack format convertible to an input - adapter - @param[in] strict whether to expect the input to be consumed until EOF - (true by default) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.110 if the given input ends prematurely or the end of - file was not reached when @a strict was set to true - @throw parse_error.112 if unsupported features from MessagePack were - used in the given input @a i or if the input is not valid MessagePack - @throw parse_error.113 if a string was expected as map key, but not found - - @complexity Linear in the size of the input @a i. - - @liveexample{The example shows the deserialization of a byte vector in - MessagePack format to a JSON value.,from_msgpack} - - @sa http://msgpack.org - @sa @ref to_msgpack(const basic_json&) for the analogous serialization - @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the - related CBOR format - @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for - the related UBJSON format - @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for - the related BSON format - - @since version 2.0.9; parameter @a start_index since 2.1.1; changed to - consume input adapters, removed start_index parameter, and added - @a strict parameter since 3.0.0; added @a allow_exceptions parameter - since 3.2.0 - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_msgpack(InputType&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - /*! - @copydoc from_msgpack(detail::input_adapter&&, const bool, const bool) - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_msgpack(IteratorType first, IteratorType last, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - - template - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) - static basic_json from_msgpack(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true) - { - return from_msgpack(ptr, ptr + len, strict, allow_exceptions); - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) - static basic_json from_msgpack(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - - /*! - @brief create a JSON value from an input in UBJSON format - - Deserializes a given input @a i to a JSON value using the UBJSON (Universal - Binary JSON) serialization format. - - The library maps UBJSON types to JSON value types as follows: - - UBJSON type | JSON value type | marker - ----------- | --------------------------------------- | ------ - no-op | *no value, next value is read* | `N` - null | `null` | `Z` - false | `false` | `F` - true | `true` | `T` - float32 | number_float | `d` - float64 | number_float | `D` - uint8 | number_unsigned | `U` - int8 | number_integer | `i` - int16 | number_integer | `I` - int32 | number_integer | `l` - int64 | number_integer | `L` - high-precision number | number_integer, number_unsigned, or number_float - depends on number string | 'H' - string | string | `S` - char | string | `C` - array | array (optimized values are supported) | `[` - object | object (optimized values are supported) | `{` - - @note The mapping is **complete** in the sense that any UBJSON value can - be converted to a JSON value. - - @param[in] i an input in UBJSON format convertible to an input adapter - @param[in] strict whether to expect the input to be consumed until EOF - (true by default) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.110 if the given input ends prematurely or the end of - file was not reached when @a strict was set to true - @throw parse_error.112 if a parse error occurs - @throw parse_error.113 if a string could not be parsed successfully - - @complexity Linear in the size of the input @a i. - - @liveexample{The example shows the deserialization of a byte vector in - UBJSON format to a JSON value.,from_ubjson} - - @sa http://ubjson.org - @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the - analogous serialization - @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the - related CBOR format - @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for - the related MessagePack format - @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for - the related BSON format - - @since version 3.1.0; added @a allow_exceptions parameter since 3.2.0 - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_ubjson(InputType&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - /*! - @copydoc from_ubjson(detail::input_adapter&&, const bool, const bool) - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_ubjson(IteratorType first, IteratorType last, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - template - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) - static basic_json from_ubjson(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true) - { - return from_ubjson(ptr, ptr + len, strict, allow_exceptions); - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) - static basic_json from_ubjson(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - - /*! - @brief Create a JSON value from an input in BSON format - - Deserializes a given input @a i to a JSON value using the BSON (Binary JSON) - serialization format. - - The library maps BSON record types to JSON value types as follows: - - BSON type | BSON marker byte | JSON value type - --------------- | ---------------- | --------------------------- - double | 0x01 | number_float - string | 0x02 | string - document | 0x03 | object - array | 0x04 | array - binary | 0x05 | binary - undefined | 0x06 | still unsupported - ObjectId | 0x07 | still unsupported - boolean | 0x08 | boolean - UTC Date-Time | 0x09 | still unsupported - null | 0x0A | null - Regular Expr. | 0x0B | still unsupported - DB Pointer | 0x0C | still unsupported - JavaScript Code | 0x0D | still unsupported - Symbol | 0x0E | still unsupported - JavaScript Code | 0x0F | still unsupported - int32 | 0x10 | number_integer - Timestamp | 0x11 | still unsupported - 128-bit decimal float | 0x13 | still unsupported - Max Key | 0x7F | still unsupported - Min Key | 0xFF | still unsupported - - @warning The mapping is **incomplete**. The unsupported mappings - are indicated in the table above. - - @param[in] i an input in BSON format convertible to an input adapter - @param[in] strict whether to expect the input to be consumed until EOF - (true by default) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.114 if an unsupported BSON record type is encountered - - @complexity Linear in the size of the input @a i. - - @liveexample{The example shows the deserialization of a byte vector in - BSON format to a JSON value.,from_bson} - - @sa http://bsonspec.org/spec.html - @sa @ref to_bson(const basic_json&) for the analogous serialization - @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the - related CBOR format - @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for - the related MessagePack format - @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the - related UBJSON format - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_bson(InputType&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - /*! - @copydoc from_bson(detail::input_adapter&&, const bool, const bool) - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_bson(IteratorType first, IteratorType last, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - template - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) - static basic_json from_bson(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true) - { - return from_bson(ptr, ptr + len, strict, allow_exceptions); - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) - static basic_json from_bson(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - /// @} - - ////////////////////////// - // JSON Pointer support // - ////////////////////////// - - /// @name JSON Pointer functions - /// @{ - - /*! - @brief access specified element via JSON Pointer - - Uses a JSON pointer to retrieve a reference to the respective JSON value. - No bound checking is performed. Similar to @ref operator[](const typename - object_t::key_type&), `null` values are created in arrays and objects if - necessary. - - In particular: - - If the JSON pointer points to an object key that does not exist, it - is created an filled with a `null` value before a reference to it - is returned. - - If the JSON pointer points to an array index that does not exist, it - is created an filled with a `null` value before a reference to it - is returned. All indices between the current maximum and the given - index are also filled with `null`. - - The special value `-` is treated as a synonym for the index past the - end. - - @param[in] ptr a JSON pointer - - @return reference to the element pointed to by @a ptr - - @complexity Constant. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.404 if the JSON pointer can not be resolved - - @liveexample{The behavior is shown in the example.,operatorjson_pointer} - - @since version 2.0.0 - */ - reference operator[](const json_pointer& ptr) - { - return ptr.get_unchecked(this); - } - - /*! - @brief access specified element via JSON Pointer - - Uses a JSON pointer to retrieve a reference to the respective JSON value. - No bound checking is performed. The function does not change the JSON - value; no `null` values are created. In particular, the special value - `-` yields an exception. - - @param[in] ptr JSON pointer to the desired element - - @return const reference to the element pointed to by @a ptr - - @complexity Constant. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - - @liveexample{The behavior is shown in the example.,operatorjson_pointer_const} - - @since version 2.0.0 - */ - const_reference operator[](const json_pointer& ptr) const - { - return ptr.get_unchecked(this); - } - - /*! - @brief access specified element via JSON Pointer - - Returns a reference to the element at with specified JSON pointer @a ptr, - with bounds checking. - - @param[in] ptr JSON pointer to the desired element - - @return reference to the element pointed to by @a ptr - - @throw parse_error.106 if an array index in the passed JSON pointer @a ptr - begins with '0'. See example below. - - @throw parse_error.109 if an array index in the passed JSON pointer @a ptr - is not a number. See example below. - - @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr - is out of range. See example below. - - @throw out_of_range.402 if the array index '-' is used in the passed JSON - pointer @a ptr. As `at` provides checked access (and no elements are - implicitly inserted), the index '-' is always invalid. See example below. - - @throw out_of_range.403 if the JSON pointer describes a key of an object - which cannot be found. See example below. - - @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. - See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 2.0.0 - - @liveexample{The behavior is shown in the example.,at_json_pointer} - */ - reference at(const json_pointer& ptr) - { - return ptr.get_checked(this); - } - - /*! - @brief access specified element via JSON Pointer - - Returns a const reference to the element at with specified JSON pointer @a - ptr, with bounds checking. - - @param[in] ptr JSON pointer to the desired element - - @return reference to the element pointed to by @a ptr - - @throw parse_error.106 if an array index in the passed JSON pointer @a ptr - begins with '0'. See example below. - - @throw parse_error.109 if an array index in the passed JSON pointer @a ptr - is not a number. See example below. - - @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr - is out of range. See example below. - - @throw out_of_range.402 if the array index '-' is used in the passed JSON - pointer @a ptr. As `at` provides checked access (and no elements are - implicitly inserted), the index '-' is always invalid. See example below. - - @throw out_of_range.403 if the JSON pointer describes a key of an object - which cannot be found. See example below. - - @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. - See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 2.0.0 - - @liveexample{The behavior is shown in the example.,at_json_pointer_const} - */ - const_reference at(const json_pointer& ptr) const - { - return ptr.get_checked(this); - } - - /*! - @brief return flattened JSON value - - The function creates a JSON object whose keys are JSON pointers (see [RFC - 6901](https://tools.ietf.org/html/rfc6901)) and whose values are all - primitive. The original JSON value can be restored using the @ref - unflatten() function. - - @return an object that maps JSON pointers to primitive values - - @note Empty objects and arrays are flattened to `null` and will not be - reconstructed correctly by the @ref unflatten() function. - - @complexity Linear in the size the JSON value. - - @liveexample{The following code shows how a JSON object is flattened to an - object whose keys consist of JSON pointers.,flatten} - - @sa @ref unflatten() for the reverse function - - @since version 2.0.0 - */ - basic_json flatten() const - { - basic_json result(value_t::object); - json_pointer::flatten("", *this, result); - return result; - } - - /*! - @brief unflatten a previously flattened JSON value - - The function restores the arbitrary nesting of a JSON value that has been - flattened before using the @ref flatten() function. The JSON value must - meet certain constraints: - 1. The value must be an object. - 2. The keys must be JSON pointers (see - [RFC 6901](https://tools.ietf.org/html/rfc6901)) - 3. The mapped values must be primitive JSON types. - - @return the original JSON from a flattened version - - @note Empty objects and arrays are flattened by @ref flatten() to `null` - values and can not unflattened to their original type. Apart from - this example, for a JSON value `j`, the following is always true: - `j == j.flatten().unflatten()`. - - @complexity Linear in the size the JSON value. - - @throw type_error.314 if value is not an object - @throw type_error.315 if object values are not primitive - - @liveexample{The following code shows how a flattened JSON object is - unflattened into the original nested JSON object.,unflatten} - - @sa @ref flatten() for the reverse function - - @since version 2.0.0 - */ - basic_json unflatten() const - { - return json_pointer::unflatten(*this); - } - - /// @} - - ////////////////////////// - // JSON Patch functions // - ////////////////////////// - - /// @name JSON Patch functions - /// @{ - - /*! - @brief applies a JSON patch - - [JSON Patch](http://jsonpatch.com) defines a JSON document structure for - expressing a sequence of operations to apply to a JSON) document. With - this function, a JSON Patch is applied to the current JSON value by - executing all operations from the patch. - - @param[in] json_patch JSON patch document - @return patched document - - @note The application of a patch is atomic: Either all operations succeed - and the patched document is returned or an exception is thrown. In - any case, the original value is not changed: the patch is applied - to a copy of the value. - - @throw parse_error.104 if the JSON patch does not consist of an array of - objects - - @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory - attributes are missing); example: `"operation add must have member path"` - - @throw out_of_range.401 if an array index is out of range. - - @throw out_of_range.403 if a JSON pointer inside the patch could not be - resolved successfully in the current JSON value; example: `"key baz not - found"` - - @throw out_of_range.405 if JSON pointer has no parent ("add", "remove", - "move") - - @throw other_error.501 if "test" operation was unsuccessful - - @complexity Linear in the size of the JSON value and the length of the - JSON patch. As usually only a fraction of the JSON value is affected by - the patch, the complexity can usually be neglected. - - @liveexample{The following code shows how a JSON patch is applied to a - value.,patch} - - @sa @ref diff -- create a JSON patch by comparing two JSON values - - @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) - @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901) - - @since version 2.0.0 - */ - basic_json patch(const basic_json& json_patch) const - { - // make a working copy to apply the patch to - basic_json result = *this; - - // the valid JSON Patch operations - enum class patch_operations {add, remove, replace, move, copy, test, invalid}; - - const auto get_op = [](const std::string & op) - { - if (op == "add") - { - return patch_operations::add; - } - if (op == "remove") - { - return patch_operations::remove; - } - if (op == "replace") - { - return patch_operations::replace; - } - if (op == "move") - { - return patch_operations::move; - } - if (op == "copy") - { - return patch_operations::copy; - } - if (op == "test") - { - return patch_operations::test; - } - - return patch_operations::invalid; - }; - - // wrapper for "add" operation; add value at ptr - const auto operation_add = [&result](json_pointer & ptr, basic_json val) - { - // adding to the root of the target document means replacing it - if (ptr.empty()) - { - result = val; - return; - } - - // make sure the top element of the pointer exists - json_pointer top_pointer = ptr.top(); - if (top_pointer != ptr) - { - result.at(top_pointer); - } - - // get reference to parent of JSON pointer ptr - const auto last_path = ptr.back(); - ptr.pop_back(); - basic_json& parent = result[ptr]; - - switch (parent.m_type) - { - case value_t::null: - case value_t::object: - { - // use operator[] to add value - parent[last_path] = val; - break; - } - - case value_t::array: - { - if (last_path == "-") - { - // special case: append to back - parent.push_back(val); - } - else - { - const auto idx = json_pointer::array_index(last_path); - if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) - { - // avoid undefined behavior - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - - // default case: insert add offset - parent.insert(parent.begin() + static_cast(idx), val); - } - break; - } - - // if there exists a parent it cannot be primitive - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - }; - - // wrapper for "remove" operation; remove value at ptr - const auto operation_remove = [&result](json_pointer & ptr) - { - // get reference to parent of JSON pointer ptr - const auto last_path = ptr.back(); - ptr.pop_back(); - basic_json& parent = result.at(ptr); - - // remove child - if (parent.is_object()) - { - // perform range check - auto it = parent.find(last_path); - if (JSON_HEDLEY_LIKELY(it != parent.end())) - { - parent.erase(it); - } - else - { - JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found")); - } - } - else if (parent.is_array()) - { - // note erase performs range check - parent.erase(json_pointer::array_index(last_path)); - } - }; - - // type check: top level value must be an array - if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) - { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); - } - - // iterate and apply the operations - for (const auto& val : json_patch) - { - // wrapper to get a value for an operation - const auto get_value = [&val](const std::string & op, - const std::string & member, - bool string_type) -> basic_json & - { - // find value - auto it = val.m_value.object->find(member); - - // context-sensitive error message - const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'"; - - // check if desired value is present - if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) - { - JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'")); - } - - // check if result is of type string - if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) - { - JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'")); - } - - // no error: return value - return it->second; - }; - - // type check: every element of the array must be an object - if (JSON_HEDLEY_UNLIKELY(!val.is_object())) - { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); - } - - // collect mandatory members - const auto op = get_value("op", "op", true).template get(); - const auto path = get_value(op, "path", true).template get(); - json_pointer ptr(path); - - switch (get_op(op)) - { - case patch_operations::add: - { - operation_add(ptr, get_value("add", "value", false)); - break; - } - - case patch_operations::remove: - { - operation_remove(ptr); - break; - } - - case patch_operations::replace: - { - // the "path" location must exist - use at() - result.at(ptr) = get_value("replace", "value", false); - break; - } - - case patch_operations::move: - { - const auto from_path = get_value("move", "from", true).template get(); - json_pointer from_ptr(from_path); - - // the "from" location must exist - use at() - basic_json v = result.at(from_ptr); - - // The move operation is functionally identical to a - // "remove" operation on the "from" location, followed - // immediately by an "add" operation at the target - // location with the value that was just removed. - operation_remove(from_ptr); - operation_add(ptr, v); - break; - } - - case patch_operations::copy: - { - const auto from_path = get_value("copy", "from", true).template get(); - const json_pointer from_ptr(from_path); - - // the "from" location must exist - use at() - basic_json v = result.at(from_ptr); - - // The copy is functionally identical to an "add" - // operation at the target location using the value - // specified in the "from" member. - operation_add(ptr, v); - break; - } - - case patch_operations::test: - { - bool success = false; - JSON_TRY - { - // check if "value" matches the one at "path" - // the "path" location must exist - use at() - success = (result.at(ptr) == get_value("test", "value", false)); - } - JSON_INTERNAL_CATCH (out_of_range&) - { - // ignore out of range errors: success remains false - } - - // throw an exception if test fails - if (JSON_HEDLEY_UNLIKELY(!success)) - { - JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump())); - } - - break; - } - - default: - { - // op must be "add", "remove", "replace", "move", "copy", or - // "test" - JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid")); - } - } - } - - return result; - } - - /*! - @brief creates a diff as a JSON patch - - Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can - be changed into the value @a target by calling @ref patch function. - - @invariant For two JSON values @a source and @a target, the following code - yields always `true`: - @code {.cpp} - source.patch(diff(source, target)) == target; - @endcode - - @note Currently, only `remove`, `add`, and `replace` operations are - generated. - - @param[in] source JSON value to compare from - @param[in] target JSON value to compare against - @param[in] path helper value to create JSON pointers - - @return a JSON patch to convert the @a source to @a target - - @complexity Linear in the lengths of @a source and @a target. - - @liveexample{The following code shows how a JSON patch is created as a - diff for two JSON values.,diff} - - @sa @ref patch -- apply a JSON patch - @sa @ref merge_patch -- apply a JSON Merge Patch - - @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) - - @since version 2.0.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json diff(const basic_json& source, const basic_json& target, - const std::string& path = "") - { - // the patch - basic_json result(value_t::array); - - // if the values are the same, return empty patch - if (source == target) - { - return result; - } - - if (source.type() != target.type()) - { - // different types: replace value - result.push_back( - { - {"op", "replace"}, {"path", path}, {"value", target} - }); - return result; - } - - switch (source.type()) - { - case value_t::array: - { - // first pass: traverse common elements - std::size_t i = 0; - while (i < source.size() && i < target.size()) - { - // recursive call to compare array values at index i - auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i)); - result.insert(result.end(), temp_diff.begin(), temp_diff.end()); - ++i; - } - - // i now reached the end of at least one array - // in a second pass, traverse the remaining elements - - // remove my remaining elements - const auto end_index = static_cast(result.size()); - while (i < source.size()) - { - // add operations in reverse order to avoid invalid - // indices - result.insert(result.begin() + end_index, object( - { - {"op", "remove"}, - {"path", path + "/" + std::to_string(i)} - })); - ++i; - } - - // add other remaining elements - while (i < target.size()) - { - result.push_back( - { - {"op", "add"}, - {"path", path + "/-"}, - {"value", target[i]} - }); - ++i; - } - - break; - } - - case value_t::object: - { - // first pass: traverse this object's elements - for (auto it = source.cbegin(); it != source.cend(); ++it) - { - // escape the key name to be used in a JSON patch - const auto key = json_pointer::escape(it.key()); - - if (target.find(it.key()) != target.end()) - { - // recursive call to compare object values at key it - auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key); - result.insert(result.end(), temp_diff.begin(), temp_diff.end()); - } - else - { - // found a key that is not in o -> remove it - result.push_back(object( - { - {"op", "remove"}, {"path", path + "/" + key} - })); - } - } - - // second pass: traverse other object's elements - for (auto it = target.cbegin(); it != target.cend(); ++it) - { - if (source.find(it.key()) == source.end()) - { - // found a key that is not in this -> add it - const auto key = json_pointer::escape(it.key()); - result.push_back( - { - {"op", "add"}, {"path", path + "/" + key}, - {"value", it.value()} - }); - } - } - - break; - } - - default: - { - // both primitive type: replace value - result.push_back( - { - {"op", "replace"}, {"path", path}, {"value", target} - }); - break; - } - } - - return result; - } - - /// @} - - //////////////////////////////// - // JSON Merge Patch functions // - //////////////////////////////// - - /// @name JSON Merge Patch functions - /// @{ - - /*! - @brief applies a JSON Merge Patch - - The merge patch format is primarily intended for use with the HTTP PATCH - method as a means of describing a set of modifications to a target - resource's content. This function applies a merge patch to the current - JSON value. - - The function implements the following algorithm from Section 2 of - [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396): - - ``` - define MergePatch(Target, Patch): - if Patch is an Object: - if Target is not an Object: - Target = {} // Ignore the contents and set it to an empty Object - for each Name/Value pair in Patch: - if Value is null: - if Name exists in Target: - remove the Name/Value pair from Target - else: - Target[Name] = MergePatch(Target[Name], Value) - return Target - else: - return Patch - ``` - - Thereby, `Target` is the current object; that is, the patch is applied to - the current value. - - @param[in] apply_patch the patch to apply - - @complexity Linear in the lengths of @a patch. - - @liveexample{The following code shows how a JSON Merge Patch is applied to - a JSON document.,merge_patch} - - @sa @ref patch -- apply a JSON patch - @sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396) - - @since version 3.0.0 - */ - void merge_patch(const basic_json& apply_patch) - { - if (apply_patch.is_object()) - { - if (!is_object()) - { - *this = object(); - } - for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) - { - if (it.value().is_null()) - { - erase(it.key()); - } - else - { - operator[](it.key()).merge_patch(it.value()); - } - } - } - else - { - *this = apply_patch; - } - } - - /// @} -}; - -/*! -@brief user-defined to_string function for JSON values - -This function implements a user-defined to_string for JSON objects. - -@param[in] j a JSON object -@return a std::string object -*/ - -NLOHMANN_BASIC_JSON_TPL_DECLARATION -std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) -{ - return j.dump(); -} -} // namespace nlohmann - -/////////////////////// -// nonmember support // -/////////////////////// - -// specialization of std::swap, and std::hash -namespace std -{ - -/// hash value for JSON objects -template<> -struct hash -{ - /*! - @brief return a hash value for a JSON object - - @since version 1.0.0 - */ - std::size_t operator()(const nlohmann::json& j) const - { - return nlohmann::detail::hash(j); - } -}; - -/// specialization for std::less -/// @note: do not remove the space after '<', -/// see https://github.com/nlohmann/json/pull/679 -template<> -struct less<::nlohmann::detail::value_t> -{ - /*! - @brief compare two value_t enum values - @since version 3.0.0 - */ - bool operator()(nlohmann::detail::value_t lhs, - nlohmann::detail::value_t rhs) const noexcept - { - return nlohmann::detail::operator<(lhs, rhs); - } -}; - -// C++20 prohibit function specialization in the std namespace. -#ifndef JSON_HAS_CPP_20 - -/*! -@brief exchanges the values of two JSON objects - -@since version 1.0.0 -*/ -template<> -inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcept( - is_nothrow_move_constructible::value&& - is_nothrow_move_assignable::value - ) -{ - j1.swap(j2); -} - -#endif - -} // namespace std - -/*! -@brief user-defined string literal for JSON values - -This operator implements a user-defined string literal for JSON objects. It -can be used by adding `"_json"` to a string literal and returns a JSON object -if no parse error occurred. - -@param[in] s a string representation of a JSON object -@param[in] n the length of string @a s -@return a JSON object - -@since version 1.0.0 -*/ -JSON_HEDLEY_NON_NULL(1) -inline nlohmann::json operator "" _json(const char* s, std::size_t n) -{ - return nlohmann::json::parse(s, s + n); -} - -/*! -@brief user-defined string literal for JSON pointer - -This operator implements a user-defined string literal for JSON Pointers. It -can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer -object if no parse error occurred. - -@param[in] s a string representation of a JSON Pointer -@param[in] n the length of string @a s -@return a JSON pointer object - -@since version 2.0.0 -*/ -JSON_HEDLEY_NON_NULL(1) -inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) -{ - return nlohmann::json::json_pointer(std::string(s, n)); -} - -// #include - - -// restore GCC/clang diagnostic settings -#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #pragma GCC diagnostic pop -#endif -#if defined(__clang__) - #pragma GCC diagnostic pop -#endif - -// clean up -#undef JSON_ASSERT -#undef JSON_INTERNAL_CATCH -#undef JSON_CATCH -#undef JSON_THROW -#undef JSON_TRY -#undef JSON_PRIVATE_UNLESS_TESTED -#undef JSON_HAS_CPP_14 -#undef JSON_HAS_CPP_17 -#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION -#undef NLOHMANN_BASIC_JSON_TPL -#undef JSON_EXPLICIT - -// #include -#undef JSON_HEDLEY_ALWAYS_INLINE -#undef JSON_HEDLEY_ARM_VERSION -#undef JSON_HEDLEY_ARM_VERSION_CHECK -#undef JSON_HEDLEY_ARRAY_PARAM -#undef JSON_HEDLEY_ASSUME -#undef JSON_HEDLEY_BEGIN_C_DECLS -#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE -#undef JSON_HEDLEY_CLANG_HAS_BUILTIN -#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE -#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE -#undef JSON_HEDLEY_CLANG_HAS_EXTENSION -#undef JSON_HEDLEY_CLANG_HAS_FEATURE -#undef JSON_HEDLEY_CLANG_HAS_WARNING -#undef JSON_HEDLEY_COMPCERT_VERSION -#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK -#undef JSON_HEDLEY_CONCAT -#undef JSON_HEDLEY_CONCAT3 -#undef JSON_HEDLEY_CONCAT3_EX -#undef JSON_HEDLEY_CONCAT_EX -#undef JSON_HEDLEY_CONST -#undef JSON_HEDLEY_CONSTEXPR -#undef JSON_HEDLEY_CONST_CAST -#undef JSON_HEDLEY_CPP_CAST -#undef JSON_HEDLEY_CRAY_VERSION -#undef JSON_HEDLEY_CRAY_VERSION_CHECK -#undef JSON_HEDLEY_C_DECL -#undef JSON_HEDLEY_DEPRECATED -#undef JSON_HEDLEY_DEPRECATED_FOR -#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ -#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#undef JSON_HEDLEY_DIAGNOSTIC_POP -#undef JSON_HEDLEY_DIAGNOSTIC_PUSH -#undef JSON_HEDLEY_DMC_VERSION -#undef JSON_HEDLEY_DMC_VERSION_CHECK -#undef JSON_HEDLEY_EMPTY_BASES -#undef JSON_HEDLEY_EMSCRIPTEN_VERSION -#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK -#undef JSON_HEDLEY_END_C_DECLS -#undef JSON_HEDLEY_FLAGS -#undef JSON_HEDLEY_FLAGS_CAST -#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE -#undef JSON_HEDLEY_GCC_HAS_BUILTIN -#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE -#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE -#undef JSON_HEDLEY_GCC_HAS_EXTENSION -#undef JSON_HEDLEY_GCC_HAS_FEATURE -#undef JSON_HEDLEY_GCC_HAS_WARNING -#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK -#undef JSON_HEDLEY_GCC_VERSION -#undef JSON_HEDLEY_GCC_VERSION_CHECK -#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE -#undef JSON_HEDLEY_GNUC_HAS_BUILTIN -#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE -#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE -#undef JSON_HEDLEY_GNUC_HAS_EXTENSION -#undef JSON_HEDLEY_GNUC_HAS_FEATURE -#undef JSON_HEDLEY_GNUC_HAS_WARNING -#undef JSON_HEDLEY_GNUC_VERSION -#undef JSON_HEDLEY_GNUC_VERSION_CHECK -#undef JSON_HEDLEY_HAS_ATTRIBUTE -#undef JSON_HEDLEY_HAS_BUILTIN -#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE -#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS -#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE -#undef JSON_HEDLEY_HAS_EXTENSION -#undef JSON_HEDLEY_HAS_FEATURE -#undef JSON_HEDLEY_HAS_WARNING -#undef JSON_HEDLEY_IAR_VERSION -#undef JSON_HEDLEY_IAR_VERSION_CHECK -#undef JSON_HEDLEY_IBM_VERSION -#undef JSON_HEDLEY_IBM_VERSION_CHECK -#undef JSON_HEDLEY_IMPORT -#undef JSON_HEDLEY_INLINE -#undef JSON_HEDLEY_INTEL_CL_VERSION -#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK -#undef JSON_HEDLEY_INTEL_VERSION -#undef JSON_HEDLEY_INTEL_VERSION_CHECK -#undef JSON_HEDLEY_IS_CONSTANT -#undef JSON_HEDLEY_IS_CONSTEXPR_ -#undef JSON_HEDLEY_LIKELY -#undef JSON_HEDLEY_MALLOC -#undef JSON_HEDLEY_MESSAGE -#undef JSON_HEDLEY_MSVC_VERSION -#undef JSON_HEDLEY_MSVC_VERSION_CHECK -#undef JSON_HEDLEY_NEVER_INLINE -#undef JSON_HEDLEY_NON_NULL -#undef JSON_HEDLEY_NO_ESCAPE -#undef JSON_HEDLEY_NO_RETURN -#undef JSON_HEDLEY_NO_THROW -#undef JSON_HEDLEY_NULL -#undef JSON_HEDLEY_PELLES_VERSION -#undef JSON_HEDLEY_PELLES_VERSION_CHECK -#undef JSON_HEDLEY_PGI_VERSION -#undef JSON_HEDLEY_PGI_VERSION_CHECK -#undef JSON_HEDLEY_PREDICT -#undef JSON_HEDLEY_PRINTF_FORMAT -#undef JSON_HEDLEY_PRIVATE -#undef JSON_HEDLEY_PUBLIC -#undef JSON_HEDLEY_PURE -#undef JSON_HEDLEY_REINTERPRET_CAST -#undef JSON_HEDLEY_REQUIRE -#undef JSON_HEDLEY_REQUIRE_CONSTEXPR -#undef JSON_HEDLEY_REQUIRE_MSG -#undef JSON_HEDLEY_RESTRICT -#undef JSON_HEDLEY_RETURNS_NON_NULL -#undef JSON_HEDLEY_SENTINEL -#undef JSON_HEDLEY_STATIC_ASSERT -#undef JSON_HEDLEY_STATIC_CAST -#undef JSON_HEDLEY_STRINGIFY -#undef JSON_HEDLEY_STRINGIFY_EX -#undef JSON_HEDLEY_SUNPRO_VERSION -#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK -#undef JSON_HEDLEY_TINYC_VERSION -#undef JSON_HEDLEY_TINYC_VERSION_CHECK -#undef JSON_HEDLEY_TI_ARMCL_VERSION -#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK -#undef JSON_HEDLEY_TI_CL2000_VERSION -#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK -#undef JSON_HEDLEY_TI_CL430_VERSION -#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK -#undef JSON_HEDLEY_TI_CL6X_VERSION -#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK -#undef JSON_HEDLEY_TI_CL7X_VERSION -#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK -#undef JSON_HEDLEY_TI_CLPRU_VERSION -#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK -#undef JSON_HEDLEY_TI_VERSION -#undef JSON_HEDLEY_TI_VERSION_CHECK -#undef JSON_HEDLEY_UNAVAILABLE -#undef JSON_HEDLEY_UNLIKELY -#undef JSON_HEDLEY_UNPREDICTABLE -#undef JSON_HEDLEY_UNREACHABLE -#undef JSON_HEDLEY_UNREACHABLE_RETURN -#undef JSON_HEDLEY_VERSION -#undef JSON_HEDLEY_VERSION_DECODE_MAJOR -#undef JSON_HEDLEY_VERSION_DECODE_MINOR -#undef JSON_HEDLEY_VERSION_DECODE_REVISION -#undef JSON_HEDLEY_VERSION_ENCODE -#undef JSON_HEDLEY_WARNING -#undef JSON_HEDLEY_WARN_UNUSED_RESULT -#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG -#undef JSON_HEDLEY_FALL_THROUGH - - - -#endif // INCLUDE_NLOHMANN_JSON_HPP_ diff --git a/dependencies/hueplusplus-1.0.0/src/CMakeLists.txt b/dependencies/hueplusplus-1.0.0/src/CMakeLists.txt deleted file mode 100644 index 5135e43c..00000000 --- a/dependencies/hueplusplus-1.0.0/src/CMakeLists.txt +++ /dev/null @@ -1,81 +0,0 @@ -set(hueplusplus_SOURCES - Action.cpp - APICache.cpp - BaseDevice.cpp - BaseHttpHandler.cpp - Bridge.cpp - BridgeConfig.cpp - CLIPSensors.cpp - ColorUnits.cpp - EntertainmentMode.cpp - ExtendedColorHueStrategy.cpp - ExtendedColorTemperatureStrategy.cpp - Group.cpp - HueCommandAPI.cpp - HueDeviceTypes.cpp - HueException.cpp - Light.cpp - ModelPictures.cpp - NewDeviceList.cpp - Rule.cpp - Scene.cpp - Schedule.cpp - Sensor.cpp - SimpleBrightnessStrategy.cpp - SimpleColorHueStrategy.cpp - SimpleColorTemperatureStrategy.cpp - StateTransaction.cpp - TimePattern.cpp - UPnP.cpp - Utils.cpp - ZLLSensors.cpp) - -# on windows we want to compile the WinHttpHandler -if(WIN32) - set(hueplusplus_SOURCES - ${hueplusplus_SOURCES} - WinHttpHandler.cpp - ) -endif() -# whereas on linux we want the LinHttpHandler -if(UNIX) - set(hueplusplus_SOURCES - ${hueplusplus_SOURCES} - LinHttpHandler.cpp - ) -endif() -if(ESP_PLATFORM) - set(hueplusplus_SOURCES - ${hueplusplus_SOURCES} - LinHttpHandler.cpp - ) -endif() - -# append current source dir before files -foreach(src ${hueplusplus_SOURCES}) - list(APPEND _srcList "${CMAKE_CURRENT_SOURCE_DIR}/${src}") -endforeach() -set(hueplusplus_SOURCES ${_srcList} PARENT_SCOPE) - -# hueplusplus shared library -add_library(hueplusplusshared SHARED ${hueplusplus_SOURCES}) -target_link_libraries(hueplusplusshared PRIVATE mbedtls) -target_compile_features(hueplusplusshared PUBLIC cxx_std_14) -target_include_directories(hueplusplusshared PUBLIC $ $) -install(TARGETS hueplusplusshared DESTINATION lib) - -# hueplusplus static library -add_library(hueplusplusstatic STATIC ${hueplusplus_SOURCES}) -target_link_libraries(hueplusplusstatic PRIVATE mbedtls) -target_compile_features(hueplusplusstatic PUBLIC cxx_std_14) -install(TARGETS hueplusplusstatic DESTINATION lib) -target_include_directories(hueplusplusstatic PUBLIC $ $) -install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/" DESTINATION include) - -# Export the package for use from the build-tree -# (this registers the build-tree with a global CMake-registry) -export(PACKAGE hueplusplus) -# Create the hueplusplus-config.cmake -configure_file ("${PROJECT_SOURCE_DIR}/cmake/hueplusplus-config.cmake.in" "${hueplusplus_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hueplusplus-config.cmake" @ONLY) -# Install hueplusplus-config.cmake -install(FILES "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hueplusplus-config.cmake" DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev) diff --git a/dependencies/hueplusplus-1.0.0/test/CMakeLists.txt b/dependencies/hueplusplus-1.0.0/test/CMakeLists.txt deleted file mode 100644 index 8ac7e3fc..00000000 --- a/dependencies/hueplusplus-1.0.0/test/CMakeLists.txt +++ /dev/null @@ -1,125 +0,0 @@ -# Download and unpack googletest at configure time -configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt) -execute_process(COMMAND ${CMAKE_COMMAND} -G ${CMAKE_GENERATOR} . - RESULT_VARIABLE result - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/googletest-download" -) -if(result) - message(FATAL_ERROR "CMake step for googletest failed: ${result}") -endif() -execute_process(COMMAND "${CMAKE_COMMAND}" --build . - RESULT_VARIABLE result - WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/googletest-download" -) -if(result) - message(FATAL_ERROR "Build step for googletest failed: ${result}") -endif() - -# Prevent overriding the parent project's compiler/linker -# settings on Windows -set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) - -# Add googletest directly to our build. This defines -# the gtest and gtest_main targets. -add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src EXCLUDE_FROM_ALL - ${CMAKE_CURRENT_BINARY_DIR}/googletest-build EXCLUDE_FROM_ALL -) - -target_compile_features(gmock PUBLIC cxx_std_14) -target_compile_features(gtest PUBLIC cxx_std_14) - -# define all test sources -set(TEST_SOURCES - test_Action.cpp - test_APICache.cpp - test_BaseDevice.cpp - test_BaseHttpHandler.cpp - test_Bridge.cpp - test_BridgeConfig.cpp - test_SensorImpls.cpp - test_ColorUnits.cpp - test_ExtendedColorHueStrategy.cpp - test_ExtendedColorTemperatureStrategy.cpp - test_Group.cpp - test_HueCommandAPI.cpp - test_Light.cpp - test_LightFactory.cpp - test_Main.cpp - test_NewDeviceList.cpp - test_UPnP.cpp - test_ResourceList.cpp - test_Rule.cpp - test_Scene.cpp - test_Schedule.cpp - test_Sensor.cpp - test_SensorList.cpp - test_SimpleBrightnessStrategy.cpp - test_SimpleColorHueStrategy.cpp - test_SimpleColorTemperatureStrategy.cpp - test_StateTransaction.cpp - test_TimePattern.cpp) - -set(HuePlusPlus_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/include") - -# test executable -add_executable(test_HuePlusPlus ${TEST_SOURCES}) -#if(DO_CLANG_TIDY) -# set_target_properties(test_HuePlusPlus PROPERTIES CXX_CLANG_TIDY ${DO_CLANG_TIDY}) -#endif() -target_compile_features(test_HuePlusPlus PUBLIC cxx_std_14) -set_property(TARGET test_HuePlusPlus PROPERTY CXX_EXTENSIONS OFF) - -target_link_libraries(test_HuePlusPlus PUBLIC hueplusplusstatic) -target_link_libraries(test_HuePlusPlus PUBLIC gtest gmock) -target_include_directories(test_HuePlusPlus PUBLIC ${GTest_INCLUDE_DIRS}) -# add custom target to make it simple to run the tests -add_custom_target("unittest" - # Run the executable - COMMAND test_HuePlusPlus - # Depends on test_HuePlusPlus - DEPENDS test_HuePlusPlus -) - -# Check for coverage test prerequisites -find_program( GCOV_PATH gcov ) -find_program( LCOV_PATH lcov ) - -mark_as_advanced(GCOV_PATH) -mark_as_advanced(LCOV_PATH) - -if(LCOV_PATH AND GCOV_PATH) - # GCov - include(CodeCoverage.cmake) - add_executable(testcov_HuePlusPlus ${TEST_SOURCES} ${hueplusplus_SOURCES}) - target_include_directories(testcov_HuePlusPlus PUBLIC "${PROJECT_SOURCE_DIR}/include") - target_compile_features(testcov_HuePlusPlus PUBLIC cxx_std_14) - set_property(TARGET testcov_HuePlusPlus PROPERTY CXX_EXTENSIONS OFF) - - target_link_libraries(testcov_HuePlusPlus PRIVATE mbedtls) - target_link_libraries(testcov_HuePlusPlus PUBLIC gtest gmock) - target_include_directories(testcov_HuePlusPlus PUBLIC ${GTest_INCLUDE_DIRS}) - # this will be already done by APPEND_COVERAGE_COMPILER_FLAGS() - #set_target_properties( - # testcov_HuePlusPlus PROPERTIES - # COMPILE_FLAGS "-O0 -g -fprofile-arcs -ftest-coverage" - #) - # Normally this would be -lgcov, but on mac only -Lgcov works - #set_target_properties( - # testcov_HuePlusPlus PROPERTIES - # LINK_FLAGS "-O0 -g -Lgcov -fprofile-arcs -ftest-coverage" - #) - # exclude some special files we do not want to profile - set(COVERAGE_EXCLUDES - '/usr/*' # unix - '*/hueplusplus/build/*' - '*/json*' - '*/test/*' - '*/v1/*' # iOS - ) - APPEND_COVERAGE_COMPILER_FLAGS() - SETUP_TARGET_FOR_COVERAGE( - NAME "coveragetest" - EXECUTABLE testcov_HuePlusPlus - DEPENDENCIES testcov_HuePlusPlus - ) -endif() diff --git a/dependencies/hueplusplus-1.0.0/.clang-format b/dependencies/hueplusplus-1.2.0/.clang-format similarity index 100% rename from dependencies/hueplusplus-1.0.0/.clang-format rename to dependencies/hueplusplus-1.2.0/.clang-format diff --git a/dependencies/hueplusplus-1.0.0/.github/CONTRIBUTING.md b/dependencies/hueplusplus-1.2.0/.github/CONTRIBUTING.md similarity index 100% rename from dependencies/hueplusplus-1.0.0/.github/CONTRIBUTING.md rename to dependencies/hueplusplus-1.2.0/.github/CONTRIBUTING.md diff --git a/dependencies/hueplusplus-1.2.0/.github/FUNDING.yml b/dependencies/hueplusplus-1.2.0/.github/FUNDING.yml new file mode 100644 index 00000000..4cb6d7c2 --- /dev/null +++ b/dependencies/hueplusplus-1.2.0/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: [enwi] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/dependencies/hueplusplus-1.0.0/.github/ISSUE_TEMPLATE/bug_report.md b/dependencies/hueplusplus-1.2.0/.github/ISSUE_TEMPLATE/bug_report.md similarity index 100% rename from dependencies/hueplusplus-1.0.0/.github/ISSUE_TEMPLATE/bug_report.md rename to dependencies/hueplusplus-1.2.0/.github/ISSUE_TEMPLATE/bug_report.md diff --git a/dependencies/hueplusplus-1.0.0/.github/ISSUE_TEMPLATE/feature_request.md b/dependencies/hueplusplus-1.2.0/.github/ISSUE_TEMPLATE/feature_request.md similarity index 100% rename from dependencies/hueplusplus-1.0.0/.github/ISSUE_TEMPLATE/feature_request.md rename to dependencies/hueplusplus-1.2.0/.github/ISSUE_TEMPLATE/feature_request.md diff --git a/dependencies/hueplusplus-1.2.0/.github/workflows/build.yml b/dependencies/hueplusplus-1.2.0/.github/workflows/build.yml new file mode 100644 index 00000000..60bea111 --- /dev/null +++ b/dependencies/hueplusplus-1.2.0/.github/workflows/build.yml @@ -0,0 +1,72 @@ +name: CI + +on: + push: + branches: + - master + - development + pull_request: + +jobs: + build: + runs-on: ubuntu-24.04 + + env: + LINUX_DIST: bionic + DEPS_DIR: ${{ github.workspace }}/deps + COMPILER_NAME: gcc + CXX: g++ + CC: gcc + RUN_TESTS: true + COVERAGE: false + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + # PATH: ${{ github.workspace }}/deps/cmake/bin:${{ env.PATH }} + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up dependencies + run: | + sudo apt-get update -qq + sudo apt-get install -y gcc g++ lcov doxygen graphviz python3-yaml + + # - name: Install CodeCov and LCOV + # run: | + # sudo update-alternatives --install /usr/bin/gcov gcov /usr/bin/gcov-7 90 + # 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 + # echo "${HOME}/.local/bin" >> $GITHUB_PATH + + - name: Show tool versions + run: | + echo $PATH + echo $CXX + $CXX --version + $CXX -v + cmake --version + lcov --version + gcov --version + + - name: Build project + run: | + 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 + touch doc/html/.nojekyll + + - name: Upload coverage to Codecov + run: | + bash <(curl -s https://codecov.io/bash) + + - name: Deploy documentation to GitHub Pages + if: github.ref == 'refs/heads/master' + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: ./doc/html diff --git a/dependencies/hueplusplus-1.0.0/.gitignore b/dependencies/hueplusplus-1.2.0/.gitignore old mode 100644 new mode 100755 similarity index 100% rename from dependencies/hueplusplus-1.0.0/.gitignore rename to dependencies/hueplusplus-1.2.0/.gitignore diff --git a/dependencies/hueplusplus-1.2.0/.gitmodules b/dependencies/hueplusplus-1.2.0/.gitmodules new file mode 100644 index 00000000..6c932c7c --- /dev/null +++ b/dependencies/hueplusplus-1.2.0/.gitmodules @@ -0,0 +1,6 @@ +[submodule "lib/mbedtls"] + path = lib/mbedtls + url = https://github.com/ARMmbed/mbedtls.git +[submodule "lib/json"] + path = lib/json + url = https://github.com/nlohmann/json.git diff --git a/dependencies/hueplusplus-1.0.0/.travis.yml b/dependencies/hueplusplus-1.2.0/.travis.yml old mode 100644 new mode 100755 similarity index 100% rename from dependencies/hueplusplus-1.0.0/.travis.yml rename to dependencies/hueplusplus-1.2.0/.travis.yml diff --git a/dependencies/hueplusplus-1.2.0/CMakeLists.txt b/dependencies/hueplusplus-1.2.0/CMakeLists.txt new file mode 100644 index 00000000..548de9d1 --- /dev/null +++ b/dependencies/hueplusplus-1.2.0/CMakeLists.txt @@ -0,0 +1,128 @@ +cmake_minimum_required(VERSION 3.10.2...3.28) + +# 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.2.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(hueplusplus_NO_EXTERNAL_LIBRARIES "Do not try to use external libraries" OFF) + +# Try to find installed packages +if(NOT hueplusplus_NO_EXTERNAL_LIBRARIES) + # Suppress warnings if libraries are not found, they will be built from submodules + find_package(MbedTLS QUIET) + find_package(nlohmann_json QUIET) +endif() + +set(NEED_SUBMODULES NOT (${MbedTLS_FOUND} AND ${nlohmann_json_FOUND})) + +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 AND NEED_SUBMODULES) + 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() + +if(NOT MbedTLS_FOUND) + # Build mbedtls if not installed + message(STATUS "MbedTLS was not found, the submodule is used.") + 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) + + if(CMAKE_VERSION VERSION_LESS 3.18) + # Aliases for compatibility with find_package, newer cmake versions add these already + add_library(MbedTLS::mbedtls ALIAS mbedtls) + add_library(MbedTLS::mbedcrypto ALIAS mbedcrypto) + add_library(MbedTLS::mbedx509 ALIAS mbedx509) + endif() +endif() + +if(NOT nlohmann_json_FOUND) + # Use embedded json + message(STATUS "nlohmann_json was not found, the submodule is used.") + # disable tests for json + set(JSON_BuildTests OFF CACHE INTERNAL "") + add_subdirectory("lib/json" EXCLUDE_FROM_ALL) +endif() + +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() diff --git a/dependencies/hueplusplus-1.0.0/Doxyfile b/dependencies/hueplusplus-1.2.0/Doxyfile old mode 100644 new mode 100755 similarity index 99% rename from dependencies/hueplusplus-1.0.0/Doxyfile rename to dependencies/hueplusplus-1.2.0/Doxyfile index 832e95ac..d3f9f886 --- a/dependencies/hueplusplus-1.0.0/Doxyfile +++ b/dependencies/hueplusplus-1.2.0/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = hueplusplus # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 1.0.0 +PROJECT_NUMBER = 1.2.0 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/dependencies/hueplusplus-1.0.0/LICENSE b/dependencies/hueplusplus-1.2.0/LICENSE old mode 100644 new mode 100755 similarity index 100% rename from dependencies/hueplusplus-1.0.0/LICENSE rename to dependencies/hueplusplus-1.2.0/LICENSE diff --git a/dependencies/hueplusplus-1.2.0/README.md b/dependencies/hueplusplus-1.2.0/README.md new file mode 100755 index 00000000..a010f2b5 --- /dev/null +++ b/dependencies/hueplusplus-1.2.0/README.md @@ -0,0 +1,165 @@ +# hueplusplus +A simple and easy to use library for Philips Hue Lights + +| Branch | CI | Codecov | LGTM +|:-|:-|:-|:-| +| [Master](https://github.com/enwi/hueplusplus/tree/master) | [![CI](https://github.com/enwi/hueplusplus/actions/workflows/build.yml/badge.svg?branch=master)](https://github.com/enwi/hueplusplus/actions/workflows/build.yml)| [![codecov](https://codecov.io/gh/enwi/hueplusplus/branch/master/graph/badge.svg)](https://codecov.io/gh/enwi/hueplusplus) | [![Language grade: C/C++](https://img.shields.io/lgtm/grade/cpp/g/enwi/hueplusplus.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/enwi/hueplusplus/context:cpp) | +| [Development](https://github.com/enwi/hueplusplus/tree/development) | [![CI](https://github.com/enwi/hueplusplus/actions/workflows/build.yml/badge.svg?branch=development)](https://github.com/enwi/hueplusplus/actions/workflows/build.yml) | [![codecov](https://codecov.io/gh/enwi/hueplusplus/branch/development/graph/badge.svg)](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 +### 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(); +handler = std::make_shared(); +hueplusplus::BridgeFinder finder(handler); +std::vector 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[\]), +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, ""); +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(); +handler = std::make_shared(); +hueplusplus::Bridge bridge("192.168.2.102", 80, "", 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(\) 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 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\, 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( 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}//hueplusplus" "${CMAKE_CURRENT_BINARY_DIR}/hueplusplus") +endif() + +target_link_libraries( 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. diff --git a/dependencies/hueplusplus-1.0.0/cmake/cmake_uninstall.cmake.in b/dependencies/hueplusplus-1.2.0/cmake/cmake_uninstall.cmake.in similarity index 100% rename from dependencies/hueplusplus-1.0.0/cmake/cmake_uninstall.cmake.in rename to dependencies/hueplusplus-1.2.0/cmake/cmake_uninstall.cmake.in diff --git a/dependencies/hueplusplus-1.0.0/cmake/hueplusplus-config.cmake.in b/dependencies/hueplusplus-1.2.0/cmake/hueplusplus-config.cmake.in similarity index 100% rename from dependencies/hueplusplus-1.0.0/cmake/hueplusplus-config.cmake.in rename to dependencies/hueplusplus-1.2.0/cmake/hueplusplus-config.cmake.in diff --git a/dependencies/hueplusplus-1.0.0/codecov.yml b/dependencies/hueplusplus-1.2.0/codecov.yml old mode 100644 new mode 100755 similarity index 100% rename from dependencies/hueplusplus-1.0.0/codecov.yml rename to dependencies/hueplusplus-1.2.0/codecov.yml diff --git a/dependencies/hueplusplus-1.0.0/doc/markdown/Build.md b/dependencies/hueplusplus-1.2.0/doc/markdown/Build.md similarity index 88% rename from dependencies/hueplusplus-1.0.0/doc/markdown/Build.md rename to dependencies/hueplusplus-1.2.0/doc/markdown/Build.md index 60c0ea46..9d9ea53f 100644 --- a/dependencies/hueplusplus-1.0.0/doc/markdown/Build.md +++ b/dependencies/hueplusplus-1.2.0/doc/markdown/Build.md @@ -18,7 +18,7 @@ When you want to update the library for a new version, use pull with rebase. ``` ## Build with CMake {#build-cmake} -To build the library, you need to use [CMake](https://cmake.org) version 3.8 or higher. +To build the library, you need to use [CMake](https://cmake.org) version 3.10 or higher. It is easiest to create a separate build directory where the build files are stored. ```{.sh} ~/hueplusplus $ mkdir build @@ -84,3 +84,7 @@ cd build cmake .. -Dhueplusplus_EXAMPLES=ON make hueplusplus_examples ``` + +## External libraries +Hueplusplus requires a few external libraries (e.g. Mbed TLS and GTest), which are included automatically. If these are pre-installed on your system, those versions will be used by default. This can potentially cause issues if your installed versions are incompatible. +In this case, set `hueplusplus_NO_EXTERNAL_LIBRARIES=ON` to force using the embedded versions instead of the installed libraries. \ No newline at end of file diff --git a/dependencies/hueplusplus-1.0.0/doc/markdown/Getting_Started.md b/dependencies/hueplusplus-1.2.0/doc/markdown/Getting_Started.md similarity index 100% rename from dependencies/hueplusplus-1.0.0/doc/markdown/Getting_Started.md rename to dependencies/hueplusplus-1.2.0/doc/markdown/Getting_Started.md diff --git a/dependencies/hueplusplus-1.0.0/doc/markdown/Mainpage.md b/dependencies/hueplusplus-1.2.0/doc/markdown/Mainpage.md similarity index 100% rename from dependencies/hueplusplus-1.0.0/doc/markdown/Mainpage.md rename to dependencies/hueplusplus-1.2.0/doc/markdown/Mainpage.md diff --git a/dependencies/hueplusplus-1.0.0/doc/markdown/Sensors.md b/dependencies/hueplusplus-1.2.0/doc/markdown/Sensors.md similarity index 100% rename from dependencies/hueplusplus-1.0.0/doc/markdown/Sensors.md rename to dependencies/hueplusplus-1.2.0/doc/markdown/Sensors.md diff --git a/dependencies/hueplusplus-1.0.0/doc/markdown/Shared_State.md b/dependencies/hueplusplus-1.2.0/doc/markdown/Shared_State.md similarity index 100% rename from dependencies/hueplusplus-1.0.0/doc/markdown/Shared_State.md rename to dependencies/hueplusplus-1.2.0/doc/markdown/Shared_State.md diff --git a/dependencies/hueplusplus-1.0.0/doc/markdown/Transactions.md b/dependencies/hueplusplus-1.2.0/doc/markdown/Transactions.md similarity index 100% rename from dependencies/hueplusplus-1.0.0/doc/markdown/Transactions.md rename to dependencies/hueplusplus-1.2.0/doc/markdown/Transactions.md diff --git a/dependencies/hueplusplus-1.0.0/examples/BridgeSetup.cpp b/dependencies/hueplusplus-1.2.0/examples/BridgeSetup.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/examples/BridgeSetup.cpp rename to dependencies/hueplusplus-1.2.0/examples/BridgeSetup.cpp diff --git a/dependencies/hueplusplus-1.0.0/examples/CMakeLists.txt b/dependencies/hueplusplus-1.2.0/examples/CMakeLists.txt similarity index 100% rename from dependencies/hueplusplus-1.0.0/examples/CMakeLists.txt rename to dependencies/hueplusplus-1.2.0/examples/CMakeLists.txt diff --git a/dependencies/hueplusplus-1.0.0/examples/LightsOff.cpp b/dependencies/hueplusplus-1.2.0/examples/LightsOff.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/examples/LightsOff.cpp rename to dependencies/hueplusplus-1.2.0/examples/LightsOff.cpp diff --git a/dependencies/hueplusplus-1.0.0/examples/Snippets.cpp b/dependencies/hueplusplus-1.2.0/examples/Snippets.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/examples/Snippets.cpp rename to dependencies/hueplusplus-1.2.0/examples/Snippets.cpp diff --git a/dependencies/hueplusplus-1.0.0/examples/UsernameConfig.cpp b/dependencies/hueplusplus-1.2.0/examples/UsernameConfig.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/examples/UsernameConfig.cpp rename to dependencies/hueplusplus-1.2.0/examples/UsernameConfig.cpp diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/APICache.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/APICache.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/APICache.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/APICache.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Action.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Action.h similarity index 98% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/Action.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/Action.h index 744bf068..9e341039 100644 --- a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Action.h +++ b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Action.h @@ -22,7 +22,7 @@ #ifndef INCLUDE_HUEPLUSPLUS_ACTION_H #define INCLUDE_HUEPLUSPLUS_ACTION_H -#include "json/json.hpp" +#include namespace hueplusplus { diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/BaseDevice.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/BaseDevice.h similarity index 99% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/BaseDevice.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/BaseDevice.h index 8ab2ea17..dccd06bf 100644 --- a/dependencies/hueplusplus-1.0.0/include/hueplusplus/BaseDevice.h +++ b/dependencies/hueplusplus-1.2.0/include/hueplusplus/BaseDevice.h @@ -27,7 +27,7 @@ #include "APICache.h" -#include "json/json.hpp" +#include namespace hueplusplus { diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/BaseHttpHandler.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/BaseHttpHandler.h similarity index 99% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/BaseHttpHandler.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/BaseHttpHandler.h index a052e2dc..717450a5 100644 --- a/dependencies/hueplusplus-1.0.0/include/hueplusplus/BaseHttpHandler.h +++ b/dependencies/hueplusplus-1.2.0/include/hueplusplus/BaseHttpHandler.h @@ -30,7 +30,7 @@ #include "IHttpHandler.h" -#include "json/json.hpp" +#include namespace hueplusplus { diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Bridge.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Bridge.h similarity index 99% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/Bridge.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/Bridge.h index 44dcab06..a5608de4 100644 --- a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Bridge.h +++ b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Bridge.h @@ -47,7 +47,7 @@ #include "SensorList.h" #include "Utils.h" -#include "json/json.hpp" +#include //! \brief Namespace for the hueplusplus library namespace hueplusplus diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/BridgeConfig.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/BridgeConfig.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/BridgeConfig.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/BridgeConfig.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/BrightnessStrategy.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/BrightnessStrategy.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/BrightnessStrategy.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/BrightnessStrategy.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/CLIPSensors.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/CLIPSensors.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/CLIPSensors.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/CLIPSensors.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/ColorHueStrategy.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/ColorHueStrategy.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/ColorHueStrategy.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/ColorHueStrategy.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/ColorTemperatureStrategy.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/ColorTemperatureStrategy.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/ColorTemperatureStrategy.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/ColorTemperatureStrategy.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/ColorUnits.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/ColorUnits.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/ColorUnits.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/ColorUnits.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Condition.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Condition.h similarity index 99% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/Condition.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/Condition.h index 3d7c766e..c96ae97f 100644 --- a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Condition.h +++ b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Condition.h @@ -24,7 +24,7 @@ #include "TimePattern.h" -#include "json/json.hpp" +#include namespace hueplusplus { diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/EntertainmentMode.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/EntertainmentMode.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/EntertainmentMode.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/EntertainmentMode.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/ExtendedColorHueStrategy.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/ExtendedColorHueStrategy.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/ExtendedColorHueStrategy.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/ExtendedColorHueStrategy.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/ExtendedColorTemperatureStrategy.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/ExtendedColorTemperatureStrategy.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/ExtendedColorTemperatureStrategy.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/ExtendedColorTemperatureStrategy.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Group.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Group.h similarity index 99% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/Group.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/Group.h index f0c929b8..5e595622 100644 --- a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Group.h +++ b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Group.h @@ -31,7 +31,7 @@ #include "HueCommandAPI.h" #include "StateTransaction.h" -#include "json/json.hpp" +#include namespace hueplusplus { diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/HueCommandAPI.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/HueCommandAPI.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/HueCommandAPI.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/HueCommandAPI.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/HueDeviceTypes.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/HueDeviceTypes.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/HueDeviceTypes.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/HueDeviceTypes.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/HueException.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/HueException.h similarity index 99% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/HueException.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/HueException.h index 974eec54..27b303f5 100644 --- a/dependencies/hueplusplus-1.0.0/include/hueplusplus/HueException.h +++ b/dependencies/hueplusplus-1.2.0/include/hueplusplus/HueException.h @@ -26,7 +26,7 @@ #include #include -#include "json/json.hpp" +#include namespace hueplusplus { diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/HueExceptionMacro.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/HueExceptionMacro.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/HueExceptionMacro.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/HueExceptionMacro.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/IHttpHandler.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/IHttpHandler.h similarity index 99% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/IHttpHandler.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/IHttpHandler.h index 6deefa7c..5f7c6ffe 100644 --- a/dependencies/hueplusplus-1.0.0/include/hueplusplus/IHttpHandler.h +++ b/dependencies/hueplusplus-1.2.0/include/hueplusplus/IHttpHandler.h @@ -29,7 +29,7 @@ #include #include -#include "json/json.hpp" +#include namespace hueplusplus { diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/LibConfig.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/LibConfig.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/LibConfig.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/LibConfig.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Light.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Light.h similarity index 99% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/Light.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/Light.h index 36d32d1f..c4cce823 100644 --- a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Light.h +++ b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Light.h @@ -33,7 +33,7 @@ #include "HueCommandAPI.h" #include "StateTransaction.h" -#include "json/json.hpp" +#include namespace hueplusplus { diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/LinHttpHandler.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/LinHttpHandler.h similarity index 98% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/LinHttpHandler.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/LinHttpHandler.h index b4b96b20..242193cf 100644 --- a/dependencies/hueplusplus-1.0.0/include/hueplusplus/LinHttpHandler.h +++ b/dependencies/hueplusplus-1.2.0/include/hueplusplus/LinHttpHandler.h @@ -28,7 +28,7 @@ #include "BaseHttpHandler.h" -#include "json/json.hpp" +#include namespace hueplusplus { diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/ModelPictures.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/ModelPictures.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/ModelPictures.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/ModelPictures.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/NewDeviceList.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/NewDeviceList.h similarity index 98% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/NewDeviceList.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/NewDeviceList.h index 715485e0..65daa0d9 100644 --- a/dependencies/hueplusplus-1.0.0/include/hueplusplus/NewDeviceList.h +++ b/dependencies/hueplusplus-1.2.0/include/hueplusplus/NewDeviceList.h @@ -27,7 +27,7 @@ #include "TimePattern.h" -#include "json/json.hpp" +#include namespace hueplusplus { diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/ResourceList.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/ResourceList.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/ResourceList.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/ResourceList.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Rule.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Rule.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/Rule.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/Rule.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Scene.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Scene.h similarity index 99% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/Scene.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/Scene.h index a80411d9..2b0cdc4f 100644 --- a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Scene.h +++ b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Scene.h @@ -26,7 +26,7 @@ #include #include -#include +#include #include "APICache.h" #include "ColorUnits.h" diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Schedule.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Schedule.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/Schedule.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/Schedule.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Sensor.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Sensor.h similarity index 99% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/Sensor.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/Sensor.h index d0104a39..72ef51a8 100644 --- a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Sensor.h +++ b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Sensor.h @@ -30,7 +30,7 @@ #include "HueCommandAPI.h" #include "TimePattern.h" -#include "json/json.hpp" +#include namespace hueplusplus { diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/SensorList.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/SensorList.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/SensorList.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/SensorList.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/SimpleBrightnessStrategy.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/SimpleBrightnessStrategy.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/SimpleBrightnessStrategy.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/SimpleBrightnessStrategy.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/SimpleColorHueStrategy.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/SimpleColorHueStrategy.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/SimpleColorHueStrategy.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/SimpleColorHueStrategy.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/SimpleColorTemperatureStrategy.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/SimpleColorTemperatureStrategy.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/SimpleColorTemperatureStrategy.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/SimpleColorTemperatureStrategy.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/StateTransaction.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/StateTransaction.h similarity index 99% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/StateTransaction.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/StateTransaction.h index 19a20c58..7e667474 100644 --- a/dependencies/hueplusplus-1.0.0/include/hueplusplus/StateTransaction.h +++ b/dependencies/hueplusplus-1.2.0/include/hueplusplus/StateTransaction.h @@ -29,7 +29,7 @@ #include "ColorUnits.h" #include "HueCommandAPI.h" -#include "json/json.hpp" +#include namespace hueplusplus { diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/TimePattern.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/TimePattern.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/TimePattern.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/TimePattern.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/UPnP.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/UPnP.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/UPnP.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/UPnP.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Utils.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Utils.h similarity index 99% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/Utils.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/Utils.h index ecb989a2..1af4b5ba 100644 --- a/dependencies/hueplusplus-1.0.0/include/hueplusplus/Utils.h +++ b/dependencies/hueplusplus-1.2.0/include/hueplusplus/Utils.h @@ -23,7 +23,7 @@ #ifndef INCLUDE_HUEPLUSPLUS_UTILS_H #define INCLUDE_HUEPLUSPLUS_UTILS_H -#include "json/json.hpp" +#include namespace hueplusplus { diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/WinHttpHandler.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/WinHttpHandler.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/WinHttpHandler.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/WinHttpHandler.h diff --git a/dependencies/hueplusplus-1.0.0/include/hueplusplus/ZLLSensors.h b/dependencies/hueplusplus-1.2.0/include/hueplusplus/ZLLSensors.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/include/hueplusplus/ZLLSensors.h rename to dependencies/hueplusplus-1.2.0/include/hueplusplus/ZLLSensors.h diff --git a/dependencies/hueplusplus-1.0.0/lgtm.yml b/dependencies/hueplusplus-1.2.0/lgtm.yml similarity index 100% rename from dependencies/hueplusplus-1.0.0/lgtm.yml rename to dependencies/hueplusplus-1.2.0/lgtm.yml diff --git a/dependencies/hueplusplus-1.0.0/src/APICache.cpp b/dependencies/hueplusplus-1.2.0/src/APICache.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/APICache.cpp rename to dependencies/hueplusplus-1.2.0/src/APICache.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/Action.cpp b/dependencies/hueplusplus-1.2.0/src/Action.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/Action.cpp rename to dependencies/hueplusplus-1.2.0/src/Action.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/BaseDevice.cpp b/dependencies/hueplusplus-1.2.0/src/BaseDevice.cpp similarity index 99% rename from dependencies/hueplusplus-1.0.0/src/BaseDevice.cpp rename to dependencies/hueplusplus-1.2.0/src/BaseDevice.cpp index a7018c08..64b949f8 100644 --- a/dependencies/hueplusplus-1.0.0/src/BaseDevice.cpp +++ b/dependencies/hueplusplus-1.2.0/src/BaseDevice.cpp @@ -27,7 +27,7 @@ #include "hueplusplus/HueExceptionMacro.h" #include "hueplusplus/Utils.h" -#include "json/json.hpp" +#include namespace hueplusplus { diff --git a/dependencies/hueplusplus-1.0.0/src/BaseHttpHandler.cpp b/dependencies/hueplusplus-1.2.0/src/BaseHttpHandler.cpp similarity index 89% rename from dependencies/hueplusplus-1.0.0/src/BaseHttpHandler.cpp rename to dependencies/hueplusplus-1.2.0/src/BaseHttpHandler.cpp index aeef09b8..d0fc846c 100644 --- a/dependencies/hueplusplus-1.0.0/src/BaseHttpHandler.cpp +++ b/dependencies/hueplusplus-1.2.0/src/BaseHttpHandler.cpp @@ -56,14 +56,20 @@ std::string BaseHttpHandler::sendHTTPRequest(const std::string& method, const st request.append("HTTP/1.0"); // HTTP-Version request.append("\r\n"); // Ending // Entities - request.append("Content-Type:"); // entity-header - request.append(" "); // Separation - request.append(contentType); // media-type - request.append("\r\n"); // Entity ending - request.append("Content-Length:"); // entity-header - request.append(" "); // Separation - request.append(std::to_string(body.size())); // length - request.append("\r\n\r\n"); // Entity ending & Request-Line ending + if (!contentType.empty()) + { + request.append("Content-Type:"); // entity-header + request.append(" "); // Separation + request.append(contentType); // media-type + request.append("\r\n"); // Entity ending + } + if (!body.empty()) + { + request.append("Content-Length:"); // entity-header + request.append(" "); // Separation + request.append(std::to_string(body.size())); // length + request.append("\r\n\r\n"); // Entity ending & Request-Line ending + } request.append(body); // message-body request.append("\r\n\r\n"); // Ending diff --git a/dependencies/hueplusplus-1.0.0/src/Bridge.cpp b/dependencies/hueplusplus-1.2.0/src/Bridge.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/Bridge.cpp rename to dependencies/hueplusplus-1.2.0/src/Bridge.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/BridgeConfig.cpp b/dependencies/hueplusplus-1.2.0/src/BridgeConfig.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/BridgeConfig.cpp rename to dependencies/hueplusplus-1.2.0/src/BridgeConfig.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/CLIPSensors.cpp b/dependencies/hueplusplus-1.2.0/src/CLIPSensors.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/CLIPSensors.cpp rename to dependencies/hueplusplus-1.2.0/src/CLIPSensors.cpp diff --git a/dependencies/hueplusplus-1.2.0/src/CMakeLists.txt b/dependencies/hueplusplus-1.2.0/src/CMakeLists.txt new file mode 100644 index 00000000..9c31f2a1 --- /dev/null +++ b/dependencies/hueplusplus-1.2.0/src/CMakeLists.txt @@ -0,0 +1,94 @@ +set(hueplusplus_SOURCES + Action.cpp + APICache.cpp + BaseDevice.cpp + BaseHttpHandler.cpp + Bridge.cpp + BridgeConfig.cpp + CLIPSensors.cpp + ColorUnits.cpp + EntertainmentMode.cpp + ExtendedColorHueStrategy.cpp + ExtendedColorTemperatureStrategy.cpp + Group.cpp + HueCommandAPI.cpp + HueDeviceTypes.cpp + HueException.cpp + Light.cpp + ModelPictures.cpp + NewDeviceList.cpp + Rule.cpp + Scene.cpp + Schedule.cpp + Sensor.cpp + SimpleBrightnessStrategy.cpp + SimpleColorHueStrategy.cpp + SimpleColorTemperatureStrategy.cpp + StateTransaction.cpp + TimePattern.cpp + UPnP.cpp + Utils.cpp + ZLLSensors.cpp) + +# on windows we want to compile the WinHttpHandler +if(WIN32) + set(hueplusplus_SOURCES + ${hueplusplus_SOURCES} + WinHttpHandler.cpp + ) +endif() +# whereas on linux we want the LinHttpHandler +if(UNIX) + set(hueplusplus_SOURCES + ${hueplusplus_SOURCES} + LinHttpHandler.cpp + ) +endif() +if(ESP_PLATFORM) + set(hueplusplus_SOURCES + ${hueplusplus_SOURCES} + LinHttpHandler.cpp + ) +endif() + +# append current source dir before files +foreach(src ${hueplusplus_SOURCES}) + list(APPEND _srcList "${CMAKE_CURRENT_SOURCE_DIR}/${src}") +endforeach() +set(hueplusplus_SOURCES ${_srcList} PARENT_SCOPE) + +# For install dir variables +include(GNUInstallDirs) + +# hueplusplus shared library +add_library(hueplusplusshared SHARED ${hueplusplus_SOURCES}) +target_link_libraries(hueplusplusshared PRIVATE MbedTLS::mbedtls) +target_link_libraries(hueplusplusshared PUBLIC nlohmann_json::nlohmann_json) +target_compile_features(hueplusplusshared PUBLIC cxx_std_14) +target_include_directories(hueplusplusshared PUBLIC $ $) + + +# hueplusplus static library +add_library(hueplusplusstatic STATIC ${hueplusplus_SOURCES}) +target_link_libraries(hueplusplusstatic PRIVATE MbedTLS::mbedtls) +target_link_libraries(hueplusplusstatic PUBLIC nlohmann_json::nlohmann_json) +target_compile_features(hueplusplusstatic PUBLIC cxx_std_14) +if(NOT WIN32) + # On windows, a shared library will also generate a .lib import library, making different names necessary. + # On other platforms the file endings are different, so the names can be the same. + set_target_properties(hueplusplusshared PROPERTIES OUTPUT_NAME hueplusplus SOVERSION 1) + set_target_properties(hueplusplusstatic PROPERTIES OUTPUT_NAME hueplusplus) +endif() + +install(TARGETS hueplusplusshared DESTINATION ${CMAKE_INSTALL_LIBDIR}) +install(TARGETS hueplusplusstatic DESTINATION ${CMAKE_INSTALL_LIBDIR}) +target_include_directories(hueplusplusstatic PUBLIC $ $) +install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +# Export the package for use from the build-tree +# (this registers the build-tree with a global CMake-registry) +export(PACKAGE hueplusplus) +# Create the hueplusplus-config.cmake +configure_file ("${PROJECT_SOURCE_DIR}/cmake/hueplusplus-config.cmake.in" "${hueplusplus_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hueplusplus-config.cmake" @ONLY) +# Install hueplusplus-config.cmake +install(FILES "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hueplusplus-config.cmake" DESTINATION "${INSTALL_CMAKE_DIR}" COMPONENT dev) diff --git a/dependencies/hueplusplus-1.0.0/src/ColorUnits.cpp b/dependencies/hueplusplus-1.2.0/src/ColorUnits.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/ColorUnits.cpp rename to dependencies/hueplusplus-1.2.0/src/ColorUnits.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/EntertainmentMode.cpp b/dependencies/hueplusplus-1.2.0/src/EntertainmentMode.cpp similarity index 95% rename from dependencies/hueplusplus-1.0.0/src/EntertainmentMode.cpp rename to dependencies/hueplusplus-1.2.0/src/EntertainmentMode.cpp index c9af1510..9a1a6128 100644 --- a/dependencies/hueplusplus-1.0.0/src/EntertainmentMode.cpp +++ b/dependencies/hueplusplus-1.2.0/src/EntertainmentMode.cpp @@ -29,6 +29,8 @@ #include "mbedtls/ssl.h" #include "mbedtls/timing.h" +#include "hueplusplus/HueExceptionMacro.h" + namespace hueplusplus { constexpr uint8_t HUE_ENTERTAINMENT_HEADER_SIZE = 16; @@ -120,13 +122,16 @@ EntertainmentMode::EntertainmentMode(Bridge& b, Group& g) /*-------------------------------------------------*\ | Seed the Deterministic Random Bit Generator (RNG) | \*-------------------------------------------------*/ - int ret = mbedtls_ctr_drbg_seed(&tls_context->ctr_drbg, mbedtls_entropy_func, &tls_context->entropy, NULL, 0); - - /*-------------------------------------------------*\ - | Parse certificate | - \*-------------------------------------------------*/ - //ret = mbedtls_x509_crt_parse( - // &tls_context->cacert, (const unsigned char*)mbedtls_test_cas_pem, mbedtls_test_cas_pem_len); + if (mbedtls_ctr_drbg_seed(&tls_context->ctr_drbg, mbedtls_entropy_func, &tls_context->entropy, NULL, 0) != 0) + { + mbedtls_entropy_free(&tls_context->entropy); + mbedtls_ctr_drbg_free(&tls_context->ctr_drbg); + mbedtls_x509_crt_free(&tls_context->cacert); + mbedtls_ssl_config_free(&tls_context->conf); + mbedtls_ssl_free(&tls_context->ssl); + mbedtls_net_free(&tls_context->server_fd); + throw HueException(CURRENT_FILE_INFO, "Failed to seed mbedtls RNG"); + } } EntertainmentMode::~EntertainmentMode() diff --git a/dependencies/hueplusplus-1.0.0/src/ExtendedColorHueStrategy.cpp b/dependencies/hueplusplus-1.2.0/src/ExtendedColorHueStrategy.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/ExtendedColorHueStrategy.cpp rename to dependencies/hueplusplus-1.2.0/src/ExtendedColorHueStrategy.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/ExtendedColorTemperatureStrategy.cpp b/dependencies/hueplusplus-1.2.0/src/ExtendedColorTemperatureStrategy.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/ExtendedColorTemperatureStrategy.cpp rename to dependencies/hueplusplus-1.2.0/src/ExtendedColorTemperatureStrategy.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/Group.cpp b/dependencies/hueplusplus-1.2.0/src/Group.cpp similarity index 99% rename from dependencies/hueplusplus-1.0.0/src/Group.cpp rename to dependencies/hueplusplus-1.2.0/src/Group.cpp index 74c50b6c..86f82d72 100644 --- a/dependencies/hueplusplus-1.0.0/src/Group.cpp +++ b/dependencies/hueplusplus-1.2.0/src/Group.cpp @@ -267,10 +267,7 @@ nlohmann::json CreateGroup::getRequest() const { result["name"] = name; } - if (!roomType.empty()) - { - result["class"] = roomType; - } + result["class"] = roomType.empty() ? "Other" : roomType; return result; } diff --git a/dependencies/hueplusplus-1.0.0/src/HueCommandAPI.cpp b/dependencies/hueplusplus-1.2.0/src/HueCommandAPI.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/HueCommandAPI.cpp rename to dependencies/hueplusplus-1.2.0/src/HueCommandAPI.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/HueDeviceTypes.cpp b/dependencies/hueplusplus-1.2.0/src/HueDeviceTypes.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/HueDeviceTypes.cpp rename to dependencies/hueplusplus-1.2.0/src/HueDeviceTypes.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/HueException.cpp b/dependencies/hueplusplus-1.2.0/src/HueException.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/HueException.cpp rename to dependencies/hueplusplus-1.2.0/src/HueException.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/Light.cpp b/dependencies/hueplusplus-1.2.0/src/Light.cpp similarity index 99% rename from dependencies/hueplusplus-1.0.0/src/Light.cpp rename to dependencies/hueplusplus-1.2.0/src/Light.cpp index 47f3403d..8754f35b 100644 --- a/dependencies/hueplusplus-1.0.0/src/Light.cpp +++ b/dependencies/hueplusplus-1.2.0/src/Light.cpp @@ -27,7 +27,7 @@ #include "hueplusplus/HueExceptionMacro.h" #include "hueplusplus/Light.h" #include "hueplusplus/Utils.h" -#include "json/json.hpp" +#include namespace hueplusplus { diff --git a/dependencies/hueplusplus-1.0.0/src/LinHttpHandler.cpp b/dependencies/hueplusplus-1.2.0/src/LinHttpHandler.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/LinHttpHandler.cpp rename to dependencies/hueplusplus-1.2.0/src/LinHttpHandler.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/ModelPictures.cpp b/dependencies/hueplusplus-1.2.0/src/ModelPictures.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/ModelPictures.cpp rename to dependencies/hueplusplus-1.2.0/src/ModelPictures.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/NewDeviceList.cpp b/dependencies/hueplusplus-1.2.0/src/NewDeviceList.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/NewDeviceList.cpp rename to dependencies/hueplusplus-1.2.0/src/NewDeviceList.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/Rule.cpp b/dependencies/hueplusplus-1.2.0/src/Rule.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/Rule.cpp rename to dependencies/hueplusplus-1.2.0/src/Rule.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/Scene.cpp b/dependencies/hueplusplus-1.2.0/src/Scene.cpp similarity index 99% rename from dependencies/hueplusplus-1.0.0/src/Scene.cpp rename to dependencies/hueplusplus-1.2.0/src/Scene.cpp index a993a401..cef82e30 100644 --- a/dependencies/hueplusplus-1.0.0/src/Scene.cpp +++ b/dependencies/hueplusplus-1.2.0/src/Scene.cpp @@ -369,7 +369,7 @@ CreateScene& CreateScene::setLightIds(const std::vector& ids) CreateScene& CreateScene::setRecycle(bool recycle) { - request["recycle"] = true; + request["recycle"] = recycle; return *this; } diff --git a/dependencies/hueplusplus-1.0.0/src/Schedule.cpp b/dependencies/hueplusplus-1.2.0/src/Schedule.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/Schedule.cpp rename to dependencies/hueplusplus-1.2.0/src/Schedule.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/Sensor.cpp b/dependencies/hueplusplus-1.2.0/src/Sensor.cpp similarity index 99% rename from dependencies/hueplusplus-1.0.0/src/Sensor.cpp rename to dependencies/hueplusplus-1.2.0/src/Sensor.cpp index fc745401..f933f831 100644 --- a/dependencies/hueplusplus-1.0.0/src/Sensor.cpp +++ b/dependencies/hueplusplus-1.2.0/src/Sensor.cpp @@ -23,7 +23,7 @@ #include "hueplusplus/HueExceptionMacro.h" #include "hueplusplus/Utils.h" -#include "json/json.hpp" +#include namespace hueplusplus { diff --git a/dependencies/hueplusplus-1.0.0/src/SimpleBrightnessStrategy.cpp b/dependencies/hueplusplus-1.2.0/src/SimpleBrightnessStrategy.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/SimpleBrightnessStrategy.cpp rename to dependencies/hueplusplus-1.2.0/src/SimpleBrightnessStrategy.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/SimpleColorHueStrategy.cpp b/dependencies/hueplusplus-1.2.0/src/SimpleColorHueStrategy.cpp similarity index 99% rename from dependencies/hueplusplus-1.0.0/src/SimpleColorHueStrategy.cpp rename to dependencies/hueplusplus-1.2.0/src/SimpleColorHueStrategy.cpp index 25294f94..8de41aea 100644 --- a/dependencies/hueplusplus-1.0.0/src/SimpleColorHueStrategy.cpp +++ b/dependencies/hueplusplus-1.2.0/src/SimpleColorHueStrategy.cpp @@ -55,7 +55,7 @@ bool SimpleColorHueStrategy::setColorXY(const XYBrightness& xy, uint8_t transiti bool SimpleColorHueStrategy::setColorLoop(bool on, Light& light) const { - return light.transaction().setColorLoop(true).commit(); + return light.transaction().setColorLoop(on).commit(); } bool SimpleColorHueStrategy::alertHueSaturation(const HueSaturation& hueSat, Light& light) const diff --git a/dependencies/hueplusplus-1.0.0/src/SimpleColorTemperatureStrategy.cpp b/dependencies/hueplusplus-1.2.0/src/SimpleColorTemperatureStrategy.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/SimpleColorTemperatureStrategy.cpp rename to dependencies/hueplusplus-1.2.0/src/SimpleColorTemperatureStrategy.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/StateTransaction.cpp b/dependencies/hueplusplus-1.2.0/src/StateTransaction.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/StateTransaction.cpp rename to dependencies/hueplusplus-1.2.0/src/StateTransaction.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/TimePattern.cpp b/dependencies/hueplusplus-1.2.0/src/TimePattern.cpp similarity index 97% rename from dependencies/hueplusplus-1.0.0/src/TimePattern.cpp rename to dependencies/hueplusplus-1.2.0/src/TimePattern.cpp index be9ef870..16ea8e4b 100644 --- a/dependencies/hueplusplus-1.0.0/src/TimePattern.cpp +++ b/dependencies/hueplusplus-1.2.0/src/TimePattern.cpp @@ -130,14 +130,14 @@ std::string durationTo_hh_mm_ss(std::chrono::system_clock::duration duration) { throw HueException(CURRENT_FILE_INFO, "Duration parameter longer than 1 day"); } - int numH = static_cast(duration_cast(duration).count()); + unsigned int numH = static_cast(duration_cast(duration).count()); duration -= hours(numH); - int numM = static_cast(duration_cast(duration).count()); + unsigned int numM = static_cast(duration_cast(duration).count()); duration -= minutes(numM); - int numS = static_cast(duration_cast(duration).count()); + unsigned int numS = static_cast(duration_cast(duration).count()); char result[9]; - std::sprintf(result, "%02d:%02d:%02d", numH, numM, numS); + std::snprintf(result, 9, "%02u:%02u:%02u", numH, numM, numS); return std::string(result); } diff --git a/dependencies/hueplusplus-1.0.0/src/UPnP.cpp b/dependencies/hueplusplus-1.2.0/src/UPnP.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/UPnP.cpp rename to dependencies/hueplusplus-1.2.0/src/UPnP.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/Utils.cpp b/dependencies/hueplusplus-1.2.0/src/Utils.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/Utils.cpp rename to dependencies/hueplusplus-1.2.0/src/Utils.cpp diff --git a/dependencies/hueplusplus-1.0.0/src/WinHttpHandler.cpp b/dependencies/hueplusplus-1.2.0/src/WinHttpHandler.cpp similarity index 94% rename from dependencies/hueplusplus-1.0.0/src/WinHttpHandler.cpp rename to dependencies/hueplusplus-1.2.0/src/WinHttpHandler.cpp index 6a4aaa07..23f0b346 100644 --- a/dependencies/hueplusplus-1.0.0/src/WinHttpHandler.cpp +++ b/dependencies/hueplusplus-1.2.0/src/WinHttpHandler.cpp @@ -39,7 +39,7 @@ namespace class AddrInfoFreer { public: - explicit AddrInfoFreer(addrinfo* p) : p(p) {} + explicit AddrInfoFreer(addrinfo* p) : p(p) { } ~AddrInfoFreer() { freeaddrinfo(p); } private: @@ -48,7 +48,7 @@ private: class SocketCloser { public: - explicit SocketCloser(SOCKET s) : s(s) {} + explicit SocketCloser(SOCKET s) : s(s) { } ~SocketCloser() { closesocket(s); } private: @@ -135,15 +135,6 @@ std::string WinHttpHandler::send(const std::string& msg, const std::string& adr, throw(std::system_error(err, std::system_category(), "WinHttpHandler: send failed")); } - // shutdown the connection for sending since no more data will be sent - // the client can still use the ConnectSocket for receiving data - //if (shutdown(connect_socket, SD_SEND) == SOCKET_ERROR) - //{ - // int err = WSAGetLastError(); - // std::cerr << "WinHttpHandler: shutdown failed: " << err << std::endl; - // throw(std::system_error(err, std::system_category(), "WinHttpHandler: shutdown failed")); - //} - const int recvbuflen = 128; char recvbuf[recvbuflen]; @@ -170,6 +161,14 @@ std::string WinHttpHandler::send(const std::string& msg, const std::string& adr, } } while (res > 0); + // shutdown the connection + if (shutdown(connect_socket, SD_BOTH) == SOCKET_ERROR) + { + int err = WSAGetLastError(); + std::cerr << "WinHttpHandler: shutdown failed: " << err << std::endl; + throw(std::system_error(err, std::system_category(), "WinHttpHandler: shutdown failed")); + } + return response; } @@ -250,7 +249,7 @@ std::vector WinHttpHandler::sendMulticast( } // shutdown the connection for sending since no more data will be sent - // the client can still use the ConnectSocket for receiving data + // the client can still use the ConnectSocket for receiving data (no issue here because this is a UDP socket) if (shutdown(connect_socket, SD_SEND) == SOCKET_ERROR) { int err = WSAGetLastError(); diff --git a/dependencies/hueplusplus-1.0.0/src/ZLLSensors.cpp b/dependencies/hueplusplus-1.2.0/src/ZLLSensors.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/src/ZLLSensors.cpp rename to dependencies/hueplusplus-1.2.0/src/ZLLSensors.cpp diff --git a/dependencies/hueplusplus-1.2.0/test/CMakeLists.txt b/dependencies/hueplusplus-1.2.0/test/CMakeLists.txt new file mode 100644 index 00000000..9ee717c2 --- /dev/null +++ b/dependencies/hueplusplus-1.2.0/test/CMakeLists.txt @@ -0,0 +1,132 @@ +if(NOT hueplusplus_NO_EXTERNAL_LIBRARIES) + find_package(GTest) + find_package(GMock) +endif() + +if(NOT GTest_FOUND OR NOT GMock_FOUND) + # Download and unpack googletest at configure time + configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt) + execute_process(COMMAND ${CMAKE_COMMAND} -G ${CMAKE_GENERATOR} . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/googletest-download" + ) + if(result) + message(FATAL_ERROR "CMake step for googletest failed: ${result}") + endif() + execute_process(COMMAND "${CMAKE_COMMAND}" --build . + RESULT_VARIABLE result + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/googletest-download" + ) + if(result) + message(FATAL_ERROR "Build step for googletest failed: ${result}") + endif() + + # Prevent overriding the parent project's compiler/linker + # settings on Windows + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + + # Add googletest directly to our build. This defines + # the gtest and gtest_main targets. + add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src EXCLUDE_FROM_ALL + ${CMAKE_CURRENT_BINARY_DIR}/googletest-build EXCLUDE_FROM_ALL + ) + target_compile_features(gmock PUBLIC cxx_std_14) + target_compile_features(gtest PUBLIC cxx_std_14) +endif() + + +# define all test sources +set(TEST_SOURCES + test_Action.cpp + test_APICache.cpp + test_BaseDevice.cpp + test_BaseHttpHandler.cpp + test_Bridge.cpp + test_BridgeConfig.cpp + test_SensorImpls.cpp + test_ColorUnits.cpp + test_ExtendedColorHueStrategy.cpp + test_ExtendedColorTemperatureStrategy.cpp + test_Group.cpp + test_HueCommandAPI.cpp + test_Light.cpp + test_LightFactory.cpp + test_Main.cpp + test_NewDeviceList.cpp + test_UPnP.cpp + test_ResourceList.cpp + test_Rule.cpp + test_Scene.cpp + test_Schedule.cpp + test_Sensor.cpp + test_SensorList.cpp + test_SimpleBrightnessStrategy.cpp + test_SimpleColorHueStrategy.cpp + test_SimpleColorTemperatureStrategy.cpp + test_StateTransaction.cpp + test_TimePattern.cpp) + +set(HuePlusPlus_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/include") + +# test executable +add_executable(test_HuePlusPlus ${TEST_SOURCES}) +#if(DO_CLANG_TIDY) +# set_target_properties(test_HuePlusPlus PROPERTIES CXX_CLANG_TIDY ${DO_CLANG_TIDY}) +#endif() +target_compile_features(test_HuePlusPlus PUBLIC cxx_std_14) +set_property(TARGET test_HuePlusPlus PROPERTY CXX_EXTENSIONS OFF) + +target_link_libraries(test_HuePlusPlus PUBLIC hueplusplusstatic) +target_link_libraries(test_HuePlusPlus PUBLIC gtest gmock) +target_include_directories(test_HuePlusPlus PUBLIC ${GTest_INCLUDE_DIRS}) +# add custom target to make it simple to run the tests +add_custom_target("unittest" + # Run the executable + COMMAND test_HuePlusPlus + # Depends on test_HuePlusPlus + DEPENDS test_HuePlusPlus +) + +# Check for coverage test prerequisites +find_program( GCOV_PATH gcov ) +find_program( LCOV_PATH lcov ) + +mark_as_advanced(GCOV_PATH) +mark_as_advanced(LCOV_PATH) + +if(LCOV_PATH AND GCOV_PATH) + # GCov + include(CodeCoverage.cmake) + add_executable(testcov_HuePlusPlus ${TEST_SOURCES} ${hueplusplus_SOURCES}) + target_include_directories(testcov_HuePlusPlus PUBLIC "${PROJECT_SOURCE_DIR}/include") + target_compile_features(testcov_HuePlusPlus PUBLIC cxx_std_14) + set_property(TARGET testcov_HuePlusPlus PROPERTY CXX_EXTENSIONS OFF) + + target_link_libraries(testcov_HuePlusPlus PRIVATE mbedtls) + target_link_libraries(testcov_HuePlusPlus PUBLIC nlohmann_json::nlohmann_json gtest gmock) + target_include_directories(testcov_HuePlusPlus PUBLIC ${GTest_INCLUDE_DIRS}) + # this will be already done by APPEND_COVERAGE_COMPILER_FLAGS() + #set_target_properties( + # testcov_HuePlusPlus PROPERTIES + # COMPILE_FLAGS "-O0 -g -fprofile-arcs -ftest-coverage" + #) + # Normally this would be -lgcov, but on mac only -Lgcov works + #set_target_properties( + # testcov_HuePlusPlus PROPERTIES + # LINK_FLAGS "-O0 -g -Lgcov -fprofile-arcs -ftest-coverage" + #) + # exclude some special files we do not want to profile + set(COVERAGE_EXCLUDES + '/usr/*' # unix + '*/hueplusplus/build/*' + '*/json*' + '*/test/*' + '*/v1/*' # iOS + ) + APPEND_COVERAGE_COMPILER_FLAGS() + SETUP_TARGET_FOR_COVERAGE( + NAME "coveragetest" + EXECUTABLE testcov_HuePlusPlus + DEPENDENCIES testcov_HuePlusPlus + ) +endif() diff --git a/dependencies/hueplusplus-1.0.0/test/CMakeLists.txt.in b/dependencies/hueplusplus-1.2.0/test/CMakeLists.txt.in similarity index 93% rename from dependencies/hueplusplus-1.0.0/test/CMakeLists.txt.in rename to dependencies/hueplusplus-1.2.0/test/CMakeLists.txt.in index c6247af5..37b622bf 100644 --- a/dependencies/hueplusplus-1.0.0/test/CMakeLists.txt.in +++ b/dependencies/hueplusplus-1.2.0/test/CMakeLists.txt.in @@ -5,7 +5,7 @@ project(googletest-download NONE) include(ExternalProject) ExternalProject_Add(googletest GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG master + GIT_TAG main SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src" BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build" CONFIGURE_COMMAND "" diff --git a/dependencies/hueplusplus-1.0.0/test/CodeCoverage.cmake b/dependencies/hueplusplus-1.2.0/test/CodeCoverage.cmake similarity index 98% rename from dependencies/hueplusplus-1.0.0/test/CodeCoverage.cmake rename to dependencies/hueplusplus-1.2.0/test/CodeCoverage.cmake index 8971d78c..57c01953 100644 --- a/dependencies/hueplusplus-1.0.0/test/CodeCoverage.cmake +++ b/dependencies/hueplusplus-1.2.0/test/CodeCoverage.cmake @@ -157,8 +157,8 @@ function(SETUP_TARGET_FOR_COVERAGE) COMMAND ${Coverage_EXECUTABLE} # Capturing lcov counters and generating report - COMMAND ${LCOV_PATH} --directory . --capture --output-file ${Coverage_NAME}.info - COMMAND ${LCOV_PATH} --remove ${Coverage_NAME}.info ${COVERAGE_EXCLUDES} --output-file ${Coverage_NAME}.info.cleaned + COMMAND ${LCOV_PATH} --directory . --capture --output-file ${Coverage_NAME}.info --ignore-errors mismatch + COMMAND ${LCOV_PATH} --remove ${Coverage_NAME}.info ${COVERAGE_EXCLUDES} --output-file ${Coverage_NAME}.info.cleaned --ignore-errors unused COMMAND ${GENHTML_PATH} -o ${Coverage_NAME} ${Coverage_NAME}.info.cleaned COMMAND ${CMAKE_COMMAND} -E remove ${Coverage_NAME}.info ${Coverage_NAME}.info.cleaned diff --git a/dependencies/hueplusplus-1.0.0/test/TestTransaction.h b/dependencies/hueplusplus-1.2.0/test/TestTransaction.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/TestTransaction.h rename to dependencies/hueplusplus-1.2.0/test/TestTransaction.h diff --git a/dependencies/hueplusplus-1.0.0/test/mocks/mock_BaseHttpHandler.h b/dependencies/hueplusplus-1.2.0/test/mocks/mock_BaseHttpHandler.h similarity index 98% rename from dependencies/hueplusplus-1.0.0/test/mocks/mock_BaseHttpHandler.h rename to dependencies/hueplusplus-1.2.0/test/mocks/mock_BaseHttpHandler.h index f38f1c57..517f73b5 100644 --- a/dependencies/hueplusplus-1.0.0/test/mocks/mock_BaseHttpHandler.h +++ b/dependencies/hueplusplus-1.2.0/test/mocks/mock_BaseHttpHandler.h @@ -29,7 +29,7 @@ #include #include "hueplusplus/BaseHttpHandler.h" -#include "json/json.hpp" +#include //! Mock Class class MockBaseHttpHandler : public hueplusplus::BaseHttpHandler diff --git a/dependencies/hueplusplus-1.0.0/test/mocks/mock_HttpHandler.h b/dependencies/hueplusplus-1.2.0/test/mocks/mock_HttpHandler.h similarity index 99% rename from dependencies/hueplusplus-1.0.0/test/mocks/mock_HttpHandler.h rename to dependencies/hueplusplus-1.2.0/test/mocks/mock_HttpHandler.h index 40263752..1730c7db 100644 --- a/dependencies/hueplusplus-1.0.0/test/mocks/mock_HttpHandler.h +++ b/dependencies/hueplusplus-1.2.0/test/mocks/mock_HttpHandler.h @@ -29,7 +29,7 @@ #include #include "hueplusplus/IHttpHandler.h" -#include "json/json.hpp" +#include //! Mock Class class MockHttpHandler : public hueplusplus::IHttpHandler diff --git a/dependencies/hueplusplus-1.0.0/test/mocks/mock_Light.h b/dependencies/hueplusplus-1.2.0/test/mocks/mock_Light.h similarity index 99% rename from dependencies/hueplusplus-1.0.0/test/mocks/mock_Light.h rename to dependencies/hueplusplus-1.2.0/test/mocks/mock_Light.h index a44656be..40b0cf6b 100644 --- a/dependencies/hueplusplus-1.0.0/test/mocks/mock_Light.h +++ b/dependencies/hueplusplus-1.2.0/test/mocks/mock_Light.h @@ -30,7 +30,7 @@ #include "../testhelper.h" #include "hueplusplus/Light.h" -#include "json/json.hpp" +#include //! Mock Class class MockLight : public hueplusplus::Light diff --git a/dependencies/hueplusplus-1.0.0/test/test_APICache.cpp b/dependencies/hueplusplus-1.2.0/test/test_APICache.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/test_APICache.cpp rename to dependencies/hueplusplus-1.2.0/test/test_APICache.cpp diff --git a/dependencies/hueplusplus-1.0.0/test/test_Action.cpp b/dependencies/hueplusplus-1.2.0/test/test_Action.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/test_Action.cpp rename to dependencies/hueplusplus-1.2.0/test/test_Action.cpp diff --git a/dependencies/hueplusplus-1.0.0/test/test_BaseDevice.cpp b/dependencies/hueplusplus-1.2.0/test/test_BaseDevice.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/test_BaseDevice.cpp rename to dependencies/hueplusplus-1.2.0/test/test_BaseDevice.cpp diff --git a/dependencies/hueplusplus-1.0.0/test/test_BaseHttpHandler.cpp b/dependencies/hueplusplus-1.2.0/test/test_BaseHttpHandler.cpp similarity index 99% rename from dependencies/hueplusplus-1.0.0/test/test_BaseHttpHandler.cpp rename to dependencies/hueplusplus-1.2.0/test/test_BaseHttpHandler.cpp index 28868f5b..1b6e2eaf 100644 --- a/dependencies/hueplusplus-1.0.0/test/test_BaseHttpHandler.cpp +++ b/dependencies/hueplusplus-1.2.0/test/test_BaseHttpHandler.cpp @@ -29,7 +29,7 @@ #include "testhelper.h" #include "hueplusplus/HueException.h" -#include "json/json.hpp" +#include #include "mocks/mock_BaseHttpHandler.h" using namespace hueplusplus; diff --git a/dependencies/hueplusplus-1.0.0/test/test_Bridge.cpp b/dependencies/hueplusplus-1.2.0/test/test_Bridge.cpp similarity index 99% rename from dependencies/hueplusplus-1.0.0/test/test_Bridge.cpp rename to dependencies/hueplusplus-1.2.0/test/test_Bridge.cpp index bd24ac96..6eba641e 100644 --- a/dependencies/hueplusplus-1.0.0/test/test_Bridge.cpp +++ b/dependencies/hueplusplus-1.2.0/test/test_Bridge.cpp @@ -30,7 +30,7 @@ #include "hueplusplus/Bridge.h" #include "hueplusplus/LibConfig.h" -#include "json/json.hpp" +#include #include "mocks/mock_HttpHandler.h" using namespace hueplusplus; diff --git a/dependencies/hueplusplus-1.0.0/test/test_BridgeConfig.cpp b/dependencies/hueplusplus-1.2.0/test/test_BridgeConfig.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/test_BridgeConfig.cpp rename to dependencies/hueplusplus-1.2.0/test/test_BridgeConfig.cpp diff --git a/dependencies/hueplusplus-1.0.0/test/test_ColorUnits.cpp b/dependencies/hueplusplus-1.2.0/test/test_ColorUnits.cpp similarity index 97% rename from dependencies/hueplusplus-1.0.0/test/test_ColorUnits.cpp rename to dependencies/hueplusplus-1.2.0/test/test_ColorUnits.cpp index bd81f1f3..9b55e501 100644 --- a/dependencies/hueplusplus-1.0.0/test/test_ColorUnits.cpp +++ b/dependencies/hueplusplus-1.2.0/test/test_ColorUnits.cpp @@ -125,7 +125,7 @@ TEST(RGB, toHueSaturation) EXPECT_EQ(254, hs.saturation); } { - const RGB darkGreen{64, 128, 128 }; + const RGB darkGreen {64, 128, 128}; HueSaturation hs = darkGreen.toHueSaturation(); EXPECT_EQ(38250, hs.hue); EXPECT_EQ(127, hs.saturation); @@ -192,7 +192,8 @@ TEST(RGB, fromXY) int maxDiffB = 0; for (int i = 0; i < N; ++i) { - const RGB rgb {dist(rng), dist(rng), dist(rng)}; + const RGB rgb { + static_cast(dist(rng)), static_cast(dist(rng)), static_cast(dist(rng))}; const XYBrightness xy = rgb.toXY(); const RGB back = RGB::fromXY(xy); int diffR = (rgb.r - back.r) * (rgb.r - back.r); diff --git a/dependencies/hueplusplus-1.0.0/test/test_ExtendedColorHueStrategy.cpp b/dependencies/hueplusplus-1.2.0/test/test_ExtendedColorHueStrategy.cpp similarity index 99% rename from dependencies/hueplusplus-1.0.0/test/test_ExtendedColorHueStrategy.cpp rename to dependencies/hueplusplus-1.2.0/test/test_ExtendedColorHueStrategy.cpp index 886e35d2..cbd61927 100644 --- a/dependencies/hueplusplus-1.0.0/test/test_ExtendedColorHueStrategy.cpp +++ b/dependencies/hueplusplus-1.2.0/test/test_ExtendedColorHueStrategy.cpp @@ -30,7 +30,7 @@ #include "testhelper.h" #include "hueplusplus/ExtendedColorHueStrategy.h" -#include "json/json.hpp" +#include #include "mocks/mock_HttpHandler.h" #include "mocks/mock_Light.h" diff --git a/dependencies/hueplusplus-1.0.0/test/test_ExtendedColorTemperatureStrategy.cpp b/dependencies/hueplusplus-1.2.0/test/test_ExtendedColorTemperatureStrategy.cpp similarity index 99% rename from dependencies/hueplusplus-1.0.0/test/test_ExtendedColorTemperatureStrategy.cpp rename to dependencies/hueplusplus-1.2.0/test/test_ExtendedColorTemperatureStrategy.cpp index 4ed85d0d..a9d0d896 100644 --- a/dependencies/hueplusplus-1.0.0/test/test_ExtendedColorTemperatureStrategy.cpp +++ b/dependencies/hueplusplus-1.2.0/test/test_ExtendedColorTemperatureStrategy.cpp @@ -30,7 +30,7 @@ #include "testhelper.h" #include "hueplusplus/ExtendedColorTemperatureStrategy.h" -#include "json/json.hpp" +#include #include "mocks/mock_HttpHandler.h" #include "mocks/mock_Light.h" diff --git a/dependencies/hueplusplus-1.0.0/test/test_Group.cpp b/dependencies/hueplusplus-1.2.0/test/test_Group.cpp similarity index 94% rename from dependencies/hueplusplus-1.0.0/test/test_Group.cpp rename to dependencies/hueplusplus-1.2.0/test/test_Group.cpp index 4bd43ea8..d0fcfac9 100644 --- a/dependencies/hueplusplus-1.0.0/test/test_Group.cpp +++ b/dependencies/hueplusplus-1.2.0/test/test_Group.cpp @@ -268,32 +268,34 @@ TEST_F(GroupTest, createSceneAction) TEST(CreateGroup, LightGroup) { - EXPECT_EQ(nlohmann::json({{"lights", {"1"}}, {"type", "LightGroup"}, {"name", "Name"}}), + EXPECT_EQ(nlohmann::json({{"lights", {"1"}}, {"type", "LightGroup"}, {"name", "Name"}, {"class", "Other"}}), CreateGroup::LightGroup({1}, "Name").getRequest()); - EXPECT_EQ( - nlohmann::json({{"lights", {"2", "4"}}, {"type", "LightGroup"}}), CreateGroup::LightGroup({2, 4}).getRequest()); + EXPECT_EQ(nlohmann::json({{"lights", {"2", "4"}}, {"type", "LightGroup"}, {"class", "Other"}}), + CreateGroup::LightGroup({2, 4}).getRequest()); } TEST(CreateGroup, Entertainment) { - EXPECT_EQ(nlohmann::json({{"lights", {"1"}}, {"type", "Entertainment"}, {"name", "Name"}}), + EXPECT_EQ(nlohmann::json({{"lights", {"1"}}, {"type", "Entertainment"}, {"name", "Name"}, {"class", "Other"}}), CreateGroup::Entertainment({1}, "Name").getRequest()); - EXPECT_EQ(nlohmann::json({{"lights", {"2", "4"}}, {"type", "Entertainment"}}), + EXPECT_EQ(nlohmann::json({{"lights", {"2", "4"}}, {"type", "Entertainment"}, {"class", "Other"}}), CreateGroup::Entertainment({2, 4}).getRequest()); } TEST(CreateGroup, Zone) { - EXPECT_EQ(nlohmann::json({{"lights", {"1"}}, {"type", "Zone"}, {"name", "Name"}}), + EXPECT_EQ(nlohmann::json({{"lights", {"1"}}, {"type", "Zone"}, {"name", "Name"}, {"class", "Other"}}), CreateGroup::Zone({1}, "Name").getRequest()); - EXPECT_EQ(nlohmann::json({{"lights", {"2", "4"}}, {"type", "Zone"}}), CreateGroup::Zone({2, 4}).getRequest()); + EXPECT_EQ(nlohmann::json({{"lights", {"2", "4"}}, {"type", "Zone"}, {"class", "Other"}}), + CreateGroup::Zone({2, 4}).getRequest()); } TEST(CreateGroup, Room) { EXPECT_EQ(nlohmann::json({{"lights", {"1"}}, {"type", "Room"}, {"name", "Name"}, {"class", "Bedroom"}}), CreateGroup::Room({1}, "Name", "Bedroom").getRequest()); - EXPECT_EQ(nlohmann::json({{"lights", {"1"}}, {"type", "Room"}, {"name", "Name"}}), + EXPECT_EQ(nlohmann::json({{"lights", {"1"}}, {"type", "Room"}, {"name", "Name"}, {"class", "Other"}}), CreateGroup::Room({1}, "Name").getRequest()); - EXPECT_EQ(nlohmann::json({{"lights", {"2", "4"}}, {"type", "Room"}}), CreateGroup::Room({2, 4}).getRequest()); -} \ No newline at end of file + EXPECT_EQ(nlohmann::json({{"lights", {"2", "4"}}, {"type", "Room"}, {"class", "Other"}}), + CreateGroup::Room({2, 4}).getRequest()); +} diff --git a/dependencies/hueplusplus-1.0.0/test/test_HueCommandAPI.cpp b/dependencies/hueplusplus-1.2.0/test/test_HueCommandAPI.cpp similarity index 99% rename from dependencies/hueplusplus-1.0.0/test/test_HueCommandAPI.cpp rename to dependencies/hueplusplus-1.2.0/test/test_HueCommandAPI.cpp index 450f527b..a7a02258 100644 --- a/dependencies/hueplusplus-1.0.0/test/test_HueCommandAPI.cpp +++ b/dependencies/hueplusplus-1.2.0/test/test_HueCommandAPI.cpp @@ -26,7 +26,7 @@ #include "testhelper.h" #include "hueplusplus/Bridge.h" -#include "json/json.hpp" +#include #include "mocks/mock_HttpHandler.h" using namespace hueplusplus; diff --git a/dependencies/hueplusplus-1.0.0/test/test_Light.cpp b/dependencies/hueplusplus-1.2.0/test/test_Light.cpp similarity index 99% rename from dependencies/hueplusplus-1.0.0/test/test_Light.cpp rename to dependencies/hueplusplus-1.2.0/test/test_Light.cpp index 8a7c84c7..748e3c61 100644 --- a/dependencies/hueplusplus-1.0.0/test/test_Light.cpp +++ b/dependencies/hueplusplus-1.2.0/test/test_Light.cpp @@ -27,7 +27,7 @@ #include "hueplusplus/Bridge.h" #include "hueplusplus/Light.h" -#include "json/json.hpp" +#include #include "mocks/mock_HttpHandler.h" using namespace hueplusplus; diff --git a/dependencies/hueplusplus-1.0.0/test/test_LightFactory.cpp b/dependencies/hueplusplus-1.2.0/test/test_LightFactory.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/test_LightFactory.cpp rename to dependencies/hueplusplus-1.2.0/test/test_LightFactory.cpp diff --git a/dependencies/hueplusplus-1.0.0/test/test_Main.cpp b/dependencies/hueplusplus-1.2.0/test/test_Main.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/test_Main.cpp rename to dependencies/hueplusplus-1.2.0/test/test_Main.cpp diff --git a/dependencies/hueplusplus-1.0.0/test/test_NewDeviceList.cpp b/dependencies/hueplusplus-1.2.0/test/test_NewDeviceList.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/test_NewDeviceList.cpp rename to dependencies/hueplusplus-1.2.0/test/test_NewDeviceList.cpp diff --git a/dependencies/hueplusplus-1.0.0/test/test_ResourceList.cpp b/dependencies/hueplusplus-1.2.0/test/test_ResourceList.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/test_ResourceList.cpp rename to dependencies/hueplusplus-1.2.0/test/test_ResourceList.cpp diff --git a/dependencies/hueplusplus-1.0.0/test/test_Rule.cpp b/dependencies/hueplusplus-1.2.0/test/test_Rule.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/test_Rule.cpp rename to dependencies/hueplusplus-1.2.0/test/test_Rule.cpp diff --git a/dependencies/hueplusplus-1.0.0/test/test_Scene.cpp b/dependencies/hueplusplus-1.2.0/test/test_Scene.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/test_Scene.cpp rename to dependencies/hueplusplus-1.2.0/test/test_Scene.cpp diff --git a/dependencies/hueplusplus-1.0.0/test/test_Schedule.cpp b/dependencies/hueplusplus-1.2.0/test/test_Schedule.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/test_Schedule.cpp rename to dependencies/hueplusplus-1.2.0/test/test_Schedule.cpp diff --git a/dependencies/hueplusplus-1.0.0/test/test_Sensor.cpp b/dependencies/hueplusplus-1.2.0/test/test_Sensor.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/test_Sensor.cpp rename to dependencies/hueplusplus-1.2.0/test/test_Sensor.cpp diff --git a/dependencies/hueplusplus-1.0.0/test/test_SensorImpls.cpp b/dependencies/hueplusplus-1.2.0/test/test_SensorImpls.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/test_SensorImpls.cpp rename to dependencies/hueplusplus-1.2.0/test/test_SensorImpls.cpp diff --git a/dependencies/hueplusplus-1.0.0/test/test_SensorList.cpp b/dependencies/hueplusplus-1.2.0/test/test_SensorList.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/test_SensorList.cpp rename to dependencies/hueplusplus-1.2.0/test/test_SensorList.cpp diff --git a/dependencies/hueplusplus-1.0.0/test/test_SimpleBrightnessStrategy.cpp b/dependencies/hueplusplus-1.2.0/test/test_SimpleBrightnessStrategy.cpp similarity index 99% rename from dependencies/hueplusplus-1.0.0/test/test_SimpleBrightnessStrategy.cpp rename to dependencies/hueplusplus-1.2.0/test/test_SimpleBrightnessStrategy.cpp index ad29b7a2..94923d8a 100644 --- a/dependencies/hueplusplus-1.0.0/test/test_SimpleBrightnessStrategy.cpp +++ b/dependencies/hueplusplus-1.2.0/test/test_SimpleBrightnessStrategy.cpp @@ -30,7 +30,7 @@ #include "testhelper.h" #include "hueplusplus/SimpleBrightnessStrategy.h" -#include "json/json.hpp" +#include #include "mocks/mock_HttpHandler.h" #include "mocks/mock_Light.h" diff --git a/dependencies/hueplusplus-1.0.0/test/test_SimpleColorHueStrategy.cpp b/dependencies/hueplusplus-1.2.0/test/test_SimpleColorHueStrategy.cpp similarity index 99% rename from dependencies/hueplusplus-1.0.0/test/test_SimpleColorHueStrategy.cpp rename to dependencies/hueplusplus-1.2.0/test/test_SimpleColorHueStrategy.cpp index 0b4f0d66..72ffdd34 100644 --- a/dependencies/hueplusplus-1.0.0/test/test_SimpleColorHueStrategy.cpp +++ b/dependencies/hueplusplus-1.2.0/test/test_SimpleColorHueStrategy.cpp @@ -30,7 +30,7 @@ #include "testhelper.h" #include "hueplusplus/SimpleColorHueStrategy.h" -#include "json/json.hpp" +#include #include "mocks/mock_HttpHandler.h" #include "mocks/mock_Light.h" diff --git a/dependencies/hueplusplus-1.0.0/test/test_SimpleColorTemperatureStrategy.cpp b/dependencies/hueplusplus-1.2.0/test/test_SimpleColorTemperatureStrategy.cpp similarity index 99% rename from dependencies/hueplusplus-1.0.0/test/test_SimpleColorTemperatureStrategy.cpp rename to dependencies/hueplusplus-1.2.0/test/test_SimpleColorTemperatureStrategy.cpp index d97b8ac9..1bb38bf7 100644 --- a/dependencies/hueplusplus-1.0.0/test/test_SimpleColorTemperatureStrategy.cpp +++ b/dependencies/hueplusplus-1.2.0/test/test_SimpleColorTemperatureStrategy.cpp @@ -31,7 +31,7 @@ #include "testhelper.h" #include "hueplusplus/SimpleColorTemperatureStrategy.h" -#include "json/json.hpp" +#include #include "mocks/mock_HttpHandler.h" #include "mocks/mock_Light.h" diff --git a/dependencies/hueplusplus-1.0.0/test/test_StateTransaction.cpp b/dependencies/hueplusplus-1.2.0/test/test_StateTransaction.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/test_StateTransaction.cpp rename to dependencies/hueplusplus-1.2.0/test/test_StateTransaction.cpp diff --git a/dependencies/hueplusplus-1.0.0/test/test_TimePattern.cpp b/dependencies/hueplusplus-1.2.0/test/test_TimePattern.cpp similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/test_TimePattern.cpp rename to dependencies/hueplusplus-1.2.0/test/test_TimePattern.cpp diff --git a/dependencies/hueplusplus-1.0.0/test/test_UPnP.cpp b/dependencies/hueplusplus-1.2.0/test/test_UPnP.cpp similarity index 98% rename from dependencies/hueplusplus-1.0.0/test/test_UPnP.cpp rename to dependencies/hueplusplus-1.2.0/test/test_UPnP.cpp index f17be6c4..af4a0d93 100644 --- a/dependencies/hueplusplus-1.0.0/test/test_UPnP.cpp +++ b/dependencies/hueplusplus-1.2.0/test/test_UPnP.cpp @@ -28,7 +28,7 @@ #include "hueplusplus/LibConfig.h" #include "hueplusplus/UPnP.h" -#include "json/json.hpp" +#include #include "mocks/mock_HttpHandler.h" using namespace hueplusplus; diff --git a/dependencies/hueplusplus-1.0.0/test/testhelper.h b/dependencies/hueplusplus-1.2.0/test/testhelper.h similarity index 100% rename from dependencies/hueplusplus-1.0.0/test/testhelper.h rename to dependencies/hueplusplus-1.2.0/test/testhelper.h diff --git a/dependencies/json/json.hpp b/dependencies/json/json.hpp deleted file mode 100644 index e821c79a..00000000 --- a/dependencies/json/json.hpp +++ /dev/null @@ -1,25533 +0,0 @@ -/* - __ _____ _____ _____ - __| | __| | | | JSON for Modern C++ -| | |__ | | | | | | version 3.9.1 -|_____|_____|_____|_|___| https://github.com/nlohmann/json - -Licensed under the MIT License . -SPDX-License-Identifier: MIT -Copyright (c) 2013-2019 Niels Lohmann . - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -#ifndef INCLUDE_NLOHMANN_JSON_HPP_ -#define INCLUDE_NLOHMANN_JSON_HPP_ - -#define NLOHMANN_JSON_VERSION_MAJOR 3 -#define NLOHMANN_JSON_VERSION_MINOR 9 -#define NLOHMANN_JSON_VERSION_PATCH 1 - -#include // all_of, find, for_each -#include // nullptr_t, ptrdiff_t, size_t -#include // hash, less -#include // initializer_list -#include // istream, ostream -#include // random_access_iterator_tag -#include // unique_ptr -#include // accumulate -#include // string, stoi, to_string -#include // declval, forward, move, pair, swap -#include // vector - -// #include - - -#include - -// #include - - -#include // transform -#include // array -#include // forward_list -#include // inserter, front_inserter, end -#include // map -#include // string -#include // tuple, make_tuple -#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible -#include // unordered_map -#include // pair, declval -#include // valarray - -// #include - - -#include // exception -#include // runtime_error -#include // to_string - -// #include - - -#include // size_t - -namespace nlohmann -{ -namespace detail -{ -/// struct to capture the start position of the current token -struct position_t -{ - /// the total number of characters read - std::size_t chars_read_total = 0; - /// the number of characters read in the current line - std::size_t chars_read_current_line = 0; - /// the number of lines read - std::size_t lines_read = 0; - - /// conversion to size_t to preserve SAX interface - constexpr operator size_t() const - { - return chars_read_total; - } -}; - -} // namespace detail -} // namespace nlohmann - -// #include - - -#include // pair -// #include -/* Hedley - https://nemequ.github.io/hedley - * Created by Evan Nemerson - * - * To the extent possible under law, the author(s) have dedicated all - * copyright and related and neighboring rights to this software to - * the public domain worldwide. This software is distributed without - * any warranty. - * - * For details, see . - * SPDX-License-Identifier: CC0-1.0 - */ - -#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 14) -#if defined(JSON_HEDLEY_VERSION) - #undef JSON_HEDLEY_VERSION -#endif -#define JSON_HEDLEY_VERSION 14 - -#if defined(JSON_HEDLEY_STRINGIFY_EX) - #undef JSON_HEDLEY_STRINGIFY_EX -#endif -#define JSON_HEDLEY_STRINGIFY_EX(x) #x - -#if defined(JSON_HEDLEY_STRINGIFY) - #undef JSON_HEDLEY_STRINGIFY -#endif -#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) - -#if defined(JSON_HEDLEY_CONCAT_EX) - #undef JSON_HEDLEY_CONCAT_EX -#endif -#define JSON_HEDLEY_CONCAT_EX(a,b) a##b - -#if defined(JSON_HEDLEY_CONCAT) - #undef JSON_HEDLEY_CONCAT -#endif -#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) - -#if defined(JSON_HEDLEY_CONCAT3_EX) - #undef JSON_HEDLEY_CONCAT3_EX -#endif -#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c - -#if defined(JSON_HEDLEY_CONCAT3) - #undef JSON_HEDLEY_CONCAT3 -#endif -#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) - -#if defined(JSON_HEDLEY_VERSION_ENCODE) - #undef JSON_HEDLEY_VERSION_ENCODE -#endif -#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) - -#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) - #undef JSON_HEDLEY_VERSION_DECODE_MAJOR -#endif -#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) - -#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) - #undef JSON_HEDLEY_VERSION_DECODE_MINOR -#endif -#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) - -#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) - #undef JSON_HEDLEY_VERSION_DECODE_REVISION -#endif -#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) - -#if defined(JSON_HEDLEY_GNUC_VERSION) - #undef JSON_HEDLEY_GNUC_VERSION -#endif -#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) - #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) -#elif defined(__GNUC__) - #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) -#endif - -#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) - #undef JSON_HEDLEY_GNUC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_GNUC_VERSION) - #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_MSVC_VERSION) - #undef JSON_HEDLEY_MSVC_VERSION -#endif -#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) -#elif defined(_MSC_FULL_VER) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) -#elif defined(_MSC_VER) && !defined(__ICL) - #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) -#endif - -#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) - #undef JSON_HEDLEY_MSVC_VERSION_CHECK -#endif -#if !defined(JSON_HEDLEY_MSVC_VERSION) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) -#elif defined(_MSC_VER) && (_MSC_VER >= 1400) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) -#elif defined(_MSC_VER) && (_MSC_VER >= 1200) - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) -#else - #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) -#endif - -#if defined(JSON_HEDLEY_INTEL_VERSION) - #undef JSON_HEDLEY_INTEL_VERSION -#endif -#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) - #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) -#elif defined(__INTEL_COMPILER) && !defined(__ICL) - #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) -#endif - -#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) - #undef JSON_HEDLEY_INTEL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_INTEL_VERSION) - #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_INTEL_CL_VERSION) - #undef JSON_HEDLEY_INTEL_CL_VERSION -#endif -#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) - #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) -#endif - -#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) - #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_INTEL_CL_VERSION) - #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_PGI_VERSION) - #undef JSON_HEDLEY_PGI_VERSION -#endif -#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) - #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) -#endif - -#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) - #undef JSON_HEDLEY_PGI_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_PGI_VERSION) - #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_SUNPRO_VERSION) - #undef JSON_HEDLEY_SUNPRO_VERSION -#endif -#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) -#elif defined(__SUNPRO_C) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) -#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) -#elif defined(__SUNPRO_CC) - #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) -#endif - -#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) - #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_SUNPRO_VERSION) - #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) - #undef JSON_HEDLEY_EMSCRIPTEN_VERSION -#endif -#if defined(__EMSCRIPTEN__) - #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) -#endif - -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) - #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) - #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_ARM_VERSION) - #undef JSON_HEDLEY_ARM_VERSION -#endif -#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) - #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) -#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) - #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) -#endif - -#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) - #undef JSON_HEDLEY_ARM_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_ARM_VERSION) - #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_IBM_VERSION) - #undef JSON_HEDLEY_IBM_VERSION -#endif -#if defined(__ibmxl__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) -#elif defined(__xlC__) && defined(__xlC_ver__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) -#elif defined(__xlC__) - #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) -#endif - -#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) - #undef JSON_HEDLEY_IBM_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_IBM_VERSION) - #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_VERSION) - #undef JSON_HEDLEY_TI_VERSION -#endif -#if \ - defined(__TI_COMPILER_VERSION__) && \ - ( \ - defined(__TMS470__) || defined(__TI_ARM__) || \ - defined(__MSP430__) || \ - defined(__TMS320C2000__) \ - ) -#if (__TI_COMPILER_VERSION__ >= 16000000) - #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif -#endif - -#if defined(JSON_HEDLEY_TI_VERSION_CHECK) - #undef JSON_HEDLEY_TI_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_VERSION) - #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL2000_VERSION) - #undef JSON_HEDLEY_TI_CL2000_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) - #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL2000_VERSION) - #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL430_VERSION) - #undef JSON_HEDLEY_TI_CL430_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) - #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL430_VERSION) - #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) - #undef JSON_HEDLEY_TI_ARMCL_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) - #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) - #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) - #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL6X_VERSION) - #undef JSON_HEDLEY_TI_CL6X_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) - #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL6X_VERSION) - #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CL7X_VERSION) - #undef JSON_HEDLEY_TI_CL7X_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) - #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CL7X_VERSION) - #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) - #undef JSON_HEDLEY_TI_CLPRU_VERSION -#endif -#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) - #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) -#endif - -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) - #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) - #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_CRAY_VERSION) - #undef JSON_HEDLEY_CRAY_VERSION -#endif -#if defined(_CRAYC) - #if defined(_RELEASE_PATCHLEVEL) - #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) - #else - #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) - #endif -#endif - -#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) - #undef JSON_HEDLEY_CRAY_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_CRAY_VERSION) - #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_IAR_VERSION) - #undef JSON_HEDLEY_IAR_VERSION -#endif -#if defined(__IAR_SYSTEMS_ICC__) - #if __VER__ > 1000 - #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) - #else - #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(VER / 100, __VER__ % 100, 0) - #endif -#endif - -#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) - #undef JSON_HEDLEY_IAR_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_IAR_VERSION) - #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_TINYC_VERSION) - #undef JSON_HEDLEY_TINYC_VERSION -#endif -#if defined(__TINYC__) - #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) -#endif - -#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) - #undef JSON_HEDLEY_TINYC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_TINYC_VERSION) - #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_DMC_VERSION) - #undef JSON_HEDLEY_DMC_VERSION -#endif -#if defined(__DMC__) - #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) -#endif - -#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) - #undef JSON_HEDLEY_DMC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_DMC_VERSION) - #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_COMPCERT_VERSION) - #undef JSON_HEDLEY_COMPCERT_VERSION -#endif -#if defined(__COMPCERT_VERSION__) - #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) -#endif - -#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) - #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_COMPCERT_VERSION) - #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_PELLES_VERSION) - #undef JSON_HEDLEY_PELLES_VERSION -#endif -#if defined(__POCC__) - #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) -#endif - -#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) - #undef JSON_HEDLEY_PELLES_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_PELLES_VERSION) - #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_GCC_VERSION) - #undef JSON_HEDLEY_GCC_VERSION -#endif -#if \ - defined(JSON_HEDLEY_GNUC_VERSION) && \ - !defined(__clang__) && \ - !defined(JSON_HEDLEY_INTEL_VERSION) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_ARM_VERSION) && \ - !defined(JSON_HEDLEY_TI_VERSION) && \ - !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ - !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ - !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ - !defined(__COMPCERT__) - #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION -#endif - -#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) - #undef JSON_HEDLEY_GCC_VERSION_CHECK -#endif -#if defined(JSON_HEDLEY_GCC_VERSION) - #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) -#else - #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) -#endif - -#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_ATTRIBUTE -#endif -#if defined(__has_attribute) - #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) -#else - #define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE -#endif -#if defined(__has_attribute) - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE -#endif -#if defined(__has_attribute) - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE -#endif -#if \ - defined(__has_cpp_attribute) && \ - defined(__cplusplus) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) - #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS -#endif -#if !defined(__cplusplus) || !defined(__has_cpp_attribute) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) -#elif \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_IAR_VERSION) && \ - (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ - (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) -#else - #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE -#endif -#if defined(__has_cpp_attribute) && defined(__cplusplus) - #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE -#endif -#if defined(__has_cpp_attribute) && defined(__cplusplus) - #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_BUILTIN) - #undef JSON_HEDLEY_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) -#else - #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) - #undef JSON_HEDLEY_GNUC_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) -#else - #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) - #undef JSON_HEDLEY_GCC_HAS_BUILTIN -#endif -#if defined(__has_builtin) - #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) -#else - #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_FEATURE) - #undef JSON_HEDLEY_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) -#else - #define JSON_HEDLEY_HAS_FEATURE(feature) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) - #undef JSON_HEDLEY_GNUC_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) -#else - #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) - #undef JSON_HEDLEY_GCC_HAS_FEATURE -#endif -#if defined(__has_feature) - #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) -#else - #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_EXTENSION) - #undef JSON_HEDLEY_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) -#else - #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) - #undef JSON_HEDLEY_GNUC_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) -#else - #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) - #undef JSON_HEDLEY_GCC_HAS_EXTENSION -#endif -#if defined(__has_extension) - #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) -#else - #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE -#endif -#if defined(__has_declspec_attribute) - #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) -#else - #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_HAS_WARNING) - #undef JSON_HEDLEY_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) -#else - #define JSON_HEDLEY_HAS_WARNING(warning) (0) -#endif - -#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) - #undef JSON_HEDLEY_GNUC_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) -#else - #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_GCC_HAS_WARNING) - #undef JSON_HEDLEY_GCC_HAS_WARNING -#endif -#if defined(__has_warning) - #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) -#else - #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - defined(__clang__) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ - (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) - #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_PRAGMA(value) __pragma(value) -#else - #define JSON_HEDLEY_PRAGMA(value) -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) - #undef JSON_HEDLEY_DIAGNOSTIC_PUSH -#endif -#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) - #undef JSON_HEDLEY_DIAGNOSTIC_POP -#endif -#if defined(__clang__) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) - #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) -#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) - #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") - #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") -#else - #define JSON_HEDLEY_DIAGNOSTIC_PUSH - #define JSON_HEDLEY_DIAGNOSTIC_POP -#endif - -/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for - HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ -#endif -#if defined(__cplusplus) -# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") -# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") -# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ - _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# endif -# else -# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ - xpr \ - JSON_HEDLEY_DIAGNOSTIC_POP -# endif -# endif -#endif -#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x -#endif - -#if defined(JSON_HEDLEY_CONST_CAST) - #undef JSON_HEDLEY_CONST_CAST -#endif -#if defined(__cplusplus) -# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) -#elif \ - JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ - ((T) (expr)); \ - JSON_HEDLEY_DIAGNOSTIC_POP \ - })) -#else -# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_REINTERPRET_CAST) - #undef JSON_HEDLEY_REINTERPRET_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) -#else - #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_STATIC_CAST) - #undef JSON_HEDLEY_STATIC_CAST -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) -#else - #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) -#endif - -#if defined(JSON_HEDLEY_CPP_CAST) - #undef JSON_HEDLEY_CPP_CAST -#endif -#if defined(__cplusplus) -# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") -# define JSON_HEDLEY_CPP_CAST(T, expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ - ((T) (expr)) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) -# define JSON_HEDLEY_CPP_CAST(T, expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("diag_suppress=Pe137") \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) -# endif -#else -# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") -#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) -#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") -#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") -#elif \ - JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#endif - -#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) - #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") -#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") -#else - #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#endif - -#if defined(JSON_HEDLEY_DEPRECATED) - #undef JSON_HEDLEY_DEPRECATED -#endif -#if defined(JSON_HEDLEY_DEPRECATED_FOR) - #undef JSON_HEDLEY_DEPRECATED_FOR -#endif -#if \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) -#elif \ - JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) - #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) -#elif defined(__cplusplus) && (__cplusplus >= 201402L) - #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") -#else - #define JSON_HEDLEY_DEPRECATED(since) - #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) -#endif - -#if defined(JSON_HEDLEY_UNAVAILABLE) - #undef JSON_HEDLEY_UNAVAILABLE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) -#else - #define JSON_HEDLEY_UNAVAILABLE(available_since) -#endif - -#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) - #undef JSON_HEDLEY_WARN_UNUSED_RESULT -#endif -#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) - #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) -#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) - #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) -#elif defined(_Check_return_) /* SAL */ - #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ -#else - #define JSON_HEDLEY_WARN_UNUSED_RESULT - #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) -#endif - -#if defined(JSON_HEDLEY_SENTINEL) - #undef JSON_HEDLEY_SENTINEL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) - #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) -#else - #define JSON_HEDLEY_SENTINEL(position) -#endif - -#if defined(JSON_HEDLEY_NO_RETURN) - #undef JSON_HEDLEY_NO_RETURN -#endif -#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_NO_RETURN __noreturn -#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) -#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L - #define JSON_HEDLEY_NO_RETURN _Noreturn -#elif defined(__cplusplus) && (__cplusplus >= 201103L) - #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) - #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") -#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) - #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) - #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) -#else - #define JSON_HEDLEY_NO_RETURN -#endif - -#if defined(JSON_HEDLEY_NO_ESCAPE) - #undef JSON_HEDLEY_NO_ESCAPE -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) - #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) -#else - #define JSON_HEDLEY_NO_ESCAPE -#endif - -#if defined(JSON_HEDLEY_UNREACHABLE) - #undef JSON_HEDLEY_UNREACHABLE -#endif -#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) - #undef JSON_HEDLEY_UNREACHABLE_RETURN -#endif -#if defined(JSON_HEDLEY_ASSUME) - #undef JSON_HEDLEY_ASSUME -#endif -#if \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_ASSUME(expr) __assume(expr) -#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) - #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) -#elif \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) - #if defined(__cplusplus) - #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) - #else - #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) - #endif -#endif -#if \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) - #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() -#elif defined(JSON_HEDLEY_ASSUME) - #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) -#endif -#if !defined(JSON_HEDLEY_ASSUME) - #if defined(JSON_HEDLEY_UNREACHABLE) - #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) - #else - #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) - #endif -#endif -#if defined(JSON_HEDLEY_UNREACHABLE) - #if \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) - #else - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() - #endif -#else - #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) -#endif -#if !defined(JSON_HEDLEY_UNREACHABLE) - #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) -#endif - -JSON_HEDLEY_DIAGNOSTIC_PUSH -#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") - #pragma clang diagnostic ignored "-Wpedantic" -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) - #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" -#endif -#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) - #if defined(__clang__) - #pragma clang diagnostic ignored "-Wvariadic-macros" - #elif defined(JSON_HEDLEY_GCC_VERSION) - #pragma GCC diagnostic ignored "-Wvariadic-macros" - #endif -#endif -#if defined(JSON_HEDLEY_NON_NULL) - #undef JSON_HEDLEY_NON_NULL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) - #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) -#else - #define JSON_HEDLEY_NON_NULL(...) -#endif -JSON_HEDLEY_DIAGNOSTIC_POP - -#if defined(JSON_HEDLEY_PRINTF_FORMAT) - #undef JSON_HEDLEY_PRINTF_FORMAT -#endif -#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) -#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) -#elif \ - JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) -#else - #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) -#endif - -#if defined(JSON_HEDLEY_CONSTEXPR) - #undef JSON_HEDLEY_CONSTEXPR -#endif -#if defined(__cplusplus) - #if __cplusplus >= 201103L - #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) - #endif -#endif -#if !defined(JSON_HEDLEY_CONSTEXPR) - #define JSON_HEDLEY_CONSTEXPR -#endif - -#if defined(JSON_HEDLEY_PREDICT) - #undef JSON_HEDLEY_PREDICT -#endif -#if defined(JSON_HEDLEY_LIKELY) - #undef JSON_HEDLEY_LIKELY -#endif -#if defined(JSON_HEDLEY_UNLIKELY) - #undef JSON_HEDLEY_UNLIKELY -#endif -#if defined(JSON_HEDLEY_UNPREDICTABLE) - #undef JSON_HEDLEY_UNPREDICTABLE -#endif -#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) - #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) -#endif -#if \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) -# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) -# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) -# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) -#elif \ - (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) -# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ - (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ - (__extension__ ({ \ - double hedley_probability_ = (probability); \ - ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ - })) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ - (__extension__ ({ \ - double hedley_probability_ = (probability); \ - ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ - })) -# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) -# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) -#else -# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) -# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) -# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) -# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) -# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) -#endif -#if !defined(JSON_HEDLEY_UNPREDICTABLE) - #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) -#endif - -#if defined(JSON_HEDLEY_MALLOC) - #undef JSON_HEDLEY_MALLOC -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_MALLOC __declspec(restrict) -#else - #define JSON_HEDLEY_MALLOC -#endif - -#if defined(JSON_HEDLEY_PURE) - #undef JSON_HEDLEY_PURE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) -# define JSON_HEDLEY_PURE __attribute__((__pure__)) -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) -# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") -#elif defined(__cplusplus) && \ - ( \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ - ) -# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") -#else -# define JSON_HEDLEY_PURE -#endif - -#if defined(JSON_HEDLEY_CONST) - #undef JSON_HEDLEY_CONST -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) - #define JSON_HEDLEY_CONST __attribute__((__const__)) -#elif \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) - #define JSON_HEDLEY_CONST _Pragma("no_side_effect") -#else - #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE -#endif - -#if defined(JSON_HEDLEY_RESTRICT) - #undef JSON_HEDLEY_RESTRICT -#endif -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) - #define JSON_HEDLEY_RESTRICT restrict -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ - JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ - defined(__clang__) - #define JSON_HEDLEY_RESTRICT __restrict -#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) - #define JSON_HEDLEY_RESTRICT _Restrict -#else - #define JSON_HEDLEY_RESTRICT -#endif - -#if defined(JSON_HEDLEY_INLINE) - #undef JSON_HEDLEY_INLINE -#endif -#if \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ - (defined(__cplusplus) && (__cplusplus >= 199711L)) - #define JSON_HEDLEY_INLINE inline -#elif \ - defined(JSON_HEDLEY_GCC_VERSION) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) - #define JSON_HEDLEY_INLINE __inline__ -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_INLINE __inline -#else - #define JSON_HEDLEY_INLINE -#endif - -#if defined(JSON_HEDLEY_ALWAYS_INLINE) - #undef JSON_HEDLEY_ALWAYS_INLINE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) -# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_ALWAYS_INLINE __forceinline -#elif defined(__cplusplus) && \ - ( \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ - ) -# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) -# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") -#else -# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE -#endif - -#if defined(JSON_HEDLEY_NEVER_INLINE) - #undef JSON_HEDLEY_NEVER_INLINE -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ - JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ - (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ - (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ - (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ - JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ - JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) - #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) -#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") -#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) - #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") -#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) - #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) - #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) -#else - #define JSON_HEDLEY_NEVER_INLINE -#endif - -#if defined(JSON_HEDLEY_PRIVATE) - #undef JSON_HEDLEY_PRIVATE -#endif -#if defined(JSON_HEDLEY_PUBLIC) - #undef JSON_HEDLEY_PUBLIC -#endif -#if defined(JSON_HEDLEY_IMPORT) - #undef JSON_HEDLEY_IMPORT -#endif -#if defined(_WIN32) || defined(__CYGWIN__) -# define JSON_HEDLEY_PRIVATE -# define JSON_HEDLEY_PUBLIC __declspec(dllexport) -# define JSON_HEDLEY_IMPORT __declspec(dllimport) -#else -# if \ - JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - ( \ - defined(__TI_EABI__) && \ - ( \ - (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ - ) \ - ) -# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) -# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) -# else -# define JSON_HEDLEY_PRIVATE -# define JSON_HEDLEY_PUBLIC -# endif -# define JSON_HEDLEY_IMPORT extern -#endif - -#if defined(JSON_HEDLEY_NO_THROW) - #undef JSON_HEDLEY_NO_THROW -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) - #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) - #define JSON_HEDLEY_NO_THROW __declspec(nothrow) -#else - #define JSON_HEDLEY_NO_THROW -#endif - -#if defined(JSON_HEDLEY_FALL_THROUGH) - #undef JSON_HEDLEY_FALL_THROUGH -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) - #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) - #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) -#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) - #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) -#elif defined(__fallthrough) /* SAL */ - #define JSON_HEDLEY_FALL_THROUGH __fallthrough -#else - #define JSON_HEDLEY_FALL_THROUGH -#endif - -#if defined(JSON_HEDLEY_RETURNS_NON_NULL) - #undef JSON_HEDLEY_RETURNS_NON_NULL -#endif -#if \ - JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) - #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) -#elif defined(_Ret_notnull_) /* SAL */ - #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ -#else - #define JSON_HEDLEY_RETURNS_NON_NULL -#endif - -#if defined(JSON_HEDLEY_ARRAY_PARAM) - #undef JSON_HEDLEY_ARRAY_PARAM -#endif -#if \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ - !defined(__STDC_NO_VLA__) && \ - !defined(__cplusplus) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_TINYC_VERSION) - #define JSON_HEDLEY_ARRAY_PARAM(name) (name) -#else - #define JSON_HEDLEY_ARRAY_PARAM(name) -#endif - -#if defined(JSON_HEDLEY_IS_CONSTANT) - #undef JSON_HEDLEY_IS_CONSTANT -#endif -#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) - #undef JSON_HEDLEY_REQUIRE_CONSTEXPR -#endif -/* JSON_HEDLEY_IS_CONSTEXPR_ is for - HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ -#if defined(JSON_HEDLEY_IS_CONSTEXPR_) - #undef JSON_HEDLEY_IS_CONSTEXPR_ -#endif -#if \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ - (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) - #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) -#endif -#if !defined(__cplusplus) -# if \ - JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ - JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ - JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) -#if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) -#else - #include - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) -#endif -# elif \ - ( \ - defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ - !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ - !defined(JSON_HEDLEY_PGI_VERSION) && \ - !defined(JSON_HEDLEY_IAR_VERSION)) || \ - JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ - JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ - JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) -#if defined(__INTPTR_TYPE__) - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) -#else - #include - #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) -#endif -# elif \ - defined(JSON_HEDLEY_GCC_VERSION) || \ - defined(JSON_HEDLEY_INTEL_VERSION) || \ - defined(JSON_HEDLEY_TINYC_VERSION) || \ - defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ - JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ - defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ - defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ - defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ - defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ - defined(__clang__) -# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ - sizeof(void) != \ - sizeof(*( \ - 1 ? \ - ((void*) ((expr) * 0L) ) : \ -((struct { char v[sizeof(void) * 2]; } *) 1) \ - ) \ - ) \ - ) -# endif -#endif -#if defined(JSON_HEDLEY_IS_CONSTEXPR_) - #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) - #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) -#else - #if !defined(JSON_HEDLEY_IS_CONSTANT) - #define JSON_HEDLEY_IS_CONSTANT(expr) (0) - #endif - #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) -#endif - -#if defined(JSON_HEDLEY_BEGIN_C_DECLS) - #undef JSON_HEDLEY_BEGIN_C_DECLS -#endif -#if defined(JSON_HEDLEY_END_C_DECLS) - #undef JSON_HEDLEY_END_C_DECLS -#endif -#if defined(JSON_HEDLEY_C_DECL) - #undef JSON_HEDLEY_C_DECL -#endif -#if defined(__cplusplus) - #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { - #define JSON_HEDLEY_END_C_DECLS } - #define JSON_HEDLEY_C_DECL extern "C" -#else - #define JSON_HEDLEY_BEGIN_C_DECLS - #define JSON_HEDLEY_END_C_DECLS - #define JSON_HEDLEY_C_DECL -#endif - -#if defined(JSON_HEDLEY_STATIC_ASSERT) - #undef JSON_HEDLEY_STATIC_ASSERT -#endif -#if \ - !defined(__cplusplus) && ( \ - (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ - (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ - JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ - defined(_Static_assert) \ - ) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) -#elif \ - (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ - JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) -#else -# define JSON_HEDLEY_STATIC_ASSERT(expr, message) -#endif - -#if defined(JSON_HEDLEY_NULL) - #undef JSON_HEDLEY_NULL -#endif -#if defined(__cplusplus) - #if __cplusplus >= 201103L - #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) - #elif defined(NULL) - #define JSON_HEDLEY_NULL NULL - #else - #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) - #endif -#elif defined(NULL) - #define JSON_HEDLEY_NULL NULL -#else - #define JSON_HEDLEY_NULL ((void*) 0) -#endif - -#if defined(JSON_HEDLEY_MESSAGE) - #undef JSON_HEDLEY_MESSAGE -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") -# define JSON_HEDLEY_MESSAGE(msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ - JSON_HEDLEY_PRAGMA(message msg) \ - JSON_HEDLEY_DIAGNOSTIC_POP -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) -#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) -#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) -# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#else -# define JSON_HEDLEY_MESSAGE(msg) -#endif - -#if defined(JSON_HEDLEY_WARNING) - #undef JSON_HEDLEY_WARNING -#endif -#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") -# define JSON_HEDLEY_WARNING(msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ - JSON_HEDLEY_PRAGMA(clang warning msg) \ - JSON_HEDLEY_DIAGNOSTIC_POP -#elif \ - JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ - JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ - JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) -#elif \ - JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) -#else -# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) -#endif - -#if defined(JSON_HEDLEY_REQUIRE) - #undef JSON_HEDLEY_REQUIRE -#endif -#if defined(JSON_HEDLEY_REQUIRE_MSG) - #undef JSON_HEDLEY_REQUIRE_MSG -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) -# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") -# define JSON_HEDLEY_REQUIRE(expr) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((diagnose_if(!(expr), #expr, "error"))) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ - __attribute__((diagnose_if(!(expr), msg, "error"))) \ - JSON_HEDLEY_DIAGNOSTIC_POP -# else -# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) -# endif -#else -# define JSON_HEDLEY_REQUIRE(expr) -# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) -#endif - -#if defined(JSON_HEDLEY_FLAGS) - #undef JSON_HEDLEY_FLAGS -#endif -#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) - #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) -#else - #define JSON_HEDLEY_FLAGS -#endif - -#if defined(JSON_HEDLEY_FLAGS_CAST) - #undef JSON_HEDLEY_FLAGS_CAST -#endif -#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) -# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ - JSON_HEDLEY_DIAGNOSTIC_PUSH \ - _Pragma("warning(disable:188)") \ - ((T) (expr)); \ - JSON_HEDLEY_DIAGNOSTIC_POP \ - })) -#else -# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) -#endif - -#if defined(JSON_HEDLEY_EMPTY_BASES) - #undef JSON_HEDLEY_EMPTY_BASES -#endif -#if \ - (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ - JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) - #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) -#else - #define JSON_HEDLEY_EMPTY_BASES -#endif - -/* Remaining macros are deprecated. */ - -#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) - #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK -#endif -#if defined(__clang__) - #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) -#else - #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) -#endif - -#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) - #undef JSON_HEDLEY_CLANG_HAS_BUILTIN -#endif -#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) - -#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) - #undef JSON_HEDLEY_CLANG_HAS_FEATURE -#endif -#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) - -#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) - #undef JSON_HEDLEY_CLANG_HAS_EXTENSION -#endif -#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) - -#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) - #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE -#endif -#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) - -#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) - #undef JSON_HEDLEY_CLANG_HAS_WARNING -#endif -#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) - -#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ - - -// This file contains all internal macro definitions -// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them - -// exclude unsupported compilers -#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) - #if defined(__clang__) - #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 - #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) - #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 - #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" - #endif - #endif -#endif - -// C++ language standard detection -#if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) - #define JSON_HAS_CPP_20 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 -#elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 - #define JSON_HAS_CPP_17 - #define JSON_HAS_CPP_14 -#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) - #define JSON_HAS_CPP_14 -#endif - -// disable float-equal warnings on GCC/clang -#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wfloat-equal" -#endif - -// disable documentation warnings on clang -#if defined(__clang__) - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wdocumentation" -#endif - -// allow to disable exceptions -#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) - #define JSON_THROW(exception) throw exception - #define JSON_TRY try - #define JSON_CATCH(exception) catch(exception) - #define JSON_INTERNAL_CATCH(exception) catch(exception) -#else - #include - #define JSON_THROW(exception) std::abort() - #define JSON_TRY if(true) - #define JSON_CATCH(exception) if(false) - #define JSON_INTERNAL_CATCH(exception) if(false) -#endif - -// override exception macros -#if defined(JSON_THROW_USER) - #undef JSON_THROW - #define JSON_THROW JSON_THROW_USER -#endif -#if defined(JSON_TRY_USER) - #undef JSON_TRY - #define JSON_TRY JSON_TRY_USER -#endif -#if defined(JSON_CATCH_USER) - #undef JSON_CATCH - #define JSON_CATCH JSON_CATCH_USER - #undef JSON_INTERNAL_CATCH - #define JSON_INTERNAL_CATCH JSON_CATCH_USER -#endif -#if defined(JSON_INTERNAL_CATCH_USER) - #undef JSON_INTERNAL_CATCH - #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER -#endif - -// allow to override assert -#if !defined(JSON_ASSERT) - #include // assert - #define JSON_ASSERT(x) assert(x) -#endif - -// allow to access some private functions (needed by the test suite) -#if defined(JSON_TESTS_PRIVATE) - #define JSON_PRIVATE_UNLESS_TESTED public -#else - #define JSON_PRIVATE_UNLESS_TESTED private -#endif - -/*! -@brief macro to briefly define a mapping between an enum and JSON -@def NLOHMANN_JSON_SERIALIZE_ENUM -@since version 3.4.0 -*/ -#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ - template \ - inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [e](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.first == e; \ - }); \ - j = ((it != std::end(m)) ? it : std::begin(m))->second; \ - } \ - template \ - inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ - { \ - static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ - static const std::pair m[] = __VA_ARGS__; \ - auto it = std::find_if(std::begin(m), std::end(m), \ - [&j](const std::pair& ej_pair) -> bool \ - { \ - return ej_pair.second == j; \ - }); \ - e = ((it != std::end(m)) ? it : std::begin(m))->first; \ - } - -// Ugly macros to avoid uglier copy-paste when specializing basic_json. They -// may be removed in the future once the class is split. - -#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ - template class ObjectType, \ - template class ArrayType, \ - class StringType, class BooleanType, class NumberIntegerType, \ - class NumberUnsignedType, class NumberFloatType, \ - template class AllocatorType, \ - template class JSONSerializer, \ - class BinaryType> - -#define NLOHMANN_BASIC_JSON_TPL \ - basic_json - -// Macros to simplify conversion from/to types - -#define NLOHMANN_JSON_EXPAND( x ) x -#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME -#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ - NLOHMANN_JSON_PASTE64, \ - NLOHMANN_JSON_PASTE63, \ - NLOHMANN_JSON_PASTE62, \ - NLOHMANN_JSON_PASTE61, \ - NLOHMANN_JSON_PASTE60, \ - NLOHMANN_JSON_PASTE59, \ - NLOHMANN_JSON_PASTE58, \ - NLOHMANN_JSON_PASTE57, \ - NLOHMANN_JSON_PASTE56, \ - NLOHMANN_JSON_PASTE55, \ - NLOHMANN_JSON_PASTE54, \ - NLOHMANN_JSON_PASTE53, \ - NLOHMANN_JSON_PASTE52, \ - NLOHMANN_JSON_PASTE51, \ - NLOHMANN_JSON_PASTE50, \ - NLOHMANN_JSON_PASTE49, \ - NLOHMANN_JSON_PASTE48, \ - NLOHMANN_JSON_PASTE47, \ - NLOHMANN_JSON_PASTE46, \ - NLOHMANN_JSON_PASTE45, \ - NLOHMANN_JSON_PASTE44, \ - NLOHMANN_JSON_PASTE43, \ - NLOHMANN_JSON_PASTE42, \ - NLOHMANN_JSON_PASTE41, \ - NLOHMANN_JSON_PASTE40, \ - NLOHMANN_JSON_PASTE39, \ - NLOHMANN_JSON_PASTE38, \ - NLOHMANN_JSON_PASTE37, \ - NLOHMANN_JSON_PASTE36, \ - NLOHMANN_JSON_PASTE35, \ - NLOHMANN_JSON_PASTE34, \ - NLOHMANN_JSON_PASTE33, \ - NLOHMANN_JSON_PASTE32, \ - NLOHMANN_JSON_PASTE31, \ - NLOHMANN_JSON_PASTE30, \ - NLOHMANN_JSON_PASTE29, \ - NLOHMANN_JSON_PASTE28, \ - NLOHMANN_JSON_PASTE27, \ - NLOHMANN_JSON_PASTE26, \ - NLOHMANN_JSON_PASTE25, \ - NLOHMANN_JSON_PASTE24, \ - NLOHMANN_JSON_PASTE23, \ - NLOHMANN_JSON_PASTE22, \ - NLOHMANN_JSON_PASTE21, \ - NLOHMANN_JSON_PASTE20, \ - NLOHMANN_JSON_PASTE19, \ - NLOHMANN_JSON_PASTE18, \ - NLOHMANN_JSON_PASTE17, \ - NLOHMANN_JSON_PASTE16, \ - NLOHMANN_JSON_PASTE15, \ - NLOHMANN_JSON_PASTE14, \ - NLOHMANN_JSON_PASTE13, \ - NLOHMANN_JSON_PASTE12, \ - NLOHMANN_JSON_PASTE11, \ - NLOHMANN_JSON_PASTE10, \ - NLOHMANN_JSON_PASTE9, \ - NLOHMANN_JSON_PASTE8, \ - NLOHMANN_JSON_PASTE7, \ - NLOHMANN_JSON_PASTE6, \ - NLOHMANN_JSON_PASTE5, \ - NLOHMANN_JSON_PASTE4, \ - NLOHMANN_JSON_PASTE3, \ - NLOHMANN_JSON_PASTE2, \ - NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) -#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) -#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) -#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) -#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) -#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) -#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) -#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) -#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) -#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) -#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) -#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) -#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) -#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) -#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) -#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) -#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) -#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) -#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) -#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) -#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) -#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) -#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) -#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) -#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) -#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) -#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) -#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) -#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) -#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) -#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) -#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) -#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) -#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) -#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) -#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) -#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) -#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) -#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) -#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) -#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) -#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) -#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) -#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) -#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) -#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) -#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) -#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) -#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) -#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) -#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) -#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) -#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) -#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) -#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) -#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) -#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) -#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) -#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) -#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) -#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) -#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) -#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) -#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) - -#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; -#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_INTRUSIVE -@since version 3.9.0 -*/ -#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ - friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } - -/*! -@brief macro -@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE -@since version 3.9.0 -*/ -#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ - inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ - inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } - -#ifndef JSON_USE_IMPLICIT_CONVERSIONS - #define JSON_USE_IMPLICIT_CONVERSIONS 1 -#endif - -#if JSON_USE_IMPLICIT_CONVERSIONS - #define JSON_EXPLICIT -#else - #define JSON_EXPLICIT explicit -#endif - - -namespace nlohmann -{ -namespace detail -{ -//////////////// -// exceptions // -//////////////// - -/*! -@brief general exception of the @ref basic_json class - -This class is an extension of `std::exception` objects with a member @a id for -exception ids. It is used as the base class for all exceptions thrown by the -@ref basic_json class. This class can hence be used as "wildcard" to catch -exceptions. - -Subclasses: -- @ref parse_error for exceptions indicating a parse error -- @ref invalid_iterator for exceptions indicating errors with iterators -- @ref type_error for exceptions indicating executing a member function with - a wrong type -- @ref out_of_range for exceptions indicating access out of the defined range -- @ref other_error for exceptions indicating other library errors - -@internal -@note To have nothrow-copy-constructible exceptions, we internally use - `std::runtime_error` which can cope with arbitrary-length error messages. - Intermediate strings are built with static functions and then passed to - the actual constructor. -@endinternal - -@liveexample{The following code shows how arbitrary library exceptions can be -caught.,exception} - -@since version 3.0.0 -*/ -class exception : public std::exception -{ - public: - /// returns the explanatory string - JSON_HEDLEY_RETURNS_NON_NULL - const char* what() const noexcept override - { - return m.what(); - } - - /// the id of the exception - const int id; - - protected: - JSON_HEDLEY_NON_NULL(3) - exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} - - static std::string name(const std::string& ename, int id_) - { - return "[json.exception." + ename + "." + std::to_string(id_) + "] "; - } - - private: - /// an exception object as storage for error messages - std::runtime_error m; -}; - -/*! -@brief exception indicating a parse error - -This exception is thrown by the library when a parse error occurs. Parse errors -can occur during the deserialization of JSON text, CBOR, MessagePack, as well -as when using JSON Patch. - -Member @a byte holds the byte index of the last read character in the input -file. - -Exceptions have ids 1xx. - -name / id | example message | description ------------------------------- | --------------- | ------------------------- -json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. -json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. -json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. -json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. -json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. -json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. -json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. -json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. -json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. -json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. -json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. -json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. -json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet). -json.exception.parse_error.115 | parse error at byte 5: syntax error while parsing UBJSON high-precision number: invalid number text: 1A | A UBJSON high-precision number could not be parsed. - -@note For an input with n bytes, 1 is the index of the first character and n+1 - is the index of the terminating null byte or the end of file. This also - holds true when reading a byte vector (CBOR or MessagePack). - -@liveexample{The following code shows how a `parse_error` exception can be -caught.,parse_error} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class parse_error : public exception -{ - public: - /*! - @brief create a parse error exception - @param[in] id_ the id of the exception - @param[in] pos the position where the error occurred (or with - chars_read_total=0 if the position cannot be - determined) - @param[in] what_arg the explanatory string - @return parse_error object - */ - static parse_error create(int id_, const position_t& pos, const std::string& what_arg) - { - std::string w = exception::name("parse_error", id_) + "parse error" + - position_string(pos) + ": " + what_arg; - return parse_error(id_, pos.chars_read_total, w.c_str()); - } - - static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) - { - std::string w = exception::name("parse_error", id_) + "parse error" + - (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + - ": " + what_arg; - return parse_error(id_, byte_, w.c_str()); - } - - /*! - @brief byte index of the parse error - - The byte index of the last read character in the input file. - - @note For an input with n bytes, 1 is the index of the first character and - n+1 is the index of the terminating null byte or the end of file. - This also holds true when reading a byte vector (CBOR or MessagePack). - */ - const std::size_t byte; - - private: - parse_error(int id_, std::size_t byte_, const char* what_arg) - : exception(id_, what_arg), byte(byte_) {} - - static std::string position_string(const position_t& pos) - { - return " at line " + std::to_string(pos.lines_read + 1) + - ", column " + std::to_string(pos.chars_read_current_line); - } -}; - -/*! -@brief exception indicating errors with iterators - -This exception is thrown if iterators passed to a library function do not match -the expected semantics. - -Exceptions have ids 2xx. - -name / id | example message | description ------------------------------------ | --------------- | ------------------------- -json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. -json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. -json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. -json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. -json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. -json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. -json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. -json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. -json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. -json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. -json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered. -json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). - -@liveexample{The following code shows how an `invalid_iterator` exception can be -caught.,invalid_iterator} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class invalid_iterator : public exception -{ - public: - static invalid_iterator create(int id_, const std::string& what_arg) - { - std::string w = exception::name("invalid_iterator", id_) + what_arg; - return invalid_iterator(id_, w.c_str()); - } - - private: - JSON_HEDLEY_NON_NULL(3) - invalid_iterator(int id_, const char* what_arg) - : exception(id_, what_arg) {} -}; - -/*! -@brief exception indicating executing a member function with a wrong type - -This exception is thrown in case of a type error; that is, a library function is -executed on a JSON value whose type does not match the expected semantics. - -Exceptions have ids 3xx. - -name / id | example message | description ------------------------------ | --------------- | ------------------------- -json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. -json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. -json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &. -json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. -json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. -json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. -json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. -json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. -json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. -json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. -json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. -json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types. -json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. -json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. -json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. -json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. | -json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) | - -@liveexample{The following code shows how a `type_error` exception can be -caught.,type_error} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref out_of_range for exceptions indicating access out of the defined range -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class type_error : public exception -{ - public: - static type_error create(int id_, const std::string& what_arg) - { - std::string w = exception::name("type_error", id_) + what_arg; - return type_error(id_, w.c_str()); - } - - private: - JSON_HEDLEY_NON_NULL(3) - type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; - -/*! -@brief exception indicating access out of the defined range - -This exception is thrown in case a library function is called on an input -parameter that exceeds the expected range, for instance in case of array -indices or nonexisting object keys. - -Exceptions have ids 4xx. - -name / id | example message | description -------------------------------- | --------------- | ------------------------- -json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. -json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. -json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. -json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. -json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. -json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. -json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. (until version 3.8.0) | -json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | -json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | - -@liveexample{The following code shows how an `out_of_range` exception can be -caught.,out_of_range} - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref other_error for exceptions indicating other library errors - -@since version 3.0.0 -*/ -class out_of_range : public exception -{ - public: - static out_of_range create(int id_, const std::string& what_arg) - { - std::string w = exception::name("out_of_range", id_) + what_arg; - return out_of_range(id_, w.c_str()); - } - - private: - JSON_HEDLEY_NON_NULL(3) - out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; - -/*! -@brief exception indicating other library errors - -This exception is thrown in case of errors that cannot be classified with the -other exception types. - -Exceptions have ids 5xx. - -name / id | example message | description ------------------------------- | --------------- | ------------------------- -json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. - -@sa - @ref exception for the base class of the library exceptions -@sa - @ref parse_error for exceptions indicating a parse error -@sa - @ref invalid_iterator for exceptions indicating errors with iterators -@sa - @ref type_error for exceptions indicating executing a member function with - a wrong type -@sa - @ref out_of_range for exceptions indicating access out of the defined range - -@liveexample{The following code shows how an `other_error` exception can be -caught.,other_error} - -@since version 3.0.0 -*/ -class other_error : public exception -{ - public: - static other_error create(int id_, const std::string& what_arg) - { - std::string w = exception::name("other_error", id_) + what_arg; - return other_error(id_, w.c_str()); - } - - private: - JSON_HEDLEY_NON_NULL(3) - other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - - -#include // size_t -#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type - -namespace nlohmann -{ -namespace detail -{ -// alias templates to reduce boilerplate -template -using enable_if_t = typename std::enable_if::type; - -template -using uncvref_t = typename std::remove_cv::type>::type; - -// implementation of C++14 index_sequence and affiliates -// source: https://stackoverflow.com/a/32223343 -template -struct index_sequence -{ - using type = index_sequence; - using value_type = std::size_t; - static constexpr std::size_t size() noexcept - { - return sizeof...(Ints); - } -}; - -template -struct merge_and_renumber; - -template -struct merge_and_renumber, index_sequence> - : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; - -template -struct make_index_sequence - : merge_and_renumber < typename make_index_sequence < N / 2 >::type, - typename make_index_sequence < N - N / 2 >::type > {}; - -template<> struct make_index_sequence<0> : index_sequence<> {}; -template<> struct make_index_sequence<1> : index_sequence<0> {}; - -template -using index_sequence_for = make_index_sequence; - -// dispatch utility (taken from ranges-v3) -template struct priority_tag : priority_tag < N - 1 > {}; -template<> struct priority_tag<0> {}; - -// taken from ranges-v3 -template -struct static_const -{ - static constexpr T value{}; -}; - -template -constexpr T static_const::value; -} // namespace detail -} // namespace nlohmann - -// #include - - -#include // numeric_limits -#include // false_type, is_constructible, is_integral, is_same, true_type -#include // declval - -// #include - - -#include // random_access_iterator_tag - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template struct make_void -{ - using type = void; -}; -template using void_t = typename make_void::type; -} // namespace detail -} // namespace nlohmann - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template -struct iterator_types {}; - -template -struct iterator_types < - It, - void_t> -{ - using difference_type = typename It::difference_type; - using value_type = typename It::value_type; - using pointer = typename It::pointer; - using reference = typename It::reference; - using iterator_category = typename It::iterator_category; -}; - -// This is required as some compilers implement std::iterator_traits in a way that -// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. -template -struct iterator_traits -{ -}; - -template -struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> - : iterator_types -{ -}; - -template -struct iterator_traits::value>> -{ - using iterator_category = std::random_access_iterator_tag; - using value_type = T; - using difference_type = ptrdiff_t; - using pointer = T*; - using reference = T&; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - -// #include - - -#include - -// #include - - -// https://en.cppreference.com/w/cpp/experimental/is_detected -namespace nlohmann -{ -namespace detail -{ -struct nonesuch -{ - nonesuch() = delete; - ~nonesuch() = delete; - nonesuch(nonesuch const&) = delete; - nonesuch(nonesuch const&&) = delete; - void operator=(nonesuch const&) = delete; - void operator=(nonesuch&&) = delete; -}; - -template class Op, - class... Args> -struct detector -{ - using value_t = std::false_type; - using type = Default; -}; - -template class Op, class... Args> -struct detector>, Op, Args...> -{ - using value_t = std::true_type; - using type = Op; -}; - -template class Op, class... Args> -using is_detected = typename detector::value_t; - -template class Op, class... Args> -using detected_t = typename detector::type; - -template class Op, class... Args> -using detected_or = detector; - -template class Op, class... Args> -using detected_or_t = typename detected_or::type; - -template class Op, class... Args> -using is_detected_exact = std::is_same>; - -template class Op, class... Args> -using is_detected_convertible = - std::is_convertible, To>; -} // namespace detail -} // namespace nlohmann - -// #include -#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ -#define INCLUDE_NLOHMANN_JSON_FWD_HPP_ - -#include // int64_t, uint64_t -#include // map -#include // allocator -#include // string -#include // vector - -/*! -@brief namespace for Niels Lohmann -@see https://github.com/nlohmann -@since version 1.0.0 -*/ -namespace nlohmann -{ -/*! -@brief default JSONSerializer template argument - -This serializer ignores the template arguments and uses ADL -([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) -for serialization. -*/ -template -struct adl_serializer; - -template class ObjectType = - std::map, - template class ArrayType = std::vector, - class StringType = std::string, class BooleanType = bool, - class NumberIntegerType = std::int64_t, - class NumberUnsignedType = std::uint64_t, - class NumberFloatType = double, - template class AllocatorType = std::allocator, - template class JSONSerializer = - adl_serializer, - class BinaryType = std::vector> -class basic_json; - -/*! -@brief JSON Pointer - -A JSON pointer defines a string syntax for identifying a specific value -within a JSON document. It can be used with functions `at` and -`operator[]`. Furthermore, JSON pointers are the base for JSON patches. - -@sa [RFC 6901](https://tools.ietf.org/html/rfc6901) - -@since version 2.0.0 -*/ -template -class json_pointer; - -/*! -@brief default JSON class - -This type is the default specialization of the @ref basic_json class which -uses the standard template types. - -@since version 1.0.0 -*/ -using json = basic_json<>; - -template -struct ordered_map; - -/*! -@brief ordered JSON class - -This type preserves the insertion order of object keys. - -@since version 3.9.0 -*/ -using ordered_json = basic_json; - -} // namespace nlohmann - -#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ - - -namespace nlohmann -{ -/*! -@brief detail namespace with internal helper functions - -This namespace collects functions that should not be exposed, -implementations of some @ref basic_json methods, and meta-programming helpers. - -@since version 2.1.0 -*/ -namespace detail -{ -///////////// -// helpers // -///////////// - -// Note to maintainers: -// -// Every trait in this file expects a non CV-qualified type. -// The only exceptions are in the 'aliases for detected' section -// (i.e. those of the form: decltype(T::member_function(std::declval()))) -// -// In this case, T has to be properly CV-qualified to constraint the function arguments -// (e.g. to_json(BasicJsonType&, const T&)) - -template struct is_basic_json : std::false_type {}; - -NLOHMANN_BASIC_JSON_TPL_DECLARATION -struct is_basic_json : std::true_type {}; - -////////////////////// -// json_ref helpers // -////////////////////// - -template -class json_ref; - -template -struct is_json_ref : std::false_type {}; - -template -struct is_json_ref> : std::true_type {}; - -////////////////////////// -// aliases for detected // -////////////////////////// - -template -using mapped_type_t = typename T::mapped_type; - -template -using key_type_t = typename T::key_type; - -template -using value_type_t = typename T::value_type; - -template -using difference_type_t = typename T::difference_type; - -template -using pointer_t = typename T::pointer; - -template -using reference_t = typename T::reference; - -template -using iterator_category_t = typename T::iterator_category; - -template -using iterator_t = typename T::iterator; - -template -using to_json_function = decltype(T::to_json(std::declval()...)); - -template -using from_json_function = decltype(T::from_json(std::declval()...)); - -template -using get_template_function = decltype(std::declval().template get()); - -// trait checking if JSONSerializer::from_json(json const&, udt&) exists -template -struct has_from_json : std::false_type {}; - -// trait checking if j.get is valid -// use this trait instead of std::is_constructible or std::is_convertible, -// both rely on, or make use of implicit conversions, and thus fail when T -// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) -template -struct is_getable -{ - static constexpr bool value = is_detected::value; -}; - -template -struct has_from_json < BasicJsonType, T, - enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -// This trait checks if JSONSerializer::from_json(json const&) exists -// this overload is used for non-default-constructible user-defined-types -template -struct has_non_default_from_json : std::false_type {}; - -template -struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - -// This trait checks if BasicJsonType::json_serializer::to_json exists -// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. -template -struct has_to_json : std::false_type {}; - -template -struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> -{ - using serializer = typename BasicJsonType::template json_serializer; - - static constexpr bool value = - is_detected_exact::value; -}; - - -/////////////////// -// is_ functions // -/////////////////// - -template -struct is_iterator_traits : std::false_type {}; - -template -struct is_iterator_traits> -{ - private: - using traits = iterator_traits; - - public: - static constexpr auto value = - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value && - is_detected::value; -}; - -// source: https://stackoverflow.com/a/37193089/4116453 - -template -struct is_complete_type : std::false_type {}; - -template -struct is_complete_type : std::true_type {}; - -template -struct is_compatible_object_type_impl : std::false_type {}; - -template -struct is_compatible_object_type_impl < - BasicJsonType, CompatibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - - using object_t = typename BasicJsonType::object_t; - - // macOS's is_constructible does not play well with nonesuch... - static constexpr bool value = - std::is_constructible::value && - std::is_constructible::value; -}; - -template -struct is_compatible_object_type - : is_compatible_object_type_impl {}; - -template -struct is_constructible_object_type_impl : std::false_type {}; - -template -struct is_constructible_object_type_impl < - BasicJsonType, ConstructibleObjectType, - enable_if_t < is_detected::value&& - is_detected::value >> -{ - using object_t = typename BasicJsonType::object_t; - - static constexpr bool value = - (std::is_default_constructible::value && - (std::is_move_assignable::value || - std::is_copy_assignable::value) && - (std::is_constructible::value && - std::is_same < - typename object_t::mapped_type, - typename ConstructibleObjectType::mapped_type >::value)) || - (has_from_json::value || - has_non_default_from_json < - BasicJsonType, - typename ConstructibleObjectType::mapped_type >::value); -}; - -template -struct is_constructible_object_type - : is_constructible_object_type_impl {}; - -template -struct is_compatible_string_type_impl : std::false_type {}; - -template -struct is_compatible_string_type_impl < - BasicJsonType, CompatibleStringType, - enable_if_t::value >> -{ - static constexpr auto value = - std::is_constructible::value; -}; - -template -struct is_compatible_string_type - : is_compatible_string_type_impl {}; - -template -struct is_constructible_string_type_impl : std::false_type {}; - -template -struct is_constructible_string_type_impl < - BasicJsonType, ConstructibleStringType, - enable_if_t::value >> -{ - static constexpr auto value = - std::is_constructible::value; -}; - -template -struct is_constructible_string_type - : is_constructible_string_type_impl {}; - -template -struct is_compatible_array_type_impl : std::false_type {}; - -template -struct is_compatible_array_type_impl < - BasicJsonType, CompatibleArrayType, - enable_if_t < is_detected::value&& - is_detected::value&& -// This is needed because json_reverse_iterator has a ::iterator type... -// Therefore it is detected as a CompatibleArrayType. -// The real fix would be to have an Iterable concept. - !is_iterator_traits < - iterator_traits>::value >> -{ - static constexpr bool value = - std::is_constructible::value; -}; - -template -struct is_compatible_array_type - : is_compatible_array_type_impl {}; - -template -struct is_constructible_array_type_impl : std::false_type {}; - -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t::value >> - : std::true_type {}; - -template -struct is_constructible_array_type_impl < - BasicJsonType, ConstructibleArrayType, - enable_if_t < !std::is_same::value&& - std::is_default_constructible::value&& -(std::is_move_assignable::value || - std::is_copy_assignable::value)&& -is_detected::value&& -is_detected::value&& -is_complete_type < -detected_t>::value >> -{ - static constexpr bool value = - // This is needed because json_reverse_iterator has a ::iterator type, - // furthermore, std::back_insert_iterator (and other iterators) have a - // base class `iterator`... Therefore it is detected as a - // ConstructibleArrayType. The real fix would be to have an Iterable - // concept. - !is_iterator_traits>::value && - - (std::is_same::value || - has_from_json::value || - has_non_default_from_json < - BasicJsonType, typename ConstructibleArrayType::value_type >::value); -}; - -template -struct is_constructible_array_type - : is_constructible_array_type_impl {}; - -template -struct is_compatible_integer_type_impl : std::false_type {}; - -template -struct is_compatible_integer_type_impl < - RealIntegerType, CompatibleNumberIntegerType, - enable_if_t < std::is_integral::value&& - std::is_integral::value&& - !std::is_same::value >> -{ - // is there an assert somewhere on overflows? - using RealLimits = std::numeric_limits; - using CompatibleLimits = std::numeric_limits; - - static constexpr auto value = - std::is_constructible::value && - CompatibleLimits::is_integer && - RealLimits::is_signed == CompatibleLimits::is_signed; -}; - -template -struct is_compatible_integer_type - : is_compatible_integer_type_impl {}; - -template -struct is_compatible_type_impl: std::false_type {}; - -template -struct is_compatible_type_impl < - BasicJsonType, CompatibleType, - enable_if_t::value >> -{ - static constexpr bool value = - has_to_json::value; -}; - -template -struct is_compatible_type - : is_compatible_type_impl {}; - -// https://en.cppreference.com/w/cpp/types/conjunction -template struct conjunction : std::true_type { }; -template struct conjunction : B1 { }; -template -struct conjunction -: std::conditional, B1>::type {}; - -template -struct is_constructible_tuple : std::false_type {}; - -template -struct is_constructible_tuple> : conjunction...> {}; -} // namespace detail -} // namespace nlohmann - -// #include - - -#include // array -#include // size_t -#include // uint8_t -#include // string - -namespace nlohmann -{ -namespace detail -{ -/////////////////////////// -// JSON type enumeration // -/////////////////////////// - -/*! -@brief the JSON type enumeration - -This enumeration collects the different JSON types. It is internally used to -distinguish the stored values, and the functions @ref basic_json::is_null(), -@ref basic_json::is_object(), @ref basic_json::is_array(), -@ref basic_json::is_string(), @ref basic_json::is_boolean(), -@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), -@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), -@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and -@ref basic_json::is_structured() rely on it. - -@note There are three enumeration entries (number_integer, number_unsigned, and -number_float), because the library distinguishes these three types for numbers: -@ref basic_json::number_unsigned_t is used for unsigned integers, -@ref basic_json::number_integer_t is used for signed integers, and -@ref basic_json::number_float_t is used for floating-point numbers or to -approximate integers which do not fit in the limits of their respective type. - -@sa @ref basic_json::basic_json(const value_t value_type) -- create a JSON -value with the default value for a given type - -@since version 1.0.0 -*/ -enum class value_t : std::uint8_t -{ - null, ///< null value - object, ///< object (unordered set of name/value pairs) - array, ///< array (ordered collection of values) - string, ///< string value - boolean, ///< boolean value - number_integer, ///< number value (signed integer) - number_unsigned, ///< number value (unsigned integer) - number_float, ///< number value (floating-point) - binary, ///< binary array (ordered collection of bytes) - discarded ///< discarded by the parser callback function -}; - -/*! -@brief comparison operator for JSON types - -Returns an ordering that is similar to Python: -- order: null < boolean < number < object < array < string < binary -- furthermore, each type is not smaller than itself -- discarded values are not comparable -- binary is represented as a b"" string in python and directly comparable to a - string; however, making a binary array directly comparable with a string would - be surprising behavior in a JSON file. - -@since version 1.0.0 -*/ -inline bool operator<(const value_t lhs, const value_t rhs) noexcept -{ - static constexpr std::array order = {{ - 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, - 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, - 6 /* binary */ - } - }; - - const auto l_index = static_cast(lhs); - const auto r_index = static_cast(rhs); - return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; -} -} // namespace detail -} // namespace nlohmann - - -namespace nlohmann -{ -namespace detail -{ -template -void from_json(const BasicJsonType& j, typename std::nullptr_t& n) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_null())) - { - JSON_THROW(type_error::create(302, "type must be null, but is " + std::string(j.type_name()))); - } - n = nullptr; -} - -// overloads for basic_json template parameters -template < typename BasicJsonType, typename ArithmeticType, - enable_if_t < std::is_arithmetic::value&& - !std::is_same::value, - int > = 0 > -void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val) -{ - switch (static_cast(j)) - { - case value_t::number_unsigned: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_integer: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_float: - { - val = static_cast(*j.template get_ptr()); - break; - } - - default: - JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); - } -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_boolean())) - { - JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(j.type_name()))); - } - b = *j.template get_ptr(); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_string())) - { - JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); - } - s = *j.template get_ptr(); -} - -template < - typename BasicJsonType, typename ConstructibleStringType, - enable_if_t < - is_constructible_string_type::value&& - !std::is_same::value, - int > = 0 > -void from_json(const BasicJsonType& j, ConstructibleStringType& s) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_string())) - { - JSON_THROW(type_error::create(302, "type must be string, but is " + std::string(j.type_name()))); - } - - s = *j.template get_ptr(); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val) -{ - get_arithmetic_value(j, val); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val) -{ - get_arithmetic_value(j, val); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val) -{ - get_arithmetic_value(j, val); -} - -template::value, int> = 0> -void from_json(const BasicJsonType& j, EnumType& e) -{ - typename std::underlying_type::type val; - get_arithmetic_value(j, val); - e = static_cast(val); -} - -// forward_list doesn't have an insert method -template::value, int> = 0> -void from_json(const BasicJsonType& j, std::forward_list& l) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); - } - l.clear(); - std::transform(j.rbegin(), j.rend(), - std::front_inserter(l), [](const BasicJsonType & i) - { - return i.template get(); - }); -} - -// valarray doesn't have an insert method -template::value, int> = 0> -void from_json(const BasicJsonType& j, std::valarray& l) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); - } - l.resize(j.size()); - std::transform(j.begin(), j.end(), std::begin(l), - [](const BasicJsonType & elem) - { - return elem.template get(); - }); -} - -template -auto from_json(const BasicJsonType& j, T (&arr)[N]) --> decltype(j.template get(), void()) -{ - for (std::size_t i = 0; i < N; ++i) - { - arr[i] = j.at(i).template get(); - } -} - -template -void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/) -{ - arr = *j.template get_ptr(); -} - -template -auto from_json_array_impl(const BasicJsonType& j, std::array& arr, - priority_tag<2> /*unused*/) --> decltype(j.template get(), void()) -{ - for (std::size_t i = 0; i < N; ++i) - { - arr[i] = j.at(i).template get(); - } -} - -template -auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/) --> decltype( - arr.reserve(std::declval()), - j.template get(), - void()) -{ - using std::end; - - ConstructibleArrayType ret; - ret.reserve(j.size()); - std::transform(j.begin(), j.end(), - std::inserter(ret, end(ret)), [](const BasicJsonType & i) - { - // get() returns *this, this won't call a from_json - // method when value_type is BasicJsonType - return i.template get(); - }); - arr = std::move(ret); -} - -template -void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, - priority_tag<0> /*unused*/) -{ - using std::end; - - ConstructibleArrayType ret; - std::transform( - j.begin(), j.end(), std::inserter(ret, end(ret)), - [](const BasicJsonType & i) - { - // get() returns *this, this won't call a from_json - // method when value_type is BasicJsonType - return i.template get(); - }); - arr = std::move(ret); -} - -template < typename BasicJsonType, typename ConstructibleArrayType, - enable_if_t < - is_constructible_array_type::value&& - !is_constructible_object_type::value&& - !is_constructible_string_type::value&& - !std::is_same::value&& - !is_basic_json::value, - int > = 0 > -auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr) --> decltype(from_json_array_impl(j, arr, priority_tag<3> {}), -j.template get(), -void()) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + - std::string(j.type_name()))); - } - - from_json_array_impl(j, arr, priority_tag<3> {}); -} - -template -void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_binary())) - { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(j.type_name()))); - } - - bin = *j.template get_ptr(); -} - -template::value, int> = 0> -void from_json(const BasicJsonType& j, ConstructibleObjectType& obj) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_object())) - { - JSON_THROW(type_error::create(302, "type must be object, but is " + std::string(j.type_name()))); - } - - ConstructibleObjectType ret; - auto inner_object = j.template get_ptr(); - using value_type = typename ConstructibleObjectType::value_type; - std::transform( - inner_object->begin(), inner_object->end(), - std::inserter(ret, ret.begin()), - [](typename BasicJsonType::object_t::value_type const & p) - { - return value_type(p.first, p.second.template get()); - }); - obj = std::move(ret); -} - -// overload for arithmetic types, not chosen for basic_json template arguments -// (BooleanType, etc..); note: Is it really necessary to provide explicit -// overloads for boolean_t etc. in case of a custom BooleanType which is not -// an arithmetic type? -template < typename BasicJsonType, typename ArithmeticType, - enable_if_t < - std::is_arithmetic::value&& - !std::is_same::value&& - !std::is_same::value&& - !std::is_same::value&& - !std::is_same::value, - int > = 0 > -void from_json(const BasicJsonType& j, ArithmeticType& val) -{ - switch (static_cast(j)) - { - case value_t::number_unsigned: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_integer: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::number_float: - { - val = static_cast(*j.template get_ptr()); - break; - } - case value_t::boolean: - { - val = static_cast(*j.template get_ptr()); - break; - } - - default: - JSON_THROW(type_error::create(302, "type must be number, but is " + std::string(j.type_name()))); - } -} - -template -void from_json(const BasicJsonType& j, std::pair& p) -{ - p = {j.at(0).template get(), j.at(1).template get()}; -} - -template -void from_json_tuple_impl(const BasicJsonType& j, Tuple& t, index_sequence /*unused*/) -{ - t = std::make_tuple(j.at(Idx).template get::type>()...); -} - -template -void from_json(const BasicJsonType& j, std::tuple& t) -{ - from_json_tuple_impl(j, t, index_sequence_for {}); -} - -template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator, - typename = enable_if_t < !std::is_constructible < - typename BasicJsonType::string_t, Key >::value >> -void from_json(const BasicJsonType& j, std::map& m) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); - } - m.clear(); - for (const auto& p : j) - { - if (JSON_HEDLEY_UNLIKELY(!p.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); - } - m.emplace(p.at(0).template get(), p.at(1).template get()); - } -} - -template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator, - typename = enable_if_t < !std::is_constructible < - typename BasicJsonType::string_t, Key >::value >> -void from_json(const BasicJsonType& j, std::unordered_map& m) -{ - if (JSON_HEDLEY_UNLIKELY(!j.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(j.type_name()))); - } - m.clear(); - for (const auto& p : j) - { - if (JSON_HEDLEY_UNLIKELY(!p.is_array())) - { - JSON_THROW(type_error::create(302, "type must be array, but is " + std::string(p.type_name()))); - } - m.emplace(p.at(0).template get(), p.at(1).template get()); - } -} - -struct from_json_fn -{ - template - auto operator()(const BasicJsonType& j, T& val) const - noexcept(noexcept(from_json(j, val))) - -> decltype(from_json(j, val), void()) - { - return from_json(j, val); - } -}; -} // namespace detail - -/// namespace to hold default `from_json` function -/// to see why this is required: -/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html -namespace -{ -constexpr const auto& from_json = detail::static_const::value; -} // namespace -} // namespace nlohmann - -// #include - - -#include // copy -#include // begin, end -#include // string -#include // tuple, get -#include // is_same, is_constructible, is_floating_point, is_enum, underlying_type -#include // move, forward, declval, pair -#include // valarray -#include // vector - -// #include - - -#include // size_t -#include // input_iterator_tag -#include // string, to_string -#include // tuple_size, get, tuple_element - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template -void int_to_string( string_type& target, std::size_t value ) -{ - // For ADL - using std::to_string; - target = to_string(value); -} -template class iteration_proxy_value -{ - public: - using difference_type = std::ptrdiff_t; - using value_type = iteration_proxy_value; - using pointer = value_type * ; - using reference = value_type & ; - using iterator_category = std::input_iterator_tag; - using string_type = typename std::remove_cv< typename std::remove_reference().key() ) >::type >::type; - - private: - /// the iterator - IteratorType anchor; - /// an index for arrays (used to create key names) - std::size_t array_index = 0; - /// last stringified array index - mutable std::size_t array_index_last = 0; - /// a string representation of the array index - mutable string_type array_index_str = "0"; - /// an empty string (to return a reference for primitive values) - const string_type empty_str = ""; - - public: - explicit iteration_proxy_value(IteratorType it) noexcept : anchor(it) {} - - /// dereference operator (needed for range-based for) - iteration_proxy_value& operator*() - { - return *this; - } - - /// increment operator (needed for range-based for) - iteration_proxy_value& operator++() - { - ++anchor; - ++array_index; - - return *this; - } - - /// equality operator (needed for InputIterator) - bool operator==(const iteration_proxy_value& o) const - { - return anchor == o.anchor; - } - - /// inequality operator (needed for range-based for) - bool operator!=(const iteration_proxy_value& o) const - { - return anchor != o.anchor; - } - - /// return key of the iterator - const string_type& key() const - { - JSON_ASSERT(anchor.m_object != nullptr); - - switch (anchor.m_object->type()) - { - // use integer array index as key - case value_t::array: - { - if (array_index != array_index_last) - { - int_to_string( array_index_str, array_index ); - array_index_last = array_index; - } - return array_index_str; - } - - // use key from the object - case value_t::object: - return anchor.key(); - - // use an empty key for all primitive types - default: - return empty_str; - } - } - - /// return value of the iterator - typename IteratorType::reference value() const - { - return anchor.value(); - } -}; - -/// proxy class for the items() function -template class iteration_proxy -{ - private: - /// the container to iterate - typename IteratorType::reference container; - - public: - /// construct iteration proxy from a container - explicit iteration_proxy(typename IteratorType::reference cont) noexcept - : container(cont) {} - - /// return iterator begin (needed for range-based for) - iteration_proxy_value begin() noexcept - { - return iteration_proxy_value(container.begin()); - } - - /// return iterator end (needed for range-based for) - iteration_proxy_value end() noexcept - { - return iteration_proxy_value(container.end()); - } -}; -// Structured Bindings Support -// For further reference see https://blog.tartanllama.xyz/structured-bindings/ -// And see https://github.com/nlohmann/json/pull/1391 -template = 0> -auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.key()) -{ - return i.key(); -} -// Structured Bindings Support -// For further reference see https://blog.tartanllama.xyz/structured-bindings/ -// And see https://github.com/nlohmann/json/pull/1391 -template = 0> -auto get(const nlohmann::detail::iteration_proxy_value& i) -> decltype(i.value()) -{ - return i.value(); -} -} // namespace detail -} // namespace nlohmann - -// The Addition to the STD Namespace is required to add -// Structured Bindings Support to the iteration_proxy_value class -// For further reference see https://blog.tartanllama.xyz/structured-bindings/ -// And see https://github.com/nlohmann/json/pull/1391 -namespace std -{ -#if defined(__clang__) - // Fix: https://github.com/nlohmann/json/issues/1401 - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wmismatched-tags" -#endif -template -class tuple_size<::nlohmann::detail::iteration_proxy_value> - : public std::integral_constant {}; - -template -class tuple_element> -{ - public: - using type = decltype( - get(std::declval < - ::nlohmann::detail::iteration_proxy_value> ())); -}; -#if defined(__clang__) - #pragma clang diagnostic pop -#endif -} // namespace std - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -////////////////// -// constructors // -////////////////// - -template struct external_constructor; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept - { - j.m_type = value_t::boolean; - j.m_value = b; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s) - { - j.m_type = value_t::string; - j.m_value = s; - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s) - { - j.m_type = value_t::string; - j.m_value = std::move(s); - j.assert_invariant(); - } - - template < typename BasicJsonType, typename CompatibleStringType, - enable_if_t < !std::is_same::value, - int > = 0 > - static void construct(BasicJsonType& j, const CompatibleStringType& str) - { - j.m_type = value_t::string; - j.m_value.string = j.template create(str); - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b) - { - j.m_type = value_t::binary; - typename BasicJsonType::binary_t value{b}; - j.m_value = value; - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b) - { - j.m_type = value_t::binary; - typename BasicJsonType::binary_t value{std::move(b)}; - j.m_value = value; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept - { - j.m_type = value_t::number_float; - j.m_value = val; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept - { - j.m_type = value_t::number_unsigned; - j.m_value = val; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept - { - j.m_type = value_t::number_integer; - j.m_value = val; - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr) - { - j.m_type = value_t::array; - j.m_value = arr; - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr) - { - j.m_type = value_t::array; - j.m_value = std::move(arr); - j.assert_invariant(); - } - - template < typename BasicJsonType, typename CompatibleArrayType, - enable_if_t < !std::is_same::value, - int > = 0 > - static void construct(BasicJsonType& j, const CompatibleArrayType& arr) - { - using std::begin; - using std::end; - j.m_type = value_t::array; - j.m_value.array = j.template create(begin(arr), end(arr)); - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, const std::vector& arr) - { - j.m_type = value_t::array; - j.m_value = value_t::array; - j.m_value.array->reserve(arr.size()); - for (const bool x : arr) - { - j.m_value.array->push_back(x); - } - j.assert_invariant(); - } - - template::value, int> = 0> - static void construct(BasicJsonType& j, const std::valarray& arr) - { - j.m_type = value_t::array; - j.m_value = value_t::array; - j.m_value.array->resize(arr.size()); - if (arr.size() > 0) - { - std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin()); - } - j.assert_invariant(); - } -}; - -template<> -struct external_constructor -{ - template - static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj) - { - j.m_type = value_t::object; - j.m_value = obj; - j.assert_invariant(); - } - - template - static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj) - { - j.m_type = value_t::object; - j.m_value = std::move(obj); - j.assert_invariant(); - } - - template < typename BasicJsonType, typename CompatibleObjectType, - enable_if_t < !std::is_same::value, int > = 0 > - static void construct(BasicJsonType& j, const CompatibleObjectType& obj) - { - using std::begin; - using std::end; - - j.m_type = value_t::object; - j.m_value.object = j.template create(begin(obj), end(obj)); - j.assert_invariant(); - } -}; - -///////////// -// to_json // -///////////// - -template::value, int> = 0> -void to_json(BasicJsonType& j, T b) noexcept -{ - external_constructor::construct(j, b); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, const CompatibleString& s) -{ - external_constructor::construct(j, s); -} - -template -void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s) -{ - external_constructor::construct(j, std::move(s)); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, FloatType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept -{ - external_constructor::construct(j, static_cast(val)); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, EnumType e) noexcept -{ - using underlying_type = typename std::underlying_type::type; - external_constructor::construct(j, static_cast(e)); -} - -template -void to_json(BasicJsonType& j, const std::vector& e) -{ - external_constructor::construct(j, e); -} - -template < typename BasicJsonType, typename CompatibleArrayType, - enable_if_t < is_compatible_array_type::value&& - !is_compatible_object_type::value&& - !is_compatible_string_type::value&& - !std::is_same::value&& - !is_basic_json::value, - int > = 0 > -void to_json(BasicJsonType& j, const CompatibleArrayType& arr) -{ - external_constructor::construct(j, arr); -} - -template -void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin) -{ - external_constructor::construct(j, bin); -} - -template::value, int> = 0> -void to_json(BasicJsonType& j, const std::valarray& arr) -{ - external_constructor::construct(j, std::move(arr)); -} - -template -void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr) -{ - external_constructor::construct(j, std::move(arr)); -} - -template < typename BasicJsonType, typename CompatibleObjectType, - enable_if_t < is_compatible_object_type::value&& !is_basic_json::value, int > = 0 > -void to_json(BasicJsonType& j, const CompatibleObjectType& obj) -{ - external_constructor::construct(j, obj); -} - -template -void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj) -{ - external_constructor::construct(j, std::move(obj)); -} - -template < - typename BasicJsonType, typename T, std::size_t N, - enable_if_t < !std::is_constructible::value, - int > = 0 > -void to_json(BasicJsonType& j, const T(&arr)[N]) -{ - external_constructor::construct(j, arr); -} - -template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible::value&& std::is_constructible::value, int > = 0 > -void to_json(BasicJsonType& j, const std::pair& p) -{ - j = { p.first, p.second }; -} - -// for https://github.com/nlohmann/json/pull/1134 -template>::value, int> = 0> -void to_json(BasicJsonType& j, const T& b) -{ - j = { {b.key(), b.value()} }; -} - -template -void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence /*unused*/) -{ - j = { std::get(t)... }; -} - -template::value, int > = 0> -void to_json(BasicJsonType& j, const T& t) -{ - to_json_tuple_impl(j, t, make_index_sequence::value> {}); -} - -struct to_json_fn -{ - template - auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward(val)))) - -> decltype(to_json(j, std::forward(val)), void()) - { - return to_json(j, std::forward(val)); - } -}; -} // namespace detail - -/// namespace to hold default `to_json` function -namespace -{ -constexpr const auto& to_json = detail::static_const::value; -} // namespace -} // namespace nlohmann - - -namespace nlohmann -{ - -template -struct adl_serializer -{ - /*! - @brief convert a JSON value to any value type - - This function is usually called by the `get()` function of the - @ref basic_json class (either explicit or via conversion operators). - - @param[in] j JSON value to read from - @param[in,out] val value to write to - */ - template - static auto from_json(BasicJsonType&& j, ValueType& val) noexcept( - noexcept(::nlohmann::from_json(std::forward(j), val))) - -> decltype(::nlohmann::from_json(std::forward(j), val), void()) - { - ::nlohmann::from_json(std::forward(j), val); - } - - /*! - @brief convert any value type to a JSON value - - This function is usually called by the constructors of the @ref basic_json - class. - - @param[in,out] j JSON value to write to - @param[in] val value to read from - */ - template - static auto to_json(BasicJsonType& j, ValueType&& val) noexcept( - noexcept(::nlohmann::to_json(j, std::forward(val)))) - -> decltype(::nlohmann::to_json(j, std::forward(val)), void()) - { - ::nlohmann::to_json(j, std::forward(val)); - } -}; - -} // namespace nlohmann - -// #include - - -#include // uint8_t -#include // tie -#include // move - -namespace nlohmann -{ - -/*! -@brief an internal type for a backed binary type - -This type extends the template parameter @a BinaryType provided to `basic_json` -with a subtype used by BSON and MessagePack. This type exists so that the user -does not have to specify a type themselves with a specific naming scheme in -order to override the binary type. - -@tparam BinaryType container to store bytes (`std::vector` by - default) - -@since version 3.8.0 -*/ -template -class byte_container_with_subtype : public BinaryType -{ - public: - /// the type of the underlying container - using container_type = BinaryType; - - byte_container_with_subtype() noexcept(noexcept(container_type())) - : container_type() - {} - - byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b))) - : container_type(b) - {} - - byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b)))) - : container_type(std::move(b)) - {} - - byte_container_with_subtype(const container_type& b, std::uint8_t subtype) noexcept(noexcept(container_type(b))) - : container_type(b) - , m_subtype(subtype) - , m_has_subtype(true) - {} - - byte_container_with_subtype(container_type&& b, std::uint8_t subtype) noexcept(noexcept(container_type(std::move(b)))) - : container_type(std::move(b)) - , m_subtype(subtype) - , m_has_subtype(true) - {} - - bool operator==(const byte_container_with_subtype& rhs) const - { - return std::tie(static_cast(*this), m_subtype, m_has_subtype) == - std::tie(static_cast(rhs), rhs.m_subtype, rhs.m_has_subtype); - } - - bool operator!=(const byte_container_with_subtype& rhs) const - { - return !(rhs == *this); - } - - /*! - @brief sets the binary subtype - - Sets the binary subtype of the value, also flags a binary JSON value as - having a subtype, which has implications for serialization. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @sa @ref subtype() -- return the binary subtype - @sa @ref clear_subtype() -- clears the binary subtype - @sa @ref has_subtype() -- returns whether or not the binary value has a - subtype - - @since version 3.8.0 - */ - void set_subtype(std::uint8_t subtype) noexcept - { - m_subtype = subtype; - m_has_subtype = true; - } - - /*! - @brief return the binary subtype - - Returns the numerical subtype of the value if it has a subtype. If it does - not have a subtype, this function will return size_t(-1) as a sentinel - value. - - @return the numerical subtype of the binary value - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @sa @ref set_subtype() -- sets the binary subtype - @sa @ref clear_subtype() -- clears the binary subtype - @sa @ref has_subtype() -- returns whether or not the binary value has a - subtype - - @since version 3.8.0 - */ - constexpr std::uint8_t subtype() const noexcept - { - return m_subtype; - } - - /*! - @brief return whether the value has a subtype - - @return whether the value has a subtype - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @sa @ref subtype() -- return the binary subtype - @sa @ref set_subtype() -- sets the binary subtype - @sa @ref clear_subtype() -- clears the binary subtype - - @since version 3.8.0 - */ - constexpr bool has_subtype() const noexcept - { - return m_has_subtype; - } - - /*! - @brief clears the binary subtype - - Clears the binary subtype and flags the value as not having a subtype, which - has implications for serialization; for instance MessagePack will prefer the - bin family over the ext family. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @sa @ref subtype() -- return the binary subtype - @sa @ref set_subtype() -- sets the binary subtype - @sa @ref has_subtype() -- returns whether or not the binary value has a - subtype - - @since version 3.8.0 - */ - void clear_subtype() noexcept - { - m_subtype = 0; - m_has_subtype = false; - } - - private: - std::uint8_t m_subtype = 0; - bool m_has_subtype = false; -}; - -} // namespace nlohmann - -// #include - -// #include - -// #include - -// #include - - -#include // size_t, uint8_t -#include // hash - -namespace nlohmann -{ -namespace detail -{ - -// boost::hash_combine -inline std::size_t combine(std::size_t seed, std::size_t h) noexcept -{ - seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U); - return seed; -} - -/*! -@brief hash a JSON value - -The hash function tries to rely on std::hash where possible. Furthermore, the -type of the JSON value is taken into account to have different hash values for -null, 0, 0U, and false, etc. - -@tparam BasicJsonType basic_json specialization -@param j JSON value to hash -@return hash value of j -*/ -template -std::size_t hash(const BasicJsonType& j) -{ - using string_t = typename BasicJsonType::string_t; - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - - const auto type = static_cast(j.type()); - switch (j.type()) - { - case BasicJsonType::value_t::null: - case BasicJsonType::value_t::discarded: - { - return combine(type, 0); - } - - case BasicJsonType::value_t::object: - { - auto seed = combine(type, j.size()); - for (const auto& element : j.items()) - { - const auto h = std::hash {}(element.key()); - seed = combine(seed, h); - seed = combine(seed, hash(element.value())); - } - return seed; - } - - case BasicJsonType::value_t::array: - { - auto seed = combine(type, j.size()); - for (const auto& element : j) - { - seed = combine(seed, hash(element)); - } - return seed; - } - - case BasicJsonType::value_t::string: - { - const auto h = std::hash {}(j.template get_ref()); - return combine(type, h); - } - - case BasicJsonType::value_t::boolean: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } - - case BasicJsonType::value_t::number_integer: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } - - case BasicJsonType::value_t::number_unsigned: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } - - case BasicJsonType::value_t::number_float: - { - const auto h = std::hash {}(j.template get()); - return combine(type, h); - } - - case BasicJsonType::value_t::binary: - { - auto seed = combine(type, j.get_binary().size()); - const auto h = std::hash {}(j.get_binary().has_subtype()); - seed = combine(seed, h); - seed = combine(seed, j.get_binary().subtype()); - for (const auto byte : j.get_binary()) - { - seed = combine(seed, std::hash {}(byte)); - } - return seed; - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - return 0; // LCOV_EXCL_LINE - } -} - -} // namespace detail -} // namespace nlohmann - -// #include - - -#include // generate_n -#include // array -#include // ldexp -#include // size_t -#include // uint8_t, uint16_t, uint32_t, uint64_t -#include // snprintf -#include // memcpy -#include // back_inserter -#include // numeric_limits -#include // char_traits, string -#include // make_pair, move - -// #include - -// #include - - -#include // array -#include // size_t -#include //FILE * -#include // strlen -#include // istream -#include // begin, end, iterator_traits, random_access_iterator_tag, distance, next -#include // shared_ptr, make_shared, addressof -#include // accumulate -#include // string, char_traits -#include // enable_if, is_base_of, is_pointer, is_integral, remove_pointer -#include // pair, declval - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -/// the supported input formats -enum class input_format_t { json, cbor, msgpack, ubjson, bson }; - -//////////////////// -// input adapters // -//////////////////// - -/*! -Input adapter for stdio file access. This adapter read only 1 byte and do not use any - buffer. This adapter is a very low level adapter. -*/ -class file_input_adapter -{ - public: - using char_type = char; - - JSON_HEDLEY_NON_NULL(2) - explicit file_input_adapter(std::FILE* f) noexcept - : m_file(f) - {} - - // make class move-only - file_input_adapter(const file_input_adapter&) = delete; - file_input_adapter(file_input_adapter&&) = default; - file_input_adapter& operator=(const file_input_adapter&) = delete; - file_input_adapter& operator=(file_input_adapter&&) = delete; - - std::char_traits::int_type get_character() noexcept - { - return std::fgetc(m_file); - } - - private: - /// the file pointer to read from - std::FILE* m_file; -}; - - -/*! -Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at -beginning of input. Does not support changing the underlying std::streambuf -in mid-input. Maintains underlying std::istream and std::streambuf to support -subsequent use of standard std::istream operations to process any input -characters following those used in parsing the JSON input. Clears the -std::istream flags; any input errors (e.g., EOF) will be detected by the first -subsequent call for input from the std::istream. -*/ -class input_stream_adapter -{ - public: - using char_type = char; - - ~input_stream_adapter() - { - // clear stream flags; we use underlying streambuf I/O, do not - // maintain ifstream flags, except eof - if (is != nullptr) - { - is->clear(is->rdstate() & std::ios::eofbit); - } - } - - explicit input_stream_adapter(std::istream& i) - : is(&i), sb(i.rdbuf()) - {} - - // delete because of pointer members - input_stream_adapter(const input_stream_adapter&) = delete; - input_stream_adapter& operator=(input_stream_adapter&) = delete; - input_stream_adapter& operator=(input_stream_adapter&& rhs) = delete; - - input_stream_adapter(input_stream_adapter&& rhs) noexcept : is(rhs.is), sb(rhs.sb) - { - rhs.is = nullptr; - rhs.sb = nullptr; - } - - // std::istream/std::streambuf use std::char_traits::to_int_type, to - // ensure that std::char_traits::eof() and the character 0xFF do not - // end up as the same value, eg. 0xFFFFFFFF. - std::char_traits::int_type get_character() - { - auto res = sb->sbumpc(); - // set eof manually, as we don't use the istream interface. - if (JSON_HEDLEY_UNLIKELY(res == EOF)) - { - is->clear(is->rdstate() | std::ios::eofbit); - } - return res; - } - - private: - /// the associated input stream - std::istream* is = nullptr; - std::streambuf* sb = nullptr; -}; - -// General-purpose iterator-based adapter. It might not be as fast as -// theoretically possible for some containers, but it is extremely versatile. -template -class iterator_input_adapter -{ - public: - using char_type = typename std::iterator_traits::value_type; - - iterator_input_adapter(IteratorType first, IteratorType last) - : current(std::move(first)), end(std::move(last)) {} - - typename std::char_traits::int_type get_character() - { - if (JSON_HEDLEY_LIKELY(current != end)) - { - auto result = std::char_traits::to_int_type(*current); - std::advance(current, 1); - return result; - } - else - { - return std::char_traits::eof(); - } - } - - private: - IteratorType current; - IteratorType end; - - template - friend struct wide_string_input_helper; - - bool empty() const - { - return current == end; - } - -}; - - -template -struct wide_string_input_helper; - -template -struct wide_string_input_helper -{ - // UTF-32 - static void fill_buffer(BaseInputAdapter& input, - std::array::int_type, 4>& utf8_bytes, - size_t& utf8_bytes_index, - size_t& utf8_bytes_filled) - { - utf8_bytes_index = 0; - - if (JSON_HEDLEY_UNLIKELY(input.empty())) - { - utf8_bytes[0] = std::char_traits::eof(); - utf8_bytes_filled = 1; - } - else - { - // get the current character - const auto wc = input.get_character(); - - // UTF-32 to UTF-8 encoding - if (wc < 0x80) - { - utf8_bytes[0] = static_cast::int_type>(wc); - utf8_bytes_filled = 1; - } - else if (wc <= 0x7FF) - { - utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u) & 0x1Fu)); - utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 2; - } - else if (wc <= 0xFFFF) - { - utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u) & 0x0Fu)); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 3; - } - else if (wc <= 0x10FFFF) - { - utf8_bytes[0] = static_cast::int_type>(0xF0u | ((static_cast(wc) >> 18u) & 0x07u)); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 12u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); - utf8_bytes[3] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 4; - } - else - { - // unknown character - utf8_bytes[0] = static_cast::int_type>(wc); - utf8_bytes_filled = 1; - } - } - } -}; - -template -struct wide_string_input_helper -{ - // UTF-16 - static void fill_buffer(BaseInputAdapter& input, - std::array::int_type, 4>& utf8_bytes, - size_t& utf8_bytes_index, - size_t& utf8_bytes_filled) - { - utf8_bytes_index = 0; - - if (JSON_HEDLEY_UNLIKELY(input.empty())) - { - utf8_bytes[0] = std::char_traits::eof(); - utf8_bytes_filled = 1; - } - else - { - // get the current character - const auto wc = input.get_character(); - - // UTF-16 to UTF-8 encoding - if (wc < 0x80) - { - utf8_bytes[0] = static_cast::int_type>(wc); - utf8_bytes_filled = 1; - } - else if (wc <= 0x7FF) - { - utf8_bytes[0] = static_cast::int_type>(0xC0u | ((static_cast(wc) >> 6u))); - utf8_bytes[1] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 2; - } - else if (0xD800 > wc || wc >= 0xE000) - { - utf8_bytes[0] = static_cast::int_type>(0xE0u | ((static_cast(wc) >> 12u))); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((static_cast(wc) >> 6u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | (static_cast(wc) & 0x3Fu)); - utf8_bytes_filled = 3; - } - else - { - if (JSON_HEDLEY_UNLIKELY(!input.empty())) - { - const auto wc2 = static_cast(input.get_character()); - const auto charcode = 0x10000u + (((static_cast(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu)); - utf8_bytes[0] = static_cast::int_type>(0xF0u | (charcode >> 18u)); - utf8_bytes[1] = static_cast::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu)); - utf8_bytes[2] = static_cast::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu)); - utf8_bytes[3] = static_cast::int_type>(0x80u | (charcode & 0x3Fu)); - utf8_bytes_filled = 4; - } - else - { - utf8_bytes[0] = static_cast::int_type>(wc); - utf8_bytes_filled = 1; - } - } - } - } -}; - -// Wraps another input apdater to convert wide character types into individual bytes. -template -class wide_string_input_adapter -{ - public: - using char_type = char; - - wide_string_input_adapter(BaseInputAdapter base) - : base_adapter(base) {} - - typename std::char_traits::int_type get_character() noexcept - { - // check if buffer needs to be filled - if (utf8_bytes_index == utf8_bytes_filled) - { - fill_buffer(); - - JSON_ASSERT(utf8_bytes_filled > 0); - JSON_ASSERT(utf8_bytes_index == 0); - } - - // use buffer - JSON_ASSERT(utf8_bytes_filled > 0); - JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled); - return utf8_bytes[utf8_bytes_index++]; - } - - private: - BaseInputAdapter base_adapter; - - template - void fill_buffer() - { - wide_string_input_helper::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled); - } - - /// a buffer for UTF-8 bytes - std::array::int_type, 4> utf8_bytes = {{0, 0, 0, 0}}; - - /// index to the utf8_codes array for the next valid byte - std::size_t utf8_bytes_index = 0; - /// number of valid bytes in the utf8_codes array - std::size_t utf8_bytes_filled = 0; -}; - - -template -struct iterator_input_adapter_factory -{ - using iterator_type = IteratorType; - using char_type = typename std::iterator_traits::value_type; - using adapter_type = iterator_input_adapter; - - static adapter_type create(IteratorType first, IteratorType last) - { - return adapter_type(std::move(first), std::move(last)); - } -}; - -template -struct is_iterator_of_multibyte -{ - using value_type = typename std::iterator_traits::value_type; - enum - { - value = sizeof(value_type) > 1 - }; -}; - -template -struct iterator_input_adapter_factory::value>> -{ - using iterator_type = IteratorType; - using char_type = typename std::iterator_traits::value_type; - using base_adapter_type = iterator_input_adapter; - using adapter_type = wide_string_input_adapter; - - static adapter_type create(IteratorType first, IteratorType last) - { - return adapter_type(base_adapter_type(std::move(first), std::move(last))); - } -}; - -// General purpose iterator-based input -template -typename iterator_input_adapter_factory::adapter_type input_adapter(IteratorType first, IteratorType last) -{ - using factory_type = iterator_input_adapter_factory; - return factory_type::create(first, last); -} - -// Convenience shorthand from container to iterator -template -auto input_adapter(const ContainerType& container) -> decltype(input_adapter(begin(container), end(container))) -{ - // Enable ADL - using std::begin; - using std::end; - - return input_adapter(begin(container), end(container)); -} - -// Special cases with fast paths -inline file_input_adapter input_adapter(std::FILE* file) -{ - return file_input_adapter(file); -} - -inline input_stream_adapter input_adapter(std::istream& stream) -{ - return input_stream_adapter(stream); -} - -inline input_stream_adapter input_adapter(std::istream&& stream) -{ - return input_stream_adapter(stream); -} - -using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval(), std::declval())); - -// Null-delimited strings, and the like. -template < typename CharT, - typename std::enable_if < - std::is_pointer::value&& - !std::is_array::value&& - std::is_integral::type>::value&& - sizeof(typename std::remove_pointer::type) == 1, - int >::type = 0 > -contiguous_bytes_input_adapter input_adapter(CharT b) -{ - auto length = std::strlen(reinterpret_cast(b)); - const auto* ptr = reinterpret_cast(b); - return input_adapter(ptr, ptr + length); -} - -template -auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) -{ - return input_adapter(array, array + N); -} - -// This class only handles inputs of input_buffer_adapter type. -// It's required so that expressions like {ptr, len} can be implicitely casted -// to the correct adapter. -class span_input_adapter -{ - public: - template < typename CharT, - typename std::enable_if < - std::is_pointer::value&& - std::is_integral::type>::value&& - sizeof(typename std::remove_pointer::type) == 1, - int >::type = 0 > - span_input_adapter(CharT b, std::size_t l) - : ia(reinterpret_cast(b), reinterpret_cast(b) + l) {} - - template::iterator_category, std::random_access_iterator_tag>::value, - int>::type = 0> - span_input_adapter(IteratorType first, IteratorType last) - : ia(input_adapter(first, last)) {} - - contiguous_bytes_input_adapter&& get() - { - return std::move(ia); - } - - private: - contiguous_bytes_input_adapter ia; -}; -} // namespace detail -} // namespace nlohmann - -// #include - - -#include -#include // string -#include // move -#include // vector - -// #include - -// #include - - -namespace nlohmann -{ - -/*! -@brief SAX interface - -This class describes the SAX interface used by @ref nlohmann::json::sax_parse. -Each function is called in different situations while the input is parsed. The -boolean return value informs the parser whether to continue processing the -input. -*/ -template -struct json_sax -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - - /*! - @brief a null value was read - @return whether parsing should proceed - */ - virtual bool null() = 0; - - /*! - @brief a boolean value was read - @param[in] val boolean value - @return whether parsing should proceed - */ - virtual bool boolean(bool val) = 0; - - /*! - @brief an integer number was read - @param[in] val integer value - @return whether parsing should proceed - */ - virtual bool number_integer(number_integer_t val) = 0; - - /*! - @brief an unsigned integer number was read - @param[in] val unsigned integer value - @return whether parsing should proceed - */ - virtual bool number_unsigned(number_unsigned_t val) = 0; - - /*! - @brief an floating-point number was read - @param[in] val floating-point value - @param[in] s raw token value - @return whether parsing should proceed - */ - virtual bool number_float(number_float_t val, const string_t& s) = 0; - - /*! - @brief a string was read - @param[in] val string value - @return whether parsing should proceed - @note It is safe to move the passed string. - */ - virtual bool string(string_t& val) = 0; - - /*! - @brief a binary string was read - @param[in] val binary value - @return whether parsing should proceed - @note It is safe to move the passed binary. - */ - virtual bool binary(binary_t& val) = 0; - - /*! - @brief the beginning of an object was read - @param[in] elements number of object elements or -1 if unknown - @return whether parsing should proceed - @note binary formats may report the number of elements - */ - virtual bool start_object(std::size_t elements) = 0; - - /*! - @brief an object key was read - @param[in] val object key - @return whether parsing should proceed - @note It is safe to move the passed string. - */ - virtual bool key(string_t& val) = 0; - - /*! - @brief the end of an object was read - @return whether parsing should proceed - */ - virtual bool end_object() = 0; - - /*! - @brief the beginning of an array was read - @param[in] elements number of array elements or -1 if unknown - @return whether parsing should proceed - @note binary formats may report the number of elements - */ - virtual bool start_array(std::size_t elements) = 0; - - /*! - @brief the end of an array was read - @return whether parsing should proceed - */ - virtual bool end_array() = 0; - - /*! - @brief a parse error occurred - @param[in] position the position in the input where the error occurs - @param[in] last_token the last read token - @param[in] ex an exception object describing the error - @return whether parsing should proceed (must return false) - */ - virtual bool parse_error(std::size_t position, - const std::string& last_token, - const detail::exception& ex) = 0; - - virtual ~json_sax() = default; -}; - - -namespace detail -{ -/*! -@brief SAX implementation to create a JSON value from SAX events - -This class implements the @ref json_sax interface and processes the SAX events -to create a JSON value which makes it basically a DOM parser. The structure or -hierarchy of the JSON value is managed by the stack `ref_stack` which contains -a pointer to the respective array or object for each recursion depth. - -After successful parsing, the value that is passed by reference to the -constructor contains the parsed value. - -@tparam BasicJsonType the JSON type -*/ -template -class json_sax_dom_parser -{ - public: - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - - /*! - @param[in, out] r reference to a JSON value that is manipulated while - parsing - @param[in] allow_exceptions_ whether parse errors yield exceptions - */ - explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true) - : root(r), allow_exceptions(allow_exceptions_) - {} - - // make class move-only - json_sax_dom_parser(const json_sax_dom_parser&) = delete; - json_sax_dom_parser(json_sax_dom_parser&&) = default; - json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete; - json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; - ~json_sax_dom_parser() = default; - - bool null() - { - handle_value(nullptr); - return true; - } - - bool boolean(bool val) - { - handle_value(val); - return true; - } - - bool number_integer(number_integer_t val) - { - handle_value(val); - return true; - } - - bool number_unsigned(number_unsigned_t val) - { - handle_value(val); - return true; - } - - bool number_float(number_float_t val, const string_t& /*unused*/) - { - handle_value(val); - return true; - } - - bool string(string_t& val) - { - handle_value(val); - return true; - } - - bool binary(binary_t& val) - { - handle_value(std::move(val)); - return true; - } - - bool start_object(std::size_t len) - { - ref_stack.push_back(handle_value(BasicJsonType::value_t::object)); - - if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, - "excessive object size: " + std::to_string(len))); - } - - return true; - } - - bool key(string_t& val) - { - // add null at given key and store the reference for later - object_element = &(ref_stack.back()->m_value.object->operator[](val)); - return true; - } - - bool end_object() - { - ref_stack.pop_back(); - return true; - } - - bool start_array(std::size_t len) - { - ref_stack.push_back(handle_value(BasicJsonType::value_t::array)); - - if (JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, - "excessive array size: " + std::to_string(len))); - } - - return true; - } - - bool end_array() - { - ref_stack.pop_back(); - return true; - } - - template - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, - const Exception& ex) - { - errored = true; - static_cast(ex); - if (allow_exceptions) - { - JSON_THROW(ex); - } - return false; - } - - constexpr bool is_errored() const - { - return errored; - } - - private: - /*! - @invariant If the ref stack is empty, then the passed value will be the new - root. - @invariant If the ref stack contains a value, then it is an array or an - object to which we can add elements - */ - template - JSON_HEDLEY_RETURNS_NON_NULL - BasicJsonType* handle_value(Value&& v) - { - if (ref_stack.empty()) - { - root = BasicJsonType(std::forward(v)); - return &root; - } - - JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); - - if (ref_stack.back()->is_array()) - { - ref_stack.back()->m_value.array->emplace_back(std::forward(v)); - return &(ref_stack.back()->m_value.array->back()); - } - - JSON_ASSERT(ref_stack.back()->is_object()); - JSON_ASSERT(object_element); - *object_element = BasicJsonType(std::forward(v)); - return object_element; - } - - /// the parsed JSON value - BasicJsonType& root; - /// stack to model hierarchy of values - std::vector ref_stack {}; - /// helper to hold the reference for the next object element - BasicJsonType* object_element = nullptr; - /// whether a syntax error occurred - bool errored = false; - /// whether to throw exceptions in case of errors - const bool allow_exceptions = true; -}; - -template -class json_sax_dom_callback_parser -{ - public: - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using parser_callback_t = typename BasicJsonType::parser_callback_t; - using parse_event_t = typename BasicJsonType::parse_event_t; - - json_sax_dom_callback_parser(BasicJsonType& r, - const parser_callback_t cb, - const bool allow_exceptions_ = true) - : root(r), callback(cb), allow_exceptions(allow_exceptions_) - { - keep_stack.push_back(true); - } - - // make class move-only - json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete; - json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; - json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete; - json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; - ~json_sax_dom_callback_parser() = default; - - bool null() - { - handle_value(nullptr); - return true; - } - - bool boolean(bool val) - { - handle_value(val); - return true; - } - - bool number_integer(number_integer_t val) - { - handle_value(val); - return true; - } - - bool number_unsigned(number_unsigned_t val) - { - handle_value(val); - return true; - } - - bool number_float(number_float_t val, const string_t& /*unused*/) - { - handle_value(val); - return true; - } - - bool string(string_t& val) - { - handle_value(val); - return true; - } - - bool binary(binary_t& val) - { - handle_value(std::move(val)); - return true; - } - - bool start_object(std::size_t len) - { - // check callback for object start - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::object_start, discarded); - keep_stack.push_back(keep); - - auto val = handle_value(BasicJsonType::value_t::object, true); - ref_stack.push_back(val.second); - - // check object limit - if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len))); - } - - return true; - } - - bool key(string_t& val) - { - BasicJsonType k = BasicJsonType(val); - - // check callback for key - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::key, k); - key_keep_stack.push_back(keep); - - // add discarded value at given key and store the reference for later - if (keep && ref_stack.back()) - { - object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded); - } - - return true; - } - - bool end_object() - { - if (ref_stack.back() && !callback(static_cast(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back())) - { - // discard object - *ref_stack.back() = discarded; - } - - JSON_ASSERT(!ref_stack.empty()); - JSON_ASSERT(!keep_stack.empty()); - ref_stack.pop_back(); - keep_stack.pop_back(); - - if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured()) - { - // remove discarded value - for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it) - { - if (it->is_discarded()) - { - ref_stack.back()->erase(it); - break; - } - } - } - - return true; - } - - bool start_array(std::size_t len) - { - const bool keep = callback(static_cast(ref_stack.size()), parse_event_t::array_start, discarded); - keep_stack.push_back(keep); - - auto val = handle_value(BasicJsonType::value_t::array, true); - ref_stack.push_back(val.second); - - // check array limit - if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != std::size_t(-1) && len > ref_stack.back()->max_size())) - { - JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len))); - } - - return true; - } - - bool end_array() - { - bool keep = true; - - if (ref_stack.back()) - { - keep = callback(static_cast(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back()); - if (!keep) - { - // discard array - *ref_stack.back() = discarded; - } - } - - JSON_ASSERT(!ref_stack.empty()); - JSON_ASSERT(!keep_stack.empty()); - ref_stack.pop_back(); - keep_stack.pop_back(); - - // remove discarded value - if (!keep && !ref_stack.empty() && ref_stack.back()->is_array()) - { - ref_stack.back()->m_value.array->pop_back(); - } - - return true; - } - - template - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, - const Exception& ex) - { - errored = true; - static_cast(ex); - if (allow_exceptions) - { - JSON_THROW(ex); - } - return false; - } - - constexpr bool is_errored() const - { - return errored; - } - - private: - /*! - @param[in] v value to add to the JSON value we build during parsing - @param[in] skip_callback whether we should skip calling the callback - function; this is required after start_array() and - start_object() SAX events, because otherwise we would call the - callback function with an empty array or object, respectively. - - @invariant If the ref stack is empty, then the passed value will be the new - root. - @invariant If the ref stack contains a value, then it is an array or an - object to which we can add elements - - @return pair of boolean (whether value should be kept) and pointer (to the - passed value in the ref_stack hierarchy; nullptr if not kept) - */ - template - std::pair handle_value(Value&& v, const bool skip_callback = false) - { - JSON_ASSERT(!keep_stack.empty()); - - // do not handle this value if we know it would be added to a discarded - // container - if (!keep_stack.back()) - { - return {false, nullptr}; - } - - // create value - auto value = BasicJsonType(std::forward(v)); - - // check callback - const bool keep = skip_callback || callback(static_cast(ref_stack.size()), parse_event_t::value, value); - - // do not handle this value if we just learnt it shall be discarded - if (!keep) - { - return {false, nullptr}; - } - - if (ref_stack.empty()) - { - root = std::move(value); - return {true, &root}; - } - - // skip this value if we already decided to skip the parent - // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360) - if (!ref_stack.back()) - { - return {false, nullptr}; - } - - // we now only expect arrays and objects - JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object()); - - // array - if (ref_stack.back()->is_array()) - { - ref_stack.back()->m_value.array->push_back(std::move(value)); - return {true, &(ref_stack.back()->m_value.array->back())}; - } - - // object - JSON_ASSERT(ref_stack.back()->is_object()); - // check if we should store an element for the current key - JSON_ASSERT(!key_keep_stack.empty()); - const bool store_element = key_keep_stack.back(); - key_keep_stack.pop_back(); - - if (!store_element) - { - return {false, nullptr}; - } - - JSON_ASSERT(object_element); - *object_element = std::move(value); - return {true, object_element}; - } - - /// the parsed JSON value - BasicJsonType& root; - /// stack to model hierarchy of values - std::vector ref_stack {}; - /// stack to manage which values to keep - std::vector keep_stack {}; - /// stack to manage which object keys to keep - std::vector key_keep_stack {}; - /// helper to hold the reference for the next object element - BasicJsonType* object_element = nullptr; - /// whether a syntax error occurred - bool errored = false; - /// callback function - const parser_callback_t callback = nullptr; - /// whether to throw exceptions in case of errors - const bool allow_exceptions = true; - /// a discarded value for the callback - BasicJsonType discarded = BasicJsonType::value_t::discarded; -}; - -template -class json_sax_acceptor -{ - public: - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - - bool null() - { - return true; - } - - bool boolean(bool /*unused*/) - { - return true; - } - - bool number_integer(number_integer_t /*unused*/) - { - return true; - } - - bool number_unsigned(number_unsigned_t /*unused*/) - { - return true; - } - - bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) - { - return true; - } - - bool string(string_t& /*unused*/) - { - return true; - } - - bool binary(binary_t& /*unused*/) - { - return true; - } - - bool start_object(std::size_t /*unused*/ = std::size_t(-1)) - { - return true; - } - - bool key(string_t& /*unused*/) - { - return true; - } - - bool end_object() - { - return true; - } - - bool start_array(std::size_t /*unused*/ = std::size_t(-1)) - { - return true; - } - - bool end_array() - { - return true; - } - - bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) - { - return false; - } -}; -} // namespace detail - -} // namespace nlohmann - -// #include - - -#include // array -#include // localeconv -#include // size_t -#include // snprintf -#include // strtof, strtod, strtold, strtoll, strtoull -#include // initializer_list -#include // char_traits, string -#include // move -#include // vector - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -/////////// -// lexer // -/////////// - -template -class lexer_base -{ - public: - /// token types for the parser - enum class token_type - { - uninitialized, ///< indicating the scanner is uninitialized - literal_true, ///< the `true` literal - literal_false, ///< the `false` literal - literal_null, ///< the `null` literal - value_string, ///< a string -- use get_string() for actual value - value_unsigned, ///< an unsigned integer -- use get_number_unsigned() for actual value - value_integer, ///< a signed integer -- use get_number_integer() for actual value - value_float, ///< an floating point number -- use get_number_float() for actual value - begin_array, ///< the character for array begin `[` - begin_object, ///< the character for object begin `{` - end_array, ///< the character for array end `]` - end_object, ///< the character for object end `}` - name_separator, ///< the name separator `:` - value_separator, ///< the value separator `,` - parse_error, ///< indicating a parse error - end_of_input, ///< indicating the end of the input buffer - literal_or_value ///< a literal or the begin of a value (only for diagnostics) - }; - - /// return name of values of type token_type (only used for errors) - JSON_HEDLEY_RETURNS_NON_NULL - JSON_HEDLEY_CONST - static const char* token_type_name(const token_type t) noexcept - { - switch (t) - { - case token_type::uninitialized: - return ""; - case token_type::literal_true: - return "true literal"; - case token_type::literal_false: - return "false literal"; - case token_type::literal_null: - return "null literal"; - case token_type::value_string: - return "string literal"; - case token_type::value_unsigned: - case token_type::value_integer: - case token_type::value_float: - return "number literal"; - case token_type::begin_array: - return "'['"; - case token_type::begin_object: - return "'{'"; - case token_type::end_array: - return "']'"; - case token_type::end_object: - return "'}'"; - case token_type::name_separator: - return "':'"; - case token_type::value_separator: - return "','"; - case token_type::parse_error: - return ""; - case token_type::end_of_input: - return "end of input"; - case token_type::literal_or_value: - return "'[', '{', or a literal"; - // LCOV_EXCL_START - default: // catch non-enum values - return "unknown token"; - // LCOV_EXCL_STOP - } - } -}; -/*! -@brief lexical analysis - -This class organizes the lexical analysis during JSON deserialization. -*/ -template -class lexer : public lexer_base -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using char_type = typename InputAdapterType::char_type; - using char_int_type = typename std::char_traits::int_type; - - public: - using token_type = typename lexer_base::token_type; - - explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) - : ia(std::move(adapter)) - , ignore_comments(ignore_comments_) - , decimal_point_char(static_cast(get_decimal_point())) - {} - - // delete because of pointer members - lexer(const lexer&) = delete; - lexer(lexer&&) = default; - lexer& operator=(lexer&) = delete; - lexer& operator=(lexer&&) = default; - ~lexer() = default; - - private: - ///////////////////// - // locales - ///////////////////// - - /// return the locale-dependent decimal point - JSON_HEDLEY_PURE - static char get_decimal_point() noexcept - { - const auto* loc = localeconv(); - JSON_ASSERT(loc != nullptr); - return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point); - } - - ///////////////////// - // scan functions - ///////////////////// - - /*! - @brief get codepoint from 4 hex characters following `\u` - - For input "\u c1 c2 c3 c4" the codepoint is: - (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4 - = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0) - - Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f' - must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The - conversion is done by subtracting the offset (0x30, 0x37, and 0x57) - between the ASCII value of the character and the desired integer value. - - @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or - non-hex character) - */ - int get_codepoint() - { - // this function only makes sense after reading `\u` - JSON_ASSERT(current == 'u'); - int codepoint = 0; - - const auto factors = { 12u, 8u, 4u, 0u }; - for (const auto factor : factors) - { - get(); - - if (current >= '0' && current <= '9') - { - codepoint += static_cast((static_cast(current) - 0x30u) << factor); - } - else if (current >= 'A' && current <= 'F') - { - codepoint += static_cast((static_cast(current) - 0x37u) << factor); - } - else if (current >= 'a' && current <= 'f') - { - codepoint += static_cast((static_cast(current) - 0x57u) << factor); - } - else - { - return -1; - } - } - - JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF); - return codepoint; - } - - /*! - @brief check if the next byte(s) are inside a given range - - Adds the current byte and, for each passed range, reads a new byte and - checks if it is inside the range. If a violation was detected, set up an - error message and return false. Otherwise, return true. - - @param[in] ranges list of integers; interpreted as list of pairs of - inclusive lower and upper bound, respectively - - @pre The passed list @a ranges must have 2, 4, or 6 elements; that is, - 1, 2, or 3 pairs. This precondition is enforced by an assertion. - - @return true if and only if no range violation was detected - */ - bool next_byte_in_range(std::initializer_list ranges) - { - JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6); - add(current); - - for (auto range = ranges.begin(); range != ranges.end(); ++range) - { - get(); - if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) - { - add(current); - } - else - { - error_message = "invalid string: ill-formed UTF-8 byte"; - return false; - } - } - - return true; - } - - /*! - @brief scan a string literal - - This function scans a string according to Sect. 7 of RFC 7159. While - scanning, bytes are escaped and copied into buffer token_buffer. Then the - function returns successfully, token_buffer is *not* null-terminated (as it - may contain \0 bytes), and token_buffer.size() is the number of bytes in the - string. - - @return token_type::value_string if string could be successfully scanned, - token_type::parse_error otherwise - - @note In case of errors, variable error_message contains a textual - description. - */ - token_type scan_string() - { - // reset token_buffer (ignore opening quote) - reset(); - - // we entered the function by reading an open quote - JSON_ASSERT(current == '\"'); - - while (true) - { - // get next character - switch (get()) - { - // end of file while parsing string - case std::char_traits::eof(): - { - error_message = "invalid string: missing closing quote"; - return token_type::parse_error; - } - - // closing quote - case '\"': - { - return token_type::value_string; - } - - // escapes - case '\\': - { - switch (get()) - { - // quotation mark - case '\"': - add('\"'); - break; - // reverse solidus - case '\\': - add('\\'); - break; - // solidus - case '/': - add('/'); - break; - // backspace - case 'b': - add('\b'); - break; - // form feed - case 'f': - add('\f'); - break; - // line feed - case 'n': - add('\n'); - break; - // carriage return - case 'r': - add('\r'); - break; - // tab - case 't': - add('\t'); - break; - - // unicode escapes - case 'u': - { - const int codepoint1 = get_codepoint(); - int codepoint = codepoint1; // start with codepoint1 - - if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1)) - { - error_message = "invalid string: '\\u' must be followed by 4 hex digits"; - return token_type::parse_error; - } - - // check if code point is a high surrogate - if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF) - { - // expect next \uxxxx entry - if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u')) - { - const int codepoint2 = get_codepoint(); - - if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1)) - { - error_message = "invalid string: '\\u' must be followed by 4 hex digits"; - return token_type::parse_error; - } - - // check if codepoint2 is a low surrogate - if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF)) - { - // overwrite codepoint - codepoint = static_cast( - // high surrogate occupies the most significant 22 bits - (static_cast(codepoint1) << 10u) - // low surrogate occupies the least significant 15 bits - + static_cast(codepoint2) - // there is still the 0xD800, 0xDC00 and 0x10000 noise - // in the result so we have to subtract with: - // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00 - - 0x35FDC00u); - } - else - { - error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; - return token_type::parse_error; - } - } - else - { - error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF"; - return token_type::parse_error; - } - } - else - { - if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF)) - { - error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF"; - return token_type::parse_error; - } - } - - // result of the above calculation yields a proper codepoint - JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF); - - // translate codepoint into bytes - if (codepoint < 0x80) - { - // 1-byte characters: 0xxxxxxx (ASCII) - add(static_cast(codepoint)); - } - else if (codepoint <= 0x7FF) - { - // 2-byte characters: 110xxxxx 10xxxxxx - add(static_cast(0xC0u | (static_cast(codepoint) >> 6u))); - add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); - } - else if (codepoint <= 0xFFFF) - { - // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx - add(static_cast(0xE0u | (static_cast(codepoint) >> 12u))); - add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); - add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); - } - else - { - // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx - add(static_cast(0xF0u | (static_cast(codepoint) >> 18u))); - add(static_cast(0x80u | ((static_cast(codepoint) >> 12u) & 0x3Fu))); - add(static_cast(0x80u | ((static_cast(codepoint) >> 6u) & 0x3Fu))); - add(static_cast(0x80u | (static_cast(codepoint) & 0x3Fu))); - } - - break; - } - - // other characters after escape - default: - error_message = "invalid string: forbidden character after backslash"; - return token_type::parse_error; - } - - break; - } - - // invalid control characters - case 0x00: - { - error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000"; - return token_type::parse_error; - } - - case 0x01: - { - error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001"; - return token_type::parse_error; - } - - case 0x02: - { - error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002"; - return token_type::parse_error; - } - - case 0x03: - { - error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003"; - return token_type::parse_error; - } - - case 0x04: - { - error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004"; - return token_type::parse_error; - } - - case 0x05: - { - error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005"; - return token_type::parse_error; - } - - case 0x06: - { - error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006"; - return token_type::parse_error; - } - - case 0x07: - { - error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007"; - return token_type::parse_error; - } - - case 0x08: - { - error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b"; - return token_type::parse_error; - } - - case 0x09: - { - error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t"; - return token_type::parse_error; - } - - case 0x0A: - { - error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n"; - return token_type::parse_error; - } - - case 0x0B: - { - error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B"; - return token_type::parse_error; - } - - case 0x0C: - { - error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f"; - return token_type::parse_error; - } - - case 0x0D: - { - error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r"; - return token_type::parse_error; - } - - case 0x0E: - { - error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E"; - return token_type::parse_error; - } - - case 0x0F: - { - error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F"; - return token_type::parse_error; - } - - case 0x10: - { - error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010"; - return token_type::parse_error; - } - - case 0x11: - { - error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011"; - return token_type::parse_error; - } - - case 0x12: - { - error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012"; - return token_type::parse_error; - } - - case 0x13: - { - error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013"; - return token_type::parse_error; - } - - case 0x14: - { - error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014"; - return token_type::parse_error; - } - - case 0x15: - { - error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015"; - return token_type::parse_error; - } - - case 0x16: - { - error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016"; - return token_type::parse_error; - } - - case 0x17: - { - error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017"; - return token_type::parse_error; - } - - case 0x18: - { - error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018"; - return token_type::parse_error; - } - - case 0x19: - { - error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019"; - return token_type::parse_error; - } - - case 0x1A: - { - error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A"; - return token_type::parse_error; - } - - case 0x1B: - { - error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B"; - return token_type::parse_error; - } - - case 0x1C: - { - error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C"; - return token_type::parse_error; - } - - case 0x1D: - { - error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D"; - return token_type::parse_error; - } - - case 0x1E: - { - error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E"; - return token_type::parse_error; - } - - case 0x1F: - { - error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F"; - return token_type::parse_error; - } - - // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace)) - case 0x20: - case 0x21: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3A: - case 0x3B: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: - case 0x59: - case 0x5A: - case 0x5B: - case 0x5D: - case 0x5E: - case 0x5F: - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - case 0x78: - case 0x79: - case 0x7A: - case 0x7B: - case 0x7C: - case 0x7D: - case 0x7E: - case 0x7F: - { - add(current); - break; - } - - // U+0080..U+07FF: bytes C2..DF 80..BF - case 0xC2: - case 0xC3: - case 0xC4: - case 0xC5: - case 0xC6: - case 0xC7: - case 0xC8: - case 0xC9: - case 0xCA: - case 0xCB: - case 0xCC: - case 0xCD: - case 0xCE: - case 0xCF: - case 0xD0: - case 0xD1: - case 0xD2: - case 0xD3: - case 0xD4: - case 0xD5: - case 0xD6: - case 0xD7: - case 0xD8: - case 0xD9: - case 0xDA: - case 0xDB: - case 0xDC: - case 0xDD: - case 0xDE: - case 0xDF: - { - if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF}))) - { - return token_type::parse_error; - } - break; - } - - // U+0800..U+0FFF: bytes E0 A0..BF 80..BF - case 0xE0: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF - // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF - case 0xE1: - case 0xE2: - case 0xE3: - case 0xE4: - case 0xE5: - case 0xE6: - case 0xE7: - case 0xE8: - case 0xE9: - case 0xEA: - case 0xEB: - case 0xEC: - case 0xEE: - case 0xEF: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+D000..U+D7FF: bytes ED 80..9F 80..BF - case 0xED: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF - case 0xF0: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF - case 0xF1: - case 0xF2: - case 0xF3: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF - case 0xF4: - { - if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF})))) - { - return token_type::parse_error; - } - break; - } - - // remaining bytes (80..C1 and F5..FF) are ill-formed - default: - { - error_message = "invalid string: ill-formed UTF-8 byte"; - return token_type::parse_error; - } - } - } - } - - /*! - * @brief scan a comment - * @return whether comment could be scanned successfully - */ - bool scan_comment() - { - switch (get()) - { - // single-line comments skip input until a newline or EOF is read - case '/': - { - while (true) - { - switch (get()) - { - case '\n': - case '\r': - case std::char_traits::eof(): - case '\0': - return true; - - default: - break; - } - } - } - - // multi-line comments skip input until */ is read - case '*': - { - while (true) - { - switch (get()) - { - case std::char_traits::eof(): - case '\0': - { - error_message = "invalid comment; missing closing '*/'"; - return false; - } - - case '*': - { - switch (get()) - { - case '/': - return true; - - default: - { - unget(); - continue; - } - } - } - - default: - continue; - } - } - } - - // unexpected character after reading '/' - default: - { - error_message = "invalid comment; expecting '/' or '*' after '/'"; - return false; - } - } - } - - JSON_HEDLEY_NON_NULL(2) - static void strtof(float& f, const char* str, char** endptr) noexcept - { - f = std::strtof(str, endptr); - } - - JSON_HEDLEY_NON_NULL(2) - static void strtof(double& f, const char* str, char** endptr) noexcept - { - f = std::strtod(str, endptr); - } - - JSON_HEDLEY_NON_NULL(2) - static void strtof(long double& f, const char* str, char** endptr) noexcept - { - f = std::strtold(str, endptr); - } - - /*! - @brief scan a number literal - - This function scans a string according to Sect. 6 of RFC 7159. - - The function is realized with a deterministic finite state machine derived - from the grammar described in RFC 7159. Starting in state "init", the - input is read and used to determined the next state. Only state "done" - accepts the number. State "error" is a trap state to model errors. In the - table below, "anything" means any character but the ones listed before. - - state | 0 | 1-9 | e E | + | - | . | anything - ---------|----------|----------|----------|---------|---------|----------|----------- - init | zero | any1 | [error] | [error] | minus | [error] | [error] - minus | zero | any1 | [error] | [error] | [error] | [error] | [error] - zero | done | done | exponent | done | done | decimal1 | done - any1 | any1 | any1 | exponent | done | done | decimal1 | done - decimal1 | decimal2 | decimal2 | [error] | [error] | [error] | [error] | [error] - decimal2 | decimal2 | decimal2 | exponent | done | done | done | done - exponent | any2 | any2 | [error] | sign | sign | [error] | [error] - sign | any2 | any2 | [error] | [error] | [error] | [error] | [error] - any2 | any2 | any2 | done | done | done | done | done - - The state machine is realized with one label per state (prefixed with - "scan_number_") and `goto` statements between them. The state machine - contains cycles, but any cycle can be left when EOF is read. Therefore, - the function is guaranteed to terminate. - - During scanning, the read bytes are stored in token_buffer. This string is - then converted to a signed integer, an unsigned integer, or a - floating-point number. - - @return token_type::value_unsigned, token_type::value_integer, or - token_type::value_float if number could be successfully scanned, - token_type::parse_error otherwise - - @note The scanner is independent of the current locale. Internally, the - locale's decimal point is used instead of `.` to work with the - locale-dependent converters. - */ - token_type scan_number() // lgtm [cpp/use-of-goto] - { - // reset token_buffer to store the number's bytes - reset(); - - // the type of the parsed number; initially set to unsigned; will be - // changed if minus sign, decimal point or exponent is read - token_type number_type = token_type::value_unsigned; - - // state (init): we just found out we need to scan a number - switch (current) - { - case '-': - { - add(current); - goto scan_number_minus; - } - - case '0': - { - add(current); - goto scan_number_zero; - } - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any1; - } - - // all other characters are rejected outside scan_number() - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - -scan_number_minus: - // state: we just parsed a leading minus sign - number_type = token_type::value_integer; - switch (get()) - { - case '0': - { - add(current); - goto scan_number_zero; - } - - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any1; - } - - default: - { - error_message = "invalid number; expected digit after '-'"; - return token_type::parse_error; - } - } - -scan_number_zero: - // state: we just parse a zero (maybe with a leading minus sign) - switch (get()) - { - case '.': - { - add(decimal_point_char); - goto scan_number_decimal1; - } - - case 'e': - case 'E': - { - add(current); - goto scan_number_exponent; - } - - default: - goto scan_number_done; - } - -scan_number_any1: - // state: we just parsed a number 0-9 (maybe with a leading minus sign) - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any1; - } - - case '.': - { - add(decimal_point_char); - goto scan_number_decimal1; - } - - case 'e': - case 'E': - { - add(current); - goto scan_number_exponent; - } - - default: - goto scan_number_done; - } - -scan_number_decimal1: - // state: we just parsed a decimal point - number_type = token_type::value_float; - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_decimal2; - } - - default: - { - error_message = "invalid number; expected digit after '.'"; - return token_type::parse_error; - } - } - -scan_number_decimal2: - // we just parsed at least one number after a decimal point - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_decimal2; - } - - case 'e': - case 'E': - { - add(current); - goto scan_number_exponent; - } - - default: - goto scan_number_done; - } - -scan_number_exponent: - // we just parsed an exponent - number_type = token_type::value_float; - switch (get()) - { - case '+': - case '-': - { - add(current); - goto scan_number_sign; - } - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any2; - } - - default: - { - error_message = - "invalid number; expected '+', '-', or digit after exponent"; - return token_type::parse_error; - } - } - -scan_number_sign: - // we just parsed an exponent sign - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any2; - } - - default: - { - error_message = "invalid number; expected digit after exponent sign"; - return token_type::parse_error; - } - } - -scan_number_any2: - // we just parsed a number after the exponent or exponent sign - switch (get()) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - { - add(current); - goto scan_number_any2; - } - - default: - goto scan_number_done; - } - -scan_number_done: - // unget the character after the number (we only read it to know that - // we are done scanning a number) - unget(); - - char* endptr = nullptr; - errno = 0; - - // try to parse integers first and fall back to floats - if (number_type == token_type::value_unsigned) - { - const auto x = std::strtoull(token_buffer.data(), &endptr, 10); - - // we checked the number format before - JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - - if (errno == 0) - { - value_unsigned = static_cast(x); - if (value_unsigned == x) - { - return token_type::value_unsigned; - } - } - } - else if (number_type == token_type::value_integer) - { - const auto x = std::strtoll(token_buffer.data(), &endptr, 10); - - // we checked the number format before - JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - - if (errno == 0) - { - value_integer = static_cast(x); - if (value_integer == x) - { - return token_type::value_integer; - } - } - } - - // this code is reached if we parse a floating-point number or if an - // integer conversion above failed - strtof(value_float, token_buffer.data(), &endptr); - - // we checked the number format before - JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size()); - - return token_type::value_float; - } - - /*! - @param[in] literal_text the literal text to expect - @param[in] length the length of the passed literal text - @param[in] return_type the token type to return on success - */ - JSON_HEDLEY_NON_NULL(2) - token_type scan_literal(const char_type* literal_text, const std::size_t length, - token_type return_type) - { - JSON_ASSERT(std::char_traits::to_char_type(current) == literal_text[0]); - for (std::size_t i = 1; i < length; ++i) - { - if (JSON_HEDLEY_UNLIKELY(std::char_traits::to_char_type(get()) != literal_text[i])) - { - error_message = "invalid literal"; - return token_type::parse_error; - } - } - return return_type; - } - - ///////////////////// - // input management - ///////////////////// - - /// reset token_buffer; current character is beginning of token - void reset() noexcept - { - token_buffer.clear(); - token_string.clear(); - token_string.push_back(std::char_traits::to_char_type(current)); - } - - /* - @brief get next character from the input - - This function provides the interface to the used input adapter. It does - not throw in case the input reached EOF, but returns a - `std::char_traits::eof()` in that case. Stores the scanned characters - for use in error messages. - - @return character read from the input - */ - char_int_type get() - { - ++position.chars_read_total; - ++position.chars_read_current_line; - - if (next_unget) - { - // just reset the next_unget variable and work with current - next_unget = false; - } - else - { - current = ia.get_character(); - } - - if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) - { - token_string.push_back(std::char_traits::to_char_type(current)); - } - - if (current == '\n') - { - ++position.lines_read; - position.chars_read_current_line = 0; - } - - return current; - } - - /*! - @brief unget current character (read it again on next get) - - We implement unget by setting variable next_unget to true. The input is not - changed - we just simulate ungetting by modifying chars_read_total, - chars_read_current_line, and token_string. The next call to get() will - behave as if the unget character is read again. - */ - void unget() - { - next_unget = true; - - --position.chars_read_total; - - // in case we "unget" a newline, we have to also decrement the lines_read - if (position.chars_read_current_line == 0) - { - if (position.lines_read > 0) - { - --position.lines_read; - } - } - else - { - --position.chars_read_current_line; - } - - if (JSON_HEDLEY_LIKELY(current != std::char_traits::eof())) - { - JSON_ASSERT(!token_string.empty()); - token_string.pop_back(); - } - } - - /// add a character to token_buffer - void add(char_int_type c) - { - token_buffer.push_back(static_cast(c)); - } - - public: - ///////////////////// - // value getters - ///////////////////// - - /// return integer value - constexpr number_integer_t get_number_integer() const noexcept - { - return value_integer; - } - - /// return unsigned integer value - constexpr number_unsigned_t get_number_unsigned() const noexcept - { - return value_unsigned; - } - - /// return floating-point value - constexpr number_float_t get_number_float() const noexcept - { - return value_float; - } - - /// return current string value (implicitly resets the token; useful only once) - string_t& get_string() - { - return token_buffer; - } - - ///////////////////// - // diagnostics - ///////////////////// - - /// return position of last read token - constexpr position_t get_position() const noexcept - { - return position; - } - - /// return the last read token (for errors only). Will never contain EOF - /// (an arbitrary value that is not a valid char value, often -1), because - /// 255 may legitimately occur. May contain NUL, which should be escaped. - std::string get_token_string() const - { - // escape control characters - std::string result; - for (const auto c : token_string) - { - if (static_cast(c) <= '\x1F') - { - // escape control characters - std::array cs{{}}; - (std::snprintf)(cs.data(), cs.size(), "", static_cast(c)); - result += cs.data(); - } - else - { - // add character as is - result.push_back(static_cast(c)); - } - } - - return result; - } - - /// return syntax error message - JSON_HEDLEY_RETURNS_NON_NULL - constexpr const char* get_error_message() const noexcept - { - return error_message; - } - - ///////////////////// - // actual scanner - ///////////////////// - - /*! - @brief skip the UTF-8 byte order mark - @return true iff there is no BOM or the correct BOM has been skipped - */ - bool skip_bom() - { - if (get() == 0xEF) - { - // check if we completely parse the BOM - return get() == 0xBB && get() == 0xBF; - } - - // the first character is not the beginning of the BOM; unget it to - // process is later - unget(); - return true; - } - - void skip_whitespace() - { - do - { - get(); - } - while (current == ' ' || current == '\t' || current == '\n' || current == '\r'); - } - - token_type scan() - { - // initially, skip the BOM - if (position.chars_read_total == 0 && !skip_bom()) - { - error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given"; - return token_type::parse_error; - } - - // read next character and ignore whitespace - skip_whitespace(); - - // ignore comments - while (ignore_comments && current == '/') - { - if (!scan_comment()) - { - return token_type::parse_error; - } - - // skip following whitespace - skip_whitespace(); - } - - switch (current) - { - // structural characters - case '[': - return token_type::begin_array; - case ']': - return token_type::end_array; - case '{': - return token_type::begin_object; - case '}': - return token_type::end_object; - case ':': - return token_type::name_separator; - case ',': - return token_type::value_separator; - - // literals - case 't': - { - std::array true_literal = {{'t', 'r', 'u', 'e'}}; - return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true); - } - case 'f': - { - std::array false_literal = {{'f', 'a', 'l', 's', 'e'}}; - return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false); - } - case 'n': - { - std::array null_literal = {{'n', 'u', 'l', 'l'}}; - return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null); - } - - // string - case '\"': - return scan_string(); - - // number - case '-': - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - return scan_number(); - - // end of input (the null byte is needed when parsing from - // string literals) - case '\0': - case std::char_traits::eof(): - return token_type::end_of_input; - - // error - default: - error_message = "invalid literal"; - return token_type::parse_error; - } - } - - private: - /// input adapter - InputAdapterType ia; - - /// whether comments should be ignored (true) or signaled as errors (false) - const bool ignore_comments = false; - - /// the current character - char_int_type current = std::char_traits::eof(); - - /// whether the next get() call should just return current - bool next_unget = false; - - /// the start position of the current token - position_t position {}; - - /// raw input token string (for error messages) - std::vector token_string {}; - - /// buffer for variable-length tokens (numbers, strings) - string_t token_buffer {}; - - /// a description of occurred lexer errors - const char* error_message = ""; - - // number values - number_integer_t value_integer = 0; - number_unsigned_t value_unsigned = 0; - number_float_t value_float = 0; - - /// the decimal point - const char_int_type decimal_point_char = '.'; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - - -#include // size_t -#include // declval -#include // string - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template -using null_function_t = decltype(std::declval().null()); - -template -using boolean_function_t = - decltype(std::declval().boolean(std::declval())); - -template -using number_integer_function_t = - decltype(std::declval().number_integer(std::declval())); - -template -using number_unsigned_function_t = - decltype(std::declval().number_unsigned(std::declval())); - -template -using number_float_function_t = decltype(std::declval().number_float( - std::declval(), std::declval())); - -template -using string_function_t = - decltype(std::declval().string(std::declval())); - -template -using binary_function_t = - decltype(std::declval().binary(std::declval())); - -template -using start_object_function_t = - decltype(std::declval().start_object(std::declval())); - -template -using key_function_t = - decltype(std::declval().key(std::declval())); - -template -using end_object_function_t = decltype(std::declval().end_object()); - -template -using start_array_function_t = - decltype(std::declval().start_array(std::declval())); - -template -using end_array_function_t = decltype(std::declval().end_array()); - -template -using parse_error_function_t = decltype(std::declval().parse_error( - std::declval(), std::declval(), - std::declval())); - -template -struct is_sax -{ - private: - static_assert(is_basic_json::value, - "BasicJsonType must be of type basic_json<...>"); - - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using exception_t = typename BasicJsonType::exception; - - public: - static constexpr bool value = - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value && - is_detected_exact::value; -}; - -template -struct is_sax_static_asserts -{ - private: - static_assert(is_basic_json::value, - "BasicJsonType must be of type basic_json<...>"); - - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using exception_t = typename BasicJsonType::exception; - - public: - static_assert(is_detected_exact::value, - "Missing/invalid function: bool null()"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool boolean(bool)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool boolean(bool)"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool number_integer(number_integer_t)"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool number_unsigned(number_unsigned_t)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool number_float(number_float_t, const string_t&)"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool string(string_t&)"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool binary(binary_t&)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool start_object(std::size_t)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool key(string_t&)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool end_object()"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool start_array(std::size_t)"); - static_assert(is_detected_exact::value, - "Missing/invalid function: bool end_array()"); - static_assert( - is_detected_exact::value, - "Missing/invalid function: bool parse_error(std::size_t, const " - "std::string&, const exception&)"); -}; -} // namespace detail -} // namespace nlohmann - -// #include - - -namespace nlohmann -{ -namespace detail -{ - -/// how to treat CBOR tags -enum class cbor_tag_handler_t -{ - error, ///< throw a parse_error exception in case of a tag - ignore ///< ignore tags -}; - -/*! -@brief determine system byte order - -@return true if and only if system's byte order is little endian - -@note from https://stackoverflow.com/a/1001328/266378 -*/ -static inline bool little_endianess(int num = 1) noexcept -{ - return *reinterpret_cast(&num) == 1; -} - - -/////////////////// -// binary reader // -/////////////////// - -/*! -@brief deserialization of CBOR, MessagePack, and UBJSON values -*/ -template> -class binary_reader -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using json_sax_t = SAX; - using char_type = typename InputAdapterType::char_type; - using char_int_type = typename std::char_traits::int_type; - - public: - /*! - @brief create a binary reader - - @param[in] adapter input adapter to read from - */ - explicit binary_reader(InputAdapterType&& adapter) : ia(std::move(adapter)) - { - (void)detail::is_sax_static_asserts {}; - } - - // make class move-only - binary_reader(const binary_reader&) = delete; - binary_reader(binary_reader&&) = default; - binary_reader& operator=(const binary_reader&) = delete; - binary_reader& operator=(binary_reader&&) = default; - ~binary_reader() = default; - - /*! - @param[in] format the binary format to parse - @param[in] sax_ a SAX event processor - @param[in] strict whether to expect the input to be consumed completed - @param[in] tag_handler how to treat CBOR tags - - @return - */ - JSON_HEDLEY_NON_NULL(3) - bool sax_parse(const input_format_t format, - json_sax_t* sax_, - const bool strict = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - sax = sax_; - bool result = false; - - switch (format) - { - case input_format_t::bson: - result = parse_bson_internal(); - break; - - case input_format_t::cbor: - result = parse_cbor_internal(true, tag_handler); - break; - - case input_format_t::msgpack: - result = parse_msgpack_internal(); - break; - - case input_format_t::ubjson: - result = parse_ubjson_internal(); - break; - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - - // strict mode: next byte must be EOF - if (result && strict) - { - if (format == input_format_t::ubjson) - { - get_ignore_noop(); - } - else - { - get(); - } - - if (JSON_HEDLEY_UNLIKELY(current != std::char_traits::eof())) - { - return sax->parse_error(chars_read, get_token_string(), - parse_error::create(110, chars_read, exception_message(format, "expected end of input; last byte: 0x" + get_token_string(), "value"))); - } - } - - return result; - } - - private: - ////////// - // BSON // - ////////// - - /*! - @brief Reads in a BSON-object and passes it to the SAX-parser. - @return whether a valid BSON-value was passed to the SAX parser - */ - bool parse_bson_internal() - { - std::int32_t document_size{}; - get_number(input_format_t::bson, document_size); - - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false))) - { - return false; - } - - return sax->end_object(); - } - - /*! - @brief Parses a C-style string from the BSON input. - @param[in, out] result A reference to the string variable where the read - string is to be stored. - @return `true` if the \x00-byte indicating the end of the string was - encountered before the EOF; false` indicates an unexpected EOF. - */ - bool get_bson_cstr(string_t& result) - { - auto out = std::back_inserter(result); - while (true) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring"))) - { - return false; - } - if (current == 0x00) - { - return true; - } - *out++ = static_cast(current); - } - } - - /*! - @brief Parses a zero-terminated string of length @a len from the BSON - input. - @param[in] len The length (including the zero-byte at the end) of the - string to be read. - @param[in, out] result A reference to the string variable where the read - string is to be stored. - @tparam NumberType The type of the length @a len - @pre len >= 1 - @return `true` if the string was successfully parsed - */ - template - bool get_bson_string(const NumberType len, string_t& result) - { - if (JSON_HEDLEY_UNLIKELY(len < 1)) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "string length must be at least 1, is " + std::to_string(len), "string"))); - } - - return get_string(input_format_t::bson, len - static_cast(1), result) && get() != std::char_traits::eof(); - } - - /*! - @brief Parses a byte array input of length @a len from the BSON input. - @param[in] len The length of the byte array to be read. - @param[in, out] result A reference to the binary variable where the read - array is to be stored. - @tparam NumberType The type of the length @a len - @pre len >= 0 - @return `true` if the byte array was successfully parsed - */ - template - bool get_bson_binary(const NumberType len, binary_t& result) - { - if (JSON_HEDLEY_UNLIKELY(len < 0)) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::bson, "byte array length cannot be negative, is " + std::to_string(len), "binary"))); - } - - // All BSON binary values have a subtype - std::uint8_t subtype{}; - get_number(input_format_t::bson, subtype); - result.set_subtype(subtype); - - return get_binary(input_format_t::bson, len, result); - } - - /*! - @brief Read a BSON document element of the given @a element_type. - @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html - @param[in] element_type_parse_position The position in the input stream, - where the `element_type` was read. - @warning Not all BSON element types are supported yet. An unsupported - @a element_type will give rise to a parse_error.114: - Unsupported BSON record type 0x... - @return whether a valid BSON-object/array was passed to the SAX parser - */ - bool parse_bson_element_internal(const char_int_type element_type, - const std::size_t element_type_parse_position) - { - switch (element_type) - { - case 0x01: // double - { - double number{}; - return get_number(input_format_t::bson, number) && sax->number_float(static_cast(number), ""); - } - - case 0x02: // string - { - std::int32_t len{}; - string_t value; - return get_number(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value); - } - - case 0x03: // object - { - return parse_bson_internal(); - } - - case 0x04: // array - { - return parse_bson_array(); - } - - case 0x05: // binary - { - std::int32_t len{}; - binary_t value; - return get_number(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value); - } - - case 0x08: // boolean - { - return sax->boolean(get() != 0); - } - - case 0x0A: // null - { - return sax->null(); - } - - case 0x10: // int32 - { - std::int32_t value{}; - return get_number(input_format_t::bson, value) && sax->number_integer(value); - } - - case 0x12: // int64 - { - std::int64_t value{}; - return get_number(input_format_t::bson, value) && sax->number_integer(value); - } - - default: // anything else not supported (yet) - { - std::array cr{{}}; - (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(element_type)); - return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data()))); - } - } - } - - /*! - @brief Read a BSON element list (as specified in the BSON-spec) - - The same binary layout is used for objects and arrays, hence it must be - indicated with the argument @a is_array which one is expected - (true --> array, false --> object). - - @param[in] is_array Determines if the element list being read is to be - treated as an object (@a is_array == false), or as an - array (@a is_array == true). - @return whether a valid BSON-object/array was passed to the SAX parser - */ - bool parse_bson_element_list(const bool is_array) - { - string_t key; - - while (auto element_type = get()) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list"))) - { - return false; - } - - const std::size_t element_type_parse_position = chars_read; - if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key))) - { - return false; - } - - if (!is_array && !sax->key(key)) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position))) - { - return false; - } - - // get_bson_cstr only appends - key.clear(); - } - - return true; - } - - /*! - @brief Reads an array from the BSON input and passes it to the SAX-parser. - @return whether a valid BSON-array was passed to the SAX parser - */ - bool parse_bson_array() - { - std::int32_t document_size{}; - get_number(input_format_t::bson, document_size); - - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true))) - { - return false; - } - - return sax->end_array(); - } - - ////////// - // CBOR // - ////////// - - /*! - @param[in] get_char whether a new character should be retrieved from the - input (true) or whether the last read character should - be considered instead (false) - @param[in] tag_handler how CBOR tags should be treated - - @return whether a valid CBOR value was passed to the SAX parser - */ - bool parse_cbor_internal(const bool get_char, - const cbor_tag_handler_t tag_handler) - { - switch (get_char ? get() : current) - { - // EOF - case std::char_traits::eof(): - return unexpect_eof(input_format_t::cbor, "value"); - - // Integer 0x00..0x17 (0..23) - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - return sax->number_unsigned(static_cast(current)); - - case 0x18: // Unsigned integer (one-byte uint8_t follows) - { - std::uint8_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } - - case 0x19: // Unsigned integer (two-byte uint16_t follows) - { - std::uint16_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } - - case 0x1A: // Unsigned integer (four-byte uint32_t follows) - { - std::uint32_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } - - case 0x1B: // Unsigned integer (eight-byte uint64_t follows) - { - std::uint64_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_unsigned(number); - } - - // Negative integer -1-0x00..-1-0x17 (-1..-24) - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - return sax->number_integer(static_cast(0x20 - 1 - current)); - - case 0x38: // Negative integer (one-byte uint8_t follows) - { - std::uint8_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); - } - - case 0x39: // Negative integer -1-n (two-byte uint16_t follows) - { - std::uint16_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); - } - - case 0x3A: // Negative integer -1-n (four-byte uint32_t follows) - { - std::uint32_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - number); - } - - case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows) - { - std::uint64_t number{}; - return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast(-1) - - static_cast(number)); - } - - // Binary data (0x00..0x17 bytes follow) - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: // Binary data (one-byte uint8_t for n follows) - case 0x59: // Binary data (two-byte uint16_t for n follow) - case 0x5A: // Binary data (four-byte uint32_t for n follow) - case 0x5B: // Binary data (eight-byte uint64_t for n follow) - case 0x5F: // Binary data (indefinite length) - { - binary_t b; - return get_cbor_binary(b) && sax->binary(b); - } - - // UTF-8 string (0x00..0x17 bytes follow) - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - case 0x78: // UTF-8 string (one-byte uint8_t for n follows) - case 0x79: // UTF-8 string (two-byte uint16_t for n follow) - case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) - case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) - case 0x7F: // UTF-8 string (indefinite length) - { - string_t s; - return get_cbor_string(s) && sax->string(s); - } - - // array (0x00..0x17 data items follow) - case 0x80: - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x85: - case 0x86: - case 0x87: - case 0x88: - case 0x89: - case 0x8A: - case 0x8B: - case 0x8C: - case 0x8D: - case 0x8E: - case 0x8F: - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - return get_cbor_array(static_cast(static_cast(current) & 0x1Fu), tag_handler); - - case 0x98: // array (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } - - case 0x99: // array (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } - - case 0x9A: // array (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } - - case 0x9B: // array (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast(len), tag_handler); - } - - case 0x9F: // array (indefinite length) - return get_cbor_array(std::size_t(-1), tag_handler); - - // map (0x00..0x17 pairs of data items follow) - case 0xA0: - case 0xA1: - case 0xA2: - case 0xA3: - case 0xA4: - case 0xA5: - case 0xA6: - case 0xA7: - case 0xA8: - case 0xA9: - case 0xAA: - case 0xAB: - case 0xAC: - case 0xAD: - case 0xAE: - case 0xAF: - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - return get_cbor_object(static_cast(static_cast(current) & 0x1Fu), tag_handler); - - case 0xB8: // map (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } - - case 0xB9: // map (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } - - case 0xBA: // map (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } - - case 0xBB: // map (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast(len), tag_handler); - } - - case 0xBF: // map (indefinite length) - return get_cbor_object(std::size_t(-1), tag_handler); - - case 0xC6: // tagged item - case 0xC7: - case 0xC8: - case 0xC9: - case 0xCA: - case 0xCB: - case 0xCC: - case 0xCD: - case 0xCE: - case 0xCF: - case 0xD0: - case 0xD1: - case 0xD2: - case 0xD3: - case 0xD4: - case 0xD8: // tagged item (1 bytes follow) - case 0xD9: // tagged item (2 bytes follow) - case 0xDA: // tagged item (4 bytes follow) - case 0xDB: // tagged item (8 bytes follow) - { - switch (tag_handler) - { - case cbor_tag_handler_t::error: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"))); - } - - case cbor_tag_handler_t::ignore: - { - switch (current) - { - case 0xD8: - { - std::uint8_t len{}; - get_number(input_format_t::cbor, len); - break; - } - case 0xD9: - { - std::uint16_t len{}; - get_number(input_format_t::cbor, len); - break; - } - case 0xDA: - { - std::uint32_t len{}; - get_number(input_format_t::cbor, len); - break; - } - case 0xDB: - { - std::uint64_t len{}; - get_number(input_format_t::cbor, len); - break; - } - default: - break; - } - return parse_cbor_internal(true, tag_handler); - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - return false; // LCOV_EXCL_LINE - } - } - - case 0xF4: // false - return sax->boolean(false); - - case 0xF5: // true - return sax->boolean(true); - - case 0xF6: // null - return sax->null(); - - case 0xF9: // Half-Precision Float (two-byte IEEE 754) - { - const auto byte1_raw = get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) - { - return false; - } - const auto byte2_raw = get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number"))) - { - return false; - } - - const auto byte1 = static_cast(byte1_raw); - const auto byte2 = static_cast(byte2_raw); - - // code from RFC 7049, Appendix D, Figure 3: - // As half-precision floating-point numbers were only added - // to IEEE 754 in 2008, today's programming platforms often - // still only have limited support for them. It is very - // easy to include at least decoding support for them even - // without such support. An example of a small decoder for - // half-precision floating-point numbers in the C language - // is shown in Fig. 3. - const auto half = static_cast((byte1 << 8u) + byte2); - const double val = [&half] - { - const int exp = (half >> 10u) & 0x1Fu; - const unsigned int mant = half & 0x3FFu; - JSON_ASSERT(0 <= exp&& exp <= 32); - JSON_ASSERT(mant <= 1024); - switch (exp) - { - case 0: - return std::ldexp(mant, -24); - case 31: - return (mant == 0) - ? std::numeric_limits::infinity() - : std::numeric_limits::quiet_NaN(); - default: - return std::ldexp(mant + 1024, exp - 25); - } - }(); - return sax->number_float((half & 0x8000u) != 0 - ? static_cast(-val) - : static_cast(val), ""); - } - - case 0xFA: // Single-Precision Float (four-byte IEEE 754) - { - float number{}; - return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); - } - - case 0xFB: // Double-Precision Float (eight-byte IEEE 754) - { - double number{}; - return get_number(input_format_t::cbor, number) && sax->number_float(static_cast(number), ""); - } - - default: // anything else (0xFF is handled inside the other types) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::cbor, "invalid byte: 0x" + last_token, "value"))); - } - } - } - - /*! - @brief reads a CBOR string - - This function first reads starting bytes to determine the expected - string length and then copies this number of bytes into a string. - Additionally, CBOR's strings with indefinite lengths are supported. - - @param[out] result created string - - @return whether string creation completed - */ - bool get_cbor_string(string_t& result) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string"))) - { - return false; - } - - switch (current) - { - // UTF-8 string (0x00..0x17 bytes follow) - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - { - return get_string(input_format_t::cbor, static_cast(current) & 0x1Fu, result); - } - - case 0x78: // UTF-8 string (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } - - case 0x79: // UTF-8 string (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } - - case 0x7A: // UTF-8 string (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } - - case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result); - } - - case 0x7F: // UTF-8 string (indefinite length) - { - while (get() != 0xFF) - { - string_t chunk; - if (!get_cbor_string(chunk)) - { - return false; - } - result.append(chunk); - } - return true; - } - - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x" + last_token, "string"))); - } - } - } - - /*! - @brief reads a CBOR byte array - - This function first reads starting bytes to determine the expected - byte array length and then copies this number of bytes into the byte array. - Additionally, CBOR's byte arrays with indefinite lengths are supported. - - @param[out] result created byte array - - @return whether byte array creation completed - */ - bool get_cbor_binary(binary_t& result) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary"))) - { - return false; - } - - switch (current) - { - // Binary data (0x00..0x17 bytes follow) - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - { - return get_binary(input_format_t::cbor, static_cast(current) & 0x1Fu, result); - } - - case 0x58: // Binary data (one-byte uint8_t for n follows) - { - std::uint8_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } - - case 0x59: // Binary data (two-byte uint16_t for n follow) - { - std::uint16_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } - - case 0x5A: // Binary data (four-byte uint32_t for n follow) - { - std::uint32_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } - - case 0x5B: // Binary data (eight-byte uint64_t for n follow) - { - std::uint64_t len{}; - return get_number(input_format_t::cbor, len) && - get_binary(input_format_t::cbor, len, result); - } - - case 0x5F: // Binary data (indefinite length) - { - while (get() != 0xFF) - { - binary_t chunk; - if (!get_cbor_binary(chunk)) - { - return false; - } - result.insert(result.end(), chunk.begin(), chunk.end()); - } - return true; - } - - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::cbor, "expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x" + last_token, "binary"))); - } - } - } - - /*! - @param[in] len the length of the array or std::size_t(-1) for an - array of indefinite size - @param[in] tag_handler how CBOR tags should be treated - @return whether array creation completed - */ - bool get_cbor_array(const std::size_t len, - const cbor_tag_handler_t tag_handler) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) - { - return false; - } - - if (len != std::size_t(-1)) - { - for (std::size_t i = 0; i < len; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) - { - return false; - } - } - } - else - { - while (get() != 0xFF) - { - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler))) - { - return false; - } - } - } - - return sax->end_array(); - } - - /*! - @param[in] len the length of the object or std::size_t(-1) for an - object of indefinite size - @param[in] tag_handler how CBOR tags should be treated - @return whether object creation completed - */ - bool get_cbor_object(const std::size_t len, - const cbor_tag_handler_t tag_handler) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) - { - return false; - } - - string_t key; - if (len != std::size_t(-1)) - { - for (std::size_t i = 0; i < len; ++i) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) - { - return false; - } - key.clear(); - } - } - else - { - while (get() != 0xFF) - { - if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key))) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler))) - { - return false; - } - key.clear(); - } - } - - return sax->end_object(); - } - - ///////////// - // MsgPack // - ///////////// - - /*! - @return whether a valid MessagePack value was passed to the SAX parser - */ - bool parse_msgpack_internal() - { - switch (get()) - { - // EOF - case std::char_traits::eof(): - return unexpect_eof(input_format_t::msgpack, "value"); - - // positive fixint - case 0x00: - case 0x01: - case 0x02: - case 0x03: - case 0x04: - case 0x05: - case 0x06: - case 0x07: - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - case 0x0C: - case 0x0D: - case 0x0E: - case 0x0F: - case 0x10: - case 0x11: - case 0x12: - case 0x13: - case 0x14: - case 0x15: - case 0x16: - case 0x17: - case 0x18: - case 0x19: - case 0x1A: - case 0x1B: - case 0x1C: - case 0x1D: - case 0x1E: - case 0x1F: - case 0x20: - case 0x21: - case 0x22: - case 0x23: - case 0x24: - case 0x25: - case 0x26: - case 0x27: - case 0x28: - case 0x29: - case 0x2A: - case 0x2B: - case 0x2C: - case 0x2D: - case 0x2E: - case 0x2F: - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3A: - case 0x3B: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - case 0x48: - case 0x49: - case 0x4A: - case 0x4B: - case 0x4C: - case 0x4D: - case 0x4E: - case 0x4F: - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - case 0x58: - case 0x59: - case 0x5A: - case 0x5B: - case 0x5C: - case 0x5D: - case 0x5E: - case 0x5F: - case 0x60: - case 0x61: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - case 0x68: - case 0x69: - case 0x6A: - case 0x6B: - case 0x6C: - case 0x6D: - case 0x6E: - case 0x6F: - case 0x70: - case 0x71: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - case 0x78: - case 0x79: - case 0x7A: - case 0x7B: - case 0x7C: - case 0x7D: - case 0x7E: - case 0x7F: - return sax->number_unsigned(static_cast(current)); - - // fixmap - case 0x80: - case 0x81: - case 0x82: - case 0x83: - case 0x84: - case 0x85: - case 0x86: - case 0x87: - case 0x88: - case 0x89: - case 0x8A: - case 0x8B: - case 0x8C: - case 0x8D: - case 0x8E: - case 0x8F: - return get_msgpack_object(static_cast(static_cast(current) & 0x0Fu)); - - // fixarray - case 0x90: - case 0x91: - case 0x92: - case 0x93: - case 0x94: - case 0x95: - case 0x96: - case 0x97: - case 0x98: - case 0x99: - case 0x9A: - case 0x9B: - case 0x9C: - case 0x9D: - case 0x9E: - case 0x9F: - return get_msgpack_array(static_cast(static_cast(current) & 0x0Fu)); - - // fixstr - case 0xA0: - case 0xA1: - case 0xA2: - case 0xA3: - case 0xA4: - case 0xA5: - case 0xA6: - case 0xA7: - case 0xA8: - case 0xA9: - case 0xAA: - case 0xAB: - case 0xAC: - case 0xAD: - case 0xAE: - case 0xAF: - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - case 0xB8: - case 0xB9: - case 0xBA: - case 0xBB: - case 0xBC: - case 0xBD: - case 0xBE: - case 0xBF: - case 0xD9: // str 8 - case 0xDA: // str 16 - case 0xDB: // str 32 - { - string_t s; - return get_msgpack_string(s) && sax->string(s); - } - - case 0xC0: // nil - return sax->null(); - - case 0xC2: // false - return sax->boolean(false); - - case 0xC3: // true - return sax->boolean(true); - - case 0xC4: // bin 8 - case 0xC5: // bin 16 - case 0xC6: // bin 32 - case 0xC7: // ext 8 - case 0xC8: // ext 16 - case 0xC9: // ext 32 - case 0xD4: // fixext 1 - case 0xD5: // fixext 2 - case 0xD6: // fixext 4 - case 0xD7: // fixext 8 - case 0xD8: // fixext 16 - { - binary_t b; - return get_msgpack_binary(b) && sax->binary(b); - } - - case 0xCA: // float 32 - { - float number{}; - return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); - } - - case 0xCB: // float 64 - { - double number{}; - return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast(number), ""); - } - - case 0xCC: // uint 8 - { - std::uint8_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } - - case 0xCD: // uint 16 - { - std::uint16_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } - - case 0xCE: // uint 32 - { - std::uint32_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } - - case 0xCF: // uint 64 - { - std::uint64_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number); - } - - case 0xD0: // int 8 - { - std::int8_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } - - case 0xD1: // int 16 - { - std::int16_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } - - case 0xD2: // int 32 - { - std::int32_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } - - case 0xD3: // int 64 - { - std::int64_t number{}; - return get_number(input_format_t::msgpack, number) && sax->number_integer(number); - } - - case 0xDC: // array 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); - } - - case 0xDD: // array 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast(len)); - } - - case 0xDE: // map 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); - } - - case 0xDF: // map 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast(len)); - } - - // negative fixint - case 0xE0: - case 0xE1: - case 0xE2: - case 0xE3: - case 0xE4: - case 0xE5: - case 0xE6: - case 0xE7: - case 0xE8: - case 0xE9: - case 0xEA: - case 0xEB: - case 0xEC: - case 0xED: - case 0xEE: - case 0xEF: - case 0xF0: - case 0xF1: - case 0xF2: - case 0xF3: - case 0xF4: - case 0xF5: - case 0xF6: - case 0xF7: - case 0xF8: - case 0xF9: - case 0xFA: - case 0xFB: - case 0xFC: - case 0xFD: - case 0xFE: - case 0xFF: - return sax->number_integer(static_cast(current)); - - default: // anything else - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::msgpack, "invalid byte: 0x" + last_token, "value"))); - } - } - } - - /*! - @brief reads a MessagePack string - - This function first reads starting bytes to determine the expected - string length and then copies this number of bytes into a string. - - @param[out] result created string - - @return whether string creation completed - */ - bool get_msgpack_string(string_t& result) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string"))) - { - return false; - } - - switch (current) - { - // fixstr - case 0xA0: - case 0xA1: - case 0xA2: - case 0xA3: - case 0xA4: - case 0xA5: - case 0xA6: - case 0xA7: - case 0xA8: - case 0xA9: - case 0xAA: - case 0xAB: - case 0xAC: - case 0xAD: - case 0xAE: - case 0xAF: - case 0xB0: - case 0xB1: - case 0xB2: - case 0xB3: - case 0xB4: - case 0xB5: - case 0xB6: - case 0xB7: - case 0xB8: - case 0xB9: - case 0xBA: - case 0xBB: - case 0xBC: - case 0xBD: - case 0xBE: - case 0xBF: - { - return get_string(input_format_t::msgpack, static_cast(current) & 0x1Fu, result); - } - - case 0xD9: // str 8 - { - std::uint8_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); - } - - case 0xDA: // str 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); - } - - case 0xDB: // str 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result); - } - - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::msgpack, "expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x" + last_token, "string"))); - } - } - } - - /*! - @brief reads a MessagePack byte array - - This function first reads starting bytes to determine the expected - byte array length and then copies this number of bytes into a byte array. - - @param[out] result created byte array - - @return whether byte array creation completed - */ - bool get_msgpack_binary(binary_t& result) - { - // helper function to set the subtype - auto assign_and_return_true = [&result](std::int8_t subtype) - { - result.set_subtype(static_cast(subtype)); - return true; - }; - - switch (current) - { - case 0xC4: // bin 8 - { - std::uint8_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); - } - - case 0xC5: // bin 16 - { - std::uint16_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); - } - - case 0xC6: // bin 32 - { - std::uint32_t len{}; - return get_number(input_format_t::msgpack, len) && - get_binary(input_format_t::msgpack, len, result); - } - - case 0xC7: // ext 8 - { - std::uint8_t len{}; - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && - assign_and_return_true(subtype); - } - - case 0xC8: // ext 16 - { - std::uint16_t len{}; - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && - assign_and_return_true(subtype); - } - - case 0xC9: // ext 32 - { - std::uint32_t len{}; - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, len) && - get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, len, result) && - assign_and_return_true(subtype); - } - - case 0xD4: // fixext 1 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 1, result) && - assign_and_return_true(subtype); - } - - case 0xD5: // fixext 2 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 2, result) && - assign_and_return_true(subtype); - } - - case 0xD6: // fixext 4 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 4, result) && - assign_and_return_true(subtype); - } - - case 0xD7: // fixext 8 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 8, result) && - assign_and_return_true(subtype); - } - - case 0xD8: // fixext 16 - { - std::int8_t subtype{}; - return get_number(input_format_t::msgpack, subtype) && - get_binary(input_format_t::msgpack, 16, result) && - assign_and_return_true(subtype); - } - - default: // LCOV_EXCL_LINE - return false; // LCOV_EXCL_LINE - } - } - - /*! - @param[in] len the length of the array - @return whether array creation completed - */ - bool get_msgpack_array(const std::size_t len) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len))) - { - return false; - } - - for (std::size_t i = 0; i < len; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) - { - return false; - } - } - - return sax->end_array(); - } - - /*! - @param[in] len the length of the object - @return whether object creation completed - */ - bool get_msgpack_object(const std::size_t len) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len))) - { - return false; - } - - string_t key; - for (std::size_t i = 0; i < len; ++i) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key))) - { - return false; - } - - if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal())) - { - return false; - } - key.clear(); - } - - return sax->end_object(); - } - - //////////// - // UBJSON // - //////////// - - /*! - @param[in] get_char whether a new character should be retrieved from the - input (true, default) or whether the last read - character should be considered instead - - @return whether a valid UBJSON value was passed to the SAX parser - */ - bool parse_ubjson_internal(const bool get_char = true) - { - return get_ubjson_value(get_char ? get_ignore_noop() : current); - } - - /*! - @brief reads a UBJSON string - - This function is either called after reading the 'S' byte explicitly - indicating a string, or in case of an object key where the 'S' byte can be - left out. - - @param[out] result created string - @param[in] get_char whether a new character should be retrieved from the - input (true, default) or whether the last read - character should be considered instead - - @return whether string creation completed - */ - bool get_ubjson_string(string_t& result, const bool get_char = true) - { - if (get_char) - { - get(); // TODO(niels): may we ignore N here? - } - - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) - { - return false; - } - - switch (current) - { - case 'U': - { - std::uint8_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - case 'i': - { - std::int8_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - case 'I': - { - std::int16_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - case 'l': - { - std::int32_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - case 'L': - { - std::int64_t len{}; - return get_number(input_format_t::ubjson, len) && get_string(input_format_t::ubjson, len, result); - } - - default: - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token, "string"))); - } - } - - /*! - @param[out] result determined size - @return whether size determination completed - */ - bool get_ubjson_size_value(std::size_t& result) - { - switch (get_ignore_noop()) - { - case 'U': - { - std::uint8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - case 'i': - { - std::int8_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - case 'I': - { - std::int16_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - case 'l': - { - std::int32_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - case 'L': - { - std::int64_t number{}; - if (JSON_HEDLEY_UNLIKELY(!get_number(input_format_t::ubjson, number))) - { - return false; - } - result = static_cast(number); - return true; - } - - default: - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token, "size"))); - } - } - } - - /*! - @brief determine the type and size for a container - - In the optimized UBJSON format, a type and a size can be provided to allow - for a more compact representation. - - @param[out] result pair of the size and the type - - @return whether pair creation completed - */ - bool get_ubjson_size_type(std::pair& result) - { - result.first = string_t::npos; // size - result.second = 0; // type - - get_ignore_noop(); - - if (current == '$') - { - result.second = get(); // must not ignore 'N', because 'N' maybe the type - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "type"))) - { - return false; - } - - get_ignore_noop(); - if (JSON_HEDLEY_UNLIKELY(current != '#')) - { - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "value"))) - { - return false; - } - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "expected '#' after type information; last byte: 0x" + last_token, "size"))); - } - - return get_ubjson_size_value(result.first); - } - - if (current == '#') - { - return get_ubjson_size_value(result.first); - } - - return true; - } - - /*! - @param prefix the previously read or set type prefix - @return whether value creation completed - */ - bool get_ubjson_value(const char_int_type prefix) - { - switch (prefix) - { - case std::char_traits::eof(): // EOF - return unexpect_eof(input_format_t::ubjson, "value"); - - case 'T': // true - return sax->boolean(true); - case 'F': // false - return sax->boolean(false); - - case 'Z': // null - return sax->null(); - - case 'U': - { - std::uint8_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_unsigned(number); - } - - case 'i': - { - std::int8_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); - } - - case 'I': - { - std::int16_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); - } - - case 'l': - { - std::int32_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); - } - - case 'L': - { - std::int64_t number{}; - return get_number(input_format_t::ubjson, number) && sax->number_integer(number); - } - - case 'd': - { - float number{}; - return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); - } - - case 'D': - { - double number{}; - return get_number(input_format_t::ubjson, number) && sax->number_float(static_cast(number), ""); - } - - case 'H': - { - return get_ubjson_high_precision_number(); - } - - case 'C': // char - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "char"))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(current > 127)) - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format_t::ubjson, "byte after 'C' must be in range 0x00..0x7F; last byte: 0x" + last_token, "char"))); - } - string_t s(1, static_cast(current)); - return sax->string(s); - } - - case 'S': // string - { - string_t s; - return get_ubjson_string(s) && sax->string(s); - } - - case '[': // array - return get_ubjson_array(); - - case '{': // object - return get_ubjson_object(); - - default: // anything else - { - auto last_token = get_token_string(); - return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format_t::ubjson, "invalid byte: 0x" + last_token, "value"))); - } - } - } - - /*! - @return whether array creation completed - */ - bool get_ubjson_array() - { - std::pair size_and_type; - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) - { - return false; - } - - if (size_and_type.first != string_t::npos) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first))) - { - return false; - } - - if (size_and_type.second != 0) - { - if (size_and_type.second != 'N') - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) - { - return false; - } - } - } - } - else - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) - { - return false; - } - } - } - } - else - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) - { - return false; - } - - while (current != ']') - { - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false))) - { - return false; - } - get_ignore_noop(); - } - } - - return sax->end_array(); - } - - /*! - @return whether object creation completed - */ - bool get_ubjson_object() - { - std::pair size_and_type; - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type))) - { - return false; - } - - string_t key; - if (size_and_type.first != string_t::npos) - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first))) - { - return false; - } - - if (size_and_type.second != 0) - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second))) - { - return false; - } - key.clear(); - } - } - else - { - for (std::size_t i = 0; i < size_and_type.first; ++i) - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) - { - return false; - } - key.clear(); - } - } - } - else - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) - { - return false; - } - - while (current != '}') - { - if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key))) - { - return false; - } - if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal())) - { - return false; - } - get_ignore_noop(); - key.clear(); - } - } - - return sax->end_object(); - } - - // Note, no reader for UBJSON binary types is implemented because they do - // not exist - - bool get_ubjson_high_precision_number() - { - // get size of following number string - std::size_t size{}; - auto res = get_ubjson_size_value(size); - if (JSON_HEDLEY_UNLIKELY(!res)) - { - return res; - } - - // get number string - std::vector number_vector; - for (std::size_t i = 0; i < size; ++i) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::ubjson, "number"))) - { - return false; - } - number_vector.push_back(static_cast(current)); - } - - // parse number string - auto number_ia = detail::input_adapter(std::forward(number_vector)); - auto number_lexer = detail::lexer(std::move(number_ia), false); - const auto result_number = number_lexer.scan(); - const auto number_string = number_lexer.get_token_string(); - const auto result_remainder = number_lexer.scan(); - - using token_type = typename detail::lexer_base::token_type; - - if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input)) - { - return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"))); - } - - switch (result_number) - { - case token_type::value_integer: - return sax->number_integer(number_lexer.get_number_integer()); - case token_type::value_unsigned: - return sax->number_unsigned(number_lexer.get_number_unsigned()); - case token_type::value_float: - return sax->number_float(number_lexer.get_number_float(), std::move(number_string)); - default: - return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read, exception_message(input_format_t::ubjson, "invalid number text: " + number_lexer.get_token_string(), "high-precision number"))); - } - } - - /////////////////////// - // Utility functions // - /////////////////////// - - /*! - @brief get next character from the input - - This function provides the interface to the used input adapter. It does - not throw in case the input reached EOF, but returns a -'ve valued - `std::char_traits::eof()` in that case. - - @return character read from the input - */ - char_int_type get() - { - ++chars_read; - return current = ia.get_character(); - } - - /*! - @return character read from the input after ignoring all 'N' entries - */ - char_int_type get_ignore_noop() - { - do - { - get(); - } - while (current == 'N'); - - return current; - } - - /* - @brief read a number from the input - - @tparam NumberType the type of the number - @param[in] format the current format (for diagnostics) - @param[out] result number of type @a NumberType - - @return whether conversion completed - - @note This function needs to respect the system's endianess, because - bytes in CBOR, MessagePack, and UBJSON are stored in network order - (big endian) and therefore need reordering on little endian systems. - */ - template - bool get_number(const input_format_t format, NumberType& result) - { - // step 1: read input into array with system's byte order - std::array vec; - for (std::size_t i = 0; i < sizeof(NumberType); ++i) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number"))) - { - return false; - } - - // reverse byte order prior to conversion if necessary - if (is_little_endian != InputIsLittleEndian) - { - vec[sizeof(NumberType) - i - 1] = static_cast(current); - } - else - { - vec[i] = static_cast(current); // LCOV_EXCL_LINE - } - } - - // step 2: convert array into number of type T and return - std::memcpy(&result, vec.data(), sizeof(NumberType)); - return true; - } - - /*! - @brief create a string by reading characters from the input - - @tparam NumberType the type of the number - @param[in] format the current format (for diagnostics) - @param[in] len number of characters to read - @param[out] result string created by reading @a len bytes - - @return whether string creation completed - - @note We can not reserve @a len bytes for the result, because @a len - may be too large. Usually, @ref unexpect_eof() detects the end of - the input before we run out of string memory. - */ - template - bool get_string(const input_format_t format, - const NumberType len, - string_t& result) - { - bool success = true; - for (NumberType i = 0; i < len; i++) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string"))) - { - success = false; - break; - } - result.push_back(static_cast(current)); - }; - return success; - } - - /*! - @brief create a byte array by reading bytes from the input - - @tparam NumberType the type of the number - @param[in] format the current format (for diagnostics) - @param[in] len number of bytes to read - @param[out] result byte array created by reading @a len bytes - - @return whether byte array creation completed - - @note We can not reserve @a len bytes for the result, because @a len - may be too large. Usually, @ref unexpect_eof() detects the end of - the input before we run out of memory. - */ - template - bool get_binary(const input_format_t format, - const NumberType len, - binary_t& result) - { - bool success = true; - for (NumberType i = 0; i < len; i++) - { - get(); - if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary"))) - { - success = false; - break; - } - result.push_back(static_cast(current)); - } - return success; - } - - /*! - @param[in] format the current format (for diagnostics) - @param[in] context further context information (for diagnostics) - @return whether the last read character is not EOF - */ - JSON_HEDLEY_NON_NULL(3) - bool unexpect_eof(const input_format_t format, const char* context) const - { - if (JSON_HEDLEY_UNLIKELY(current == std::char_traits::eof())) - { - return sax->parse_error(chars_read, "", - parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context))); - } - return true; - } - - /*! - @return a string representation of the last read byte - */ - std::string get_token_string() const - { - std::array cr{{}}; - (std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast(current)); - return std::string{cr.data()}; - } - - /*! - @param[in] format the current format - @param[in] detail a detailed error message - @param[in] context further context information - @return a message string to use in the parse_error exceptions - */ - std::string exception_message(const input_format_t format, - const std::string& detail, - const std::string& context) const - { - std::string error_msg = "syntax error while parsing "; - - switch (format) - { - case input_format_t::cbor: - error_msg += "CBOR"; - break; - - case input_format_t::msgpack: - error_msg += "MessagePack"; - break; - - case input_format_t::ubjson: - error_msg += "UBJSON"; - break; - - case input_format_t::bson: - error_msg += "BSON"; - break; - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - - return error_msg + " " + context + ": " + detail; - } - - private: - /// input adapter - InputAdapterType ia; - - /// the current character - char_int_type current = std::char_traits::eof(); - - /// the number of characters read - std::size_t chars_read = 0; - - /// whether we can assume little endianess - const bool is_little_endian = little_endianess(); - - /// the SAX parser - json_sax_t* sax = nullptr; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - -// #include - - -#include // isfinite -#include // uint8_t -#include // function -#include // string -#include // move -#include // vector - -// #include - -// #include - -// #include - -// #include - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -//////////// -// parser // -//////////// - -enum class parse_event_t : uint8_t -{ - /// the parser read `{` and started to process a JSON object - object_start, - /// the parser read `}` and finished processing a JSON object - object_end, - /// the parser read `[` and started to process a JSON array - array_start, - /// the parser read `]` and finished processing a JSON array - array_end, - /// the parser read a key of a value in an object - key, - /// the parser finished reading a JSON value - value -}; - -template -using parser_callback_t = - std::function; - -/*! -@brief syntax analysis - -This class implements a recursive descent parser. -*/ -template -class parser -{ - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using number_float_t = typename BasicJsonType::number_float_t; - using string_t = typename BasicJsonType::string_t; - using lexer_t = lexer; - using token_type = typename lexer_t::token_type; - - public: - /// a parser reading from an input adapter - explicit parser(InputAdapterType&& adapter, - const parser_callback_t cb = nullptr, - const bool allow_exceptions_ = true, - const bool skip_comments = false) - : callback(cb) - , m_lexer(std::move(adapter), skip_comments) - , allow_exceptions(allow_exceptions_) - { - // read first token - get_token(); - } - - /*! - @brief public parser interface - - @param[in] strict whether to expect the last token to be EOF - @param[in,out] result parsed JSON value - - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - */ - void parse(const bool strict, BasicJsonType& result) - { - if (callback) - { - json_sax_dom_callback_parser sdp(result, callback, allow_exceptions); - sax_parse_internal(&sdp); - result.assert_invariant(); - - // in strict mode, input must be completely read - if (strict && (get_token() != token_type::end_of_input)) - { - sdp.parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_of_input, "value"))); - } - - // in case of an error, return discarded value - if (sdp.is_errored()) - { - result = value_t::discarded; - return; - } - - // set top-level value to null if it was discarded by the callback - // function - if (result.is_discarded()) - { - result = nullptr; - } - } - else - { - json_sax_dom_parser sdp(result, allow_exceptions); - sax_parse_internal(&sdp); - result.assert_invariant(); - - // in strict mode, input must be completely read - if (strict && (get_token() != token_type::end_of_input)) - { - sdp.parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_of_input, "value"))); - } - - // in case of an error, return discarded value - if (sdp.is_errored()) - { - result = value_t::discarded; - return; - } - } - } - - /*! - @brief public accept interface - - @param[in] strict whether to expect the last token to be EOF - @return whether the input is a proper JSON text - */ - bool accept(const bool strict = true) - { - json_sax_acceptor sax_acceptor; - return sax_parse(&sax_acceptor, strict); - } - - template - JSON_HEDLEY_NON_NULL(2) - bool sax_parse(SAX* sax, const bool strict = true) - { - (void)detail::is_sax_static_asserts {}; - const bool result = sax_parse_internal(sax); - - // strict mode: next byte must be EOF - if (result && strict && (get_token() != token_type::end_of_input)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_of_input, "value"))); - } - - return result; - } - - private: - template - JSON_HEDLEY_NON_NULL(2) - bool sax_parse_internal(SAX* sax) - { - // stack to remember the hierarchy of structured values we are parsing - // true = array; false = object - std::vector states; - // value to avoid a goto (see comment where set to true) - bool skip_to_state_evaluation = false; - - while (true) - { - if (!skip_to_state_evaluation) - { - // invariant: get_token() was called before each iteration - switch (last_token) - { - case token_type::begin_object: - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_object(std::size_t(-1)))) - { - return false; - } - - // closing } -> we are done - if (get_token() == token_type::end_object) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) - { - return false; - } - break; - } - - // parse key - if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::value_string, "object key"))); - } - if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) - { - return false; - } - - // parse separator (:) - if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::name_separator, "object separator"))); - } - - // remember we are now inside an object - states.push_back(false); - - // parse values - get_token(); - continue; - } - - case token_type::begin_array: - { - if (JSON_HEDLEY_UNLIKELY(!sax->start_array(std::size_t(-1)))) - { - return false; - } - - // closing ] -> we are done - if (get_token() == token_type::end_array) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) - { - return false; - } - break; - } - - // remember we are now inside an array - states.push_back(true); - - // parse values (no need to call get_token) - continue; - } - - case token_type::value_float: - { - const auto res = m_lexer.get_number_float(); - - if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res))) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - out_of_range::create(406, "number overflow parsing '" + m_lexer.get_token_string() + "'")); - } - - if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string()))) - { - return false; - } - - break; - } - - case token_type::literal_false: - { - if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false))) - { - return false; - } - break; - } - - case token_type::literal_null: - { - if (JSON_HEDLEY_UNLIKELY(!sax->null())) - { - return false; - } - break; - } - - case token_type::literal_true: - { - if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true))) - { - return false; - } - break; - } - - case token_type::value_integer: - { - if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer()))) - { - return false; - } - break; - } - - case token_type::value_string: - { - if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string()))) - { - return false; - } - break; - } - - case token_type::value_unsigned: - { - if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned()))) - { - return false; - } - break; - } - - case token_type::parse_error: - { - // using "uninitialized" to avoid "expected" message - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::uninitialized, "value"))); - } - - default: // the last token was unexpected - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::literal_or_value, "value"))); - } - } - } - else - { - skip_to_state_evaluation = false; - } - - // we reached this line after we successfully parsed a value - if (states.empty()) - { - // empty stack: we reached the end of the hierarchy: done - return true; - } - - if (states.back()) // array - { - // comma -> next value - if (get_token() == token_type::value_separator) - { - // parse a new value - get_token(); - continue; - } - - // closing ] - if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array)) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_array())) - { - return false; - } - - // We are done with this array. Before we can parse a - // new value, we need to evaluate the new state first. - // By setting skip_to_state_evaluation to false, we - // are effectively jumping to the beginning of this if. - JSON_ASSERT(!states.empty()); - states.pop_back(); - skip_to_state_evaluation = true; - continue; - } - - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_array, "array"))); - } - else // object - { - // comma -> next value - if (get_token() == token_type::value_separator) - { - // parse key - if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::value_string, "object key"))); - } - - if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string()))) - { - return false; - } - - // parse separator (:) - if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator)) - { - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::name_separator, "object separator"))); - } - - // parse values - get_token(); - continue; - } - - // closing } - if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object)) - { - if (JSON_HEDLEY_UNLIKELY(!sax->end_object())) - { - return false; - } - - // We are done with this object. Before we can parse a - // new value, we need to evaluate the new state first. - // By setting skip_to_state_evaluation to false, we - // are effectively jumping to the beginning of this if. - JSON_ASSERT(!states.empty()); - states.pop_back(); - skip_to_state_evaluation = true; - continue; - } - - return sax->parse_error(m_lexer.get_position(), - m_lexer.get_token_string(), - parse_error::create(101, m_lexer.get_position(), - exception_message(token_type::end_object, "object"))); - } - } - } - - /// get next token from lexer - token_type get_token() - { - return last_token = m_lexer.scan(); - } - - std::string exception_message(const token_type expected, const std::string& context) - { - std::string error_msg = "syntax error "; - - if (!context.empty()) - { - error_msg += "while parsing " + context + " "; - } - - error_msg += "- "; - - if (last_token == token_type::parse_error) - { - error_msg += std::string(m_lexer.get_error_message()) + "; last read: '" + - m_lexer.get_token_string() + "'"; - } - else - { - error_msg += "unexpected " + std::string(lexer_t::token_type_name(last_token)); - } - - if (expected != token_type::uninitialized) - { - error_msg += "; expected " + std::string(lexer_t::token_type_name(expected)); - } - - return error_msg; - } - - private: - /// callback function - const parser_callback_t callback = nullptr; - /// the type of the last read token - token_type last_token = token_type::uninitialized; - /// the lexer - lexer_t m_lexer; - /// whether to throw exceptions in case of errors - const bool allow_exceptions = true; -}; -} // namespace detail -} // namespace nlohmann - -// #include - - -// #include - - -#include // ptrdiff_t -#include // numeric_limits - -namespace nlohmann -{ -namespace detail -{ -/* -@brief an iterator for primitive JSON types - -This class models an iterator for primitive JSON types (boolean, number, -string). It's only purpose is to allow the iterator/const_iterator classes -to "iterate" over primitive values. Internally, the iterator is modeled by -a `difference_type` variable. Value begin_value (`0`) models the begin, -end_value (`1`) models past the end. -*/ -class primitive_iterator_t -{ - private: - using difference_type = std::ptrdiff_t; - static constexpr difference_type begin_value = 0; - static constexpr difference_type end_value = begin_value + 1; - - JSON_PRIVATE_UNLESS_TESTED: - /// iterator as signed integer type - difference_type m_it = (std::numeric_limits::min)(); - - public: - constexpr difference_type get_value() const noexcept - { - return m_it; - } - - /// set iterator to a defined beginning - void set_begin() noexcept - { - m_it = begin_value; - } - - /// set iterator to a defined past the end - void set_end() noexcept - { - m_it = end_value; - } - - /// return whether the iterator can be dereferenced - constexpr bool is_begin() const noexcept - { - return m_it == begin_value; - } - - /// return whether the iterator is at end - constexpr bool is_end() const noexcept - { - return m_it == end_value; - } - - friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it == rhs.m_it; - } - - friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it < rhs.m_it; - } - - primitive_iterator_t operator+(difference_type n) noexcept - { - auto result = *this; - result += n; - return result; - } - - friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept - { - return lhs.m_it - rhs.m_it; - } - - primitive_iterator_t& operator++() noexcept - { - ++m_it; - return *this; - } - - primitive_iterator_t const operator++(int) noexcept - { - auto result = *this; - ++m_it; - return result; - } - - primitive_iterator_t& operator--() noexcept - { - --m_it; - return *this; - } - - primitive_iterator_t const operator--(int) noexcept - { - auto result = *this; - --m_it; - return result; - } - - primitive_iterator_t& operator+=(difference_type n) noexcept - { - m_it += n; - return *this; - } - - primitive_iterator_t& operator-=(difference_type n) noexcept - { - m_it -= n; - return *this; - } -}; -} // namespace detail -} // namespace nlohmann - - -namespace nlohmann -{ -namespace detail -{ -/*! -@brief an iterator value - -@note This structure could easily be a union, but MSVC currently does not allow -unions members with complex constructors, see https://github.com/nlohmann/json/pull/105. -*/ -template struct internal_iterator -{ - /// iterator for JSON objects - typename BasicJsonType::object_t::iterator object_iterator {}; - /// iterator for JSON arrays - typename BasicJsonType::array_t::iterator array_iterator {}; - /// generic iterator for all other types - primitive_iterator_t primitive_iterator {}; -}; -} // namespace detail -} // namespace nlohmann - -// #include - - -#include // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next -#include // conditional, is_const, remove_const - -// #include - -// #include - -// #include - -// #include - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -// forward declare, to be able to friend it later on -template class iteration_proxy; -template class iteration_proxy_value; - -/*! -@brief a template for a bidirectional iterator for the @ref basic_json class -This class implements a both iterators (iterator and const_iterator) for the -@ref basic_json class. -@note An iterator is called *initialized* when a pointer to a JSON value has - been set (e.g., by a constructor or a copy assignment). If the iterator is - default-constructed, it is *uninitialized* and most methods are undefined. - **The library uses assertions to detect calls on uninitialized iterators.** -@requirement The class satisfies the following concept requirements: -- -[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): - The iterator that can be moved can be moved in both directions (i.e. - incremented and decremented). -@since version 1.0.0, simplified in version 2.0.9, change to bidirectional - iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593) -*/ -template -class iter_impl -{ - /// allow basic_json to access private members - friend iter_impl::value, typename std::remove_const::type, const BasicJsonType>::type>; - friend BasicJsonType; - friend iteration_proxy; - friend iteration_proxy_value; - - using object_t = typename BasicJsonType::object_t; - using array_t = typename BasicJsonType::array_t; - // make sure BasicJsonType is basic_json or const basic_json - static_assert(is_basic_json::type>::value, - "iter_impl only accepts (const) basic_json"); - - public: - - /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. - /// The C++ Standard has never required user-defined iterators to derive from std::iterator. - /// A user-defined iterator should provide publicly accessible typedefs named - /// iterator_category, value_type, difference_type, pointer, and reference. - /// Note that value_type is required to be non-const, even for constant iterators. - using iterator_category = std::bidirectional_iterator_tag; - - /// the type of the values when the iterator is dereferenced - using value_type = typename BasicJsonType::value_type; - /// a type to represent differences between iterators - using difference_type = typename BasicJsonType::difference_type; - /// defines a pointer to the type iterated over (value_type) - using pointer = typename std::conditional::value, - typename BasicJsonType::const_pointer, - typename BasicJsonType::pointer>::type; - /// defines a reference to the type iterated over (value_type) - using reference = - typename std::conditional::value, - typename BasicJsonType::const_reference, - typename BasicJsonType::reference>::type; - - /// default constructor - iter_impl() = default; - - /*! - @brief constructor for a given JSON instance - @param[in] object pointer to a JSON object for this iterator - @pre object != nullptr - @post The iterator is initialized; i.e. `m_object != nullptr`. - */ - explicit iter_impl(pointer object) noexcept : m_object(object) - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - m_it.object_iterator = typename object_t::iterator(); - break; - } - - case value_t::array: - { - m_it.array_iterator = typename array_t::iterator(); - break; - } - - default: - { - m_it.primitive_iterator = primitive_iterator_t(); - break; - } - } - } - - /*! - @note The conventional copy constructor and copy assignment are implicitly - defined. Combined with the following converting constructor and - assignment, they support: (1) copy from iterator to iterator, (2) - copy from const iterator to const iterator, and (3) conversion from - iterator to const iterator. However conversion from const iterator - to iterator is not defined. - */ - - /*! - @brief const copy constructor - @param[in] other const iterator to copy from - @note This copy constructor had to be defined explicitly to circumvent a bug - occurring on msvc v19.0 compiler (VS 2015) debug build. For more - information refer to: https://github.com/nlohmann/json/issues/1608 - */ - iter_impl(const iter_impl& other) noexcept - : m_object(other.m_object), m_it(other.m_it) - {} - - /*! - @brief converting assignment - @param[in] other const iterator to copy from - @return const/non-const iterator - @note It is not checked whether @a other is initialized. - */ - iter_impl& operator=(const iter_impl& other) noexcept - { - m_object = other.m_object; - m_it = other.m_it; - return *this; - } - - /*! - @brief converting constructor - @param[in] other non-const iterator to copy from - @note It is not checked whether @a other is initialized. - */ - iter_impl(const iter_impl::type>& other) noexcept - : m_object(other.m_object), m_it(other.m_it) - {} - - /*! - @brief converting assignment - @param[in] other non-const iterator to copy from - @return const/non-const iterator - @note It is not checked whether @a other is initialized. - */ - iter_impl& operator=(const iter_impl::type>& other) noexcept - { - m_object = other.m_object; - m_it = other.m_it; - return *this; - } - - JSON_PRIVATE_UNLESS_TESTED: - /*! - @brief set the iterator to the first value - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - void set_begin() noexcept - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - m_it.object_iterator = m_object->m_value.object->begin(); - break; - } - - case value_t::array: - { - m_it.array_iterator = m_object->m_value.array->begin(); - break; - } - - case value_t::null: - { - // set to end so begin()==end() is true: null is empty - m_it.primitive_iterator.set_end(); - break; - } - - default: - { - m_it.primitive_iterator.set_begin(); - break; - } - } - } - - /*! - @brief set the iterator past the last value - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - void set_end() noexcept - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - m_it.object_iterator = m_object->m_value.object->end(); - break; - } - - case value_t::array: - { - m_it.array_iterator = m_object->m_value.array->end(); - break; - } - - default: - { - m_it.primitive_iterator.set_end(); - break; - } - } - } - - public: - /*! - @brief return a reference to the value pointed to by the iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - reference operator*() const - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); - return m_it.object_iterator->second; - } - - case value_t::array: - { - JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); - return *m_it.array_iterator; - } - - case value_t::null: - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - - default: - { - if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) - { - return *m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - } - } - } - - /*! - @brief dereference the iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - pointer operator->() const - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end()); - return &(m_it.object_iterator->second); - } - - case value_t::array: - { - JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end()); - return &*m_it.array_iterator; - } - - default: - { - if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin())) - { - return m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - } - } - } - - /*! - @brief post-increment (it++) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl const operator++(int) - { - auto result = *this; - ++(*this); - return result; - } - - /*! - @brief pre-increment (++it) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator++() - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - std::advance(m_it.object_iterator, 1); - break; - } - - case value_t::array: - { - std::advance(m_it.array_iterator, 1); - break; - } - - default: - { - ++m_it.primitive_iterator; - break; - } - } - - return *this; - } - - /*! - @brief post-decrement (it--) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl const operator--(int) - { - auto result = *this; - --(*this); - return result; - } - - /*! - @brief pre-decrement (--it) - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator--() - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - { - std::advance(m_it.object_iterator, -1); - break; - } - - case value_t::array: - { - std::advance(m_it.array_iterator, -1); - break; - } - - default: - { - --m_it.primitive_iterator; - break; - } - } - - return *this; - } - - /*! - @brief comparison: equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator==(const iter_impl& other) const - { - // if objects are not the same, the comparison is undefined - if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) - { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); - } - - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - return (m_it.object_iterator == other.m_it.object_iterator); - - case value_t::array: - return (m_it.array_iterator == other.m_it.array_iterator); - - default: - return (m_it.primitive_iterator == other.m_it.primitive_iterator); - } - } - - /*! - @brief comparison: not equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator!=(const iter_impl& other) const - { - return !operator==(other); - } - - /*! - @brief comparison: smaller - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator<(const iter_impl& other) const - { - // if objects are not the same, the comparison is undefined - if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object)) - { - JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers")); - } - - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators")); - - case value_t::array: - return (m_it.array_iterator < other.m_it.array_iterator); - - default: - return (m_it.primitive_iterator < other.m_it.primitive_iterator); - } - } - - /*! - @brief comparison: less than or equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator<=(const iter_impl& other) const - { - return !other.operator < (*this); - } - - /*! - @brief comparison: greater than - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator>(const iter_impl& other) const - { - return !operator<=(other); - } - - /*! - @brief comparison: greater than or equal - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - bool operator>=(const iter_impl& other) const - { - return !operator<(other); - } - - /*! - @brief add to iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator+=(difference_type i) - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); - - case value_t::array: - { - std::advance(m_it.array_iterator, i); - break; - } - - default: - { - m_it.primitive_iterator += i; - break; - } - } - - return *this; - } - - /*! - @brief subtract from iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl& operator-=(difference_type i) - { - return operator+=(-i); - } - - /*! - @brief add to iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl operator+(difference_type i) const - { - auto result = *this; - result += i; - return result; - } - - /*! - @brief addition of distance and iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - friend iter_impl operator+(difference_type i, const iter_impl& it) - { - auto result = it; - result += i; - return result; - } - - /*! - @brief subtract from iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - iter_impl operator-(difference_type i) const - { - auto result = *this; - result -= i; - return result; - } - - /*! - @brief return difference - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - difference_type operator-(const iter_impl& other) const - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators")); - - case value_t::array: - return m_it.array_iterator - other.m_it.array_iterator; - - default: - return m_it.primitive_iterator - other.m_it.primitive_iterator; - } - } - - /*! - @brief access to successor - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - reference operator[](difference_type n) const - { - JSON_ASSERT(m_object != nullptr); - - switch (m_object->m_type) - { - case value_t::object: - JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators")); - - case value_t::array: - return *std::next(m_it.array_iterator, n); - - case value_t::null: - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - - default: - { - if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n)) - { - return *m_object; - } - - JSON_THROW(invalid_iterator::create(214, "cannot get value")); - } - } - } - - /*! - @brief return the key of an object iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - const typename object_t::key_type& key() const - { - JSON_ASSERT(m_object != nullptr); - - if (JSON_HEDLEY_LIKELY(m_object->is_object())) - { - return m_it.object_iterator->first; - } - - JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators")); - } - - /*! - @brief return the value of an iterator - @pre The iterator is initialized; i.e. `m_object != nullptr`. - */ - reference value() const - { - return operator*(); - } - - JSON_PRIVATE_UNLESS_TESTED: - /// associated JSON instance - pointer m_object = nullptr; - /// the actual iterator of the associated instance - internal_iterator::type> m_it {}; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - - -#include // ptrdiff_t -#include // reverse_iterator -#include // declval - -namespace nlohmann -{ -namespace detail -{ -////////////////////// -// reverse_iterator // -////////////////////// - -/*! -@brief a template for a reverse iterator class - -@tparam Base the base iterator type to reverse. Valid types are @ref -iterator (to create @ref reverse_iterator) and @ref const_iterator (to -create @ref const_reverse_iterator). - -@requirement The class satisfies the following concept requirements: -- -[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator): - The iterator that can be moved can be moved in both directions (i.e. - incremented and decremented). -- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator): - It is possible to write to the pointed-to element (only if @a Base is - @ref iterator). - -@since version 1.0.0 -*/ -template -class json_reverse_iterator : public std::reverse_iterator -{ - public: - using difference_type = std::ptrdiff_t; - /// shortcut to the reverse iterator adapter - using base_iterator = std::reverse_iterator; - /// the reference type for the pointed-to element - using reference = typename Base::reference; - - /// create reverse iterator from iterator - explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept - : base_iterator(it) {} - - /// create reverse iterator from base class - explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {} - - /// post-increment (it++) - json_reverse_iterator const operator++(int) - { - return static_cast(base_iterator::operator++(1)); - } - - /// pre-increment (++it) - json_reverse_iterator& operator++() - { - return static_cast(base_iterator::operator++()); - } - - /// post-decrement (it--) - json_reverse_iterator const operator--(int) - { - return static_cast(base_iterator::operator--(1)); - } - - /// pre-decrement (--it) - json_reverse_iterator& operator--() - { - return static_cast(base_iterator::operator--()); - } - - /// add to iterator - json_reverse_iterator& operator+=(difference_type i) - { - return static_cast(base_iterator::operator+=(i)); - } - - /// add to iterator - json_reverse_iterator operator+(difference_type i) const - { - return static_cast(base_iterator::operator+(i)); - } - - /// subtract from iterator - json_reverse_iterator operator-(difference_type i) const - { - return static_cast(base_iterator::operator-(i)); - } - - /// return difference - difference_type operator-(const json_reverse_iterator& other) const - { - return base_iterator(*this) - base_iterator(other); - } - - /// access to successor - reference operator[](difference_type n) const - { - return *(this->operator+(n)); - } - - /// return the key of an object iterator - auto key() const -> decltype(std::declval().key()) - { - auto it = --this->base(); - return it.key(); - } - - /// return the value of an iterator - reference value() const - { - auto it = --this->base(); - return it.operator * (); - } -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - - -#include // all_of -#include // isdigit -#include // max -#include // accumulate -#include // string -#include // move -#include // vector - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -template -class json_pointer -{ - // allow basic_json to access private members - NLOHMANN_BASIC_JSON_TPL_DECLARATION - friend class basic_json; - - public: - /*! - @brief create JSON pointer - - Create a JSON pointer according to the syntax described in - [Section 3 of RFC6901](https://tools.ietf.org/html/rfc6901#section-3). - - @param[in] s string representing the JSON pointer; if omitted, the empty - string is assumed which references the whole JSON value - - @throw parse_error.107 if the given JSON pointer @a s is nonempty and does - not begin with a slash (`/`); see example below - - @throw parse_error.108 if a tilde (`~`) in the given JSON pointer @a s is - not followed by `0` (representing `~`) or `1` (representing `/`); see - example below - - @liveexample{The example shows the construction several valid JSON pointers - as well as the exceptional behavior.,json_pointer} - - @since version 2.0.0 - */ - explicit json_pointer(const std::string& s = "") - : reference_tokens(split(s)) - {} - - /*! - @brief return a string representation of the JSON pointer - - @invariant For each JSON pointer `ptr`, it holds: - @code {.cpp} - ptr == json_pointer(ptr.to_string()); - @endcode - - @return a string representation of the JSON pointer - - @liveexample{The example shows the result of `to_string`.,json_pointer__to_string} - - @since version 2.0.0 - */ - std::string to_string() const - { - return std::accumulate(reference_tokens.begin(), reference_tokens.end(), - std::string{}, - [](const std::string & a, const std::string & b) - { - return a + "/" + escape(b); - }); - } - - /// @copydoc to_string() - operator std::string() const - { - return to_string(); - } - - /*! - @brief append another JSON pointer at the end of this JSON pointer - - @param[in] ptr JSON pointer to append - @return JSON pointer with @a ptr appended - - @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} - - @complexity Linear in the length of @a ptr. - - @sa @ref operator/=(std::string) to append a reference token - @sa @ref operator/=(std::size_t) to append an array index - @sa @ref operator/(const json_pointer&, const json_pointer&) for a binary operator - - @since version 3.6.0 - */ - json_pointer& operator/=(const json_pointer& ptr) - { - reference_tokens.insert(reference_tokens.end(), - ptr.reference_tokens.begin(), - ptr.reference_tokens.end()); - return *this; - } - - /*! - @brief append an unescaped reference token at the end of this JSON pointer - - @param[in] token reference token to append - @return JSON pointer with @a token appended without escaping @a token - - @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} - - @complexity Amortized constant. - - @sa @ref operator/=(const json_pointer&) to append a JSON pointer - @sa @ref operator/=(std::size_t) to append an array index - @sa @ref operator/(const json_pointer&, std::size_t) for a binary operator - - @since version 3.6.0 - */ - json_pointer& operator/=(std::string token) - { - push_back(std::move(token)); - return *this; - } - - /*! - @brief append an array index at the end of this JSON pointer - - @param[in] array_idx array index to append - @return JSON pointer with @a array_idx appended - - @liveexample{The example shows the usage of `operator/=`.,json_pointer__operator_add} - - @complexity Amortized constant. - - @sa @ref operator/=(const json_pointer&) to append a JSON pointer - @sa @ref operator/=(std::string) to append a reference token - @sa @ref operator/(const json_pointer&, std::string) for a binary operator - - @since version 3.6.0 - */ - json_pointer& operator/=(std::size_t array_idx) - { - return *this /= std::to_string(array_idx); - } - - /*! - @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer - - @param[in] lhs JSON pointer - @param[in] rhs JSON pointer - @return a new JSON pointer with @a rhs appended to @a lhs - - @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} - - @complexity Linear in the length of @a lhs and @a rhs. - - @sa @ref operator/=(const json_pointer&) to append a JSON pointer - - @since version 3.6.0 - */ - friend json_pointer operator/(const json_pointer& lhs, - const json_pointer& rhs) - { - return json_pointer(lhs) /= rhs; - } - - /*! - @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer - - @param[in] ptr JSON pointer - @param[in] token reference token - @return a new JSON pointer with unescaped @a token appended to @a ptr - - @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} - - @complexity Linear in the length of @a ptr. - - @sa @ref operator/=(std::string) to append a reference token - - @since version 3.6.0 - */ - friend json_pointer operator/(const json_pointer& ptr, std::string token) - { - return json_pointer(ptr) /= std::move(token); - } - - /*! - @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer - - @param[in] ptr JSON pointer - @param[in] array_idx array index - @return a new JSON pointer with @a array_idx appended to @a ptr - - @liveexample{The example shows the usage of `operator/`.,json_pointer__operator_add_binary} - - @complexity Linear in the length of @a ptr. - - @sa @ref operator/=(std::size_t) to append an array index - - @since version 3.6.0 - */ - friend json_pointer operator/(const json_pointer& ptr, std::size_t array_idx) - { - return json_pointer(ptr) /= array_idx; - } - - /*! - @brief returns the parent of this JSON pointer - - @return parent of this JSON pointer; in case this JSON pointer is the root, - the root itself is returned - - @complexity Linear in the length of the JSON pointer. - - @liveexample{The example shows the result of `parent_pointer` for different - JSON Pointers.,json_pointer__parent_pointer} - - @since version 3.6.0 - */ - json_pointer parent_pointer() const - { - if (empty()) - { - return *this; - } - - json_pointer res = *this; - res.pop_back(); - return res; - } - - /*! - @brief remove last reference token - - @pre not `empty()` - - @liveexample{The example shows the usage of `pop_back`.,json_pointer__pop_back} - - @complexity Constant. - - @throw out_of_range.405 if JSON pointer has no parent - - @since version 3.6.0 - */ - void pop_back() - { - if (JSON_HEDLEY_UNLIKELY(empty())) - { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); - } - - reference_tokens.pop_back(); - } - - /*! - @brief return last reference token - - @pre not `empty()` - @return last reference token - - @liveexample{The example shows the usage of `back`.,json_pointer__back} - - @complexity Constant. - - @throw out_of_range.405 if JSON pointer has no parent - - @since version 3.6.0 - */ - const std::string& back() const - { - if (JSON_HEDLEY_UNLIKELY(empty())) - { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); - } - - return reference_tokens.back(); - } - - /*! - @brief append an unescaped token at the end of the reference pointer - - @param[in] token token to add - - @complexity Amortized constant. - - @liveexample{The example shows the result of `push_back` for different - JSON Pointers.,json_pointer__push_back} - - @since version 3.6.0 - */ - void push_back(const std::string& token) - { - reference_tokens.push_back(token); - } - - /// @copydoc push_back(const std::string&) - void push_back(std::string&& token) - { - reference_tokens.push_back(std::move(token)); - } - - /*! - @brief return whether pointer points to the root document - - @return true iff the JSON pointer points to the root document - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example shows the result of `empty` for different JSON - Pointers.,json_pointer__empty} - - @since version 3.6.0 - */ - bool empty() const noexcept - { - return reference_tokens.empty(); - } - - private: - /*! - @param[in] s reference token to be converted into an array index - - @return integer representation of @a s - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index begins not with a digit - @throw out_of_range.404 if string @a s could not be converted to an integer - @throw out_of_range.410 if an array index exceeds size_type - */ - static typename BasicJsonType::size_type array_index(const std::string& s) - { - using size_type = typename BasicJsonType::size_type; - - // error condition (cf. RFC 6901, Sect. 4) - if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0')) - { - JSON_THROW(detail::parse_error::create(106, 0, - "array index '" + s + - "' must not begin with '0'")); - } - - // error condition (cf. RFC 6901, Sect. 4) - if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9'))) - { - JSON_THROW(detail::parse_error::create(109, 0, "array index '" + s + "' is not a number")); - } - - std::size_t processed_chars = 0; - unsigned long long res = 0; - JSON_TRY - { - res = std::stoull(s, &processed_chars); - } - JSON_CATCH(std::out_of_range&) - { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); - } - - // check if the string was completely read - if (JSON_HEDLEY_UNLIKELY(processed_chars != s.size())) - { - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + s + "'")); - } - - // only triggered on special platforms (like 32bit), see also - // https://github.com/nlohmann/json/pull/2203 - if (res >= static_cast((std::numeric_limits::max)())) - { - JSON_THROW(detail::out_of_range::create(410, "array index " + s + " exceeds size_type")); // LCOV_EXCL_LINE - } - - return static_cast(res); - } - - JSON_PRIVATE_UNLESS_TESTED: - json_pointer top() const - { - if (JSON_HEDLEY_UNLIKELY(empty())) - { - JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent")); - } - - json_pointer result = *this; - result.reference_tokens = {reference_tokens[0]}; - return result; - } - - private: - /*! - @brief create and return a reference to the pointed to value - - @complexity Linear in the number of reference tokens. - - @throw parse_error.109 if array index is not a number - @throw type_error.313 if value cannot be unflattened - */ - BasicJsonType& get_and_create(BasicJsonType& j) const - { - auto result = &j; - - // in case no reference tokens exist, return a reference to the JSON value - // j which will be overwritten by a primitive value - for (const auto& reference_token : reference_tokens) - { - switch (result->type()) - { - case detail::value_t::null: - { - if (reference_token == "0") - { - // start a new array if reference token is 0 - result = &result->operator[](0); - } - else - { - // start a new object otherwise - result = &result->operator[](reference_token); - } - break; - } - - case detail::value_t::object: - { - // create an entry in the object - result = &result->operator[](reference_token); - break; - } - - case detail::value_t::array: - { - // create an entry in the array - result = &result->operator[](array_index(reference_token)); - break; - } - - /* - The following code is only reached if there exists a reference - token _and_ the current value is primitive. In this case, we have - an error situation, because primitive values may only occur as - single value; that is, with an empty list of reference tokens. - */ - default: - JSON_THROW(detail::type_error::create(313, "invalid value to unflatten")); - } - } - - return *result; - } - - /*! - @brief return a reference to the pointed to value - - @note This version does not throw if a value is not present, but tries to - create nested values instead. For instance, calling this function - with pointer `"/this/that"` on a null value is equivalent to calling - `operator[]("this").operator[]("that")` on that value, effectively - changing the null value to an object. - - @param[in] ptr a JSON value - - @return reference to the JSON value pointed to by the JSON pointer - - @complexity Linear in the length of the JSON pointer. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - BasicJsonType& get_unchecked(BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - // convert null values to arrays or objects before continuing - if (ptr->is_null()) - { - // check if reference token is a number - const bool nums = - std::all_of(reference_token.begin(), reference_token.end(), - [](const unsigned char x) - { - return std::isdigit(x); - }); - - // change value to array for numbers or "-" or to object otherwise - *ptr = (nums || reference_token == "-") - ? detail::value_t::array - : detail::value_t::object; - } - - switch (ptr->type()) - { - case detail::value_t::object: - { - // use unchecked object access - ptr = &ptr->operator[](reference_token); - break; - } - - case detail::value_t::array: - { - if (reference_token == "-") - { - // explicitly treat "-" as index beyond the end - ptr = &ptr->operator[](ptr->m_value.array->size()); - } - else - { - // convert array index to number; unchecked access - ptr = &ptr->operator[](array_index(reference_token)); - } - break; - } - - default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); - } - } - - return *ptr; - } - - /*! - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - BasicJsonType& get_checked(BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - // note: at performs range check - ptr = &ptr->at(reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" always fails the range check - JSON_THROW(detail::out_of_range::create(402, - "array index '-' (" + std::to_string(ptr->m_value.array->size()) + - ") is out of range")); - } - - // note: at performs range check - ptr = &ptr->at(array_index(reference_token)); - break; - } - - default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); - } - } - - return *ptr; - } - - /*! - @brief return a const reference to the pointed to value - - @param[in] ptr a JSON value - - @return const reference to the JSON value pointed to by the JSON - pointer - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - // use unchecked object access - ptr = &ptr->operator[](reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" cannot be used for const access - JSON_THROW(detail::out_of_range::create(402, - "array index '-' (" + std::to_string(ptr->m_value.array->size()) + - ") is out of range")); - } - - // use unchecked array access - ptr = &ptr->operator[](array_index(reference_token)); - break; - } - - default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); - } - } - - return *ptr; - } - - /*! - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - */ - const BasicJsonType& get_checked(const BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - // note: at performs range check - ptr = &ptr->at(reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" always fails the range check - JSON_THROW(detail::out_of_range::create(402, - "array index '-' (" + std::to_string(ptr->m_value.array->size()) + - ") is out of range")); - } - - // note: at performs range check - ptr = &ptr->at(array_index(reference_token)); - break; - } - - default: - JSON_THROW(detail::out_of_range::create(404, "unresolved reference token '" + reference_token + "'")); - } - } - - return *ptr; - } - - /*! - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - */ - bool contains(const BasicJsonType* ptr) const - { - for (const auto& reference_token : reference_tokens) - { - switch (ptr->type()) - { - case detail::value_t::object: - { - if (!ptr->contains(reference_token)) - { - // we did not find the key in the object - return false; - } - - ptr = &ptr->operator[](reference_token); - break; - } - - case detail::value_t::array: - { - if (JSON_HEDLEY_UNLIKELY(reference_token == "-")) - { - // "-" always fails the range check - return false; - } - if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9"))) - { - // invalid char - return false; - } - if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1)) - { - if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9'))) - { - // first char should be between '1' and '9' - return false; - } - for (std::size_t i = 1; i < reference_token.size(); i++) - { - if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9'))) - { - // other char should be between '0' and '9' - return false; - } - } - } - - const auto idx = array_index(reference_token); - if (idx >= ptr->size()) - { - // index out of range - return false; - } - - ptr = &ptr->operator[](idx); - break; - } - - default: - { - // we do not expect primitive values if there is still a - // reference token to process - return false; - } - } - } - - // no reference token left means we found a primitive value - return true; - } - - /*! - @brief split the string input to reference tokens - - @note This function is only called by the json_pointer constructor. - All exceptions below are documented there. - - @throw parse_error.107 if the pointer is not empty or begins with '/' - @throw parse_error.108 if character '~' is not followed by '0' or '1' - */ - static std::vector split(const std::string& reference_string) - { - std::vector result; - - // special case: empty reference string -> no reference tokens - if (reference_string.empty()) - { - return result; - } - - // check if nonempty reference string begins with slash - if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/')) - { - JSON_THROW(detail::parse_error::create(107, 1, - "JSON pointer must be empty or begin with '/' - was: '" + - reference_string + "'")); - } - - // extract the reference tokens: - // - slash: position of the last read slash (or end of string) - // - start: position after the previous slash - for ( - // search for the first slash after the first character - std::size_t slash = reference_string.find_first_of('/', 1), - // set the beginning of the first reference token - start = 1; - // we can stop if start == 0 (if slash == std::string::npos) - start != 0; - // set the beginning of the next reference token - // (will eventually be 0 if slash == std::string::npos) - start = (slash == std::string::npos) ? 0 : slash + 1, - // find next slash - slash = reference_string.find_first_of('/', start)) - { - // use the text between the beginning of the reference token - // (start) and the last slash (slash). - auto reference_token = reference_string.substr(start, slash - start); - - // check reference tokens are properly escaped - for (std::size_t pos = reference_token.find_first_of('~'); - pos != std::string::npos; - pos = reference_token.find_first_of('~', pos + 1)) - { - JSON_ASSERT(reference_token[pos] == '~'); - - // ~ must be followed by 0 or 1 - if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || - (reference_token[pos + 1] != '0' && - reference_token[pos + 1] != '1'))) - { - JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'")); - } - } - - // finally, store the reference token - unescape(reference_token); - result.push_back(reference_token); - } - - return result; - } - - /*! - @brief replace all occurrences of a substring by another string - - @param[in,out] s the string to manipulate; changed so that all - occurrences of @a f are replaced with @a t - @param[in] f the substring to replace with @a t - @param[in] t the string to replace @a f - - @pre The search string @a f must not be empty. **This precondition is - enforced with an assertion.** - - @since version 2.0.0 - */ - static void replace_substring(std::string& s, const std::string& f, - const std::string& t) - { - JSON_ASSERT(!f.empty()); - for (auto pos = s.find(f); // find first occurrence of f - pos != std::string::npos; // make sure f was found - s.replace(pos, f.size(), t), // replace with t, and - pos = s.find(f, pos + t.size())) // find next occurrence of f - {} - } - - JSON_PRIVATE_UNLESS_TESTED: - /// escape "~" to "~0" and "/" to "~1" - static std::string escape(std::string s) - { - replace_substring(s, "~", "~0"); - replace_substring(s, "/", "~1"); - return s; - } - - /// unescape "~1" to tilde and "~0" to slash (order is important!) - static void unescape(std::string& s) - { - replace_substring(s, "~1", "/"); - replace_substring(s, "~0", "~"); - } - - private: - /*! - @param[in] reference_string the reference string to the current value - @param[in] value the value to consider - @param[in,out] result the result object to insert values to - - @note Empty objects or arrays are flattened to `null`. - */ - static void flatten(const std::string& reference_string, - const BasicJsonType& value, - BasicJsonType& result) - { - switch (value.type()) - { - case detail::value_t::array: - { - if (value.m_value.array->empty()) - { - // flatten empty array as null - result[reference_string] = nullptr; - } - else - { - // iterate array and use index as reference string - for (std::size_t i = 0; i < value.m_value.array->size(); ++i) - { - flatten(reference_string + "/" + std::to_string(i), - value.m_value.array->operator[](i), result); - } - } - break; - } - - case detail::value_t::object: - { - if (value.m_value.object->empty()) - { - // flatten empty object as null - result[reference_string] = nullptr; - } - else - { - // iterate object and use keys as reference string - for (const auto& element : *value.m_value.object) - { - flatten(reference_string + "/" + escape(element.first), element.second, result); - } - } - break; - } - - default: - { - // add primitive value with its reference string - result[reference_string] = value; - break; - } - } - } - - /*! - @param[in] value flattened JSON - - @return unflattened JSON - - @throw parse_error.109 if array index is not a number - @throw type_error.314 if value is not an object - @throw type_error.315 if object values are not primitive - @throw type_error.313 if value cannot be unflattened - */ - static BasicJsonType - unflatten(const BasicJsonType& value) - { - if (JSON_HEDLEY_UNLIKELY(!value.is_object())) - { - JSON_THROW(detail::type_error::create(314, "only objects can be unflattened")); - } - - BasicJsonType result; - - // iterate the JSON object values - for (const auto& element : *value.m_value.object) - { - if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive())) - { - JSON_THROW(detail::type_error::create(315, "values in object must be primitive")); - } - - // assign value to reference pointed to by JSON pointer; Note that if - // the JSON pointer is "" (i.e., points to the whole value), function - // get_and_create returns a reference to result itself. An assignment - // will then create a primitive value. - json_pointer(element.first).get_and_create(result) = element.second; - } - - return result; - } - - /*! - @brief compares two JSON pointers for equality - - @param[in] lhs JSON pointer to compare - @param[in] rhs JSON pointer to compare - @return whether @a lhs is equal to @a rhs - - @complexity Linear in the length of the JSON pointer - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - */ - friend bool operator==(json_pointer const& lhs, - json_pointer const& rhs) noexcept - { - return lhs.reference_tokens == rhs.reference_tokens; - } - - /*! - @brief compares two JSON pointers for inequality - - @param[in] lhs JSON pointer to compare - @param[in] rhs JSON pointer to compare - @return whether @a lhs is not equal @a rhs - - @complexity Linear in the length of the JSON pointer - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - */ - friend bool operator!=(json_pointer const& lhs, - json_pointer const& rhs) noexcept - { - return !(lhs == rhs); - } - - /// the reference tokens - std::vector reference_tokens; -}; -} // namespace nlohmann - -// #include - - -#include -#include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -template -class json_ref -{ - public: - using value_type = BasicJsonType; - - json_ref(value_type&& value) - : owned_value(std::move(value)) - , value_ref(&owned_value) - , is_rvalue(true) - {} - - json_ref(const value_type& value) - : value_ref(const_cast(&value)) - , is_rvalue(false) - {} - - json_ref(std::initializer_list init) - : owned_value(init) - , value_ref(&owned_value) - , is_rvalue(true) - {} - - template < - class... Args, - enable_if_t::value, int> = 0 > - json_ref(Args && ... args) - : owned_value(std::forward(args)...) - , value_ref(&owned_value) - , is_rvalue(true) - {} - - // class should be movable only - json_ref(json_ref&&) = default; - json_ref(const json_ref&) = delete; - json_ref& operator=(const json_ref&) = delete; - json_ref& operator=(json_ref&&) = delete; - ~json_ref() = default; - - value_type moved_or_copied() const - { - if (is_rvalue) - { - return std::move(*value_ref); - } - return *value_ref; - } - - value_type const& operator*() const - { - return *static_cast(value_ref); - } - - value_type const* operator->() const - { - return static_cast(value_ref); - } - - private: - mutable value_type owned_value = nullptr; - value_type* value_ref = nullptr; - const bool is_rvalue = true; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - -// #include - -// #include - - -#include // reverse -#include // array -#include // uint8_t, uint16_t, uint32_t, uint64_t -#include // memcpy -#include // numeric_limits -#include // string -#include // isnan, isinf - -// #include - -// #include - -// #include - - -#include // copy -#include // size_t -#include // streamsize -#include // back_inserter -#include // shared_ptr, make_shared -#include // basic_ostream -#include // basic_string -#include // vector -// #include - - -namespace nlohmann -{ -namespace detail -{ -/// abstract output adapter interface -template struct output_adapter_protocol -{ - virtual void write_character(CharType c) = 0; - virtual void write_characters(const CharType* s, std::size_t length) = 0; - virtual ~output_adapter_protocol() = default; -}; - -/// a type to simplify interfaces -template -using output_adapter_t = std::shared_ptr>; - -/// output adapter for byte vectors -template -class output_vector_adapter : public output_adapter_protocol -{ - public: - explicit output_vector_adapter(std::vector& vec) noexcept - : v(vec) - {} - - void write_character(CharType c) override - { - v.push_back(c); - } - - JSON_HEDLEY_NON_NULL(2) - void write_characters(const CharType* s, std::size_t length) override - { - std::copy(s, s + length, std::back_inserter(v)); - } - - private: - std::vector& v; -}; - -/// output adapter for output streams -template -class output_stream_adapter : public output_adapter_protocol -{ - public: - explicit output_stream_adapter(std::basic_ostream& s) noexcept - : stream(s) - {} - - void write_character(CharType c) override - { - stream.put(c); - } - - JSON_HEDLEY_NON_NULL(2) - void write_characters(const CharType* s, std::size_t length) override - { - stream.write(s, static_cast(length)); - } - - private: - std::basic_ostream& stream; -}; - -/// output adapter for basic_string -template> -class output_string_adapter : public output_adapter_protocol -{ - public: - explicit output_string_adapter(StringType& s) noexcept - : str(s) - {} - - void write_character(CharType c) override - { - str.push_back(c); - } - - JSON_HEDLEY_NON_NULL(2) - void write_characters(const CharType* s, std::size_t length) override - { - str.append(s, length); - } - - private: - StringType& str; -}; - -template> -class output_adapter -{ - public: - output_adapter(std::vector& vec) - : oa(std::make_shared>(vec)) {} - - output_adapter(std::basic_ostream& s) - : oa(std::make_shared>(s)) {} - - output_adapter(StringType& s) - : oa(std::make_shared>(s)) {} - - operator output_adapter_t() - { - return oa; - } - - private: - output_adapter_t oa = nullptr; -}; -} // namespace detail -} // namespace nlohmann - - -namespace nlohmann -{ -namespace detail -{ -/////////////////// -// binary writer // -/////////////////// - -/*! -@brief serialization to CBOR and MessagePack values -*/ -template -class binary_writer -{ - using string_t = typename BasicJsonType::string_t; - using binary_t = typename BasicJsonType::binary_t; - using number_float_t = typename BasicJsonType::number_float_t; - - public: - /*! - @brief create a binary writer - - @param[in] adapter output adapter to write to - */ - explicit binary_writer(output_adapter_t adapter) : oa(adapter) - { - JSON_ASSERT(oa); - } - - /*! - @param[in] j JSON value to serialize - @pre j.type() == value_t::object - */ - void write_bson(const BasicJsonType& j) - { - switch (j.type()) - { - case value_t::object: - { - write_bson_object(*j.m_value.object); - break; - } - - default: - { - JSON_THROW(type_error::create(317, "to serialize to BSON, top-level type must be object, but is " + std::string(j.type_name()))); - } - } - } - - /*! - @param[in] j JSON value to serialize - */ - void write_cbor(const BasicJsonType& j) - { - switch (j.type()) - { - case value_t::null: - { - oa->write_character(to_char_type(0xF6)); - break; - } - - case value_t::boolean: - { - oa->write_character(j.m_value.boolean - ? to_char_type(0xF5) - : to_char_type(0xF4)); - break; - } - - case value_t::number_integer: - { - if (j.m_value.number_integer >= 0) - { - // CBOR does not differentiate between positive signed - // integers and unsigned integers. Therefore, we used the - // code from the value_t::number_unsigned case here. - if (j.m_value.number_integer <= 0x17) - { - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x18)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x19)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x1A)); - write_number(static_cast(j.m_value.number_integer)); - } - else - { - oa->write_character(to_char_type(0x1B)); - write_number(static_cast(j.m_value.number_integer)); - } - } - else - { - // The conversions below encode the sign in the first - // byte, and the value is converted to a positive number. - const auto positive_number = -1 - j.m_value.number_integer; - if (j.m_value.number_integer >= -24) - { - write_number(static_cast(0x20 + positive_number)); - } - else if (positive_number <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x38)); - write_number(static_cast(positive_number)); - } - else if (positive_number <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x39)); - write_number(static_cast(positive_number)); - } - else if (positive_number <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x3A)); - write_number(static_cast(positive_number)); - } - else - { - oa->write_character(to_char_type(0x3B)); - write_number(static_cast(positive_number)); - } - } - break; - } - - case value_t::number_unsigned: - { - if (j.m_value.number_unsigned <= 0x17) - { - write_number(static_cast(j.m_value.number_unsigned)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x18)); - write_number(static_cast(j.m_value.number_unsigned)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x19)); - write_number(static_cast(j.m_value.number_unsigned)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x1A)); - write_number(static_cast(j.m_value.number_unsigned)); - } - else - { - oa->write_character(to_char_type(0x1B)); - write_number(static_cast(j.m_value.number_unsigned)); - } - break; - } - - case value_t::number_float: - { - if (std::isnan(j.m_value.number_float)) - { - // NaN is 0xf97e00 in CBOR - oa->write_character(to_char_type(0xF9)); - oa->write_character(to_char_type(0x7E)); - oa->write_character(to_char_type(0x00)); - } - else if (std::isinf(j.m_value.number_float)) - { - // Infinity is 0xf97c00, -Infinity is 0xf9fc00 - oa->write_character(to_char_type(0xf9)); - oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC)); - oa->write_character(to_char_type(0x00)); - } - else - { - write_compact_float(j.m_value.number_float, detail::input_format_t::cbor); - } - break; - } - - case value_t::string: - { - // step 1: write control byte and the string length - const auto N = j.m_value.string->size(); - if (N <= 0x17) - { - write_number(static_cast(0x60 + N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x78)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x79)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x7A)); - write_number(static_cast(N)); - } - // LCOV_EXCL_START - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x7B)); - write_number(static_cast(N)); - } - // LCOV_EXCL_STOP - - // step 2: write the string - oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.m_value.string->size()); - break; - } - - case value_t::array: - { - // step 1: write control byte and the array size - const auto N = j.m_value.array->size(); - if (N <= 0x17) - { - write_number(static_cast(0x80 + N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x98)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x99)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x9A)); - write_number(static_cast(N)); - } - // LCOV_EXCL_START - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x9B)); - write_number(static_cast(N)); - } - // LCOV_EXCL_STOP - - // step 2: write each element - for (const auto& el : *j.m_value.array) - { - write_cbor(el); - } - break; - } - - case value_t::binary: - { - if (j.m_value.binary->has_subtype()) - { - write_number(static_cast(0xd8)); - write_number(j.m_value.binary->subtype()); - } - - // step 1: write control byte and the binary array size - const auto N = j.m_value.binary->size(); - if (N <= 0x17) - { - write_number(static_cast(0x40 + N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x58)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x59)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x5A)); - write_number(static_cast(N)); - } - // LCOV_EXCL_START - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0x5B)); - write_number(static_cast(N)); - } - // LCOV_EXCL_STOP - - // step 2: write each element - oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), - N); - - break; - } - - case value_t::object: - { - // step 1: write control byte and the object size - const auto N = j.m_value.object->size(); - if (N <= 0x17) - { - write_number(static_cast(0xA0 + N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0xB8)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0xB9)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0xBA)); - write_number(static_cast(N)); - } - // LCOV_EXCL_START - else if (N <= (std::numeric_limits::max)()) - { - oa->write_character(to_char_type(0xBB)); - write_number(static_cast(N)); - } - // LCOV_EXCL_STOP - - // step 2: write each element - for (const auto& el : *j.m_value.object) - { - write_cbor(el.first); - write_cbor(el.second); - } - break; - } - - default: - break; - } - } - - /*! - @param[in] j JSON value to serialize - */ - void write_msgpack(const BasicJsonType& j) - { - switch (j.type()) - { - case value_t::null: // nil - { - oa->write_character(to_char_type(0xC0)); - break; - } - - case value_t::boolean: // true and false - { - oa->write_character(j.m_value.boolean - ? to_char_type(0xC3) - : to_char_type(0xC2)); - break; - } - - case value_t::number_integer: - { - if (j.m_value.number_integer >= 0) - { - // MessagePack does not differentiate between positive - // signed integers and unsigned integers. Therefore, we used - // the code from the value_t::number_unsigned case here. - if (j.m_value.number_unsigned < 128) - { - // positive fixnum - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 8 - oa->write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 16 - oa->write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 32 - oa->write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 64 - oa->write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_value.number_integer)); - } - } - else - { - if (j.m_value.number_integer >= -32) - { - // negative fixnum - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 8 - oa->write_character(to_char_type(0xD0)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 16 - oa->write_character(to_char_type(0xD1)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 32 - oa->write_character(to_char_type(0xD2)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_integer >= (std::numeric_limits::min)() && - j.m_value.number_integer <= (std::numeric_limits::max)()) - { - // int 64 - oa->write_character(to_char_type(0xD3)); - write_number(static_cast(j.m_value.number_integer)); - } - } - break; - } - - case value_t::number_unsigned: - { - if (j.m_value.number_unsigned < 128) - { - // positive fixnum - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 8 - oa->write_character(to_char_type(0xCC)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 16 - oa->write_character(to_char_type(0xCD)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 32 - oa->write_character(to_char_type(0xCE)); - write_number(static_cast(j.m_value.number_integer)); - } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) - { - // uint 64 - oa->write_character(to_char_type(0xCF)); - write_number(static_cast(j.m_value.number_integer)); - } - break; - } - - case value_t::number_float: - { - write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack); - break; - } - - case value_t::string: - { - // step 1: write control byte and the string length - const auto N = j.m_value.string->size(); - if (N <= 31) - { - // fixstr - write_number(static_cast(0xA0 | N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // str 8 - oa->write_character(to_char_type(0xD9)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // str 16 - oa->write_character(to_char_type(0xDA)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // str 32 - oa->write_character(to_char_type(0xDB)); - write_number(static_cast(N)); - } - - // step 2: write the string - oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.m_value.string->size()); - break; - } - - case value_t::array: - { - // step 1: write control byte and the array size - const auto N = j.m_value.array->size(); - if (N <= 15) - { - // fixarray - write_number(static_cast(0x90 | N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // array 16 - oa->write_character(to_char_type(0xDC)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // array 32 - oa->write_character(to_char_type(0xDD)); - write_number(static_cast(N)); - } - - // step 2: write each element - for (const auto& el : *j.m_value.array) - { - write_msgpack(el); - } - break; - } - - case value_t::binary: - { - // step 0: determine if the binary type has a set subtype to - // determine whether or not to use the ext or fixext types - const bool use_ext = j.m_value.binary->has_subtype(); - - // step 1: write control byte and the byte string length - const auto N = j.m_value.binary->size(); - if (N <= (std::numeric_limits::max)()) - { - std::uint8_t output_type{}; - bool fixed = true; - if (use_ext) - { - switch (N) - { - case 1: - output_type = 0xD4; // fixext 1 - break; - case 2: - output_type = 0xD5; // fixext 2 - break; - case 4: - output_type = 0xD6; // fixext 4 - break; - case 8: - output_type = 0xD7; // fixext 8 - break; - case 16: - output_type = 0xD8; // fixext 16 - break; - default: - output_type = 0xC7; // ext 8 - fixed = false; - break; - } - - } - else - { - output_type = 0xC4; // bin 8 - fixed = false; - } - - oa->write_character(to_char_type(output_type)); - if (!fixed) - { - write_number(static_cast(N)); - } - } - else if (N <= (std::numeric_limits::max)()) - { - std::uint8_t output_type = use_ext - ? 0xC8 // ext 16 - : 0xC5; // bin 16 - - oa->write_character(to_char_type(output_type)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - std::uint8_t output_type = use_ext - ? 0xC9 // ext 32 - : 0xC6; // bin 32 - - oa->write_character(to_char_type(output_type)); - write_number(static_cast(N)); - } - - // step 1.5: if this is an ext type, write the subtype - if (use_ext) - { - write_number(static_cast(j.m_value.binary->subtype())); - } - - // step 2: write the byte string - oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), - N); - - break; - } - - case value_t::object: - { - // step 1: write control byte and the object size - const auto N = j.m_value.object->size(); - if (N <= 15) - { - // fixmap - write_number(static_cast(0x80 | (N & 0xF))); - } - else if (N <= (std::numeric_limits::max)()) - { - // map 16 - oa->write_character(to_char_type(0xDE)); - write_number(static_cast(N)); - } - else if (N <= (std::numeric_limits::max)()) - { - // map 32 - oa->write_character(to_char_type(0xDF)); - write_number(static_cast(N)); - } - - // step 2: write each element - for (const auto& el : *j.m_value.object) - { - write_msgpack(el.first); - write_msgpack(el.second); - } - break; - } - - default: - break; - } - } - - /*! - @param[in] j JSON value to serialize - @param[in] use_count whether to use '#' prefixes (optimized format) - @param[in] use_type whether to use '$' prefixes (optimized format) - @param[in] add_prefix whether prefixes need to be used for this value - */ - void write_ubjson(const BasicJsonType& j, const bool use_count, - const bool use_type, const bool add_prefix = true) - { - switch (j.type()) - { - case value_t::null: - { - if (add_prefix) - { - oa->write_character(to_char_type('Z')); - } - break; - } - - case value_t::boolean: - { - if (add_prefix) - { - oa->write_character(j.m_value.boolean - ? to_char_type('T') - : to_char_type('F')); - } - break; - } - - case value_t::number_integer: - { - write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix); - break; - } - - case value_t::number_unsigned: - { - write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix); - break; - } - - case value_t::number_float: - { - write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix); - break; - } - - case value_t::string: - { - if (add_prefix) - { - oa->write_character(to_char_type('S')); - } - write_number_with_ubjson_prefix(j.m_value.string->size(), true); - oa->write_characters( - reinterpret_cast(j.m_value.string->c_str()), - j.m_value.string->size()); - break; - } - - case value_t::array: - { - if (add_prefix) - { - oa->write_character(to_char_type('[')); - } - - bool prefix_required = true; - if (use_type && !j.m_value.array->empty()) - { - JSON_ASSERT(use_count); - const CharType first_prefix = ubjson_prefix(j.front()); - const bool same_prefix = std::all_of(j.begin() + 1, j.end(), - [this, first_prefix](const BasicJsonType & v) - { - return ubjson_prefix(v) == first_prefix; - }); - - if (same_prefix) - { - prefix_required = false; - oa->write_character(to_char_type('$')); - oa->write_character(first_prefix); - } - } - - if (use_count) - { - oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.array->size(), true); - } - - for (const auto& el : *j.m_value.array) - { - write_ubjson(el, use_count, use_type, prefix_required); - } - - if (!use_count) - { - oa->write_character(to_char_type(']')); - } - - break; - } - - case value_t::binary: - { - if (add_prefix) - { - oa->write_character(to_char_type('[')); - } - - if (use_type && !j.m_value.binary->empty()) - { - JSON_ASSERT(use_count); - oa->write_character(to_char_type('$')); - oa->write_character('U'); - } - - if (use_count) - { - oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.binary->size(), true); - } - - if (use_type) - { - oa->write_characters( - reinterpret_cast(j.m_value.binary->data()), - j.m_value.binary->size()); - } - else - { - for (size_t i = 0; i < j.m_value.binary->size(); ++i) - { - oa->write_character(to_char_type('U')); - oa->write_character(j.m_value.binary->data()[i]); - } - } - - if (!use_count) - { - oa->write_character(to_char_type(']')); - } - - break; - } - - case value_t::object: - { - if (add_prefix) - { - oa->write_character(to_char_type('{')); - } - - bool prefix_required = true; - if (use_type && !j.m_value.object->empty()) - { - JSON_ASSERT(use_count); - const CharType first_prefix = ubjson_prefix(j.front()); - const bool same_prefix = std::all_of(j.begin(), j.end(), - [this, first_prefix](const BasicJsonType & v) - { - return ubjson_prefix(v) == first_prefix; - }); - - if (same_prefix) - { - prefix_required = false; - oa->write_character(to_char_type('$')); - oa->write_character(first_prefix); - } - } - - if (use_count) - { - oa->write_character(to_char_type('#')); - write_number_with_ubjson_prefix(j.m_value.object->size(), true); - } - - for (const auto& el : *j.m_value.object) - { - write_number_with_ubjson_prefix(el.first.size(), true); - oa->write_characters( - reinterpret_cast(el.first.c_str()), - el.first.size()); - write_ubjson(el.second, use_count, use_type, prefix_required); - } - - if (!use_count) - { - oa->write_character(to_char_type('}')); - } - - break; - } - - default: - break; - } - } - - private: - ////////// - // BSON // - ////////// - - /*! - @return The size of a BSON document entry header, including the id marker - and the entry name size (and its null-terminator). - */ - static std::size_t calc_bson_entry_header_size(const string_t& name) - { - const auto it = name.find(static_cast(0)); - if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos)) - { - JSON_THROW(out_of_range::create(409, - "BSON key cannot contain code point U+0000 (at byte " + std::to_string(it) + ")")); - } - - return /*id*/ 1ul + name.size() + /*zero-terminator*/1u; - } - - /*! - @brief Writes the given @a element_type and @a name to the output adapter - */ - void write_bson_entry_header(const string_t& name, - const std::uint8_t element_type) - { - oa->write_character(to_char_type(element_type)); // boolean - oa->write_characters( - reinterpret_cast(name.c_str()), - name.size() + 1u); - } - - /*! - @brief Writes a BSON element with key @a name and boolean value @a value - */ - void write_bson_boolean(const string_t& name, - const bool value) - { - write_bson_entry_header(name, 0x08); - oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00)); - } - - /*! - @brief Writes a BSON element with key @a name and double value @a value - */ - void write_bson_double(const string_t& name, - const double value) - { - write_bson_entry_header(name, 0x01); - write_number(value); - } - - /*! - @return The size of the BSON-encoded string in @a value - */ - static std::size_t calc_bson_string_size(const string_t& value) - { - return sizeof(std::int32_t) + value.size() + 1ul; - } - - /*! - @brief Writes a BSON element with key @a name and string value @a value - */ - void write_bson_string(const string_t& name, - const string_t& value) - { - write_bson_entry_header(name, 0x02); - - write_number(static_cast(value.size() + 1ul)); - oa->write_characters( - reinterpret_cast(value.c_str()), - value.size() + 1); - } - - /*! - @brief Writes a BSON element with key @a name and null value - */ - void write_bson_null(const string_t& name) - { - write_bson_entry_header(name, 0x0A); - } - - /*! - @return The size of the BSON-encoded integer @a value - */ - static std::size_t calc_bson_integer_size(const std::int64_t value) - { - return (std::numeric_limits::min)() <= value && value <= (std::numeric_limits::max)() - ? sizeof(std::int32_t) - : sizeof(std::int64_t); - } - - /*! - @brief Writes a BSON element with key @a name and integer @a value - */ - void write_bson_integer(const string_t& name, - const std::int64_t value) - { - if ((std::numeric_limits::min)() <= value && value <= (std::numeric_limits::max)()) - { - write_bson_entry_header(name, 0x10); // int32 - write_number(static_cast(value)); - } - else - { - write_bson_entry_header(name, 0x12); // int64 - write_number(static_cast(value)); - } - } - - /*! - @return The size of the BSON-encoded unsigned integer in @a j - */ - static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept - { - return (value <= static_cast((std::numeric_limits::max)())) - ? sizeof(std::int32_t) - : sizeof(std::int64_t); - } - - /*! - @brief Writes a BSON element with key @a name and unsigned @a value - */ - void write_bson_unsigned(const string_t& name, - const std::uint64_t value) - { - if (value <= static_cast((std::numeric_limits::max)())) - { - write_bson_entry_header(name, 0x10 /* int32 */); - write_number(static_cast(value)); - } - else if (value <= static_cast((std::numeric_limits::max)())) - { - write_bson_entry_header(name, 0x12 /* int64 */); - write_number(static_cast(value)); - } - else - { - JSON_THROW(out_of_range::create(407, "integer number " + std::to_string(value) + " cannot be represented by BSON as it does not fit int64")); - } - } - - /*! - @brief Writes a BSON element with key @a name and object @a value - */ - void write_bson_object_entry(const string_t& name, - const typename BasicJsonType::object_t& value) - { - write_bson_entry_header(name, 0x03); // object - write_bson_object(value); - } - - /*! - @return The size of the BSON-encoded array @a value - */ - static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value) - { - std::size_t array_index = 0ul; - - const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), std::size_t(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el) - { - return result + calc_bson_element_size(std::to_string(array_index++), el); - }); - - return sizeof(std::int32_t) + embedded_document_size + 1ul; - } - - /*! - @return The size of the BSON-encoded binary array @a value - */ - static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value) - { - return sizeof(std::int32_t) + value.size() + 1ul; - } - - /*! - @brief Writes a BSON element with key @a name and array @a value - */ - void write_bson_array(const string_t& name, - const typename BasicJsonType::array_t& value) - { - write_bson_entry_header(name, 0x04); // array - write_number(static_cast(calc_bson_array_size(value))); - - std::size_t array_index = 0ul; - - for (const auto& el : value) - { - write_bson_element(std::to_string(array_index++), el); - } - - oa->write_character(to_char_type(0x00)); - } - - /*! - @brief Writes a BSON element with key @a name and binary value @a value - */ - void write_bson_binary(const string_t& name, - const binary_t& value) - { - write_bson_entry_header(name, 0x05); - - write_number(static_cast(value.size())); - write_number(value.has_subtype() ? value.subtype() : std::uint8_t(0x00)); - - oa->write_characters(reinterpret_cast(value.data()), value.size()); - } - - /*! - @brief Calculates the size necessary to serialize the JSON value @a j with its @a name - @return The calculated size for the BSON document entry for @a j with the given @a name. - */ - static std::size_t calc_bson_element_size(const string_t& name, - const BasicJsonType& j) - { - const auto header_size = calc_bson_entry_header_size(name); - switch (j.type()) - { - case value_t::object: - return header_size + calc_bson_object_size(*j.m_value.object); - - case value_t::array: - return header_size + calc_bson_array_size(*j.m_value.array); - - case value_t::binary: - return header_size + calc_bson_binary_size(*j.m_value.binary); - - case value_t::boolean: - return header_size + 1ul; - - case value_t::number_float: - return header_size + 8ul; - - case value_t::number_integer: - return header_size + calc_bson_integer_size(j.m_value.number_integer); - - case value_t::number_unsigned: - return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned); - - case value_t::string: - return header_size + calc_bson_string_size(*j.m_value.string); - - case value_t::null: - return header_size + 0ul; - - // LCOV_EXCL_START - default: - JSON_ASSERT(false); - return 0ul; - // LCOV_EXCL_STOP - } - } - - /*! - @brief Serializes the JSON value @a j to BSON and associates it with the - key @a name. - @param name The name to associate with the JSON entity @a j within the - current BSON document - @return The size of the BSON entry - */ - void write_bson_element(const string_t& name, - const BasicJsonType& j) - { - switch (j.type()) - { - case value_t::object: - return write_bson_object_entry(name, *j.m_value.object); - - case value_t::array: - return write_bson_array(name, *j.m_value.array); - - case value_t::binary: - return write_bson_binary(name, *j.m_value.binary); - - case value_t::boolean: - return write_bson_boolean(name, j.m_value.boolean); - - case value_t::number_float: - return write_bson_double(name, j.m_value.number_float); - - case value_t::number_integer: - return write_bson_integer(name, j.m_value.number_integer); - - case value_t::number_unsigned: - return write_bson_unsigned(name, j.m_value.number_unsigned); - - case value_t::string: - return write_bson_string(name, *j.m_value.string); - - case value_t::null: - return write_bson_null(name); - - // LCOV_EXCL_START - default: - JSON_ASSERT(false); - return; - // LCOV_EXCL_STOP - } - } - - /*! - @brief Calculates the size of the BSON serialization of the given - JSON-object @a j. - @param[in] j JSON value to serialize - @pre j.type() == value_t::object - */ - static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value) - { - std::size_t document_size = std::accumulate(value.begin(), value.end(), std::size_t(0), - [](size_t result, const typename BasicJsonType::object_t::value_type & el) - { - return result += calc_bson_element_size(el.first, el.second); - }); - - return sizeof(std::int32_t) + document_size + 1ul; - } - - /*! - @param[in] j JSON value to serialize - @pre j.type() == value_t::object - */ - void write_bson_object(const typename BasicJsonType::object_t& value) - { - write_number(static_cast(calc_bson_object_size(value))); - - for (const auto& el : value) - { - write_bson_element(el.first, el.second); - } - - oa->write_character(to_char_type(0x00)); - } - - ////////// - // CBOR // - ////////// - - static constexpr CharType get_cbor_float_prefix(float /*unused*/) - { - return to_char_type(0xFA); // Single-Precision Float - } - - static constexpr CharType get_cbor_float_prefix(double /*unused*/) - { - return to_char_type(0xFB); // Double-Precision Float - } - - ///////////// - // MsgPack // - ///////////// - - static constexpr CharType get_msgpack_float_prefix(float /*unused*/) - { - return to_char_type(0xCA); // float 32 - } - - static constexpr CharType get_msgpack_float_prefix(double /*unused*/) - { - return to_char_type(0xCB); // float 64 - } - - //////////// - // UBJSON // - //////////// - - // UBJSON: write number (floating point) - template::value, int>::type = 0> - void write_number_with_ubjson_prefix(const NumberType n, - const bool add_prefix) - { - if (add_prefix) - { - oa->write_character(get_ubjson_float_prefix(n)); - } - write_number(n); - } - - // UBJSON: write number (unsigned integer) - template::value, int>::type = 0> - void write_number_with_ubjson_prefix(const NumberType n, - const bool add_prefix) - { - if (n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('i')); // int8 - } - write_number(static_cast(n)); - } - else if (n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('U')); // uint8 - } - write_number(static_cast(n)); - } - else if (n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('I')); // int16 - } - write_number(static_cast(n)); - } - else if (n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('l')); // int32 - } - write_number(static_cast(n)); - } - else if (n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('L')); // int64 - } - write_number(static_cast(n)); - } - else - { - if (add_prefix) - { - oa->write_character(to_char_type('H')); // high-precision number - } - - const auto number = BasicJsonType(n).dump(); - write_number_with_ubjson_prefix(number.size(), true); - for (std::size_t i = 0; i < number.size(); ++i) - { - oa->write_character(to_char_type(static_cast(number[i]))); - } - } - } - - // UBJSON: write number (signed integer) - template < typename NumberType, typename std::enable_if < - std::is_signed::value&& - !std::is_floating_point::value, int >::type = 0 > - void write_number_with_ubjson_prefix(const NumberType n, - const bool add_prefix) - { - if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('i')); // int8 - } - write_number(static_cast(n)); - } - else if (static_cast((std::numeric_limits::min)()) <= n && n <= static_cast((std::numeric_limits::max)())) - { - if (add_prefix) - { - oa->write_character(to_char_type('U')); // uint8 - } - write_number(static_cast(n)); - } - else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('I')); // int16 - } - write_number(static_cast(n)); - } - else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('l')); // int32 - } - write_number(static_cast(n)); - } - else if ((std::numeric_limits::min)() <= n && n <= (std::numeric_limits::max)()) - { - if (add_prefix) - { - oa->write_character(to_char_type('L')); // int64 - } - write_number(static_cast(n)); - } - // LCOV_EXCL_START - else - { - if (add_prefix) - { - oa->write_character(to_char_type('H')); // high-precision number - } - - const auto number = BasicJsonType(n).dump(); - write_number_with_ubjson_prefix(number.size(), true); - for (std::size_t i = 0; i < number.size(); ++i) - { - oa->write_character(to_char_type(static_cast(number[i]))); - } - } - // LCOV_EXCL_STOP - } - - /*! - @brief determine the type prefix of container values - */ - CharType ubjson_prefix(const BasicJsonType& j) const noexcept - { - switch (j.type()) - { - case value_t::null: - return 'Z'; - - case value_t::boolean: - return j.m_value.boolean ? 'T' : 'F'; - - case value_t::number_integer: - { - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'i'; - } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'U'; - } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'I'; - } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'l'; - } - if ((std::numeric_limits::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits::max)()) - { - return 'L'; - } - // anything else is treated as high-precision number - return 'H'; // LCOV_EXCL_LINE - } - - case value_t::number_unsigned: - { - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'i'; - } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'U'; - } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'I'; - } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'l'; - } - if (j.m_value.number_unsigned <= static_cast((std::numeric_limits::max)())) - { - return 'L'; - } - // anything else is treated as high-precision number - return 'H'; // LCOV_EXCL_LINE - } - - case value_t::number_float: - return get_ubjson_float_prefix(j.m_value.number_float); - - case value_t::string: - return 'S'; - - case value_t::array: // fallthrough - case value_t::binary: - return '['; - - case value_t::object: - return '{'; - - default: // discarded values - return 'N'; - } - } - - static constexpr CharType get_ubjson_float_prefix(float /*unused*/) - { - return 'd'; // float 32 - } - - static constexpr CharType get_ubjson_float_prefix(double /*unused*/) - { - return 'D'; // float 64 - } - - /////////////////////// - // Utility functions // - /////////////////////// - - /* - @brief write a number to output input - @param[in] n number of type @a NumberType - @tparam NumberType the type of the number - @tparam OutputIsLittleEndian Set to true if output data is - required to be little endian - - @note This function needs to respect the system's endianess, because bytes - in CBOR, MessagePack, and UBJSON are stored in network order (big - endian) and therefore need reordering on little endian systems. - */ - template - void write_number(const NumberType n) - { - // step 1: write number to array of length NumberType - std::array vec; - std::memcpy(vec.data(), &n, sizeof(NumberType)); - - // step 2: write array to output (with possible reordering) - if (is_little_endian != OutputIsLittleEndian) - { - // reverse byte order prior to conversion if necessary - std::reverse(vec.begin(), vec.end()); - } - - oa->write_characters(vec.data(), sizeof(NumberType)); - } - - void write_compact_float(const number_float_t n, detail::input_format_t format) - { - if (static_cast(n) >= static_cast(std::numeric_limits::lowest()) && - static_cast(n) <= static_cast((std::numeric_limits::max)()) && - static_cast(static_cast(n)) == static_cast(n)) - { - oa->write_character(format == detail::input_format_t::cbor - ? get_cbor_float_prefix(static_cast(n)) - : get_msgpack_float_prefix(static_cast(n))); - write_number(static_cast(n)); - } - else - { - oa->write_character(format == detail::input_format_t::cbor - ? get_cbor_float_prefix(n) - : get_msgpack_float_prefix(n)); - write_number(n); - } - } - - public: - // The following to_char_type functions are implement the conversion - // between uint8_t and CharType. In case CharType is not unsigned, - // such a conversion is required to allow values greater than 128. - // See for a discussion. - template < typename C = CharType, - enable_if_t < std::is_signed::value && std::is_signed::value > * = nullptr > - static constexpr CharType to_char_type(std::uint8_t x) noexcept - { - return *reinterpret_cast(&x); - } - - template < typename C = CharType, - enable_if_t < std::is_signed::value && std::is_unsigned::value > * = nullptr > - static CharType to_char_type(std::uint8_t x) noexcept - { - static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t"); - static_assert(std::is_trivial::value, "CharType must be trivial"); - CharType result; - std::memcpy(&result, &x, sizeof(x)); - return result; - } - - template::value>* = nullptr> - static constexpr CharType to_char_type(std::uint8_t x) noexcept - { - return x; - } - - template < typename InputCharType, typename C = CharType, - enable_if_t < - std::is_signed::value && - std::is_signed::value && - std::is_same::type>::value - > * = nullptr > - static constexpr CharType to_char_type(InputCharType x) noexcept - { - return x; - } - - private: - /// whether we can assume little endianess - const bool is_little_endian = little_endianess(); - - /// the output - output_adapter_t oa = nullptr; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - - -#include // reverse, remove, fill, find, none_of -#include // array -#include // localeconv, lconv -#include // labs, isfinite, isnan, signbit -#include // size_t, ptrdiff_t -#include // uint8_t -#include // snprintf -#include // numeric_limits -#include // string, char_traits -#include // is_same -#include // move - -// #include - - -#include // array -#include // signbit, isfinite -#include // intN_t, uintN_t -#include // memcpy, memmove -#include // numeric_limits -#include // conditional - -// #include - - -namespace nlohmann -{ -namespace detail -{ - -/*! -@brief implements the Grisu2 algorithm for binary to decimal floating-point -conversion. - -This implementation is a slightly modified version of the reference -implementation which may be obtained from -http://florian.loitsch.com/publications (bench.tar.gz). - -The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch. - -For a detailed description of the algorithm see: - -[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with - Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming - Language Design and Implementation, PLDI 2010 -[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately", - Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language - Design and Implementation, PLDI 1996 -*/ -namespace dtoa_impl -{ - -template -Target reinterpret_bits(const Source source) -{ - static_assert(sizeof(Target) == sizeof(Source), "size mismatch"); - - Target target; - std::memcpy(&target, &source, sizeof(Source)); - return target; -} - -struct diyfp // f * 2^e -{ - static constexpr int kPrecision = 64; // = q - - std::uint64_t f = 0; - int e = 0; - - constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {} - - /*! - @brief returns x - y - @pre x.e == y.e and x.f >= y.f - */ - static diyfp sub(const diyfp& x, const diyfp& y) noexcept - { - JSON_ASSERT(x.e == y.e); - JSON_ASSERT(x.f >= y.f); - - return {x.f - y.f, x.e}; - } - - /*! - @brief returns x * y - @note The result is rounded. (Only the upper q bits are returned.) - */ - static diyfp mul(const diyfp& x, const diyfp& y) noexcept - { - static_assert(kPrecision == 64, "internal error"); - - // Computes: - // f = round((x.f * y.f) / 2^q) - // e = x.e + y.e + q - - // Emulate the 64-bit * 64-bit multiplication: - // - // p = u * v - // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi) - // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi ) - // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 ) - // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 ) - // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3) - // = (p0_lo ) + 2^32 (Q ) + 2^64 (H ) - // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H ) - // - // (Since Q might be larger than 2^32 - 1) - // - // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H) - // - // (Q_hi + H does not overflow a 64-bit int) - // - // = p_lo + 2^64 p_hi - - const std::uint64_t u_lo = x.f & 0xFFFFFFFFu; - const std::uint64_t u_hi = x.f >> 32u; - const std::uint64_t v_lo = y.f & 0xFFFFFFFFu; - const std::uint64_t v_hi = y.f >> 32u; - - const std::uint64_t p0 = u_lo * v_lo; - const std::uint64_t p1 = u_lo * v_hi; - const std::uint64_t p2 = u_hi * v_lo; - const std::uint64_t p3 = u_hi * v_hi; - - const std::uint64_t p0_hi = p0 >> 32u; - const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu; - const std::uint64_t p1_hi = p1 >> 32u; - const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu; - const std::uint64_t p2_hi = p2 >> 32u; - - std::uint64_t Q = p0_hi + p1_lo + p2_lo; - - // The full product might now be computed as - // - // p_hi = p3 + p2_hi + p1_hi + (Q >> 32) - // p_lo = p0_lo + (Q << 32) - // - // But in this particular case here, the full p_lo is not required. - // Effectively we only need to add the highest bit in p_lo to p_hi (and - // Q_hi + 1 does not overflow). - - Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up - - const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u); - - return {h, x.e + y.e + 64}; - } - - /*! - @brief normalize x such that the significand is >= 2^(q-1) - @pre x.f != 0 - */ - static diyfp normalize(diyfp x) noexcept - { - JSON_ASSERT(x.f != 0); - - while ((x.f >> 63u) == 0) - { - x.f <<= 1u; - x.e--; - } - - return x; - } - - /*! - @brief normalize x such that the result has the exponent E - @pre e >= x.e and the upper e - x.e bits of x.f must be zero. - */ - static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept - { - const int delta = x.e - target_exponent; - - JSON_ASSERT(delta >= 0); - JSON_ASSERT(((x.f << delta) >> delta) == x.f); - - return {x.f << delta, target_exponent}; - } -}; - -struct boundaries -{ - diyfp w; - diyfp minus; - diyfp plus; -}; - -/*! -Compute the (normalized) diyfp representing the input number 'value' and its -boundaries. - -@pre value must be finite and positive -*/ -template -boundaries compute_boundaries(FloatType value) -{ - JSON_ASSERT(std::isfinite(value)); - JSON_ASSERT(value > 0); - - // Convert the IEEE representation into a diyfp. - // - // If v is denormal: - // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1)) - // If v is normalized: - // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1)) - - static_assert(std::numeric_limits::is_iec559, - "internal error: dtoa_short requires an IEEE-754 floating-point implementation"); - - constexpr int kPrecision = std::numeric_limits::digits; // = p (includes the hidden bit) - constexpr int kBias = std::numeric_limits::max_exponent - 1 + (kPrecision - 1); - constexpr int kMinExp = 1 - kBias; - constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1) - - using bits_type = typename std::conditional::type; - - const std::uint64_t bits = reinterpret_bits(value); - const std::uint64_t E = bits >> (kPrecision - 1); - const std::uint64_t F = bits & (kHiddenBit - 1); - - const bool is_denormal = E == 0; - const diyfp v = is_denormal - ? diyfp(F, kMinExp) - : diyfp(F + kHiddenBit, static_cast(E) - kBias); - - // Compute the boundaries m- and m+ of the floating-point value - // v = f * 2^e. - // - // Determine v- and v+, the floating-point predecessor and successor if v, - // respectively. - // - // v- = v - 2^e if f != 2^(p-1) or e == e_min (A) - // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B) - // - // v+ = v + 2^e - // - // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_ - // between m- and m+ round to v, regardless of how the input rounding - // algorithm breaks ties. - // - // ---+-------------+-------------+-------------+-------------+--- (A) - // v- m- v m+ v+ - // - // -----------------+------+------+-------------+-------------+--- (B) - // v- m- v m+ v+ - - const bool lower_boundary_is_closer = F == 0 && E > 1; - const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1); - const diyfp m_minus = lower_boundary_is_closer - ? diyfp(4 * v.f - 1, v.e - 2) // (B) - : diyfp(2 * v.f - 1, v.e - 1); // (A) - - // Determine the normalized w+ = m+. - const diyfp w_plus = diyfp::normalize(m_plus); - - // Determine w- = m- such that e_(w-) = e_(w+). - const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e); - - return {diyfp::normalize(v), w_minus, w_plus}; -} - -// Given normalized diyfp w, Grisu needs to find a (normalized) cached -// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies -// within a certain range [alpha, gamma] (Definition 3.2 from [1]) -// -// alpha <= e = e_c + e_w + q <= gamma -// -// or -// -// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q -// <= f_c * f_w * 2^gamma -// -// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies -// -// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma -// -// or -// -// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma) -// -// The choice of (alpha,gamma) determines the size of the table and the form of -// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well -// in practice: -// -// The idea is to cut the number c * w = f * 2^e into two parts, which can be -// processed independently: An integral part p1, and a fractional part p2: -// -// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e -// = (f div 2^-e) + (f mod 2^-e) * 2^e -// = p1 + p2 * 2^e -// -// The conversion of p1 into decimal form requires a series of divisions and -// modulos by (a power of) 10. These operations are faster for 32-bit than for -// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be -// achieved by choosing -// -// -e >= 32 or e <= -32 := gamma -// -// In order to convert the fractional part -// -// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ... -// -// into decimal form, the fraction is repeatedly multiplied by 10 and the digits -// d[-i] are extracted in order: -// -// (10 * p2) div 2^-e = d[-1] -// (10 * p2) mod 2^-e = d[-2] / 10^1 + ... -// -// The multiplication by 10 must not overflow. It is sufficient to choose -// -// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64. -// -// Since p2 = f mod 2^-e < 2^-e, -// -// -e <= 60 or e >= -60 := alpha - -constexpr int kAlpha = -60; -constexpr int kGamma = -32; - -struct cached_power // c = f * 2^e ~= 10^k -{ - std::uint64_t f; - int e; - int k; -}; - -/*! -For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached -power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c -satisfies (Definition 3.2 from [1]) - - alpha <= e_c + e + q <= gamma. -*/ -inline cached_power get_cached_power_for_binary_exponent(int e) -{ - // Now - // - // alpha <= e_c + e + q <= gamma (1) - // ==> f_c * 2^alpha <= c * 2^e * 2^q - // - // and since the c's are normalized, 2^(q-1) <= f_c, - // - // ==> 2^(q - 1 + alpha) <= c * 2^(e + q) - // ==> 2^(alpha - e - 1) <= c - // - // If c were an exact power of ten, i.e. c = 10^k, one may determine k as - // - // k = ceil( log_10( 2^(alpha - e - 1) ) ) - // = ceil( (alpha - e - 1) * log_10(2) ) - // - // From the paper: - // "In theory the result of the procedure could be wrong since c is rounded, - // and the computation itself is approximated [...]. In practice, however, - // this simple function is sufficient." - // - // For IEEE double precision floating-point numbers converted into - // normalized diyfp's w = f * 2^e, with q = 64, - // - // e >= -1022 (min IEEE exponent) - // -52 (p - 1) - // -52 (p - 1, possibly normalize denormal IEEE numbers) - // -11 (normalize the diyfp) - // = -1137 - // - // and - // - // e <= +1023 (max IEEE exponent) - // -52 (p - 1) - // -11 (normalize the diyfp) - // = 960 - // - // This binary exponent range [-1137,960] results in a decimal exponent - // range [-307,324]. One does not need to store a cached power for each - // k in this range. For each such k it suffices to find a cached power - // such that the exponent of the product lies in [alpha,gamma]. - // This implies that the difference of the decimal exponents of adjacent - // table entries must be less than or equal to - // - // floor( (gamma - alpha) * log_10(2) ) = 8. - // - // (A smaller distance gamma-alpha would require a larger table.) - - // NB: - // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34. - - constexpr int kCachedPowersMinDecExp = -300; - constexpr int kCachedPowersDecStep = 8; - - static constexpr std::array kCachedPowers = - { - { - { 0xAB70FE17C79AC6CA, -1060, -300 }, - { 0xFF77B1FCBEBCDC4F, -1034, -292 }, - { 0xBE5691EF416BD60C, -1007, -284 }, - { 0x8DD01FAD907FFC3C, -980, -276 }, - { 0xD3515C2831559A83, -954, -268 }, - { 0x9D71AC8FADA6C9B5, -927, -260 }, - { 0xEA9C227723EE8BCB, -901, -252 }, - { 0xAECC49914078536D, -874, -244 }, - { 0x823C12795DB6CE57, -847, -236 }, - { 0xC21094364DFB5637, -821, -228 }, - { 0x9096EA6F3848984F, -794, -220 }, - { 0xD77485CB25823AC7, -768, -212 }, - { 0xA086CFCD97BF97F4, -741, -204 }, - { 0xEF340A98172AACE5, -715, -196 }, - { 0xB23867FB2A35B28E, -688, -188 }, - { 0x84C8D4DFD2C63F3B, -661, -180 }, - { 0xC5DD44271AD3CDBA, -635, -172 }, - { 0x936B9FCEBB25C996, -608, -164 }, - { 0xDBAC6C247D62A584, -582, -156 }, - { 0xA3AB66580D5FDAF6, -555, -148 }, - { 0xF3E2F893DEC3F126, -529, -140 }, - { 0xB5B5ADA8AAFF80B8, -502, -132 }, - { 0x87625F056C7C4A8B, -475, -124 }, - { 0xC9BCFF6034C13053, -449, -116 }, - { 0x964E858C91BA2655, -422, -108 }, - { 0xDFF9772470297EBD, -396, -100 }, - { 0xA6DFBD9FB8E5B88F, -369, -92 }, - { 0xF8A95FCF88747D94, -343, -84 }, - { 0xB94470938FA89BCF, -316, -76 }, - { 0x8A08F0F8BF0F156B, -289, -68 }, - { 0xCDB02555653131B6, -263, -60 }, - { 0x993FE2C6D07B7FAC, -236, -52 }, - { 0xE45C10C42A2B3B06, -210, -44 }, - { 0xAA242499697392D3, -183, -36 }, - { 0xFD87B5F28300CA0E, -157, -28 }, - { 0xBCE5086492111AEB, -130, -20 }, - { 0x8CBCCC096F5088CC, -103, -12 }, - { 0xD1B71758E219652C, -77, -4 }, - { 0x9C40000000000000, -50, 4 }, - { 0xE8D4A51000000000, -24, 12 }, - { 0xAD78EBC5AC620000, 3, 20 }, - { 0x813F3978F8940984, 30, 28 }, - { 0xC097CE7BC90715B3, 56, 36 }, - { 0x8F7E32CE7BEA5C70, 83, 44 }, - { 0xD5D238A4ABE98068, 109, 52 }, - { 0x9F4F2726179A2245, 136, 60 }, - { 0xED63A231D4C4FB27, 162, 68 }, - { 0xB0DE65388CC8ADA8, 189, 76 }, - { 0x83C7088E1AAB65DB, 216, 84 }, - { 0xC45D1DF942711D9A, 242, 92 }, - { 0x924D692CA61BE758, 269, 100 }, - { 0xDA01EE641A708DEA, 295, 108 }, - { 0xA26DA3999AEF774A, 322, 116 }, - { 0xF209787BB47D6B85, 348, 124 }, - { 0xB454E4A179DD1877, 375, 132 }, - { 0x865B86925B9BC5C2, 402, 140 }, - { 0xC83553C5C8965D3D, 428, 148 }, - { 0x952AB45CFA97A0B3, 455, 156 }, - { 0xDE469FBD99A05FE3, 481, 164 }, - { 0xA59BC234DB398C25, 508, 172 }, - { 0xF6C69A72A3989F5C, 534, 180 }, - { 0xB7DCBF5354E9BECE, 561, 188 }, - { 0x88FCF317F22241E2, 588, 196 }, - { 0xCC20CE9BD35C78A5, 614, 204 }, - { 0x98165AF37B2153DF, 641, 212 }, - { 0xE2A0B5DC971F303A, 667, 220 }, - { 0xA8D9D1535CE3B396, 694, 228 }, - { 0xFB9B7CD9A4A7443C, 720, 236 }, - { 0xBB764C4CA7A44410, 747, 244 }, - { 0x8BAB8EEFB6409C1A, 774, 252 }, - { 0xD01FEF10A657842C, 800, 260 }, - { 0x9B10A4E5E9913129, 827, 268 }, - { 0xE7109BFBA19C0C9D, 853, 276 }, - { 0xAC2820D9623BF429, 880, 284 }, - { 0x80444B5E7AA7CF85, 907, 292 }, - { 0xBF21E44003ACDD2D, 933, 300 }, - { 0x8E679C2F5E44FF8F, 960, 308 }, - { 0xD433179D9C8CB841, 986, 316 }, - { 0x9E19DB92B4E31BA9, 1013, 324 }, - } - }; - - // This computation gives exactly the same results for k as - // k = ceil((kAlpha - e - 1) * 0.30102999566398114) - // for |e| <= 1500, but doesn't require floating-point operations. - // NB: log_10(2) ~= 78913 / 2^18 - JSON_ASSERT(e >= -1500); - JSON_ASSERT(e <= 1500); - const int f = kAlpha - e - 1; - const int k = (f * 78913) / (1 << 18) + static_cast(f > 0); - - const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep; - JSON_ASSERT(index >= 0); - JSON_ASSERT(static_cast(index) < kCachedPowers.size()); - - const cached_power cached = kCachedPowers[static_cast(index)]; - JSON_ASSERT(kAlpha <= cached.e + e + 64); - JSON_ASSERT(kGamma >= cached.e + e + 64); - - return cached; -} - -/*! -For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k. -For n == 0, returns 1 and sets pow10 := 1. -*/ -inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10) -{ - // LCOV_EXCL_START - if (n >= 1000000000) - { - pow10 = 1000000000; - return 10; - } - // LCOV_EXCL_STOP - else if (n >= 100000000) - { - pow10 = 100000000; - return 9; - } - else if (n >= 10000000) - { - pow10 = 10000000; - return 8; - } - else if (n >= 1000000) - { - pow10 = 1000000; - return 7; - } - else if (n >= 100000) - { - pow10 = 100000; - return 6; - } - else if (n >= 10000) - { - pow10 = 10000; - return 5; - } - else if (n >= 1000) - { - pow10 = 1000; - return 4; - } - else if (n >= 100) - { - pow10 = 100; - return 3; - } - else if (n >= 10) - { - pow10 = 10; - return 2; - } - else - { - pow10 = 1; - return 1; - } -} - -inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta, - std::uint64_t rest, std::uint64_t ten_k) -{ - JSON_ASSERT(len >= 1); - JSON_ASSERT(dist <= delta); - JSON_ASSERT(rest <= delta); - JSON_ASSERT(ten_k > 0); - - // <--------------------------- delta ----> - // <---- dist ---------> - // --------------[------------------+-------------------]-------------- - // M- w M+ - // - // ten_k - // <------> - // <---- rest ----> - // --------------[------------------+----+--------------]-------------- - // w V - // = buf * 10^k - // - // ten_k represents a unit-in-the-last-place in the decimal representation - // stored in buf. - // Decrement buf by ten_k while this takes buf closer to w. - - // The tests are written in this order to avoid overflow in unsigned - // integer arithmetic. - - while (rest < dist - && delta - rest >= ten_k - && (rest + ten_k < dist || dist - rest > rest + ten_k - dist)) - { - JSON_ASSERT(buf[len - 1] != '0'); - buf[len - 1]--; - rest += ten_k; - } -} - -/*! -Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+. -M- and M+ must be normalized and share the same exponent -60 <= e <= -32. -*/ -inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, - diyfp M_minus, diyfp w, diyfp M_plus) -{ - static_assert(kAlpha >= -60, "internal error"); - static_assert(kGamma <= -32, "internal error"); - - // Generates the digits (and the exponent) of a decimal floating-point - // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's - // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma. - // - // <--------------------------- delta ----> - // <---- dist ---------> - // --------------[------------------+-------------------]-------------- - // M- w M+ - // - // Grisu2 generates the digits of M+ from left to right and stops as soon as - // V is in [M-,M+]. - - JSON_ASSERT(M_plus.e >= kAlpha); - JSON_ASSERT(M_plus.e <= kGamma); - - std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e) - std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e) - - // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0): - // - // M+ = f * 2^e - // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e - // = ((p1 ) * 2^-e + (p2 )) * 2^e - // = p1 + p2 * 2^e - - const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e); - - auto p1 = static_cast(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.) - std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e - - // 1) - // - // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0] - - JSON_ASSERT(p1 > 0); - - std::uint32_t pow10; - const int k = find_largest_pow10(p1, pow10); - - // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1) - // - // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1)) - // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1)) - // - // M+ = p1 + p2 * 2^e - // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e - // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e - // = d[k-1] * 10^(k-1) + ( rest) * 2^e - // - // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0) - // - // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0] - // - // but stop as soon as - // - // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e - - int n = k; - while (n > 0) - { - // Invariants: - // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k) - // pow10 = 10^(n-1) <= p1 < 10^n - // - const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1) - const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1) - // - // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e - // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e) - // - JSON_ASSERT(d <= 9); - buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d - // - // M+ = buffer * 10^(n-1) + (r + p2 * 2^e) - // - p1 = r; - n--; - // - // M+ = buffer * 10^n + (p1 + p2 * 2^e) - // pow10 = 10^n - // - - // Now check if enough digits have been generated. - // Compute - // - // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e - // - // Note: - // Since rest and delta share the same exponent e, it suffices to - // compare the significands. - const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2; - if (rest <= delta) - { - // V = buffer * 10^n, with M- <= V <= M+. - - decimal_exponent += n; - - // We may now just stop. But instead look if the buffer could be - // decremented to bring V closer to w. - // - // pow10 = 10^n is now 1 ulp in the decimal representation V. - // The rounding procedure works with diyfp's with an implicit - // exponent of e. - // - // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e - // - const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e; - grisu2_round(buffer, length, dist, delta, rest, ten_n); - - return; - } - - pow10 /= 10; - // - // pow10 = 10^(n-1) <= p1 < 10^n - // Invariants restored. - } - - // 2) - // - // The digits of the integral part have been generated: - // - // M+ = d[k-1]...d[1]d[0] + p2 * 2^e - // = buffer + p2 * 2^e - // - // Now generate the digits of the fractional part p2 * 2^e. - // - // Note: - // No decimal point is generated: the exponent is adjusted instead. - // - // p2 actually represents the fraction - // - // p2 * 2^e - // = p2 / 2^-e - // = d[-1] / 10^1 + d[-2] / 10^2 + ... - // - // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...) - // - // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m - // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...) - // - // using - // - // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e) - // = ( d) * 2^-e + ( r) - // - // or - // 10^m * p2 * 2^e = d + r * 2^e - // - // i.e. - // - // M+ = buffer + p2 * 2^e - // = buffer + 10^-m * (d + r * 2^e) - // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e - // - // and stop as soon as 10^-m * r * 2^e <= delta * 2^e - - JSON_ASSERT(p2 > delta); - - int m = 0; - for (;;) - { - // Invariant: - // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e - // = buffer * 10^-m + 10^-m * (p2 ) * 2^e - // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e - // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e - // - JSON_ASSERT(p2 <= (std::numeric_limits::max)() / 10); - p2 *= 10; - const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e - const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e - // - // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e - // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e)) - // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e - // - JSON_ASSERT(d <= 9); - buffer[length++] = static_cast('0' + d); // buffer := buffer * 10 + d - // - // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e - // - p2 = r; - m++; - // - // M+ = buffer * 10^-m + 10^-m * p2 * 2^e - // Invariant restored. - - // Check if enough digits have been generated. - // - // 10^-m * p2 * 2^e <= delta * 2^e - // p2 * 2^e <= 10^m * delta * 2^e - // p2 <= 10^m * delta - delta *= 10; - dist *= 10; - if (p2 <= delta) - { - break; - } - } - - // V = buffer * 10^-m, with M- <= V <= M+. - - decimal_exponent -= m; - - // 1 ulp in the decimal representation is now 10^-m. - // Since delta and dist are now scaled by 10^m, we need to do the - // same with ulp in order to keep the units in sync. - // - // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e - // - const std::uint64_t ten_m = one.f; - grisu2_round(buffer, length, dist, delta, p2, ten_m); - - // By construction this algorithm generates the shortest possible decimal - // number (Loitsch, Theorem 6.2) which rounds back to w. - // For an input number of precision p, at least - // - // N = 1 + ceil(p * log_10(2)) - // - // decimal digits are sufficient to identify all binary floating-point - // numbers (Matula, "In-and-Out conversions"). - // This implies that the algorithm does not produce more than N decimal - // digits. - // - // N = 17 for p = 53 (IEEE double precision) - // N = 9 for p = 24 (IEEE single precision) -} - -/*! -v = buf * 10^decimal_exponent -len is the length of the buffer (number of decimal digits) -The buffer must be large enough, i.e. >= max_digits10. -*/ -JSON_HEDLEY_NON_NULL(1) -inline void grisu2(char* buf, int& len, int& decimal_exponent, - diyfp m_minus, diyfp v, diyfp m_plus) -{ - JSON_ASSERT(m_plus.e == m_minus.e); - JSON_ASSERT(m_plus.e == v.e); - - // --------(-----------------------+-----------------------)-------- (A) - // m- v m+ - // - // --------------------(-----------+-----------------------)-------- (B) - // m- v m+ - // - // First scale v (and m- and m+) such that the exponent is in the range - // [alpha, gamma]. - - const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e); - - const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k - - // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma] - const diyfp w = diyfp::mul(v, c_minus_k); - const diyfp w_minus = diyfp::mul(m_minus, c_minus_k); - const diyfp w_plus = diyfp::mul(m_plus, c_minus_k); - - // ----(---+---)---------------(---+---)---------------(---+---)---- - // w- w w+ - // = c*m- = c*v = c*m+ - // - // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and - // w+ are now off by a small amount. - // In fact: - // - // w - v * 10^k < 1 ulp - // - // To account for this inaccuracy, add resp. subtract 1 ulp. - // - // --------+---[---------------(---+---)---------------]---+-------- - // w- M- w M+ w+ - // - // Now any number in [M-, M+] (bounds included) will round to w when input, - // regardless of how the input rounding algorithm breaks ties. - // - // And digit_gen generates the shortest possible such number in [M-, M+]. - // Note that this does not mean that Grisu2 always generates the shortest - // possible number in the interval (m-, m+). - const diyfp M_minus(w_minus.f + 1, w_minus.e); - const diyfp M_plus (w_plus.f - 1, w_plus.e ); - - decimal_exponent = -cached.k; // = -(-k) = k - - grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus); -} - -/*! -v = buf * 10^decimal_exponent -len is the length of the buffer (number of decimal digits) -The buffer must be large enough, i.e. >= max_digits10. -*/ -template -JSON_HEDLEY_NON_NULL(1) -void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value) -{ - static_assert(diyfp::kPrecision >= std::numeric_limits::digits + 3, - "internal error: not enough precision"); - - JSON_ASSERT(std::isfinite(value)); - JSON_ASSERT(value > 0); - - // If the neighbors (and boundaries) of 'value' are always computed for double-precision - // numbers, all float's can be recovered using strtod (and strtof). However, the resulting - // decimal representations are not exactly "short". - // - // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars) - // says "value is converted to a string as if by std::sprintf in the default ("C") locale" - // and since sprintf promotes float's to double's, I think this is exactly what 'std::to_chars' - // does. - // On the other hand, the documentation for 'std::to_chars' requires that "parsing the - // representation using the corresponding std::from_chars function recovers value exactly". That - // indicates that single precision floating-point numbers should be recovered using - // 'std::strtof'. - // - // NB: If the neighbors are computed for single-precision numbers, there is a single float - // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision - // value is off by 1 ulp. -#if 0 - const boundaries w = compute_boundaries(static_cast(value)); -#else - const boundaries w = compute_boundaries(value); -#endif - - grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus); -} - -/*! -@brief appends a decimal representation of e to buf -@return a pointer to the element following the exponent. -@pre -1000 < e < 1000 -*/ -JSON_HEDLEY_NON_NULL(1) -JSON_HEDLEY_RETURNS_NON_NULL -inline char* append_exponent(char* buf, int e) -{ - JSON_ASSERT(e > -1000); - JSON_ASSERT(e < 1000); - - if (e < 0) - { - e = -e; - *buf++ = '-'; - } - else - { - *buf++ = '+'; - } - - auto k = static_cast(e); - if (k < 10) - { - // Always print at least two digits in the exponent. - // This is for compatibility with printf("%g"). - *buf++ = '0'; - *buf++ = static_cast('0' + k); - } - else if (k < 100) - { - *buf++ = static_cast('0' + k / 10); - k %= 10; - *buf++ = static_cast('0' + k); - } - else - { - *buf++ = static_cast('0' + k / 100); - k %= 100; - *buf++ = static_cast('0' + k / 10); - k %= 10; - *buf++ = static_cast('0' + k); - } - - return buf; -} - -/*! -@brief prettify v = buf * 10^decimal_exponent - -If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point -notation. Otherwise it will be printed in exponential notation. - -@pre min_exp < 0 -@pre max_exp > 0 -*/ -JSON_HEDLEY_NON_NULL(1) -JSON_HEDLEY_RETURNS_NON_NULL -inline char* format_buffer(char* buf, int len, int decimal_exponent, - int min_exp, int max_exp) -{ - JSON_ASSERT(min_exp < 0); - JSON_ASSERT(max_exp > 0); - - const int k = len; - const int n = len + decimal_exponent; - - // v = buf * 10^(n-k) - // k is the length of the buffer (number of decimal digits) - // n is the position of the decimal point relative to the start of the buffer. - - if (k <= n && n <= max_exp) - { - // digits[000] - // len <= max_exp + 2 - - std::memset(buf + k, '0', static_cast(n) - static_cast(k)); - // Make it look like a floating-point number (#362, #378) - buf[n + 0] = '.'; - buf[n + 1] = '0'; - return buf + (static_cast(n) + 2); - } - - if (0 < n && n <= max_exp) - { - // dig.its - // len <= max_digits10 + 1 - - JSON_ASSERT(k > n); - - std::memmove(buf + (static_cast(n) + 1), buf + n, static_cast(k) - static_cast(n)); - buf[n] = '.'; - return buf + (static_cast(k) + 1U); - } - - if (min_exp < n && n <= 0) - { - // 0.[000]digits - // len <= 2 + (-min_exp - 1) + max_digits10 - - std::memmove(buf + (2 + static_cast(-n)), buf, static_cast(k)); - buf[0] = '0'; - buf[1] = '.'; - std::memset(buf + 2, '0', static_cast(-n)); - return buf + (2U + static_cast(-n) + static_cast(k)); - } - - if (k == 1) - { - // dE+123 - // len <= 1 + 5 - - buf += 1; - } - else - { - // d.igitsE+123 - // len <= max_digits10 + 1 + 5 - - std::memmove(buf + 2, buf + 1, static_cast(k) - 1); - buf[1] = '.'; - buf += 1 + static_cast(k); - } - - *buf++ = 'e'; - return append_exponent(buf, n - 1); -} - -} // namespace dtoa_impl - -/*! -@brief generates a decimal representation of the floating-point number value in [first, last). - -The format of the resulting decimal representation is similar to printf's %g -format. Returns an iterator pointing past-the-end of the decimal representation. - -@note The input number must be finite, i.e. NaN's and Inf's are not supported. -@note The buffer must be large enough. -@note The result is NOT null-terminated. -*/ -template -JSON_HEDLEY_NON_NULL(1, 2) -JSON_HEDLEY_RETURNS_NON_NULL -char* to_chars(char* first, const char* last, FloatType value) -{ - static_cast(last); // maybe unused - fix warning - JSON_ASSERT(std::isfinite(value)); - - // Use signbit(value) instead of (value < 0) since signbit works for -0. - if (std::signbit(value)) - { - value = -value; - *first++ = '-'; - } - - if (value == 0) // +-0 - { - *first++ = '0'; - // Make it look like a floating-point number (#362, #378) - *first++ = '.'; - *first++ = '0'; - return first; - } - - JSON_ASSERT(last - first >= std::numeric_limits::max_digits10); - - // Compute v = buffer * 10^decimal_exponent. - // The decimal digits are stored in the buffer, which needs to be interpreted - // as an unsigned decimal integer. - // len is the length of the buffer, i.e. the number of decimal digits. - int len = 0; - int decimal_exponent = 0; - dtoa_impl::grisu2(first, len, decimal_exponent, value); - - JSON_ASSERT(len <= std::numeric_limits::max_digits10); - - // Format the buffer like printf("%.*g", prec, value) - constexpr int kMinExp = -4; - // Use digits10 here to increase compatibility with version 2. - constexpr int kMaxExp = std::numeric_limits::digits10; - - JSON_ASSERT(last - first >= kMaxExp + 2); - JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits::max_digits10); - JSON_ASSERT(last - first >= std::numeric_limits::max_digits10 + 6); - - return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp); -} - -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - -// #include - -// #include - -// #include - -// #include - - -namespace nlohmann -{ -namespace detail -{ -/////////////////// -// serialization // -/////////////////// - -/// how to treat decoding errors -enum class error_handler_t -{ - strict, ///< throw a type_error exception in case of invalid UTF-8 - replace, ///< replace invalid UTF-8 sequences with U+FFFD - ignore ///< ignore invalid UTF-8 sequences -}; - -template -class serializer -{ - using string_t = typename BasicJsonType::string_t; - using number_float_t = typename BasicJsonType::number_float_t; - using number_integer_t = typename BasicJsonType::number_integer_t; - using number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using binary_char_t = typename BasicJsonType::binary_t::value_type; - static constexpr std::uint8_t UTF8_ACCEPT = 0; - static constexpr std::uint8_t UTF8_REJECT = 1; - - public: - /*! - @param[in] s output stream to serialize to - @param[in] ichar indentation character to use - @param[in] error_handler_ how to react on decoding errors - */ - serializer(output_adapter_t s, const char ichar, - error_handler_t error_handler_ = error_handler_t::strict) - : o(std::move(s)) - , loc(std::localeconv()) - , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->thousands_sep))) - , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits::to_char_type(* (loc->decimal_point))) - , indent_char(ichar) - , indent_string(512, indent_char) - , error_handler(error_handler_) - {} - - // delete because of pointer members - serializer(const serializer&) = delete; - serializer& operator=(const serializer&) = delete; - serializer(serializer&&) = delete; - serializer& operator=(serializer&&) = delete; - ~serializer() = default; - - /*! - @brief internal implementation of the serialization function - - This function is called by the public member function dump and organizes - the serialization internally. The indentation level is propagated as - additional parameter. In case of arrays and objects, the function is - called recursively. - - - strings and object keys are escaped using `escape_string()` - - integer numbers are converted implicitly via `operator<<` - - floating-point numbers are converted to a string using `"%g"` format - - binary values are serialized as objects containing the subtype and the - byte array - - @param[in] val value to serialize - @param[in] pretty_print whether the output shall be pretty-printed - @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters - in the output are escaped with `\uXXXX` sequences, and the result consists - of ASCII characters only. - @param[in] indent_step the indent level - @param[in] current_indent the current indent level (only used internally) - */ - void dump(const BasicJsonType& val, - const bool pretty_print, - const bool ensure_ascii, - const unsigned int indent_step, - const unsigned int current_indent = 0) - { - switch (val.m_type) - { - case value_t::object: - { - if (val.m_value.object->empty()) - { - o->write_characters("{}", 2); - return; - } - - if (pretty_print) - { - o->write_characters("{\n", 2); - - // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; - if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) - { - indent_string.resize(indent_string.size() * 2, ' '); - } - - // first n-1 elements - auto i = val.m_value.object->cbegin(); - for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) - { - o->write_characters(indent_string.c_str(), new_indent); - o->write_character('\"'); - dump_escaped(i->first, ensure_ascii); - o->write_characters("\": ", 3); - dump(i->second, true, ensure_ascii, indent_step, new_indent); - o->write_characters(",\n", 2); - } - - // last element - JSON_ASSERT(i != val.m_value.object->cend()); - JSON_ASSERT(std::next(i) == val.m_value.object->cend()); - o->write_characters(indent_string.c_str(), new_indent); - o->write_character('\"'); - dump_escaped(i->first, ensure_ascii); - o->write_characters("\": ", 3); - dump(i->second, true, ensure_ascii, indent_step, new_indent); - - o->write_character('\n'); - o->write_characters(indent_string.c_str(), current_indent); - o->write_character('}'); - } - else - { - o->write_character('{'); - - // first n-1 elements - auto i = val.m_value.object->cbegin(); - for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i) - { - o->write_character('\"'); - dump_escaped(i->first, ensure_ascii); - o->write_characters("\":", 2); - dump(i->second, false, ensure_ascii, indent_step, current_indent); - o->write_character(','); - } - - // last element - JSON_ASSERT(i != val.m_value.object->cend()); - JSON_ASSERT(std::next(i) == val.m_value.object->cend()); - o->write_character('\"'); - dump_escaped(i->first, ensure_ascii); - o->write_characters("\":", 2); - dump(i->second, false, ensure_ascii, indent_step, current_indent); - - o->write_character('}'); - } - - return; - } - - case value_t::array: - { - if (val.m_value.array->empty()) - { - o->write_characters("[]", 2); - return; - } - - if (pretty_print) - { - o->write_characters("[\n", 2); - - // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; - if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) - { - indent_string.resize(indent_string.size() * 2, ' '); - } - - // first n-1 elements - for (auto i = val.m_value.array->cbegin(); - i != val.m_value.array->cend() - 1; ++i) - { - o->write_characters(indent_string.c_str(), new_indent); - dump(*i, true, ensure_ascii, indent_step, new_indent); - o->write_characters(",\n", 2); - } - - // last element - JSON_ASSERT(!val.m_value.array->empty()); - o->write_characters(indent_string.c_str(), new_indent); - dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent); - - o->write_character('\n'); - o->write_characters(indent_string.c_str(), current_indent); - o->write_character(']'); - } - else - { - o->write_character('['); - - // first n-1 elements - for (auto i = val.m_value.array->cbegin(); - i != val.m_value.array->cend() - 1; ++i) - { - dump(*i, false, ensure_ascii, indent_step, current_indent); - o->write_character(','); - } - - // last element - JSON_ASSERT(!val.m_value.array->empty()); - dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent); - - o->write_character(']'); - } - - return; - } - - case value_t::string: - { - o->write_character('\"'); - dump_escaped(*val.m_value.string, ensure_ascii); - o->write_character('\"'); - return; - } - - case value_t::binary: - { - if (pretty_print) - { - o->write_characters("{\n", 2); - - // variable to hold indentation for recursive calls - const auto new_indent = current_indent + indent_step; - if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent)) - { - indent_string.resize(indent_string.size() * 2, ' '); - } - - o->write_characters(indent_string.c_str(), new_indent); - - o->write_characters("\"bytes\": [", 10); - - if (!val.m_value.binary->empty()) - { - for (auto i = val.m_value.binary->cbegin(); - i != val.m_value.binary->cend() - 1; ++i) - { - dump_integer(*i); - o->write_characters(", ", 2); - } - dump_integer(val.m_value.binary->back()); - } - - o->write_characters("],\n", 3); - o->write_characters(indent_string.c_str(), new_indent); - - o->write_characters("\"subtype\": ", 11); - if (val.m_value.binary->has_subtype()) - { - dump_integer(val.m_value.binary->subtype()); - } - else - { - o->write_characters("null", 4); - } - o->write_character('\n'); - o->write_characters(indent_string.c_str(), current_indent); - o->write_character('}'); - } - else - { - o->write_characters("{\"bytes\":[", 10); - - if (!val.m_value.binary->empty()) - { - for (auto i = val.m_value.binary->cbegin(); - i != val.m_value.binary->cend() - 1; ++i) - { - dump_integer(*i); - o->write_character(','); - } - dump_integer(val.m_value.binary->back()); - } - - o->write_characters("],\"subtype\":", 12); - if (val.m_value.binary->has_subtype()) - { - dump_integer(val.m_value.binary->subtype()); - o->write_character('}'); - } - else - { - o->write_characters("null}", 5); - } - } - return; - } - - case value_t::boolean: - { - if (val.m_value.boolean) - { - o->write_characters("true", 4); - } - else - { - o->write_characters("false", 5); - } - return; - } - - case value_t::number_integer: - { - dump_integer(val.m_value.number_integer); - return; - } - - case value_t::number_unsigned: - { - dump_integer(val.m_value.number_unsigned); - return; - } - - case value_t::number_float: - { - dump_float(val.m_value.number_float); - return; - } - - case value_t::discarded: - { - o->write_characters("", 11); - return; - } - - case value_t::null: - { - o->write_characters("null", 4); - return; - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - } - - JSON_PRIVATE_UNLESS_TESTED: - /*! - @brief dump escaped string - - Escape a string by replacing certain special characters by a sequence of an - escape character (backslash) and another character and other control - characters by a sequence of "\u" followed by a four-digit hex - representation. The escaped string is written to output stream @a o. - - @param[in] s the string to escape - @param[in] ensure_ascii whether to escape non-ASCII characters with - \uXXXX sequences - - @complexity Linear in the length of string @a s. - */ - void dump_escaped(const string_t& s, const bool ensure_ascii) - { - std::uint32_t codepoint; - std::uint8_t state = UTF8_ACCEPT; - std::size_t bytes = 0; // number of bytes written to string_buffer - - // number of bytes written at the point of the last valid byte - std::size_t bytes_after_last_accept = 0; - std::size_t undumped_chars = 0; - - for (std::size_t i = 0; i < s.size(); ++i) - { - const auto byte = static_cast(s[i]); - - switch (decode(state, codepoint, byte)) - { - case UTF8_ACCEPT: // decode found a new code point - { - switch (codepoint) - { - case 0x08: // backspace - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'b'; - break; - } - - case 0x09: // horizontal tab - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 't'; - break; - } - - case 0x0A: // newline - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'n'; - break; - } - - case 0x0C: // formfeed - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'f'; - break; - } - - case 0x0D: // carriage return - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'r'; - break; - } - - case 0x22: // quotation mark - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = '\"'; - break; - } - - case 0x5C: // reverse solidus - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = '\\'; - break; - } - - default: - { - // escape control characters (0x00..0x1F) or, if - // ensure_ascii parameter is used, non-ASCII characters - if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F))) - { - if (codepoint <= 0xFFFF) - { - (std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x", - static_cast(codepoint)); - bytes += 6; - } - else - { - (std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x", - static_cast(0xD7C0u + (codepoint >> 10u)), - static_cast(0xDC00u + (codepoint & 0x3FFu))); - bytes += 12; - } - } - else - { - // copy byte to buffer (all previous bytes - // been copied have in default case above) - string_buffer[bytes++] = s[i]; - } - break; - } - } - - // write buffer and reset index; there must be 13 bytes - // left, as this is the maximal number of bytes to be - // written ("\uxxxx\uxxxx\0") for one code point - if (string_buffer.size() - bytes < 13) - { - o->write_characters(string_buffer.data(), bytes); - bytes = 0; - } - - // remember the byte position of this accept - bytes_after_last_accept = bytes; - undumped_chars = 0; - break; - } - - case UTF8_REJECT: // decode found invalid UTF-8 byte - { - switch (error_handler) - { - case error_handler_t::strict: - { - std::string sn(3, '\0'); - (std::snprintf)(&sn[0], sn.size(), "%.2X", byte); - JSON_THROW(type_error::create(316, "invalid UTF-8 byte at index " + std::to_string(i) + ": 0x" + sn)); - } - - case error_handler_t::ignore: - case error_handler_t::replace: - { - // in case we saw this character the first time, we - // would like to read it again, because the byte - // may be OK for itself, but just not OK for the - // previous sequence - if (undumped_chars > 0) - { - --i; - } - - // reset length buffer to the last accepted index; - // thus removing/ignoring the invalid characters - bytes = bytes_after_last_accept; - - if (error_handler == error_handler_t::replace) - { - // add a replacement character - if (ensure_ascii) - { - string_buffer[bytes++] = '\\'; - string_buffer[bytes++] = 'u'; - string_buffer[bytes++] = 'f'; - string_buffer[bytes++] = 'f'; - string_buffer[bytes++] = 'f'; - string_buffer[bytes++] = 'd'; - } - else - { - string_buffer[bytes++] = detail::binary_writer::to_char_type('\xEF'); - string_buffer[bytes++] = detail::binary_writer::to_char_type('\xBF'); - string_buffer[bytes++] = detail::binary_writer::to_char_type('\xBD'); - } - - // write buffer and reset index; there must be 13 bytes - // left, as this is the maximal number of bytes to be - // written ("\uxxxx\uxxxx\0") for one code point - if (string_buffer.size() - bytes < 13) - { - o->write_characters(string_buffer.data(), bytes); - bytes = 0; - } - - bytes_after_last_accept = bytes; - } - - undumped_chars = 0; - - // continue processing the string - state = UTF8_ACCEPT; - break; - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - break; - } - - default: // decode found yet incomplete multi-byte code point - { - if (!ensure_ascii) - { - // code point will not be escaped - copy byte to buffer - string_buffer[bytes++] = s[i]; - } - ++undumped_chars; - break; - } - } - } - - // we finished processing the string - if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT)) - { - // write buffer - if (bytes > 0) - { - o->write_characters(string_buffer.data(), bytes); - } - } - else - { - // we finish reading, but do not accept: string was incomplete - switch (error_handler) - { - case error_handler_t::strict: - { - std::string sn(3, '\0'); - (std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast(s.back())); - JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn)); - } - - case error_handler_t::ignore: - { - // write all accepted bytes - o->write_characters(string_buffer.data(), bytes_after_last_accept); - break; - } - - case error_handler_t::replace: - { - // write all accepted bytes - o->write_characters(string_buffer.data(), bytes_after_last_accept); - // add a replacement character - if (ensure_ascii) - { - o->write_characters("\\ufffd", 6); - } - else - { - o->write_characters("\xEF\xBF\xBD", 3); - } - break; - } - - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - } - } - - private: - /*! - @brief count digits - - Count the number of decimal (base 10) digits for an input unsigned integer. - - @param[in] x unsigned integer number to count its digits - @return number of decimal digits - */ - inline unsigned int count_digits(number_unsigned_t x) noexcept - { - unsigned int n_digits = 1; - for (;;) - { - if (x < 10) - { - return n_digits; - } - if (x < 100) - { - return n_digits + 1; - } - if (x < 1000) - { - return n_digits + 2; - } - if (x < 10000) - { - return n_digits + 3; - } - x = x / 10000u; - n_digits += 4; - } - } - - /*! - @brief dump an integer - - Dump a given integer to output stream @a o. Works internally with - @a number_buffer. - - @param[in] x integer number (signed or unsigned) to dump - @tparam NumberType either @a number_integer_t or @a number_unsigned_t - */ - template < typename NumberType, detail::enable_if_t < - std::is_same::value || - std::is_same::value || - std::is_same::value, - int > = 0 > - void dump_integer(NumberType x) - { - static constexpr std::array, 100> digits_to_99 - { - { - {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}}, - {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}}, - {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}}, - {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}}, - {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}}, - {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}}, - {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}}, - {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}}, - {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}}, - {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}}, - } - }; - - // special case for "0" - if (x == 0) - { - o->write_character('0'); - return; - } - - // use a pointer to fill the buffer - auto buffer_ptr = number_buffer.begin(); - - const bool is_negative = std::is_same::value && !(x >= 0); // see issue #755 - number_unsigned_t abs_value; - - unsigned int n_chars; - - if (is_negative) - { - *buffer_ptr = '-'; - abs_value = remove_sign(static_cast(x)); - - // account one more byte for the minus sign - n_chars = 1 + count_digits(abs_value); - } - else - { - abs_value = static_cast(x); - n_chars = count_digits(abs_value); - } - - // spare 1 byte for '\0' - JSON_ASSERT(n_chars < number_buffer.size() - 1); - - // jump to the end to generate the string from backward - // so we later avoid reversing the result - buffer_ptr += n_chars; - - // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu - // See: https://www.youtube.com/watch?v=o4-CwDo2zpg - while (abs_value >= 100) - { - const auto digits_index = static_cast((abs_value % 100)); - abs_value /= 100; - *(--buffer_ptr) = digits_to_99[digits_index][1]; - *(--buffer_ptr) = digits_to_99[digits_index][0]; - } - - if (abs_value >= 10) - { - const auto digits_index = static_cast(abs_value); - *(--buffer_ptr) = digits_to_99[digits_index][1]; - *(--buffer_ptr) = digits_to_99[digits_index][0]; - } - else - { - *(--buffer_ptr) = static_cast('0' + abs_value); - } - - o->write_characters(number_buffer.data(), n_chars); - } - - /*! - @brief dump a floating-point number - - Dump a given floating-point number to output stream @a o. Works internally - with @a number_buffer. - - @param[in] x floating-point number to dump - */ - void dump_float(number_float_t x) - { - // NaN / inf - if (!std::isfinite(x)) - { - o->write_characters("null", 4); - return; - } - - // If number_float_t is an IEEE-754 single or double precision number, - // use the Grisu2 algorithm to produce short numbers which are - // guaranteed to round-trip, using strtof and strtod, resp. - // - // NB: The test below works if == . - static constexpr bool is_ieee_single_or_double - = (std::numeric_limits::is_iec559 && std::numeric_limits::digits == 24 && std::numeric_limits::max_exponent == 128) || - (std::numeric_limits::is_iec559 && std::numeric_limits::digits == 53 && std::numeric_limits::max_exponent == 1024); - - dump_float(x, std::integral_constant()); - } - - void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/) - { - char* begin = number_buffer.data(); - char* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x); - - o->write_characters(begin, static_cast(end - begin)); - } - - void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/) - { - // get number of digits for a float -> text -> float round-trip - static constexpr auto d = std::numeric_limits::max_digits10; - - // the actual conversion - std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x); - - // negative value indicates an error - JSON_ASSERT(len > 0); - // check if buffer was large enough - JSON_ASSERT(static_cast(len) < number_buffer.size()); - - // erase thousands separator - if (thousands_sep != '\0') - { - const auto end = std::remove(number_buffer.begin(), - number_buffer.begin() + len, thousands_sep); - std::fill(end, number_buffer.end(), '\0'); - JSON_ASSERT((end - number_buffer.begin()) <= len); - len = (end - number_buffer.begin()); - } - - // convert decimal point to '.' - if (decimal_point != '\0' && decimal_point != '.') - { - const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point); - if (dec_pos != number_buffer.end()) - { - *dec_pos = '.'; - } - } - - o->write_characters(number_buffer.data(), static_cast(len)); - - // determine if need to append ".0" - const bool value_is_int_like = - std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, - [](char c) - { - return c == '.' || c == 'e'; - }); - - if (value_is_int_like) - { - o->write_characters(".0", 2); - } - } - - /*! - @brief check whether a string is UTF-8 encoded - - The function checks each byte of a string whether it is UTF-8 encoded. The - result of the check is stored in the @a state parameter. The function must - be called initially with state 0 (accept). State 1 means the string must - be rejected, because the current byte is not allowed. If the string is - completely processed, but the state is non-zero, the string ended - prematurely; that is, the last byte indicated more bytes should have - followed. - - @param[in,out] state the state of the decoding - @param[in,out] codep codepoint (valid only if resulting state is UTF8_ACCEPT) - @param[in] byte next byte to decode - @return new state - - @note The function has been edited: a std::array is used. - - @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann - @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ - */ - static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept - { - static const std::array utf8d = - { - { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF - 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF - 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF - 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF - 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2 - 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4 - 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6 - 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8 - } - }; - - const std::uint8_t type = utf8d[byte]; - - codep = (state != UTF8_ACCEPT) - ? (byte & 0x3fu) | (codep << 6u) - : (0xFFu >> type) & (byte); - - std::size_t index = 256u + static_cast(state) * 16u + static_cast(type); - JSON_ASSERT(index < 400); - state = utf8d[index]; - return state; - } - - /* - * Overload to make the compiler happy while it is instantiating - * dump_integer for number_unsigned_t. - * Must never be called. - */ - number_unsigned_t remove_sign(number_unsigned_t x) - { - JSON_ASSERT(false); // LCOV_EXCL_LINE - return x; // LCOV_EXCL_LINE - } - - /* - * Helper function for dump_integer - * - * This function takes a negative signed integer and returns its absolute - * value as unsigned integer. The plus/minus shuffling is necessary as we can - * not directly remove the sign of an arbitrary signed integer as the - * absolute values of INT_MIN and INT_MAX are usually not the same. See - * #1708 for details. - */ - inline number_unsigned_t remove_sign(number_integer_t x) noexcept - { - JSON_ASSERT(x < 0 && x < (std::numeric_limits::max)()); - return static_cast(-(x + 1)) + 1; - } - - private: - /// the output of the serializer - output_adapter_t o = nullptr; - - /// a (hopefully) large enough character buffer - std::array number_buffer{{}}; - - /// the locale - const std::lconv* loc = nullptr; - /// the locale's thousand separator character - const char thousands_sep = '\0'; - /// the locale's decimal point character - const char decimal_point = '\0'; - - /// string buffer - std::array string_buffer{{}}; - - /// the indentation character - const char indent_char; - /// the indentation string - string_t indent_string; - - /// error_handler how to react on decoding errors - const error_handler_t error_handler; -}; -} // namespace detail -} // namespace nlohmann - -// #include - -// #include - -// #include - - -#include // less -#include // allocator -#include // pair -#include // vector - -// #include - - -namespace nlohmann -{ - -/// ordered_map: a minimal map-like container that preserves insertion order -/// for use within nlohmann::basic_json -template , - class Allocator = std::allocator>> - struct ordered_map : std::vector, Allocator> -{ - using key_type = Key; - using mapped_type = T; - using Container = std::vector, Allocator>; - using typename Container::iterator; - using typename Container::const_iterator; - using typename Container::size_type; - using typename Container::value_type; - - // Explicit constructors instead of `using Container::Container` - // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4) - ordered_map(const Allocator& alloc = Allocator()) : Container{alloc} {} - template - ordered_map(It first, It last, const Allocator& alloc = Allocator()) - : Container{first, last, alloc} {} - ordered_map(std::initializer_list init, const Allocator& alloc = Allocator() ) - : Container{init, alloc} {} - - std::pair emplace(const key_type& key, T&& t) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return {it, false}; - } - } - Container::emplace_back(key, t); - return {--this->end(), true}; - } - - T& operator[](const Key& key) - { - return emplace(key, T{}).first->second; - } - - const T& operator[](const Key& key) const - { - return at(key); - } - - T& at(const Key& key) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return it->second; - } - } - - JSON_THROW(std::out_of_range("key not found")); - } - - const T& at(const Key& key) const - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return it->second; - } - } - - JSON_THROW(std::out_of_range("key not found")); - } - - size_type erase(const Key& key) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - // Since we cannot move const Keys, re-construct them in place - for (auto next = it; ++next != this->end(); ++it) - { - it->~value_type(); // Destroy but keep allocation - new (&*it) value_type{std::move(*next)}; - } - Container::pop_back(); - return 1; - } - } - return 0; - } - - iterator erase(iterator pos) - { - auto it = pos; - - // Since we cannot move const Keys, re-construct them in place - for (auto next = it; ++next != this->end(); ++it) - { - it->~value_type(); // Destroy but keep allocation - new (&*it) value_type{std::move(*next)}; - } - Container::pop_back(); - return pos; - } - - size_type count(const Key& key) const - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return 1; - } - } - return 0; - } - - iterator find(const Key& key) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return it; - } - } - return Container::end(); - } - - const_iterator find(const Key& key) const - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == key) - { - return it; - } - } - return Container::end(); - } - - std::pair insert( value_type&& value ) - { - return emplace(value.first, std::move(value.second)); - } - - std::pair insert( const value_type& value ) - { - for (auto it = this->begin(); it != this->end(); ++it) - { - if (it->first == value.first) - { - return {it, false}; - } - } - Container::push_back(value); - return {--this->end(), true}; - } -}; - -} // namespace nlohmann - - -/*! -@brief namespace for Niels Lohmann -@see https://github.com/nlohmann -@since version 1.0.0 -*/ -namespace nlohmann -{ - -/*! -@brief a class to store JSON values - -@tparam ObjectType type for JSON objects (`std::map` by default; will be used -in @ref object_t) -@tparam ArrayType type for JSON arrays (`std::vector` by default; will be used -in @ref array_t) -@tparam StringType type for JSON strings and object keys (`std::string` by -default; will be used in @ref string_t) -@tparam BooleanType type for JSON booleans (`bool` by default; will be used -in @ref boolean_t) -@tparam NumberIntegerType type for JSON integer numbers (`int64_t` by -default; will be used in @ref number_integer_t) -@tparam NumberUnsignedType type for JSON unsigned integer numbers (@c -`uint64_t` by default; will be used in @ref number_unsigned_t) -@tparam NumberFloatType type for JSON floating-point numbers (`double` by -default; will be used in @ref number_float_t) -@tparam BinaryType type for packed binary data for compatibility with binary -serialization formats (`std::vector` by default; will be used in -@ref binary_t) -@tparam AllocatorType type of the allocator to use (`std::allocator` by -default) -@tparam JSONSerializer the serializer to resolve internal calls to `to_json()` -and `from_json()` (@ref adl_serializer by default) - -@requirement The class satisfies the following concept requirements: -- Basic - - [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible): - JSON values can be default constructed. The result will be a JSON null - value. - - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible): - A JSON value can be constructed from an rvalue argument. - - [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible): - A JSON value can be copy-constructed from an lvalue expression. - - [MoveAssignable](https://en.cppreference.com/w/cpp/named_req/MoveAssignable): - A JSON value van be assigned from an rvalue argument. - - [CopyAssignable](https://en.cppreference.com/w/cpp/named_req/CopyAssignable): - A JSON value can be copy-assigned from an lvalue expression. - - [Destructible](https://en.cppreference.com/w/cpp/named_req/Destructible): - JSON values can be destructed. -- Layout - - [StandardLayoutType](https://en.cppreference.com/w/cpp/named_req/StandardLayoutType): - JSON values have - [standard layout](https://en.cppreference.com/w/cpp/language/data_members#Standard_layout): - All non-static data members are private and standard layout types, the - class has no virtual functions or (virtual) base classes. -- Library-wide - - [EqualityComparable](https://en.cppreference.com/w/cpp/named_req/EqualityComparable): - JSON values can be compared with `==`, see @ref - operator==(const_reference,const_reference). - - [LessThanComparable](https://en.cppreference.com/w/cpp/named_req/LessThanComparable): - JSON values can be compared with `<`, see @ref - operator<(const_reference,const_reference). - - [Swappable](https://en.cppreference.com/w/cpp/named_req/Swappable): - Any JSON lvalue or rvalue of can be swapped with any lvalue or rvalue of - other compatible types, using unqualified function call @ref swap(). - - [NullablePointer](https://en.cppreference.com/w/cpp/named_req/NullablePointer): - JSON values can be compared against `std::nullptr_t` objects which are used - to model the `null` value. -- Container - - [Container](https://en.cppreference.com/w/cpp/named_req/Container): - JSON values can be used like STL containers and provide iterator access. - - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer); - JSON values can be used like STL containers and provide reverse iterator - access. - -@invariant The member variables @a m_value and @a m_type have the following -relationship: -- If `m_type == value_t::object`, then `m_value.object != nullptr`. -- If `m_type == value_t::array`, then `m_value.array != nullptr`. -- If `m_type == value_t::string`, then `m_value.string != nullptr`. -The invariants are checked by member function assert_invariant(). - -@internal -@note ObjectType trick from https://stackoverflow.com/a/9860911 -@endinternal - -@see [RFC 7159: The JavaScript Object Notation (JSON) Data Interchange -Format](http://rfc7159.net/rfc7159) - -@since version 1.0.0 - -@nosubgrouping -*/ -NLOHMANN_BASIC_JSON_TPL_DECLARATION -class basic_json -{ - private: - template friend struct detail::external_constructor; - friend ::nlohmann::json_pointer; - - template - friend class ::nlohmann::detail::parser; - friend ::nlohmann::detail::serializer; - template - friend class ::nlohmann::detail::iter_impl; - template - friend class ::nlohmann::detail::binary_writer; - template - friend class ::nlohmann::detail::binary_reader; - template - friend class ::nlohmann::detail::json_sax_dom_parser; - template - friend class ::nlohmann::detail::json_sax_dom_callback_parser; - - /// workaround type for MSVC - using basic_json_t = NLOHMANN_BASIC_JSON_TPL; - - JSON_PRIVATE_UNLESS_TESTED: - // convenience aliases for types residing in namespace detail; - using lexer = ::nlohmann::detail::lexer_base; - - template - static ::nlohmann::detail::parser parser( - InputAdapterType adapter, - detail::parser_callback_tcb = nullptr, - const bool allow_exceptions = true, - const bool ignore_comments = false - ) - { - return ::nlohmann::detail::parser(std::move(adapter), - std::move(cb), allow_exceptions, ignore_comments); - } - - private: - using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t; - template - using internal_iterator = ::nlohmann::detail::internal_iterator; - template - using iter_impl = ::nlohmann::detail::iter_impl; - template - using iteration_proxy = ::nlohmann::detail::iteration_proxy; - template using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator; - - template - using output_adapter_t = ::nlohmann::detail::output_adapter_t; - - template - using binary_reader = ::nlohmann::detail::binary_reader; - template using binary_writer = ::nlohmann::detail::binary_writer; - - JSON_PRIVATE_UNLESS_TESTED: - using serializer = ::nlohmann::detail::serializer; - - public: - using value_t = detail::value_t; - /// JSON Pointer, see @ref nlohmann::json_pointer - using json_pointer = ::nlohmann::json_pointer; - template - using json_serializer = JSONSerializer; - /// how to treat decoding errors - using error_handler_t = detail::error_handler_t; - /// how to treat CBOR tags - using cbor_tag_handler_t = detail::cbor_tag_handler_t; - /// helper type for initializer lists of basic_json values - using initializer_list_t = std::initializer_list>; - - using input_format_t = detail::input_format_t; - /// SAX interface type, see @ref nlohmann::json_sax - using json_sax_t = json_sax; - - //////////////// - // exceptions // - //////////////// - - /// @name exceptions - /// Classes to implement user-defined exceptions. - /// @{ - - /// @copydoc detail::exception - using exception = detail::exception; - /// @copydoc detail::parse_error - using parse_error = detail::parse_error; - /// @copydoc detail::invalid_iterator - using invalid_iterator = detail::invalid_iterator; - /// @copydoc detail::type_error - using type_error = detail::type_error; - /// @copydoc detail::out_of_range - using out_of_range = detail::out_of_range; - /// @copydoc detail::other_error - using other_error = detail::other_error; - - /// @} - - - ///////////////////// - // container types // - ///////////////////// - - /// @name container types - /// The canonic container types to use @ref basic_json like any other STL - /// container. - /// @{ - - /// the type of elements in a basic_json container - using value_type = basic_json; - - /// the type of an element reference - using reference = value_type&; - /// the type of an element const reference - using const_reference = const value_type&; - - /// a type to represent differences between iterators - using difference_type = std::ptrdiff_t; - /// a type to represent container sizes - using size_type = std::size_t; - - /// the allocator type - using allocator_type = AllocatorType; - - /// the type of an element pointer - using pointer = typename std::allocator_traits::pointer; - /// the type of an element const pointer - using const_pointer = typename std::allocator_traits::const_pointer; - - /// an iterator for a basic_json container - using iterator = iter_impl; - /// a const iterator for a basic_json container - using const_iterator = iter_impl; - /// a reverse iterator for a basic_json container - using reverse_iterator = json_reverse_iterator; - /// a const reverse iterator for a basic_json container - using const_reverse_iterator = json_reverse_iterator; - - /// @} - - - /*! - @brief returns the allocator associated with the container - */ - static allocator_type get_allocator() - { - return allocator_type(); - } - - /*! - @brief returns version information on the library - - This function returns a JSON object with information about the library, - including the version number and information on the platform and compiler. - - @return JSON object holding version information - key | description - ----------- | --------------- - `compiler` | Information on the used compiler. It is an object with the following keys: `c++` (the used C++ standard), `family` (the compiler family; possible values are `clang`, `icc`, `gcc`, `ilecpp`, `msvc`, `pgcpp`, `sunpro`, and `unknown`), and `version` (the compiler version). - `copyright` | The copyright line for the library as string. - `name` | The name of the library as string. - `platform` | The used platform as string. Possible values are `win32`, `linux`, `apple`, `unix`, and `unknown`. - `url` | The URL of the project as string. - `version` | The version of the library. It is an object with the following keys: `major`, `minor`, and `patch` as defined by [Semantic Versioning](http://semver.org), and `string` (the version string). - - @liveexample{The following code shows an example output of the `meta()` - function.,meta} - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @complexity Constant. - - @since 2.1.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json meta() - { - basic_json result; - - result["copyright"] = "(C) 2013-2020 Niels Lohmann"; - result["name"] = "JSON for Modern C++"; - result["url"] = "https://github.com/nlohmann/json"; - result["version"]["string"] = - std::to_string(NLOHMANN_JSON_VERSION_MAJOR) + "." + - std::to_string(NLOHMANN_JSON_VERSION_MINOR) + "." + - std::to_string(NLOHMANN_JSON_VERSION_PATCH); - result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR; - result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR; - result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH; - -#ifdef _WIN32 - result["platform"] = "win32"; -#elif defined __linux__ - result["platform"] = "linux"; -#elif defined __APPLE__ - result["platform"] = "apple"; -#elif defined __unix__ - result["platform"] = "unix"; -#else - result["platform"] = "unknown"; -#endif - -#if defined(__ICC) || defined(__INTEL_COMPILER) - result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}}; -#elif defined(__clang__) - result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}}; -#elif defined(__GNUC__) || defined(__GNUG__) - result["compiler"] = {{"family", "gcc"}, {"version", std::to_string(__GNUC__) + "." + std::to_string(__GNUC_MINOR__) + "." + std::to_string(__GNUC_PATCHLEVEL__)}}; -#elif defined(__HP_cc) || defined(__HP_aCC) - result["compiler"] = "hp" -#elif defined(__IBMCPP__) - result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}}; -#elif defined(_MSC_VER) - result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}}; -#elif defined(__PGI) - result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}}; -#elif defined(__SUNPRO_CC) - result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}}; -#else - result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}}; -#endif - -#ifdef __cplusplus - result["compiler"]["c++"] = std::to_string(__cplusplus); -#else - result["compiler"]["c++"] = "unknown"; -#endif - return result; - } - - - /////////////////////////// - // JSON value data types // - /////////////////////////// - - /// @name JSON value data types - /// The data types to store a JSON value. These types are derived from - /// the template arguments passed to class @ref basic_json. - /// @{ - -#if defined(JSON_HAS_CPP_14) - // Use transparent comparator if possible, combined with perfect forwarding - // on find() and count() calls prevents unnecessary string construction. - using object_comparator_t = std::less<>; -#else - using object_comparator_t = std::less; -#endif - - /*! - @brief a type for an object - - [RFC 7159](http://rfc7159.net/rfc7159) describes JSON objects as follows: - > An object is an unordered collection of zero or more name/value pairs, - > where a name is a string and a value is a string, number, boolean, null, - > object, or array. - - To store objects in C++, a type is defined by the template parameters - described below. - - @tparam ObjectType the container to store objects (e.g., `std::map` or - `std::unordered_map`) - @tparam StringType the type of the keys or names (e.g., `std::string`). - The comparison function `std::less` is used to order elements - inside the container. - @tparam AllocatorType the allocator to use for objects (e.g., - `std::allocator`) - - #### Default type - - With the default values for @a ObjectType (`std::map`), @a StringType - (`std::string`), and @a AllocatorType (`std::allocator`), the default - value for @a object_t is: - - @code {.cpp} - std::map< - std::string, // key_type - basic_json, // value_type - std::less, // key_compare - std::allocator> // allocator_type - > - @endcode - - #### Behavior - - The choice of @a object_t influences the behavior of the JSON class. With - the default type, objects have the following behavior: - - - When all names are unique, objects will be interoperable in the sense - that all software implementations receiving that object will agree on - the name-value mappings. - - When the names within an object are not unique, it is unspecified which - one of the values for a given key will be chosen. For instance, - `{"key": 2, "key": 1}` could be equal to either `{"key": 1}` or - `{"key": 2}`. - - Internally, name/value pairs are stored in lexicographical order of the - names. Objects will also be serialized (see @ref dump) in this order. - For instance, `{"b": 1, "a": 2}` and `{"a": 2, "b": 1}` will be stored - and serialized as `{"a": 2, "b": 1}`. - - When comparing objects, the order of the name/value pairs is irrelevant. - This makes objects interoperable in the sense that they will not be - affected by these differences. For instance, `{"b": 1, "a": 2}` and - `{"a": 2, "b": 1}` will be treated as equal. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the maximum depth of nesting. - - In this class, the object's limit of nesting is not explicitly constrained. - However, a maximum depth of nesting may be introduced by the compiler or - runtime environment. A theoretical limit can be queried by calling the - @ref max_size function of a JSON object. - - #### Storage - - Objects are stored as pointers in a @ref basic_json type. That is, for any - access to object values, a pointer of type `object_t*` must be - dereferenced. - - @sa @ref array_t -- type for an array value - - @since version 1.0.0 - - @note The order name/value pairs are added to the object is *not* - preserved by the library. Therefore, iterating an object may return - name/value pairs in a different order than they were originally stored. In - fact, keys will be traversed in alphabetical order as `std::map` with - `std::less` is used by default. Please note this behavior conforms to [RFC - 7159](http://rfc7159.net/rfc7159), because any order implements the - specified "unordered" nature of JSON objects. - */ - using object_t = ObjectType>>; - - /*! - @brief a type for an array - - [RFC 7159](http://rfc7159.net/rfc7159) describes JSON arrays as follows: - > An array is an ordered sequence of zero or more values. - - To store objects in C++, a type is defined by the template parameters - explained below. - - @tparam ArrayType container type to store arrays (e.g., `std::vector` or - `std::list`) - @tparam AllocatorType allocator to use for arrays (e.g., `std::allocator`) - - #### Default type - - With the default values for @a ArrayType (`std::vector`) and @a - AllocatorType (`std::allocator`), the default value for @a array_t is: - - @code {.cpp} - std::vector< - basic_json, // value_type - std::allocator // allocator_type - > - @endcode - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the maximum depth of nesting. - - In this class, the array's limit of nesting is not explicitly constrained. - However, a maximum depth of nesting may be introduced by the compiler or - runtime environment. A theoretical limit can be queried by calling the - @ref max_size function of a JSON array. - - #### Storage - - Arrays are stored as pointers in a @ref basic_json type. That is, for any - access to array values, a pointer of type `array_t*` must be dereferenced. - - @sa @ref object_t -- type for an object value - - @since version 1.0.0 - */ - using array_t = ArrayType>; - - /*! - @brief a type for a string - - [RFC 7159](http://rfc7159.net/rfc7159) describes JSON strings as follows: - > A string is a sequence of zero or more Unicode characters. - - To store objects in C++, a type is defined by the template parameter - described below. Unicode values are split by the JSON class into - byte-sized characters during deserialization. - - @tparam StringType the container to store strings (e.g., `std::string`). - Note this container is used for keys/names in objects, see @ref object_t. - - #### Default type - - With the default values for @a StringType (`std::string`), the default - value for @a string_t is: - - @code {.cpp} - std::string - @endcode - - #### Encoding - - Strings are stored in UTF-8 encoding. Therefore, functions like - `std::string::size()` or `std::string::length()` return the number of - bytes in the string rather than the number of characters or glyphs. - - #### String comparison - - [RFC 7159](http://rfc7159.net/rfc7159) states: - > Software implementations are typically required to test names of object - > members for equality. Implementations that transform the textual - > representation into sequences of Unicode code units and then perform the - > comparison numerically, code unit by code unit, are interoperable in the - > sense that implementations will agree in all cases on equality or - > inequality of two strings. For example, implementations that compare - > strings with escaped characters unconverted may incorrectly find that - > `"a\\b"` and `"a\u005Cb"` are not equal. - - This implementation is interoperable as it does compare strings code unit - by code unit. - - #### Storage - - String values are stored as pointers in a @ref basic_json type. That is, - for any access to string values, a pointer of type `string_t*` must be - dereferenced. - - @since version 1.0.0 - */ - using string_t = StringType; - - /*! - @brief a type for a boolean - - [RFC 7159](http://rfc7159.net/rfc7159) implicitly describes a boolean as a - type which differentiates the two literals `true` and `false`. - - To store objects in C++, a type is defined by the template parameter @a - BooleanType which chooses the type to use. - - #### Default type - - With the default values for @a BooleanType (`bool`), the default value for - @a boolean_t is: - - @code {.cpp} - bool - @endcode - - #### Storage - - Boolean values are stored directly inside a @ref basic_json type. - - @since version 1.0.0 - */ - using boolean_t = BooleanType; - - /*! - @brief a type for a number (integer) - - [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. - - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. - - To store integer numbers in C++, a type is defined by the template - parameter @a NumberIntegerType which chooses the type to use. - - #### Default type - - With the default values for @a NumberIntegerType (`int64_t`), the default - value for @a number_integer_t is: - - @code {.cpp} - int64_t - @endcode - - #### Default behavior - - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in integer literals lead to an interpretation as octal - number. Internally, the value will be stored as decimal number. For - instance, the C++ integer literal `010` will be serialized to `8`. - During deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the range and precision of numbers. - - When the default type is used, the maximal integer number that can be - stored is `9223372036854775807` (INT64_MAX) and the minimal integer number - that can be stored is `-9223372036854775808` (INT64_MIN). Integer numbers - that are out of range will yield over/underflow when used in a - constructor. During deserialization, too large or small integer numbers - will be automatically be stored as @ref number_unsigned_t or @ref - number_float_t. - - [RFC 7159](http://rfc7159.net/rfc7159) further states: - > Note that when such software is used, numbers that are integers and are - > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense - > that implementations will agree exactly on their numeric values. - - As this range is a subrange of the exactly supported range [INT64_MIN, - INT64_MAX], this class's integer type is interoperable. - - #### Storage - - Integer number values are stored directly inside a @ref basic_json type. - - @sa @ref number_float_t -- type for number values (floating-point) - - @sa @ref number_unsigned_t -- type for number values (unsigned integer) - - @since version 1.0.0 - */ - using number_integer_t = NumberIntegerType; - - /*! - @brief a type for a number (unsigned) - - [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. - - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. - - To store unsigned integer numbers in C++, a type is defined by the - template parameter @a NumberUnsignedType which chooses the type to use. - - #### Default type - - With the default values for @a NumberUnsignedType (`uint64_t`), the - default value for @a number_unsigned_t is: - - @code {.cpp} - uint64_t - @endcode - - #### Default behavior - - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in integer literals lead to an interpretation as octal - number. Internally, the value will be stored as decimal number. For - instance, the C++ integer literal `010` will be serialized to `8`. - During deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) specifies: - > An implementation may set limits on the range and precision of numbers. - - When the default type is used, the maximal integer number that can be - stored is `18446744073709551615` (UINT64_MAX) and the minimal integer - number that can be stored is `0`. Integer numbers that are out of range - will yield over/underflow when used in a constructor. During - deserialization, too large or small integer numbers will be automatically - be stored as @ref number_integer_t or @ref number_float_t. - - [RFC 7159](http://rfc7159.net/rfc7159) further states: - > Note that when such software is used, numbers that are integers and are - > in the range \f$[-2^{53}+1, 2^{53}-1]\f$ are interoperable in the sense - > that implementations will agree exactly on their numeric values. - - As this range is a subrange (when considered in conjunction with the - number_integer_t type) of the exactly supported range [0, UINT64_MAX], - this class's integer type is interoperable. - - #### Storage - - Integer number values are stored directly inside a @ref basic_json type. - - @sa @ref number_float_t -- type for number values (floating-point) - @sa @ref number_integer_t -- type for number values (integer) - - @since version 2.0.0 - */ - using number_unsigned_t = NumberUnsignedType; - - /*! - @brief a type for a number (floating-point) - - [RFC 7159](http://rfc7159.net/rfc7159) describes numbers as follows: - > The representation of numbers is similar to that used in most - > programming languages. A number is represented in base 10 using decimal - > digits. It contains an integer component that may be prefixed with an - > optional minus sign, which may be followed by a fraction part and/or an - > exponent part. Leading zeros are not allowed. (...) Numeric values that - > cannot be represented in the grammar below (such as Infinity and NaN) - > are not permitted. - - This description includes both integer and floating-point numbers. - However, C++ allows more precise storage if it is known whether the number - is a signed integer, an unsigned integer or a floating-point number. - Therefore, three different types, @ref number_integer_t, @ref - number_unsigned_t and @ref number_float_t are used. - - To store floating-point numbers in C++, a type is defined by the template - parameter @a NumberFloatType which chooses the type to use. - - #### Default type - - With the default values for @a NumberFloatType (`double`), the default - value for @a number_float_t is: - - @code {.cpp} - double - @endcode - - #### Default behavior - - - The restrictions about leading zeros is not enforced in C++. Instead, - leading zeros in floating-point literals will be ignored. Internally, - the value will be stored as decimal number. For instance, the C++ - floating-point literal `01.2` will be serialized to `1.2`. During - deserialization, leading zeros yield an error. - - Not-a-number (NaN) values will be serialized to `null`. - - #### Limits - - [RFC 7159](http://rfc7159.net/rfc7159) states: - > This specification allows implementations to set limits on the range and - > precision of numbers accepted. Since software that implements IEEE - > 754-2008 binary64 (double precision) numbers is generally available and - > widely used, good interoperability can be achieved by implementations - > that expect no more precision or range than these provide, in the sense - > that implementations will approximate JSON numbers within the expected - > precision. - - This implementation does exactly follow this approach, as it uses double - precision floating-point numbers. Note values smaller than - `-1.79769313486232e+308` and values greater than `1.79769313486232e+308` - will be stored as NaN internally and be serialized to `null`. - - #### Storage - - Floating-point number values are stored directly inside a @ref basic_json - type. - - @sa @ref number_integer_t -- type for number values (integer) - - @sa @ref number_unsigned_t -- type for number values (unsigned integer) - - @since version 1.0.0 - */ - using number_float_t = NumberFloatType; - - /*! - @brief a type for a packed binary type - - This type is a type designed to carry binary data that appears in various - serialized formats, such as CBOR's Major Type 2, MessagePack's bin, and - BSON's generic binary subtype. This type is NOT a part of standard JSON and - exists solely for compatibility with these binary types. As such, it is - simply defined as an ordered sequence of zero or more byte values. - - Additionally, as an implementation detail, the subtype of the binary data is - carried around as a `std::uint8_t`, which is compatible with both of the - binary data formats that use binary subtyping, (though the specific - numbering is incompatible with each other, and it is up to the user to - translate between them). - - [CBOR's RFC 7049](https://tools.ietf.org/html/rfc7049) describes this type - as: - > Major type 2: a byte string. The string's length in bytes is represented - > following the rules for positive integers (major type 0). - - [MessagePack's documentation on the bin type - family](https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family) - describes this type as: - > Bin format family stores an byte array in 2, 3, or 5 bytes of extra bytes - > in addition to the size of the byte array. - - [BSON's specifications](http://bsonspec.org/spec.html) describe several - binary types; however, this type is intended to represent the generic binary - type which has the description: - > Generic binary subtype - This is the most commonly used binary subtype and - > should be the 'default' for drivers and tools. - - None of these impose any limitations on the internal representation other - than the basic unit of storage be some type of array whose parts are - decomposable into bytes. - - The default representation of this binary format is a - `std::vector`, which is a very common way to represent a byte - array in modern C++. - - #### Default type - - The default values for @a BinaryType is `std::vector` - - #### Storage - - Binary Arrays are stored as pointers in a @ref basic_json type. That is, - for any access to array values, a pointer of the type `binary_t*` must be - dereferenced. - - #### Notes on subtypes - - - CBOR - - Binary values are represented as byte strings. No subtypes are - supported and will be ignored when CBOR is written. - - MessagePack - - If a subtype is given and the binary array contains exactly 1, 2, 4, 8, - or 16 elements, the fixext family (fixext1, fixext2, fixext4, fixext8) - is used. For other sizes, the ext family (ext8, ext16, ext32) is used. - The subtype is then added as singed 8-bit integer. - - If no subtype is given, the bin family (bin8, bin16, bin32) is used. - - BSON - - If a subtype is given, it is used and added as unsigned 8-bit integer. - - If no subtype is given, the generic binary subtype 0x00 is used. - - @sa @ref binary -- create a binary array - - @since version 3.8.0 - */ - using binary_t = nlohmann::byte_container_with_subtype; - /// @} - - private: - - /// helper for exception-safe object creation - template - JSON_HEDLEY_RETURNS_NON_NULL - static T* create(Args&& ... args) - { - AllocatorType alloc; - using AllocatorTraits = std::allocator_traits>; - - auto deleter = [&](T * object) - { - AllocatorTraits::deallocate(alloc, object, 1); - }; - std::unique_ptr object(AllocatorTraits::allocate(alloc, 1), deleter); - AllocatorTraits::construct(alloc, object.get(), std::forward(args)...); - JSON_ASSERT(object != nullptr); - return object.release(); - } - - //////////////////////// - // JSON value storage // - //////////////////////// - - JSON_PRIVATE_UNLESS_TESTED: - /*! - @brief a JSON value - - The actual storage for a JSON value of the @ref basic_json class. This - union combines the different storage types for the JSON value types - defined in @ref value_t. - - JSON type | value_t type | used type - --------- | --------------- | ------------------------ - object | object | pointer to @ref object_t - array | array | pointer to @ref array_t - string | string | pointer to @ref string_t - boolean | boolean | @ref boolean_t - number | number_integer | @ref number_integer_t - number | number_unsigned | @ref number_unsigned_t - number | number_float | @ref number_float_t - binary | binary | pointer to @ref binary_t - null | null | *no value is stored* - - @note Variable-length types (objects, arrays, and strings) are stored as - pointers. The size of the union should not exceed 64 bits if the default - value types are used. - - @since version 1.0.0 - */ - union json_value - { - /// object (stored with pointer to save storage) - object_t* object; - /// array (stored with pointer to save storage) - array_t* array; - /// string (stored with pointer to save storage) - string_t* string; - /// binary (stored with pointer to save storage) - binary_t* binary; - /// boolean - boolean_t boolean; - /// number (integer) - number_integer_t number_integer; - /// number (unsigned integer) - number_unsigned_t number_unsigned; - /// number (floating-point) - number_float_t number_float; - - /// default constructor (for null values) - json_value() = default; - /// constructor for booleans - json_value(boolean_t v) noexcept : boolean(v) {} - /// constructor for numbers (integer) - json_value(number_integer_t v) noexcept : number_integer(v) {} - /// constructor for numbers (unsigned) - json_value(number_unsigned_t v) noexcept : number_unsigned(v) {} - /// constructor for numbers (floating-point) - json_value(number_float_t v) noexcept : number_float(v) {} - /// constructor for empty values of a given type - json_value(value_t t) - { - switch (t) - { - case value_t::object: - { - object = create(); - break; - } - - case value_t::array: - { - array = create(); - break; - } - - case value_t::string: - { - string = create(""); - break; - } - - case value_t::binary: - { - binary = create(); - break; - } - - case value_t::boolean: - { - boolean = boolean_t(false); - break; - } - - case value_t::number_integer: - { - number_integer = number_integer_t(0); - break; - } - - case value_t::number_unsigned: - { - number_unsigned = number_unsigned_t(0); - break; - } - - case value_t::number_float: - { - number_float = number_float_t(0.0); - break; - } - - case value_t::null: - { - object = nullptr; // silence warning, see #821 - break; - } - - default: - { - object = nullptr; // silence warning, see #821 - if (JSON_HEDLEY_UNLIKELY(t == value_t::null)) - { - JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.9.1")); // LCOV_EXCL_LINE - } - break; - } - } - } - - /// constructor for strings - json_value(const string_t& value) - { - string = create(value); - } - - /// constructor for rvalue strings - json_value(string_t&& value) - { - string = create(std::move(value)); - } - - /// constructor for objects - json_value(const object_t& value) - { - object = create(value); - } - - /// constructor for rvalue objects - json_value(object_t&& value) - { - object = create(std::move(value)); - } - - /// constructor for arrays - json_value(const array_t& value) - { - array = create(value); - } - - /// constructor for rvalue arrays - json_value(array_t&& value) - { - array = create(std::move(value)); - } - - /// constructor for binary arrays - json_value(const typename binary_t::container_type& value) - { - binary = create(value); - } - - /// constructor for rvalue binary arrays - json_value(typename binary_t::container_type&& value) - { - binary = create(std::move(value)); - } - - /// constructor for binary arrays (internal type) - json_value(const binary_t& value) - { - binary = create(value); - } - - /// constructor for rvalue binary arrays (internal type) - json_value(binary_t&& value) - { - binary = create(std::move(value)); - } - - void destroy(value_t t) noexcept - { - // flatten the current json_value to a heap-allocated stack - std::vector stack; - - // move the top-level items to stack - if (t == value_t::array) - { - stack.reserve(array->size()); - std::move(array->begin(), array->end(), std::back_inserter(stack)); - } - else if (t == value_t::object) - { - stack.reserve(object->size()); - for (auto&& it : *object) - { - stack.push_back(std::move(it.second)); - } - } - - while (!stack.empty()) - { - // move the last item to local variable to be processed - basic_json current_item(std::move(stack.back())); - stack.pop_back(); - - // if current_item is array/object, move - // its children to the stack to be processed later - if (current_item.is_array()) - { - std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), - std::back_inserter(stack)); - - current_item.m_value.array->clear(); - } - else if (current_item.is_object()) - { - for (auto&& it : *current_item.m_value.object) - { - stack.push_back(std::move(it.second)); - } - - current_item.m_value.object->clear(); - } - - // it's now safe that current_item get destructed - // since it doesn't have any children - } - - switch (t) - { - case value_t::object: - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, object); - std::allocator_traits::deallocate(alloc, object, 1); - break; - } - - case value_t::array: - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, array); - std::allocator_traits::deallocate(alloc, array, 1); - break; - } - - case value_t::string: - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, string); - std::allocator_traits::deallocate(alloc, string, 1); - break; - } - - case value_t::binary: - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, binary); - std::allocator_traits::deallocate(alloc, binary, 1); - break; - } - - default: - { - break; - } - } - } - }; - - private: - /*! - @brief checks the class invariants - - This function asserts the class invariants. It needs to be called at the - end of every constructor to make sure that created objects respect the - invariant. Furthermore, it has to be called each time the type of a JSON - value is changed, because the invariant expresses a relationship between - @a m_type and @a m_value. - */ - void assert_invariant() const noexcept - { - JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr); - JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr); - JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr); - JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr); - } - - public: - ////////////////////////// - // JSON parser callback // - ////////////////////////// - - /*! - @brief parser event types - - The parser callback distinguishes the following events: - - `object_start`: the parser read `{` and started to process a JSON object - - `key`: the parser read a key of a value in an object - - `object_end`: the parser read `}` and finished processing a JSON object - - `array_start`: the parser read `[` and started to process a JSON array - - `array_end`: the parser read `]` and finished processing a JSON array - - `value`: the parser finished reading a JSON value - - @image html callback_events.png "Example when certain parse events are triggered" - - @sa @ref parser_callback_t for more information and examples - */ - using parse_event_t = detail::parse_event_t; - - /*! - @brief per-element parser callback type - - With a parser callback function, the result of parsing a JSON text can be - influenced. When passed to @ref parse, it is called on certain events - (passed as @ref parse_event_t via parameter @a event) with a set recursion - depth @a depth and context JSON value @a parsed. The return value of the - callback function is a boolean indicating whether the element that emitted - the callback shall be kept or not. - - We distinguish six scenarios (determined by the event type) in which the - callback function can be called. The following table describes the values - of the parameters @a depth, @a event, and @a parsed. - - parameter @a event | description | parameter @a depth | parameter @a parsed - ------------------ | ----------- | ------------------ | ------------------- - parse_event_t::object_start | the parser read `{` and started to process a JSON object | depth of the parent of the JSON object | a JSON value with type discarded - parse_event_t::key | the parser read a key of a value in an object | depth of the currently parsed JSON object | a JSON string containing the key - parse_event_t::object_end | the parser read `}` and finished processing a JSON object | depth of the parent of the JSON object | the parsed JSON object - parse_event_t::array_start | the parser read `[` and started to process a JSON array | depth of the parent of the JSON array | a JSON value with type discarded - parse_event_t::array_end | the parser read `]` and finished processing a JSON array | depth of the parent of the JSON array | the parsed JSON array - parse_event_t::value | the parser finished reading a JSON value | depth of the value | the parsed JSON value - - @image html callback_events.png "Example when certain parse events are triggered" - - Discarding a value (i.e., returning `false`) has different effects - depending on the context in which function was called: - - - Discarded values in structured types are skipped. That is, the parser - will behave as if the discarded value was never read. - - In case a value outside a structured type is skipped, it is replaced - with `null`. This case happens if the top-level element is skipped. - - @param[in] depth the depth of the recursion during parsing - - @param[in] event an event of type parse_event_t indicating the context in - the callback function has been called - - @param[in,out] parsed the current intermediate parse result; note that - writing to this value has no effect for parse_event_t::key events - - @return Whether the JSON value which called the function during parsing - should be kept (`true`) or not (`false`). In the latter case, it is either - skipped completely or replaced by an empty discarded object. - - @sa @ref parse for examples - - @since version 1.0.0 - */ - using parser_callback_t = detail::parser_callback_t; - - ////////////////// - // constructors // - ////////////////// - - /// @name constructors and destructors - /// Constructors of class @ref basic_json, copy/move constructor, copy - /// assignment, static functions creating objects, and the destructor. - /// @{ - - /*! - @brief create an empty value with a given type - - Create an empty JSON value with a given type. The value will be default - initialized with an empty value which depends on the type: - - Value type | initial value - ----------- | ------------- - null | `null` - boolean | `false` - string | `""` - number | `0` - object | `{}` - array | `[]` - binary | empty array - - @param[in] v the type of the value to create - - @complexity Constant. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The following code shows the constructor for different @ref - value_t values,basic_json__value_t} - - @sa @ref clear() -- restores the postcondition of this constructor - - @since version 1.0.0 - */ - basic_json(const value_t v) - : m_type(v), m_value(v) - { - assert_invariant(); - } - - /*! - @brief create a null object - - Create a `null` JSON value. It either takes a null pointer as parameter - (explicitly creating `null`) or no parameter (implicitly creating `null`). - The passed null pointer itself is not read -- it is only used to choose - the right constructor. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this constructor never throws - exceptions. - - @liveexample{The following code shows the constructor with and without a - null pointer parameter.,basic_json__nullptr_t} - - @since version 1.0.0 - */ - basic_json(std::nullptr_t = nullptr) noexcept - : basic_json(value_t::null) - { - assert_invariant(); - } - - /*! - @brief create a JSON value - - This is a "catch all" constructor for all compatible JSON types; that is, - types for which a `to_json()` method exists. The constructor forwards the - parameter @a val to that method (to `json_serializer::to_json` method - with `U = uncvref_t`, to be exact). - - Template type @a CompatibleType includes, but is not limited to, the - following types: - - **arrays**: @ref array_t and all kinds of compatible containers such as - `std::vector`, `std::deque`, `std::list`, `std::forward_list`, - `std::array`, `std::valarray`, `std::set`, `std::unordered_set`, - `std::multiset`, and `std::unordered_multiset` with a `value_type` from - which a @ref basic_json value can be constructed. - - **objects**: @ref object_t and all kinds of compatible associative - containers such as `std::map`, `std::unordered_map`, `std::multimap`, - and `std::unordered_multimap` with a `key_type` compatible to - @ref string_t and a `value_type` from which a @ref basic_json value can - be constructed. - - **strings**: @ref string_t, string literals, and all compatible string - containers can be used. - - **numbers**: @ref number_integer_t, @ref number_unsigned_t, - @ref number_float_t, and all convertible number types such as `int`, - `size_t`, `int64_t`, `float` or `double` can be used. - - **boolean**: @ref boolean_t / `bool` can be used. - - **binary**: @ref binary_t / `std::vector` may be used, - unfortunately because string literals cannot be distinguished from binary - character arrays by the C++ type system, all types compatible with `const - char*` will be directed to the string constructor instead. This is both - for backwards compatibility, and due to the fact that a binary type is not - a standard JSON type. - - See the examples below. - - @tparam CompatibleType a type such that: - - @a CompatibleType is not derived from `std::istream`, - - @a CompatibleType is not @ref basic_json (to avoid hijacking copy/move - constructors), - - @a CompatibleType is not a different @ref basic_json type (i.e. with different template arguments) - - @a CompatibleType is not a @ref basic_json nested type (e.g., - @ref json_pointer, @ref iterator, etc ...) - - @ref @ref json_serializer has a - `to_json(basic_json_t&, CompatibleType&&)` method - - @tparam U = `uncvref_t` - - @param[in] val the value to be forwarded to the respective constructor - - @complexity Usually linear in the size of the passed @a val, also - depending on the implementation of the called `to_json()` - method. - - @exceptionsafety Depends on the called constructor. For types directly - supported by the library (i.e., all types for which no `to_json()` function - was provided), strong guarantee holds: if an exception is thrown, there are - no changes to any JSON value. - - @liveexample{The following code shows the constructor with several - compatible types.,basic_json__CompatibleType} - - @since version 2.1.0 - */ - template < typename CompatibleType, - typename U = detail::uncvref_t, - detail::enable_if_t < - !detail::is_basic_json::value && detail::is_compatible_type::value, int > = 0 > - basic_json(CompatibleType && val) noexcept(noexcept( - JSONSerializer::to_json(std::declval(), - std::forward(val)))) - { - JSONSerializer::to_json(*this, std::forward(val)); - assert_invariant(); - } - - /*! - @brief create a JSON value from an existing one - - This is a constructor for existing @ref basic_json types. - It does not hijack copy/move constructors, since the parameter has different - template arguments than the current ones. - - The constructor tries to convert the internal @ref m_value of the parameter. - - @tparam BasicJsonType a type such that: - - @a BasicJsonType is a @ref basic_json type. - - @a BasicJsonType has different template arguments than @ref basic_json_t. - - @param[in] val the @ref basic_json value to be converted. - - @complexity Usually linear in the size of the passed @a val, also - depending on the implementation of the called `to_json()` - method. - - @exceptionsafety Depends on the called constructor. For types directly - supported by the library (i.e., all types for which no `to_json()` function - was provided), strong guarantee holds: if an exception is thrown, there are - no changes to any JSON value. - - @since version 3.2.0 - */ - template < typename BasicJsonType, - detail::enable_if_t < - detail::is_basic_json::value&& !std::is_same::value, int > = 0 > - basic_json(const BasicJsonType& val) - { - using other_boolean_t = typename BasicJsonType::boolean_t; - using other_number_float_t = typename BasicJsonType::number_float_t; - using other_number_integer_t = typename BasicJsonType::number_integer_t; - using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t; - using other_string_t = typename BasicJsonType::string_t; - using other_object_t = typename BasicJsonType::object_t; - using other_array_t = typename BasicJsonType::array_t; - using other_binary_t = typename BasicJsonType::binary_t; - - switch (val.type()) - { - case value_t::boolean: - JSONSerializer::to_json(*this, val.template get()); - break; - case value_t::number_float: - JSONSerializer::to_json(*this, val.template get()); - break; - case value_t::number_integer: - JSONSerializer::to_json(*this, val.template get()); - break; - case value_t::number_unsigned: - JSONSerializer::to_json(*this, val.template get()); - break; - case value_t::string: - JSONSerializer::to_json(*this, val.template get_ref()); - break; - case value_t::object: - JSONSerializer::to_json(*this, val.template get_ref()); - break; - case value_t::array: - JSONSerializer::to_json(*this, val.template get_ref()); - break; - case value_t::binary: - JSONSerializer::to_json(*this, val.template get_ref()); - break; - case value_t::null: - *this = nullptr; - break; - case value_t::discarded: - m_type = value_t::discarded; - break; - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - assert_invariant(); - } - - /*! - @brief create a container (array or object) from an initializer list - - Creates a JSON value of type array or object from the passed initializer - list @a init. In case @a type_deduction is `true` (default), the type of - the JSON value to be created is deducted from the initializer list @a init - according to the following rules: - - 1. If the list is empty, an empty JSON object value `{}` is created. - 2. If the list consists of pairs whose first element is a string, a JSON - object value is created where the first elements of the pairs are - treated as keys and the second elements are as values. - 3. In all other cases, an array is created. - - The rules aim to create the best fit between a C++ initializer list and - JSON values. The rationale is as follows: - - 1. The empty initializer list is written as `{}` which is exactly an empty - JSON object. - 2. C++ has no way of describing mapped types other than to list a list of - pairs. As JSON requires that keys must be of type string, rule 2 is the - weakest constraint one can pose on initializer lists to interpret them - as an object. - 3. In all other cases, the initializer list could not be interpreted as - JSON object type, so interpreting it as JSON array type is safe. - - With the rules described above, the following JSON values cannot be - expressed by an initializer list: - - - the empty array (`[]`): use @ref array(initializer_list_t) - with an empty initializer list in this case - - arrays whose elements satisfy rule 2: use @ref - array(initializer_list_t) with the same initializer list - in this case - - @note When used without parentheses around an empty initializer list, @ref - basic_json() is called instead of this function, yielding the JSON null - value. - - @param[in] init initializer list with JSON values - - @param[in] type_deduction internal parameter; when set to `true`, the type - of the JSON value is deducted from the initializer list @a init; when set - to `false`, the type provided via @a manual_type is forced. This mode is - used by the functions @ref array(initializer_list_t) and - @ref object(initializer_list_t). - - @param[in] manual_type internal parameter; when @a type_deduction is set - to `false`, the created JSON value will use the provided type (only @ref - value_t::array and @ref value_t::object are valid); when @a type_deduction - is set to `true`, this parameter has no effect - - @throw type_error.301 if @a type_deduction is `false`, @a manual_type is - `value_t::object`, but @a init contains an element which is not a pair - whose first element is a string. In this case, the constructor could not - create an object. If @a type_deduction would have be `true`, an array - would have been created. See @ref object(initializer_list_t) - for an example. - - @complexity Linear in the size of the initializer list @a init. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The example below shows how JSON values are created from - initializer lists.,basic_json__list_init_t} - - @sa @ref array(initializer_list_t) -- create a JSON array - value from an initializer list - @sa @ref object(initializer_list_t) -- create a JSON object - value from an initializer list - - @since version 1.0.0 - */ - basic_json(initializer_list_t init, - bool type_deduction = true, - value_t manual_type = value_t::array) - { - // check if each element is an array with two elements whose first - // element is a string - bool is_an_object = std::all_of(init.begin(), init.end(), - [](const detail::json_ref& element_ref) - { - return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string(); - }); - - // adjust type if type deduction is not wanted - if (!type_deduction) - { - // if array is wanted, do not create an object though possible - if (manual_type == value_t::array) - { - is_an_object = false; - } - - // if object is wanted but impossible, throw an exception - if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object)) - { - JSON_THROW(type_error::create(301, "cannot create object from initializer list")); - } - } - - if (is_an_object) - { - // the initializer list is a list of pairs -> create object - m_type = value_t::object; - m_value = value_t::object; - - std::for_each(init.begin(), init.end(), [this](const detail::json_ref& element_ref) - { - auto element = element_ref.moved_or_copied(); - m_value.object->emplace( - std::move(*((*element.m_value.array)[0].m_value.string)), - std::move((*element.m_value.array)[1])); - }); - } - else - { - // the initializer list describes an array -> create array - m_type = value_t::array; - m_value.array = create(init.begin(), init.end()); - } - - assert_invariant(); - } - - /*! - @brief explicitly create a binary array (without subtype) - - Creates a JSON binary array value from a given binary container. Binary - values are part of various binary formats, such as CBOR, MessagePack, and - BSON. This constructor is used to create a value for serialization to those - formats. - - @note Note, this function exists because of the difficulty in correctly - specifying the correct template overload in the standard value ctor, as both - JSON arrays and JSON binary arrays are backed with some form of a - `std::vector`. Because JSON binary arrays are a non-standard extension it - was decided that it would be best to prevent automatic initialization of a - binary array type, for backwards compatibility and so it does not happen on - accident. - - @param[in] init container containing bytes to use as binary type - - @return JSON binary array value - - @complexity Linear in the size of @a init. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @since version 3.8.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json binary(const typename binary_t::container_type& init) - { - auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = init; - return res; - } - - /*! - @brief explicitly create a binary array (with subtype) - - Creates a JSON binary array value from a given binary container. Binary - values are part of various binary formats, such as CBOR, MessagePack, and - BSON. This constructor is used to create a value for serialization to those - formats. - - @note Note, this function exists because of the difficulty in correctly - specifying the correct template overload in the standard value ctor, as both - JSON arrays and JSON binary arrays are backed with some form of a - `std::vector`. Because JSON binary arrays are a non-standard extension it - was decided that it would be best to prevent automatic initialization of a - binary array type, for backwards compatibility and so it does not happen on - accident. - - @param[in] init container containing bytes to use as binary type - @param[in] subtype subtype to use in MessagePack and BSON - - @return JSON binary array value - - @complexity Linear in the size of @a init. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @since version 3.8.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json binary(const typename binary_t::container_type& init, std::uint8_t subtype) - { - auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = binary_t(init, subtype); - return res; - } - - /// @copydoc binary(const typename binary_t::container_type&) - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json binary(typename binary_t::container_type&& init) - { - auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = std::move(init); - return res; - } - - /// @copydoc binary(const typename binary_t::container_type&, std::uint8_t) - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json binary(typename binary_t::container_type&& init, std::uint8_t subtype) - { - auto res = basic_json(); - res.m_type = value_t::binary; - res.m_value = binary_t(std::move(init), subtype); - return res; - } - - /*! - @brief explicitly create an array from an initializer list - - Creates a JSON array value from a given initializer list. That is, given a - list of values `a, b, c`, creates the JSON value `[a, b, c]`. If the - initializer list is empty, the empty array `[]` is created. - - @note This function is only needed to express two edge cases that cannot - be realized with the initializer list constructor (@ref - basic_json(initializer_list_t, bool, value_t)). These cases - are: - 1. creating an array whose elements are all pairs whose first element is a - string -- in this case, the initializer list constructor would create an - object, taking the first elements as keys - 2. creating an empty array -- passing the empty initializer list to the - initializer list constructor yields an empty object - - @param[in] init initializer list with JSON values to create an array from - (optional) - - @return JSON array value - - @complexity Linear in the size of @a init. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The following code shows an example for the `array` - function.,array} - - @sa @ref basic_json(initializer_list_t, bool, value_t) -- - create a JSON value from an initializer list - @sa @ref object(initializer_list_t) -- create a JSON object - value from an initializer list - - @since version 1.0.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json array(initializer_list_t init = {}) - { - return basic_json(init, false, value_t::array); - } - - /*! - @brief explicitly create an object from an initializer list - - Creates a JSON object value from a given initializer list. The initializer - lists elements must be pairs, and their first elements must be strings. If - the initializer list is empty, the empty object `{}` is created. - - @note This function is only added for symmetry reasons. In contrast to the - related function @ref array(initializer_list_t), there are - no cases which can only be expressed by this function. That is, any - initializer list @a init can also be passed to the initializer list - constructor @ref basic_json(initializer_list_t, bool, value_t). - - @param[in] init initializer list to create an object from (optional) - - @return JSON object value - - @throw type_error.301 if @a init is not a list of pairs whose first - elements are strings. In this case, no object can be created. When such a - value is passed to @ref basic_json(initializer_list_t, bool, value_t), - an array would have been created from the passed initializer list @a init. - See example below. - - @complexity Linear in the size of @a init. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The following code shows an example for the `object` - function.,object} - - @sa @ref basic_json(initializer_list_t, bool, value_t) -- - create a JSON value from an initializer list - @sa @ref array(initializer_list_t) -- create a JSON array - value from an initializer list - - @since version 1.0.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json object(initializer_list_t init = {}) - { - return basic_json(init, false, value_t::object); - } - - /*! - @brief construct an array with count copies of given value - - Constructs a JSON array value by creating @a cnt copies of a passed value. - In case @a cnt is `0`, an empty array is created. - - @param[in] cnt the number of JSON copies of @a val to create - @param[in] val the JSON value to copy - - @post `std::distance(begin(),end()) == cnt` holds. - - @complexity Linear in @a cnt. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The following code shows examples for the @ref - basic_json(size_type\, const basic_json&) - constructor.,basic_json__size_type_basic_json} - - @since version 1.0.0 - */ - basic_json(size_type cnt, const basic_json& val) - : m_type(value_t::array) - { - m_value.array = create(cnt, val); - assert_invariant(); - } - - /*! - @brief construct a JSON container given an iterator range - - Constructs the JSON value with the contents of the range `[first, last)`. - The semantics depends on the different types a JSON value can have: - - In case of a null type, invalid_iterator.206 is thrown. - - In case of other primitive types (number, boolean, or string), @a first - must be `begin()` and @a last must be `end()`. In this case, the value is - copied. Otherwise, invalid_iterator.204 is thrown. - - In case of structured types (array, object), the constructor behaves as - similar versions for `std::vector` or `std::map`; that is, a JSON array - or object is constructed from the values in the range. - - @tparam InputIT an input iterator type (@ref iterator or @ref - const_iterator) - - @param[in] first begin of the range to copy from (included) - @param[in] last end of the range to copy from (excluded) - - @pre Iterators @a first and @a last must be initialized. **This - precondition is enforced with an assertion (see warning).** If - assertions are switched off, a violation of this precondition yields - undefined behavior. - - @pre Range `[first, last)` is valid. Usually, this precondition cannot be - checked efficiently. Only certain edge cases are detected; see the - description of the exceptions below. A violation of this precondition - yields undefined behavior. - - @warning A precondition is enforced with a runtime assertion that will - result in calling `std::abort` if this precondition is not met. - Assertions can be disabled by defining `NDEBUG` at compile time. - See https://en.cppreference.com/w/cpp/error/assert for more - information. - - @throw invalid_iterator.201 if iterators @a first and @a last are not - compatible (i.e., do not belong to the same JSON value). In this case, - the range `[first, last)` is undefined. - @throw invalid_iterator.204 if iterators @a first and @a last belong to a - primitive type (number, boolean, or string), but @a first does not point - to the first element any more. In this case, the range `[first, last)` is - undefined. See example code below. - @throw invalid_iterator.206 if iterators @a first and @a last belong to a - null value. In this case, the range `[first, last)` is undefined. - - @complexity Linear in distance between @a first and @a last. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @liveexample{The example below shows several ways to create JSON values by - specifying a subrange with iterators.,basic_json__InputIt_InputIt} - - @since version 1.0.0 - */ - template < class InputIT, typename std::enable_if < - std::is_same::value || - std::is_same::value, int >::type = 0 > - basic_json(InputIT first, InputIT last) - { - JSON_ASSERT(first.m_object != nullptr); - JSON_ASSERT(last.m_object != nullptr); - - // make sure iterator fits the current value - if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) - { - JSON_THROW(invalid_iterator::create(201, "iterators are not compatible")); - } - - // copy type from first iterator - m_type = first.m_object->m_type; - - // check if iterator range is complete for primitive values - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - { - if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin() - || !last.m_it.primitive_iterator.is_end())) - { - JSON_THROW(invalid_iterator::create(204, "iterators out of range")); - } - break; - } - - default: - break; - } - - switch (m_type) - { - case value_t::number_integer: - { - m_value.number_integer = first.m_object->m_value.number_integer; - break; - } - - case value_t::number_unsigned: - { - m_value.number_unsigned = first.m_object->m_value.number_unsigned; - break; - } - - case value_t::number_float: - { - m_value.number_float = first.m_object->m_value.number_float; - break; - } - - case value_t::boolean: - { - m_value.boolean = first.m_object->m_value.boolean; - break; - } - - case value_t::string: - { - m_value = *first.m_object->m_value.string; - break; - } - - case value_t::object: - { - m_value.object = create(first.m_it.object_iterator, - last.m_it.object_iterator); - break; - } - - case value_t::array: - { - m_value.array = create(first.m_it.array_iterator, - last.m_it.array_iterator); - break; - } - - case value_t::binary: - { - m_value = *first.m_object->m_value.binary; - break; - } - - default: - JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " + - std::string(first.m_object->type_name()))); - } - - assert_invariant(); - } - - - /////////////////////////////////////// - // other constructors and destructor // - /////////////////////////////////////// - - template, - std::is_same>::value, int> = 0 > - basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {} - - /*! - @brief copy constructor - - Creates a copy of a given JSON value. - - @param[in] other the JSON value to copy - - @post `*this == other` - - @complexity Linear in the size of @a other. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes to any JSON value. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is linear. - - As postcondition, it holds: `other == basic_json(other)`. - - @liveexample{The following code shows an example for the copy - constructor.,basic_json__basic_json} - - @since version 1.0.0 - */ - basic_json(const basic_json& other) - : m_type(other.m_type) - { - // check of passed value is valid - other.assert_invariant(); - - switch (m_type) - { - case value_t::object: - { - m_value = *other.m_value.object; - break; - } - - case value_t::array: - { - m_value = *other.m_value.array; - break; - } - - case value_t::string: - { - m_value = *other.m_value.string; - break; - } - - case value_t::boolean: - { - m_value = other.m_value.boolean; - break; - } - - case value_t::number_integer: - { - m_value = other.m_value.number_integer; - break; - } - - case value_t::number_unsigned: - { - m_value = other.m_value.number_unsigned; - break; - } - - case value_t::number_float: - { - m_value = other.m_value.number_float; - break; - } - - case value_t::binary: - { - m_value = *other.m_value.binary; - break; - } - - default: - break; - } - - assert_invariant(); - } - - /*! - @brief move constructor - - Move constructor. Constructs a JSON value with the contents of the given - value @a other using move semantics. It "steals" the resources from @a - other and leaves it as JSON null value. - - @param[in,out] other value to move to this object - - @post `*this` has the same value as @a other before the call. - @post @a other is a JSON null value. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this constructor never throws - exceptions. - - @requirement This function helps `basic_json` satisfying the - [MoveConstructible](https://en.cppreference.com/w/cpp/named_req/MoveConstructible) - requirements. - - @liveexample{The code below shows the move constructor explicitly called - via std::move.,basic_json__moveconstructor} - - @since version 1.0.0 - */ - basic_json(basic_json&& other) noexcept - : m_type(std::move(other.m_type)), - m_value(std::move(other.m_value)) - { - // check that passed value is valid - other.assert_invariant(); - - // invalidate payload - other.m_type = value_t::null; - other.m_value = {}; - - assert_invariant(); - } - - /*! - @brief copy assignment - - Copy assignment operator. Copies a JSON value via the "copy and swap" - strategy: It is expressed in terms of the copy constructor, destructor, - and the `swap()` member function. - - @param[in] other value to copy from - - @complexity Linear. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is linear. - - @liveexample{The code below shows and example for the copy assignment. It - creates a copy of value `a` which is then swapped with `b`. Finally\, the - copy of `a` (which is the null value after the swap) is - destroyed.,basic_json__copyassignment} - - @since version 1.0.0 - */ - basic_json& operator=(basic_json other) noexcept ( - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value - ) - { - // check that passed value is valid - other.assert_invariant(); - - using std::swap; - swap(m_type, other.m_type); - swap(m_value, other.m_value); - - assert_invariant(); - return *this; - } - - /*! - @brief destructor - - Destroys the JSON value and frees all allocated memory. - - @complexity Linear. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is linear. - - All stored elements are destroyed and all memory is freed. - - @since version 1.0.0 - */ - ~basic_json() noexcept - { - assert_invariant(); - m_value.destroy(m_type); - } - - /// @} - - public: - /////////////////////// - // object inspection // - /////////////////////// - - /// @name object inspection - /// Functions to inspect the type of a JSON value. - /// @{ - - /*! - @brief serialization - - Serialization function for JSON values. The function tries to mimic - Python's `json.dumps()` function, and currently supports its @a indent - and @a ensure_ascii parameters. - - @param[in] indent If indent is nonnegative, then array elements and object - members will be pretty-printed with that indent level. An indent level of - `0` will only insert newlines. `-1` (the default) selects the most compact - representation. - @param[in] indent_char The character to use for indentation if @a indent is - greater than `0`. The default is ` ` (space). - @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters - in the output are escaped with `\uXXXX` sequences, and the result consists - of ASCII characters only. - @param[in] error_handler how to react on decoding errors; there are three - possible values: `strict` (throws and exception in case a decoding error - occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD), - and `ignore` (ignore invalid UTF-8 sequences during serialization; all - bytes are copied to the output unchanged). - - @return string containing the serialization of the JSON value - - @throw type_error.316 if a string stored inside the JSON value is not - UTF-8 encoded and @a error_handler is set to strict - - @note Binary values are serialized as object containing two keys: - - "bytes": an array of bytes as integers - - "subtype": the subtype as integer or "null" if the binary has no subtype - - @complexity Linear. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @liveexample{The following example shows the effect of different @a indent\, - @a indent_char\, and @a ensure_ascii parameters to the result of the - serialization.,dump} - - @see https://docs.python.org/2/library/json.html#json.dump - - @since version 1.0.0; indentation character @a indent_char, option - @a ensure_ascii and exceptions added in version 3.0.0; error - handlers added in version 3.4.0; serialization of binary values added - in version 3.8.0. - */ - string_t dump(const int indent = -1, - const char indent_char = ' ', - const bool ensure_ascii = false, - const error_handler_t error_handler = error_handler_t::strict) const - { - string_t result; - serializer s(detail::output_adapter(result), indent_char, error_handler); - - if (indent >= 0) - { - s.dump(*this, true, ensure_ascii, static_cast(indent)); - } - else - { - s.dump(*this, false, ensure_ascii, 0); - } - - return result; - } - - /*! - @brief return the type of the JSON value (explicit) - - Return the type of the JSON value as a value from the @ref value_t - enumeration. - - @return the type of the JSON value - Value type | return value - ------------------------- | ------------------------- - null | value_t::null - boolean | value_t::boolean - string | value_t::string - number (integer) | value_t::number_integer - number (unsigned integer) | value_t::number_unsigned - number (floating-point) | value_t::number_float - object | value_t::object - array | value_t::array - binary | value_t::binary - discarded | value_t::discarded - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `type()` for all JSON - types.,type} - - @sa @ref operator value_t() -- return the type of the JSON value (implicit) - @sa @ref type_name() -- return the type as string - - @since version 1.0.0 - */ - constexpr value_t type() const noexcept - { - return m_type; - } - - /*! - @brief return whether type is primitive - - This function returns true if and only if the JSON type is primitive - (string, number, boolean, or null). - - @return `true` if type is primitive (string, number, boolean, or null), - `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_primitive()` for all JSON - types.,is_primitive} - - @sa @ref is_structured() -- returns whether JSON value is structured - @sa @ref is_null() -- returns whether JSON value is `null` - @sa @ref is_string() -- returns whether JSON value is a string - @sa @ref is_boolean() -- returns whether JSON value is a boolean - @sa @ref is_number() -- returns whether JSON value is a number - @sa @ref is_binary() -- returns whether JSON value is a binary array - - @since version 1.0.0 - */ - constexpr bool is_primitive() const noexcept - { - return is_null() || is_string() || is_boolean() || is_number() || is_binary(); - } - - /*! - @brief return whether type is structured - - This function returns true if and only if the JSON type is structured - (array or object). - - @return `true` if type is structured (array or object), `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_structured()` for all JSON - types.,is_structured} - - @sa @ref is_primitive() -- returns whether value is primitive - @sa @ref is_array() -- returns whether value is an array - @sa @ref is_object() -- returns whether value is an object - - @since version 1.0.0 - */ - constexpr bool is_structured() const noexcept - { - return is_array() || is_object(); - } - - /*! - @brief return whether value is null - - This function returns true if and only if the JSON value is null. - - @return `true` if type is null, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_null()` for all JSON - types.,is_null} - - @since version 1.0.0 - */ - constexpr bool is_null() const noexcept - { - return m_type == value_t::null; - } - - /*! - @brief return whether value is a boolean - - This function returns true if and only if the JSON value is a boolean. - - @return `true` if type is boolean, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_boolean()` for all JSON - types.,is_boolean} - - @since version 1.0.0 - */ - constexpr bool is_boolean() const noexcept - { - return m_type == value_t::boolean; - } - - /*! - @brief return whether value is a number - - This function returns true if and only if the JSON value is a number. This - includes both integer (signed and unsigned) and floating-point values. - - @return `true` if type is number (regardless whether integer, unsigned - integer or floating-type), `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number()` for all JSON - types.,is_number} - - @sa @ref is_number_integer() -- check if value is an integer or unsigned - integer number - @sa @ref is_number_unsigned() -- check if value is an unsigned integer - number - @sa @ref is_number_float() -- check if value is a floating-point number - - @since version 1.0.0 - */ - constexpr bool is_number() const noexcept - { - return is_number_integer() || is_number_float(); - } - - /*! - @brief return whether value is an integer number - - This function returns true if and only if the JSON value is a signed or - unsigned integer number. This excludes floating-point values. - - @return `true` if type is an integer or unsigned integer number, `false` - otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number_integer()` for all - JSON types.,is_number_integer} - - @sa @ref is_number() -- check if value is a number - @sa @ref is_number_unsigned() -- check if value is an unsigned integer - number - @sa @ref is_number_float() -- check if value is a floating-point number - - @since version 1.0.0 - */ - constexpr bool is_number_integer() const noexcept - { - return m_type == value_t::number_integer || m_type == value_t::number_unsigned; - } - - /*! - @brief return whether value is an unsigned integer number - - This function returns true if and only if the JSON value is an unsigned - integer number. This excludes floating-point and signed integer values. - - @return `true` if type is an unsigned integer number, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number_unsigned()` for all - JSON types.,is_number_unsigned} - - @sa @ref is_number() -- check if value is a number - @sa @ref is_number_integer() -- check if value is an integer or unsigned - integer number - @sa @ref is_number_float() -- check if value is a floating-point number - - @since version 2.0.0 - */ - constexpr bool is_number_unsigned() const noexcept - { - return m_type == value_t::number_unsigned; - } - - /*! - @brief return whether value is a floating-point number - - This function returns true if and only if the JSON value is a - floating-point number. This excludes signed and unsigned integer values. - - @return `true` if type is a floating-point number, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_number_float()` for all - JSON types.,is_number_float} - - @sa @ref is_number() -- check if value is number - @sa @ref is_number_integer() -- check if value is an integer number - @sa @ref is_number_unsigned() -- check if value is an unsigned integer - number - - @since version 1.0.0 - */ - constexpr bool is_number_float() const noexcept - { - return m_type == value_t::number_float; - } - - /*! - @brief return whether value is an object - - This function returns true if and only if the JSON value is an object. - - @return `true` if type is object, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_object()` for all JSON - types.,is_object} - - @since version 1.0.0 - */ - constexpr bool is_object() const noexcept - { - return m_type == value_t::object; - } - - /*! - @brief return whether value is an array - - This function returns true if and only if the JSON value is an array. - - @return `true` if type is array, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_array()` for all JSON - types.,is_array} - - @since version 1.0.0 - */ - constexpr bool is_array() const noexcept - { - return m_type == value_t::array; - } - - /*! - @brief return whether value is a string - - This function returns true if and only if the JSON value is a string. - - @return `true` if type is string, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_string()` for all JSON - types.,is_string} - - @since version 1.0.0 - */ - constexpr bool is_string() const noexcept - { - return m_type == value_t::string; - } - - /*! - @brief return whether value is a binary array - - This function returns true if and only if the JSON value is a binary array. - - @return `true` if type is binary array, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_binary()` for all JSON - types.,is_binary} - - @since version 3.8.0 - */ - constexpr bool is_binary() const noexcept - { - return m_type == value_t::binary; - } - - /*! - @brief return whether value is discarded - - This function returns true if and only if the JSON value was discarded - during parsing with a callback function (see @ref parser_callback_t). - - @note This function will always be `false` for JSON values after parsing. - That is, discarded values can only occur during parsing, but will be - removed when inside a structured value or replaced by null in other cases. - - @return `true` if type is discarded, `false` otherwise. - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies `is_discarded()` for all JSON - types.,is_discarded} - - @since version 1.0.0 - */ - constexpr bool is_discarded() const noexcept - { - return m_type == value_t::discarded; - } - - /*! - @brief return the type of the JSON value (implicit) - - Implicitly return the type of the JSON value as a value from the @ref - value_t enumeration. - - @return the type of the JSON value - - @complexity Constant. - - @exceptionsafety No-throw guarantee: this member function never throws - exceptions. - - @liveexample{The following code exemplifies the @ref value_t operator for - all JSON types.,operator__value_t} - - @sa @ref type() -- return the type of the JSON value (explicit) - @sa @ref type_name() -- return the type as string - - @since version 1.0.0 - */ - constexpr operator value_t() const noexcept - { - return m_type; - } - - /// @} - - private: - ////////////////// - // value access // - ////////////////// - - /// get a boolean (explicit) - boolean_t get_impl(boolean_t* /*unused*/) const - { - if (JSON_HEDLEY_LIKELY(is_boolean())) - { - return m_value.boolean; - } - - JSON_THROW(type_error::create(302, "type must be boolean, but is " + std::string(type_name()))); - } - - /// get a pointer to the value (object) - object_t* get_impl_ptr(object_t* /*unused*/) noexcept - { - return is_object() ? m_value.object : nullptr; - } - - /// get a pointer to the value (object) - constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept - { - return is_object() ? m_value.object : nullptr; - } - - /// get a pointer to the value (array) - array_t* get_impl_ptr(array_t* /*unused*/) noexcept - { - return is_array() ? m_value.array : nullptr; - } - - /// get a pointer to the value (array) - constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept - { - return is_array() ? m_value.array : nullptr; - } - - /// get a pointer to the value (string) - string_t* get_impl_ptr(string_t* /*unused*/) noexcept - { - return is_string() ? m_value.string : nullptr; - } - - /// get a pointer to the value (string) - constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept - { - return is_string() ? m_value.string : nullptr; - } - - /// get a pointer to the value (boolean) - boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept - { - return is_boolean() ? &m_value.boolean : nullptr; - } - - /// get a pointer to the value (boolean) - constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept - { - return is_boolean() ? &m_value.boolean : nullptr; - } - - /// get a pointer to the value (integer number) - number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept - { - return is_number_integer() ? &m_value.number_integer : nullptr; - } - - /// get a pointer to the value (integer number) - constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept - { - return is_number_integer() ? &m_value.number_integer : nullptr; - } - - /// get a pointer to the value (unsigned number) - number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept - { - return is_number_unsigned() ? &m_value.number_unsigned : nullptr; - } - - /// get a pointer to the value (unsigned number) - constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept - { - return is_number_unsigned() ? &m_value.number_unsigned : nullptr; - } - - /// get a pointer to the value (floating-point number) - number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept - { - return is_number_float() ? &m_value.number_float : nullptr; - } - - /// get a pointer to the value (floating-point number) - constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept - { - return is_number_float() ? &m_value.number_float : nullptr; - } - - /// get a pointer to the value (binary) - binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept - { - return is_binary() ? m_value.binary : nullptr; - } - - /// get a pointer to the value (binary) - constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept - { - return is_binary() ? m_value.binary : nullptr; - } - - /*! - @brief helper function to implement get_ref() - - This function helps to implement get_ref() without code duplication for - const and non-const overloads - - @tparam ThisType will be deduced as `basic_json` or `const basic_json` - - @throw type_error.303 if ReferenceType does not match underlying value - type of the current JSON - */ - template - static ReferenceType get_ref_impl(ThisType& obj) - { - // delegate the call to get_ptr<>() - auto ptr = obj.template get_ptr::type>(); - - if (JSON_HEDLEY_LIKELY(ptr != nullptr)) - { - return *ptr; - } - - JSON_THROW(type_error::create(303, "incompatible ReferenceType for get_ref, actual type is " + std::string(obj.type_name()))); - } - - public: - /// @name value access - /// Direct access to the stored value of a JSON value. - /// @{ - - /*! - @brief get special-case overload - - This overloads avoids a lot of template boilerplate, it can be seen as the - identity method - - @tparam BasicJsonType == @ref basic_json - - @return a copy of *this - - @complexity Constant. - - @since version 2.1.0 - */ - template::type, basic_json_t>::value, - int> = 0> - basic_json get() const - { - return *this; - } - - /*! - @brief get special-case overload - - This overloads converts the current @ref basic_json in a different - @ref basic_json type - - @tparam BasicJsonType == @ref basic_json - - @return a copy of *this, converted into @tparam BasicJsonType - - @complexity Depending on the implementation of the called `from_json()` - method. - - @since version 3.2.0 - */ - template < typename BasicJsonType, detail::enable_if_t < - !std::is_same::value&& - detail::is_basic_json::value, int > = 0 > - BasicJsonType get() const - { - return *this; - } - - /*! - @brief get a value (explicit) - - Explicit type conversion between the JSON value and a compatible value - which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) - and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). - The value is converted by calling the @ref json_serializer - `from_json()` method. - - The function is equivalent to executing - @code {.cpp} - ValueType ret; - JSONSerializer::from_json(*this, ret); - return ret; - @endcode - - This overloads is chosen if: - - @a ValueType is not @ref basic_json, - - @ref json_serializer has a `from_json()` method of the form - `void from_json(const basic_json&, ValueType&)`, and - - @ref json_serializer does not have a `from_json()` method of - the form `ValueType from_json(const basic_json&)` - - @tparam ValueTypeCV the provided value type - @tparam ValueType the returned value type - - @return copy of the JSON value, converted to @a ValueType - - @throw what @ref json_serializer `from_json()` method throws - - @liveexample{The example below shows several conversions from JSON values - to other types. There a few things to note: (1) Floating-point numbers can - be converted to integers\, (2) A JSON array can be converted to a standard - `std::vector`\, (3) A JSON object can be converted to C++ - associative containers such as `std::unordered_map`.,get__ValueType_const} - - @since version 2.1.0 - */ - template < typename ValueTypeCV, typename ValueType = detail::uncvref_t, - detail::enable_if_t < - !detail::is_basic_json::value && - detail::has_from_json::value && - !detail::has_non_default_from_json::value, - int > = 0 > - ValueType get() const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), std::declval()))) - { - // we cannot static_assert on ValueTypeCV being non-const, because - // there is support for get(), which is why we - // still need the uncvref - static_assert(!std::is_reference::value, - "get() cannot be used with reference types, you might want to use get_ref()"); - static_assert(std::is_default_constructible::value, - "types must be DefaultConstructible when used with get()"); - - ValueType ret; - JSONSerializer::from_json(*this, ret); - return ret; - } - - /*! - @brief get a value (explicit); special case - - Explicit type conversion between the JSON value and a compatible value - which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible) - and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). - The value is converted by calling the @ref json_serializer - `from_json()` method. - - The function is equivalent to executing - @code {.cpp} - return JSONSerializer::from_json(*this); - @endcode - - This overloads is chosen if: - - @a ValueType is not @ref basic_json and - - @ref json_serializer has a `from_json()` method of the form - `ValueType from_json(const basic_json&)` - - @note If @ref json_serializer has both overloads of - `from_json()`, this one is chosen. - - @tparam ValueTypeCV the provided value type - @tparam ValueType the returned value type - - @return copy of the JSON value, converted to @a ValueType - - @throw what @ref json_serializer `from_json()` method throws - - @since version 2.1.0 - */ - template < typename ValueTypeCV, typename ValueType = detail::uncvref_t, - detail::enable_if_t < !std::is_same::value && - detail::has_non_default_from_json::value, - int > = 0 > - ValueType get() const noexcept(noexcept( - JSONSerializer::from_json(std::declval()))) - { - static_assert(!std::is_reference::value, - "get() cannot be used with reference types, you might want to use get_ref()"); - return JSONSerializer::from_json(*this); - } - - /*! - @brief get a value (explicit) - - Explicit type conversion between the JSON value and a compatible value. - The value is filled into the input parameter by calling the @ref json_serializer - `from_json()` method. - - The function is equivalent to executing - @code {.cpp} - ValueType v; - JSONSerializer::from_json(*this, v); - @endcode - - This overloads is chosen if: - - @a ValueType is not @ref basic_json, - - @ref json_serializer has a `from_json()` method of the form - `void from_json(const basic_json&, ValueType&)`, and - - @tparam ValueType the input parameter type. - - @return the input parameter, allowing chaining calls. - - @throw what @ref json_serializer `from_json()` method throws - - @liveexample{The example below shows several conversions from JSON values - to other types. There a few things to note: (1) Floating-point numbers can - be converted to integers\, (2) A JSON array can be converted to a standard - `std::vector`\, (3) A JSON object can be converted to C++ - associative containers such as `std::unordered_map`.,get_to} - - @since version 3.3.0 - */ - template < typename ValueType, - detail::enable_if_t < - !detail::is_basic_json::value&& - detail::has_from_json::value, - int > = 0 > - ValueType & get_to(ValueType& v) const noexcept(noexcept( - JSONSerializer::from_json(std::declval(), v))) - { - JSONSerializer::from_json(*this, v); - return v; - } - - // specialization to allow to call get_to with a basic_json value - // see https://github.com/nlohmann/json/issues/2175 - template::value, - int> = 0> - ValueType & get_to(ValueType& v) const - { - v = *this; - return v; - } - - template < - typename T, std::size_t N, - typename Array = T (&)[N], - detail::enable_if_t < - detail::has_from_json::value, int > = 0 > - Array get_to(T (&v)[N]) const - noexcept(noexcept(JSONSerializer::from_json( - std::declval(), v))) - { - JSONSerializer::from_json(*this, v); - return v; - } - - - /*! - @brief get a pointer value (implicit) - - Implicit pointer access to the internally stored JSON value. No copies are - made. - - @warning Writing data to the pointee of the result yields an undefined - state. - - @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref - object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, - @ref number_unsigned_t, or @ref number_float_t. Enforced by a static - assertion. - - @return pointer to the internally stored JSON value if the requested - pointer type @a PointerType fits to the JSON value; `nullptr` otherwise - - @complexity Constant. - - @liveexample{The example below shows how pointers to internal values of a - JSON value can be requested. Note that no type conversions are made and a - `nullptr` is returned if the value and the requested pointer type does not - match.,get_ptr} - - @since version 1.0.0 - */ - template::value, int>::type = 0> - auto get_ptr() noexcept -> decltype(std::declval().get_impl_ptr(std::declval())) - { - // delegate the call to get_impl_ptr<>() - return get_impl_ptr(static_cast(nullptr)); - } - - /*! - @brief get a pointer value (implicit) - @copydoc get_ptr() - */ - template < typename PointerType, typename std::enable_if < - std::is_pointer::value&& - std::is_const::type>::value, int >::type = 0 > - constexpr auto get_ptr() const noexcept -> decltype(std::declval().get_impl_ptr(std::declval())) - { - // delegate the call to get_impl_ptr<>() const - return get_impl_ptr(static_cast(nullptr)); - } - - /*! - @brief get a pointer value (explicit) - - Explicit pointer access to the internally stored JSON value. No copies are - made. - - @warning The pointer becomes invalid if the underlying JSON object - changes. - - @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref - object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, - @ref number_unsigned_t, or @ref number_float_t. - - @return pointer to the internally stored JSON value if the requested - pointer type @a PointerType fits to the JSON value; `nullptr` otherwise - - @complexity Constant. - - @liveexample{The example below shows how pointers to internal values of a - JSON value can be requested. Note that no type conversions are made and a - `nullptr` is returned if the value and the requested pointer type does not - match.,get__PointerType} - - @sa @ref get_ptr() for explicit pointer-member access - - @since version 1.0.0 - */ - template::value, int>::type = 0> - auto get() noexcept -> decltype(std::declval().template get_ptr()) - { - // delegate the call to get_ptr - return get_ptr(); - } - - /*! - @brief get a pointer value (explicit) - @copydoc get() - */ - template::value, int>::type = 0> - constexpr auto get() const noexcept -> decltype(std::declval().template get_ptr()) - { - // delegate the call to get_ptr - return get_ptr(); - } - - /*! - @brief get a reference value (implicit) - - Implicit reference access to the internally stored JSON value. No copies - are made. - - @warning Writing data to the referee of the result yields an undefined - state. - - @tparam ReferenceType reference type; must be a reference to @ref array_t, - @ref object_t, @ref string_t, @ref boolean_t, @ref number_integer_t, or - @ref number_float_t. Enforced by static assertion. - - @return reference to the internally stored JSON value if the requested - reference type @a ReferenceType fits to the JSON value; throws - type_error.303 otherwise - - @throw type_error.303 in case passed type @a ReferenceType is incompatible - with the stored JSON value; see example below - - @complexity Constant. - - @liveexample{The example shows several calls to `get_ref()`.,get_ref} - - @since version 1.1.0 - */ - template::value, int>::type = 0> - ReferenceType get_ref() - { - // delegate call to get_ref_impl - return get_ref_impl(*this); - } - - /*! - @brief get a reference value (implicit) - @copydoc get_ref() - */ - template < typename ReferenceType, typename std::enable_if < - std::is_reference::value&& - std::is_const::type>::value, int >::type = 0 > - ReferenceType get_ref() const - { - // delegate call to get_ref_impl - return get_ref_impl(*this); - } - - /*! - @brief get a value (implicit) - - Implicit type conversion between the JSON value and a compatible value. - The call is realized by calling @ref get() const. - - @tparam ValueType non-pointer type compatible to the JSON value, for - instance `int` for JSON integer numbers, `bool` for JSON booleans, or - `std::vector` types for JSON arrays. The character type of @ref string_t - as well as an initializer list of this type is excluded to avoid - ambiguities as these types implicitly convert to `std::string`. - - @return copy of the JSON value, converted to type @a ValueType - - @throw type_error.302 in case passed type @a ValueType is incompatible - to the JSON value type (e.g., the JSON value is of type boolean, but a - string is requested); see example below - - @complexity Linear in the size of the JSON value. - - @liveexample{The example below shows several conversions from JSON values - to other types. There a few things to note: (1) Floating-point numbers can - be converted to integers\, (2) A JSON array can be converted to a standard - `std::vector`\, (3) A JSON object can be converted to C++ - associative containers such as `std::unordered_map`.,operator__ValueType} - - @since version 1.0.0 - */ - template < typename ValueType, typename std::enable_if < - !std::is_pointer::value&& - !std::is_same>::value&& - !std::is_same::value&& - !detail::is_basic_json::value - && !std::is_same>::value -#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914)) - && !std::is_same::value -#endif - && detail::is_detected::value - , int >::type = 0 > - JSON_EXPLICIT operator ValueType() const - { - // delegate the call to get<>() const - return get(); - } - - /*! - @return reference to the binary value - - @throw type_error.302 if the value is not binary - - @sa @ref is_binary() to check if the value is binary - - @since version 3.8.0 - */ - binary_t& get_binary() - { - if (!is_binary()) - { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()))); - } - - return *get_ptr(); - } - - /// @copydoc get_binary() - const binary_t& get_binary() const - { - if (!is_binary()) - { - JSON_THROW(type_error::create(302, "type must be binary, but is " + std::string(type_name()))); - } - - return *get_ptr(); - } - - /// @} - - - //////////////////// - // element access // - //////////////////// - - /// @name element access - /// Access to the JSON value. - /// @{ - - /*! - @brief access specified array element with bounds checking - - Returns a reference to the element at specified location @a idx, with - bounds checking. - - @param[in] idx index of the element to access - - @return reference to the element at index @a idx - - @throw type_error.304 if the JSON value is not an array; in this case, - calling `at` with an index makes no sense. See example below. - @throw out_of_range.401 if the index @a idx is out of range of the array; - that is, `idx >= size()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 1.0.0 - - @liveexample{The example below shows how array elements can be read and - written using `at()`. It also demonstrates the different exceptions that - can be thrown.,at__size_type} - */ - reference at(size_type idx) - { - // at only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - JSON_TRY - { - return m_value.array->at(idx); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); - } - } - - /*! - @brief access specified array element with bounds checking - - Returns a const reference to the element at specified location @a idx, - with bounds checking. - - @param[in] idx index of the element to access - - @return const reference to the element at index @a idx - - @throw type_error.304 if the JSON value is not an array; in this case, - calling `at` with an index makes no sense. See example below. - @throw out_of_range.401 if the index @a idx is out of range of the array; - that is, `idx >= size()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 1.0.0 - - @liveexample{The example below shows how array elements can be read using - `at()`. It also demonstrates the different exceptions that can be thrown., - at__size_type_const} - */ - const_reference at(size_type idx) const - { - // at only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - JSON_TRY - { - return m_value.array->at(idx); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); - } - } - - /*! - @brief access specified object element with bounds checking - - Returns a reference to the element at with specified key @a key, with - bounds checking. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.304 if the JSON value is not an object; in this case, - calling `at` with a key makes no sense. See example below. - @throw out_of_range.403 if the key @a key is is not stored in the object; - that is, `find(key) == end()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Logarithmic in the size of the container. - - @sa @ref operator[](const typename object_t::key_type&) for unchecked - access by reference - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - - @liveexample{The example below shows how object elements can be read and - written using `at()`. It also demonstrates the different exceptions that - can be thrown.,at__object_t_key_type} - */ - reference at(const typename object_t::key_type& key) - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_TRY - { - return m_value.object->at(key); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); - } - } - - /*! - @brief access specified object element with bounds checking - - Returns a const reference to the element at with specified key @a key, - with bounds checking. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @throw type_error.304 if the JSON value is not an object; in this case, - calling `at` with a key makes no sense. See example below. - @throw out_of_range.403 if the key @a key is is not stored in the object; - that is, `find(key) == end()`. See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Logarithmic in the size of the container. - - @sa @ref operator[](const typename object_t::key_type&) for unchecked - access by reference - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - - @liveexample{The example below shows how object elements can be read using - `at()`. It also demonstrates the different exceptions that can be thrown., - at__object_t_key_type_const} - */ - const_reference at(const typename object_t::key_type& key) const - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_TRY - { - return m_value.object->at(key); - } - JSON_CATCH (std::out_of_range&) - { - // create better exception explanation - JSON_THROW(out_of_range::create(403, "key '" + key + "' not found")); - } - } - else - { - JSON_THROW(type_error::create(304, "cannot use at() with " + std::string(type_name()))); - } - } - - /*! - @brief access specified array element - - Returns a reference to the element at specified location @a idx. - - @note If @a idx is beyond the range of the array (i.e., `idx >= size()`), - then the array is silently filled up with `null` values to make `idx` a - valid reference to the last stored element. - - @param[in] idx index of the element to access - - @return reference to the element at index @a idx - - @throw type_error.305 if the JSON value is not an array or null; in that - cases, using the [] operator with an index makes no sense. - - @complexity Constant if @a idx is in the range of the array. Otherwise - linear in `idx - size()`. - - @liveexample{The example below shows how array elements can be read and - written using `[]` operator. Note the addition of `null` - values.,operatorarray__size_type} - - @since version 1.0.0 - */ - reference operator[](size_type idx) - { - // implicitly convert null value to an empty array - if (is_null()) - { - m_type = value_t::array; - m_value.array = create(); - assert_invariant(); - } - - // operator[] only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - // fill up array with null values if given idx is outside range - if (idx >= m_value.array->size()) - { - m_value.array->insert(m_value.array->end(), - idx - m_value.array->size() + 1, - basic_json()); - } - - return m_value.array->operator[](idx); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()))); - } - - /*! - @brief access specified array element - - Returns a const reference to the element at specified location @a idx. - - @param[in] idx index of the element to access - - @return const reference to the element at index @a idx - - @throw type_error.305 if the JSON value is not an array; in that case, - using the [] operator with an index makes no sense. - - @complexity Constant. - - @liveexample{The example below shows how array elements can be read using - the `[]` operator.,operatorarray__size_type_const} - - @since version 1.0.0 - */ - const_reference operator[](size_type idx) const - { - // const operator[] only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - return m_value.array->operator[](idx); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a numeric argument with " + std::string(type_name()))); - } - - /*! - @brief access specified object element - - Returns a reference to the element at with specified key @a key. - - @note If @a key is not found in the object, then it is silently added to - the object and filled with a `null` value to make `key` a valid reference. - In case the value was `null` before, it is converted to an object. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.305 if the JSON value is not an object or null; in that - cases, using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read and - written using the `[]` operator.,operatorarray__key_type} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - */ - reference operator[](const typename object_t::key_type& key) - { - // implicitly convert null value to an empty object - if (is_null()) - { - m_type = value_t::object; - m_value.object = create(); - assert_invariant(); - } - - // operator[] only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - return m_value.object->operator[](key); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); - } - - /*! - @brief read-only access specified object element - - Returns a const reference to the element at with specified key @a key. No - bounds checking is performed. - - @warning If the element with key @a key does not exist, the behavior is - undefined. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @pre The element with key @a key must exist. **This precondition is - enforced with an assertion.** - - @throw type_error.305 if the JSON value is not an object; in that case, - using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read using - the `[]` operator.,operatorarray__key_type_const} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.0.0 - */ - const_reference operator[](const typename object_t::key_type& key) const - { - // const operator[] only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_ASSERT(m_value.object->find(key) != m_value.object->end()); - return m_value.object->find(key)->second; - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); - } - - /*! - @brief access specified object element - - Returns a reference to the element at with specified key @a key. - - @note If @a key is not found in the object, then it is silently added to - the object and filled with a `null` value to make `key` a valid reference. - In case the value was `null` before, it is converted to an object. - - @param[in] key key of the element to access - - @return reference to the element at key @a key - - @throw type_error.305 if the JSON value is not an object or null; in that - cases, using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read and - written using the `[]` operator.,operatorarray__key_type} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.1.0 - */ - template - JSON_HEDLEY_NON_NULL(2) - reference operator[](T* key) - { - // implicitly convert null to object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); - } - - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - return m_value.object->operator[](key); - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); - } - - /*! - @brief read-only access specified object element - - Returns a const reference to the element at with specified key @a key. No - bounds checking is performed. - - @warning If the element with key @a key does not exist, the behavior is - undefined. - - @param[in] key key of the element to access - - @return const reference to the element at key @a key - - @pre The element with key @a key must exist. **This precondition is - enforced with an assertion.** - - @throw type_error.305 if the JSON value is not an object; in that case, - using the [] operator with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be read using - the `[]` operator.,operatorarray__key_type_const} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref value() for access by value with a default value - - @since version 1.1.0 - */ - template - JSON_HEDLEY_NON_NULL(2) - const_reference operator[](T* key) const - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - JSON_ASSERT(m_value.object->find(key) != m_value.object->end()); - return m_value.object->find(key)->second; - } - - JSON_THROW(type_error::create(305, "cannot use operator[] with a string argument with " + std::string(type_name()))); - } - - /*! - @brief access specified object element with default value - - Returns either a copy of an object's element at the specified key @a key - or a given default value if no element with key @a key exists. - - The function is basically equivalent to executing - @code {.cpp} - try { - return at(key); - } catch(out_of_range) { - return default_value; - } - @endcode - - @note Unlike @ref at(const typename object_t::key_type&), this function - does not throw if the given key @a key was not found. - - @note Unlike @ref operator[](const typename object_t::key_type& key), this - function does not implicitly add an element to the position defined by @a - key. This function is furthermore also applicable to const objects. - - @param[in] key key of the element to access - @param[in] default_value the value to return if @a key is not found - - @tparam ValueType type compatible to JSON values, for instance `int` for - JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for - JSON arrays. Note the type of the expected value at @a key and the default - value @a default_value must be compatible. - - @return copy of the element at key @a key or @a default_value if @a key - is not found - - @throw type_error.302 if @a default_value does not match the type of the - value at @a key - @throw type_error.306 if the JSON value is not an object; in that case, - using `value()` with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be queried - with a default value.,basic_json__value} - - @sa @ref at(const typename object_t::key_type&) for access by reference - with range checking - @sa @ref operator[](const typename object_t::key_type&) for unchecked - access by reference - - @since version 1.0.0 - */ - // using std::is_convertible in a std::enable_if will fail when using explicit conversions - template < class ValueType, typename std::enable_if < - detail::is_getable::value - && !std::is_same::value, int >::type = 0 > - ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - // if key is found, return value and given default value otherwise - const auto it = find(key); - if (it != end()) - { - return it->template get(); - } - - return default_value; - } - - JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); - } - - /*! - @brief overload for a default value of type const char* - @copydoc basic_json::value(const typename object_t::key_type&, const ValueType&) const - */ - string_t value(const typename object_t::key_type& key, const char* default_value) const - { - return value(key, string_t(default_value)); - } - - /*! - @brief access specified object element via JSON Pointer with default value - - Returns either a copy of an object's element at the specified key @a key - or a given default value if no element with key @a key exists. - - The function is basically equivalent to executing - @code {.cpp} - try { - return at(ptr); - } catch(out_of_range) { - return default_value; - } - @endcode - - @note Unlike @ref at(const json_pointer&), this function does not throw - if the given key @a key was not found. - - @param[in] ptr a JSON pointer to the element to access - @param[in] default_value the value to return if @a ptr found no value - - @tparam ValueType type compatible to JSON values, for instance `int` for - JSON integer numbers, `bool` for JSON booleans, or `std::vector` types for - JSON arrays. Note the type of the expected value at @a key and the default - value @a default_value must be compatible. - - @return copy of the element at key @a key or @a default_value if @a key - is not found - - @throw type_error.302 if @a default_value does not match the type of the - value at @a ptr - @throw type_error.306 if the JSON value is not an object; in that case, - using `value()` with a key makes no sense. - - @complexity Logarithmic in the size of the container. - - @liveexample{The example below shows how object elements can be queried - with a default value.,basic_json__value_ptr} - - @sa @ref operator[](const json_pointer&) for unchecked access by reference - - @since version 2.0.2 - */ - template::value, int>::type = 0> - ValueType value(const json_pointer& ptr, const ValueType& default_value) const - { - // at only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - // if pointer resolves a value, return it or use default value - JSON_TRY - { - return ptr.get_checked(this).template get(); - } - JSON_INTERNAL_CATCH (out_of_range&) - { - return default_value; - } - } - - JSON_THROW(type_error::create(306, "cannot use value() with " + std::string(type_name()))); - } - - /*! - @brief overload for a default value of type const char* - @copydoc basic_json::value(const json_pointer&, ValueType) const - */ - JSON_HEDLEY_NON_NULL(3) - string_t value(const json_pointer& ptr, const char* default_value) const - { - return value(ptr, string_t(default_value)); - } - - /*! - @brief access the first element - - Returns a reference to the first element in the container. For a JSON - container `c`, the expression `c.front()` is equivalent to `*c.begin()`. - - @return In case of a structured type (array or object), a reference to the - first element is returned. In case of number, string, boolean, or binary - values, a reference to the value is returned. - - @complexity Constant. - - @pre The JSON value must not be `null` (would throw `std::out_of_range`) - or an empty array or object (undefined behavior, **guarded by - assertions**). - @post The JSON value remains unchanged. - - @throw invalid_iterator.214 when called on `null` value - - @liveexample{The following code shows an example for `front()`.,front} - - @sa @ref back() -- access the last element - - @since version 1.0.0 - */ - reference front() - { - return *begin(); - } - - /*! - @copydoc basic_json::front() - */ - const_reference front() const - { - return *cbegin(); - } - - /*! - @brief access the last element - - Returns a reference to the last element in the container. For a JSON - container `c`, the expression `c.back()` is equivalent to - @code {.cpp} - auto tmp = c.end(); - --tmp; - return *tmp; - @endcode - - @return In case of a structured type (array or object), a reference to the - last element is returned. In case of number, string, boolean, or binary - values, a reference to the value is returned. - - @complexity Constant. - - @pre The JSON value must not be `null` (would throw `std::out_of_range`) - or an empty array or object (undefined behavior, **guarded by - assertions**). - @post The JSON value remains unchanged. - - @throw invalid_iterator.214 when called on a `null` value. See example - below. - - @liveexample{The following code shows an example for `back()`.,back} - - @sa @ref front() -- access the first element - - @since version 1.0.0 - */ - reference back() - { - auto tmp = end(); - --tmp; - return *tmp; - } - - /*! - @copydoc basic_json::back() - */ - const_reference back() const - { - auto tmp = cend(); - --tmp; - return *tmp; - } - - /*! - @brief remove element given an iterator - - Removes the element specified by iterator @a pos. The iterator @a pos must - be valid and dereferenceable. Thus the `end()` iterator (which is valid, - but is not dereferenceable) cannot be used as a value for @a pos. - - If called on a primitive type other than `null`, the resulting JSON value - will be `null`. - - @param[in] pos iterator to the element to remove - @return Iterator following the last removed element. If the iterator @a - pos refers to the last element, the `end()` iterator is returned. - - @tparam IteratorType an @ref iterator or @ref const_iterator - - @post Invalidates iterators and references at or after the point of the - erase, including the `end()` iterator. - - @throw type_error.307 if called on a `null` value; example: `"cannot use - erase() with null"` - @throw invalid_iterator.202 if called on an iterator which does not belong - to the current JSON value; example: `"iterator does not fit current - value"` - @throw invalid_iterator.205 if called on a primitive type with invalid - iterator (i.e., any iterator which is not `begin()`); example: `"iterator - out of range"` - - @complexity The complexity depends on the type: - - objects: amortized constant - - arrays: linear in distance between @a pos and the end of the container - - strings and binary: linear in the length of the member - - other types: constant - - @liveexample{The example shows the result of `erase()` for different JSON - types.,erase__IteratorType} - - @sa @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa @ref erase(const typename object_t::key_type&) -- removes the element - from an object at the given key - @sa @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 1.0.0 - */ - template < class IteratorType, typename std::enable_if < - std::is_same::value || - std::is_same::value, int >::type - = 0 > - IteratorType erase(IteratorType pos) - { - // make sure iterator fits the current value - if (JSON_HEDLEY_UNLIKELY(this != pos.m_object)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - IteratorType result = end(); - - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - case value_t::binary: - { - if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin())) - { - JSON_THROW(invalid_iterator::create(205, "iterator out of range")); - } - - if (is_string()) - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.string); - std::allocator_traits::deallocate(alloc, m_value.string, 1); - m_value.string = nullptr; - } - else if (is_binary()) - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.binary); - std::allocator_traits::deallocate(alloc, m_value.binary, 1); - m_value.binary = nullptr; - } - - m_type = value_t::null; - assert_invariant(); - break; - } - - case value_t::object: - { - result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator); - break; - } - - case value_t::array: - { - result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator); - break; - } - - default: - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); - } - - return result; - } - - /*! - @brief remove elements given an iterator range - - Removes the element specified by the range `[first; last)`. The iterator - @a first does not need to be dereferenceable if `first == last`: erasing - an empty range is a no-op. - - If called on a primitive type other than `null`, the resulting JSON value - will be `null`. - - @param[in] first iterator to the beginning of the range to remove - @param[in] last iterator past the end of the range to remove - @return Iterator following the last removed element. If the iterator @a - second refers to the last element, the `end()` iterator is returned. - - @tparam IteratorType an @ref iterator or @ref const_iterator - - @post Invalidates iterators and references at or after the point of the - erase, including the `end()` iterator. - - @throw type_error.307 if called on a `null` value; example: `"cannot use - erase() with null"` - @throw invalid_iterator.203 if called on iterators which does not belong - to the current JSON value; example: `"iterators do not fit current value"` - @throw invalid_iterator.204 if called on a primitive type with invalid - iterators (i.e., if `first != begin()` and `last != end()`); example: - `"iterators out of range"` - - @complexity The complexity depends on the type: - - objects: `log(size()) + std::distance(first, last)` - - arrays: linear in the distance between @a first and @a last, plus linear - in the distance between @a last and end of the container - - strings and binary: linear in the length of the member - - other types: constant - - @liveexample{The example shows the result of `erase()` for different JSON - types.,erase__IteratorType_IteratorType} - - @sa @ref erase(IteratorType) -- removes the element at a given position - @sa @ref erase(const typename object_t::key_type&) -- removes the element - from an object at the given key - @sa @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 1.0.0 - */ - template < class IteratorType, typename std::enable_if < - std::is_same::value || - std::is_same::value, int >::type - = 0 > - IteratorType erase(IteratorType first, IteratorType last) - { - // make sure iterator fits the current value - if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object)) - { - JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value")); - } - - IteratorType result = end(); - - switch (m_type) - { - case value_t::boolean: - case value_t::number_float: - case value_t::number_integer: - case value_t::number_unsigned: - case value_t::string: - case value_t::binary: - { - if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin() - || !last.m_it.primitive_iterator.is_end())) - { - JSON_THROW(invalid_iterator::create(204, "iterators out of range")); - } - - if (is_string()) - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.string); - std::allocator_traits::deallocate(alloc, m_value.string, 1); - m_value.string = nullptr; - } - else if (is_binary()) - { - AllocatorType alloc; - std::allocator_traits::destroy(alloc, m_value.binary); - std::allocator_traits::deallocate(alloc, m_value.binary, 1); - m_value.binary = nullptr; - } - - m_type = value_t::null; - assert_invariant(); - break; - } - - case value_t::object: - { - result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator, - last.m_it.object_iterator); - break; - } - - case value_t::array: - { - result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator, - last.m_it.array_iterator); - break; - } - - default: - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); - } - - return result; - } - - /*! - @brief remove element from a JSON object given a key - - Removes elements from a JSON object with the key value @a key. - - @param[in] key value of the elements to remove - - @return Number of elements removed. If @a ObjectType is the default - `std::map` type, the return value will always be `0` (@a key was not - found) or `1` (@a key was found). - - @post References and iterators to the erased elements are invalidated. - Other references and iterators are not affected. - - @throw type_error.307 when called on a type other than JSON object; - example: `"cannot use erase() with null"` - - @complexity `log(size()) + count(key)` - - @liveexample{The example shows the effect of `erase()`.,erase__key_type} - - @sa @ref erase(IteratorType) -- removes the element at a given position - @sa @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa @ref erase(const size_type) -- removes the element from an array at - the given index - - @since version 1.0.0 - */ - size_type erase(const typename object_t::key_type& key) - { - // this erase only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - return m_value.object->erase(key); - } - - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); - } - - /*! - @brief remove element from a JSON array given an index - - Removes element from a JSON array at the index @a idx. - - @param[in] idx index of the element to remove - - @throw type_error.307 when called on a type other than JSON object; - example: `"cannot use erase() with null"` - @throw out_of_range.401 when `idx >= size()`; example: `"array index 17 - is out of range"` - - @complexity Linear in distance between @a idx and the end of the container. - - @liveexample{The example shows the effect of `erase()`.,erase__size_type} - - @sa @ref erase(IteratorType) -- removes the element at a given position - @sa @ref erase(IteratorType, IteratorType) -- removes the elements in - the given range - @sa @ref erase(const typename object_t::key_type&) -- removes the element - from an object at the given key - - @since version 1.0.0 - */ - void erase(const size_type idx) - { - // this erase only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - if (JSON_HEDLEY_UNLIKELY(idx >= size())) - { - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - - m_value.array->erase(m_value.array->begin() + static_cast(idx)); - } - else - { - JSON_THROW(type_error::create(307, "cannot use erase() with " + std::string(type_name()))); - } - } - - /// @} - - - //////////// - // lookup // - //////////// - - /// @name lookup - /// @{ - - /*! - @brief find an element in a JSON object - - Finds an element in a JSON object with key equivalent to @a key. If the - element is not found or the JSON value is not an object, end() is - returned. - - @note This method always returns @ref end() when executed on a JSON type - that is not an object. - - @param[in] key key value of the element to search for. - - @return Iterator to an element with key equivalent to @a key. If no such - element is found or the JSON value is not an object, past-the-end (see - @ref end()) iterator is returned. - - @complexity Logarithmic in the size of the JSON object. - - @liveexample{The example shows how `find()` is used.,find__key_type} - - @sa @ref contains(KeyT&&) const -- checks whether a key exists - - @since version 1.0.0 - */ - template - iterator find(KeyT&& key) - { - auto result = end(); - - if (is_object()) - { - result.m_it.object_iterator = m_value.object->find(std::forward(key)); - } - - return result; - } - - /*! - @brief find an element in a JSON object - @copydoc find(KeyT&&) - */ - template - const_iterator find(KeyT&& key) const - { - auto result = cend(); - - if (is_object()) - { - result.m_it.object_iterator = m_value.object->find(std::forward(key)); - } - - return result; - } - - /*! - @brief returns the number of occurrences of a key in a JSON object - - Returns the number of elements with key @a key. If ObjectType is the - default `std::map` type, the return value will always be `0` (@a key was - not found) or `1` (@a key was found). - - @note This method always returns `0` when executed on a JSON type that is - not an object. - - @param[in] key key value of the element to count - - @return Number of elements with key @a key. If the JSON value is not an - object, the return value will be `0`. - - @complexity Logarithmic in the size of the JSON object. - - @liveexample{The example shows how `count()` is used.,count} - - @since version 1.0.0 - */ - template - size_type count(KeyT&& key) const - { - // return 0 for all nonobject types - return is_object() ? m_value.object->count(std::forward(key)) : 0; - } - - /*! - @brief check the existence of an element in a JSON object - - Check whether an element exists in a JSON object with key equivalent to - @a key. If the element is not found or the JSON value is not an object, - false is returned. - - @note This method always returns false when executed on a JSON type - that is not an object. - - @param[in] key key value to check its existence. - - @return true if an element with specified @a key exists. If no such - element with such key is found or the JSON value is not an object, - false is returned. - - @complexity Logarithmic in the size of the JSON object. - - @liveexample{The following code shows an example for `contains()`.,contains} - - @sa @ref find(KeyT&&) -- returns an iterator to an object element - @sa @ref contains(const json_pointer&) const -- checks the existence for a JSON pointer - - @since version 3.6.0 - */ - template < typename KeyT, typename std::enable_if < - !std::is_same::type, json_pointer>::value, int >::type = 0 > - bool contains(KeyT && key) const - { - return is_object() && m_value.object->find(std::forward(key)) != m_value.object->end(); - } - - /*! - @brief check the existence of an element in a JSON object given a JSON pointer - - Check whether the given JSON pointer @a ptr can be resolved in the current - JSON value. - - @note This method can be executed on any JSON value type. - - @param[in] ptr JSON pointer to check its existence. - - @return true if the JSON pointer can be resolved to a stored value, false - otherwise. - - @post If `j.contains(ptr)` returns true, it is safe to call `j[ptr]`. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - - @complexity Logarithmic in the size of the JSON object. - - @liveexample{The following code shows an example for `contains()`.,contains_json_pointer} - - @sa @ref contains(KeyT &&) const -- checks the existence of a key - - @since version 3.7.0 - */ - bool contains(const json_pointer& ptr) const - { - return ptr.contains(this); - } - - /// @} - - - /////////////// - // iterators // - /////////////// - - /// @name iterators - /// @{ - - /*! - @brief returns an iterator to the first element - - Returns an iterator to the first element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return iterator to the first element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - @liveexample{The following code shows an example for `begin()`.,begin} - - @sa @ref cbegin() -- returns a const iterator to the beginning - @sa @ref end() -- returns an iterator to the end - @sa @ref cend() -- returns a const iterator to the end - - @since version 1.0.0 - */ - iterator begin() noexcept - { - iterator result(this); - result.set_begin(); - return result; - } - - /*! - @copydoc basic_json::cbegin() - */ - const_iterator begin() const noexcept - { - return cbegin(); - } - - /*! - @brief returns a const iterator to the first element - - Returns a const iterator to the first element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return const iterator to the first element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).begin()`. - - @liveexample{The following code shows an example for `cbegin()`.,cbegin} - - @sa @ref begin() -- returns an iterator to the beginning - @sa @ref end() -- returns an iterator to the end - @sa @ref cend() -- returns a const iterator to the end - - @since version 1.0.0 - */ - const_iterator cbegin() const noexcept - { - const_iterator result(this); - result.set_begin(); - return result; - } - - /*! - @brief returns an iterator to one past the last element - - Returns an iterator to one past the last element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return iterator one past the last element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - @liveexample{The following code shows an example for `end()`.,end} - - @sa @ref cend() -- returns a const iterator to the end - @sa @ref begin() -- returns an iterator to the beginning - @sa @ref cbegin() -- returns a const iterator to the beginning - - @since version 1.0.0 - */ - iterator end() noexcept - { - iterator result(this); - result.set_end(); - return result; - } - - /*! - @copydoc basic_json::cend() - */ - const_iterator end() const noexcept - { - return cend(); - } - - /*! - @brief returns a const iterator to one past the last element - - Returns a const iterator to one past the last element. - - @image html range-begin-end.svg "Illustration from cppreference.com" - - @return const iterator one past the last element - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).end()`. - - @liveexample{The following code shows an example for `cend()`.,cend} - - @sa @ref end() -- returns an iterator to the end - @sa @ref begin() -- returns an iterator to the beginning - @sa @ref cbegin() -- returns a const iterator to the beginning - - @since version 1.0.0 - */ - const_iterator cend() const noexcept - { - const_iterator result(this); - result.set_end(); - return result; - } - - /*! - @brief returns an iterator to the reverse-beginning - - Returns an iterator to the reverse-beginning; that is, the last element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `reverse_iterator(end())`. - - @liveexample{The following code shows an example for `rbegin()`.,rbegin} - - @sa @ref crbegin() -- returns a const reverse iterator to the beginning - @sa @ref rend() -- returns a reverse iterator to the end - @sa @ref crend() -- returns a const reverse iterator to the end - - @since version 1.0.0 - */ - reverse_iterator rbegin() noexcept - { - return reverse_iterator(end()); - } - - /*! - @copydoc basic_json::crbegin() - */ - const_reverse_iterator rbegin() const noexcept - { - return crbegin(); - } - - /*! - @brief returns an iterator to the reverse-end - - Returns an iterator to the reverse-end; that is, one before the first - element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `reverse_iterator(begin())`. - - @liveexample{The following code shows an example for `rend()`.,rend} - - @sa @ref crend() -- returns a const reverse iterator to the end - @sa @ref rbegin() -- returns a reverse iterator to the beginning - @sa @ref crbegin() -- returns a const reverse iterator to the beginning - - @since version 1.0.0 - */ - reverse_iterator rend() noexcept - { - return reverse_iterator(begin()); - } - - /*! - @copydoc basic_json::crend() - */ - const_reverse_iterator rend() const noexcept - { - return crend(); - } - - /*! - @brief returns a const reverse iterator to the last element - - Returns a const iterator to the reverse-beginning; that is, the last - element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).rbegin()`. - - @liveexample{The following code shows an example for `crbegin()`.,crbegin} - - @sa @ref rbegin() -- returns a reverse iterator to the beginning - @sa @ref rend() -- returns a reverse iterator to the end - @sa @ref crend() -- returns a const reverse iterator to the end - - @since version 1.0.0 - */ - const_reverse_iterator crbegin() const noexcept - { - return const_reverse_iterator(cend()); - } - - /*! - @brief returns a const reverse iterator to one before the first - - Returns a const reverse iterator to the reverse-end; that is, one before - the first element. - - @image html range-rbegin-rend.svg "Illustration from cppreference.com" - - @complexity Constant. - - @requirement This function helps `basic_json` satisfying the - [ReversibleContainer](https://en.cppreference.com/w/cpp/named_req/ReversibleContainer) - requirements: - - The complexity is constant. - - Has the semantics of `const_cast(*this).rend()`. - - @liveexample{The following code shows an example for `crend()`.,crend} - - @sa @ref rend() -- returns a reverse iterator to the end - @sa @ref rbegin() -- returns a reverse iterator to the beginning - @sa @ref crbegin() -- returns a const reverse iterator to the beginning - - @since version 1.0.0 - */ - const_reverse_iterator crend() const noexcept - { - return const_reverse_iterator(cbegin()); - } - - public: - /*! - @brief wrapper to access iterator member functions in range-based for - - This function allows to access @ref iterator::key() and @ref - iterator::value() during range-based for loops. In these loops, a - reference to the JSON values is returned, so there is no access to the - underlying iterator. - - For loop without iterator_wrapper: - - @code{cpp} - for (auto it = j_object.begin(); it != j_object.end(); ++it) - { - std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; - } - @endcode - - Range-based for loop without iterator proxy: - - @code{cpp} - for (auto it : j_object) - { - // "it" is of type json::reference and has no key() member - std::cout << "value: " << it << '\n'; - } - @endcode - - Range-based for loop with iterator proxy: - - @code{cpp} - for (auto it : json::iterator_wrapper(j_object)) - { - std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; - } - @endcode - - @note When iterating over an array, `key()` will return the index of the - element as string (see example). - - @param[in] ref reference to a JSON value - @return iteration proxy object wrapping @a ref with an interface to use in - range-based for loops - - @liveexample{The following code shows how the wrapper is used,iterator_wrapper} - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @note The name of this function is not yet final and may change in the - future. - - @deprecated This stream operator is deprecated and will be removed in - future 4.0.0 of the library. Please use @ref items() instead; - that is, replace `json::iterator_wrapper(j)` with `j.items()`. - */ - JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) - static iteration_proxy iterator_wrapper(reference ref) noexcept - { - return ref.items(); - } - - /*! - @copydoc iterator_wrapper(reference) - */ - JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items()) - static iteration_proxy iterator_wrapper(const_reference ref) noexcept - { - return ref.items(); - } - - /*! - @brief helper to access iterator member functions in range-based for - - This function allows to access @ref iterator::key() and @ref - iterator::value() during range-based for loops. In these loops, a - reference to the JSON values is returned, so there is no access to the - underlying iterator. - - For loop without `items()` function: - - @code{cpp} - for (auto it = j_object.begin(); it != j_object.end(); ++it) - { - std::cout << "key: " << it.key() << ", value:" << it.value() << '\n'; - } - @endcode - - Range-based for loop without `items()` function: - - @code{cpp} - for (auto it : j_object) - { - // "it" is of type json::reference and has no key() member - std::cout << "value: " << it << '\n'; - } - @endcode - - Range-based for loop with `items()` function: - - @code{cpp} - for (auto& el : j_object.items()) - { - std::cout << "key: " << el.key() << ", value:" << el.value() << '\n'; - } - @endcode - - The `items()` function also allows to use - [structured bindings](https://en.cppreference.com/w/cpp/language/structured_binding) - (C++17): - - @code{cpp} - for (auto& [key, val] : j_object.items()) - { - std::cout << "key: " << key << ", value:" << val << '\n'; - } - @endcode - - @note When iterating over an array, `key()` will return the index of the - element as string (see example). For primitive types (e.g., numbers), - `key()` returns an empty string. - - @warning Using `items()` on temporary objects is dangerous. Make sure the - object's lifetime exeeds the iteration. See - for more - information. - - @return iteration proxy object wrapping @a ref with an interface to use in - range-based for loops - - @liveexample{The following code shows how the function is used.,items} - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 3.1.0, structured bindings support since 3.5.0. - */ - iteration_proxy items() noexcept - { - return iteration_proxy(*this); - } - - /*! - @copydoc items() - */ - iteration_proxy items() const noexcept - { - return iteration_proxy(*this); - } - - /// @} - - - ////////////// - // capacity // - ////////////// - - /// @name capacity - /// @{ - - /*! - @brief checks whether the container is empty. - - Checks if a JSON value has no elements (i.e. whether its @ref size is `0`). - - @return The return value depends on the different types and is - defined as follows: - Value type | return value - ----------- | ------------- - null | `true` - boolean | `false` - string | `false` - number | `false` - binary | `false` - object | result of function `object_t::empty()` - array | result of function `array_t::empty()` - - @liveexample{The following code uses `empty()` to check if a JSON - object contains any elements.,empty} - - @complexity Constant, as long as @ref array_t and @ref object_t satisfy - the Container concept; that is, their `empty()` functions have constant - complexity. - - @iterators No changes. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @note This function does not return whether a string stored as JSON value - is empty - it returns whether the JSON container itself is empty which is - false in the case of a string. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - Has the semantics of `begin() == end()`. - - @sa @ref size() -- returns the number of elements - - @since version 1.0.0 - */ - bool empty() const noexcept - { - switch (m_type) - { - case value_t::null: - { - // null values are empty - return true; - } - - case value_t::array: - { - // delegate call to array_t::empty() - return m_value.array->empty(); - } - - case value_t::object: - { - // delegate call to object_t::empty() - return m_value.object->empty(); - } - - default: - { - // all other types are nonempty - return false; - } - } - } - - /*! - @brief returns the number of elements - - Returns the number of elements in a JSON value. - - @return The return value depends on the different types and is - defined as follows: - Value type | return value - ----------- | ------------- - null | `0` - boolean | `1` - string | `1` - number | `1` - binary | `1` - object | result of function object_t::size() - array | result of function array_t::size() - - @liveexample{The following code calls `size()` on the different value - types.,size} - - @complexity Constant, as long as @ref array_t and @ref object_t satisfy - the Container concept; that is, their size() functions have constant - complexity. - - @iterators No changes. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @note This function does not return the length of a string stored as JSON - value - it returns the number of elements in the JSON value which is 1 in - the case of a string. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - Has the semantics of `std::distance(begin(), end())`. - - @sa @ref empty() -- checks whether the container is empty - @sa @ref max_size() -- returns the maximal number of elements - - @since version 1.0.0 - */ - size_type size() const noexcept - { - switch (m_type) - { - case value_t::null: - { - // null values are empty - return 0; - } - - case value_t::array: - { - // delegate call to array_t::size() - return m_value.array->size(); - } - - case value_t::object: - { - // delegate call to object_t::size() - return m_value.object->size(); - } - - default: - { - // all other types have size 1 - return 1; - } - } - } - - /*! - @brief returns the maximum possible number of elements - - Returns the maximum number of elements a JSON value is able to hold due to - system or library implementation limitations, i.e. `std::distance(begin(), - end())` for the JSON value. - - @return The return value depends on the different types and is - defined as follows: - Value type | return value - ----------- | ------------- - null | `0` (same as `size()`) - boolean | `1` (same as `size()`) - string | `1` (same as `size()`) - number | `1` (same as `size()`) - binary | `1` (same as `size()`) - object | result of function `object_t::max_size()` - array | result of function `array_t::max_size()` - - @liveexample{The following code calls `max_size()` on the different value - types. Note the output is implementation specific.,max_size} - - @complexity Constant, as long as @ref array_t and @ref object_t satisfy - the Container concept; that is, their `max_size()` functions have constant - complexity. - - @iterators No changes. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @requirement This function helps `basic_json` satisfying the - [Container](https://en.cppreference.com/w/cpp/named_req/Container) - requirements: - - The complexity is constant. - - Has the semantics of returning `b.size()` where `b` is the largest - possible JSON value. - - @sa @ref size() -- returns the number of elements - - @since version 1.0.0 - */ - size_type max_size() const noexcept - { - switch (m_type) - { - case value_t::array: - { - // delegate call to array_t::max_size() - return m_value.array->max_size(); - } - - case value_t::object: - { - // delegate call to object_t::max_size() - return m_value.object->max_size(); - } - - default: - { - // all other types have max_size() == size() - return size(); - } - } - } - - /// @} - - - /////////////// - // modifiers // - /////////////// - - /// @name modifiers - /// @{ - - /*! - @brief clears the contents - - Clears the content of a JSON value and resets it to the default value as - if @ref basic_json(value_t) would have been called with the current value - type from @ref type(): - - Value type | initial value - ----------- | ------------- - null | `null` - boolean | `false` - string | `""` - number | `0` - binary | An empty byte vector - object | `{}` - array | `[]` - - @post Has the same effect as calling - @code {.cpp} - *this = basic_json(type()); - @endcode - - @liveexample{The example below shows the effect of `clear()` to different - JSON types.,clear} - - @complexity Linear in the size of the JSON value. - - @iterators All iterators, pointers and references related to this container - are invalidated. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @sa @ref basic_json(value_t) -- constructor that creates an object with the - same value than calling `clear()` - - @since version 1.0.0 - */ - void clear() noexcept - { - switch (m_type) - { - case value_t::number_integer: - { - m_value.number_integer = 0; - break; - } - - case value_t::number_unsigned: - { - m_value.number_unsigned = 0; - break; - } - - case value_t::number_float: - { - m_value.number_float = 0.0; - break; - } - - case value_t::boolean: - { - m_value.boolean = false; - break; - } - - case value_t::string: - { - m_value.string->clear(); - break; - } - - case value_t::binary: - { - m_value.binary->clear(); - break; - } - - case value_t::array: - { - m_value.array->clear(); - break; - } - - case value_t::object: - { - m_value.object->clear(); - break; - } - - default: - break; - } - } - - /*! - @brief add an object to an array - - Appends the given element @a val to the end of the JSON value. If the - function is called on a JSON null value, an empty array is created before - appending @a val. - - @param[in] val the value to add to the JSON array - - @throw type_error.308 when called on a type other than JSON array or - null; example: `"cannot use push_back() with number"` - - @complexity Amortized constant. - - @liveexample{The example shows how `push_back()` and `+=` can be used to - add elements to a JSON array. Note how the `null` value was silently - converted to a JSON array.,push_back} - - @since version 1.0.0 - */ - void push_back(basic_json&& val) - { - // push_back only works for null objects or arrays - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); - } - - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array (move semantics) - m_value.array->push_back(std::move(val)); - // if val is moved from, basic_json move constructor marks it null so we do not call the destructor - } - - /*! - @brief add an object to an array - @copydoc push_back(basic_json&&) - */ - reference operator+=(basic_json&& val) - { - push_back(std::move(val)); - return *this; - } - - /*! - @brief add an object to an array - @copydoc push_back(basic_json&&) - */ - void push_back(const basic_json& val) - { - // push_back only works for null objects or arrays - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); - } - - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array - m_value.array->push_back(val); - } - - /*! - @brief add an object to an array - @copydoc push_back(basic_json&&) - */ - reference operator+=(const basic_json& val) - { - push_back(val); - return *this; - } - - /*! - @brief add an object to an object - - Inserts the given element @a val to the JSON object. If the function is - called on a JSON null value, an empty object is created before inserting - @a val. - - @param[in] val the value to add to the JSON object - - @throw type_error.308 when called on a type other than JSON object or - null; example: `"cannot use push_back() with number"` - - @complexity Logarithmic in the size of the container, O(log(`size()`)). - - @liveexample{The example shows how `push_back()` and `+=` can be used to - add elements to a JSON object. Note how the `null` value was silently - converted to a JSON object.,push_back__object_t__value} - - @since version 1.0.0 - */ - void push_back(const typename object_t::value_type& val) - { - // push_back only works for null objects or objects - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) - { - JSON_THROW(type_error::create(308, "cannot use push_back() with " + std::string(type_name()))); - } - - // transform null object into an object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); - } - - // add element to array - m_value.object->insert(val); - } - - /*! - @brief add an object to an object - @copydoc push_back(const typename object_t::value_type&) - */ - reference operator+=(const typename object_t::value_type& val) - { - push_back(val); - return *this; - } - - /*! - @brief add an object to an object - - This function allows to use `push_back` with an initializer list. In case - - 1. the current value is an object, - 2. the initializer list @a init contains only two elements, and - 3. the first element of @a init is a string, - - @a init is converted into an object element and added using - @ref push_back(const typename object_t::value_type&). Otherwise, @a init - is converted to a JSON value and added using @ref push_back(basic_json&&). - - @param[in] init an initializer list - - @complexity Linear in the size of the initializer list @a init. - - @note This function is required to resolve an ambiguous overload error, - because pairs like `{"key", "value"}` can be both interpreted as - `object_t::value_type` or `std::initializer_list`, see - https://github.com/nlohmann/json/issues/235 for more information. - - @liveexample{The example shows how initializer lists are treated as - objects when possible.,push_back__initializer_list} - */ - void push_back(initializer_list_t init) - { - if (is_object() && init.size() == 2 && (*init.begin())->is_string()) - { - basic_json&& key = init.begin()->moved_or_copied(); - push_back(typename object_t::value_type( - std::move(key.get_ref()), (init.begin() + 1)->moved_or_copied())); - } - else - { - push_back(basic_json(init)); - } - } - - /*! - @brief add an object to an object - @copydoc push_back(initializer_list_t) - */ - reference operator+=(initializer_list_t init) - { - push_back(init); - return *this; - } - - /*! - @brief add an object to an array - - Creates a JSON value from the passed parameters @a args to the end of the - JSON value. If the function is called on a JSON null value, an empty array - is created before appending the value created from @a args. - - @param[in] args arguments to forward to a constructor of @ref basic_json - @tparam Args compatible types to create a @ref basic_json object - - @return reference to the inserted element - - @throw type_error.311 when called on a type other than JSON array or - null; example: `"cannot use emplace_back() with number"` - - @complexity Amortized constant. - - @liveexample{The example shows how `push_back()` can be used to add - elements to a JSON array. Note how the `null` value was silently converted - to a JSON array.,emplace_back} - - @since version 2.0.8, returns reference since 3.7.0 - */ - template - reference emplace_back(Args&& ... args) - { - // emplace_back only works for null objects or arrays - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array()))) - { - JSON_THROW(type_error::create(311, "cannot use emplace_back() with " + std::string(type_name()))); - } - - // transform null object into an array - if (is_null()) - { - m_type = value_t::array; - m_value = value_t::array; - assert_invariant(); - } - - // add element to array (perfect forwarding) -#ifdef JSON_HAS_CPP_17 - return m_value.array->emplace_back(std::forward(args)...); -#else - m_value.array->emplace_back(std::forward(args)...); - return m_value.array->back(); -#endif - } - - /*! - @brief add an object to an object if key does not exist - - Inserts a new element into a JSON object constructed in-place with the - given @a args if there is no element with the key in the container. If the - function is called on a JSON null value, an empty object is created before - appending the value created from @a args. - - @param[in] args arguments to forward to a constructor of @ref basic_json - @tparam Args compatible types to create a @ref basic_json object - - @return a pair consisting of an iterator to the inserted element, or the - already-existing element if no insertion happened, and a bool - denoting whether the insertion took place. - - @throw type_error.311 when called on a type other than JSON object or - null; example: `"cannot use emplace() with number"` - - @complexity Logarithmic in the size of the container, O(log(`size()`)). - - @liveexample{The example shows how `emplace()` can be used to add elements - to a JSON object. Note how the `null` value was silently converted to a - JSON object. Further note how no value is added if there was already one - value stored with the same key.,emplace} - - @since version 2.0.8 - */ - template - std::pair emplace(Args&& ... args) - { - // emplace only works for null objects or arrays - if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object()))) - { - JSON_THROW(type_error::create(311, "cannot use emplace() with " + std::string(type_name()))); - } - - // transform null object into an object - if (is_null()) - { - m_type = value_t::object; - m_value = value_t::object; - assert_invariant(); - } - - // add element to array (perfect forwarding) - auto res = m_value.object->emplace(std::forward(args)...); - // create result iterator and set iterator to the result of emplace - auto it = begin(); - it.m_it.object_iterator = res.first; - - // return pair of iterator and boolean - return {it, res.second}; - } - - /// Helper for insertion of an iterator - /// @note: This uses std::distance to support GCC 4.8, - /// see https://github.com/nlohmann/json/pull/1257 - template - iterator insert_iterator(const_iterator pos, Args&& ... args) - { - iterator result(this); - JSON_ASSERT(m_value.array != nullptr); - - auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator); - m_value.array->insert(pos.m_it.array_iterator, std::forward(args)...); - result.m_it.array_iterator = m_value.array->begin() + insert_pos; - - // This could have been written as: - // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val); - // but the return value of insert is missing in GCC 4.8, so it is written this way instead. - - return result; - } - - /*! - @brief inserts element - - Inserts element @a val before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] val element to insert - @return iterator pointing to the inserted @a val. - - @throw type_error.309 if called on JSON values other than arrays; - example: `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - - @complexity Constant plus linear in the distance between @a pos and end of - the container. - - @liveexample{The example shows how `insert()` is used.,insert} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, const basic_json& val) - { - // insert only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - // check if iterator pos fits to this JSON value - if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // insert to array and return iterator - return insert_iterator(pos, val); - } - - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); - } - - /*! - @brief inserts element - @copydoc insert(const_iterator, const basic_json&) - */ - iterator insert(const_iterator pos, basic_json&& val) - { - return insert(pos, val); - } - - /*! - @brief inserts elements - - Inserts @a cnt copies of @a val before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] cnt number of copies of @a val to insert - @param[in] val element to insert - @return iterator pointing to the first element inserted, or @a pos if - `cnt==0` - - @throw type_error.309 if called on JSON values other than arrays; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - - @complexity Linear in @a cnt plus linear in the distance between @a pos - and end of the container. - - @liveexample{The example shows how `insert()` is used.,insert__count} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, size_type cnt, const basic_json& val) - { - // insert only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - // check if iterator pos fits to this JSON value - if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // insert to array and return iterator - return insert_iterator(pos, cnt, val); - } - - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); - } - - /*! - @brief inserts elements - - Inserts elements from range `[first, last)` before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] first begin of the range of elements to insert - @param[in] last end of the range of elements to insert - - @throw type_error.309 if called on JSON values other than arrays; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - @throw invalid_iterator.210 if @a first and @a last do not belong to the - same JSON value; example: `"iterators do not fit"` - @throw invalid_iterator.211 if @a first or @a last are iterators into - container for which insert is called; example: `"passed iterators may not - belong to container"` - - @return iterator pointing to the first element inserted, or @a pos if - `first==last` - - @complexity Linear in `std::distance(first, last)` plus linear in the - distance between @a pos and end of the container. - - @liveexample{The example shows how `insert()` is used.,insert__range} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, const_iterator first, const_iterator last) - { - // insert only works for arrays - if (JSON_HEDLEY_UNLIKELY(!is_array())) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); - } - - // check if iterator pos fits to this JSON value - if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // check if range iterators belong to the same JSON object - if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) - { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); - } - - if (JSON_HEDLEY_UNLIKELY(first.m_object == this)) - { - JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container")); - } - - // insert to array and return iterator - return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator); - } - - /*! - @brief inserts elements - - Inserts elements from initializer list @a ilist before iterator @a pos. - - @param[in] pos iterator before which the content will be inserted; may be - the end() iterator - @param[in] ilist initializer list to insert the values from - - @throw type_error.309 if called on JSON values other than arrays; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if @a pos is not an iterator of *this; - example: `"iterator does not fit current value"` - - @return iterator pointing to the first element inserted, or @a pos if - `ilist` is empty - - @complexity Linear in `ilist.size()` plus linear in the distance between - @a pos and end of the container. - - @liveexample{The example shows how `insert()` is used.,insert__ilist} - - @since version 1.0.0 - */ - iterator insert(const_iterator pos, initializer_list_t ilist) - { - // insert only works for arrays - if (JSON_HEDLEY_UNLIKELY(!is_array())) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); - } - - // check if iterator pos fits to this JSON value - if (JSON_HEDLEY_UNLIKELY(pos.m_object != this)) - { - JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value")); - } - - // insert to array and return iterator - return insert_iterator(pos, ilist.begin(), ilist.end()); - } - - /*! - @brief inserts elements - - Inserts elements from range `[first, last)`. - - @param[in] first begin of the range of elements to insert - @param[in] last end of the range of elements to insert - - @throw type_error.309 if called on JSON values other than objects; example: - `"cannot use insert() with string"` - @throw invalid_iterator.202 if iterator @a first or @a last does does not - point to an object; example: `"iterators first and last must point to - objects"` - @throw invalid_iterator.210 if @a first and @a last do not belong to the - same JSON value; example: `"iterators do not fit"` - - @complexity Logarithmic: `O(N*log(size() + N))`, where `N` is the number - of elements to insert. - - @liveexample{The example shows how `insert()` is used.,insert__range_object} - - @since version 3.0.0 - */ - void insert(const_iterator first, const_iterator last) - { - // insert only works for objects - if (JSON_HEDLEY_UNLIKELY(!is_object())) - { - JSON_THROW(type_error::create(309, "cannot use insert() with " + std::string(type_name()))); - } - - // check if range iterators belong to the same JSON object - if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) - { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); - } - - // passed iterators must belong to objects - if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object())) - { - JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); - } - - m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator); - } - - /*! - @brief updates a JSON object from another object, overwriting existing keys - - Inserts all values from JSON object @a j and overwrites existing keys. - - @param[in] j JSON object to read values from - - @throw type_error.312 if called on JSON values other than objects; example: - `"cannot use update() with string"` - - @complexity O(N*log(size() + N)), where N is the number of elements to - insert. - - @liveexample{The example shows how `update()` is used.,update} - - @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update - - @since version 3.0.0 - */ - void update(const_reference j) - { - // implicitly convert null value to an empty object - if (is_null()) - { - m_type = value_t::object; - m_value.object = create(); - assert_invariant(); - } - - if (JSON_HEDLEY_UNLIKELY(!is_object())) - { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()))); - } - if (JSON_HEDLEY_UNLIKELY(!j.is_object())) - { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(j.type_name()))); - } - - for (auto it = j.cbegin(); it != j.cend(); ++it) - { - m_value.object->operator[](it.key()) = it.value(); - } - } - - /*! - @brief updates a JSON object from another object, overwriting existing keys - - Inserts all values from from range `[first, last)` and overwrites existing - keys. - - @param[in] first begin of the range of elements to insert - @param[in] last end of the range of elements to insert - - @throw type_error.312 if called on JSON values other than objects; example: - `"cannot use update() with string"` - @throw invalid_iterator.202 if iterator @a first or @a last does does not - point to an object; example: `"iterators first and last must point to - objects"` - @throw invalid_iterator.210 if @a first and @a last do not belong to the - same JSON value; example: `"iterators do not fit"` - - @complexity O(N*log(size() + N)), where N is the number of elements to - insert. - - @liveexample{The example shows how `update()` is used__range.,update} - - @sa https://docs.python.org/3.6/library/stdtypes.html#dict.update - - @since version 3.0.0 - */ - void update(const_iterator first, const_iterator last) - { - // implicitly convert null value to an empty object - if (is_null()) - { - m_type = value_t::object; - m_value.object = create(); - assert_invariant(); - } - - if (JSON_HEDLEY_UNLIKELY(!is_object())) - { - JSON_THROW(type_error::create(312, "cannot use update() with " + std::string(type_name()))); - } - - // check if range iterators belong to the same JSON object - if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object)) - { - JSON_THROW(invalid_iterator::create(210, "iterators do not fit")); - } - - // passed iterators must belong to objects - if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object() - || !last.m_object->is_object())) - { - JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects")); - } - - for (auto it = first; it != last; ++it) - { - m_value.object->operator[](it.key()) = it.value(); - } - } - - /*! - @brief exchanges the values - - Exchanges the contents of the JSON value with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other JSON value to exchange the contents with - - @complexity Constant. - - @liveexample{The example below shows how JSON values can be swapped with - `swap()`.,swap__reference} - - @since version 1.0.0 - */ - void swap(reference other) noexcept ( - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value - ) - { - std::swap(m_type, other.m_type); - std::swap(m_value, other.m_value); - assert_invariant(); - } - - /*! - @brief exchanges the values - - Exchanges the contents of the JSON value from @a left with those of @a right. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. implemented as a friend function callable via ADL. - - @param[in,out] left JSON value to exchange the contents with - @param[in,out] right JSON value to exchange the contents with - - @complexity Constant. - - @liveexample{The example below shows how JSON values can be swapped with - `swap()`.,swap__reference} - - @since version 1.0.0 - */ - friend void swap(reference left, reference right) noexcept ( - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value&& - std::is_nothrow_move_constructible::value&& - std::is_nothrow_move_assignable::value - ) - { - left.swap(right); - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON array with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other array to exchange the contents with - - @throw type_error.310 when JSON value is not an array; example: `"cannot - use swap() with string"` - - @complexity Constant. - - @liveexample{The example below shows how arrays can be swapped with - `swap()`.,swap__array_t} - - @since version 1.0.0 - */ - void swap(array_t& other) - { - // swap only works for arrays - if (JSON_HEDLEY_LIKELY(is_array())) - { - std::swap(*(m_value.array), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); - } - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON object with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other object to exchange the contents with - - @throw type_error.310 when JSON value is not an object; example: - `"cannot use swap() with string"` - - @complexity Constant. - - @liveexample{The example below shows how objects can be swapped with - `swap()`.,swap__object_t} - - @since version 1.0.0 - */ - void swap(object_t& other) - { - // swap only works for objects - if (JSON_HEDLEY_LIKELY(is_object())) - { - std::swap(*(m_value.object), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); - } - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON string with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other string to exchange the contents with - - @throw type_error.310 when JSON value is not a string; example: `"cannot - use swap() with boolean"` - - @complexity Constant. - - @liveexample{The example below shows how strings can be swapped with - `swap()`.,swap__string_t} - - @since version 1.0.0 - */ - void swap(string_t& other) - { - // swap only works for strings - if (JSON_HEDLEY_LIKELY(is_string())) - { - std::swap(*(m_value.string), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); - } - } - - /*! - @brief exchanges the values - - Exchanges the contents of a JSON string with those of @a other. Does not - invoke any move, copy, or swap operations on individual elements. All - iterators and references remain valid. The past-the-end iterator is - invalidated. - - @param[in,out] other binary to exchange the contents with - - @throw type_error.310 when JSON value is not a string; example: `"cannot - use swap() with boolean"` - - @complexity Constant. - - @liveexample{The example below shows how strings can be swapped with - `swap()`.,swap__binary_t} - - @since version 3.8.0 - */ - void swap(binary_t& other) - { - // swap only works for strings - if (JSON_HEDLEY_LIKELY(is_binary())) - { - std::swap(*(m_value.binary), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); - } - } - - /// @copydoc swap(binary_t) - void swap(typename binary_t::container_type& other) - { - // swap only works for strings - if (JSON_HEDLEY_LIKELY(is_binary())) - { - std::swap(*(m_value.binary), other); - } - else - { - JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name()))); - } - } - - /// @} - - public: - ////////////////////////////////////////// - // lexicographical comparison operators // - ////////////////////////////////////////// - - /// @name lexicographical comparison operators - /// @{ - - /*! - @brief comparison: equal - - Compares two JSON values for equality according to the following rules: - - Two JSON values are equal if (1) they are from the same type and (2) - their stored values are the same according to their respective - `operator==`. - - Integer and floating-point numbers are automatically converted before - comparison. Note that two NaN values are always treated as unequal. - - Two JSON null values are equal. - - @note Floating-point inside JSON values numbers are compared with - `json::number_float_t::operator==` which is `double::operator==` by - default. To compare floating-point while respecting an epsilon, an alternative - [comparison function](https://github.com/mariokonrad/marnav/blob/master/include/marnav/math/floatingpoint.hpp#L34-#L39) - could be used, for instance - @code {.cpp} - template::value, T>::type> - inline bool is_same(T a, T b, T epsilon = std::numeric_limits::epsilon()) noexcept - { - return std::abs(a - b) <= epsilon; - } - @endcode - Or you can self-defined operator equal function like this: - @code {.cpp} - bool my_equal(const_reference lhs, const_reference rhs) { - const auto lhs_type lhs.type(); - const auto rhs_type rhs.type(); - if (lhs_type == rhs_type) { - switch(lhs_type) - // self_defined case - case value_t::number_float: - return std::abs(lhs - rhs) <= std::numeric_limits::epsilon(); - // other cases remain the same with the original - ... - } - ... - } - @endcode - - @note NaN values never compare equal to themselves or to other NaN values. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether the values @a lhs and @a rhs are equal - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @complexity Linear. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__equal} - - @since version 1.0.0 - */ - friend bool operator==(const_reference lhs, const_reference rhs) noexcept - { - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); - - if (lhs_type == rhs_type) - { - switch (lhs_type) - { - case value_t::array: - return *lhs.m_value.array == *rhs.m_value.array; - - case value_t::object: - return *lhs.m_value.object == *rhs.m_value.object; - - case value_t::null: - return true; - - case value_t::string: - return *lhs.m_value.string == *rhs.m_value.string; - - case value_t::boolean: - return lhs.m_value.boolean == rhs.m_value.boolean; - - case value_t::number_integer: - return lhs.m_value.number_integer == rhs.m_value.number_integer; - - case value_t::number_unsigned: - return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned; - - case value_t::number_float: - return lhs.m_value.number_float == rhs.m_value.number_float; - - case value_t::binary: - return *lhs.m_value.binary == *rhs.m_value.binary; - - default: - return false; - } - } - else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_integer) == rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) - { - return lhs.m_value.number_float == static_cast(rhs.m_value.number_integer); - } - else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_float == static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) - { - return static_cast(lhs.m_value.number_unsigned) == rhs.m_value.number_integer; - } - else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_integer == static_cast(rhs.m_value.number_unsigned); - } - - return false; - } - - /*! - @brief comparison: equal - @copydoc operator==(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs == basic_json(rhs); - } - - /*! - @brief comparison: equal - @copydoc operator==(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) == rhs; - } - - /*! - @brief comparison: not equal - - Compares two JSON values for inequality by calculating `not (lhs == rhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether the values @a lhs and @a rhs are not equal - - @complexity Linear. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__notequal} - - @since version 1.0.0 - */ - friend bool operator!=(const_reference lhs, const_reference rhs) noexcept - { - return !(lhs == rhs); - } - - /*! - @brief comparison: not equal - @copydoc operator!=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs != basic_json(rhs); - } - - /*! - @brief comparison: not equal - @copydoc operator!=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) != rhs; - } - - /*! - @brief comparison: less than - - Compares whether one JSON value @a lhs is less than another JSON value @a - rhs according to the following rules: - - If @a lhs and @a rhs have the same type, the values are compared using - the default `<` operator. - - Integer and floating-point numbers are automatically converted before - comparison - - In case @a lhs and @a rhs have different types, the values are ignored - and the order of the types is considered, see - @ref operator<(const value_t, const value_t). - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is less than @a rhs - - @complexity Linear. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__less} - - @since version 1.0.0 - */ - friend bool operator<(const_reference lhs, const_reference rhs) noexcept - { - const auto lhs_type = lhs.type(); - const auto rhs_type = rhs.type(); - - if (lhs_type == rhs_type) - { - switch (lhs_type) - { - case value_t::array: - // note parentheses are necessary, see - // https://github.com/nlohmann/json/issues/1530 - return (*lhs.m_value.array) < (*rhs.m_value.array); - - case value_t::object: - return (*lhs.m_value.object) < (*rhs.m_value.object); - - case value_t::null: - return false; - - case value_t::string: - return (*lhs.m_value.string) < (*rhs.m_value.string); - - case value_t::boolean: - return (lhs.m_value.boolean) < (rhs.m_value.boolean); - - case value_t::number_integer: - return (lhs.m_value.number_integer) < (rhs.m_value.number_integer); - - case value_t::number_unsigned: - return (lhs.m_value.number_unsigned) < (rhs.m_value.number_unsigned); - - case value_t::number_float: - return (lhs.m_value.number_float) < (rhs.m_value.number_float); - - case value_t::binary: - return (*lhs.m_value.binary) < (*rhs.m_value.binary); - - default: - return false; - } - } - else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_integer) < rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) - { - return lhs.m_value.number_float < static_cast(rhs.m_value.number_integer); - } - else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) - { - return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_float; - } - else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_float < static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) - { - return lhs.m_value.number_integer < static_cast(rhs.m_value.number_unsigned); - } - else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) - { - return static_cast(lhs.m_value.number_unsigned) < rhs.m_value.number_integer; - } - - // We only reach this line if we cannot compare values. In that case, - // we compare types. Note we have to call the operator explicitly, - // because MSVC has problems otherwise. - return operator<(lhs_type, rhs_type); - } - - /*! - @brief comparison: less than - @copydoc operator<(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs < basic_json(rhs); - } - - /*! - @brief comparison: less than - @copydoc operator<(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) < rhs; - } - - /*! - @brief comparison: less than or equal - - Compares whether one JSON value @a lhs is less than or equal to another - JSON value by calculating `not (rhs < lhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is less than or equal to @a rhs - - @complexity Linear. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__greater} - - @since version 1.0.0 - */ - friend bool operator<=(const_reference lhs, const_reference rhs) noexcept - { - return !(rhs < lhs); - } - - /*! - @brief comparison: less than or equal - @copydoc operator<=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs <= basic_json(rhs); - } - - /*! - @brief comparison: less than or equal - @copydoc operator<=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) <= rhs; - } - - /*! - @brief comparison: greater than - - Compares whether one JSON value @a lhs is greater than another - JSON value by calculating `not (lhs <= rhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is greater than to @a rhs - - @complexity Linear. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__lessequal} - - @since version 1.0.0 - */ - friend bool operator>(const_reference lhs, const_reference rhs) noexcept - { - return !(lhs <= rhs); - } - - /*! - @brief comparison: greater than - @copydoc operator>(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs > basic_json(rhs); - } - - /*! - @brief comparison: greater than - @copydoc operator>(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) > rhs; - } - - /*! - @brief comparison: greater than or equal - - Compares whether one JSON value @a lhs is greater than or equal to another - JSON value by calculating `not (lhs < rhs)`. - - @param[in] lhs first JSON value to consider - @param[in] rhs second JSON value to consider - @return whether @a lhs is greater than or equal to @a rhs - - @complexity Linear. - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @liveexample{The example demonstrates comparing several JSON - types.,operator__greaterequal} - - @since version 1.0.0 - */ - friend bool operator>=(const_reference lhs, const_reference rhs) noexcept - { - return !(lhs < rhs); - } - - /*! - @brief comparison: greater than or equal - @copydoc operator>=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept - { - return lhs >= basic_json(rhs); - } - - /*! - @brief comparison: greater than or equal - @copydoc operator>=(const_reference, const_reference) - */ - template::value, int>::type = 0> - friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept - { - return basic_json(lhs) >= rhs; - } - - /// @} - - /////////////////// - // serialization // - /////////////////// - - /// @name serialization - /// @{ - - /*! - @brief serialize to stream - - Serialize the given JSON value @a j to the output stream @a o. The JSON - value will be serialized using the @ref dump member function. - - - The indentation of the output can be controlled with the member variable - `width` of the output stream @a o. For instance, using the manipulator - `std::setw(4)` on @a o sets the indentation level to `4` and the - serialization result is the same as calling `dump(4)`. - - - The indentation character can be controlled with the member variable - `fill` of the output stream @a o. For instance, the manipulator - `std::setfill('\\t')` sets indentation to use a tab character rather than - the default space character. - - @param[in,out] o stream to serialize to - @param[in] j JSON value to serialize - - @return the stream @a o - - @throw type_error.316 if a string stored inside the JSON value is not - UTF-8 encoded - - @complexity Linear. - - @liveexample{The example below shows the serialization with different - parameters to `width` to adjust the indentation level.,operator_serialize} - - @since version 1.0.0; indentation character added in version 3.0.0 - */ - friend std::ostream& operator<<(std::ostream& o, const basic_json& j) - { - // read width member and use it as indentation parameter if nonzero - const bool pretty_print = o.width() > 0; - const auto indentation = pretty_print ? o.width() : 0; - - // reset width to 0 for subsequent calls to this stream - o.width(0); - - // do the actual serialization - serializer s(detail::output_adapter(o), o.fill()); - s.dump(j, pretty_print, false, static_cast(indentation)); - return o; - } - - /*! - @brief serialize to stream - @deprecated This stream operator is deprecated and will be removed in - future 4.0.0 of the library. Please use - @ref operator<<(std::ostream&, const basic_json&) - instead; that is, replace calls like `j >> o;` with `o << j;`. - @since version 1.0.0; deprecated since version 3.0.0 - */ - JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&)) - friend std::ostream& operator>>(const basic_json& j, std::ostream& o) - { - return o << j; - } - - /// @} - - - ///////////////////// - // deserialization // - ///////////////////// - - /// @name deserialization - /// @{ - - /*! - @brief deserialize from a compatible input - - @tparam InputType A compatible input, for instance - - an std::istream object - - a FILE pointer - - a C-style array of characters - - a pointer to a null-terminated string of single byte characters - - an object obj for which begin(obj) and end(obj) produces a valid pair of - iterators. - - @param[in] i input to read from - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - @param[in] ignore_comments whether comments should be ignored and treated - like whitespace (true) or yield a parse error (true); (optional, false by - default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.101 if a parse error occurs; example: `""unexpected end - of input; expected string literal""` - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the parser callback function - @a cb or reading from the input @a i has a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `parse()` function reading - from an array.,parse__array__parser_callback_t} - - @liveexample{The example below demonstrates the `parse()` function with - and without callback function.,parse__string__parser_callback_t} - - @liveexample{The example below demonstrates the `parse()` function with - and without callback function.,parse__istream__parser_callback_t} - - @liveexample{The example below demonstrates the `parse()` function reading - from a contiguous container.,parse__contiguouscontainer__parser_callback_t} - - @since version 2.0.3 (contiguous containers); version 3.9.0 allowed to - ignore comments. - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json parse(InputType&& i, - const parser_callback_t cb = nullptr, - const bool allow_exceptions = true, - const bool ignore_comments = false) - { - basic_json result; - parser(detail::input_adapter(std::forward(i)), cb, allow_exceptions, ignore_comments).parse(true, result); - return result; - } - - /*! - @brief deserialize from a pair of character iterators - - The value_type of the iterator must be a integral type with size of 1, 2 or - 4 bytes, which will be interpreted respectively as UTF-8, UTF-16 and UTF-32. - - @param[in] first iterator to start of character range - @param[in] last iterator to end of character range - @param[in] cb a parser callback function of type @ref parser_callback_t - which is used to control the deserialization by filtering unwanted values - (optional) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - @param[in] ignore_comments whether comments should be ignored and treated - like whitespace (true) or yield a parse error (true); (optional, false by - default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.101 if a parse error occurs; example: `""unexpected end - of input; expected string literal""` - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json parse(IteratorType first, - IteratorType last, - const parser_callback_t cb = nullptr, - const bool allow_exceptions = true, - const bool ignore_comments = false) - { - basic_json result; - parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result); - return result; - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len)) - static basic_json parse(detail::span_input_adapter&& i, - const parser_callback_t cb = nullptr, - const bool allow_exceptions = true, - const bool ignore_comments = false) - { - basic_json result; - parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result); - return result; - } - - /*! - @brief check if the input is valid JSON - - Unlike the @ref parse(InputType&&, const parser_callback_t,const bool) - function, this function neither throws an exception in case of invalid JSON - input (i.e., a parse error) nor creates diagnostic information. - - @tparam InputType A compatible input, for instance - - an std::istream object - - a FILE pointer - - a C-style array of characters - - a pointer to a null-terminated string of single byte characters - - an object obj for which begin(obj) and end(obj) produces a valid pair of - iterators. - - @param[in] i input to read from - @param[in] ignore_comments whether comments should be ignored and treated - like whitespace (true) or yield a parse error (true); (optional, false by - default) - - @return Whether the input read from @a i is valid JSON. - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `accept()` function reading - from a string.,accept__string} - */ - template - static bool accept(InputType&& i, - const bool ignore_comments = false) - { - return parser(detail::input_adapter(std::forward(i)), nullptr, false, ignore_comments).accept(true); - } - - template - static bool accept(IteratorType first, IteratorType last, - const bool ignore_comments = false) - { - return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true); - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len)) - static bool accept(detail::span_input_adapter&& i, - const bool ignore_comments = false) - { - return parser(i.get(), nullptr, false, ignore_comments).accept(true); - } - - /*! - @brief generate SAX events - - The SAX event lister must follow the interface of @ref json_sax. - - This function reads from a compatible input. Examples are: - - an std::istream object - - a FILE pointer - - a C-style array of characters - - a pointer to a null-terminated string of single byte characters - - an object obj for which begin(obj) and end(obj) produces a valid pair of - iterators. - - @param[in] i input to read from - @param[in,out] sax SAX event listener - @param[in] format the format to parse (JSON, CBOR, MessagePack, or UBJSON) - @param[in] strict whether the input has to be consumed completely - @param[in] ignore_comments whether comments should be ignored and treated - like whitespace (true) or yield a parse error (true); (optional, false by - default); only applies to the JSON file format. - - @return return value of the last processed SAX event - - @throw parse_error.101 if a parse error occurs; example: `""unexpected end - of input; expected string literal""` - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. The complexity can be higher if the SAX consumer @a sax has - a super-linear complexity. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below demonstrates the `sax_parse()` function - reading from string and processing the events with a user-defined SAX - event consumer.,sax_parse} - - @since version 3.2.0 - */ - template - JSON_HEDLEY_NON_NULL(2) - static bool sax_parse(InputType&& i, SAX* sax, - input_format_t format = input_format_t::json, - const bool strict = true, - const bool ignore_comments = false) - { - auto ia = detail::input_adapter(std::forward(i)); - return format == input_format_t::json - ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) - : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); - } - - template - JSON_HEDLEY_NON_NULL(3) - static bool sax_parse(IteratorType first, IteratorType last, SAX* sax, - input_format_t format = input_format_t::json, - const bool strict = true, - const bool ignore_comments = false) - { - auto ia = detail::input_adapter(std::move(first), std::move(last)); - return format == input_format_t::json - ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) - : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); - } - - template - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...)) - JSON_HEDLEY_NON_NULL(2) - static bool sax_parse(detail::span_input_adapter&& i, SAX* sax, - input_format_t format = input_format_t::json, - const bool strict = true, - const bool ignore_comments = false) - { - auto ia = i.get(); - return format == input_format_t::json - ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict) - : detail::binary_reader(std::move(ia)).sax_parse(format, sax, strict); - } - - /*! - @brief deserialize from stream - @deprecated This stream operator is deprecated and will be removed in - version 4.0.0 of the library. Please use - @ref operator>>(std::istream&, basic_json&) - instead; that is, replace calls like `j << i;` with `i >> j;`. - @since version 1.0.0; deprecated since version 3.0.0 - */ - JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&)) - friend std::istream& operator<<(basic_json& j, std::istream& i) - { - return operator>>(i, j); - } - - /*! - @brief deserialize from stream - - Deserializes an input stream to a JSON value. - - @param[in,out] i input stream to read a serialized JSON value from - @param[in,out] j JSON value to write the deserialized input to - - @throw parse_error.101 in case of an unexpected token - @throw parse_error.102 if to_unicode fails or surrogate error - @throw parse_error.103 if to_unicode fails - - @complexity Linear in the length of the input. The parser is a predictive - LL(1) parser. - - @note A UTF-8 byte order mark is silently ignored. - - @liveexample{The example below shows how a JSON value is constructed by - reading a serialization from a stream.,operator_deserialize} - - @sa parse(std::istream&, const parser_callback_t) for a variant with a - parser callback function to filter values while parsing - - @since version 1.0.0 - */ - friend std::istream& operator>>(std::istream& i, basic_json& j) - { - parser(detail::input_adapter(i)).parse(false, j); - return i; - } - - /// @} - - /////////////////////////// - // convenience functions // - /////////////////////////// - - /*! - @brief return the type as string - - Returns the type name as string to be used in error messages - usually to - indicate that a function was called on a wrong JSON type. - - @return a string representation of a the @a m_type member: - Value type | return value - ----------- | ------------- - null | `"null"` - boolean | `"boolean"` - string | `"string"` - number | `"number"` (for all number types) - object | `"object"` - array | `"array"` - binary | `"binary"` - discarded | `"discarded"` - - @exceptionsafety No-throw guarantee: this function never throws exceptions. - - @complexity Constant. - - @liveexample{The following code exemplifies `type_name()` for all JSON - types.,type_name} - - @sa @ref type() -- return the type of the JSON value - @sa @ref operator value_t() -- return the type of the JSON value (implicit) - - @since version 1.0.0, public since 2.1.0, `const char*` and `noexcept` - since 3.0.0 - */ - JSON_HEDLEY_RETURNS_NON_NULL - const char* type_name() const noexcept - { - { - switch (m_type) - { - case value_t::null: - return "null"; - case value_t::object: - return "object"; - case value_t::array: - return "array"; - case value_t::string: - return "string"; - case value_t::boolean: - return "boolean"; - case value_t::binary: - return "binary"; - case value_t::discarded: - return "discarded"; - default: - return "number"; - } - } - } - - - JSON_PRIVATE_UNLESS_TESTED: - ////////////////////// - // member variables // - ////////////////////// - - /// the type of the current element - value_t m_type = value_t::null; - - /// the value of the current element - json_value m_value = {}; - - ////////////////////////////////////////// - // binary serialization/deserialization // - ////////////////////////////////////////// - - /// @name binary serialization/deserialization support - /// @{ - - public: - /*! - @brief create a CBOR serialization of a given JSON value - - Serializes a given JSON value @a j to a byte vector using the CBOR (Concise - Binary Object Representation) serialization format. CBOR is a binary - serialization format which aims to be more compact than JSON itself, yet - more efficient to parse. - - The library uses the following mapping from JSON values types to - CBOR types according to the CBOR specification (RFC 7049): - - JSON value type | value/range | CBOR type | first byte - --------------- | ------------------------------------------ | ---------------------------------- | --------------- - null | `null` | Null | 0xF6 - boolean | `true` | True | 0xF5 - boolean | `false` | False | 0xF4 - number_integer | -9223372036854775808..-2147483649 | Negative integer (8 bytes follow) | 0x3B - number_integer | -2147483648..-32769 | Negative integer (4 bytes follow) | 0x3A - number_integer | -32768..-129 | Negative integer (2 bytes follow) | 0x39 - number_integer | -128..-25 | Negative integer (1 byte follow) | 0x38 - number_integer | -24..-1 | Negative integer | 0x20..0x37 - number_integer | 0..23 | Integer | 0x00..0x17 - number_integer | 24..255 | Unsigned integer (1 byte follow) | 0x18 - number_integer | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 - number_integer | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A - number_integer | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B - number_unsigned | 0..23 | Integer | 0x00..0x17 - number_unsigned | 24..255 | Unsigned integer (1 byte follow) | 0x18 - number_unsigned | 256..65535 | Unsigned integer (2 bytes follow) | 0x19 - number_unsigned | 65536..4294967295 | Unsigned integer (4 bytes follow) | 0x1A - number_unsigned | 4294967296..18446744073709551615 | Unsigned integer (8 bytes follow) | 0x1B - number_float | *any value representable by a float* | Single-Precision Float | 0xFA - number_float | *any value NOT representable by a float* | Double-Precision Float | 0xFB - string | *length*: 0..23 | UTF-8 string | 0x60..0x77 - string | *length*: 23..255 | UTF-8 string (1 byte follow) | 0x78 - string | *length*: 256..65535 | UTF-8 string (2 bytes follow) | 0x79 - string | *length*: 65536..4294967295 | UTF-8 string (4 bytes follow) | 0x7A - string | *length*: 4294967296..18446744073709551615 | UTF-8 string (8 bytes follow) | 0x7B - array | *size*: 0..23 | array | 0x80..0x97 - array | *size*: 23..255 | array (1 byte follow) | 0x98 - array | *size*: 256..65535 | array (2 bytes follow) | 0x99 - array | *size*: 65536..4294967295 | array (4 bytes follow) | 0x9A - array | *size*: 4294967296..18446744073709551615 | array (8 bytes follow) | 0x9B - object | *size*: 0..23 | map | 0xA0..0xB7 - object | *size*: 23..255 | map (1 byte follow) | 0xB8 - object | *size*: 256..65535 | map (2 bytes follow) | 0xB9 - object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA - object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB - binary | *size*: 0..23 | byte string | 0x40..0x57 - binary | *size*: 23..255 | byte string (1 byte follow) | 0x58 - binary | *size*: 256..65535 | byte string (2 bytes follow) | 0x59 - binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A - binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B - - @note The mapping is **complete** in the sense that any JSON value type - can be converted to a CBOR value. - - @note If NaN or Infinity are stored inside a JSON number, they are - serialized properly. This behavior differs from the @ref dump() - function which serializes NaN or Infinity to `null`. - - @note The following CBOR types are not used in the conversion: - - UTF-8 strings terminated by "break" (0x7F) - - arrays terminated by "break" (0x9F) - - maps terminated by "break" (0xBF) - - byte strings terminated by "break" (0x5F) - - date/time (0xC0..0xC1) - - bignum (0xC2..0xC3) - - decimal fraction (0xC4) - - bigfloat (0xC5) - - expected conversions (0xD5..0xD7) - - simple values (0xE0..0xF3, 0xF8) - - undefined (0xF7) - - half-precision floats (0xF9) - - break (0xFF) - - @param[in] j JSON value to serialize - @return CBOR serialization as byte vector - - @complexity Linear in the size of the JSON value @a j. - - @liveexample{The example shows the serialization of a JSON value to a byte - vector in CBOR format.,to_cbor} - - @sa http://cbor.io - @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the - analogous deserialization - @sa @ref to_msgpack(const basic_json&) for the related MessagePack format - @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the - related UBJSON format - - @since version 2.0.9; compact representation of floating-point numbers - since version 3.8.0 - */ - static std::vector to_cbor(const basic_json& j) - { - std::vector result; - to_cbor(j, result); - return result; - } - - static void to_cbor(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_cbor(j); - } - - static void to_cbor(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_cbor(j); - } - - /*! - @brief create a MessagePack serialization of a given JSON value - - Serializes a given JSON value @a j to a byte vector using the MessagePack - serialization format. MessagePack is a binary serialization format which - aims to be more compact than JSON itself, yet more efficient to parse. - - The library uses the following mapping from JSON values types to - MessagePack types according to the MessagePack specification: - - JSON value type | value/range | MessagePack type | first byte - --------------- | --------------------------------- | ---------------- | ---------- - null | `null` | nil | 0xC0 - boolean | `true` | true | 0xC3 - boolean | `false` | false | 0xC2 - number_integer | -9223372036854775808..-2147483649 | int64 | 0xD3 - number_integer | -2147483648..-32769 | int32 | 0xD2 - number_integer | -32768..-129 | int16 | 0xD1 - number_integer | -128..-33 | int8 | 0xD0 - number_integer | -32..-1 | negative fixint | 0xE0..0xFF - number_integer | 0..127 | positive fixint | 0x00..0x7F - number_integer | 128..255 | uint 8 | 0xCC - number_integer | 256..65535 | uint 16 | 0xCD - number_integer | 65536..4294967295 | uint 32 | 0xCE - number_integer | 4294967296..18446744073709551615 | uint 64 | 0xCF - number_unsigned | 0..127 | positive fixint | 0x00..0x7F - number_unsigned | 128..255 | uint 8 | 0xCC - number_unsigned | 256..65535 | uint 16 | 0xCD - number_unsigned | 65536..4294967295 | uint 32 | 0xCE - number_unsigned | 4294967296..18446744073709551615 | uint 64 | 0xCF - number_float | *any value representable by a float* | float 32 | 0xCA - number_float | *any value NOT representable by a float* | float 64 | 0xCB - string | *length*: 0..31 | fixstr | 0xA0..0xBF - string | *length*: 32..255 | str 8 | 0xD9 - string | *length*: 256..65535 | str 16 | 0xDA - string | *length*: 65536..4294967295 | str 32 | 0xDB - array | *size*: 0..15 | fixarray | 0x90..0x9F - array | *size*: 16..65535 | array 16 | 0xDC - array | *size*: 65536..4294967295 | array 32 | 0xDD - object | *size*: 0..15 | fix map | 0x80..0x8F - object | *size*: 16..65535 | map 16 | 0xDE - object | *size*: 65536..4294967295 | map 32 | 0xDF - binary | *size*: 0..255 | bin 8 | 0xC4 - binary | *size*: 256..65535 | bin 16 | 0xC5 - binary | *size*: 65536..4294967295 | bin 32 | 0xC6 - - @note The mapping is **complete** in the sense that any JSON value type - can be converted to a MessagePack value. - - @note The following values can **not** be converted to a MessagePack value: - - strings with more than 4294967295 bytes - - byte strings with more than 4294967295 bytes - - arrays with more than 4294967295 elements - - objects with more than 4294967295 elements - - @note Any MessagePack output created @ref to_msgpack can be successfully - parsed by @ref from_msgpack. - - @note If NaN or Infinity are stored inside a JSON number, they are - serialized properly. This behavior differs from the @ref dump() - function which serializes NaN or Infinity to `null`. - - @param[in] j JSON value to serialize - @return MessagePack serialization as byte vector - - @complexity Linear in the size of the JSON value @a j. - - @liveexample{The example shows the serialization of a JSON value to a byte - vector in MessagePack format.,to_msgpack} - - @sa http://msgpack.org - @sa @ref from_msgpack for the analogous deserialization - @sa @ref to_cbor(const basic_json& for the related CBOR format - @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the - related UBJSON format - - @since version 2.0.9 - */ - static std::vector to_msgpack(const basic_json& j) - { - std::vector result; - to_msgpack(j, result); - return result; - } - - static void to_msgpack(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_msgpack(j); - } - - static void to_msgpack(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_msgpack(j); - } - - /*! - @brief create a UBJSON serialization of a given JSON value - - Serializes a given JSON value @a j to a byte vector using the UBJSON - (Universal Binary JSON) serialization format. UBJSON aims to be more compact - than JSON itself, yet more efficient to parse. - - The library uses the following mapping from JSON values types to - UBJSON types according to the UBJSON specification: - - JSON value type | value/range | UBJSON type | marker - --------------- | --------------------------------- | ----------- | ------ - null | `null` | null | `Z` - boolean | `true` | true | `T` - boolean | `false` | false | `F` - number_integer | -9223372036854775808..-2147483649 | int64 | `L` - number_integer | -2147483648..-32769 | int32 | `l` - number_integer | -32768..-129 | int16 | `I` - number_integer | -128..127 | int8 | `i` - number_integer | 128..255 | uint8 | `U` - number_integer | 256..32767 | int16 | `I` - number_integer | 32768..2147483647 | int32 | `l` - number_integer | 2147483648..9223372036854775807 | int64 | `L` - number_unsigned | 0..127 | int8 | `i` - number_unsigned | 128..255 | uint8 | `U` - number_unsigned | 256..32767 | int16 | `I` - number_unsigned | 32768..2147483647 | int32 | `l` - number_unsigned | 2147483648..9223372036854775807 | int64 | `L` - number_unsigned | 2147483649..18446744073709551615 | high-precision | `H` - number_float | *any value* | float64 | `D` - string | *with shortest length indicator* | string | `S` - array | *see notes on optimized format* | array | `[` - object | *see notes on optimized format* | map | `{` - - @note The mapping is **complete** in the sense that any JSON value type - can be converted to a UBJSON value. - - @note The following values can **not** be converted to a UBJSON value: - - strings with more than 9223372036854775807 bytes (theoretical) - - @note The following markers are not used in the conversion: - - `Z`: no-op values are not created. - - `C`: single-byte strings are serialized with `S` markers. - - @note Any UBJSON output created @ref to_ubjson can be successfully parsed - by @ref from_ubjson. - - @note If NaN or Infinity are stored inside a JSON number, they are - serialized properly. This behavior differs from the @ref dump() - function which serializes NaN or Infinity to `null`. - - @note The optimized formats for containers are supported: Parameter - @a use_size adds size information to the beginning of a container and - removes the closing marker. Parameter @a use_type further checks - whether all elements of a container have the same type and adds the - type marker to the beginning of the container. The @a use_type - parameter must only be used together with @a use_size = true. Note - that @a use_size = true alone may result in larger representations - - the benefit of this parameter is that the receiving side is - immediately informed on the number of elements of the container. - - @note If the JSON data contains the binary type, the value stored is a list - of integers, as suggested by the UBJSON documentation. In particular, - this means that serialization and the deserialization of a JSON - containing binary values into UBJSON and back will result in a - different JSON object. - - @param[in] j JSON value to serialize - @param[in] use_size whether to add size annotations to container types - @param[in] use_type whether to add type annotations to container types - (must be combined with @a use_size = true) - @return UBJSON serialization as byte vector - - @complexity Linear in the size of the JSON value @a j. - - @liveexample{The example shows the serialization of a JSON value to a byte - vector in UBJSON format.,to_ubjson} - - @sa http://ubjson.org - @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the - analogous deserialization - @sa @ref to_cbor(const basic_json& for the related CBOR format - @sa @ref to_msgpack(const basic_json&) for the related MessagePack format - - @since version 3.1.0 - */ - static std::vector to_ubjson(const basic_json& j, - const bool use_size = false, - const bool use_type = false) - { - std::vector result; - to_ubjson(j, result, use_size, use_type); - return result; - } - - static void to_ubjson(const basic_json& j, detail::output_adapter o, - const bool use_size = false, const bool use_type = false) - { - binary_writer(o).write_ubjson(j, use_size, use_type); - } - - static void to_ubjson(const basic_json& j, detail::output_adapter o, - const bool use_size = false, const bool use_type = false) - { - binary_writer(o).write_ubjson(j, use_size, use_type); - } - - - /*! - @brief Serializes the given JSON object `j` to BSON and returns a vector - containing the corresponding BSON-representation. - - BSON (Binary JSON) is a binary format in which zero or more ordered key/value pairs are - stored as a single entity (a so-called document). - - The library uses the following mapping from JSON values types to BSON types: - - JSON value type | value/range | BSON type | marker - --------------- | --------------------------------- | ----------- | ------ - null | `null` | null | 0x0A - boolean | `true`, `false` | boolean | 0x08 - number_integer | -9223372036854775808..-2147483649 | int64 | 0x12 - number_integer | -2147483648..2147483647 | int32 | 0x10 - number_integer | 2147483648..9223372036854775807 | int64 | 0x12 - number_unsigned | 0..2147483647 | int32 | 0x10 - number_unsigned | 2147483648..9223372036854775807 | int64 | 0x12 - number_unsigned | 9223372036854775808..18446744073709551615| -- | -- - number_float | *any value* | double | 0x01 - string | *any value* | string | 0x02 - array | *any value* | document | 0x04 - object | *any value* | document | 0x03 - binary | *any value* | binary | 0x05 - - @warning The mapping is **incomplete**, since only JSON-objects (and things - contained therein) can be serialized to BSON. - Also, integers larger than 9223372036854775807 cannot be serialized to BSON, - and the keys may not contain U+0000, since they are serialized a - zero-terminated c-strings. - - @throw out_of_range.407 if `j.is_number_unsigned() && j.get() > 9223372036854775807` - @throw out_of_range.409 if a key in `j` contains a NULL (U+0000) - @throw type_error.317 if `!j.is_object()` - - @pre The input `j` is required to be an object: `j.is_object() == true`. - - @note Any BSON output created via @ref to_bson can be successfully parsed - by @ref from_bson. - - @param[in] j JSON value to serialize - @return BSON serialization as byte vector - - @complexity Linear in the size of the JSON value @a j. - - @liveexample{The example shows the serialization of a JSON value to a byte - vector in BSON format.,to_bson} - - @sa http://bsonspec.org/spec.html - @sa @ref from_bson(detail::input_adapter&&, const bool strict) for the - analogous deserialization - @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the - related UBJSON format - @sa @ref to_cbor(const basic_json&) for the related CBOR format - @sa @ref to_msgpack(const basic_json&) for the related MessagePack format - */ - static std::vector to_bson(const basic_json& j) - { - std::vector result; - to_bson(j, result); - return result; - } - - /*! - @brief Serializes the given JSON object `j` to BSON and forwards the - corresponding BSON-representation to the given output_adapter `o`. - @param j The JSON object to convert to BSON. - @param o The output adapter that receives the binary BSON representation. - @pre The input `j` shall be an object: `j.is_object() == true` - @sa @ref to_bson(const basic_json&) - */ - static void to_bson(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_bson(j); - } - - /*! - @copydoc to_bson(const basic_json&, detail::output_adapter) - */ - static void to_bson(const basic_json& j, detail::output_adapter o) - { - binary_writer(o).write_bson(j); - } - - - /*! - @brief create a JSON value from an input in CBOR format - - Deserializes a given input @a i to a JSON value using the CBOR (Concise - Binary Object Representation) serialization format. - - The library maps CBOR types to JSON value types as follows: - - CBOR type | JSON value type | first byte - ---------------------- | --------------- | ---------- - Integer | number_unsigned | 0x00..0x17 - Unsigned integer | number_unsigned | 0x18 - Unsigned integer | number_unsigned | 0x19 - Unsigned integer | number_unsigned | 0x1A - Unsigned integer | number_unsigned | 0x1B - Negative integer | number_integer | 0x20..0x37 - Negative integer | number_integer | 0x38 - Negative integer | number_integer | 0x39 - Negative integer | number_integer | 0x3A - Negative integer | number_integer | 0x3B - Byte string | binary | 0x40..0x57 - Byte string | binary | 0x58 - Byte string | binary | 0x59 - Byte string | binary | 0x5A - Byte string | binary | 0x5B - UTF-8 string | string | 0x60..0x77 - UTF-8 string | string | 0x78 - UTF-8 string | string | 0x79 - UTF-8 string | string | 0x7A - UTF-8 string | string | 0x7B - UTF-8 string | string | 0x7F - array | array | 0x80..0x97 - array | array | 0x98 - array | array | 0x99 - array | array | 0x9A - array | array | 0x9B - array | array | 0x9F - map | object | 0xA0..0xB7 - map | object | 0xB8 - map | object | 0xB9 - map | object | 0xBA - map | object | 0xBB - map | object | 0xBF - False | `false` | 0xF4 - True | `true` | 0xF5 - Null | `null` | 0xF6 - Half-Precision Float | number_float | 0xF9 - Single-Precision Float | number_float | 0xFA - Double-Precision Float | number_float | 0xFB - - @warning The mapping is **incomplete** in the sense that not all CBOR - types can be converted to a JSON value. The following CBOR types - are not supported and will yield parse errors (parse_error.112): - - date/time (0xC0..0xC1) - - bignum (0xC2..0xC3) - - decimal fraction (0xC4) - - bigfloat (0xC5) - - expected conversions (0xD5..0xD7) - - simple values (0xE0..0xF3, 0xF8) - - undefined (0xF7) - - @warning CBOR allows map keys of any type, whereas JSON only allows - strings as keys in object values. Therefore, CBOR maps with keys - other than UTF-8 strings are rejected (parse_error.113). - - @note Any CBOR output created @ref to_cbor can be successfully parsed by - @ref from_cbor. - - @param[in] i an input in CBOR format convertible to an input adapter - @param[in] strict whether to expect the input to be consumed until EOF - (true by default) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - @param[in] tag_handler how to treat CBOR tags (optional, error by default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.110 if the given input ends prematurely or the end of - file was not reached when @a strict was set to true - @throw parse_error.112 if unsupported features from CBOR were - used in the given input @a v or if the input is not valid CBOR - @throw parse_error.113 if a string was expected as map key, but not found - - @complexity Linear in the size of the input @a i. - - @liveexample{The example shows the deserialization of a byte vector in CBOR - format to a JSON value.,from_cbor} - - @sa http://cbor.io - @sa @ref to_cbor(const basic_json&) for the analogous serialization - @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for the - related MessagePack format - @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the - related UBJSON format - - @since version 2.0.9; parameter @a start_index since 2.1.1; changed to - consume input adapters, removed start_index parameter, and added - @a strict parameter since 3.0.0; added @a allow_exceptions parameter - since 3.2.0; added @a tag_handler parameter since 3.9.0. - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_cbor(InputType&& i, - const bool strict = true, - const bool allow_exceptions = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); - return res ? result : basic_json(value_t::discarded); - } - - /*! - @copydoc from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_cbor(IteratorType first, IteratorType last, - const bool strict = true, - const bool allow_exceptions = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); - return res ? result : basic_json(value_t::discarded); - } - - template - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) - static basic_json from_cbor(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler); - } - - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len)) - static basic_json from_cbor(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true, - const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); - return res ? result : basic_json(value_t::discarded); - } - - /*! - @brief create a JSON value from an input in MessagePack format - - Deserializes a given input @a i to a JSON value using the MessagePack - serialization format. - - The library maps MessagePack types to JSON value types as follows: - - MessagePack type | JSON value type | first byte - ---------------- | --------------- | ---------- - positive fixint | number_unsigned | 0x00..0x7F - fixmap | object | 0x80..0x8F - fixarray | array | 0x90..0x9F - fixstr | string | 0xA0..0xBF - nil | `null` | 0xC0 - false | `false` | 0xC2 - true | `true` | 0xC3 - float 32 | number_float | 0xCA - float 64 | number_float | 0xCB - uint 8 | number_unsigned | 0xCC - uint 16 | number_unsigned | 0xCD - uint 32 | number_unsigned | 0xCE - uint 64 | number_unsigned | 0xCF - int 8 | number_integer | 0xD0 - int 16 | number_integer | 0xD1 - int 32 | number_integer | 0xD2 - int 64 | number_integer | 0xD3 - str 8 | string | 0xD9 - str 16 | string | 0xDA - str 32 | string | 0xDB - array 16 | array | 0xDC - array 32 | array | 0xDD - map 16 | object | 0xDE - map 32 | object | 0xDF - bin 8 | binary | 0xC4 - bin 16 | binary | 0xC5 - bin 32 | binary | 0xC6 - ext 8 | binary | 0xC7 - ext 16 | binary | 0xC8 - ext 32 | binary | 0xC9 - fixext 1 | binary | 0xD4 - fixext 2 | binary | 0xD5 - fixext 4 | binary | 0xD6 - fixext 8 | binary | 0xD7 - fixext 16 | binary | 0xD8 - negative fixint | number_integer | 0xE0-0xFF - - @note Any MessagePack output created @ref to_msgpack can be successfully - parsed by @ref from_msgpack. - - @param[in] i an input in MessagePack format convertible to an input - adapter - @param[in] strict whether to expect the input to be consumed until EOF - (true by default) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.110 if the given input ends prematurely or the end of - file was not reached when @a strict was set to true - @throw parse_error.112 if unsupported features from MessagePack were - used in the given input @a i or if the input is not valid MessagePack - @throw parse_error.113 if a string was expected as map key, but not found - - @complexity Linear in the size of the input @a i. - - @liveexample{The example shows the deserialization of a byte vector in - MessagePack format to a JSON value.,from_msgpack} - - @sa http://msgpack.org - @sa @ref to_msgpack(const basic_json&) for the analogous serialization - @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the - related CBOR format - @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for - the related UBJSON format - @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for - the related BSON format - - @since version 2.0.9; parameter @a start_index since 2.1.1; changed to - consume input adapters, removed start_index parameter, and added - @a strict parameter since 3.0.0; added @a allow_exceptions parameter - since 3.2.0 - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_msgpack(InputType&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - /*! - @copydoc from_msgpack(detail::input_adapter&&, const bool, const bool) - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_msgpack(IteratorType first, IteratorType last, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - - template - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) - static basic_json from_msgpack(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true) - { - return from_msgpack(ptr, ptr + len, strict, allow_exceptions); - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len)) - static basic_json from_msgpack(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::msgpack, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - - /*! - @brief create a JSON value from an input in UBJSON format - - Deserializes a given input @a i to a JSON value using the UBJSON (Universal - Binary JSON) serialization format. - - The library maps UBJSON types to JSON value types as follows: - - UBJSON type | JSON value type | marker - ----------- | --------------------------------------- | ------ - no-op | *no value, next value is read* | `N` - null | `null` | `Z` - false | `false` | `F` - true | `true` | `T` - float32 | number_float | `d` - float64 | number_float | `D` - uint8 | number_unsigned | `U` - int8 | number_integer | `i` - int16 | number_integer | `I` - int32 | number_integer | `l` - int64 | number_integer | `L` - high-precision number | number_integer, number_unsigned, or number_float - depends on number string | 'H' - string | string | `S` - char | string | `C` - array | array (optimized values are supported) | `[` - object | object (optimized values are supported) | `{` - - @note The mapping is **complete** in the sense that any UBJSON value can - be converted to a JSON value. - - @param[in] i an input in UBJSON format convertible to an input adapter - @param[in] strict whether to expect the input to be consumed until EOF - (true by default) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.110 if the given input ends prematurely or the end of - file was not reached when @a strict was set to true - @throw parse_error.112 if a parse error occurs - @throw parse_error.113 if a string could not be parsed successfully - - @complexity Linear in the size of the input @a i. - - @liveexample{The example shows the deserialization of a byte vector in - UBJSON format to a JSON value.,from_ubjson} - - @sa http://ubjson.org - @sa @ref to_ubjson(const basic_json&, const bool, const bool) for the - analogous serialization - @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the - related CBOR format - @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for - the related MessagePack format - @sa @ref from_bson(detail::input_adapter&&, const bool, const bool) for - the related BSON format - - @since version 3.1.0; added @a allow_exceptions parameter since 3.2.0 - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_ubjson(InputType&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - /*! - @copydoc from_ubjson(detail::input_adapter&&, const bool, const bool) - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_ubjson(IteratorType first, IteratorType last, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - template - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) - static basic_json from_ubjson(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true) - { - return from_ubjson(ptr, ptr + len, strict, allow_exceptions); - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len)) - static basic_json from_ubjson(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::ubjson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - - /*! - @brief Create a JSON value from an input in BSON format - - Deserializes a given input @a i to a JSON value using the BSON (Binary JSON) - serialization format. - - The library maps BSON record types to JSON value types as follows: - - BSON type | BSON marker byte | JSON value type - --------------- | ---------------- | --------------------------- - double | 0x01 | number_float - string | 0x02 | string - document | 0x03 | object - array | 0x04 | array - binary | 0x05 | binary - undefined | 0x06 | still unsupported - ObjectId | 0x07 | still unsupported - boolean | 0x08 | boolean - UTC Date-Time | 0x09 | still unsupported - null | 0x0A | null - Regular Expr. | 0x0B | still unsupported - DB Pointer | 0x0C | still unsupported - JavaScript Code | 0x0D | still unsupported - Symbol | 0x0E | still unsupported - JavaScript Code | 0x0F | still unsupported - int32 | 0x10 | number_integer - Timestamp | 0x11 | still unsupported - 128-bit decimal float | 0x13 | still unsupported - Max Key | 0x7F | still unsupported - Min Key | 0xFF | still unsupported - - @warning The mapping is **incomplete**. The unsupported mappings - are indicated in the table above. - - @param[in] i an input in BSON format convertible to an input adapter - @param[in] strict whether to expect the input to be consumed until EOF - (true by default) - @param[in] allow_exceptions whether to throw exceptions in case of a - parse error (optional, true by default) - - @return deserialized JSON value; in case of a parse error and - @a allow_exceptions set to `false`, the return value will be - value_t::discarded. - - @throw parse_error.114 if an unsupported BSON record type is encountered - - @complexity Linear in the size of the input @a i. - - @liveexample{The example shows the deserialization of a byte vector in - BSON format to a JSON value.,from_bson} - - @sa http://bsonspec.org/spec.html - @sa @ref to_bson(const basic_json&) for the analogous serialization - @sa @ref from_cbor(detail::input_adapter&&, const bool, const bool, const cbor_tag_handler_t) for the - related CBOR format - @sa @ref from_msgpack(detail::input_adapter&&, const bool, const bool) for - the related MessagePack format - @sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the - related UBJSON format - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_bson(InputType&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::forward(i)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - /*! - @copydoc from_bson(detail::input_adapter&&, const bool, const bool) - */ - template - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json from_bson(IteratorType first, IteratorType last, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = detail::input_adapter(std::move(first), std::move(last)); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - - template - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) - static basic_json from_bson(const T* ptr, std::size_t len, - const bool strict = true, - const bool allow_exceptions = true) - { - return from_bson(ptr, ptr + len, strict, allow_exceptions); - } - - JSON_HEDLEY_WARN_UNUSED_RESULT - JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len)) - static basic_json from_bson(detail::span_input_adapter&& i, - const bool strict = true, - const bool allow_exceptions = true) - { - basic_json result; - detail::json_sax_dom_parser sdp(result, allow_exceptions); - auto ia = i.get(); - const bool res = binary_reader(std::move(ia)).sax_parse(input_format_t::bson, &sdp, strict); - return res ? result : basic_json(value_t::discarded); - } - /// @} - - ////////////////////////// - // JSON Pointer support // - ////////////////////////// - - /// @name JSON Pointer functions - /// @{ - - /*! - @brief access specified element via JSON Pointer - - Uses a JSON pointer to retrieve a reference to the respective JSON value. - No bound checking is performed. Similar to @ref operator[](const typename - object_t::key_type&), `null` values are created in arrays and objects if - necessary. - - In particular: - - If the JSON pointer points to an object key that does not exist, it - is created an filled with a `null` value before a reference to it - is returned. - - If the JSON pointer points to an array index that does not exist, it - is created an filled with a `null` value before a reference to it - is returned. All indices between the current maximum and the given - index are also filled with `null`. - - The special value `-` is treated as a synonym for the index past the - end. - - @param[in] ptr a JSON pointer - - @return reference to the element pointed to by @a ptr - - @complexity Constant. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.404 if the JSON pointer can not be resolved - - @liveexample{The behavior is shown in the example.,operatorjson_pointer} - - @since version 2.0.0 - */ - reference operator[](const json_pointer& ptr) - { - return ptr.get_unchecked(this); - } - - /*! - @brief access specified element via JSON Pointer - - Uses a JSON pointer to retrieve a reference to the respective JSON value. - No bound checking is performed. The function does not change the JSON - value; no `null` values are created. In particular, the special value - `-` yields an exception. - - @param[in] ptr JSON pointer to the desired element - - @return const reference to the element pointed to by @a ptr - - @complexity Constant. - - @throw parse_error.106 if an array index begins with '0' - @throw parse_error.109 if an array index was not a number - @throw out_of_range.402 if the array index '-' is used - @throw out_of_range.404 if the JSON pointer can not be resolved - - @liveexample{The behavior is shown in the example.,operatorjson_pointer_const} - - @since version 2.0.0 - */ - const_reference operator[](const json_pointer& ptr) const - { - return ptr.get_unchecked(this); - } - - /*! - @brief access specified element via JSON Pointer - - Returns a reference to the element at with specified JSON pointer @a ptr, - with bounds checking. - - @param[in] ptr JSON pointer to the desired element - - @return reference to the element pointed to by @a ptr - - @throw parse_error.106 if an array index in the passed JSON pointer @a ptr - begins with '0'. See example below. - - @throw parse_error.109 if an array index in the passed JSON pointer @a ptr - is not a number. See example below. - - @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr - is out of range. See example below. - - @throw out_of_range.402 if the array index '-' is used in the passed JSON - pointer @a ptr. As `at` provides checked access (and no elements are - implicitly inserted), the index '-' is always invalid. See example below. - - @throw out_of_range.403 if the JSON pointer describes a key of an object - which cannot be found. See example below. - - @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. - See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 2.0.0 - - @liveexample{The behavior is shown in the example.,at_json_pointer} - */ - reference at(const json_pointer& ptr) - { - return ptr.get_checked(this); - } - - /*! - @brief access specified element via JSON Pointer - - Returns a const reference to the element at with specified JSON pointer @a - ptr, with bounds checking. - - @param[in] ptr JSON pointer to the desired element - - @return reference to the element pointed to by @a ptr - - @throw parse_error.106 if an array index in the passed JSON pointer @a ptr - begins with '0'. See example below. - - @throw parse_error.109 if an array index in the passed JSON pointer @a ptr - is not a number. See example below. - - @throw out_of_range.401 if an array index in the passed JSON pointer @a ptr - is out of range. See example below. - - @throw out_of_range.402 if the array index '-' is used in the passed JSON - pointer @a ptr. As `at` provides checked access (and no elements are - implicitly inserted), the index '-' is always invalid. See example below. - - @throw out_of_range.403 if the JSON pointer describes a key of an object - which cannot be found. See example below. - - @throw out_of_range.404 if the JSON pointer @a ptr can not be resolved. - See example below. - - @exceptionsafety Strong guarantee: if an exception is thrown, there are no - changes in the JSON value. - - @complexity Constant. - - @since version 2.0.0 - - @liveexample{The behavior is shown in the example.,at_json_pointer_const} - */ - const_reference at(const json_pointer& ptr) const - { - return ptr.get_checked(this); - } - - /*! - @brief return flattened JSON value - - The function creates a JSON object whose keys are JSON pointers (see [RFC - 6901](https://tools.ietf.org/html/rfc6901)) and whose values are all - primitive. The original JSON value can be restored using the @ref - unflatten() function. - - @return an object that maps JSON pointers to primitive values - - @note Empty objects and arrays are flattened to `null` and will not be - reconstructed correctly by the @ref unflatten() function. - - @complexity Linear in the size the JSON value. - - @liveexample{The following code shows how a JSON object is flattened to an - object whose keys consist of JSON pointers.,flatten} - - @sa @ref unflatten() for the reverse function - - @since version 2.0.0 - */ - basic_json flatten() const - { - basic_json result(value_t::object); - json_pointer::flatten("", *this, result); - return result; - } - - /*! - @brief unflatten a previously flattened JSON value - - The function restores the arbitrary nesting of a JSON value that has been - flattened before using the @ref flatten() function. The JSON value must - meet certain constraints: - 1. The value must be an object. - 2. The keys must be JSON pointers (see - [RFC 6901](https://tools.ietf.org/html/rfc6901)) - 3. The mapped values must be primitive JSON types. - - @return the original JSON from a flattened version - - @note Empty objects and arrays are flattened by @ref flatten() to `null` - values and can not unflattened to their original type. Apart from - this example, for a JSON value `j`, the following is always true: - `j == j.flatten().unflatten()`. - - @complexity Linear in the size the JSON value. - - @throw type_error.314 if value is not an object - @throw type_error.315 if object values are not primitive - - @liveexample{The following code shows how a flattened JSON object is - unflattened into the original nested JSON object.,unflatten} - - @sa @ref flatten() for the reverse function - - @since version 2.0.0 - */ - basic_json unflatten() const - { - return json_pointer::unflatten(*this); - } - - /// @} - - ////////////////////////// - // JSON Patch functions // - ////////////////////////// - - /// @name JSON Patch functions - /// @{ - - /*! - @brief applies a JSON patch - - [JSON Patch](http://jsonpatch.com) defines a JSON document structure for - expressing a sequence of operations to apply to a JSON) document. With - this function, a JSON Patch is applied to the current JSON value by - executing all operations from the patch. - - @param[in] json_patch JSON patch document - @return patched document - - @note The application of a patch is atomic: Either all operations succeed - and the patched document is returned or an exception is thrown. In - any case, the original value is not changed: the patch is applied - to a copy of the value. - - @throw parse_error.104 if the JSON patch does not consist of an array of - objects - - @throw parse_error.105 if the JSON patch is malformed (e.g., mandatory - attributes are missing); example: `"operation add must have member path"` - - @throw out_of_range.401 if an array index is out of range. - - @throw out_of_range.403 if a JSON pointer inside the patch could not be - resolved successfully in the current JSON value; example: `"key baz not - found"` - - @throw out_of_range.405 if JSON pointer has no parent ("add", "remove", - "move") - - @throw other_error.501 if "test" operation was unsuccessful - - @complexity Linear in the size of the JSON value and the length of the - JSON patch. As usually only a fraction of the JSON value is affected by - the patch, the complexity can usually be neglected. - - @liveexample{The following code shows how a JSON patch is applied to a - value.,patch} - - @sa @ref diff -- create a JSON patch by comparing two JSON values - - @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) - @sa [RFC 6901 (JSON Pointer)](https://tools.ietf.org/html/rfc6901) - - @since version 2.0.0 - */ - basic_json patch(const basic_json& json_patch) const - { - // make a working copy to apply the patch to - basic_json result = *this; - - // the valid JSON Patch operations - enum class patch_operations {add, remove, replace, move, copy, test, invalid}; - - const auto get_op = [](const std::string & op) - { - if (op == "add") - { - return patch_operations::add; - } - if (op == "remove") - { - return patch_operations::remove; - } - if (op == "replace") - { - return patch_operations::replace; - } - if (op == "move") - { - return patch_operations::move; - } - if (op == "copy") - { - return patch_operations::copy; - } - if (op == "test") - { - return patch_operations::test; - } - - return patch_operations::invalid; - }; - - // wrapper for "add" operation; add value at ptr - const auto operation_add = [&result](json_pointer & ptr, basic_json val) - { - // adding to the root of the target document means replacing it - if (ptr.empty()) - { - result = val; - return; - } - - // make sure the top element of the pointer exists - json_pointer top_pointer = ptr.top(); - if (top_pointer != ptr) - { - result.at(top_pointer); - } - - // get reference to parent of JSON pointer ptr - const auto last_path = ptr.back(); - ptr.pop_back(); - basic_json& parent = result[ptr]; - - switch (parent.m_type) - { - case value_t::null: - case value_t::object: - { - // use operator[] to add value - parent[last_path] = val; - break; - } - - case value_t::array: - { - if (last_path == "-") - { - // special case: append to back - parent.push_back(val); - } - else - { - const auto idx = json_pointer::array_index(last_path); - if (JSON_HEDLEY_UNLIKELY(idx > parent.size())) - { - // avoid undefined behavior - JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range")); - } - - // default case: insert add offset - parent.insert(parent.begin() + static_cast(idx), val); - } - break; - } - - // if there exists a parent it cannot be primitive - default: // LCOV_EXCL_LINE - JSON_ASSERT(false); // LCOV_EXCL_LINE - } - }; - - // wrapper for "remove" operation; remove value at ptr - const auto operation_remove = [&result](json_pointer & ptr) - { - // get reference to parent of JSON pointer ptr - const auto last_path = ptr.back(); - ptr.pop_back(); - basic_json& parent = result.at(ptr); - - // remove child - if (parent.is_object()) - { - // perform range check - auto it = parent.find(last_path); - if (JSON_HEDLEY_LIKELY(it != parent.end())) - { - parent.erase(it); - } - else - { - JSON_THROW(out_of_range::create(403, "key '" + last_path + "' not found")); - } - } - else if (parent.is_array()) - { - // note erase performs range check - parent.erase(json_pointer::array_index(last_path)); - } - }; - - // type check: top level value must be an array - if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array())) - { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); - } - - // iterate and apply the operations - for (const auto& val : json_patch) - { - // wrapper to get a value for an operation - const auto get_value = [&val](const std::string & op, - const std::string & member, - bool string_type) -> basic_json & - { - // find value - auto it = val.m_value.object->find(member); - - // context-sensitive error message - const auto error_msg = (op == "op") ? "operation" : "operation '" + op + "'"; - - // check if desired value is present - if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end())) - { - JSON_THROW(parse_error::create(105, 0, error_msg + " must have member '" + member + "'")); - } - - // check if result is of type string - if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string())) - { - JSON_THROW(parse_error::create(105, 0, error_msg + " must have string member '" + member + "'")); - } - - // no error: return value - return it->second; - }; - - // type check: every element of the array must be an object - if (JSON_HEDLEY_UNLIKELY(!val.is_object())) - { - JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects")); - } - - // collect mandatory members - const auto op = get_value("op", "op", true).template get(); - const auto path = get_value(op, "path", true).template get(); - json_pointer ptr(path); - - switch (get_op(op)) - { - case patch_operations::add: - { - operation_add(ptr, get_value("add", "value", false)); - break; - } - - case patch_operations::remove: - { - operation_remove(ptr); - break; - } - - case patch_operations::replace: - { - // the "path" location must exist - use at() - result.at(ptr) = get_value("replace", "value", false); - break; - } - - case patch_operations::move: - { - const auto from_path = get_value("move", "from", true).template get(); - json_pointer from_ptr(from_path); - - // the "from" location must exist - use at() - basic_json v = result.at(from_ptr); - - // The move operation is functionally identical to a - // "remove" operation on the "from" location, followed - // immediately by an "add" operation at the target - // location with the value that was just removed. - operation_remove(from_ptr); - operation_add(ptr, v); - break; - } - - case patch_operations::copy: - { - const auto from_path = get_value("copy", "from", true).template get(); - const json_pointer from_ptr(from_path); - - // the "from" location must exist - use at() - basic_json v = result.at(from_ptr); - - // The copy is functionally identical to an "add" - // operation at the target location using the value - // specified in the "from" member. - operation_add(ptr, v); - break; - } - - case patch_operations::test: - { - bool success = false; - JSON_TRY - { - // check if "value" matches the one at "path" - // the "path" location must exist - use at() - success = (result.at(ptr) == get_value("test", "value", false)); - } - JSON_INTERNAL_CATCH (out_of_range&) - { - // ignore out of range errors: success remains false - } - - // throw an exception if test fails - if (JSON_HEDLEY_UNLIKELY(!success)) - { - JSON_THROW(other_error::create(501, "unsuccessful: " + val.dump())); - } - - break; - } - - default: - { - // op must be "add", "remove", "replace", "move", "copy", or - // "test" - JSON_THROW(parse_error::create(105, 0, "operation value '" + op + "' is invalid")); - } - } - } - - return result; - } - - /*! - @brief creates a diff as a JSON patch - - Creates a [JSON Patch](http://jsonpatch.com) so that value @a source can - be changed into the value @a target by calling @ref patch function. - - @invariant For two JSON values @a source and @a target, the following code - yields always `true`: - @code {.cpp} - source.patch(diff(source, target)) == target; - @endcode - - @note Currently, only `remove`, `add`, and `replace` operations are - generated. - - @param[in] source JSON value to compare from - @param[in] target JSON value to compare against - @param[in] path helper value to create JSON pointers - - @return a JSON patch to convert the @a source to @a target - - @complexity Linear in the lengths of @a source and @a target. - - @liveexample{The following code shows how a JSON patch is created as a - diff for two JSON values.,diff} - - @sa @ref patch -- apply a JSON patch - @sa @ref merge_patch -- apply a JSON Merge Patch - - @sa [RFC 6902 (JSON Patch)](https://tools.ietf.org/html/rfc6902) - - @since version 2.0.0 - */ - JSON_HEDLEY_WARN_UNUSED_RESULT - static basic_json diff(const basic_json& source, const basic_json& target, - const std::string& path = "") - { - // the patch - basic_json result(value_t::array); - - // if the values are the same, return empty patch - if (source == target) - { - return result; - } - - if (source.type() != target.type()) - { - // different types: replace value - result.push_back( - { - {"op", "replace"}, {"path", path}, {"value", target} - }); - return result; - } - - switch (source.type()) - { - case value_t::array: - { - // first pass: traverse common elements - std::size_t i = 0; - while (i < source.size() && i < target.size()) - { - // recursive call to compare array values at index i - auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i)); - result.insert(result.end(), temp_diff.begin(), temp_diff.end()); - ++i; - } - - // i now reached the end of at least one array - // in a second pass, traverse the remaining elements - - // remove my remaining elements - const auto end_index = static_cast(result.size()); - while (i < source.size()) - { - // add operations in reverse order to avoid invalid - // indices - result.insert(result.begin() + end_index, object( - { - {"op", "remove"}, - {"path", path + "/" + std::to_string(i)} - })); - ++i; - } - - // add other remaining elements - while (i < target.size()) - { - result.push_back( - { - {"op", "add"}, - {"path", path + "/-"}, - {"value", target[i]} - }); - ++i; - } - - break; - } - - case value_t::object: - { - // first pass: traverse this object's elements - for (auto it = source.cbegin(); it != source.cend(); ++it) - { - // escape the key name to be used in a JSON patch - const auto key = json_pointer::escape(it.key()); - - if (target.find(it.key()) != target.end()) - { - // recursive call to compare object values at key it - auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key); - result.insert(result.end(), temp_diff.begin(), temp_diff.end()); - } - else - { - // found a key that is not in o -> remove it - result.push_back(object( - { - {"op", "remove"}, {"path", path + "/" + key} - })); - } - } - - // second pass: traverse other object's elements - for (auto it = target.cbegin(); it != target.cend(); ++it) - { - if (source.find(it.key()) == source.end()) - { - // found a key that is not in this -> add it - const auto key = json_pointer::escape(it.key()); - result.push_back( - { - {"op", "add"}, {"path", path + "/" + key}, - {"value", it.value()} - }); - } - } - - break; - } - - default: - { - // both primitive type: replace value - result.push_back( - { - {"op", "replace"}, {"path", path}, {"value", target} - }); - break; - } - } - - return result; - } - - /// @} - - //////////////////////////////// - // JSON Merge Patch functions // - //////////////////////////////// - - /// @name JSON Merge Patch functions - /// @{ - - /*! - @brief applies a JSON Merge Patch - - The merge patch format is primarily intended for use with the HTTP PATCH - method as a means of describing a set of modifications to a target - resource's content. This function applies a merge patch to the current - JSON value. - - The function implements the following algorithm from Section 2 of - [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396): - - ``` - define MergePatch(Target, Patch): - if Patch is an Object: - if Target is not an Object: - Target = {} // Ignore the contents and set it to an empty Object - for each Name/Value pair in Patch: - if Value is null: - if Name exists in Target: - remove the Name/Value pair from Target - else: - Target[Name] = MergePatch(Target[Name], Value) - return Target - else: - return Patch - ``` - - Thereby, `Target` is the current object; that is, the patch is applied to - the current value. - - @param[in] apply_patch the patch to apply - - @complexity Linear in the lengths of @a patch. - - @liveexample{The following code shows how a JSON Merge Patch is applied to - a JSON document.,merge_patch} - - @sa @ref patch -- apply a JSON patch - @sa [RFC 7396 (JSON Merge Patch)](https://tools.ietf.org/html/rfc7396) - - @since version 3.0.0 - */ - void merge_patch(const basic_json& apply_patch) - { - if (apply_patch.is_object()) - { - if (!is_object()) - { - *this = object(); - } - for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it) - { - if (it.value().is_null()) - { - erase(it.key()); - } - else - { - operator[](it.key()).merge_patch(it.value()); - } - } - } - else - { - *this = apply_patch; - } - } - - /// @} -}; - -/*! -@brief user-defined to_string function for JSON values - -This function implements a user-defined to_string for JSON objects. - -@param[in] j a JSON object -@return a std::string object -*/ - -NLOHMANN_BASIC_JSON_TPL_DECLARATION -std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j) -{ - return j.dump(); -} -} // namespace nlohmann - -/////////////////////// -// nonmember support // -/////////////////////// - -// specialization of std::swap, and std::hash -namespace std -{ - -/// hash value for JSON objects -template<> -struct hash -{ - /*! - @brief return a hash value for a JSON object - - @since version 1.0.0 - */ - std::size_t operator()(const nlohmann::json& j) const - { - return nlohmann::detail::hash(j); - } -}; - -/// specialization for std::less -/// @note: do not remove the space after '<', -/// see https://github.com/nlohmann/json/pull/679 -template<> -struct less<::nlohmann::detail::value_t> -{ - /*! - @brief compare two value_t enum values - @since version 3.0.0 - */ - bool operator()(nlohmann::detail::value_t lhs, - nlohmann::detail::value_t rhs) const noexcept - { - return nlohmann::detail::operator<(lhs, rhs); - } -}; - -// C++20 prohibit function specialization in the std namespace. -#ifndef JSON_HAS_CPP_20 - -/*! -@brief exchanges the values of two JSON objects - -@since version 1.0.0 -*/ -template<> -inline void swap(nlohmann::json& j1, nlohmann::json& j2) noexcept( - is_nothrow_move_constructible::value&& - is_nothrow_move_assignable::value - ) -{ - j1.swap(j2); -} - -#endif - -} // namespace std - -/*! -@brief user-defined string literal for JSON values - -This operator implements a user-defined string literal for JSON objects. It -can be used by adding `"_json"` to a string literal and returns a JSON object -if no parse error occurred. - -@param[in] s a string representation of a JSON object -@param[in] n the length of string @a s -@return a JSON object - -@since version 1.0.0 -*/ -JSON_HEDLEY_NON_NULL(1) -inline nlohmann::json operator "" _json(const char* s, std::size_t n) -{ - return nlohmann::json::parse(s, s + n); -} - -/*! -@brief user-defined string literal for JSON pointer - -This operator implements a user-defined string literal for JSON Pointers. It -can be used by adding `"_json_pointer"` to a string literal and returns a JSON pointer -object if no parse error occurred. - -@param[in] s a string representation of a JSON Pointer -@param[in] n the length of string @a s -@return a JSON pointer object - -@since version 2.0.0 -*/ -JSON_HEDLEY_NON_NULL(1) -inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n) -{ - return nlohmann::json::json_pointer(std::string(s, n)); -} - -// #include - - -// restore GCC/clang diagnostic settings -#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) - #pragma GCC diagnostic pop -#endif -#if defined(__clang__) - #pragma GCC diagnostic pop -#endif - -// clean up -#undef JSON_ASSERT -#undef JSON_INTERNAL_CATCH -#undef JSON_CATCH -#undef JSON_THROW -#undef JSON_TRY -#undef JSON_PRIVATE_UNLESS_TESTED -#undef JSON_HAS_CPP_14 -#undef JSON_HAS_CPP_17 -#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION -#undef NLOHMANN_BASIC_JSON_TPL -#undef JSON_EXPLICIT - -// #include -#undef JSON_HEDLEY_ALWAYS_INLINE -#undef JSON_HEDLEY_ARM_VERSION -#undef JSON_HEDLEY_ARM_VERSION_CHECK -#undef JSON_HEDLEY_ARRAY_PARAM -#undef JSON_HEDLEY_ASSUME -#undef JSON_HEDLEY_BEGIN_C_DECLS -#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE -#undef JSON_HEDLEY_CLANG_HAS_BUILTIN -#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE -#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE -#undef JSON_HEDLEY_CLANG_HAS_EXTENSION -#undef JSON_HEDLEY_CLANG_HAS_FEATURE -#undef JSON_HEDLEY_CLANG_HAS_WARNING -#undef JSON_HEDLEY_COMPCERT_VERSION -#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK -#undef JSON_HEDLEY_CONCAT -#undef JSON_HEDLEY_CONCAT3 -#undef JSON_HEDLEY_CONCAT3_EX -#undef JSON_HEDLEY_CONCAT_EX -#undef JSON_HEDLEY_CONST -#undef JSON_HEDLEY_CONSTEXPR -#undef JSON_HEDLEY_CONST_CAST -#undef JSON_HEDLEY_CPP_CAST -#undef JSON_HEDLEY_CRAY_VERSION -#undef JSON_HEDLEY_CRAY_VERSION_CHECK -#undef JSON_HEDLEY_C_DECL -#undef JSON_HEDLEY_DEPRECATED -#undef JSON_HEDLEY_DEPRECATED_FOR -#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL -#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ -#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED -#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES -#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS -#undef JSON_HEDLEY_DIAGNOSTIC_POP -#undef JSON_HEDLEY_DIAGNOSTIC_PUSH -#undef JSON_HEDLEY_DMC_VERSION -#undef JSON_HEDLEY_DMC_VERSION_CHECK -#undef JSON_HEDLEY_EMPTY_BASES -#undef JSON_HEDLEY_EMSCRIPTEN_VERSION -#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK -#undef JSON_HEDLEY_END_C_DECLS -#undef JSON_HEDLEY_FLAGS -#undef JSON_HEDLEY_FLAGS_CAST -#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE -#undef JSON_HEDLEY_GCC_HAS_BUILTIN -#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE -#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE -#undef JSON_HEDLEY_GCC_HAS_EXTENSION -#undef JSON_HEDLEY_GCC_HAS_FEATURE -#undef JSON_HEDLEY_GCC_HAS_WARNING -#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK -#undef JSON_HEDLEY_GCC_VERSION -#undef JSON_HEDLEY_GCC_VERSION_CHECK -#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE -#undef JSON_HEDLEY_GNUC_HAS_BUILTIN -#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE -#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE -#undef JSON_HEDLEY_GNUC_HAS_EXTENSION -#undef JSON_HEDLEY_GNUC_HAS_FEATURE -#undef JSON_HEDLEY_GNUC_HAS_WARNING -#undef JSON_HEDLEY_GNUC_VERSION -#undef JSON_HEDLEY_GNUC_VERSION_CHECK -#undef JSON_HEDLEY_HAS_ATTRIBUTE -#undef JSON_HEDLEY_HAS_BUILTIN -#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE -#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS -#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE -#undef JSON_HEDLEY_HAS_EXTENSION -#undef JSON_HEDLEY_HAS_FEATURE -#undef JSON_HEDLEY_HAS_WARNING -#undef JSON_HEDLEY_IAR_VERSION -#undef JSON_HEDLEY_IAR_VERSION_CHECK -#undef JSON_HEDLEY_IBM_VERSION -#undef JSON_HEDLEY_IBM_VERSION_CHECK -#undef JSON_HEDLEY_IMPORT -#undef JSON_HEDLEY_INLINE -#undef JSON_HEDLEY_INTEL_CL_VERSION -#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK -#undef JSON_HEDLEY_INTEL_VERSION -#undef JSON_HEDLEY_INTEL_VERSION_CHECK -#undef JSON_HEDLEY_IS_CONSTANT -#undef JSON_HEDLEY_IS_CONSTEXPR_ -#undef JSON_HEDLEY_LIKELY -#undef JSON_HEDLEY_MALLOC -#undef JSON_HEDLEY_MESSAGE -#undef JSON_HEDLEY_MSVC_VERSION -#undef JSON_HEDLEY_MSVC_VERSION_CHECK -#undef JSON_HEDLEY_NEVER_INLINE -#undef JSON_HEDLEY_NON_NULL -#undef JSON_HEDLEY_NO_ESCAPE -#undef JSON_HEDLEY_NO_RETURN -#undef JSON_HEDLEY_NO_THROW -#undef JSON_HEDLEY_NULL -#undef JSON_HEDLEY_PELLES_VERSION -#undef JSON_HEDLEY_PELLES_VERSION_CHECK -#undef JSON_HEDLEY_PGI_VERSION -#undef JSON_HEDLEY_PGI_VERSION_CHECK -#undef JSON_HEDLEY_PREDICT -#undef JSON_HEDLEY_PRINTF_FORMAT -#undef JSON_HEDLEY_PRIVATE -#undef JSON_HEDLEY_PUBLIC -#undef JSON_HEDLEY_PURE -#undef JSON_HEDLEY_REINTERPRET_CAST -#undef JSON_HEDLEY_REQUIRE -#undef JSON_HEDLEY_REQUIRE_CONSTEXPR -#undef JSON_HEDLEY_REQUIRE_MSG -#undef JSON_HEDLEY_RESTRICT -#undef JSON_HEDLEY_RETURNS_NON_NULL -#undef JSON_HEDLEY_SENTINEL -#undef JSON_HEDLEY_STATIC_ASSERT -#undef JSON_HEDLEY_STATIC_CAST -#undef JSON_HEDLEY_STRINGIFY -#undef JSON_HEDLEY_STRINGIFY_EX -#undef JSON_HEDLEY_SUNPRO_VERSION -#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK -#undef JSON_HEDLEY_TINYC_VERSION -#undef JSON_HEDLEY_TINYC_VERSION_CHECK -#undef JSON_HEDLEY_TI_ARMCL_VERSION -#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK -#undef JSON_HEDLEY_TI_CL2000_VERSION -#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK -#undef JSON_HEDLEY_TI_CL430_VERSION -#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK -#undef JSON_HEDLEY_TI_CL6X_VERSION -#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK -#undef JSON_HEDLEY_TI_CL7X_VERSION -#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK -#undef JSON_HEDLEY_TI_CLPRU_VERSION -#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK -#undef JSON_HEDLEY_TI_VERSION -#undef JSON_HEDLEY_TI_VERSION_CHECK -#undef JSON_HEDLEY_UNAVAILABLE -#undef JSON_HEDLEY_UNLIKELY -#undef JSON_HEDLEY_UNPREDICTABLE -#undef JSON_HEDLEY_UNREACHABLE -#undef JSON_HEDLEY_UNREACHABLE_RETURN -#undef JSON_HEDLEY_VERSION -#undef JSON_HEDLEY_VERSION_DECODE_MAJOR -#undef JSON_HEDLEY_VERSION_DECODE_MINOR -#undef JSON_HEDLEY_VERSION_DECODE_REVISION -#undef JSON_HEDLEY_VERSION_ENCODE -#undef JSON_HEDLEY_WARNING -#undef JSON_HEDLEY_WARN_UNUSED_RESULT -#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG -#undef JSON_HEDLEY_FALL_THROUGH - - - -#endif // INCLUDE_NLOHMANN_JSON_HPP_ diff --git a/dependencies/json/nlohmann/json.hpp b/dependencies/json/nlohmann/json.hpp new file mode 100644 index 00000000..8b72ea65 --- /dev/null +++ b/dependencies/json/nlohmann/json.hpp @@ -0,0 +1,24765 @@ +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +/****************************************************************************\ + * Note on documentation: The source files contain links to the online * + * documentation of the public API at https://json.nlohmann.me. This URL * + * contains the most recent documentation and should also be applicable to * + * previous versions; documentation for deprecated functions is not * + * removed, but marked deprecated. See "Generate documentation" section in * + * file docs/README.md. * +\****************************************************************************/ + +#ifndef INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +#include // all_of, find, for_each +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#ifndef JSON_NO_IO + #include // istream, ostream +#endif // JSON_NO_IO +#include // random_access_iterator_tag +#include // unique_ptr +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// This file contains all macro definitions affecting or depending on the ABI + +#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK + #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH) + #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3 + #warning "Already included a different version of the library!" + #endif + #endif +#endif + +#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum) +#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum) + +#ifndef JSON_DIAGNOSTICS + #define JSON_DIAGNOSTICS 0 +#endif + +#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0 +#endif + +#if JSON_DIAGNOSTICS + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag +#else + #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS +#endif + +#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp +#else + #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION + #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0 +#endif + +// Construct the namespace ABI tags component +#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b +#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \ + NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) + +#define NLOHMANN_JSON_ABI_TAGS \ + NLOHMANN_JSON_ABI_TAGS_CONCAT( \ + NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \ + NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON) + +// Construct the namespace version component +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \ + _v ## major ## _ ## minor ## _ ## patch +#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) + +#if NLOHMANN_JSON_NAMESPACE_NO_VERSION +#define NLOHMANN_JSON_NAMESPACE_VERSION +#else +#define NLOHMANN_JSON_NAMESPACE_VERSION \ + NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \ + NLOHMANN_JSON_VERSION_MINOR, \ + NLOHMANN_JSON_VERSION_PATCH) +#endif + +// Combine namespace components +#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b +#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \ + NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) + +#ifndef NLOHMANN_JSON_NAMESPACE +#define NLOHMANN_JSON_NAMESPACE \ + nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN +#define NLOHMANN_JSON_NAMESPACE_BEGIN \ + namespace nlohmann \ + { \ + inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \ + NLOHMANN_JSON_ABI_TAGS, \ + NLOHMANN_JSON_NAMESPACE_VERSION) \ + { +#endif + +#ifndef NLOHMANN_JSON_NAMESPACE_END +#define NLOHMANN_JSON_NAMESPACE_END \ + } /* namespace (inline namespace) NOLINT(readability/namespace) */ \ + } // namespace nlohmann +#endif + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // transform +#include // array +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // nullptr_t +#include // exception +#if JSON_DIAGNOSTICS + #include // accumulate +#endif +#include // runtime_error +#include // to_string +#include // vector + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // uint8_t +#include // string + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // declval, pair +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template struct make_void +{ + using type = void; +}; +template using void_t = typename make_void::type; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +// https://en.cppreference.com/w/cpp/experimental/is_detected +struct nonesuch +{ + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; +}; + +template class Op, + class... Args> +struct detector +{ + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> +{ + using value_t = std::true_type; + using type = Op; +}; + +template class Op, class... Args> +using is_detected = typename detector::value_t; + +template class Op, class... Args> +struct is_detected_lazy : is_detected { }; + +template class Op, class... Args> +using detected_t = typename detector::type; + +template class Op, class... Args> +using detected_or = detector; + +template class Op, class... Args> +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +using is_detected_convertible = + std::is_convertible, To>; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + + +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson +// SPDX-License-Identifier: MIT + +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15) +#if defined(JSON_HEDLEY_VERSION) + #undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 15 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) + #undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) + #undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) + #undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) + #undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_CONCAT3_EX) + #undef JSON_HEDLEY_CONCAT3_EX +#endif +#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c + +#if defined(JSON_HEDLEY_CONCAT3) + #undef JSON_HEDLEY_CONCAT3 +#endif +#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) + #undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) + #undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) + #undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) + #undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) + #undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) + #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) + #undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) + #undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) && !defined(__ICL) + #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) + #undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(JSON_HEDLEY_MSVC_VERSION) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else + #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) + #undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) && !defined(__ICL) + #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #undef JSON_HEDLEY_INTEL_CL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL) + #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK) + #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_CL_VERSION) + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) + #undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) + #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) + #undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) + #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) + #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) + #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) + #undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) + #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) + #undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) + #undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) + #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) + #undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) + #undef JSON_HEDLEY_TI_VERSION +#endif +#if \ + defined(__TI_COMPILER_VERSION__) && \ + ( \ + defined(__TMS470__) || defined(__TI_ARM__) || \ + defined(__MSP430__) || \ + defined(__TMS320C2000__) \ + ) +#if (__TI_COMPILER_VERSION__ >= 16000000) + #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) + #undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #undef JSON_HEDLEY_TI_CL2000_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__) + #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL2000_VERSION) + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #undef JSON_HEDLEY_TI_CL430_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__) + #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL430_VERSION) + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #undef JSON_HEDLEY_TI_ARMCL_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__)) + #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK) + #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_ARMCL_VERSION) + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #undef JSON_HEDLEY_TI_CL6X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__) + #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL6X_VERSION) + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #undef JSON_HEDLEY_TI_CL7X_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__) + #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CL7X_VERSION) + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #undef JSON_HEDLEY_TI_CLPRU_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__) + #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK) + #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_CLPRU_VERSION) + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) + #undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) + #if defined(_RELEASE_PATCHLEVEL) + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) + #else + #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) + #undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) + #undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) + #if __VER__ > 1000 + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) + #else + #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0) + #endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) + #undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) + #undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) + #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) + #undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) + #undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) + #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) + #undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) + #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) + #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) + #undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) + #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) + #undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #undef JSON_HEDLEY_MCST_LCC_VERSION +#endif +#if defined(__LCC__) && defined(__LCC_MINOR__) + #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__) +#endif + +#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK) + #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) + #undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_CRAY_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL430_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \ + !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \ + !defined(__COMPCERT__) && \ + !defined(JSON_HEDLEY_MCST_LCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else + #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if \ + defined(__has_attribute) && \ + ( \ + (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \ + ) +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else +# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) + #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else + #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) + #undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else + #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) + #undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) + #undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else + #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) + #undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else + #define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) + #undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) + #undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else + #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) + #undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else + #define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) + #undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) + #undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else + #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else + #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) + #undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else + #define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) + #undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) + #undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else + #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) + #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else + #define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) + #undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) + #undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) + #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") + #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_PUSH + #define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions") +# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +# endif +# endif +#endif +#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) + #undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) + #undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else + #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) + #undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else + #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) + #undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast") +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \ + ((T) (expr)) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0) +# define JSON_HEDLEY_CPP_CAST(T, expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("diag_suppress=Pe137") \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr)) +# endif +#else +# define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097") +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION) + #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunused-function") + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505)) +#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142") +#else + #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) + #undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) + #undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif defined(__cplusplus) && (__cplusplus >= 201402L) + #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else + #define JSON_HEDLEY_DEPRECATED(since) + #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) + #undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else + #define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG) + #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__)) +#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) + #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif defined(_Check_return_) /* SAL */ + #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_ +#else + #define JSON_HEDLEY_WARN_UNUSED_RESULT + #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) +#endif + +#if defined(JSON_HEDLEY_SENTINEL) + #undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else + #define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) + #undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NO_RETURN __noreturn +#elif \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) + #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else + #define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) + #undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) + #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else + #define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) + #undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) + #undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if defined(JSON_HEDLEY_ASSUME) + #undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) + #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #if defined(__cplusplus) + #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) + #else + #define JSON_HEDLEY_ASSUME(expr) _nassert(expr) + #endif +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif defined(JSON_HEDLEY_ASSUME) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif +#if !defined(JSON_HEDLEY_ASSUME) + #if defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1))) + #else + #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr) + #endif +#endif +#if defined(JSON_HEDLEY_UNREACHABLE) + #if \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value)) + #else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() + #endif +#else + #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value) +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE) + #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") + #pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) + #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) + #if defined(__clang__) + #pragma clang diagnostic ignored "-Wvariadic-macros" + #elif defined(JSON_HEDLEY_GCC_VERSION) + #pragma GCC diagnostic ignored "-Wvariadic-macros" + #endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) + #undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else + #define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) + #undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else + #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) + #undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) + #endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) + #define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) + #undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) + #undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) + #undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) + #undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) + #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr)) +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability)) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 ) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 ) +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) + #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) + #undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_MALLOC __declspec(restrict) +#else + #define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) + #undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \ + ) +# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else +# define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) + #undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) + #define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else + #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) + #undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) + #define JSON_HEDLEY_RESTRICT _Restrict +#else + #define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) + #undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) + #define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) + #define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_INLINE __inline +#else + #define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) + #undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) +# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif defined(__cplusplus) && \ + ( \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \ + ) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else +# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) + #undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \ + (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \ + (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \ + (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \ + JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \ + JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) + #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) + #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) + #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else + #define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) + #undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) + #undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) + #undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC __declspec(dllexport) +# define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else +# if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + ( \ + defined(__TI_EABI__) && \ + ( \ + (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \ + ) \ + ) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) +# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +# else +# define JSON_HEDLEY_PRIVATE +# define JSON_HEDLEY_PUBLIC +# endif +# define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) + #undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) + #define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else + #define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) + #undef JSON_HEDLEY_FALL_THROUGH +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) + #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ + #define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else + #define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) + #undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ + #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else + #define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) + #undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) + #define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else + #define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) + #undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) + #undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) + #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + ( \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ + !defined(JSON_HEDLEY_SUNPRO_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_IAR_VERSION)) || \ + (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else + #include + #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \ + JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \ + defined(JSON_HEDLEY_TI_CL2000_VERSION) || \ + defined(JSON_HEDLEY_TI_CL6X_VERSION) || \ + defined(JSON_HEDLEY_TI_CL7X_VERSION) || \ + defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else + #if !defined(JSON_HEDLEY_IS_CONSTANT) + #define JSON_HEDLEY_IS_CONSTANT(expr) (0) + #endif + #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) + #undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) + #undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) + #undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) + #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { + #define JSON_HEDLEY_END_C_DECLS } + #define JSON_HEDLEY_C_DECL extern "C" +#else + #define JSON_HEDLEY_BEGIN_C_DECLS + #define JSON_HEDLEY_END_C_DECLS + #define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) + #undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_NULL) + #undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) + #if __cplusplus >= 201103L + #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) + #elif defined(NULL) + #define JSON_HEDLEY_NULL NULL + #else + #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) + #endif +#elif defined(NULL) + #define JSON_HEDLEY_NULL NULL +#else + #define JSON_HEDLEY_NULL ((void*) 0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) + #undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) + #undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) + #undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) + #undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) + #undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion")) + #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#else + #define JSON_HEDLEY_FLAGS +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) + #undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) + #undef JSON_HEDLEY_EMPTY_BASES +#endif +#if \ + (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \ + JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) + #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else + #define JSON_HEDLEY_EMPTY_BASES +#endif + +/* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) + #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else + #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) + #undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) + #undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) + #undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) + #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) + #undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + + +// This file contains all internal macro definitions (except those affecting ABI) +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// #include + + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) + #if defined(__clang__) + #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 + #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) + #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 + #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" + #endif + #endif +#endif + +// C++ language standard detection +// if the user manually specified the used c++ version this is skipped +#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11) + #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L) + #define JSON_HAS_CPP_20 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 + #define JSON_HAS_CPP_17 + #define JSON_HAS_CPP_14 + #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) + #define JSON_HAS_CPP_14 + #endif + // the cpp 11 flag is always specified because it is the minimal required version + #define JSON_HAS_CPP_11 +#endif + +#ifdef __has_include + #if __has_include() + #include + #endif +#endif + +#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM) + #ifdef JSON_HAS_CPP_17 + #if defined(__cpp_lib_filesystem) + #define JSON_HAS_FILESYSTEM 1 + #elif defined(__cpp_lib_experimental_filesystem) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif !defined(__has_include) + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_FILESYSTEM 1 + #elif __has_include() + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1 + #endif + + // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/ + #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support + #if defined(__clang_major__) && __clang_major__ < 7 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support + #if defined(_MSC_VER) && _MSC_VER < 1914 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before iOS 13 + #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + + // no filesystem support before macOS Catalina + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 + #undef JSON_HAS_FILESYSTEM + #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #endif + #endif +#endif + +#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM + #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_FILESYSTEM + #define JSON_HAS_FILESYSTEM 0 +#endif + +#ifndef JSON_HAS_THREE_WAY_COMPARISON + #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \ + && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L + #define JSON_HAS_THREE_WAY_COMPARISON 1 + #else + #define JSON_HAS_THREE_WAY_COMPARISON 0 + #endif +#endif + +#ifndef JSON_HAS_RANGES + // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error + #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427 + #define JSON_HAS_RANGES 0 + #elif defined(__cpp_lib_ranges) + #define JSON_HAS_RANGES 1 + #else + #define JSON_HAS_RANGES 0 + #endif +#endif + +#ifndef JSON_HAS_STATIC_RTTI + #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0 + #define JSON_HAS_STATIC_RTTI 1 + #else + #define JSON_HAS_STATIC_RTTI 0 + #endif +#endif + +#ifdef JSON_HAS_CPP_17 + #define JSON_INLINE_VARIABLE inline +#else + #define JSON_INLINE_VARIABLE +#endif + +#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address) + #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else + #define JSON_NO_UNIQUE_ADDRESS +#endif + +// disable documentation warnings on clang +#if defined(__clang__) + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdocumentation" + #pragma clang diagnostic ignored "-Wdocumentation-unknown-command" +#endif + +// allow disabling exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) + #define JSON_THROW(exception) throw exception + #define JSON_TRY try + #define JSON_CATCH(exception) catch(exception) + #define JSON_INTERNAL_CATCH(exception) catch(exception) +#else + #include + #define JSON_THROW(exception) std::abort() + #define JSON_TRY if(true) + #define JSON_CATCH(exception) if(false) + #define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) + #undef JSON_THROW + #define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) + #undef JSON_TRY + #define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) + #undef JSON_CATCH + #define JSON_CATCH JSON_CATCH_USER + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) + #undef JSON_INTERNAL_CATCH + #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +// allow overriding assert +#if !defined(JSON_ASSERT) + #include // assert + #define JSON_ASSERT(x) assert(x) +#endif + +// allow to access some private functions (needed by the test suite) +#if defined(JSON_TESTS_PRIVATE) + #define JSON_PRIVATE_UNLESS_TESTED public +#else + #define JSON_PRIVATE_UNLESS_TESTED private +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer, \ + class BinaryType, \ + class CustomBaseClass> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + +// Macros to simplify conversion from/to types + +#define NLOHMANN_JSON_EXPAND( x ) x +#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME +#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \ + NLOHMANN_JSON_PASTE64, \ + NLOHMANN_JSON_PASTE63, \ + NLOHMANN_JSON_PASTE62, \ + NLOHMANN_JSON_PASTE61, \ + NLOHMANN_JSON_PASTE60, \ + NLOHMANN_JSON_PASTE59, \ + NLOHMANN_JSON_PASTE58, \ + NLOHMANN_JSON_PASTE57, \ + NLOHMANN_JSON_PASTE56, \ + NLOHMANN_JSON_PASTE55, \ + NLOHMANN_JSON_PASTE54, \ + NLOHMANN_JSON_PASTE53, \ + NLOHMANN_JSON_PASTE52, \ + NLOHMANN_JSON_PASTE51, \ + NLOHMANN_JSON_PASTE50, \ + NLOHMANN_JSON_PASTE49, \ + NLOHMANN_JSON_PASTE48, \ + NLOHMANN_JSON_PASTE47, \ + NLOHMANN_JSON_PASTE46, \ + NLOHMANN_JSON_PASTE45, \ + NLOHMANN_JSON_PASTE44, \ + NLOHMANN_JSON_PASTE43, \ + NLOHMANN_JSON_PASTE42, \ + NLOHMANN_JSON_PASTE41, \ + NLOHMANN_JSON_PASTE40, \ + NLOHMANN_JSON_PASTE39, \ + NLOHMANN_JSON_PASTE38, \ + NLOHMANN_JSON_PASTE37, \ + NLOHMANN_JSON_PASTE36, \ + NLOHMANN_JSON_PASTE35, \ + NLOHMANN_JSON_PASTE34, \ + NLOHMANN_JSON_PASTE33, \ + NLOHMANN_JSON_PASTE32, \ + NLOHMANN_JSON_PASTE31, \ + NLOHMANN_JSON_PASTE30, \ + NLOHMANN_JSON_PASTE29, \ + NLOHMANN_JSON_PASTE28, \ + NLOHMANN_JSON_PASTE27, \ + NLOHMANN_JSON_PASTE26, \ + NLOHMANN_JSON_PASTE25, \ + NLOHMANN_JSON_PASTE24, \ + NLOHMANN_JSON_PASTE23, \ + NLOHMANN_JSON_PASTE22, \ + NLOHMANN_JSON_PASTE21, \ + NLOHMANN_JSON_PASTE20, \ + NLOHMANN_JSON_PASTE19, \ + NLOHMANN_JSON_PASTE18, \ + NLOHMANN_JSON_PASTE17, \ + NLOHMANN_JSON_PASTE16, \ + NLOHMANN_JSON_PASTE15, \ + NLOHMANN_JSON_PASTE14, \ + NLOHMANN_JSON_PASTE13, \ + NLOHMANN_JSON_PASTE12, \ + NLOHMANN_JSON_PASTE11, \ + NLOHMANN_JSON_PASTE10, \ + NLOHMANN_JSON_PASTE9, \ + NLOHMANN_JSON_PASTE8, \ + NLOHMANN_JSON_PASTE7, \ + NLOHMANN_JSON_PASTE6, \ + NLOHMANN_JSON_PASTE5, \ + NLOHMANN_JSON_PASTE4, \ + NLOHMANN_JSON_PASTE3, \ + NLOHMANN_JSON_PASTE2, \ + NLOHMANN_JSON_PASTE1)(__VA_ARGS__)) +#define NLOHMANN_JSON_PASTE2(func, v1) func(v1) +#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2) +#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3) +#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4) +#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5) +#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6) +#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7) +#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8) +#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9) +#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10) +#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) +#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) +#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) +#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) +#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) +#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) +#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) +#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) +#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) +#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) +#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) +#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) +#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) +#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) +#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) +#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) +#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) +#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) +#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) +#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) +#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) +#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) +#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) +#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) +#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) +#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) +#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) +#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) +#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) +#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) +#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) +#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) +#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) +#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) +#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) +#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) +#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) +#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) +#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) +#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) +#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) +#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) +#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) +#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) +#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) +#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) +#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) +#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) +#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) +#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) +#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) +#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) +#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) + +#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1; +#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1); +#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1); + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ + friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +/*! +@brief macro +@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE +@since version 3.9.0 +*/ +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } + +#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \ + inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \ + inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) } + +// inspired from https://stackoverflow.com/a/26745591 +// allows to call any std function as if (e.g. with begin): +// using std::begin; begin(x); +// +// it allows using the detected idiom to retrieve the return type +// of such an expression +#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \ + namespace detail { \ + using std::std_name; \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + } \ + \ + namespace detail2 { \ + struct std_name##_tag \ + { \ + }; \ + \ + template \ + std_name##_tag std_name(T&&...); \ + \ + template \ + using result_of_##std_name = decltype(std_name(std::declval()...)); \ + \ + template \ + struct would_call_std_##std_name \ + { \ + static constexpr auto const value = ::nlohmann::detail:: \ + is_detected_exact::value; \ + }; \ + } /* namespace detail2 */ \ + \ + template \ + struct would_call_std_##std_name : detail2::would_call_std_##std_name \ + { \ + } + +#ifndef JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_USE_IMPLICIT_CONVERSIONS 1 +#endif + +#if JSON_USE_IMPLICIT_CONVERSIONS + #define JSON_EXPLICIT +#else + #define JSON_EXPLICIT explicit +#endif + +#ifndef JSON_DISABLE_ENUM_SERIALIZATION + #define JSON_DISABLE_ENUM_SERIALIZATION 0 +#endif + +#ifndef JSON_USE_GLOBAL_UDLS + #define JSON_USE_GLOBAL_UDLS 1 +#endif + +#if JSON_HAS_THREE_WAY_COMPARISON + #include // partial_ordering +#endif + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/////////////////////////// +// JSON type enumeration // +/////////////////////////// + +/*! +@brief the JSON type enumeration + +This enumeration collects the different JSON types. It is internally used to +distinguish the stored values, and the functions @ref basic_json::is_null(), +@ref basic_json::is_object(), @ref basic_json::is_array(), +@ref basic_json::is_string(), @ref basic_json::is_boolean(), +@ref basic_json::is_number() (with @ref basic_json::is_number_integer(), +@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()), +@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and +@ref basic_json::is_structured() rely on it. + +@note There are three enumeration entries (number_integer, number_unsigned, and +number_float), because the library distinguishes these three types for numbers: +@ref basic_json::number_unsigned_t is used for unsigned integers, +@ref basic_json::number_integer_t is used for signed integers, and +@ref basic_json::number_float_t is used for floating-point numbers or to +approximate integers which do not fit in the limits of their respective type. + +@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON +value with the default value for a given type + +@since version 1.0.0 +*/ +enum class value_t : std::uint8_t +{ + null, ///< null value + object, ///< object (unordered set of name/value pairs) + array, ///< array (ordered collection of values) + string, ///< string value + boolean, ///< boolean value + number_integer, ///< number value (signed integer) + number_unsigned, ///< number value (unsigned integer) + number_float, ///< number value (floating-point) + binary, ///< binary array (ordered collection of bytes) + discarded ///< discarded by the parser callback function +}; + +/*! +@brief comparison operator for JSON types + +Returns an ordering that is similar to Python: +- order: null < boolean < number < object < array < string < binary +- furthermore, each type is not smaller than itself +- discarded values are not comparable +- binary is represented as a b"" string in python and directly comparable to a + string; however, making a binary array directly comparable with a string would + be surprising behavior in a JSON file. + +@since version 1.0.0 +*/ +#if JSON_HAS_THREE_WAY_COMPARISON + inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD* +#else + inline bool operator<(const value_t lhs, const value_t rhs) noexcept +#endif +{ + static constexpr std::array order = {{ + 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */, + 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */, + 6 /* binary */ + } + }; + + const auto l_index = static_cast(lhs); + const auto r_index = static_cast(rhs); +#if JSON_HAS_THREE_WAY_COMPARISON + if (l_index < order.size() && r_index < order.size()) + { + return order[l_index] <=> order[r_index]; // *NOPAD* + } + return std::partial_ordering::unordered; +#else + return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index]; +#endif +} + +// GCC selects the built-in operator< over an operator rewritten from +// a user-defined spaceship operator +// Clang, MSVC, and ICC select the rewritten candidate +// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200) +#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__) +inline bool operator<(const value_t lhs, const value_t rhs) noexcept +{ + return std::is_lt(lhs <=> rhs); // *NOPAD* +} +#endif + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/*! +@brief replace all occurrences of a substring by another string + +@param[in,out] s the string to manipulate; changed so that all + occurrences of @a f are replaced with @a t +@param[in] f the substring to replace with @a t +@param[in] t the string to replace @a f + +@pre The search string @a f must not be empty. **This precondition is +enforced with an assertion.** + +@since version 2.0.0 +*/ +template +inline void replace_substring(StringType& s, const StringType& f, + const StringType& t) +{ + JSON_ASSERT(!f.empty()); + for (auto pos = s.find(f); // find first occurrence of f + pos != StringType::npos; // make sure f was found + s.replace(pos, f.size(), t), // replace with t, and + pos = s.find(f, pos + t.size())) // find next occurrence of f + {} +} + +/*! + * @brief string escaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to escape + * @return escaped string + * + * Note the order of escaping "~" to "~0" and "/" to "~1" is important. + */ +template +inline StringType escape(StringType s) +{ + replace_substring(s, StringType{"~"}, StringType{"~0"}); + replace_substring(s, StringType{"/"}, StringType{"~1"}); + return s; +} + +/*! + * @brief string unescaping as described in RFC 6901 (Sect. 4) + * @param[in] s string to unescape + * @return unescaped string + * + * Note the order of escaping "~1" to "/" and "~0" to "~" is important. + */ +template +static void unescape(StringType& s) +{ + replace_substring(s, StringType{"~1"}, StringType{"/"}); + replace_substring(s, StringType{"~0"}, StringType{"~"}); +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // size_t + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +/// struct to capture the start position of the current token +struct position_t +{ + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-FileCopyrightText: 2018 The Abseil Authors +// SPDX-License-Identifier: MIT + + + +#include // array +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type +#include // index_sequence, make_index_sequence, index_sequence_for + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +using uncvref_t = typename std::remove_cv::type>::type; + +#ifdef JSON_HAS_CPP_14 + +// the following utilities are natively available in C++14 +using std::enable_if_t; +using std::index_sequence; +using std::make_index_sequence; +using std::index_sequence_for; + +#else + +// alias templates to reduce boilerplate +template +using enable_if_t = typename std::enable_if::type; + +// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h +// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0. + +//// START OF CODE FROM GOOGLE ABSEIL + +// integer_sequence +// +// Class template representing a compile-time integer sequence. An instantiation +// of `integer_sequence` has a sequence of integers encoded in its +// type through its template arguments (which is a common need when +// working with C++11 variadic templates). `absl::integer_sequence` is designed +// to be a drop-in replacement for C++14's `std::integer_sequence`. +// +// Example: +// +// template< class T, T... Ints > +// void user_function(integer_sequence); +// +// int main() +// { +// // user_function's `T` will be deduced to `int` and `Ints...` +// // will be deduced to `0, 1, 2, 3, 4`. +// user_function(make_integer_sequence()); +// } +template +struct integer_sequence +{ + using value_type = T; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } +}; + +// index_sequence +// +// A helper template for an `integer_sequence` of `size_t`, +// `absl::index_sequence` is designed to be a drop-in replacement for C++14's +// `std::index_sequence`. +template +using index_sequence = integer_sequence; + +namespace utility_internal +{ + +template +struct Extend; + +// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency. +template +struct Extend, SeqSize, 0> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >; +}; + +template +struct Extend, SeqSize, 1> +{ + using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >; +}; + +// Recursion helper for 'make_integer_sequence'. +// 'Gen::type' is an alias for 'integer_sequence'. +template +struct Gen +{ + using type = + typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type; +}; + +template +struct Gen +{ + using type = integer_sequence; +}; + +} // namespace utility_internal + +// Compile-time sequences of integers + +// make_integer_sequence +// +// This template alias is equivalent to +// `integer_sequence`, and is designed to be a drop-in +// replacement for C++14's `std::make_integer_sequence`. +template +using make_integer_sequence = typename utility_internal::Gen::type; + +// make_index_sequence +// +// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`, +// and is designed to be a drop-in replacement for C++14's +// `std::make_index_sequence`. +template +using make_index_sequence = make_integer_sequence; + +// index_sequence_for +// +// Converts a typename pack into an index sequence of the same length, and +// is designed to be a drop-in replacement for C++14's +// `std::index_sequence_for()` +template +using index_sequence_for = make_index_sequence; + +//// END OF CODE FROM GOOGLE ABSEIL + +#endif + +// dispatch utility (taken from ranges-v3) +template struct priority_tag : priority_tag < N - 1 > {}; +template<> struct priority_tag<0> {}; + +// taken from ranges-v3 +template +struct static_const +{ + static JSON_INLINE_VARIABLE constexpr T value{}; +}; + +#ifndef JSON_HAS_CPP_17 + template + constexpr T static_const::value; +#endif + +template +inline constexpr std::array make_array(Args&& ... args) +{ + return std::array {{static_cast(std::forward(args))...}}; +} + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval +#include // tuple +#include // char_traits + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +#include // random_access_iterator_tag + +// #include + +// #include + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN +namespace detail +{ + +template +struct iterator_types {}; + +template +struct iterator_types < + It, + void_t> +{ + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; +}; + +// This is required as some compilers implement std::iterator_traits in a way that +// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. +template +struct iterator_traits +{ +}; + +template +struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types +{ +}; + +template +struct iterator_traits::value>> +{ + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; +}; + +} // namespace detail +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin); + +NLOHMANN_JSON_NAMESPACE_END + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + + + +// #include + + +NLOHMANN_JSON_NAMESPACE_BEGIN + +NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end); + +NLOHMANN_JSON_NAMESPACE_END + +// #include + +// #include + +// #include +// __ _____ _____ _____ +// __| | __| | | | JSON for Modern C++ +// | | |__ | | | | | | version 3.11.3 +// |_____|_____|_____|_|___| https://github.com/nlohmann/json +// +// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann +// SPDX-License-Identifier: MIT + +#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_ + #define INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + #include // int64_t, uint64_t + #include // map + #include // allocator + #include // string + #include // vector + + // #include + + + /*! + @brief namespace for Niels Lohmann + @see https://github.com/nlohmann + @since version 1.0.0 + */ + NLOHMANN_JSON_NAMESPACE_BEGIN + + /*! + @brief default JSONSerializer template argument + + This serializer ignores the template arguments and uses ADL + ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl)) + for serialization. + */ + template + struct adl_serializer; + + /// a class to store JSON values + /// @sa https://json.nlohmann.me/api/basic_json/ + template class ObjectType = + std::map, + template class ArrayType = std::vector, + class StringType = std::string, class BooleanType = bool, + class NumberIntegerType = std::int64_t, + class NumberUnsignedType = std::uint64_t, + class NumberFloatType = double, + template class AllocatorType = std::allocator, + template class JSONSerializer = + adl_serializer, + class BinaryType = std::vector, // cppcheck-suppress syntaxError + class CustomBaseClass = void> + class basic_json; + + /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document + /// @sa https://json.nlohmann.me/api/json_pointer/ + template + class json_pointer; + + /*! + @brief default specialization + @sa https://json.nlohmann.me/api/json/ + */ + using json = basic_json<>; + + /// @brief a minimal map-like container that preserves insertion order + /// @sa https://json.nlohmann.me/api/ordered_map/ + template + struct ordered_map; + + /// @brief specialization that maintains the insertion order of object keys + /// @sa https://json.nlohmann.me/api/ordered_json/ + using ordered_json = basic_json; + + NLOHMANN_JSON_NAMESPACE_END + +#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_ + + +NLOHMANN_JSON_NAMESPACE_BEGIN +/*! +@brief detail namespace with internal helper functions + +This namespace collects functions that should not be exposed, +implementations of some @ref basic_json methods, and meta-programming helpers. + +@since version 2.1.0 +*/ +namespace detail +{ + +///////////// +// helpers // +///////////// + +// Note to maintainers: +// +// Every trait in this file expects a non CV-qualified type. +// The only exceptions are in the 'aliases for detected' section +// (i.e. those of the form: decltype(T::member_function(std::declval()))) +// +// In this case, T has to be properly CV-qualified to constraint the function arguments +// (e.g. to_json(BasicJsonType&, const T&)) + +template struct is_basic_json : std::false_type {}; + +NLOHMANN_BASIC_JSON_TPL_DECLARATION +struct is_basic_json : std::true_type {}; + +// used by exceptions create() member functions +// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t +// false_type otherwise +template +struct is_basic_json_context : + std::integral_constant < bool, + is_basic_json::type>::type>::value + || std::is_same::value > +{}; + +////////////////////// +// json_ref helpers // +////////////////////// + +template +class json_ref; + +template +struct is_json_ref : std::false_type {}; + +template +struct is_json_ref> : std::true_type {}; + +////////////////////////// +// aliases for detected // +////////////////////////// + +template +using mapped_type_t = typename T::mapped_type; + +template +using key_type_t = typename T::key_type; + +template +using value_type_t = typename T::value_type; + +template +using difference_type_t = typename T::difference_type; + +template +using pointer_t = typename T::pointer; + +template +using reference_t = typename T::reference; + +template +using iterator_category_t = typename T::iterator_category; + +template +using to_json_function = decltype(T::to_json(std::declval()...)); + +template +using from_json_function = decltype(T::from_json(std::declval()...)); + +template +using get_template_function = decltype(std::declval().template get()); + +// trait checking if JSONSerializer::from_json(json const&, udt&) exists +template +struct has_from_json : std::false_type {}; + +// trait checking if j.get is valid +// use this trait instead of std::is_constructible or std::is_convertible, +// both rely on, or make use of implicit conversions, and thus fail when T +// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958) +template +struct is_getable +{ + static constexpr bool value = is_detected::value; +}; + +template +struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if JSONSerializer::from_json(json const&) exists +// this overload is used for non-default-constructible user-defined-types +template +struct has_non_default_from_json : std::false_type {}; + +template +struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +// This trait checks if BasicJsonType::json_serializer::to_json exists +// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion. +template +struct has_to_json : std::false_type {}; + +template +struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json::value >> +{ + using serializer = typename BasicJsonType::template json_serializer; + + static constexpr bool value = + is_detected_exact::value; +}; + +template +using detect_key_compare = typename T::key_compare; + +template +struct has_key_compare : std::integral_constant::value> {}; + +// obtains the actual object key comparator +template +struct actual_object_comparator +{ + using object_t = typename BasicJsonType::object_t; + using object_comparator_t = typename BasicJsonType::default_object_comparator_t; + using type = typename std::conditional < has_key_compare::value, + typename object_t::key_compare, object_comparator_t>::type; +}; + +template +using actual_object_comparator_t = typename actual_object_comparator::type; + +///////////////// +// char_traits // +///////////////// + +// Primary template of char_traits calls std char_traits +template +struct char_traits : std::char_traits +{}; + +// Explicitly define char traits for unsigned char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = unsigned char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(EOF); + } +}; + +// Explicitly define char traits for signed char since it is not standard +template<> +struct char_traits : std::char_traits +{ + using char_type = signed char; + using int_type = uint64_t; + + // Redefine to_int_type function + static int_type to_int_type(char_type c) noexcept + { + return static_cast(c); + } + + static char_type to_char_type(int_type i) noexcept + { + return static_cast(i); + } + + static constexpr int_type eof() noexcept + { + return static_cast(EOF); + } +}; + +/////////////////// +// is_ functions // +/////////////////// + +// https://en.cppreference.com/w/cpp/types/conjunction +template struct conjunction : std::true_type { }; +template struct conjunction : B { }; +template +struct conjunction +: std::conditional(B::value), conjunction, B>::type {}; + +// https://en.cppreference.com/w/cpp/types/negation +template struct negation : std::integral_constant < bool, !B::value > { }; + +// Reimplementation of is_constructible and is_default_constructible, due to them being broken for +// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367). +// This causes compile errors in e.g. clang 3.5 or gcc 4.9. +template +struct is_default_constructible : std::is_default_constructible {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction, is_default_constructible> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_default_constructible> + : conjunction...> {}; + +template +struct is_constructible : std::is_constructible {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_constructible> : is_default_constructible> {}; + +template +struct is_iterator_traits : std::false_type {}; + +template +struct is_iterator_traits> +{ + private: + using traits = iterator_traits; + + public: + static constexpr auto value = + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value && + is_detected::value; +}; + +template +struct is_range +{ + private: + using t_ref = typename std::add_lvalue_reference::type; + + using iterator = detected_t; + using sentinel = detected_t; + + // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator + // and https://en.cppreference.com/w/cpp/iterator/sentinel_for + // but reimplementing these would be too much work, as a lot of other concepts are used underneath + static constexpr auto is_iterator_begin = + is_iterator_traits>::value; + + public: + static constexpr bool value = !std::is_same::value && !std::is_same::value && is_iterator_begin; +}; + +template +using iterator_t = enable_if_t::value, result_of_begin())>>; + +template +using range_value_t = value_type_t>>; + +// The following implementation of is_complete_type is taken from +// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/ +// and is written by Xiang Fan who agreed to using it in this library. + +template +struct is_complete_type : std::false_type {}; + +template +struct is_complete_type : std::true_type {}; + +template +struct is_compatible_object_type_impl : std::false_type {}; + +template +struct is_compatible_object_type_impl < + BasicJsonType, CompatibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + // macOS's is_constructible does not play well with nonesuch... + static constexpr bool value = + is_constructible::value && + is_constructible::value; +}; + +template +struct is_compatible_object_type + : is_compatible_object_type_impl {}; + +template +struct is_constructible_object_type_impl : std::false_type {}; + +template +struct is_constructible_object_type_impl < + BasicJsonType, ConstructibleObjectType, + enable_if_t < is_detected::value&& + is_detected::value >> +{ + using object_t = typename BasicJsonType::object_t; + + static constexpr bool value = + (is_default_constructible::value && + (std::is_move_assignable::value || + std::is_copy_assignable::value) && + (is_constructible::value && + std::is_same < + typename object_t::mapped_type, + typename ConstructibleObjectType::mapped_type >::value)) || + (has_from_json::value || + has_non_default_from_json < + BasicJsonType, + typename ConstructibleObjectType::mapped_type >::value); +}; + +template +struct is_constructible_object_type + : is_constructible_object_type_impl {}; + +template +struct is_compatible_string_type +{ + static constexpr auto value = + is_constructible::value; +}; + +template +struct is_constructible_string_type +{ + // launder type through decltype() to fix compilation failure on ICPC +#ifdef __INTEL_COMPILER + using laundered_type = decltype(std::declval()); +#else + using laundered_type = ConstructibleStringType; +#endif + + static constexpr auto value = + conjunction < + is_constructible, + is_detected_exact>::value; +}; + +template +struct is_compatible_array_type_impl : std::false_type {}; + +template +struct is_compatible_array_type_impl < + BasicJsonType, CompatibleArrayType, + enable_if_t < + is_detected::value&& + is_iterator_traits>>::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 + !std::is_same>::value >> +{ + static constexpr bool value = + is_constructible>::value; +}; + +template +struct is_compatible_array_type + : is_compatible_array_type_impl {}; + +template +struct is_constructible_array_type_impl : std::false_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t::value >> + : std::true_type {}; + +template +struct is_constructible_array_type_impl < + BasicJsonType, ConstructibleArrayType, + enable_if_t < !std::is_same::value&& + !is_compatible_string_type::value&& + is_default_constructible::value&& +(std::is_move_assignable::value || + std::is_copy_assignable::value)&& +is_detected::value&& +is_iterator_traits>>::value&& +is_detected::value&& +// special case for types like std::filesystem::path whose iterator's value_type are themselves +// c.f. https://github.com/nlohmann/json/pull/3073 +!std::is_same>::value&& + is_complete_type < + detected_t>::value >> +{ + using value_type = range_value_t; + + static constexpr bool value = + std::is_same::value || + has_from_json::value || + has_non_default_from_json < + BasicJsonType, + value_type >::value; +}; + +template +struct is_constructible_array_type + : is_constructible_array_type_impl {}; + +template +struct is_compatible_integer_type_impl : std::false_type {}; + +template +struct is_compatible_integer_type_impl < + RealIntegerType, CompatibleNumberIntegerType, + enable_if_t < std::is_integral::value&& + std::is_integral::value&& + !std::is_same::value >> +{ + // is there an assert somewhere on overflows? + using RealLimits = std::numeric_limits; + using CompatibleLimits = std::numeric_limits; + + static constexpr auto value = + is_constructible::value && + CompatibleLimits::is_integer && + RealLimits::is_signed == CompatibleLimits::is_signed; +}; + +template +struct is_compatible_integer_type + : is_compatible_integer_type_impl {}; + +template +struct is_compatible_type_impl: std::false_type {}; + +template +struct is_compatible_type_impl < + BasicJsonType, CompatibleType, + enable_if_t::value >> +{ + static constexpr bool value = + has_to_json::value; +}; + +template +struct is_compatible_type + : is_compatible_type_impl {}; + +template +struct is_constructible_tuple : std::false_type {}; + +template +struct is_constructible_tuple> : conjunction...> {}; + +template +struct is_json_iterator_of : std::false_type {}; + +template +struct is_json_iterator_of : std::true_type {}; + +template +struct is_json_iterator_of : std::true_type +{}; + +// checks if a given type T is a template specialization of Primary +template